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, 2008, 2009, 2010 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
18 #include "perprocess.h"
20 #include "cygwin/version.h"
32 static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */
34 struct __cygwin_perfile *perfile_table;
37 fhandler_base::operator =(fhandler_base& x)
39 memcpy (this, &x, sizeof *this);
50 fhandler_base::puts_readahead (const char *s, size_t len)
53 while ((len == (size_t) -1 ? *s : len--)
54 && (success = put_readahead (*s++) > 0))
60 fhandler_base::put_readahead (char value)
63 if (raixput < rabuflen)
65 else if ((newrabuf = (char *) realloc (rabuf, rabuflen += 32)))
70 rabuf[raixput++] = value;
76 fhandler_base::get_readahead ()
80 chret = ((unsigned char) rabuf[raixget++]) & 0xff;
81 /* FIXME - not thread safe */
83 raixget = raixput = ralen = 0;
88 fhandler_base::peek_readahead (int queryput)
91 if (!queryput && raixget < ralen)
92 chret = ((unsigned char) rabuf[raixget]) & 0xff;
93 else if (queryput && raixput > 0)
94 chret = ((unsigned char) rabuf[raixput - 1]) & 0xff;
99 fhandler_base::set_readahead_valid (int val, int ch)
102 ralen = raixget = raixput = 0;
108 fhandler_base::eat_readahead (int n)
115 if ((int) (ralen -= n) < 0)
118 if (raixget >= ralen)
119 raixget = raixput = ralen = 0;
120 else if (raixput > ralen)
128 fhandler_base::get_readahead_into_buffer (char *buf, size_t buflen)
131 int copied_chars = 0;
134 if ((ch = get_readahead ()) < 0)
138 buf[copied_chars++] = (unsigned char)(ch & 0xff);
145 /* Record the file name. and name hash */
147 fhandler_base::set_name (path_conv &in_pc)
152 char *fhandler_base::get_proc_fd_name (char *buf)
155 return strcpy (buf, get_name ());
157 return strcpy (buf, dev ().name);
158 return strcpy (buf, "");
161 /* Detect if we are sitting at EOF for conditions where Windows
162 returns an error but UNIX doesn't. */
164 is_at_eof (HANDLE h, DWORD err)
167 FILE_POSITION_INFORMATION fpi;
168 FILE_STANDARD_INFORMATION fsi;
170 if (NT_SUCCESS (NtQueryInformationFile (h, &io, &fsi, sizeof fsi,
171 FileStandardInformation))
172 && NT_SUCCESS (NtQueryInformationFile (h, &io, &fpi, sizeof fpi,
173 FilePositionInformation))
174 && fsi.EndOfFile.QuadPart == fpi.CurrentByteOffset.QuadPart)
181 fhandler_base::set_flags (int flags, int supplied_bin)
185 debug_printf ("flags %p, supplied_bin %p", flags, supplied_bin);
186 if ((bin = flags & (O_BINARY | O_TEXT)))
187 debug_printf ("O_TEXT/O_BINARY set in flags %p", bin);
188 else if (rbinset () && wbinset ())
189 bin = rbinary () ? O_BINARY : O_TEXT; // FIXME: Not quite right
190 else if ((fmode = get_default_fmode (flags)) & O_BINARY)
192 else if (fmode & O_TEXT)
194 else if (supplied_bin)
197 bin = wbinary () || rbinary () ? O_BINARY : O_TEXT;
199 openflags = flags | bin;
202 rbinary (bin ? true : false);
203 wbinary (bin ? true : false);
204 syscall_printf ("filemode set to %s", bin ? "binary" : "text");
207 /* Normal file i/o handlers. */
209 /* Cover function to ReadFile to achieve (as much as possible) Posix style
210 semantics and use of errno. */
212 fhandler_base::raw_read (void *ptr, size_t& ulen)
214 #define bytes_read ulen
216 int try_noreserve = 1;
221 BOOL res = ReadFile (get_handle (), ptr, len, (DWORD *) &ulen, NULL);
224 /* Some errors are not really errors. Detect such cases here. */
226 DWORD errcode = GetLastError ();
229 case ERROR_BROKEN_PIPE:
230 /* This is really EOF. */
233 case ERROR_MORE_DATA:
234 /* `bytes_read' is supposedly valid. */
237 if (is_at_eof (get_handle (), errcode))
245 switch (mmap_is_attached_or_noreserve (ptr, len))
247 case MMAP_NORESERVE_COMMITED:
249 case MMAP_RAISE_SIGBUS:
256 case ERROR_INVALID_FUNCTION:
257 case ERROR_INVALID_PARAMETER:
258 case ERROR_INVALID_HANDLE:
262 bytes_read = (size_t) -1;
266 syscall_printf ("ReadFile %s(%p) failed, %E", get_name (), get_handle ());
267 __seterrno_from_win_error (errcode);
268 bytes_read = (size_t) -1;
275 /* Cover function to WriteFile to provide Posix interface and semantics
276 (as much as possible). */
277 static LARGE_INTEGER off_current = { QuadPart:FILE_USE_FILE_POINTER_POSITION };
278 static LARGE_INTEGER off_append = { QuadPart:FILE_WRITE_TO_END_OF_FILE };
281 fhandler_base::raw_write (const void *ptr, size_t len)
286 status = NtWriteFile (get_output_handle (), NULL, NULL, NULL, &io,
288 (get_flags () & O_APPEND) ? &off_append : &off_current,
290 if (!NT_SUCCESS (status))
292 __seterrno_from_nt_status (status);
293 if (get_errno () == EPIPE)
297 return io.Information;
301 fhandler_base::get_default_fmode (int flags)
306 size_t nlen = strlen (get_name ());
307 unsigned accflags = (flags & O_ACCMODE);
308 for (__cygwin_perfile *pf = perfile_table; pf->name; pf++)
309 if (!*pf->name && (pf->flags & O_ACCMODE) == accflags)
311 fmode = pf->flags & ~O_ACCMODE;
316 size_t pflen = strlen (pf->name);
317 const char *stem = get_name () + nlen - pflen;
318 if (pflen > nlen || (stem != get_name () && !isdirsep (stem[-1])))
320 else if ((pf->flags & O_ACCMODE) == accflags
321 && pathmatch (stem, pf->name, !!pc.objcaseinsensitive ()))
323 fmode = pf->flags & ~O_ACCMODE;
332 fhandler_base::device_access_denied (int flags)
338 if (flags & (O_WRONLY | O_APPEND))
343 return fhaccess (mode, true);
347 fhandler_base::fhaccess (int flags, bool effective)
352 set_errno (error ());
362 if (!(flags & (R_OK | W_OK | X_OK)))
365 if (is_fs_special ())
367 else if (has_attribute (FILE_ATTRIBUTE_READONLY) && (flags & W_OK)
370 else if (has_acls ())
372 res = check_file_access (pc, flags, effective);
375 else if (get_device () == FH_REGISTRY && open (O_RDONLY, 0) && get_handle ())
377 res = check_registry_access (get_handle (), flags, effective);
388 if (st.st_uid == (effective ? myself->uid : cygheap->user.real_uid))
390 if (!(st.st_mode & S_IRUSR))
393 else if (st.st_gid == (effective ? myself->gid : cygheap->user.real_gid))
395 if (!(st.st_mode & S_IRGRP))
398 else if (!(st.st_mode & S_IROTH))
404 if (st.st_uid == (effective ? myself->uid : cygheap->user.real_uid))
406 if (!(st.st_mode & S_IWUSR))
409 else if (st.st_gid == (effective ? myself->gid : cygheap->user.real_gid))
411 if (!(st.st_mode & S_IWGRP))
414 else if (!(st.st_mode & S_IWOTH))
420 if (st.st_uid == (effective ? myself->uid : cygheap->user.real_uid))
422 if (!(st.st_mode & S_IXUSR))
425 else if (st.st_gid == (effective ? myself->gid : cygheap->user.real_gid))
427 if (!(st.st_mode & S_IXGRP))
430 else if (!(st.st_mode & S_IXOTH))
440 if (!res && (flags & W_OK) && get_device () == FH_FS
441 && (pc.fs_flags () & FILE_READ_ONLY_VOLUME))
446 debug_printf ("returning %d", res);
450 /* Open system call handler function. */
452 fhandler_base::open (int flags, mode_t mode)
456 ULONG file_attributes = 0;
457 ULONG shared = (get_major () == DEV_TAPE_MAJOR ? 0 : FILE_SHARE_VALID_FLAGS);
458 ULONG create_disposition;
459 ULONG create_options = FILE_OPEN_FOR_BACKUP_INTENT;
460 OBJECT_ATTRIBUTES attr;
463 PFILE_FULL_EA_INFORMATION p = NULL;
466 syscall_printf ("(%S, %p)", pc.get_nt_native_path (), flags);
468 pc.get_object_attr (attr, *sec_none_cloexec (flags));
470 switch (query_open ())
472 case query_read_control:
473 access = READ_CONTROL;
475 case query_read_attributes:
476 access = READ_CONTROL | FILE_READ_ATTRIBUTES;
478 case query_write_control:
479 access = READ_CONTROL | WRITE_OWNER | WRITE_DAC | FILE_WRITE_ATTRIBUTES;
481 case query_write_dac:
482 access = READ_CONTROL | WRITE_DAC | FILE_WRITE_ATTRIBUTES;
484 case query_write_attributes:
485 access = READ_CONTROL | FILE_WRITE_ATTRIBUTES;
488 if ((flags & O_ACCMODE) == O_RDONLY)
489 access = GENERIC_READ;
490 else if ((flags & O_ACCMODE) == O_WRONLY)
491 access = GENERIC_WRITE | READ_CONTROL | FILE_READ_ATTRIBUTES;
493 access = GENERIC_READ | GENERIC_WRITE;
495 create_options |= FILE_WRITE_THROUGH;
496 if (flags & O_DIRECT)
497 create_options |= FILE_NO_INTERMEDIATE_BUFFERING;
498 if (get_major () != DEV_SERIAL_MAJOR && get_major () != DEV_TAPE_MAJOR)
500 create_options |= FILE_SYNCHRONOUS_IO_NONALERT;
501 access |= SYNCHRONIZE;
508 /* Make sure we can read EAs of files on an NFS share. Also make
509 sure that we're going to act on the file itself, even if it's a
511 access |= FILE_READ_EA;
514 if (query_open () >= query_write_control)
515 access |= FILE_WRITE_EA;
516 plen = sizeof nfs_aol_ffei;
517 p = (PFILE_FULL_EA_INFORMATION) &nfs_aol_ffei;
521 if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY))
524 create_disposition = FILE_OVERWRITE_IF;
526 create_disposition = FILE_OVERWRITE;
528 else if (flags & O_CREAT)
529 create_disposition = FILE_OPEN_IF;
531 create_disposition = FILE_OPEN;
533 if ((flags & O_EXCL) && (flags & O_CREAT))
534 create_disposition = FILE_CREATE;
536 if (get_device () == FH_FS)
538 /* Add the reparse point flag to native symlinks, otherwise we open the
539 target, not the symlink. This would break lstat. */
540 if (pc.is_rep_symlink ())
541 create_options |= FILE_OPEN_REPARSE_POINT;
543 /* Starting with Windows 2000, when trying to overwrite an already
544 existing file with FILE_ATTRIBUTE_HIDDEN and/or FILE_ATTRIBUTE_SYSTEM
545 attribute set, CreateFile fails with ERROR_ACCESS_DENIED.
546 Per MSDN you have to create the file with the same attributes as
547 already specified for the file. */
548 if (((flags & O_CREAT) || create_disposition == FILE_OVERWRITE)
549 && has_attribute (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM))
550 file_attributes |= pc.file_attributes ();
554 file_attributes |= FILE_ATTRIBUTE_NORMAL;
558 /* When creating a file on an NFS share, we have to set the
559 file mode by writing a NFS fattr3 structure with the
560 correct mode bits set. */
561 access |= FILE_WRITE_EA;
562 plen = sizeof (FILE_FULL_EA_INFORMATION) + sizeof (NFS_V3_ATTR)
564 p = (PFILE_FULL_EA_INFORMATION) alloca (plen);
565 p->NextEntryOffset = 0;
567 p->EaNameLength = sizeof (NFS_V3_ATTR) - 1;
568 p->EaValueLength = sizeof (fattr3);
569 strcpy (p->EaName, NFS_V3_ATTR);
570 fattr3 *nfs_attr = (fattr3 *) (p->EaName
571 + p->EaNameLength + 1);
572 memset (nfs_attr, 0, sizeof (fattr3));
573 nfs_attr->type = NF3REG;
574 nfs_attr->mode = mode;
576 else if (!has_acls () && !(mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
577 /* If mode has no write bits set, and ACLs are not used, we set
578 the DOS R/O attribute. */
579 file_attributes |= FILE_ATTRIBUTE_READONLY;
580 /* The file attributes are needed for later use in, e.g. fchmod. */
581 pc.file_attributes (file_attributes);
585 status = NtCreateFile (&fh, access, &attr, &io, NULL, file_attributes, shared,
586 create_disposition, create_options, p, plen);
587 if (!NT_SUCCESS (status))
589 /* Trying to create a directory should return EISDIR, not ENOENT. */
590 PUNICODE_STRING upath = pc.get_nt_native_path ();
591 if (status == STATUS_OBJECT_NAME_INVALID && (flags & O_CREAT)
592 && upath->Buffer[upath->Length / sizeof (WCHAR) - 1] == '\\')
595 __seterrno_from_nt_status (status);
600 /* Always create files using a NULL SD. Create correct permission bits
601 afterwards, maintaining the owner and group information just like chmod.
603 This is done for two reasons.
605 On Windows filesystems we need to create the file with default
606 permissions to allow inheriting ACEs. When providing an explicit DACL
607 in calls to [Nt]CreateFile, the created file will not inherit default
608 permissions from the parent object. This breaks not only Windows
609 inheritance, but also POSIX ACL inheritance.
611 Another reason to do this are remote shares. Files on a remote share
612 are created as the user used for authentication. In a domain that's
613 usually the user you're logged in as. Outside of a domain you're
614 authenticating using a local user account on the sharing machine.
615 If the SIDs of the client machine are used, that's entirely
616 unexpected behaviour. Doing it like we do here creates the expected SD
617 in a domain as well as on standalone servers.
618 This is the result of a discussion on the samba-technical list, starting at
619 http://lists.samba.org/archive/samba-technical/2008-July/060247.html */
620 if (io.Information == FILE_CREATED && has_acls ())
621 set_file_attribute (fh, pc, ILLEGAL_UID, ILLEGAL_GID, S_JUSTCREATED | mode);
624 set_flags (flags, pc.binmode ());
629 debug_printf ("%x = NtCreateFile "
630 "(%p, %x, %S, io, NULL, %x, %x, %x, %x, NULL, 0)",
631 status, fh, access, pc.get_nt_native_path (), file_attributes,
632 shared, create_disposition, create_options);
634 syscall_printf ("%d = fhandler_base::open (%S, %p)",
635 res, pc.get_nt_native_path (), flags);
640 open buffer in binary mode? Just do the read.
642 open buffer in text mode? Scan buffer for control zs and handle
643 the first one found. Then scan buffer, converting every \r\n into
644 an \n. If last char is an \r, look ahead one more char, if \n then
645 modify \r, if not, remember char.
648 fhandler_base::read (void *in_ptr, size_t& len)
650 char *ptr = (char *) in_ptr;
651 ssize_t copied_chars = get_readahead_into_buffer (ptr, len);
653 if (copied_chars && is_slow ())
655 len = (size_t) copied_chars;
662 len = (size_t) copied_chars;
666 raw_read (ptr + copied_chars, len);
669 else if ((ssize_t) len > 0)
674 if (rbinary () || (ssize_t) len <= 0)
677 /* Scan buffer and turn \r\n into \n */
678 char *src, *dst, *end;
683 /* Read up to the last but one char - the last char needs special handling */
686 if (*src == '\r' && src[1] == '\n')
691 /* If not beyond end and last char is a '\r' then read one more
692 to see if we should translate this one too */
695 else if (*src != '\r')
701 raw_read (&c1, c1len);
708 set_readahead_valid (1, c1);
713 len = dst - (char *) ptr;
716 if (strace.active ())
718 char buf[16 * 6 + 1];
721 for (int i = 0; i < copied_chars && i < 16; ++i)
723 unsigned char c = ((unsigned char *) ptr)[i];
724 __small_sprintf (p, " %c", c);
728 debug_printf ("read %d bytes (%s%s)", copied_chars, buf,
729 copied_chars > 16 ? " ..." : "");
734 debug_printf ("returning %d, %s mode", len, rbinary () ? "binary" : "text");
738 fhandler_base::write (const void *ptr, size_t len)
742 FILE_POSITION_INFORMATION fpi;
743 FILE_STANDARD_INFORMATION fsi;
747 did_lseek (false); /* don't do it again */
749 if (!(get_flags () & O_APPEND)
750 && NT_SUCCESS (NtQueryInformationFile (get_output_handle (),
751 &io, &fsi, sizeof fsi,
752 FileStandardInformation))
753 && NT_SUCCESS (NtQueryInformationFile (get_output_handle (),
754 &io, &fpi, sizeof fpi,
755 FilePositionInformation))
756 && fpi.CurrentByteOffset.QuadPart
757 >= fsi.EndOfFile.QuadPart + (128 * 1024)
758 && (pc.fs_flags () & FILE_SUPPORTS_SPARSE_FILES))
760 /* If the file system supports sparse files and the application
761 is writing after a long seek beyond EOF, convert the file to
764 status = NtFsControlFile (get_output_handle (), NULL, NULL, NULL,
765 &io, FSCTL_SET_SPARSE, NULL, 0, NULL, 0);
766 syscall_printf ("%p = NtFsControlFile(%S, FSCTL_SET_SPARSE)",
767 status, pc.get_nt_native_path ());
773 debug_printf ("binary write");
774 res = raw_write (ptr, len);
778 debug_printf ("text write");
779 /* This is the Microsoft/DJGPP way. Still not ideal, but it's
781 Modified slightly by CGF 2000-10-07 */
783 int left_in_data = len;
784 char *data = (char *)ptr;
787 while (left_in_data > 0)
789 char buf[CHUNK_SIZE + 1], *buf_ptr = buf;
790 int left_in_buf = CHUNK_SIZE;
792 while (left_in_buf > 0 && left_in_data > 0)
803 if (left_in_data > 0 && ch == '\r' && *data == '\n')
805 *buf_ptr++ = *data++;
811 /* We've got a buffer-full, or we're out of data. Write it out */
813 int want = buf_ptr - buf;
814 if ((nbytes = raw_write (buf, want)) == want)
816 /* Keep track of how much written not counting additional \r's */
817 res = data - (char *)ptr;
822 res = -1; /* Error */
824 res += nbytes; /* Partial write. Return total bytes written. */
825 break; /* All done */
833 fhandler_base::readv (const struct iovec *const iov, const int iovcnt,
837 assert (iovcnt >= 1);
843 read (iov->iov_base, len);
847 if (tot == -1) // i.e. if not pre-calculated by the caller.
850 const struct iovec *iovptr = iov + iovcnt;
854 len += iovptr->iov_len;
856 while (iovptr != iov);
862 char *buf = (char *) malloc (len);
871 ssize_t nbytes = (ssize_t) len;
873 const struct iovec *iovptr = iov;
878 const int frag = min (nbytes, (ssize_t) iovptr->iov_len);
879 memcpy (iovptr->iov_base, p, frag);
890 fhandler_base::writev (const struct iovec *const iov, const int iovcnt,
894 assert (iovcnt >= 1);
897 return write (iov->iov_base, iov->iov_len);
899 if (tot == -1) // i.e. if not pre-calculated by the caller.
902 const struct iovec *iovptr = iov + iovcnt;
906 tot += iovptr->iov_len;
908 while (iovptr != iov);
916 char *const buf = (char *) malloc (tot);
925 const struct iovec *iovptr = iov;
930 const int frag = min (nbytes, (ssize_t) iovptr->iov_len);
931 memcpy (bufptr, iovptr->iov_base, frag);
936 ssize_t ret = write (buf, tot);
942 fhandler_base::lseek (_off64_t offset, int whence)
946 FILE_POSITION_INFORMATION fpi;
947 FILE_STANDARD_INFORMATION fsi;
949 /* Seeks on text files is tough, we rewind and read till we get to the
952 if (whence != SEEK_CUR || offset != 0)
954 if (whence == SEEK_CUR)
955 offset -= ralen - raixget;
956 set_readahead_valid (0);
962 fpi.CurrentByteOffset.QuadPart = offset;
965 status = NtQueryInformationFile (get_handle (), &io, &fpi, sizeof fpi,
966 FilePositionInformation);
967 if (!NT_SUCCESS (status))
969 __seterrno_from_nt_status (status);
972 fpi.CurrentByteOffset.QuadPart += offset;
974 default: /* SEEK_END */
975 status = NtQueryInformationFile (get_handle (), &io, &fsi, sizeof fsi,
976 FileStandardInformation);
977 if (!NT_SUCCESS (status))
979 __seterrno_from_nt_status (status);
982 fpi.CurrentByteOffset.QuadPart = fsi.EndOfFile.QuadPart + offset;
986 debug_printf ("setting file pointer to %U", fpi.CurrentByteOffset.QuadPart);
987 status = NtSetInformationFile (get_handle (), &io, &fpi, sizeof fpi,
988 FilePositionInformation);
989 if (!NT_SUCCESS (status))
991 __seterrno_from_nt_status (status);
994 _off64_t res = fpi.CurrentByteOffset.QuadPart;
996 /* When next we write(), we will check to see if *this* seek went beyond
997 the end of the file and if so, potentially sparsify the file. */
1000 /* If this was a SEEK_CUR with offset 0, we still might have
1001 readahead that we have to take into account when calculating
1002 the actual position for the application. */
1003 if (whence == SEEK_CUR)
1004 res -= ralen - raixget;
1010 fhandler_base::pread (void *, size_t, _off64_t)
1017 fhandler_base::pwrite (void *, size_t, _off64_t)
1024 fhandler_base::close ()
1028 syscall_printf ("closing '%s' handle %p", get_name (), get_handle ());
1029 /* Delete all POSIX locks on the file. Delete all flock locks on the
1030 file if this is the last reference to this file. */
1032 del_my_locks (on_close);
1033 if (nohandle () || CloseHandle (get_handle ()))
1037 paranoid_printf ("CloseHandle (%d <%s>) failed", get_handle (),
1047 fhandler_base_overlapped::close ()
1049 destroy_overlapped ();
1050 return fhandler_base::close ();
1054 fhandler_base::ioctl (unsigned int cmd, void *buf)
1061 set_nonblocking (*(int *) buf);
1070 syscall_printf ("%d = ioctl (%x, %p)", res, cmd, buf);
1075 fhandler_base::lock (int, struct __flock64 *)
1082 fhandler_base::fstat (struct __stat64 *buf)
1084 debug_printf ("here");
1086 if (is_fs_special ())
1087 return fstat_fs (buf);
1089 switch (get_device ())
1092 buf->st_mode = S_IFIFO | S_IRUSR | S_IWUSR;
1095 buf->st_mode = S_IFIFO | S_IWUSR;
1098 buf->st_mode = S_IFIFO | S_IRUSR;
1101 buf->st_mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
1104 buf->st_mode = S_IFCHR | STD_RBITS | STD_WBITS | S_IWGRP | S_IWOTH;
1108 buf->st_uid = geteuid32 ();
1109 buf->st_gid = getegid32 ();
1111 buf->st_blksize = PREFERRED_IO_BLKSIZE;
1113 buf->st_ctim.tv_sec = 1164931200L; /* Arbitrary value: 2006-12-01 */
1114 buf->st_ctim.tv_nsec = 0L;
1115 buf->st_birthtim = buf->st_ctim;
1116 buf->st_mtim.tv_sec = time (NULL); /* Arbitrary value: current time,
1118 buf->st_mtim.tv_nsec = 0L;
1119 buf->st_atim = buf->st_mtim;
1125 fhandler_base::fstatvfs (struct statvfs *sfs)
1127 /* If we hit this base implementation, it's some device in /dev.
1128 Just call statvfs on /dev for simplicity. */
1129 path_conv pc ("/dev", PC_KEEP_HANDLE);
1130 fhandler_disk_file fh (pc);
1131 return fh.fstatvfs (sfs);
1135 fhandler_base::init (HANDLE f, DWORD a, mode_t bin)
1139 a &= GENERIC_READ | GENERIC_WRITE;
1141 if (a == GENERIC_READ)
1143 else if (a == GENERIC_WRITE)
1145 else if (a == (GENERIC_READ | GENERIC_WRITE))
1147 set_flags (flags | bin);
1149 debug_printf ("created new fhandler_base for handle %p, bin %d", f, rbinary ());
1154 fhandler_base::dup (fhandler_base *child)
1156 debug_printf ("in fhandler_base dup");
1161 if (!DuplicateHandle (GetCurrentProcess (), get_handle (),
1162 GetCurrentProcess (), &nh,
1163 0, TRUE, DUPLICATE_SAME_ACCESS))
1165 debug_printf ("dup(%s) failed, handle %x, %E",
1166 get_name (), get_handle ());
1172 child->set_io_handle (nh);
1178 fhandler_base_overlapped::dup (fhandler_base *child)
1180 int res = fhandler_base::dup (child) ||
1181 ((fhandler_base_overlapped *) child)->setup_overlapped ();
1185 int fhandler_base::fcntl (int cmd, void *arg)
1192 res = close_on_exec () ? FD_CLOEXEC : 0;
1195 set_close_on_exec (((int) arg & FD_CLOEXEC) ? 1 : 0);
1200 debug_printf ("GETFL: %p", res);
1204 /* Only O_APPEND, O_ASYNC and O_NONBLOCK/O_NDELAY are allowed.
1205 Each other flag will be ignored.
1206 Since O_ASYNC isn't defined in fcntl.h it's currently
1208 const int allowed_flags = O_APPEND | O_NONBLOCK_MASK;
1209 int new_flags = (int) arg & allowed_flags;
1210 /* Carefully test for the O_NONBLOCK or deprecated OLD_O_NDELAY flag.
1211 Set only the flag that has been passed in. If both are set, just
1212 record O_NONBLOCK. */
1213 if ((new_flags & OLD_O_NDELAY) && (new_flags & O_NONBLOCK))
1214 new_flags &= ~OLD_O_NDELAY;
1215 set_flags ((get_flags () & ~allowed_flags) | new_flags);
1227 /* Base terminal handlers. These just return errors. */
1230 fhandler_base::tcflush (int)
1237 fhandler_base::tcsendbreak (int)
1244 fhandler_base::tcdrain ()
1251 fhandler_base::tcflow (int)
1258 fhandler_base::tcsetattr (int, const struct termios *)
1265 fhandler_base::tcgetattr (struct termios *)
1272 fhandler_base::tcsetpgrp (const pid_t)
1279 fhandler_base::tcgetpgrp ()
1286 fhandler_base::operator delete (void *p)
1291 /* Normal I/O constructor */
1292 fhandler_base::fhandler_base () :
1310 /* Normal I/O destructor */
1311 fhandler_base::~fhandler_base ()
1317 /**********************************************************************/
1320 fhandler_dev_null::fhandler_dev_null () :
1326 fhandler_base::set_no_inheritance (HANDLE &h, bool not_inheriting)
1328 if (!SetHandleInformation (h, HANDLE_FLAG_INHERIT,
1329 not_inheriting ? 0 : HANDLE_FLAG_INHERIT))
1330 debug_printf ("SetHandleInformation failed, %E");
1331 #ifdef DEBUGGING_AND_FDS_PROTECTED
1333 setclexec (oh, h, not_inheriting);
1338 fhandler_base::fork_fixup (HANDLE parent, HANDLE &h, const char *name)
1342 if (/* !is_socket () && */ !close_on_exec ())
1343 debug_printf ("handle %p already opened", h);
1344 else if (!DuplicateHandle (parent, h, GetCurrentProcess (), &h,
1345 0, !close_on_exec (), DUPLICATE_SAME_ACCESS))
1346 system_printf ("%s - %E, handle %s<%p>", get_name (), name, h);
1357 fhandler_base::set_close_on_exec (bool val)
1360 set_no_inheritance (io_handle, val);
1361 close_on_exec (val);
1362 debug_printf ("set close_on_exec for %s to %d", get_name (), val);
1366 fhandler_base::fixup_after_fork (HANDLE parent)
1368 debug_printf ("inheriting '%s' from parent", get_name ());
1370 fork_fixup (parent, io_handle, "io_handle");
1371 /* POSIX locks are not inherited across fork. */
1373 del_my_locks (after_fork);
1377 fhandler_base_overlapped::fixup_after_fork (HANDLE parent)
1379 setup_overlapped ();
1380 fhandler_base::fixup_after_fork (parent);
1384 fhandler_base::fixup_after_exec ()
1386 debug_printf ("here for '%s'", get_name ());
1387 if (unique_id && close_on_exec ())
1388 del_my_locks (after_exec);
1391 fhandler_base_overlapped::fixup_after_exec ()
1393 setup_overlapped ();
1394 fhandler_base::fixup_after_exec ();
1398 fhandler_base::is_nonblocking ()
1400 return (openflags & O_NONBLOCK_MASK) != 0;
1404 fhandler_base::set_nonblocking (int yes)
1406 int current = openflags & O_NONBLOCK_MASK;
1407 int new_flags = yes ? (!current ? O_NONBLOCK : current) : 0;
1408 openflags = (openflags & ~O_NONBLOCK_MASK) | new_flags;
1412 fhandler_base::mkdir (mode_t)
1422 fhandler_base::rmdir ()
1426 else if (!pc.isdir ())
1427 set_errno (ENOTDIR);
1434 fhandler_base::opendir (int fd)
1436 set_errno (ENOTDIR);
1441 fhandler_base::readdir (DIR *, dirent *)
1447 fhandler_base::telldir (DIR *)
1449 set_errno (ENOTDIR);
1454 fhandler_base::seekdir (DIR *, long)
1456 set_errno (ENOTDIR);
1460 fhandler_base::rewinddir (DIR *)
1462 set_errno (ENOTDIR);
1466 fhandler_base::closedir (DIR *)
1468 set_errno (ENOTDIR);
1473 fhandler_base::fchmod (mode_t mode)
1475 extern int chmod_device (path_conv& pc, mode_t mode);
1476 if (pc.is_fs_special ())
1477 return chmod_device (pc, mode);
1478 /* By default, just succeeds. */
1483 fhandler_base::fchown (__uid32_t uid, __gid32_t gid)
1485 if (pc.is_fs_special ())
1486 return ((fhandler_disk_file *) this)->fhandler_disk_file::fchown (uid, gid);
1487 /* By default, just succeeds. */
1492 fhandler_base::facl (int cmd, int nentries, __aclent32_t *aclbufp)
1498 /* By default, just succeeds. */
1504 else if (nentries < MIN_ACL_ENTRIES)
1508 aclbufp[0].a_type = USER_OBJ;
1509 aclbufp[0].a_id = myself->uid;
1510 aclbufp[0].a_perm = (S_IRUSR | S_IWUSR) >> 6;
1511 aclbufp[1].a_type = GROUP_OBJ;
1512 aclbufp[1].a_id = myself->gid;
1513 aclbufp[1].a_perm = (S_IRGRP | S_IWGRP) >> 3;
1514 aclbufp[2].a_type = OTHER_OBJ;
1515 aclbufp[2].a_id = ILLEGAL_GID;
1516 aclbufp[2].a_perm = S_IROTH | S_IWOTH;
1517 aclbufp[3].a_type = CLASS_OBJ;
1518 aclbufp[3].a_id = ILLEGAL_GID;
1519 aclbufp[3].a_perm = S_IRWXU | S_IRWXG | S_IRWXO;
1520 res = MIN_ACL_ENTRIES;
1524 res = MIN_ACL_ENTRIES;
1534 fhandler_base::fgetxattr (const char *name, void *value, size_t size)
1536 set_errno (ENOTSUP);
1541 fhandler_base::fsetxattr (const char *name, const void *value, size_t size,
1544 set_errno (ENOTSUP);
1549 fhandler_base::fadvise (_off64_t offset, _off64_t length, int advice)
1556 fhandler_base::ftruncate (_off64_t length, bool allow_truncate)
1563 fhandler_base::link (const char *newpath)
1570 fhandler_base::utimens (const struct timespec *tvp)
1572 if (is_fs_special ())
1573 return utimens_fs (tvp);
1580 fhandler_base::fsync ()
1582 if (!get_handle () || nohandle ())
1587 if (pc.isdir ()) /* Just succeed. */
1589 if (FlushFileBuffers (get_handle ()))
1592 /* Ignore ERROR_INVALID_FUNCTION because FlushFileBuffers() always fails
1593 with this code on raw devices which are unbuffered by default. */
1594 DWORD errcode = GetLastError();
1595 if (errcode == ERROR_INVALID_FUNCTION)
1598 __seterrno_from_win_error (errcode);
1603 fhandler_base::fpathconf (int v)
1610 return pc.fs_is_ntfs () || pc.fs_is_samba () || pc.fs_is_nfs ()
1623 /* NAME_MAX is without trailing \0 */
1626 ret = NT_MAX_PATH - strlen (get_name ()) - 2;
1627 return ret < 0 ? 0 : ret > NAME_MAX ? NAME_MAX : ret;
1629 /* PATH_MAX is with trailing \0 */
1632 ret = NT_MAX_PATH - strlen (get_name ()) - 1;
1633 return ret < 0 ? 0 : ret > PATH_MAX ? PATH_MAX : ret;
1636 || get_device () == FH_FIFO || get_device () == FH_PIPE
1637 || get_device () == FH_PIPER || get_device () == FH_PIPEW)
1641 case _PC_CHOWN_RESTRICTED:
1647 return _POSIX_VDISABLE;
1655 case _PC_FILESIZEBITS:
1656 return FILESIZEBITS;
1657 case _PC_2_SYMLINKS:
1659 case _PC_SYMLINK_MAX:
1661 case _PC_POSIX_PERMISSIONS:
1662 case _PC_POSIX_SECURITY:
1663 if (get_device () == FH_FS)
1664 return pc.has_acls () || pc.fs_is_nfs ();
1674 /* Overlapped I/O */
1677 fhandler_base_overlapped::setup_overlapped ()
1679 OVERLAPPED *ov = get_overlapped_buffer ();
1680 memset (ov, 0, sizeof (*ov));
1681 set_overlapped (ov);
1682 ov->hEvent = CreateEvent (&sec_none_nih, true, true, NULL);
1683 return ov->hEvent ? 0 : -1;
1687 fhandler_base_overlapped::destroy_overlapped ()
1689 OVERLAPPED *ov = get_overlapped ();
1690 if (ov && ov->hEvent)
1692 CloseHandle (ov->hEvent);
1696 get_overlapped () = NULL;
1700 fhandler_base_overlapped::has_ongoing_io ()
1704 if (WaitForSingleObject (get_overlapped ()->hEvent, 0) != WAIT_OBJECT_0)
1714 fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *bytes, DWORD len)
1716 if (!get_overlapped ())
1721 DWORD err = GetLastError ();
1722 if (is_nonblocking ())
1724 if (inres || err == ERROR_IO_PENDING)
1726 io_pending = err == ERROR_IO_PENDING;
1727 if (writing && !inres)
1728 *bytes = len; /* This really isn't true but it seems like
1729 this is a corner-case for linux's
1730 non-blocking I/O implementation. How can
1731 you know how many bytes were written until
1732 the I/O operation really completes? */
1737 else if (inres || err == ERROR_IO_PENDING)
1740 if (!get_overlapped ()->hEvent)
1741 system_printf ("hEvent is zero?");
1745 w4[0] = get_overlapped ()->hEvent;
1746 if (&_my_tls == _main_tls)
1747 w4[n++] = signal_arrived;
1748 HANDLE h = writing ? get_output_handle () : get_handle ();
1749 DWORD wfres = WaitForMultipleObjects (n, w4, false, INFINITE);
1750 if (wfres != WAIT_OBJECT_0)
1752 BOOL wores = GetOverlappedResult (h, get_overlapped (), bytes, false);
1753 bool signalled = !wores && (wfres == WAIT_OBJECT_0 + 1);
1756 debug_printf ("got a signal");
1758 *bytes = (DWORD) -1;
1764 err = GetLastError ();
1765 debug_printf ("GetOverLappedResult failed");
1769 debug_printf ("normal %s, %u bytes", writing ? "write" : "read", *bytes);
1776 /* nothing to do */;
1777 else if (err != ERROR_HANDLE_EOF && err != ERROR_BROKEN_PIPE)
1779 debug_printf ("err %u", err);
1780 __seterrno_from_win_error (err);
1781 *bytes = (DWORD) -1;
1789 debug_printf ("EOF");
1792 if (writing && (err == ERROR_NO_DATA || err == ERROR_BROKEN_PIPE))
1798 fhandler_base_overlapped::read_overlapped (void *ptr, size_t& len)
1801 if (has_ongoing_io ())
1802 nbytes = (DWORD) -1;
1806 bool res = ReadFile (get_handle (), ptr, len, &nbytes,
1808 int wres = wait_overlapped (res, false, &nbytes);
1809 if (wres || !_my_tls.call_signal_handler ())
1812 len = (size_t) nbytes;
1816 fhandler_base_overlapped::write_overlapped (const void *ptr, size_t len)
1819 if (has_ongoing_io ())
1820 nbytes = (DWORD) -1;
1824 bool res = WriteFile (get_output_handle (), ptr, len, &nbytes,
1826 int wres = wait_overlapped (res, true, &nbytes, (size_t) len);
1827 if (wres || !_my_tls.call_signal_handler ())
1830 debug_printf ("returning %u", nbytes);