1 /* fhandler.cc. See console.cc for fhandler_console functions.
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4 2005, 2006, 2007 Red Hat, Inc.
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
15 #include <sys/cygwin.h>
18 #include <sys/statvfs.h>
21 #include "perprocess.h"
23 #include "cygwin/version.h"
28 #include "shared_info.h"
38 static NO_COPY
const int CHUNK_SIZE
= 1024; /* Used for crlf conversions */
40 struct __cygwin_perfile
*perfile_table
;
45 fhandler_base::operator =(fhandler_base
& x
)
47 memcpy (this, &x
, sizeof *this);
58 fhandler_base::puts_readahead (const char *s
, size_t len
)
61 while ((len
== (size_t) -1 ? *s
: len
--)
62 && (success
= put_readahead (*s
++) > 0))
68 fhandler_base::put_readahead (char value
)
71 if (raixput
< rabuflen
)
73 else if ((newrabuf
= (char *) realloc (rabuf
, rabuflen
+= 32)))
78 rabuf
[raixput
++] = value
;
84 fhandler_base::get_readahead ()
88 chret
= ((unsigned char) rabuf
[raixget
++]) & 0xff;
89 /* FIXME - not thread safe */
91 raixget
= raixput
= ralen
= 0;
96 fhandler_base::peek_readahead (int queryput
)
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;
107 fhandler_base::set_readahead_valid (int val
, int ch
)
110 ralen
= raixget
= raixput
= 0;
116 fhandler_base::eat_readahead (int n
)
123 if ((int) (ralen
-= n
) < 0)
126 if (raixget
>= ralen
)
127 raixget
= raixput
= ralen
= 0;
128 else if (raixput
> ralen
)
136 fhandler_base::get_readahead_into_buffer (char *buf
, size_t buflen
)
139 int copied_chars
= 0;
142 if ((ch
= get_readahead ()) < 0)
146 buf
[copied_chars
++] = (unsigned char)(ch
& 0xff);
153 /* Record the file name. and name hash */
155 fhandler_base::set_name (path_conv
&in_pc
)
160 char *fhandler_base::get_proc_fd_name (char *buf
)
163 return strcpy (buf
, get_name ());
165 return strcpy (buf
, dev ().name
);
166 return strcpy (buf
, "");
169 /* Detect if we are sitting at EOF for conditions where Windows
170 returns an error but UNIX doesn't. */
172 is_at_eof (HANDLE h
, DWORD err
)
175 FILE_POSITION_INFORMATION fpi
;
176 FILE_STANDARD_INFORMATION fsi
;
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
)
189 fhandler_base::set_flags (int flags
, int supplied_bin
)
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
)
200 else if (fmode
& O_TEXT
)
202 else if (supplied_bin
)
205 bin
= wbinary () || rbinary () || (binmode
!= O_TEXT
)
208 openflags
= flags
| bin
;
211 rbinary (bin
? true : false);
212 wbinary (bin
? true : false);
213 syscall_printf ("filemode set to %s", bin
? "binary" : "text");
216 /* Normal file i/o handlers. */
218 /* Cover function to ReadFile to achieve (as much as possible) Posix style
219 semantics and use of errno. */
221 fhandler_base::raw_read (void *ptr
, size_t& ulen
)
223 #define bytes_read ulen
225 int try_noreserve
= 1;
230 BOOL res
= ReadFile (get_handle (), ptr
, len
, (DWORD
*) &ulen
, NULL
);
233 /* Some errors are not really errors. Detect such cases here. */
235 DWORD errcode
= GetLastError ();
238 case ERROR_BROKEN_PIPE
:
239 /* This is really EOF. */
242 case ERROR_MORE_DATA
:
243 /* `bytes_read' is supposedly valid. */
246 if (is_at_eof (get_handle (), errcode
))
254 switch (mmap_is_attached_or_noreserve (ptr
, len
))
256 case MMAP_NORESERVE_COMMITED
:
258 case MMAP_RAISE_SIGBUS
:
265 case ERROR_INVALID_FUNCTION
:
266 case ERROR_INVALID_PARAMETER
:
267 case ERROR_INVALID_HANDLE
:
271 bytes_read
= (size_t) -1;
275 syscall_printf ("ReadFile %s(%p) failed, %E", get_name (), get_handle ());
276 __seterrno_from_win_error (errcode
);
277 bytes_read
= (size_t) -1;
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
};
290 fhandler_base::raw_write (const void *ptr
, size_t len
)
295 status
= NtWriteFile (get_output_handle (), NULL
, NULL
, NULL
, &io
,
297 (get_flags () & O_APPEND
) ? &off_append
: &off_current
,
299 if (!NT_SUCCESS (status
))
301 if (status
== STATUS_DISK_FULL
&& io
.Information
> 0)
303 __seterrno_from_nt_status (status
);
304 if (get_errno () == EPIPE
)
309 return io
.Information
;
313 fhandler_base::get_default_fmode (int flags
)
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
)
323 fmode
= pf
->flags
& ~O_ACCMODE
;
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])))
332 else if ((pf
->flags
& O_ACCMODE
) == accflags
333 && strcasematch (stem
, pf
->name
))
335 fmode
= pf
->flags
& ~O_ACCMODE
;
344 fhandler_base::device_access_denied (int flags
)
350 if (flags
& (O_WRONLY
| O_APPEND
))
355 return fhaccess (mode
);
359 fhandler_base::fhaccess (int flags
)
364 set_errno (error ());
374 if (!(flags
& (R_OK
| W_OK
| X_OK
)))
377 if (is_fs_special ())
379 else if (has_attribute (FILE_ATTRIBUTE_READONLY
) && (flags
& W_OK
)
382 else if (has_acls () && allow_ntsec
)
384 res
= check_file_access (pc
, flags
);
387 else if (get_device () == FH_REGISTRY
&& allow_ntsec
&& open (O_RDONLY
, 0)
390 res
= check_registry_access (get_handle (), flags
);
401 if (st
.st_uid
== myself
->uid
)
403 if (!(st
.st_mode
& S_IRUSR
))
406 else if (st
.st_gid
== myself
->gid
)
408 if (!(st
.st_mode
& S_IRGRP
))
411 else if (!(st
.st_mode
& S_IROTH
))
417 if (st
.st_uid
== myself
->uid
)
419 if (!(st
.st_mode
& S_IWUSR
))
422 else if (st
.st_gid
== myself
->gid
)
424 if (!(st
.st_mode
& S_IWGRP
))
427 else if (!(st
.st_mode
& S_IWOTH
))
433 if (st
.st_uid
== myself
->uid
)
435 if (!(st
.st_mode
& S_IXUSR
))
438 else if (st
.st_gid
== myself
->gid
)
440 if (!(st
.st_mode
& S_IXGRP
))
443 else if (!(st
.st_mode
& S_IXOTH
))
453 if (!res
&& (flags
& W_OK
) && get_device () == FH_FS
454 && (pc
.fs_flags () & FILE_READ_ONLY_VOLUME
))
459 debug_printf ("returning %d", res
);
463 /* Open system call handler function. */
465 fhandler_base::open (int flags
, mode_t mode
)
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
;
479 syscall_printf ("(%S, %p)", pc
.get_nt_native_path (), flags
);
481 pc
.get_object_attr (attr
, sa
);
483 switch (query_open ())
485 case query_read_control
:
486 access
= READ_CONTROL
;
487 create_options
= FILE_OPEN_FOR_BACKUP_INTENT
;
489 case query_read_attributes
:
490 access
= READ_CONTROL
| FILE_READ_ATTRIBUTES
;
491 create_options
= FILE_OPEN_FOR_BACKUP_INTENT
;
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
;
497 case query_write_attributes
:
498 access
= READ_CONTROL
| FILE_WRITE_ATTRIBUTES
;
499 create_options
= FILE_OPEN_FOR_BACKUP_INTENT
| FILE_OPEN_FOR_RECOVERY
;
502 if ((flags
& O_ACCMODE
) == O_RDONLY
)
504 access
= GENERIC_READ
;
505 create_options
= FILE_OPEN_FOR_BACKUP_INTENT
;
507 else if ((flags
& O_ACCMODE
) == O_WRONLY
)
509 access
= GENERIC_WRITE
| READ_CONTROL
| FILE_READ_ATTRIBUTES
;
510 create_options
= FILE_OPEN_FOR_BACKUP_INTENT
511 | FILE_OPEN_FOR_RECOVERY
;
515 access
= GENERIC_READ
| GENERIC_WRITE
;
516 create_options
= FILE_OPEN_FOR_BACKUP_INTENT
517 | FILE_OPEN_FOR_RECOVERY
;
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
)
525 create_options
|= FILE_SYNCHRONOUS_IO_NONALERT
;
526 access
|= SYNCHRONIZE
;
531 if ((flags
& O_TRUNC
) && ((flags
& O_ACCMODE
) != O_RDONLY
))
534 create_disposition
= FILE_OVERWRITE_IF
;
536 create_disposition
= FILE_OVERWRITE
;
538 else if (flags
& O_CREAT
)
539 create_disposition
= FILE_OPEN_IF
;
541 create_disposition
= FILE_OPEN
;
543 if ((flags
& O_EXCL
) && (flags
& O_CREAT
))
544 create_disposition
= FILE_CREATE
;
546 if (get_device () == FH_FS
)
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
;
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 ();
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 ())
581 set_security_attribute (mode
, &sa
, sd
);
582 attr
.SecurityDescriptor
= sa
.lpSecurityDescriptor
;
584 /* The file attributes are needed for later use in, e.g. fchmod. */
585 pc
.file_attributes (file_attributes
);
589 status
= NtCreateFile (&x
, access
, &attr
, &io
, NULL
, file_attributes
, shared
,
590 create_disposition
, create_options
, NULL
, 0);
591 if (!NT_SUCCESS (status
))
593 __seterrno_from_nt_status (status
);
599 set_flags (flags
, pc
.binmode ());
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
);
609 syscall_printf ("%d = fhandler_base::open (%s, %p)",
610 res
, pc
.get_nt_native_path (), flags
);
615 open buffer in binary mode? Just do the read.
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.
623 fhandler_base::read (void *in_ptr
, size_t& len
)
625 char *ptr
= (char *) in_ptr
;
626 ssize_t copied_chars
= get_readahead_into_buffer (ptr
, len
);
628 if (copied_chars
&& is_slow ())
630 len
= (size_t) copied_chars
;
637 len
= (size_t) copied_chars
;
641 raw_read (ptr
+ copied_chars
, len
);
644 else if ((ssize_t
) len
> 0)
649 if (rbinary () || len
<= 0)
652 /* Scan buffer and turn \r\n into \n */
653 char *src
, *dst
, *end
;
658 /* Read up to the last but one char - the last char needs special handling */
661 if (*src
== '\r' && src
[1] == '\n')
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 */
670 else if (*src
!= '\r')
676 raw_read (&c1
, c1len
);
683 set_readahead_valid (1, c1
);
688 len
= dst
- (char *) ptr
;
691 if (strace
.active ())
693 char buf
[16 * 6 + 1];
696 for (int i
= 0; i
< copied_chars
&& i
< 16; ++i
)
698 unsigned char c
= ((unsigned char *) ptr
)[i
];
699 __small_sprintf (p
, " %c", c
);
703 debug_printf ("read %d bytes (%s%s)", copied_chars
, buf
,
704 copied_chars
> 16 ? " ..." : "");
709 debug_printf ("returning %d, %s mode", len
, rbinary () ? "binary" : "text");
713 fhandler_base::write (const void *ptr
, size_t len
)
717 FILE_POSITION_INFORMATION fpi
;
718 FILE_STANDARD_INFORMATION fsi
;
722 did_lseek (false); /* don't do it again */
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
))
735 /* If the file system supports sparse files and the application
736 is writing after a long seek beyond EOF, convert the file to
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 ());
748 debug_printf ("binary write");
749 res
= raw_write (ptr
, len
);
753 debug_printf ("text write");
754 /* This is the Microsoft/DJGPP way. Still not ideal, but it's
756 Modified slightly by CGF 2000-10-07 */
758 int left_in_data
= len
;
759 char *data
= (char *)ptr
;
762 while (left_in_data
> 0)
764 char buf
[CHUNK_SIZE
+ 1], *buf_ptr
= buf
;
765 int left_in_buf
= CHUNK_SIZE
;
767 while (left_in_buf
> 0 && left_in_data
> 0)
778 if (left_in_data
> 0 && ch
== '\r' && *data
== '\n')
780 *buf_ptr
++ = *data
++;
786 /* We've got a buffer-full, or we're out of data. Write it out */
788 int want
= buf_ptr
- buf
;
789 if ((nbytes
= raw_write (buf
, want
)) == want
)
791 /* Keep track of how much written not counting additional \r's */
792 res
= data
- (char *)ptr
;
797 res
= -1; /* Error */
799 res
+= nbytes
; /* Partial write. Return total bytes written. */
800 break; /* All done */
808 fhandler_base::readv (const struct iovec
*const iov
, const int iovcnt
,
812 assert (iovcnt
>= 1);
818 read (iov
->iov_base
, len
);
822 if (tot
== -1) // i.e. if not pre-calculated by the caller.
825 const struct iovec
*iovptr
= iov
+ iovcnt
;
829 len
+= iovptr
->iov_len
;
831 while (iovptr
!= iov
);
837 char *buf
= (char *) malloc (len
);
846 ssize_t nbytes
= (ssize_t
) len
;
848 const struct iovec
*iovptr
= iov
;
853 const int frag
= min (nbytes
, (ssize_t
) iovptr
->iov_len
);
854 memcpy (iovptr
->iov_base
, p
, frag
);
865 fhandler_base::writev (const struct iovec
*const iov
, const int iovcnt
,
869 assert (iovcnt
>= 1);
872 return write (iov
->iov_base
, iov
->iov_len
);
874 if (tot
== -1) // i.e. if not pre-calculated by the caller.
877 const struct iovec
*iovptr
= iov
+ iovcnt
;
881 tot
+= iovptr
->iov_len
;
883 while (iovptr
!= iov
);
891 char *const buf
= (char *) malloc (tot
);
900 const struct iovec
*iovptr
= iov
;
905 const int frag
= min (nbytes
, (ssize_t
) iovptr
->iov_len
);
906 memcpy (bufptr
, iovptr
->iov_base
, frag
);
911 ssize_t ret
= write (buf
, tot
);
917 fhandler_base::lseek (_off64_t offset
, int whence
)
921 FILE_POSITION_INFORMATION fpi
;
922 FILE_STANDARD_INFORMATION fsi
;
924 /* Seeks on text files is tough, we rewind and read till we get to the
927 if (whence
!= SEEK_CUR
|| offset
!= 0)
929 if (whence
== SEEK_CUR
)
930 offset
-= ralen
- raixget
;
931 set_readahead_valid (0);
937 fpi
.CurrentByteOffset
.QuadPart
= offset
;
940 status
= NtQueryInformationFile (get_handle (), &io
, &fpi
, sizeof fpi
,
941 FilePositionInformation
);
942 if (!NT_SUCCESS (status
))
944 __seterrno_from_nt_status (status
);
947 fpi
.CurrentByteOffset
.QuadPart
+= offset
;
949 default: /* SEEK_END */
950 status
= NtQueryInformationFile (get_handle (), &io
, &fsi
, sizeof fsi
,
951 FileStandardInformation
);
952 if (!NT_SUCCESS (status
))
954 __seterrno_from_nt_status (status
);
957 fpi
.CurrentByteOffset
.QuadPart
= fsi
.EndOfFile
.QuadPart
+ offset
;
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
))
966 __seterrno_from_nt_status (status
);
969 _off64_t res
= fpi
.CurrentByteOffset
.QuadPart
;
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. */
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
;
985 fhandler_base::pread (void *, size_t, _off64_t
)
992 fhandler_base::pwrite (void *, size_t, _off64_t
)
999 fhandler_base::close ()
1003 syscall_printf ("closing '%s' handle %p", get_name (), get_handle ());
1004 if (nohandle () || CloseHandle (get_handle ()))
1008 paranoid_printf ("CloseHandle (%d <%s>) failed", get_handle (),
1013 destroy_overlapped ();
1018 fhandler_base::ioctl (unsigned int cmd
, void *buf
)
1025 set_nonblocking (*(int *) buf
);
1034 syscall_printf ("%d = ioctl (%x, %p)", res
, cmd
, buf
);
1039 fhandler_base::lock (int, struct __flock64
*)
1046 fhandler_base::fstat (struct __stat64
*buf
)
1048 debug_printf ("here");
1050 if (is_fs_special ())
1051 return fstat_fs (buf
);
1053 switch (get_device ())
1056 buf
->st_mode
= S_IFIFO
| S_IRUSR
| S_IWUSR
;
1059 buf
->st_mode
= S_IFIFO
| S_IWUSR
;
1062 buf
->st_mode
= S_IFIFO
| S_IRUSR
;
1065 buf
->st_mode
= S_IFCHR
| S_IRUSR
| S_IWUSR
| S_IWGRP
| S_IWOTH
;
1068 buf
->st_mode
= S_IFCHR
| STD_RBITS
| STD_WBITS
| S_IWGRP
| S_IWOTH
;
1072 buf
->st_uid
= geteuid32 ();
1073 buf
->st_gid
= getegid32 ();
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
;
1083 fhandler_base::fstatvfs (struct statvfs
*sfs
)
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
);
1093 fhandler_base::init (HANDLE f
, DWORD a
, mode_t bin
)
1097 a
&= GENERIC_READ
| GENERIC_WRITE
;
1099 if (a
== GENERIC_READ
)
1101 else if (a
== GENERIC_WRITE
)
1103 else if (a
== (GENERIC_READ
| GENERIC_WRITE
))
1105 set_flags (flags
| bin
);
1107 debug_printf ("created new fhandler_base for handle %p, bin %d", f
, rbinary ());
1111 fhandler_base::dup (fhandler_base
*child
)
1113 debug_printf ("in fhandler_base dup");
1118 if (!DuplicateHandle (hMainProc
, get_handle (), hMainProc
, &nh
, 0, TRUE
,
1119 DUPLICATE_SAME_ACCESS
))
1121 debug_printf ("dup(%s) failed, handle %x, %E",
1122 get_name (), get_handle ());
1128 child
->set_io_handle (nh
);
1130 if (get_overlapped ())
1131 child
->setup_overlapped ();
1132 set_flags (child
->get_flags ());
1136 int fhandler_base::fcntl (int cmd
, void *arg
)
1143 res
= close_on_exec () ? FD_CLOEXEC
: 0;
1146 set_close_on_exec (((int) arg
& FD_CLOEXEC
) ? 1 : 0);
1151 debug_printf ("GETFL: %p", res
);
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
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
);
1175 res
= lock (cmd
, (struct __flock64
*) arg
);
1185 /* Base terminal handlers. These just return errors. */
1188 fhandler_base::tcflush (int)
1195 fhandler_base::tcsendbreak (int)
1202 fhandler_base::tcdrain ()
1209 fhandler_base::tcflow (int)
1216 fhandler_base::tcsetattr (int, const struct termios
*)
1223 fhandler_base::tcgetattr (struct termios
*)
1230 fhandler_base::tcsetpgrp (const pid_t
)
1237 fhandler_base::tcgetpgrp ()
1244 fhandler_base::operator delete (void *p
)
1249 /* Normal I/O constructor */
1250 fhandler_base::fhandler_base () :
1268 /* Normal I/O destructor */
1269 fhandler_base::~fhandler_base ()
1275 /**********************************************************************/
1278 fhandler_dev_null::fhandler_dev_null () :
1284 fhandler_base::set_no_inheritance (HANDLE
&h
, bool not_inheriting
)
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
1291 setclexec (oh
, h
, not_inheriting
);
1296 fhandler_base::fork_fixup (HANDLE parent
, HANDLE
&h
, const char *name
)
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
);
1311 if (get_overlapped ())
1312 setup_overlapped ();
1317 fhandler_base::set_close_on_exec (bool val
)
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
);
1326 fhandler_base::fixup_after_fork (HANDLE parent
)
1328 debug_printf ("inheriting '%s' from parent", get_name ());
1330 fork_fixup (parent
, io_handle
, "io_handle");
1331 if (get_overlapped ())
1332 setup_overlapped ();
1336 fhandler_base::fixup_after_exec ()
1338 debug_printf ("here for '%s'", get_name ());
1339 if (get_overlapped ())
1340 setup_overlapped ();
1344 fhandler_base::is_nonblocking ()
1346 return (openflags
& O_NONBLOCK_MASK
) != 0;
1350 fhandler_base::set_nonblocking (int yes
)
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
;
1358 fhandler_base::mkdir (mode_t
)
1368 fhandler_base::rmdir ()
1372 else if (!pc
.isdir ())
1373 set_errno (ENOTDIR
);
1380 fhandler_base::opendir (int fd
)
1382 set_errno (ENOTDIR
);
1387 fhandler_base::readdir (DIR *, dirent
*)
1393 fhandler_base::telldir (DIR *)
1395 set_errno (ENOTDIR
);
1400 fhandler_base::seekdir (DIR *, _off64_t
)
1402 set_errno (ENOTDIR
);
1406 fhandler_base::rewinddir (DIR *)
1408 set_errno (ENOTDIR
);
1412 fhandler_base::closedir (DIR *)
1414 set_errno (ENOTDIR
);
1419 fhandler_base::fchmod (mode_t mode
)
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. */
1429 fhandler_base::fchown (__uid32_t uid
, __gid32_t gid
)
1431 if (pc
.is_fs_special ())
1432 return ((fhandler_disk_file
*) this)->fhandler_disk_file::fchown (uid
, gid
);
1433 /* By default, just succeeds. */
1438 fhandler_base::facl (int cmd
, int nentries
, __aclent32_t
*aclbufp
)
1444 /* By default, just succeeds. */
1450 else if (nentries
< MIN_ACL_ENTRIES
)
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
;
1470 res
= MIN_ACL_ENTRIES
;
1480 fhandler_base::fgetxattr (const char *name
, void *value
, size_t size
)
1482 set_errno (ENOTSUP
);
1487 fhandler_base::fsetxattr (const char *name
, const void *value
, size_t size
,
1490 set_errno (ENOTSUP
);
1495 fhandler_base::fadvise (_off64_t offset
, _off64_t length
, int advice
)
1502 fhandler_base::ftruncate (_off64_t length
, bool allow_truncate
)
1509 fhandler_base::link (const char *newpath
)
1516 fhandler_base::utimes (const struct timeval
*tvp
)
1518 if (is_fs_special ())
1519 return utimes_fs (tvp
);
1526 fhandler_base::fsync ()
1528 if (!get_handle () || nohandle ())
1533 if (pc
.isdir ()) /* Just succeed. */
1535 if (FlushFileBuffers (get_handle ()))
1542 fhandler_base::fpathconf (int v
)
1547 return pc
.fs_is_ntfs () || pc
.fs_is_samba () || pc
.fs_is_nfs ()
1560 /* NAME_MAX is without trailing \0 */
1561 return pc
.isdir () ? PATH_MAX
- strlen (get_name ()) - 2 : NAME_MAX
;
1563 /* PATH_MAX is with trailing \0 */
1564 return pc
.isdir () ? PATH_MAX
- strlen (get_name ()) - 1 : PATH_MAX
;
1567 || get_device () == FH_FIFO
|| get_device () == FH_PIPE
1568 || get_device () == FH_PIPER
|| get_device () == FH_PIPEW
)
1572 case _PC_CHOWN_RESTRICTED
:
1578 return _POSIX_VDISABLE
;
1586 case _PC_FILESIZEBITS
:
1587 return FILESIZEBITS
;
1588 case _PC_2_SYMLINKS
:
1590 case _PC_SYMLINK_MAX
:
1592 case _PC_POSIX_PERMISSIONS
:
1593 case _PC_POSIX_SECURITY
:
1594 if (get_device () == FH_FS
)
1595 return pc
.has_acls ();
1605 /* Overlapped I/O */
1608 fhandler_base::setup_overlapped ()
1610 OVERLAPPED
*ov
= get_overlapped ();
1611 memset (ov
, 0, sizeof (*ov
));
1612 return ov
->hEvent
= CreateEvent (&sec_none_nih
, true, false, NULL
);
1616 fhandler_base::destroy_overlapped ()
1618 OVERLAPPED
*ov
= get_overlapped ();
1619 if (ov
&& ov
->hEvent
)
1621 CloseHandle (ov
->hEvent
);
1627 fhandler_base::wait_overlapped (bool& res
, bool writing
, DWORD
*bytes
)
1630 *bytes
= (DWORD
) -1;
1631 DWORD err
= GetLastError ();
1632 if (!res
&& err
!= ERROR_IO_PENDING
)
1634 if (err
!= ERROR_HANDLE_EOF
&& err
!= ERROR_BROKEN_PIPE
)
1643 if (!get_overlapped ())
1644 system_printf ("get_overlapped is zero?");
1645 if (!get_overlapped ()->hEvent
)
1646 system_printf ("hEvent is zero?");
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
))
1657 debug_printf ("normal read");
1659 GetOverlappedResult (h
, get_overlapped (), bytes
, false))
1663 err
= GetLastError ();
1667 case WAIT_OBJECT_0
+ 1:
1668 debug_printf ("got a signal");
1674 err
= GetLastError ();
1675 debug_printf ("WFMO error, %E");
1683 __seterrno_from_win_error (err
);
1685 if (err
== ERROR_NO_DATA
)
1688 ResetEvent (get_overlapped ()->hEvent
);
1693 fhandler_base::read_overlapped (void *ptr
, size_t& len
)
1696 assert (get_overlapped ());
1697 assert (get_overlapped ()->hEvent
);
1701 bool res
= ReadFile (get_handle (), ptr
, len
, (DWORD
*) &len
,
1703 int wres
= wait_overlapped (res
, false, (DWORD
*) &len
);
1704 if (wres
|| !_my_tls
.call_signal_handler ())
1710 fhandler_base::write_overlapped (const void *ptr
, size_t len
)
1712 DWORD bytes_written
;
1716 bool res
= WriteFile (get_output_handle (), ptr
, len
, &bytes_written
,
1718 int wres
= wait_overlapped (res
, true, &bytes_written
);
1721 if (wres
|| !_my_tls
.call_signal_handler ())
1724 return bytes_written
;