]> sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/fhandler.cc
* environ.cc (environ_init): Avoid a compiler warning.
[newlib-cygwin.git] / winsup / cygwin / fhandler.cc
1 /* fhandler.cc. See console.cc for fhandler_console functions.
2
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
4
5 This file is part of Cygwin.
6
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
9 details. */
10
11 #include "winsup.h"
12 #include <errno.h>
13 #include <unistd.h>
14 #include <stdlib.h>
15 #include <sys/cygwin.h>
16 #include <sys/uio.h>
17 #include <signal.h>
18 #include "cygerrno.h"
19 #include "perprocess.h"
20 #include "security.h"
21 #include "cygwin/version.h"
22 #include "fhandler.h"
23 #include "path.h"
24 #include "dtable.h"
25 #include "cygheap.h"
26 #include "shared_info.h"
27 #include "pinfo.h"
28 #include <assert.h>
29 #include <limits.h>
30
31 static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */
32
33 struct __cygwin_perfile *perfile_table;
34
35 DWORD binmode;
36
37 inline fhandler_base&
38 fhandler_base::operator =(fhandler_base &x)
39 {
40 memcpy (this, &x, sizeof *this);
41 unix_path_name = x.unix_path_name ? cstrdup (x.unix_path_name) : NULL;
42 win32_path_name = x.win32_path_name ? cstrdup (x.win32_path_name) : NULL;
43 rabuf = NULL;
44 ralen = 0;
45 raixget = 0;
46 raixput = 0;
47 rabuflen = 0;
48 return *this;
49 }
50
51 int
52 fhandler_base::puts_readahead (const char *s, size_t len)
53 {
54 int success = 1;
55 while ((*s || (len != (size_t) -1 && len--))
56 && (success = put_readahead (*s++) > 0))
57 continue;
58 return success;
59 }
60
61 int
62 fhandler_base::put_readahead (char value)
63 {
64 char *newrabuf;
65 if (raixput < rabuflen)
66 /* Nothing to do */;
67 else if ((newrabuf = (char *) realloc (rabuf, rabuflen += 32)))
68 rabuf = newrabuf;
69 else
70 return 0;
71
72 rabuf[raixput++] = value;
73 ralen++;
74 return 1;
75 }
76
77 int
78 fhandler_base::get_readahead ()
79 {
80 int chret = -1;
81 if (raixget < ralen)
82 chret = ((unsigned char) rabuf[raixget++]) & 0xff;
83 /* FIXME - not thread safe */
84 if (raixget >= ralen)
85 raixget = raixput = ralen = 0;
86 return chret;
87 }
88
89 int
90 fhandler_base::peek_readahead (int queryput)
91 {
92 int chret = -1;
93 if (!queryput && raixget < ralen)
94 chret = ((unsigned char) rabuf[raixget]) & 0xff;
95 else if (queryput && raixput > 0)
96 chret = ((unsigned char) rabuf[raixput - 1]) & 0xff;
97 return chret;
98 }
99
100 void
101 fhandler_base::set_readahead_valid (int val, int ch)
102 {
103 if (!val)
104 ralen = raixget = raixput = 0;
105 if (ch != -1)
106 put_readahead (ch);
107 }
108
109 int
110 fhandler_base::eat_readahead (int n)
111 {
112 int oralen = ralen;
113 if (n < 0)
114 n = ralen;
115 if (n > 0 && ralen)
116 {
117 if ((int) (ralen -= n) < 0)
118 ralen = 0;
119
120 if (raixget >= ralen)
121 raixget = raixput = ralen = 0;
122 else if (raixput > ralen)
123 raixput = ralen;
124 }
125
126 return oralen;
127 }
128
129 int
130 fhandler_base::get_readahead_into_buffer (char *buf, size_t buflen)
131 {
132 int ch;
133 int copied_chars = 0;
134
135 while (buflen)
136 if ((ch = get_readahead ()) < 0)
137 break;
138 else
139 {
140 buf[copied_chars++] = (unsigned char)(ch & 0xff);
141 buflen--;
142 }
143
144 return copied_chars;
145 }
146
147 /* Record the file name.
148 Filenames are used mostly for debugging messages, and it's hoped that
149 in cases where the name is really required, the filename wouldn't ever
150 be too long (e.g. devices or some such).
151 The unix_path_name is also used by virtual fhandlers. */
152 void
153 fhandler_base::set_name (const char *unix_path, const char *win32_path, int unit)
154 {
155 if (unix_path == NULL || !*unix_path)
156 return;
157
158 if (win32_path)
159 win32_path_name = cstrdup (win32_path);
160 else
161 {
162 const char *fmt = get_native_name ();
163 char *w = (char *) cmalloc (HEAP_STR, strlen (fmt) + 16);
164 __small_sprintf (w, fmt, unit);
165 win32_path_name = w;
166 }
167
168 if (win32_path_name == NULL)
169 {
170 system_printf ("fatal error. strdup failed");
171 exit (ENOMEM);
172 }
173
174 assert (unix_path_name == NULL);
175 /* FIXME: This isn't really right. It ignores the first argument if we're
176 building names for a device and just converts the device name from the
177 win32 name since it has theoretically been previously detected by
178 path_conv. Ideally, we should pass in a format string and build the
179 unix_path, too. */
180 if (!is_device () || *win32_path_name != '\\')
181 unix_path_name = unix_path;
182 else
183 {
184 char *p = cstrdup (win32_path_name);
185 unix_path_name = p;
186 while ((p = strchr (p, '\\')) != NULL)
187 *p++ = '/';
188 if (unix_path)
189 cfree ((void *) unix_path);
190 }
191
192 if (unix_path_name == NULL)
193 {
194 system_printf ("fatal error. strdup failed");
195 exit (ENOMEM);
196 }
197 namehash = hash_path_name (0, win32_path_name);
198 }
199
200 /* Detect if we are sitting at EOF for conditions where Windows
201 returns an error but UNIX doesn't. */
202 static int __stdcall
203 is_at_eof (HANDLE h, DWORD err)
204 {
205 DWORD size, upper1, curr;
206
207 size = GetFileSize (h, &upper1);
208 if (upper1 != 0xffffffff || GetLastError () == NO_ERROR)
209 {
210 LONG upper2 = 0;
211 curr = SetFilePointer (h, 0, &upper2, FILE_CURRENT);
212 if (curr == size && upper1 == (DWORD) upper2)
213 return 1;
214 }
215
216 SetLastError (err);
217 return 0;
218 }
219
220 void
221 fhandler_base::set_flags (int flags, int supplied_bin)
222 {
223 int bin;
224 int fmode;
225 debug_printf ("flags %p, supplied_bin %p", flags, supplied_bin);
226 if ((bin = flags & (O_BINARY | O_TEXT)))
227 debug_printf ("O_TEXT/O_BINARY set in flags %p", bin);
228 else if (get_r_binset () && get_w_binset ())
229 bin = get_r_binary () ? O_BINARY : O_TEXT; // FIXME: Not quite right
230 else if ((fmode = get_default_fmode (flags)) & O_BINARY)
231 bin = O_BINARY;
232 else if (fmode & O_TEXT)
233 bin = O_TEXT;
234 else if (supplied_bin)
235 bin = supplied_bin;
236 else
237 bin = get_w_binary () || get_r_binary () || (binmode != O_TEXT)
238 ? O_BINARY : O_TEXT;
239
240 openflags = flags | bin;
241
242 bin &= O_BINARY;
243 set_r_binary (bin);
244 set_w_binary (bin);
245 syscall_printf ("filemode set to %s", bin ? "binary" : "text");
246 }
247
248 /* Normal file i/o handlers. */
249
250 /* Cover function to ReadFile to achieve (as much as possible) Posix style
251 semantics and use of errno. */
252 int
253 fhandler_base::raw_read (void *ptr, size_t ulen)
254 {
255 DWORD bytes_read;
256
257 if (!ReadFile (get_handle (), ptr, ulen, &bytes_read, 0))
258 {
259 int errcode;
260
261 /* Some errors are not really errors. Detect such cases here. */
262
263 errcode = GetLastError ();
264 switch (errcode)
265 {
266 case ERROR_BROKEN_PIPE:
267 /* This is really EOF. */
268 bytes_read = 0;
269 break;
270 case ERROR_MORE_DATA:
271 /* `bytes_read' is supposedly valid. */
272 break;
273 case ERROR_NOACCESS:
274 if (is_at_eof (get_handle (), errcode))
275 return 0;
276 case ERROR_INVALID_FUNCTION:
277 case ERROR_INVALID_PARAMETER:
278 case ERROR_INVALID_HANDLE:
279 if (openflags & O_DIROPEN)
280 {
281 set_errno (EISDIR);
282 return -1;
283 }
284 default:
285 syscall_printf ("ReadFile %s failed, %E", unix_path_name);
286 __seterrno_from_win_error (errcode);
287 return -1;
288 break;
289 }
290 }
291
292 return bytes_read;
293 }
294
295 /* Cover function to WriteFile to provide Posix interface and semantics
296 (as much as possible). */
297 int
298 fhandler_base::raw_write (const void *ptr, size_t len)
299 {
300 DWORD bytes_written;
301
302 if (!WriteFile (get_handle (), ptr, len, &bytes_written, 0))
303 {
304 if (GetLastError () == ERROR_DISK_FULL && bytes_written > 0)
305 return bytes_written;
306 __seterrno ();
307 if (get_errno () == EPIPE)
308 raise (SIGPIPE);
309 return -1;
310 }
311 return bytes_written;
312 }
313
314 #define ACCFLAGS(x) (x & (O_RDONLY | O_WRONLY | O_RDWR))
315 int
316 fhandler_base::get_default_fmode (int flags)
317 {
318 int fmode = __fmode;
319 if (perfile_table)
320 {
321 size_t nlen = strlen (get_name ());
322 unsigned accflags = ACCFLAGS (flags);
323 for (__cygwin_perfile *pf = perfile_table; pf->name; pf++)
324 if (!*pf->name && ACCFLAGS (pf->flags) == accflags)
325 {
326 fmode = pf->flags & ~(O_RDONLY | O_WRONLY | O_RDWR);
327 break;
328 }
329 else
330 {
331 size_t pflen = strlen (pf->name);
332 const char *stem = get_name () + nlen - pflen;
333 if (pflen > nlen || (stem != get_name () && !isdirsep (stem[-1])))
334 continue;
335 else if (ACCFLAGS (pf->flags) == accflags && strcasematch (stem, pf->name))
336 {
337 fmode = pf->flags & ~(O_RDONLY | O_WRONLY | O_RDWR);
338 break;
339 }
340 }
341 }
342 return fmode;
343 }
344
345 /* Open system call handler function. */
346 int
347 fhandler_base::open (path_conv *pc, int flags, mode_t mode)
348 {
349 int res = 0;
350 HANDLE x;
351 int file_attributes;
352 int shared;
353 int creation_distribution;
354 SECURITY_ATTRIBUTES sa = sec_none;
355
356 syscall_printf ("(%s, %p) query_open %d", get_win32_name (), flags, get_query_open ());
357
358 if (get_win32_name () == NULL)
359 {
360 set_errno (ENOENT);
361 goto done;
362 }
363
364 if (get_query_open ())
365 access = 0;
366 else if (get_device () == FH_TAPE)
367 access = GENERIC_READ | GENERIC_WRITE;
368 else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY)
369 access = GENERIC_READ;
370 else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY)
371 access = GENERIC_WRITE;
372 else
373 access = GENERIC_READ | GENERIC_WRITE;
374
375 /* Allow reliable lseek on disk devices. */
376 if (get_device () == FH_FLOPPY)
377 access |= GENERIC_READ;
378
379 /* FIXME: O_EXCL handling? */
380
381 if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY))
382 {
383 if (flags & O_CREAT)
384 creation_distribution = CREATE_ALWAYS;
385 else
386 creation_distribution = TRUNCATE_EXISTING;
387 }
388 else if (flags & O_CREAT)
389 creation_distribution = OPEN_ALWAYS;
390 else
391 creation_distribution = OPEN_EXISTING;
392
393 if ((flags & O_EXCL) && (flags & O_CREAT))
394 creation_distribution = CREATE_NEW;
395
396 if (flags & O_APPEND)
397 set_append_p ();
398
399 /* These flags are host dependent. */
400 shared = wincap.shared ();
401
402 file_attributes = FILE_ATTRIBUTE_NORMAL;
403 if (flags & O_DIROPEN)
404 file_attributes |= FILE_FLAG_BACKUP_SEMANTICS;
405 if (get_device () == FH_SERIAL)
406 file_attributes |= FILE_FLAG_OVERLAPPED;
407
408 #ifdef HIDDEN_DOT_FILES
409 if (flags & O_CREAT && get_device () == FH_DISK)
410 {
411 char *c = strrchr (get_win32_name (), '\\');
412 if ((c && c[1] == '.') || *get_win32_name () == '.')
413 file_attributes |= FILE_ATTRIBUTE_HIDDEN;
414 }
415 #endif
416
417 /* CreateFile() with dwDesiredAccess == 0 when called on remote
418 share returns some handle, even if file doesn't exist. This code
419 works around this bug. */
420 if (get_query_open () && isremote () &&
421 creation_distribution == OPEN_EXISTING && pc && !pc->exists ())
422 {
423 set_errno (ENOENT);
424 goto done;
425 }
426
427 /* If mode has no write bits set, we set the R/O attribute. */
428 if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
429 file_attributes |= FILE_ATTRIBUTE_READONLY;
430
431 /* If the file should actually be created and ntsec is on,
432 set files attributes. */
433 if (flags & O_CREAT && get_device () == FH_DISK && allow_ntsec && has_acls ())
434 set_security_attribute (mode, &sa, alloca (4096), 4096);
435
436 x = CreateFile (get_win32_name (), access, shared, &sa, creation_distribution,
437 file_attributes, 0);
438
439 syscall_printf ("%p = CreateFile (%s, %p, %p, %p, %p, %p, 0)",
440 x, get_win32_name (), access, shared, &sa,
441 creation_distribution, file_attributes);
442
443 if (x == INVALID_HANDLE_VALUE)
444 {
445 if (pc->isdir () && !wincap.can_open_directories ())
446 {
447 if (mode & (O_CREAT | O_EXCL) == (O_CREAT | O_EXCL))
448 set_errno (EEXIST);
449 else if (mode & (O_WRONLY | O_RDWR))
450 set_errno (EISDIR);
451 else
452 set_nohandle (true);
453 }
454 else if (GetLastError () == ERROR_INVALID_HANDLE)
455 set_errno (ENOENT);
456 else
457 __seterrno ();
458 if (!get_nohandle ())
459 goto done;
460 }
461
462 /* Attributes may be set only if a file is _really_ created.
463 This code is now only used for ntea here since the files
464 security attributes are set in CreateFile () now. */
465 if (flags & O_CREAT && get_device () == FH_DISK
466 && GetLastError () != ERROR_ALREADY_EXISTS
467 && !allow_ntsec && allow_ntea)
468 set_file_attribute (has_acls (), get_win32_name (), mode);
469
470 set_io_handle (x);
471 set_flags (flags, pc ? pc->binmode () : 0);
472
473 res = 1;
474 set_open_status ();
475 done:
476 syscall_printf ("%d = fhandler_base::open (%s, %p)", res, get_win32_name (),
477 flags);
478 return res;
479 }
480
481 /* states:
482 open buffer in binary mode? Just do the read.
483
484 open buffer in text mode? Scan buffer for control zs and handle
485 the first one found. Then scan buffer, converting every \r\n into
486 an \n. If last char is an \r, look ahead one more char, if \n then
487 modify \r, if not, remember char.
488 */
489 int
490 fhandler_base::read (void *in_ptr, size_t in_len)
491 {
492 int len = (int) in_len;
493 char *ptr = (char *) in_ptr;
494
495 int c;
496 int copied_chars = 0;
497
498 while (len)
499 if ((c = get_readahead ()) < 0)
500 break;
501 else
502 {
503 ptr[copied_chars++] = (unsigned char) (c & 0xff);
504 len--;
505 }
506
507 if (copied_chars && is_slow ())
508 return copied_chars;
509
510 if (len)
511 {
512 int readlen = raw_read (ptr + copied_chars, len);
513 if (copied_chars == 0)
514 copied_chars = readlen; /* Propagate error or EOF */
515 else if (readlen > 0) /* FIXME: should flag EOF for next read */
516 copied_chars += readlen;
517 }
518
519 if (copied_chars <= 0)
520 return copied_chars;
521 if (get_r_binary ())
522 {
523 debug_printf ("returning %d chars, binary mode", copied_chars);
524 return copied_chars;
525 }
526
527 #if 0
528 char *ctrlzpos;
529 /* Scan buffer for a control-z and shorten the buffer to that length */
530
531 ctrlzpos = (char *) memchr ((char *) ptr, 0x1a, copied_chars);
532 if (ctrlzpos)
533 {
534 lseek ((ctrlzpos - ((char *) ptr + copied_chars)), SEEK_CUR);
535 copied_chars = ctrlzpos - (char *) ptr;
536 }
537
538 if (copied_chars == 0)
539 {
540 debug_printf ("returning 0 chars, text mode, CTRL-Z found");
541 return 0;
542 }
543 #endif
544
545 /* Scan buffer and turn \r\n into \n */
546 register char *src = (char *) ptr;
547 register char *dst = (char *) ptr;
548 register char *end = src + copied_chars - 1;
549
550 /* Read up to the last but one char - the last char needs special handling */
551 while (src < end)
552 {
553 *dst = *src++;
554 if (*dst != '\r' || *src != '\n')
555 dst++;
556 }
557
558 c = *src;
559 /* if last char is a '\r' then read one more to see if we should
560 translate this one too */
561 if (c == '\r')
562 {
563 char c1 = 0;
564 len = raw_read (&c1, 1);
565 if (len <= 0)
566 /* nothing */;
567 else if (c1 == '\n')
568 c = '\n';
569 else
570 set_readahead_valid (1, c1);
571 }
572
573 *dst++ = c;
574 copied_chars = dst - (char *) ptr;
575
576 #ifndef NOSTRACE
577 if (strace.active)
578 {
579 char buf[16 * 6 + 1];
580 char *p = buf;
581
582 for (int i = 0; i < copied_chars && i < 16; ++i)
583 {
584 unsigned char c = ((unsigned char *) ptr)[i];
585 /* >= 33 so space prints in hex */
586 __small_sprintf (p, c >= 33 && c <= 127 ? " %c" : " %p", c);
587 p += strlen (p);
588 }
589 debug_printf ("read %d bytes (%s%s)", copied_chars, buf,
590 copied_chars > 16 ? " ..." : "");
591 }
592 #endif
593
594 debug_printf ("returning %d chars, text mode", copied_chars);
595 return copied_chars;
596 }
597
598 int
599 fhandler_base::write (const void *ptr, size_t len)
600 {
601 int res;
602
603 if (get_append_p ())
604 SetFilePointer (get_handle (), 0, 0, FILE_END);
605 else if (wincap.has_lseek_bug () && get_check_win95_lseek_bug ())
606 {
607 /* Note: this bug doesn't happen on NT4, even though the documentation
608 for WriteFile() says that it *may* happen on any OS. */
609 int actual_length, current_position;
610 set_check_win95_lseek_bug (0); /* don't do it again */
611 actual_length = GetFileSize (get_handle (), NULL);
612 current_position = SetFilePointer (get_handle (), 0, 0, FILE_CURRENT);
613 if (current_position > actual_length)
614 {
615 /* Oops, this is the bug case - Win95 uses whatever is on the disk
616 instead of some known (safe) value, so we must seek back and
617 fill in the gap with zeros. - DJ */
618 char zeros[512];
619 int number_of_zeros_to_write = current_position - actual_length;
620 memset (zeros, 0, 512);
621 SetFilePointer (get_handle (), 0, 0, FILE_END);
622 while (number_of_zeros_to_write > 0)
623 {
624 DWORD zeros_this_time = (number_of_zeros_to_write > 512
625 ? 512 : number_of_zeros_to_write);
626 DWORD written;
627 if (!WriteFile (get_handle (), zeros, zeros_this_time, &written,
628 NULL))
629 {
630 __seterrno ();
631 if (get_errno () == EPIPE)
632 raise (SIGPIPE);
633 /* This might fail, but it's the best we can hope for */
634 SetFilePointer (get_handle (), current_position, 0, FILE_BEGIN);
635 return -1;
636
637 }
638 if (written < zeros_this_time) /* just in case */
639 {
640 set_errno (ENOSPC);
641 /* This might fail, but it's the best we can hope for */
642 SetFilePointer (get_handle (), current_position, 0, FILE_BEGIN);
643 return -1;
644 }
645 number_of_zeros_to_write -= written;
646 }
647 }
648 }
649
650 if (get_w_binary ())
651 {
652 debug_printf ("binary write");
653 res = raw_write (ptr, len);
654 }
655 else
656 {
657 debug_printf ("text write");
658 /* This is the Microsoft/DJGPP way. Still not ideal, but it's
659 compatible.
660 Modified slightly by CGF 2000-10-07 */
661
662 int left_in_data = len;
663 char *data = (char *)ptr;
664 res = 0;
665
666 while (left_in_data > 0)
667 {
668 char buf[CHUNK_SIZE + 1], *buf_ptr = buf;
669 int left_in_buf = CHUNK_SIZE;
670
671 while (left_in_buf > 0 && left_in_data > 0)
672 {
673 char ch = *data++;
674 if (ch == '\n')
675 {
676 *buf_ptr++ = '\r';
677 left_in_buf--;
678 }
679 *buf_ptr++ = ch;
680 left_in_buf--;
681 left_in_data--;
682 if (left_in_data > 0 && ch == '\r' && *data == '\n')
683 {
684 *buf_ptr++ = *data++;
685 left_in_buf--;
686 left_in_data--;
687 }
688 }
689
690 /* We've got a buffer-full, or we're out of data. Write it out */
691 int nbytes;
692 int want = buf_ptr - buf;
693 if ((nbytes = raw_write (buf, want)) == want)
694 {
695 /* Keep track of how much written not counting additional \r's */
696 res = data - (char *)ptr;
697 continue;
698 }
699
700 if (nbytes == -1)
701 res = -1; /* Error */
702 else
703 res += nbytes; /* Partial write. Return total bytes written. */
704 break; /* All done */
705 }
706 }
707
708 debug_printf ("%d = write (%p, %d)", res, ptr, len);
709 return res;
710 }
711
712 ssize_t
713 fhandler_base::readv (const struct iovec *const iov, const int iovcnt,
714 ssize_t tot)
715 {
716 assert (iov);
717 assert (iovcnt >= 1);
718
719 if (iovcnt == 1)
720 return read (iov->iov_base, iov->iov_len);
721
722 if (tot == -1) // i.e. if not pre-calculated by the caller.
723 {
724 tot = 0;
725 const struct iovec *iovptr = iov + iovcnt;
726 do
727 {
728 iovptr -= 1;
729 tot += iovptr->iov_len;
730 }
731 while (iovptr != iov);
732 }
733
734 assert (tot >= 0);
735
736 if (tot == 0)
737 return 0;
738
739 char *buf = (char *) alloca (tot);
740
741 if (!buf)
742 {
743 set_errno (ENOMEM);
744 return -1;
745 }
746
747 const ssize_t res = read (buf, tot);
748
749 const struct iovec *iovptr = iov;
750 int nbytes = res;
751
752 while (nbytes > 0)
753 {
754 const int frag = min (nbytes, (ssize_t) iovptr->iov_len);
755 memcpy (iovptr->iov_base, buf, frag);
756 buf += frag;
757 iovptr += 1;
758 nbytes -= frag;
759 }
760
761 return res;
762 }
763
764 ssize_t
765 fhandler_base::writev (const struct iovec *const iov, const int iovcnt,
766 ssize_t tot)
767 {
768 assert (iov);
769 assert (iovcnt >= 1);
770
771 if (iovcnt == 1)
772 return write (iov->iov_base, iov->iov_len);
773
774 if (tot == -1) // i.e. if not pre-calculated by the caller.
775 {
776 tot = 0;
777 const struct iovec *iovptr = iov + iovcnt;
778 do
779 {
780 iovptr -= 1;
781 tot += iovptr->iov_len;
782 }
783 while (iovptr != iov);
784 }
785
786 assert (tot >= 0);
787
788 if (tot == 0)
789 return 0;
790
791 char *const buf = (char *) alloca (tot);
792
793 if (!buf)
794 {
795 set_errno (ENOMEM);
796 return -1;
797 }
798
799 char *bufptr = buf;
800 const struct iovec *iovptr = iov;
801 int nbytes = tot;
802
803 while (nbytes != 0)
804 {
805 const int frag = min (nbytes, (ssize_t) iovptr->iov_len);
806 memcpy (bufptr, iovptr->iov_base, frag);
807 bufptr += frag;
808 iovptr += 1;
809 nbytes -= frag;
810 }
811
812 return write (buf, tot);
813 }
814
815 __off64_t
816 fhandler_base::lseek (__off64_t offset, int whence)
817 {
818 __off64_t res;
819
820 /* 9x/Me doesn't support 64bit offsets. We trap that here and return
821 EINVAL. It doesn't make sense to simulate bigger offsets by a
822 SetFilePointer sequence since FAT and FAT32 don't support file
823 size >= 4GB anyway. */
824 if (!wincap.has_64bit_file_access ()
825 && (offset < LONG_MIN || offset > LONG_MAX))
826 {
827 debug_printf ("Win9x, offset not 32 bit.");
828 set_errno (EINVAL);
829 return (__off64_t)-1;
830 }
831
832 /* Seeks on text files is tough, we rewind and read till we get to the
833 right place. */
834
835 if (whence != SEEK_CUR || offset != 0)
836 {
837 if (whence == SEEK_CUR)
838 offset -= ralen - raixget;
839 set_readahead_valid (0);
840 }
841
842 debug_printf ("lseek (%s, %D, %d)", unix_path_name, offset, whence);
843
844 DWORD win32_whence = whence == SEEK_SET ? FILE_BEGIN
845 : (whence == SEEK_CUR ? FILE_CURRENT : FILE_END);
846
847 LONG off_low = offset & 0xffffffff;
848 LONG *poff_high, off_high;
849 if (!wincap.has_64bit_file_access ())
850 poff_high = NULL;
851 else
852 {
853 off_high = offset >> 32;
854 poff_high = &off_high;
855 }
856
857 debug_printf ("setting file pointer to %u (high), %u (low)", off_high, off_low);
858 res = SetFilePointer (get_handle (), off_low, poff_high, win32_whence);
859 if (res == INVALID_SET_FILE_POINTER && GetLastError ())
860 {
861 __seterrno ();
862 }
863 else
864 {
865 /* When next we write(), we will check to see if *this* seek went beyond
866 the end of the file, and back-seek and fill with zeros if so - DJ */
867 set_check_win95_lseek_bug ();
868
869 /* If this was a SEEK_CUR with offset 0, we still might have
870 readahead that we have to take into account when calculating
871 the actual position for the application. */
872 if (whence == SEEK_CUR)
873 res -= ralen - raixget;
874 }
875
876 return res;
877 }
878
879 int
880 fhandler_base::close ()
881 {
882 int res = -1;
883
884 syscall_printf ("closing '%s' handle %p", get_name (), get_handle ());
885 if (get_nohandle () || CloseHandle (get_handle ()))
886 res = 0;
887 else
888 {
889 paranoid_printf ("CloseHandle (%d <%s>) failed", get_handle (),
890 get_name ());
891
892 __seterrno ();
893 }
894 return res;
895 }
896
897 int
898 fhandler_base::ioctl (unsigned int cmd, void *buf)
899 {
900 if (cmd == FIONBIO)
901 syscall_printf ("ioctl (FIONBIO, %p)", buf);
902 else
903 syscall_printf ("ioctl (%x, %p)", cmd, buf);
904
905 set_errno (EINVAL);
906 return -1;
907 }
908
909 int
910 fhandler_base::lock (int, struct flock *)
911 {
912 set_errno (EINVAL);
913 return -1;
914 }
915
916 extern "C" char * __stdcall
917 rootdir (char *full_path)
918 {
919 /* Possible choices:
920 * d:... -> d:/
921 * \\server\share... -> \\server\share\
922 * else current drive.
923 */
924 char *root = full_path;
925
926 if (full_path[1] == ':')
927 strcpy (full_path + 2, "\\");
928 else if (full_path[0] == '\\' && full_path[1] == '\\')
929 {
930 char *cp = full_path + 2;
931 while (*cp && *cp != '\\')
932 cp++;
933 if (!*cp)
934 {
935 set_errno (ENOTDIR);
936 return NULL;
937 }
938 cp++;
939 while (*cp && *cp != '\\')
940 cp++;
941 strcpy (cp, "\\");
942 }
943 else
944 root = NULL;
945
946 return root;
947 }
948
949 int __stdcall
950 fhandler_base::fstat (struct __stat64 *buf, path_conv *)
951 {
952 debug_printf ("here");
953 switch (get_device ())
954 {
955 case FH_PIPE:
956 buf->st_mode = S_IFIFO | STD_RBITS | STD_WBITS | S_IWGRP | S_IWOTH;
957 break;
958 case FH_PIPEW:
959 buf->st_mode = S_IFIFO | STD_WBITS | S_IWGRP | S_IWOTH;
960 break;
961 case FH_PIPER:
962 buf->st_mode = S_IFIFO | STD_RBITS;
963 break;
964 case FH_FLOPPY:
965 buf->st_mode = S_IFBLK | STD_RBITS | STD_WBITS | S_IWGRP | S_IWOTH;
966 break;
967 default:
968 buf->st_mode = S_IFCHR | STD_RBITS | STD_WBITS | S_IWGRP | S_IWOTH;
969 break;
970 }
971
972 buf->st_nlink = 1;
973 buf->st_blksize = S_BLKSIZE;
974 time_as_timestruc_t (&buf->st_ctim);
975 buf->st_atim = buf->st_mtim = buf->st_ctim;
976 return 0;
977 }
978
979 void
980 fhandler_base::init (HANDLE f, DWORD a, mode_t bin)
981 {
982 set_io_handle (f);
983 access = a;
984 a &= GENERIC_READ | GENERIC_WRITE;
985 int flags = 0;
986 if (a == GENERIC_READ)
987 flags = O_RDONLY;
988 else if (a == GENERIC_WRITE)
989 flags = O_WRONLY;
990 else if (a == (GENERIC_READ | GENERIC_WRITE))
991 flags = O_RDWR;
992 set_flags (flags | bin);
993 set_open_status ();
994 debug_printf ("created new fhandler_base for handle %p, bin %d", f, get_r_binary ());
995 }
996
997 void
998 fhandler_base::dump (void)
999 {
1000 paranoid_printf ("here");
1001 }
1002
1003 int
1004 fhandler_base::dup (fhandler_base *child)
1005 {
1006 debug_printf ("in fhandler_base dup");
1007
1008 HANDLE nh;
1009 if (!get_nohandle ())
1010 {
1011 if (!DuplicateHandle (hMainProc, get_handle (), hMainProc, &nh, 0, TRUE,
1012 DUPLICATE_SAME_ACCESS))
1013 {
1014 system_printf ("dup(%s) failed, handle %x, %E",
1015 get_name (), get_handle ());
1016 __seterrno ();
1017 return -1;
1018 }
1019
1020 child->set_io_handle (nh);
1021 }
1022 return 0;
1023 }
1024
1025 int fhandler_base::fcntl (int cmd, void *arg)
1026 {
1027 int res;
1028
1029 switch (cmd)
1030 {
1031 case F_GETFD:
1032 res = get_close_on_exec () ? FD_CLOEXEC : 0;
1033 break;
1034 case F_SETFD:
1035 set_close_on_exec ((int) arg);
1036 res = 0;
1037 break;
1038 case F_GETFL:
1039 res = get_flags ();
1040 debug_printf ("GETFL: %d", res);
1041 break;
1042 case F_SETFL:
1043 {
1044 /*
1045 * Only O_APPEND, O_ASYNC and O_NONBLOCK/O_NDELAY are allowed.
1046 * Each other flag will be ignored.
1047 * Since O_ASYNC isn't defined in fcntl.h it's currently
1048 * ignored as well.
1049 */
1050 const int allowed_flags = O_APPEND | O_NONBLOCK_MASK;
1051 int new_flags = (int) arg & allowed_flags;
1052 /* Carefully test for the O_NONBLOCK or deprecated OLD_O_NDELAY flag.
1053 Set only the flag that has been passed in. If both are set, just
1054 record O_NONBLOCK. */
1055 if ((new_flags & OLD_O_NDELAY) && (new_flags & O_NONBLOCK))
1056 new_flags = O_NONBLOCK;
1057 set_flags ((get_flags () & ~allowed_flags) | new_flags);
1058 }
1059 res = 0;
1060 break;
1061 case F_GETLK:
1062 case F_SETLK:
1063 case F_SETLKW:
1064 res = lock (cmd, (struct flock *) arg);
1065 break;
1066 default:
1067 set_errno (EINVAL);
1068 res = -1;
1069 break;
1070 }
1071 return res;
1072 }
1073
1074 /* Base terminal handlers. These just return errors. */
1075
1076 int
1077 fhandler_base::tcflush (int)
1078 {
1079 set_errno (ENOTTY);
1080 return -1;
1081 }
1082
1083 int
1084 fhandler_base::tcsendbreak (int)
1085 {
1086 set_errno (ENOTTY);
1087 return -1;
1088 }
1089
1090 int
1091 fhandler_base::tcdrain (void)
1092 {
1093 set_errno (ENOTTY);
1094 return -1;
1095 }
1096
1097 int
1098 fhandler_base::tcflow (int)
1099 {
1100 set_errno (ENOTTY);
1101 return -1;
1102 }
1103
1104 int
1105 fhandler_base::tcsetattr (int, const struct termios *)
1106 {
1107 set_errno (ENOTTY);
1108 return -1;
1109 }
1110
1111 int
1112 fhandler_base::tcgetattr (struct termios *)
1113 {
1114 set_errno (ENOTTY);
1115 return -1;
1116 }
1117
1118 int
1119 fhandler_base::tcsetpgrp (const pid_t)
1120 {
1121 set_errno (ENOTTY);
1122 return -1;
1123 }
1124
1125 int
1126 fhandler_base::tcgetpgrp (void)
1127 {
1128 set_errno (ENOTTY);
1129 return -1;
1130 }
1131
1132 void
1133 fhandler_base::operator delete (void *p)
1134 {
1135 cfree (p);
1136 return;
1137 }
1138
1139 /* Normal I/O constructor */
1140 fhandler_base::fhandler_base (DWORD devtype, int unit):
1141 status (devtype),
1142 access (0),
1143 io_handle (NULL),
1144 namehash (0),
1145 openflags (0),
1146 rabuf (NULL),
1147 ralen (0),
1148 raixget (0),
1149 raixput (0),
1150 rabuflen (0),
1151 unix_path_name (NULL),
1152 win32_path_name (NULL),
1153 open_status (0)
1154 {
1155 }
1156
1157 /* Normal I/O destructor */
1158 fhandler_base::~fhandler_base (void)
1159 {
1160 if (unix_path_name != NULL)
1161 cfree ((void *) unix_path_name);
1162 if (win32_path_name != NULL)
1163 cfree ((void *) win32_path_name);
1164 if (rabuf)
1165 free (rabuf);
1166 unix_path_name = win32_path_name = NULL;
1167 }
1168
1169 /**********************************************************************/
1170 /* /dev/null */
1171
1172 fhandler_dev_null::fhandler_dev_null () :
1173 fhandler_base (FH_NULL)
1174 {
1175 }
1176
1177 void
1178 fhandler_dev_null::dump (void)
1179 {
1180 paranoid_printf ("here");
1181 }
1182
1183 void
1184 fhandler_base::set_inheritance (HANDLE &h, int not_inheriting)
1185 {
1186 #ifdef DEBUGGING_AND_FDS_PROTECTED
1187 HANDLE oh = h;
1188 #endif
1189 /* Note that we could use SetHandleInformation here but it is not available
1190 on all platforms. Test cases seem to indicate that using DuplicateHandle
1191 in this fashion does not actually close the original handle, which is
1192 what we want. If this changes in the future, we may be forced to use
1193 SetHandleInformation on newer OS's */
1194 if (!DuplicateHandle (hMainProc, h, hMainProc, &h, 0, !not_inheriting,
1195 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
1196 debug_printf ("DuplicateHandle failed, %E");
1197 #ifdef DEBUGGING_AND_FDS_PROTECTED
1198 if (h)
1199 setclexec (oh, h, not_inheriting);
1200 #endif
1201 }
1202
1203 void
1204 fhandler_base::fork_fixup (HANDLE parent, HANDLE &h, const char *name)
1205 {
1206 if (/* !is_socket () && */ !get_close_on_exec ())
1207 debug_printf ("handle %p already opened", h);
1208 else if (!DuplicateHandle (parent, h, hMainProc, &h, 0, !get_close_on_exec (),
1209 DUPLICATE_SAME_ACCESS))
1210 system_printf ("%s - %E, handle %s<%p>", get_name (), name, h);
1211 #ifdef DEBUGGING_AND_FDS_PROTECTED
1212 else if (get_close_on_exec ())
1213 ProtectHandle (h); /* would have to be fancier than this */
1214 else
1215 /* ProtectHandleINH (h) */; /* Should already be protected */
1216 #endif
1217 }
1218
1219 void
1220 fhandler_base::set_close_on_exec (int val)
1221 {
1222 if (!get_nohandle ())
1223 set_inheritance (io_handle, val);
1224 set_close_on_exec_flag (val);
1225 debug_printf ("set close_on_exec for %s to %d", get_name (), val);
1226 }
1227
1228 void
1229 fhandler_base::fixup_after_fork (HANDLE parent)
1230 {
1231 debug_printf ("inheriting '%s' from parent", get_name ());
1232 if (!get_nohandle ())
1233 fork_fixup (parent, io_handle, "io_handle");
1234 }
1235
1236 bool
1237 fhandler_base::is_nonblocking ()
1238 {
1239 return (openflags & O_NONBLOCK_MASK) != 0;
1240 }
1241
1242 void
1243 fhandler_base::set_nonblocking (int yes)
1244 {
1245 int current = openflags & O_NONBLOCK_MASK;
1246 int new_flags = yes ? (!current ? O_NONBLOCK : current) : 0;
1247 openflags = (openflags & ~O_NONBLOCK_MASK) | new_flags;
1248 }
1249
1250 DIR *
1251 fhandler_base::opendir (path_conv&)
1252 {
1253 set_errno (ENOTDIR);
1254 return NULL;
1255 }
1256
1257 struct dirent *
1258 fhandler_base::readdir (DIR *)
1259 {
1260 set_errno (ENOTDIR);
1261 return NULL;
1262 }
1263
1264 __off64_t
1265 fhandler_base::telldir (DIR *)
1266 {
1267 set_errno (ENOTDIR);
1268 return -1;
1269 }
1270
1271 void
1272 fhandler_base::seekdir (DIR *, __off64_t)
1273 {
1274 set_errno (ENOTDIR);
1275 return;
1276 }
1277
1278 void
1279 fhandler_base::rewinddir (DIR *)
1280 {
1281 set_errno (ENOTDIR);
1282 return;
1283 }
1284
1285 int
1286 fhandler_base::closedir (DIR *)
1287 {
1288 set_errno (ENOTDIR);
1289 return -1;
1290 }
This page took 0.086375 seconds and 5 git commands to generate.