]> sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/fhandler.cc
75528d35e3734feea3f6dbcc0da4b88aa4dc8d59
[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, 2003, 2004,
4 2005, 2006, 2007 Red Hat, Inc.
5
6 This file is part of Cygwin.
7
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10 details. */
11
12 #include "winsup.h"
13 #include <unistd.h>
14 #include <stdlib.h>
15 #include <sys/cygwin.h>
16 #include <sys/uio.h>
17 #include <sys/acl.h>
18 #include <sys/statvfs.h>
19 #include <signal.h>
20 #include "cygerrno.h"
21 #include "perprocess.h"
22 #include "security.h"
23 #include "cygwin/version.h"
24 #include "path.h"
25 #include "fhandler.h"
26 #include "dtable.h"
27 #include "cygheap.h"
28 #include "shared_info.h"
29 #include "pinfo.h"
30 #include <assert.h>
31 #include <limits.h>
32 #include <winioctl.h>
33 #include <ntdef.h>
34 #include "ntdll.h"
35 #include "cygtls.h"
36 #include "sigproc.h"
37
38 static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */
39
40 struct __cygwin_perfile *perfile_table;
41
42 DWORD binmode;
43
44 inline fhandler_base&
45 fhandler_base::operator =(fhandler_base& x)
46 {
47 memcpy (this, &x, sizeof *this);
48 pc = x.pc;
49 rabuf = NULL;
50 ralen = 0;
51 raixget = 0;
52 raixput = 0;
53 rabuflen = 0;
54 return *this;
55 }
56
57 int
58 fhandler_base::puts_readahead (const char *s, size_t len)
59 {
60 int success = 1;
61 while ((len == (size_t) -1 ? *s : len--)
62 && (success = put_readahead (*s++) > 0))
63 continue;
64 return success;
65 }
66
67 int
68 fhandler_base::put_readahead (char value)
69 {
70 char *newrabuf;
71 if (raixput < rabuflen)
72 /* Nothing to do */;
73 else if ((newrabuf = (char *) realloc (rabuf, rabuflen += 32)))
74 rabuf = newrabuf;
75 else
76 return 0;
77
78 rabuf[raixput++] = value;
79 ralen++;
80 return 1;
81 }
82
83 int
84 fhandler_base::get_readahead ()
85 {
86 int chret = -1;
87 if (raixget < ralen)
88 chret = ((unsigned char) rabuf[raixget++]) & 0xff;
89 /* FIXME - not thread safe */
90 if (raixget >= ralen)
91 raixget = raixput = ralen = 0;
92 return chret;
93 }
94
95 int
96 fhandler_base::peek_readahead (int queryput)
97 {
98 int chret = -1;
99 if (!queryput && raixget < ralen)
100 chret = ((unsigned char) rabuf[raixget]) & 0xff;
101 else if (queryput && raixput > 0)
102 chret = ((unsigned char) rabuf[raixput - 1]) & 0xff;
103 return chret;
104 }
105
106 void
107 fhandler_base::set_readahead_valid (int val, int ch)
108 {
109 if (!val)
110 ralen = raixget = raixput = 0;
111 if (ch != -1)
112 put_readahead (ch);
113 }
114
115 int
116 fhandler_base::eat_readahead (int n)
117 {
118 int oralen = ralen;
119 if (n < 0)
120 n = ralen;
121 if (n > 0 && ralen)
122 {
123 if ((int) (ralen -= n) < 0)
124 ralen = 0;
125
126 if (raixget >= ralen)
127 raixget = raixput = ralen = 0;
128 else if (raixput > ralen)
129 raixput = ralen;
130 }
131
132 return oralen;
133 }
134
135 int
136 fhandler_base::get_readahead_into_buffer (char *buf, size_t buflen)
137 {
138 int ch;
139 int copied_chars = 0;
140
141 while (buflen)
142 if ((ch = get_readahead ()) < 0)
143 break;
144 else
145 {
146 buf[copied_chars++] = (unsigned char)(ch & 0xff);
147 buflen--;
148 }
149
150 return copied_chars;
151 }
152
153 /* Record the file name. and name hash */
154 void
155 fhandler_base::set_name (path_conv &in_pc)
156 {
157 pc = in_pc;
158 }
159
160 char *fhandler_base::get_proc_fd_name (char *buf)
161 {
162 if (get_name ())
163 return strcpy (buf, get_name ());
164 if (dev ().name)
165 return strcpy (buf, dev ().name);
166 return strcpy (buf, "");
167 }
168
169 /* Detect if we are sitting at EOF for conditions where Windows
170 returns an error but UNIX doesn't. */
171 static int __stdcall
172 is_at_eof (HANDLE h, DWORD err)
173 {
174 IO_STATUS_BLOCK io;
175 FILE_POSITION_INFORMATION fpi;
176 FILE_STANDARD_INFORMATION fsi;
177
178 if (NT_SUCCESS (NtQueryInformationFile (h, &io, &fsi, sizeof fsi,
179 FileStandardInformation))
180 && NT_SUCCESS (NtQueryInformationFile (h, &io, &fpi, sizeof fpi,
181 FilePositionInformation))
182 && fsi.EndOfFile.QuadPart == fpi.CurrentByteOffset.QuadPart)
183 return 1;
184 SetLastError (err);
185 return 0;
186 }
187
188 void
189 fhandler_base::set_flags (int flags, int supplied_bin)
190 {
191 int bin;
192 int fmode;
193 debug_printf ("flags %p, supplied_bin %p", flags, supplied_bin);
194 if ((bin = flags & (O_BINARY | O_TEXT)))
195 debug_printf ("O_TEXT/O_BINARY set in flags %p", bin);
196 else if (rbinset () && wbinset ())
197 bin = rbinary () ? O_BINARY : O_TEXT; // FIXME: Not quite right
198 else if ((fmode = get_default_fmode (flags)) & O_BINARY)
199 bin = O_BINARY;
200 else if (fmode & O_TEXT)
201 bin = O_TEXT;
202 else if (supplied_bin)
203 bin = supplied_bin;
204 else
205 bin = wbinary () || rbinary () || (binmode != O_TEXT)
206 ? O_BINARY : O_TEXT;
207
208 openflags = flags | bin;
209
210 bin &= O_BINARY;
211 rbinary (bin ? true : false);
212 wbinary (bin ? true : false);
213 syscall_printf ("filemode set to %s", bin ? "binary" : "text");
214 }
215
216 /* Normal file i/o handlers. */
217
218 /* Cover function to ReadFile to achieve (as much as possible) Posix style
219 semantics and use of errno. */
220 void
221 fhandler_base::raw_read (void *ptr, size_t& ulen)
222 {
223 #define bytes_read ulen
224
225 int try_noreserve = 1;
226 DWORD len = ulen;
227
228 retry:
229 ulen = (size_t) -1;
230 BOOL res = ReadFile (get_handle (), ptr, len, (DWORD *) &ulen, NULL);
231 if (!res)
232 {
233 /* Some errors are not really errors. Detect such cases here. */
234
235 DWORD errcode = GetLastError ();
236 switch (errcode)
237 {
238 case ERROR_BROKEN_PIPE:
239 /* This is really EOF. */
240 bytes_read = 0;
241 break;
242 case ERROR_MORE_DATA:
243 /* `bytes_read' is supposedly valid. */
244 break;
245 case ERROR_NOACCESS:
246 if (is_at_eof (get_handle (), errcode))
247 {
248 bytes_read = 0;
249 break;
250 }
251 if (try_noreserve)
252 {
253 try_noreserve = 0;
254 switch (mmap_is_attached_or_noreserve (ptr, len))
255 {
256 case MMAP_NORESERVE_COMMITED:
257 goto retry;
258 case MMAP_RAISE_SIGBUS:
259 raise(SIGBUS);
260 case MMAP_NONE:
261 break;
262 }
263 }
264 /*FALLTHRU*/
265 case ERROR_INVALID_FUNCTION:
266 case ERROR_INVALID_PARAMETER:
267 case ERROR_INVALID_HANDLE:
268 if (pc.isdir ())
269 {
270 set_errno (EISDIR);
271 bytes_read = (size_t) -1;
272 break;
273 }
274 default:
275 syscall_printf ("ReadFile %s(%p) failed, %E", get_name (), get_handle ());
276 __seterrno_from_win_error (errcode);
277 bytes_read = (size_t) -1;
278 break;
279 }
280 }
281 #undef bytes_read
282 }
283
284 /* Cover function to WriteFile to provide Posix interface and semantics
285 (as much as possible). */
286 static LARGE_INTEGER off_current = { QuadPart:FILE_USE_FILE_POINTER_POSITION };
287 static LARGE_INTEGER off_append = { QuadPart:FILE_WRITE_TO_END_OF_FILE };
288
289 int
290 fhandler_base::raw_write (const void *ptr, size_t len)
291 {
292 NTSTATUS status;
293 IO_STATUS_BLOCK io;
294
295 status = NtWriteFile (get_output_handle (), NULL, NULL, NULL, &io,
296 (PVOID) ptr, len,
297 (get_flags () & O_APPEND) ? &off_append : &off_current,
298 NULL);
299 if (!NT_SUCCESS (status))
300 {
301 if (status == STATUS_DISK_FULL && io.Information > 0)
302 goto written;
303 __seterrno_from_nt_status (status);
304 if (get_errno () == EPIPE)
305 raise (SIGPIPE);
306 return -1;
307 }
308 written:
309 return io.Information;
310 }
311
312 int
313 fhandler_base::get_default_fmode (int flags)
314 {
315 int fmode = __fmode;
316 if (perfile_table)
317 {
318 size_t nlen = strlen (get_name ());
319 unsigned accflags = (flags & O_ACCMODE);
320 for (__cygwin_perfile *pf = perfile_table; pf->name; pf++)
321 if (!*pf->name && (pf->flags & O_ACCMODE) == accflags)
322 {
323 fmode = pf->flags & ~O_ACCMODE;
324 break;
325 }
326 else
327 {
328 size_t pflen = strlen (pf->name);
329 const char *stem = get_name () + nlen - pflen;
330 if (pflen > nlen || (stem != get_name () && !isdirsep (stem[-1])))
331 continue;
332 else if ((pf->flags & O_ACCMODE) == accflags
333 && strcasematch (stem, pf->name))
334 {
335 fmode = pf->flags & ~O_ACCMODE;
336 break;
337 }
338 }
339 }
340 return fmode;
341 }
342
343 bool
344 fhandler_base::device_access_denied (int flags)
345 {
346 int mode = 0;
347
348 if (flags & O_RDWR)
349 mode |= R_OK | W_OK;
350 if (flags & (O_WRONLY | O_APPEND))
351 mode |= W_OK;
352 if (!mode)
353 mode |= R_OK;
354
355 return fhaccess (mode);
356 }
357
358 int
359 fhandler_base::fhaccess (int flags)
360 {
361 int res = -1;
362 if (error ())
363 {
364 set_errno (error ());
365 goto done;
366 }
367
368 if (!exists ())
369 {
370 set_errno (ENOENT);
371 goto done;
372 }
373
374 if (!(flags & (R_OK | W_OK | X_OK)))
375 return 0;
376
377 if (is_fs_special ())
378 /* short circuit */;
379 else if (has_attribute (FILE_ATTRIBUTE_READONLY) && (flags & W_OK)
380 && !pc.isdir ())
381 goto eaccess_done;
382 else if (has_acls () && allow_ntsec)
383 {
384 res = check_file_access (pc, flags);
385 goto done;
386 }
387 else if (get_device () == FH_REGISTRY && allow_ntsec && open (O_RDONLY, 0)
388 && get_handle ())
389 {
390 res = check_registry_access (get_handle (), flags);
391 close ();
392 return res;
393 }
394
395 struct __stat64 st;
396 if (fstat (&st))
397 goto done;
398
399 if (flags & R_OK)
400 {
401 if (st.st_uid == myself->uid)
402 {
403 if (!(st.st_mode & S_IRUSR))
404 goto eaccess_done;
405 }
406 else if (st.st_gid == myself->gid)
407 {
408 if (!(st.st_mode & S_IRGRP))
409 goto eaccess_done;
410 }
411 else if (!(st.st_mode & S_IROTH))
412 goto eaccess_done;
413 }
414
415 if (flags & W_OK)
416 {
417 if (st.st_uid == myself->uid)
418 {
419 if (!(st.st_mode & S_IWUSR))
420 goto eaccess_done;
421 }
422 else if (st.st_gid == myself->gid)
423 {
424 if (!(st.st_mode & S_IWGRP))
425 goto eaccess_done;
426 }
427 else if (!(st.st_mode & S_IWOTH))
428 goto eaccess_done;
429 }
430
431 if (flags & X_OK)
432 {
433 if (st.st_uid == myself->uid)
434 {
435 if (!(st.st_mode & S_IXUSR))
436 goto eaccess_done;
437 }
438 else if (st.st_gid == myself->gid)
439 {
440 if (!(st.st_mode & S_IXGRP))
441 goto eaccess_done;
442 }
443 else if (!(st.st_mode & S_IXOTH))
444 goto eaccess_done;
445 }
446
447 res = 0;
448 goto done;
449
450 eaccess_done:
451 set_errno (EACCES);
452 done:
453 if (!res && (flags & W_OK) && get_device () == FH_FS
454 && (pc.fs_flags () & FILE_READ_ONLY_VOLUME))
455 {
456 set_errno (EROFS);
457 res = -1;
458 }
459 debug_printf ("returning %d", res);
460 return res;
461 }
462
463 /* Open system call handler function. */
464 int
465 fhandler_base::open (int flags, mode_t mode)
466 {
467 int res = 0;
468 HANDLE x;
469 ULONG file_attributes = 0;
470 ULONG shared = (get_major () == DEV_TAPE_MAJOR ? 0 : FILE_SHARE_VALID_FLAGS);
471 ULONG create_disposition;
472 ULONG create_options;
473 SECURITY_ATTRIBUTES sa = sec_none;
474 security_descriptor sd;
475 OBJECT_ATTRIBUTES attr;
476 IO_STATUS_BLOCK io;
477 NTSTATUS status;
478
479 syscall_printf ("(%S, %p)", pc.get_nt_native_path (), flags);
480
481 pc.get_object_attr (attr, sa);
482
483 switch (query_open ())
484 {
485 case query_read_control:
486 access = READ_CONTROL;
487 create_options = FILE_OPEN_FOR_BACKUP_INTENT;
488 break;
489 case query_read_attributes:
490 access = READ_CONTROL | FILE_READ_ATTRIBUTES;
491 create_options = FILE_OPEN_FOR_BACKUP_INTENT;
492 break;
493 case query_write_control:
494 access = READ_CONTROL | WRITE_OWNER | WRITE_DAC | FILE_WRITE_ATTRIBUTES;
495 create_options = FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_FOR_RECOVERY;
496 break;
497 case query_write_attributes:
498 access = READ_CONTROL | FILE_WRITE_ATTRIBUTES;
499 create_options = FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_FOR_RECOVERY;
500 break;
501 default:
502 if ((flags & O_ACCMODE) == O_RDONLY)
503 {
504 access = GENERIC_READ;
505 create_options = FILE_OPEN_FOR_BACKUP_INTENT;
506 }
507 else if ((flags & O_ACCMODE) == O_WRONLY)
508 {
509 access = GENERIC_WRITE | READ_CONTROL | FILE_READ_ATTRIBUTES;
510 create_options = FILE_OPEN_FOR_BACKUP_INTENT
511 | FILE_OPEN_FOR_RECOVERY;
512 }
513 else
514 {
515 access = GENERIC_READ | GENERIC_WRITE;
516 create_options = FILE_OPEN_FOR_BACKUP_INTENT
517 | FILE_OPEN_FOR_RECOVERY;
518 }
519 if (flags & O_SYNC)
520 create_options |= FILE_WRITE_THROUGH;
521 if (flags & O_DIRECT)
522 create_options |= FILE_NO_INTERMEDIATE_BUFFERING;
523 if (get_major () != DEV_SERIAL_MAJOR && get_major () != DEV_TAPE_MAJOR)
524 {
525 create_options |= FILE_SYNCHRONOUS_IO_NONALERT;
526 access |= SYNCHRONIZE;
527 }
528 break;
529 }
530
531 if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY))
532 {
533 if (flags & O_CREAT)
534 create_disposition = FILE_OVERWRITE_IF;
535 else
536 create_disposition = FILE_OVERWRITE;
537 }
538 else if (flags & O_CREAT)
539 create_disposition = FILE_OPEN_IF;
540 else
541 create_disposition = FILE_OPEN;
542
543 if ((flags & O_EXCL) && (flags & O_CREAT))
544 create_disposition = FILE_CREATE;
545
546 if (get_device () == FH_FS)
547 {
548 /* Add the reparse point flag to native symlinks, otherwise we open the
549 target, not the symlink. This would break lstat. */
550 if (pc.is_rep_symlink ())
551 create_options |= FILE_OPEN_REPARSE_POINT;
552
553 if (flags & O_CREAT)
554 {
555 file_attributes = FILE_ATTRIBUTE_NORMAL;
556 /* If mode has no write bits set, we set the R/O attribute. */
557 if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
558 file_attributes |= FILE_ATTRIBUTE_READONLY;
559 /* Starting with Windows 2000, when trying to overwrite an already
560 existing file with FILE_ATTRIBUTE_HIDDEN and/or FILE_ATTRIBUTE_SYSTEM
561 attribute set, CreateFile fails with ERROR_ACCESS_DENIED.
562 Per MSDN you have to create the file with the same attributes as
563 already specified for the file. */
564 if (has_attribute (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM))
565 file_attributes |= pc.file_attributes ();
566
567 /* If the file should actually be created and ntsec is on,
568 set files attributes. */
569 /* TODO: Don't remove the call to has_acls() unless there's a
570 solution for the security descriptor problem on remote samba
571 drives. The local user SID is used in set_security_attribute,
572 but the actual owner on the Samba share is the SID of the Unix
573 account. There's no transparent mapping between these accounts.
574 And Samba has a strange behaviour when creating a file. Apparently
575 it *first* creates the file, *then* it looks if the security
576 descriptor matches. The result is that the file gets created, but
577 then NtCreateFile doesn't return a handle to the file and fails
578 with STATUS_ACCESS_DENIED. Go figure! */
579 if (allow_ntsec && has_acls ())
580 {
581 set_security_attribute (mode, &sa, sd);
582 attr.SecurityDescriptor = sa.lpSecurityDescriptor;
583 }
584 /* The file attributes are needed for later use in, e.g. fchmod. */
585 pc.file_attributes (file_attributes);
586 }
587 }
588
589 status = NtCreateFile (&x, access, &attr, &io, NULL, file_attributes, shared,
590 create_disposition, create_options, NULL, 0);
591 if (!NT_SUCCESS (status))
592 {
593 __seterrno_from_nt_status (status);
594 if (!nohandle ())
595 goto done;
596 }
597
598 set_io_handle (x);
599 set_flags (flags, pc.binmode ());
600
601 res = 1;
602 set_open_status ();
603 done:
604 debug_printf ("%x = NtCreateFile "
605 "(%p, %x, %S, io, NULL, %x, %x, %x, %x, NULL, 0)",
606 status, x, access, pc.get_nt_native_path (), file_attributes,
607 shared, create_disposition, create_options);
608
609 syscall_printf ("%d = fhandler_base::open (%s, %p)",
610 res, pc.get_nt_native_path (), flags);
611 return res;
612 }
613
614 /* states:
615 open buffer in binary mode? Just do the read.
616
617 open buffer in text mode? Scan buffer for control zs and handle
618 the first one found. Then scan buffer, converting every \r\n into
619 an \n. If last char is an \r, look ahead one more char, if \n then
620 modify \r, if not, remember char.
621 */
622 void
623 fhandler_base::read (void *in_ptr, size_t& len)
624 {
625 char *ptr = (char *) in_ptr;
626 ssize_t copied_chars = get_readahead_into_buffer (ptr, len);
627
628 if (copied_chars && is_slow ())
629 {
630 len = (size_t) copied_chars;
631 goto out;
632 }
633
634 len -= copied_chars;
635 if (!len)
636 {
637 len = (size_t) copied_chars;
638 goto out;
639 }
640
641 raw_read (ptr + copied_chars, len);
642 if (!copied_chars)
643 /* nothing */;
644 else if ((ssize_t) len > 0)
645 len += copied_chars;
646 else
647 len = copied_chars;
648
649 if (rbinary () || len <= 0)
650 goto out;
651
652 /* Scan buffer and turn \r\n into \n */
653 char *src, *dst, *end;
654 src = (char *) ptr;
655 dst = (char *) ptr;
656 end = src + len - 1;
657
658 /* Read up to the last but one char - the last char needs special handling */
659 while (src < end)
660 {
661 if (*src == '\r' && src[1] == '\n')
662 src++;
663 *dst++ = *src++;
664 }
665
666 /* If not beyond end and last char is a '\r' then read one more
667 to see if we should translate this one too */
668 if (src > end)
669 /* nothing */;
670 else if (*src != '\r')
671 *dst++ = *src;
672 else
673 {
674 char c1;
675 size_t c1len = 1;
676 raw_read (&c1, c1len);
677 if (c1len <= 0)
678 /* nothing */;
679 else if (c1 == '\n')
680 *dst++ = '\n';
681 else
682 {
683 set_readahead_valid (1, c1);
684 *dst++ = *src;
685 }
686 }
687
688 len = dst - (char *) ptr;
689
690 #ifndef NOSTRACE
691 if (strace.active ())
692 {
693 char buf[16 * 6 + 1];
694 char *p = buf;
695
696 for (int i = 0; i < copied_chars && i < 16; ++i)
697 {
698 unsigned char c = ((unsigned char *) ptr)[i];
699 __small_sprintf (p, " %c", c);
700 p += strlen (p);
701 }
702 *p = '\0';
703 debug_printf ("read %d bytes (%s%s)", copied_chars, buf,
704 copied_chars > 16 ? " ..." : "");
705 }
706 #endif
707
708 out:
709 debug_printf ("returning %d, %s mode", len, rbinary () ? "binary" : "text");
710 }
711
712 int
713 fhandler_base::write (const void *ptr, size_t len)
714 {
715 int res;
716 IO_STATUS_BLOCK io;
717 FILE_POSITION_INFORMATION fpi;
718 FILE_STANDARD_INFORMATION fsi;
719
720 if (did_lseek ())
721 {
722 did_lseek (false); /* don't do it again */
723
724 if (!(get_flags () & O_APPEND)
725 && NT_SUCCESS (NtQueryInformationFile (get_output_handle (),
726 &io, &fsi, sizeof fsi,
727 FileStandardInformation))
728 && NT_SUCCESS (NtQueryInformationFile (get_output_handle (),
729 &io, &fpi, sizeof fpi,
730 FilePositionInformation))
731 && fpi.CurrentByteOffset.QuadPart
732 >= fsi.EndOfFile.QuadPart + (128 * 1024)
733 && get_fs_flags (FILE_SUPPORTS_SPARSE_FILES))
734 {
735 /* If the file system supports sparse files and the application
736 is writing after a long seek beyond EOF, convert the file to
737 a sparse file. */
738 NTSTATUS status;
739 status = NtFsControlFile (get_output_handle (), NULL, NULL, NULL,
740 &io, FSCTL_SET_SPARSE, NULL, 0, NULL, 0);
741 syscall_printf ("%p = NtFsControlFile(%S, FSCTL_SET_SPARSE)",
742 status, pc.get_nt_native_path ());
743 }
744 }
745
746 if (wbinary ())
747 {
748 debug_printf ("binary write");
749 res = raw_write (ptr, len);
750 }
751 else
752 {
753 debug_printf ("text write");
754 /* This is the Microsoft/DJGPP way. Still not ideal, but it's
755 compatible.
756 Modified slightly by CGF 2000-10-07 */
757
758 int left_in_data = len;
759 char *data = (char *)ptr;
760 res = 0;
761
762 while (left_in_data > 0)
763 {
764 char buf[CHUNK_SIZE + 1], *buf_ptr = buf;
765 int left_in_buf = CHUNK_SIZE;
766
767 while (left_in_buf > 0 && left_in_data > 0)
768 {
769 char ch = *data++;
770 if (ch == '\n')
771 {
772 *buf_ptr++ = '\r';
773 left_in_buf--;
774 }
775 *buf_ptr++ = ch;
776 left_in_buf--;
777 left_in_data--;
778 if (left_in_data > 0 && ch == '\r' && *data == '\n')
779 {
780 *buf_ptr++ = *data++;
781 left_in_buf--;
782 left_in_data--;
783 }
784 }
785
786 /* We've got a buffer-full, or we're out of data. Write it out */
787 int nbytes;
788 int want = buf_ptr - buf;
789 if ((nbytes = raw_write (buf, want)) == want)
790 {
791 /* Keep track of how much written not counting additional \r's */
792 res = data - (char *)ptr;
793 continue;
794 }
795
796 if (nbytes == -1)
797 res = -1; /* Error */
798 else
799 res += nbytes; /* Partial write. Return total bytes written. */
800 break; /* All done */
801 }
802 }
803
804 return res;
805 }
806
807 ssize_t
808 fhandler_base::readv (const struct iovec *const iov, const int iovcnt,
809 ssize_t tot)
810 {
811 assert (iov);
812 assert (iovcnt >= 1);
813
814 size_t len = tot;
815 if (iovcnt == 1)
816 {
817 len = iov->iov_len;
818 read (iov->iov_base, len);
819 return len;
820 }
821
822 if (tot == -1) // i.e. if not pre-calculated by the caller.
823 {
824 len = 0;
825 const struct iovec *iovptr = iov + iovcnt;
826 do
827 {
828 iovptr -= 1;
829 len += iovptr->iov_len;
830 }
831 while (iovptr != iov);
832 }
833
834 if (!len)
835 return 0;
836
837 char *buf = (char *) malloc (len);
838
839 if (!buf)
840 {
841 set_errno (ENOMEM);
842 return -1;
843 }
844
845 read (buf, len);
846 ssize_t nbytes = (ssize_t) len;
847
848 const struct iovec *iovptr = iov;
849
850 char *p = buf;
851 while (nbytes > 0)
852 {
853 const int frag = min (nbytes, (ssize_t) iovptr->iov_len);
854 memcpy (iovptr->iov_base, p, frag);
855 p += frag;
856 iovptr += 1;
857 nbytes -= frag;
858 }
859
860 free (buf);
861 return len;
862 }
863
864 ssize_t
865 fhandler_base::writev (const struct iovec *const iov, const int iovcnt,
866 ssize_t tot)
867 {
868 assert (iov);
869 assert (iovcnt >= 1);
870
871 if (iovcnt == 1)
872 return write (iov->iov_base, iov->iov_len);
873
874 if (tot == -1) // i.e. if not pre-calculated by the caller.
875 {
876 tot = 0;
877 const struct iovec *iovptr = iov + iovcnt;
878 do
879 {
880 iovptr -= 1;
881 tot += iovptr->iov_len;
882 }
883 while (iovptr != iov);
884 }
885
886 assert (tot >= 0);
887
888 if (tot == 0)
889 return 0;
890
891 char *const buf = (char *) malloc (tot);
892
893 if (!buf)
894 {
895 set_errno (ENOMEM);
896 return -1;
897 }
898
899 char *bufptr = buf;
900 const struct iovec *iovptr = iov;
901 int nbytes = tot;
902
903 while (nbytes != 0)
904 {
905 const int frag = min (nbytes, (ssize_t) iovptr->iov_len);
906 memcpy (bufptr, iovptr->iov_base, frag);
907 bufptr += frag;
908 iovptr += 1;
909 nbytes -= frag;
910 }
911 ssize_t ret = write (buf, tot);
912 free (buf);
913 return ret;
914 }
915
916 _off64_t
917 fhandler_base::lseek (_off64_t offset, int whence)
918 {
919 NTSTATUS status;
920 IO_STATUS_BLOCK io;
921 FILE_POSITION_INFORMATION fpi;
922 FILE_STANDARD_INFORMATION fsi;
923
924 /* Seeks on text files is tough, we rewind and read till we get to the
925 right place. */
926
927 if (whence != SEEK_CUR || offset != 0)
928 {
929 if (whence == SEEK_CUR)
930 offset -= ralen - raixget;
931 set_readahead_valid (0);
932 }
933
934 switch (whence)
935 {
936 case SEEK_SET:
937 fpi.CurrentByteOffset.QuadPart = offset;
938 break;
939 case SEEK_CUR:
940 status = NtQueryInformationFile (get_handle (), &io, &fpi, sizeof fpi,
941 FilePositionInformation);
942 if (!NT_SUCCESS (status))
943 {
944 __seterrno_from_nt_status (status);
945 return -1;
946 }
947 fpi.CurrentByteOffset.QuadPart += offset;
948 break;
949 default: /* SEEK_END */
950 status = NtQueryInformationFile (get_handle (), &io, &fsi, sizeof fsi,
951 FileStandardInformation);
952 if (!NT_SUCCESS (status))
953 {
954 __seterrno_from_nt_status (status);
955 return -1;
956 }
957 fpi.CurrentByteOffset.QuadPart = fsi.EndOfFile.QuadPart + offset;
958 break;
959 }
960
961 debug_printf ("setting file pointer to %U", fpi.CurrentByteOffset.QuadPart);
962 status = NtSetInformationFile (get_handle (), &io, &fpi, sizeof fpi,
963 FilePositionInformation);
964 if (!NT_SUCCESS (status))
965 {
966 __seterrno_from_nt_status (status);
967 return -1;
968 }
969 _off64_t res = fpi.CurrentByteOffset.QuadPart;
970
971 /* When next we write(), we will check to see if *this* seek went beyond
972 the end of the file and if so, potentially sparsify the file. */
973 did_lseek (true);
974
975 /* If this was a SEEK_CUR with offset 0, we still might have
976 readahead that we have to take into account when calculating
977 the actual position for the application. */
978 if (whence == SEEK_CUR)
979 res -= ralen - raixget;
980
981 return res;
982 }
983
984 ssize_t __stdcall
985 fhandler_base::pread (void *, size_t, _off64_t)
986 {
987 set_errno (ESPIPE);
988 return -1;
989 }
990
991 ssize_t __stdcall
992 fhandler_base::pwrite (void *, size_t, _off64_t)
993 {
994 set_errno (ESPIPE);
995 return -1;
996 }
997
998 int
999 fhandler_base::close ()
1000 {
1001 int res = -1;
1002
1003 syscall_printf ("closing '%s' handle %p", get_name (), get_handle ());
1004 if (nohandle () || CloseHandle (get_handle ()))
1005 res = 0;
1006 else
1007 {
1008 paranoid_printf ("CloseHandle (%d <%s>) failed", get_handle (),
1009 get_name ());
1010
1011 __seterrno ();
1012 }
1013 destroy_overlapped ();
1014 return res;
1015 }
1016
1017 int
1018 fhandler_base::ioctl (unsigned int cmd, void *buf)
1019 {
1020 int res;
1021
1022 switch (cmd)
1023 {
1024 case FIONBIO:
1025 set_nonblocking (*(int *) buf);
1026 res = 0;
1027 break;
1028 default:
1029 set_errno (EINVAL);
1030 res = -1;
1031 break;
1032 }
1033
1034 syscall_printf ("%d = ioctl (%x, %p)", res, cmd, buf);
1035 return res;
1036 }
1037
1038 int
1039 fhandler_base::lock (int, struct __flock64 *)
1040 {
1041 set_errno (EINVAL);
1042 return -1;
1043 }
1044
1045 int __stdcall
1046 fhandler_base::fstat (struct __stat64 *buf)
1047 {
1048 debug_printf ("here");
1049
1050 if (is_fs_special ())
1051 return fstat_fs (buf);
1052
1053 switch (get_device ())
1054 {
1055 case FH_PIPE:
1056 buf->st_mode = S_IFIFO | S_IRUSR | S_IWUSR;
1057 break;
1058 case FH_PIPEW:
1059 buf->st_mode = S_IFIFO | S_IWUSR;
1060 break;
1061 case FH_PIPER:
1062 buf->st_mode = S_IFIFO | S_IRUSR;
1063 break;
1064 case FH_FULL:
1065 buf->st_mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
1066 break;
1067 default:
1068 buf->st_mode = S_IFCHR | STD_RBITS | STD_WBITS | S_IWGRP | S_IWOTH;
1069 break;
1070 }
1071
1072 buf->st_uid = geteuid32 ();
1073 buf->st_gid = getegid32 ();
1074 buf->st_nlink = 1;
1075 buf->st_blksize = PREFERRED_IO_BLKSIZE;
1076 buf->st_ctim.tv_sec = 1164931200L; /* Arbitrary value: 2006-12-01 */
1077 buf->st_ctim.tv_nsec = 0L;
1078 buf->st_atim = buf->st_mtim = buf->st_birthtim = buf->st_ctim;
1079 return 0;
1080 }
1081
1082 int __stdcall
1083 fhandler_base::fstatvfs (struct statvfs *sfs)
1084 {
1085 /* If we hit this base implementation, it's some device in /dev.
1086 Just call statvfs on /dev for simplicity. */
1087 path_conv pc ("/dev");
1088 fhandler_disk_file fh (pc);
1089 return fh.fstatvfs (sfs);
1090 }
1091
1092 void
1093 fhandler_base::init (HANDLE f, DWORD a, mode_t bin)
1094 {
1095 set_io_handle (f);
1096 access = a;
1097 a &= GENERIC_READ | GENERIC_WRITE;
1098 int flags = 0;
1099 if (a == GENERIC_READ)
1100 flags = O_RDONLY;
1101 else if (a == GENERIC_WRITE)
1102 flags = O_WRONLY;
1103 else if (a == (GENERIC_READ | GENERIC_WRITE))
1104 flags = O_RDWR;
1105 set_flags (flags | bin);
1106 set_open_status ();
1107 debug_printf ("created new fhandler_base for handle %p, bin %d", f, rbinary ());
1108 }
1109
1110 int
1111 fhandler_base::dup (fhandler_base *child)
1112 {
1113 debug_printf ("in fhandler_base dup");
1114
1115 HANDLE nh;
1116 if (!nohandle ())
1117 {
1118 if (!DuplicateHandle (hMainProc, get_handle (), hMainProc, &nh, 0, TRUE,
1119 DUPLICATE_SAME_ACCESS))
1120 {
1121 debug_printf ("dup(%s) failed, handle %x, %E",
1122 get_name (), get_handle ());
1123 __seterrno ();
1124 return -1;
1125 }
1126
1127 VerifyHandle (nh);
1128 child->set_io_handle (nh);
1129 }
1130 if (get_overlapped ())
1131 child->setup_overlapped ();
1132 set_flags (child->get_flags ());
1133 return 0;
1134 }
1135
1136 int fhandler_base::fcntl (int cmd, void *arg)
1137 {
1138 int res;
1139
1140 switch (cmd)
1141 {
1142 case F_GETFD:
1143 res = close_on_exec () ? FD_CLOEXEC : 0;
1144 break;
1145 case F_SETFD:
1146 set_close_on_exec (((int) arg & FD_CLOEXEC) ? 1 : 0);
1147 res = 0;
1148 break;
1149 case F_GETFL:
1150 res = get_flags ();
1151 debug_printf ("GETFL: %p", res);
1152 break;
1153 case F_SETFL:
1154 {
1155 /*
1156 * Only O_APPEND, O_ASYNC and O_NONBLOCK/O_NDELAY are allowed.
1157 * Each other flag will be ignored.
1158 * Since O_ASYNC isn't defined in fcntl.h it's currently
1159 * ignored as well.
1160 */
1161 const int allowed_flags = O_APPEND | O_NONBLOCK_MASK;
1162 int new_flags = (int) arg & allowed_flags;
1163 /* Carefully test for the O_NONBLOCK or deprecated OLD_O_NDELAY flag.
1164 Set only the flag that has been passed in. If both are set, just
1165 record O_NONBLOCK. */
1166 if ((new_flags & OLD_O_NDELAY) && (new_flags & O_NONBLOCK))
1167 new_flags &= ~OLD_O_NDELAY;
1168 set_flags ((get_flags () & ~allowed_flags) | new_flags);
1169 }
1170 res = 0;
1171 break;
1172 case F_GETLK:
1173 case F_SETLK:
1174 case F_SETLKW:
1175 res = lock (cmd, (struct __flock64 *) arg);
1176 break;
1177 default:
1178 set_errno (EINVAL);
1179 res = -1;
1180 break;
1181 }
1182 return res;
1183 }
1184
1185 /* Base terminal handlers. These just return errors. */
1186
1187 int
1188 fhandler_base::tcflush (int)
1189 {
1190 set_errno (ENOTTY);
1191 return -1;
1192 }
1193
1194 int
1195 fhandler_base::tcsendbreak (int)
1196 {
1197 set_errno (ENOTTY);
1198 return -1;
1199 }
1200
1201 int
1202 fhandler_base::tcdrain ()
1203 {
1204 set_errno (ENOTTY);
1205 return -1;
1206 }
1207
1208 int
1209 fhandler_base::tcflow (int)
1210 {
1211 set_errno (ENOTTY);
1212 return -1;
1213 }
1214
1215 int
1216 fhandler_base::tcsetattr (int, const struct termios *)
1217 {
1218 set_errno (ENOTTY);
1219 return -1;
1220 }
1221
1222 int
1223 fhandler_base::tcgetattr (struct termios *)
1224 {
1225 set_errno (ENOTTY);
1226 return -1;
1227 }
1228
1229 int
1230 fhandler_base::tcsetpgrp (const pid_t)
1231 {
1232 set_errno (ENOTTY);
1233 return -1;
1234 }
1235
1236 int
1237 fhandler_base::tcgetpgrp ()
1238 {
1239 set_errno (ENOTTY);
1240 return -1;
1241 }
1242
1243 void
1244 fhandler_base::operator delete (void *p)
1245 {
1246 cfree (p);
1247 }
1248
1249 /* Normal I/O constructor */
1250 fhandler_base::fhandler_base () :
1251 status (),
1252 open_status (),
1253 access (0),
1254 io_handle (NULL),
1255 namehash (0),
1256 openflags (0),
1257 rabuf (NULL),
1258 ralen (0),
1259 raixget (0),
1260 raixput (0),
1261 rabuflen (0),
1262 fs_flags (0),
1263 archetype (NULL),
1264 usecount (0)
1265 {
1266 }
1267
1268 /* Normal I/O destructor */
1269 fhandler_base::~fhandler_base ()
1270 {
1271 if (rabuf)
1272 free (rabuf);
1273 }
1274
1275 /**********************************************************************/
1276 /* /dev/null */
1277
1278 fhandler_dev_null::fhandler_dev_null () :
1279 fhandler_base ()
1280 {
1281 }
1282
1283 void
1284 fhandler_base::set_no_inheritance (HANDLE &h, bool not_inheriting)
1285 {
1286 if (!SetHandleInformation (h, HANDLE_FLAG_INHERIT,
1287 not_inheriting ? 0 : HANDLE_FLAG_INHERIT))
1288 debug_printf ("SetHandleInformation failed, %E");
1289 #ifdef DEBUGGING_AND_FDS_PROTECTED
1290 if (h)
1291 setclexec (oh, h, not_inheriting);
1292 #endif
1293 }
1294
1295 bool
1296 fhandler_base::fork_fixup (HANDLE parent, HANDLE &h, const char *name)
1297 {
1298 HANDLE oh = h;
1299 bool res = false;
1300 if (/* !is_socket () && */ !close_on_exec ())
1301 debug_printf ("handle %p already opened", h);
1302 else if (!DuplicateHandle (parent, h, hMainProc, &h, 0, !close_on_exec (),
1303 DUPLICATE_SAME_ACCESS))
1304 system_printf ("%s - %E, handle %s<%p>", get_name (), name, h);
1305 else
1306 {
1307 if (oh != h)
1308 VerifyHandle (h);
1309 res = true;
1310 }
1311 if (get_overlapped ())
1312 setup_overlapped ();
1313 return res;
1314 }
1315
1316 void
1317 fhandler_base::set_close_on_exec (bool val)
1318 {
1319 if (!nohandle ())
1320 set_no_inheritance (io_handle, val);
1321 close_on_exec (val);
1322 debug_printf ("set close_on_exec for %s to %d", get_name (), val);
1323 }
1324
1325 void
1326 fhandler_base::fixup_after_fork (HANDLE parent)
1327 {
1328 debug_printf ("inheriting '%s' from parent", get_name ());
1329 if (!nohandle ())
1330 fork_fixup (parent, io_handle, "io_handle");
1331 if (get_overlapped ())
1332 setup_overlapped ();
1333 }
1334
1335 void
1336 fhandler_base::fixup_after_exec ()
1337 {
1338 debug_printf ("here for '%s'", get_name ());
1339 if (get_overlapped ())
1340 setup_overlapped ();
1341 }
1342
1343 bool
1344 fhandler_base::is_nonblocking ()
1345 {
1346 return (openflags & O_NONBLOCK_MASK) != 0;
1347 }
1348
1349 void
1350 fhandler_base::set_nonblocking (int yes)
1351 {
1352 int current = openflags & O_NONBLOCK_MASK;
1353 int new_flags = yes ? (!current ? O_NONBLOCK : current) : 0;
1354 openflags = (openflags & ~O_NONBLOCK_MASK) | new_flags;
1355 }
1356
1357 int
1358 fhandler_base::mkdir (mode_t)
1359 {
1360 if (exists ())
1361 set_errno (EEXIST);
1362 else
1363 set_errno (EROFS);
1364 return -1;
1365 }
1366
1367 int
1368 fhandler_base::rmdir ()
1369 {
1370 if (!exists ())
1371 set_errno (ENOENT);
1372 else if (!pc.isdir ())
1373 set_errno (ENOTDIR);
1374 else
1375 set_errno (EROFS);
1376 return -1;
1377 }
1378
1379 DIR *
1380 fhandler_base::opendir (int fd)
1381 {
1382 set_errno (ENOTDIR);
1383 return NULL;
1384 }
1385
1386 int
1387 fhandler_base::readdir (DIR *, dirent *)
1388 {
1389 return ENOTDIR;
1390 }
1391
1392 _off64_t
1393 fhandler_base::telldir (DIR *)
1394 {
1395 set_errno (ENOTDIR);
1396 return -1;
1397 }
1398
1399 void
1400 fhandler_base::seekdir (DIR *, _off64_t)
1401 {
1402 set_errno (ENOTDIR);
1403 }
1404
1405 void
1406 fhandler_base::rewinddir (DIR *)
1407 {
1408 set_errno (ENOTDIR);
1409 }
1410
1411 int
1412 fhandler_base::closedir (DIR *)
1413 {
1414 set_errno (ENOTDIR);
1415 return -1;
1416 }
1417
1418 int
1419 fhandler_base::fchmod (mode_t mode)
1420 {
1421 extern int chmod_device (path_conv& pc, mode_t mode);
1422 if (pc.is_fs_special ())
1423 return chmod_device (pc, mode);
1424 /* By default, just succeeds. */
1425 return 0;
1426 }
1427
1428 int
1429 fhandler_base::fchown (__uid32_t uid, __gid32_t gid)
1430 {
1431 if (pc.is_fs_special ())
1432 return ((fhandler_disk_file *) this)->fhandler_disk_file::fchown (uid, gid);
1433 /* By default, just succeeds. */
1434 return 0;
1435 }
1436
1437 int
1438 fhandler_base::facl (int cmd, int nentries, __aclent32_t *aclbufp)
1439 {
1440 int res = -1;
1441 switch (cmd)
1442 {
1443 case SETACL:
1444 /* By default, just succeeds. */
1445 res = 0;
1446 break;
1447 case GETACL:
1448 if (!aclbufp)
1449 set_errno(EFAULT);
1450 else if (nentries < MIN_ACL_ENTRIES)
1451 set_errno (ENOSPC);
1452 else
1453 {
1454 aclbufp[0].a_type = USER_OBJ;
1455 aclbufp[0].a_id = myself->uid;
1456 aclbufp[0].a_perm = (S_IRUSR | S_IWUSR) >> 6;
1457 aclbufp[1].a_type = GROUP_OBJ;
1458 aclbufp[1].a_id = myself->gid;
1459 aclbufp[1].a_perm = (S_IRGRP | S_IWGRP) >> 3;
1460 aclbufp[2].a_type = OTHER_OBJ;
1461 aclbufp[2].a_id = ILLEGAL_GID;
1462 aclbufp[2].a_perm = S_IROTH | S_IWOTH;
1463 aclbufp[3].a_type = CLASS_OBJ;
1464 aclbufp[3].a_id = ILLEGAL_GID;
1465 aclbufp[3].a_perm = S_IRWXU | S_IRWXG | S_IRWXO;
1466 res = MIN_ACL_ENTRIES;
1467 }
1468 break;
1469 case GETACLCNT:
1470 res = MIN_ACL_ENTRIES;
1471 break;
1472 default:
1473 set_errno (EINVAL);
1474 break;
1475 }
1476 return res;
1477 }
1478
1479 ssize_t
1480 fhandler_base::fgetxattr (const char *name, void *value, size_t size)
1481 {
1482 set_errno (ENOTSUP);
1483 return -1;
1484 }
1485
1486 int
1487 fhandler_base::fsetxattr (const char *name, const void *value, size_t size,
1488 int flags)
1489 {
1490 set_errno (ENOTSUP);
1491 return -1;
1492 }
1493
1494 int
1495 fhandler_base::fadvise (_off64_t offset, _off64_t length, int advice)
1496 {
1497 set_errno (EINVAL);
1498 return -1;
1499 }
1500
1501 int
1502 fhandler_base::ftruncate (_off64_t length, bool allow_truncate)
1503 {
1504 set_errno (EINVAL);
1505 return -1;
1506 }
1507
1508 int
1509 fhandler_base::link (const char *newpath)
1510 {
1511 set_errno (EINVAL);
1512 return -1;
1513 }
1514
1515 int
1516 fhandler_base::utimes (const struct timeval *tvp)
1517 {
1518 if (is_fs_special ())
1519 return utimes_fs (tvp);
1520
1521 set_errno (EINVAL);
1522 return -1;
1523 }
1524
1525 int
1526 fhandler_base::fsync ()
1527 {
1528 if (!get_handle () || nohandle ())
1529 {
1530 set_errno (EINVAL);
1531 return -1;
1532 }
1533 if (pc.isdir ()) /* Just succeed. */
1534 return 0;
1535 if (FlushFileBuffers (get_handle ()))
1536 return 0;
1537 __seterrno ();
1538 return -1;
1539 }
1540
1541 int
1542 fhandler_base::fpathconf (int v)
1543 {
1544 switch (v)
1545 {
1546 case _PC_LINK_MAX:
1547 return pc.fs_is_ntfs () || pc.fs_is_samba () || pc.fs_is_nfs ()
1548 ? LINK_MAX : 1;
1549 case _PC_MAX_CANON:
1550 if (is_tty ())
1551 return MAX_CANON;
1552 set_errno (EINVAL);
1553 break;
1554 case _PC_MAX_INPUT:
1555 if (is_tty ())
1556 return MAX_INPUT;
1557 set_errno (EINVAL);
1558 break;
1559 case _PC_NAME_MAX:
1560 /* NAME_MAX is without trailing \0 */
1561 return pc.isdir () ? PATH_MAX - strlen (get_name ()) - 2 : NAME_MAX;
1562 case _PC_PATH_MAX:
1563 /* PATH_MAX is with trailing \0 */
1564 return pc.isdir () ? PATH_MAX - strlen (get_name ()) - 1 : PATH_MAX;
1565 case _PC_PIPE_BUF:
1566 if (pc.isdir ()
1567 || get_device () == FH_FIFO || get_device () == FH_PIPE
1568 || get_device () == FH_PIPER || get_device () == FH_PIPEW)
1569 return PIPE_BUF;
1570 set_errno (EINVAL);
1571 break;
1572 case _PC_CHOWN_RESTRICTED:
1573 return 1;
1574 case _PC_NO_TRUNC:
1575 return 1;
1576 case _PC_VDISABLE:
1577 if (is_tty ())
1578 return _POSIX_VDISABLE;
1579 set_errno (EINVAL);
1580 break;
1581 case _PC_ASYNC_IO:
1582 case _PC_PRIO_IO:
1583 break;
1584 case _PC_SYNC_IO:
1585 return 1;
1586 case _PC_FILESIZEBITS:
1587 return FILESIZEBITS;
1588 case _PC_2_SYMLINKS:
1589 return 1;
1590 case _PC_SYMLINK_MAX:
1591 return SYMLINK_MAX;
1592 case _PC_POSIX_PERMISSIONS:
1593 case _PC_POSIX_SECURITY:
1594 if (get_device () == FH_FS)
1595 return pc.has_acls ();
1596 set_errno (EINVAL);
1597 break;
1598 default:
1599 set_errno (EINVAL);
1600 break;
1601 }
1602 return -1;
1603 }
1604
1605 /* Overlapped I/O */
1606
1607 bool
1608 fhandler_base::setup_overlapped ()
1609 {
1610 OVERLAPPED *ov = get_overlapped ();
1611 memset (ov, 0, sizeof (*ov));
1612 return ov->hEvent = CreateEvent (&sec_none_nih, true, false, NULL);
1613 }
1614
1615 void
1616 fhandler_base::destroy_overlapped ()
1617 {
1618 OVERLAPPED *ov = get_overlapped ();
1619 if (ov && ov->hEvent)
1620 {
1621 CloseHandle (ov->hEvent);
1622 ov->hEvent = NULL;
1623 }
1624 }
1625
1626 int
1627 fhandler_base::wait_overlapped (bool& res, bool writing, DWORD *bytes)
1628 {
1629 if (bytes)
1630 *bytes = (DWORD) -1;
1631 DWORD err = GetLastError ();
1632 if (!res && err != ERROR_IO_PENDING)
1633 {
1634 if (err != ERROR_HANDLE_EOF && err != ERROR_BROKEN_PIPE)
1635 goto err;
1636 res = 1;
1637 if (*bytes)
1638 *bytes = 0;
1639 }
1640 else
1641 {
1642 #ifdef DEBUGGING
1643 if (!get_overlapped ())
1644 system_printf ("get_overlapped is zero?");
1645 if (!get_overlapped ()->hEvent)
1646 system_printf ("hEvent is zero?");
1647 #endif
1648 DWORD n = 1;
1649 HANDLE w4[2];
1650 w4[0] = get_overlapped ()->hEvent;
1651 if (&_my_tls == _main_tls)
1652 w4[n++] = signal_arrived;
1653 HANDLE h = writing ? get_output_handle () : get_handle ();
1654 switch (WaitForMultipleObjects (n, w4, false, INFINITE))
1655 {
1656 case WAIT_OBJECT_0:
1657 debug_printf ("normal read");
1658 if (!bytes ||
1659 GetOverlappedResult (h, get_overlapped (), bytes, false))
1660 res = 1;
1661 else
1662 {
1663 err = GetLastError ();
1664 goto err;
1665 }
1666 break;
1667 case WAIT_OBJECT_0 + 1:
1668 debug_printf ("got a signal");
1669 CancelIo (h);
1670 set_errno (EINTR);
1671 res = 0;
1672 break;
1673 default:
1674 err = GetLastError ();
1675 debug_printf ("WFMO error, %E");
1676 goto err;
1677 break;
1678 }
1679 }
1680 goto out;
1681
1682 err:
1683 __seterrno_from_win_error (err);
1684 res = -1;
1685 if (err == ERROR_NO_DATA)
1686 raise (SIGPIPE);
1687 out:
1688 ResetEvent (get_overlapped ()->hEvent);
1689 return res;
1690 }
1691
1692 void
1693 fhandler_base::read_overlapped (void *ptr, size_t& len)
1694 {
1695 #ifdef DEBUGGING
1696 assert (get_overlapped ());
1697 assert (get_overlapped ()->hEvent);
1698 #endif
1699 while (1)
1700 {
1701 bool res = ReadFile (get_handle (), ptr, len, (DWORD *) &len,
1702 get_overlapped ());
1703 int wres = wait_overlapped (res, false, (DWORD *) &len);
1704 if (wres || !_my_tls.call_signal_handler ())
1705 break;
1706 }
1707 }
1708
1709 int
1710 fhandler_base::write_overlapped (const void *ptr, size_t len)
1711 {
1712 DWORD bytes_written;
1713
1714 while (1)
1715 {
1716 bool res = WriteFile (get_output_handle (), ptr, len, &bytes_written,
1717 get_overlapped ());
1718 int wres = wait_overlapped (res, true, &bytes_written);
1719 if (wres < 0)
1720 return -1;
1721 if (wres || !_my_tls.call_signal_handler ())
1722 break;
1723 }
1724 return bytes_written;
1725 }
This page took 0.099047 seconds and 4 git commands to generate.