Cygwin: strptime: add release note
[newlib-cygwin.git] / winsup / cygwin / fhandler / base.cc
blob643236751ab1c600b777e4638521e428aee4d832
1 /* base.cc. Base functions, inherited by all fhandlers.
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
7 details. */
9 #include "winsup.h"
10 #include <unistd.h>
11 #include <stdlib.h>
12 #include <sys/uio.h>
13 #include <cygwin/acl.h>
14 #include <sys/param.h>
15 #include "cygerrno.h"
16 #include "perprocess.h"
17 #include "security.h"
18 #include "cygwin/version.h"
19 #include "path.h"
20 #include "fhandler.h"
21 #include "dtable.h"
22 #include "cygheap.h"
23 #include "pinfo.h"
24 #include <assert.h>
25 #include <winioctl.h>
26 #include "ntdll.h"
27 #include "cygtls.h"
28 #include "sigproc.h"
29 #include "shared_info.h"
30 #include <asm/socket.h>
31 #include "cygwait.h"
33 static const int CHUNK_SIZE = 1024; /* Used for crlf conversions */
35 struct __cygwin_perfile *perfile_table;
37 int
38 fhandler_base::puts_readahead (const char *s, size_t len)
40 int success = 1;
41 while ((len == (size_t) -1 ? *s : len--)
42 && (success = put_readahead (*s++) > 0))
43 continue;
44 return success;
47 int
48 fhandler_base::put_readahead (char value)
50 char *newrabuf;
51 if (raixput () < rabuflen ())
52 /* Nothing to do */;
53 else if ((newrabuf = (char *) realloc (rabuf (), rabuflen () += 32)))
54 rabuf () = newrabuf;
55 else
56 return 0;
58 rabuf ()[raixput ()++] = value;
59 ralen ()++;
60 return 1;
63 int
64 fhandler_base::get_readahead ()
66 int chret = -1;
67 if (raixget () < ralen ())
68 chret = ((unsigned char) rabuf ()[raixget ()++]) & 0xff;
69 /* FIXME - not thread safe */
70 if (raixget () >= ralen ())
71 raixget () = raixput () = ralen () = 0;
72 return chret;
75 int
76 fhandler_base::peek_readahead (int queryput)
78 int chret = -1;
79 if (!queryput && raixget () < ralen ())
80 chret = ((unsigned char) rabuf ()[raixget ()]) & 0xff;
81 else if (queryput && raixput () > 0)
82 chret = ((unsigned char) rabuf ()[raixput () - 1]) & 0xff;
83 return chret;
86 void
87 fhandler_base::set_readahead_valid (int val, int ch)
89 if (!val)
90 ralen () = raixget () = raixput () = 0;
91 if (ch != -1)
92 put_readahead (ch);
95 int
96 fhandler_base::get_readahead_into_buffer (char *buf, size_t buflen)
98 int ch;
99 int copied_chars = 0;
101 while (buflen)
102 if ((ch = get_readahead ()) < 0)
103 break;
104 else
106 buf[copied_chars++] = (unsigned char)(ch & 0xff);
107 buflen--;
110 return copied_chars;
113 /* Record the file name. and name hash */
114 void
115 fhandler_base::set_name (path_conv &in_pc)
117 pc << in_pc;
120 char *fhandler_base::get_proc_fd_name (char *buf)
122 IO_STATUS_BLOCK io;
123 FILE_STANDARD_INFORMATION fsi;
125 /* If the file had been opened with O_TMPFILE, don't expose the filename. */
126 if ((get_flags () & O_TMPFILE)
127 || (get_device () == FH_FS
128 && NT_SUCCESS (NtQueryInformationFile (get_handle (), &io,
129 &fsi, sizeof fsi,
130 FileStandardInformation))
131 && fsi.DeletePending))
133 stpcpy (stpcpy (buf, get_name ()), " (deleted)");
134 return buf;
136 if (get_name ())
137 return strcpy (buf, get_name ());
138 if (dev ().name ())
139 return strcpy (buf, dev ().name ());
140 return strcpy (buf, "");
143 /* Detect if we are sitting at EOF for conditions where Windows
144 returns an error but UNIX doesn't. */
146 is_at_eof (HANDLE h)
148 IO_STATUS_BLOCK io;
149 FILE_POSITION_INFORMATION fpi;
150 FILE_STANDARD_INFORMATION fsi;
152 if (NT_SUCCESS (NtQueryInformationFile (h, &io, &fsi, sizeof fsi,
153 FileStandardInformation))
154 && NT_SUCCESS (NtQueryInformationFile (h, &io, &fpi, sizeof fpi,
155 FilePositionInformation))
156 && fsi.EndOfFile.QuadPart == fpi.CurrentByteOffset.QuadPart)
157 return 1;
158 return 0;
161 void
162 fhandler_base::set_flags (int flags, int supplied_bin)
164 int bin;
165 int fmode;
166 debug_printf ("flags %y, supplied_bin %y", flags, supplied_bin);
167 if ((bin = flags & (O_BINARY | O_TEXT)))
168 debug_printf ("O_TEXT/O_BINARY set in flags %y", bin);
169 else if (rbinset () && wbinset ())
170 bin = rbinary () ? O_BINARY : O_TEXT; // FIXME: Not quite right
171 else if ((fmode = get_default_fmode (flags)) & O_BINARY)
172 bin = O_BINARY;
173 else if (fmode & O_TEXT)
174 bin = O_TEXT;
175 else if (supplied_bin)
176 bin = supplied_bin;
177 else
178 bin = wbinary () || rbinary () ? O_BINARY : O_TEXT;
180 openflags = flags | bin;
182 bin &= O_BINARY;
183 rbinary (bin ? true : false);
184 wbinary (bin ? true : false);
185 syscall_printf ("filemode set to %s", bin ? "binary" : "text");
188 /* Normal file i/o handlers. */
190 /* Cover function to ReadFile to achieve (as much as possible) Posix style
191 semantics and use of errno. */
192 void
193 fhandler_base::raw_read (void *ptr, size_t& len)
195 NTSTATUS status;
196 IO_STATUS_BLOCK io;
197 int try_noreserve = 1;
199 retry:
200 status = NtReadFile (get_handle (), NULL, NULL, NULL, &io, ptr, len,
201 NULL, NULL);
202 if (NT_SUCCESS (status))
203 len = io.Information;
204 else
206 /* Some errors are not really errors. Detect such cases here. */
207 switch (status)
209 case STATUS_END_OF_FILE:
210 case STATUS_PIPE_BROKEN:
211 /* This is really EOF. */
212 len = 0;
213 break;
214 case STATUS_MORE_ENTRIES:
215 case STATUS_BUFFER_OVERFLOW:
216 /* `io.Information' is supposedly valid. */
217 len = io.Information;
218 break;
219 case STATUS_ACCESS_VIOLATION:
220 if (is_at_eof (get_handle ()))
222 len = 0;
223 break;
225 if (try_noreserve)
227 try_noreserve = 0;
228 switch (mmap_is_attached_or_noreserve (ptr, len))
230 case MMAP_NORESERVE_COMMITED:
231 goto retry;
232 case MMAP_RAISE_SIGBUS:
233 raise(SIGBUS);
234 case MMAP_NONE:
235 break;
238 fallthrough;
239 case STATUS_INVALID_DEVICE_REQUEST:
240 case STATUS_INVALID_PARAMETER:
241 case STATUS_INVALID_HANDLE:
242 if (pc.isdir ())
244 set_errno (EISDIR);
245 len = (size_t) -1;
246 break;
248 fallthrough;
249 default:
250 __seterrno_from_nt_status (status);
251 len = (size_t) -1;
252 break;
257 /* Cover function to WriteFile to provide Posix interface and semantics
258 (as much as possible). */
259 ssize_t
260 fhandler_base::raw_write (const void *ptr, size_t len)
262 NTSTATUS status;
263 IO_STATUS_BLOCK io;
264 static _RDATA LARGE_INTEGER off_current =
265 { QuadPart:FILE_USE_FILE_POINTER_POSITION };
266 static _RDATA LARGE_INTEGER off_append =
267 { QuadPart:FILE_WRITE_TO_END_OF_FILE };
269 status = NtWriteFile (get_output_handle (), NULL, NULL, NULL, &io,
270 (PVOID) ptr, len,
271 (get_flags () & O_APPEND) ? &off_append : &off_current,
272 NULL);
273 if (!NT_SUCCESS (status))
275 __seterrno_from_nt_status (status);
276 if (get_errno () == EPIPE)
277 raise (SIGPIPE);
278 return -1;
280 return io.Information;
284 fhandler_base::get_default_fmode (int flags)
286 int fmode = __fmode;
287 if (perfile_table)
289 size_t nlen = strlen (get_name ());
290 unsigned accflags = (flags & O_ACCMODE);
291 for (__cygwin_perfile *pf = perfile_table; pf->name; pf++)
292 if (!*pf->name && (pf->flags & O_ACCMODE) == accflags)
294 fmode = pf->flags & ~O_ACCMODE;
295 break;
297 else
299 size_t pflen = strlen (pf->name);
300 const char *stem = get_name () + nlen - pflen;
301 if (pflen > nlen || (stem != get_name () && !isdirsep (stem[-1])))
302 continue;
303 else if ((pf->flags & O_ACCMODE) == accflags
304 && pathmatch (stem, pf->name, !!pc.objcaseinsensitive ()))
306 fmode = pf->flags & ~O_ACCMODE;
307 break;
311 return fmode;
314 bool
315 fhandler_base::device_access_denied (int flags)
317 int mode = 0;
319 if (flags & O_PATH)
320 return false;
322 if (flags & O_RDWR)
323 mode |= R_OK | W_OK;
324 if (flags & (O_WRONLY | O_APPEND))
325 mode |= W_OK;
326 if (!mode)
327 mode |= R_OK;
329 return fhaccess (mode, true);
333 fhandler_base::fhaccess (int flags, bool effective)
335 int res = -1;
336 if (error ())
338 set_errno (error ());
339 goto done;
342 if (!exists ())
344 set_errno (ENOENT);
345 goto done;
348 if (!(flags & (R_OK | W_OK | X_OK)))
349 return 0;
351 if (is_fs_special ())
352 /* short circuit */;
353 else if (has_attribute (FILE_ATTRIBUTE_READONLY) && (flags & W_OK)
354 && !pc.isdir ())
355 goto eaccess_done;
356 else if (has_acls ())
358 res = check_file_access (pc, flags, effective);
359 goto done;
361 else if (get_device () == FH_REGISTRY && open (O_RDONLY, 0) && get_handle ())
363 res = check_registry_access (get_handle (), flags, effective);
364 close ();
365 return res;
368 struct stat st;
369 if (fstat (&st))
370 goto done;
372 if (flags & R_OK)
374 if (st.st_uid == (effective ? myself->uid : cygheap->user.real_uid))
376 if (!(st.st_mode & S_IRUSR))
377 goto eaccess_done;
379 else if (st.st_gid == (effective ? myself->gid : cygheap->user.real_gid))
381 if (!(st.st_mode & S_IRGRP))
382 goto eaccess_done;
384 else if (!(st.st_mode & S_IROTH))
385 goto eaccess_done;
388 if (flags & W_OK)
390 if (st.st_uid == (effective ? myself->uid : cygheap->user.real_uid))
392 if (!(st.st_mode & S_IWUSR))
393 goto eaccess_done;
395 else if (st.st_gid == (effective ? myself->gid : cygheap->user.real_gid))
397 if (!(st.st_mode & S_IWGRP))
398 goto eaccess_done;
400 else if (!(st.st_mode & S_IWOTH))
401 goto eaccess_done;
404 if (flags & X_OK)
406 if (st.st_uid == (effective ? myself->uid : cygheap->user.real_uid))
408 if (!(st.st_mode & S_IXUSR))
409 goto eaccess_done;
411 else if (st.st_gid == (effective ? myself->gid : cygheap->user.real_gid))
413 if (!(st.st_mode & S_IXGRP))
414 goto eaccess_done;
416 else if (!(st.st_mode & S_IXOTH))
417 goto eaccess_done;
420 res = 0;
421 goto done;
423 eaccess_done:
424 set_errno (EACCES);
425 done:
426 if (!res && (flags & W_OK) && get_device () == FH_FS
427 && (pc.fs_flags () & FILE_READ_ONLY_VOLUME))
429 set_errno (EROFS);
430 res = -1;
432 debug_printf ("returning %d", res);
433 return res;
437 fhandler_base::open_with_arch (int flags, mode_t mode)
439 int res;
440 if (!(res = (archetype && archetype->io_handle)
441 || open (flags, mode & 07777)))
443 if (archetype && archetype->usecount == 0)
444 cygheap->fdtab.delete_archetype (archetype);
446 else if (archetype)
448 if (!archetype->get_handle ())
450 archetype->copy_from (this);
451 archetype_usecount (1);
452 archetype->archetype = NULL;
453 usecount = 0;
455 else
457 char *name;
458 /* Preserve any name (like /dev/tty) derived from build_fh_pc. */
459 if (!get_name ())
460 name = NULL;
461 else
463 name = (char *) alloca (strlen (get_name ()) + 1);
464 strcpy (name, get_name ());
466 fhandler_base *arch = archetype;
467 copy_from (archetype);
468 if (name)
469 set_name (name);
470 archetype = arch;
471 archetype_usecount (1);
472 usecount = 0;
474 if (!open_setup (flags))
475 api_fatal ("open_setup failed, %E");
478 close_on_exec (flags & O_CLOEXEC);
479 /* A unique ID is necessary to recognize fhandler entries which are
480 duplicated by dup(2) or fork(2). This is used in BSD flock calls
481 to identify the descriptor. Skip nohandle fhandlers since advisory
482 locking is unusable for those anyway. */
483 if (!nohandle ())
484 set_unique_id ();
485 return res;
488 /* Open a fake handle to \\Device\\Null. This is a helper function for
489 fhandlers which just need some handle to keep track of BSD flock locks. */
491 fhandler_base::open_null (int flags)
493 int res = 0;
494 HANDLE fh;
495 OBJECT_ATTRIBUTES attr;
496 IO_STATUS_BLOCK io;
497 NTSTATUS status;
499 InitializeObjectAttributes (&attr, &ro_u_null, OBJ_CASE_INSENSITIVE |
500 ((flags & O_CLOEXEC) ? 0 : OBJ_INHERIT),
501 NULL, NULL);
502 status = NtCreateFile (&fh, GENERIC_READ | SYNCHRONIZE, &attr, &io, NULL, 0,
503 FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN,
504 FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
505 if (!NT_SUCCESS (status))
507 __seterrno_from_nt_status (status);
508 goto done;
510 set_handle (fh);
511 set_flags (flags, pc.binmode ());
512 res = 1;
513 set_open_status ();
514 done:
515 debug_printf ("%y = NtCreateFile (%p, ... %S ...)", status, fh, &ro_u_null);
516 syscall_printf ("%d = fhandler_base::open_null (%y)", res, flags);
517 return res;
520 /* Open system call handler function. */
522 fhandler_base::open (int flags, mode_t mode)
524 int res = 0;
525 HANDLE fh;
526 ULONG file_attributes = 0;
527 ULONG shared = (get_major () == DEV_TAPE_MAJOR ? 0 : FILE_SHARE_VALID_FLAGS);
528 ULONG create_disposition;
529 OBJECT_ATTRIBUTES attr;
530 IO_STATUS_BLOCK io;
531 NTSTATUS status;
532 PFILE_FULL_EA_INFORMATION p = NULL;
533 ULONG plen = 0;
535 syscall_printf ("(%S, %y)%s", pc.get_nt_native_path (), flags,
536 get_handle () ? " by handle" : "");
538 if (flags & O_PATH)
539 query_open (query_read_attributes);
541 /* Allow to reopen from handle. This is utilized by
542 open ("/proc/PID/fd/DESCRIPTOR", ...); */
543 if (get_handle ())
545 pc.init_reopen_attr (attr, get_handle ());
546 if (!(flags & O_CLOEXEC))
547 attr.Attributes |= OBJ_INHERIT;
548 if (pc.has_buggy_reopen ())
549 debug_printf ("Reopen by handle requested but FS doesn't support it");
551 else
552 pc.get_object_attr (attr, *sec_none_cloexec (flags));
554 options = FILE_OPEN_FOR_BACKUP_INTENT;
555 switch (query_open ())
557 case query_read_control:
558 access = READ_CONTROL;
559 break;
560 case query_read_attributes:
561 access = READ_CONTROL | FILE_READ_ATTRIBUTES;
562 break;
563 case query_write_control:
564 access = READ_CONTROL | WRITE_OWNER | WRITE_DAC | FILE_WRITE_ATTRIBUTES;
565 break;
566 case query_write_dac:
567 access = READ_CONTROL | WRITE_DAC | FILE_WRITE_ATTRIBUTES;
568 break;
569 case query_write_attributes:
570 access = READ_CONTROL | FILE_WRITE_ATTRIBUTES;
571 break;
572 default:
573 switch (flags & O_ACCMODE)
575 case O_RDONLY:
576 access = GENERIC_READ;
577 break;
578 case O_WRONLY:
579 access = GENERIC_WRITE | READ_CONTROL | FILE_READ_ATTRIBUTES;
580 break;
581 default:
582 access = GENERIC_READ | GENERIC_WRITE;
583 break;
585 if (flags & O_SYNC)
586 options |= FILE_WRITE_THROUGH;
587 if (flags & O_DIRECT)
588 options |= FILE_NO_INTERMEDIATE_BUFFERING;
589 if (get_major () != DEV_SERIAL_MAJOR && get_major () != DEV_TAPE_MAJOR)
591 options |= FILE_SYNCHRONOUS_IO_NONALERT;
592 access |= SYNCHRONIZE;
594 break;
597 /* Don't use the FILE_OVERWRITE{_IF} flags here. See below for an
598 explanation, why that's not such a good idea. */
599 if (((flags & O_EXCL) && (flags & O_CREAT)) || (flags & O_TMPFILE))
600 create_disposition = FILE_CREATE;
601 else
602 create_disposition = (flags & O_CREAT) ? FILE_OPEN_IF : FILE_OPEN;
604 if (get_device () == FH_FS
605 #ifdef __WITH_AF_UNIX
606 || get_device () == FH_UNIX
607 #endif
610 /* Add the reparse point flag to known reparse points, otherwise we
611 open the target, not the reparse point. This would break lstat. */
612 if (pc.is_known_reparse_point ())
613 options |= FILE_OPEN_REPARSE_POINT;
616 /* If the file is a FIFO, open has been called for an operation on the file
617 constituting the FIFO, e. g., chmod or statvfs. Handle it like a normal
618 file. Eespecially the access flags have to be set correctly. */
619 if (get_device () == FH_FS || get_device () == FH_FIFO)
621 /* O_TMPFILE files are created with delete-on-close semantics, as well
622 as with FILE_ATTRIBUTE_TEMPORARY. The latter speeds up file access,
623 because the OS tries to keep the file in memory as much as possible.
624 In conjunction with FILE_DELETE_ON_CLOSE, ideally the OS never has
625 to write to the disk at all.
626 Note that O_TMPFILE_FILE_ATTRS also sets the DOS HIDDEN attribute
627 to help telling Cygwin O_TMPFILE files apart from other files
628 accidentally setting FILE_ATTRIBUTE_TEMPORARY. */
629 if (flags & O_TMPFILE)
631 access |= DELETE;
632 file_attributes |= O_TMPFILE_FILE_ATTRS;
633 options |= FILE_DELETE_ON_CLOSE;
636 if (pc.fs_is_nfs ())
638 /* Make sure we can read EAs of files on an NFS share. Also make
639 sure that we're going to act on the file itself, even if it's a
640 a symlink. */
641 access |= FILE_READ_EA;
642 if (query_open ())
644 if (query_open () >= query_write_control)
645 access |= FILE_WRITE_EA;
646 plen = sizeof nfs_aol_ffei;
647 p = (PFILE_FULL_EA_INFORMATION) &nfs_aol_ffei;
651 if (flags & (O_CREAT | O_TMPFILE))
653 file_attributes |= FILE_ATTRIBUTE_NORMAL;
655 if (pc.fs_is_nfs ())
657 /* When creating a file on an NFS share, we have to set the
658 file mode by writing a NFS fattr3 structure with the
659 correct mode bits set. */
660 access |= FILE_WRITE_EA;
661 plen = sizeof (FILE_FULL_EA_INFORMATION) + sizeof (NFS_V3_ATTR)
662 + sizeof (fattr3);
663 p = (PFILE_FULL_EA_INFORMATION) alloca (plen);
664 p->NextEntryOffset = 0;
665 p->Flags = 0;
666 p->EaNameLength = sizeof (NFS_V3_ATTR) - 1;
667 p->EaValueLength = sizeof (fattr3);
668 strcpy (p->EaName, NFS_V3_ATTR);
669 fattr3 *nfs_attr = (fattr3 *) (p->EaName
670 + p->EaNameLength + 1);
671 memset (nfs_attr, 0, sizeof (fattr3));
672 nfs_attr->type = NF3REG;
673 nfs_attr->mode = (mode & 07777) & ~cygheap->umask;
675 else if (!has_acls ()
676 && !(mode & ~cygheap->umask & (S_IWUSR | S_IWGRP | S_IWOTH)))
677 /* If mode has no write bits set, and ACLs are not used, we set
678 the DOS R/O attribute. */
679 file_attributes |= FILE_ATTRIBUTE_READONLY;
680 /* Never set the WRITE_DAC flag here. Calls to fstat may return
681 wrong st_ctime information after calls to fchmod, fchown, etc
682 because Windows only guarantees the update of metadata when
683 the handle is closed or flushed. However, flushing the file
684 on every fstat to enforce POSIXy stat behaviour is excessivly
685 slow, compared to an extra open/close to change the file's
686 security descriptor. */
690 status = NtCreateFile (&fh, access, &attr, &io, NULL, file_attributes, shared,
691 create_disposition, options, p, plen);
692 /* Pre-W10, we can't reopen a file by handle with delete disposition
693 set, so we have to lie our ass off. */
694 if (get_handle () && status == STATUS_DELETE_PENDING)
696 BOOL ret = DuplicateHandle (GetCurrentProcess (), get_handle (),
697 GetCurrentProcess (), &fh,
698 access, !(flags & O_CLOEXEC), 0);
699 if (!ret)
700 ret = DuplicateHandle (GetCurrentProcess (), get_handle (),
701 GetCurrentProcess (), &fh,
702 0, !(flags & O_CLOEXEC),
703 DUPLICATE_SAME_ACCESS);
704 if (!ret)
705 debug_printf ("DuplicateHandle after STATUS_DELETE_PENDING, %E");
706 else
707 status = STATUS_SUCCESS;
709 if (!NT_SUCCESS (status))
711 /* Trying to create a directory should return EISDIR, not ENOENT. */
712 PUNICODE_STRING upath = pc.get_nt_native_path ();
713 if (status == STATUS_OBJECT_NAME_INVALID && (flags & O_CREAT)
714 && upath->Buffer[upath->Length / sizeof (WCHAR) - 1] == '\\')
715 set_errno (EISDIR);
716 else
717 __seterrno_from_nt_status (status);
718 if (!nohandle ())
719 goto done;
722 if (io.Information == FILE_CREATED)
724 /* Correct file attributes are needed for later use in, e.g. fchmod. */
725 FILE_BASIC_INFORMATION fbi;
727 if (!NT_SUCCESS (NtQueryInformationFile (fh, &io, &fbi, sizeof fbi,
728 FileBasicInformation)))
729 fbi.FileAttributes = file_attributes | FILE_ATTRIBUTE_ARCHIVE;
730 pc.file_attributes (fbi.FileAttributes);
732 /* Always create files using a NULL SD. Create correct permission bits
733 afterwards, maintaining the owner and group information just like
734 chmod. This is done for two reasons.
736 On Windows filesystems we need to create the file with default
737 permissions to allow inheriting ACEs. When providing an explicit DACL
738 in calls to [Nt]CreateFile, the created file will not inherit default
739 permissions from the parent object. This breaks not only Windows
740 inheritance, but also POSIX ACL inheritance.
742 Another reason to do this are remote shares. Files on a remote share
743 are created as the user used for authentication. In a domain that's
744 usually the user you're logged in as. Outside of a domain you're
745 authenticating using a local user account on the sharing machine.
746 If the SIDs of the client machine are used, that's entirely unexpected
747 behaviour. Doing it like we do here creates the expected SD in a
748 domain as well as on standalone servers. This is the result of a
749 discussion on the samba-technical list, starting at
750 http://lists.samba.org/archive/samba-technical/2008-July/060247.html */
751 if (has_acls ())
752 set_created_file_access (fh, pc, mode);
755 /* If you O_TRUNC a file on Linux, the data is truncated, but the EAs are
756 preserved. If you open a file on Windows with FILE_OVERWRITE{_IF} or
757 FILE_SUPERSEDE, all streams are truncated, including the EAs. So we don't
758 use the FILE_OVERWRITE{_IF} flags, but instead just open the file and set
759 the size of the data stream explicitely to 0. Apart from being more Linux
760 compatible, this implementation has the pleasant side-effect to be more
761 than 5% faster than using FILE_OVERWRITE{_IF} (tested on W7 32 bit). */
762 if ((flags & O_TRUNC)
763 && (flags & O_ACCMODE) != O_RDONLY
764 && io.Information != FILE_CREATED
765 && get_device () == FH_FS)
767 FILE_END_OF_FILE_INFORMATION feofi = { EndOfFile:{ QuadPart:0 } };
768 status = NtSetInformationFile (fh, &io, &feofi, sizeof feofi,
769 FileEndOfFileInformation);
770 /* In theory, truncating the file should never fail, since the opened
771 handle has FILE_WRITE_DATA permissions, which is all you need to
772 be allowed to truncate a file. Better safe than sorry. */
773 if (!NT_SUCCESS (status))
775 __seterrno_from_nt_status (status);
776 NtClose (fh);
777 goto done;
779 /* Drop sparseness */
780 if (pc.file_attributes () & FILE_ATTRIBUTE_SPARSE_FILE)
782 FILE_SET_SPARSE_BUFFER fssb = { SetSparse: FALSE };
783 status = NtFsControlFile (fh, NULL, NULL, NULL, &io,
784 FSCTL_SET_SPARSE, &fssb, sizeof fssb, NULL, 0);
785 if (NT_SUCCESS (status))
786 pc.file_attributes (pc.file_attributes () & ~FILE_ATTRIBUTE_SPARSE_FILE);
790 set_handle (fh);
791 set_flags (flags, pc.binmode ());
793 res = 1;
794 set_open_status ();
795 done:
796 debug_printf ("%y = NtCreateFile "
797 "(%p, %y, %S, io, NULL, %y, %y, %y, %y, NULL, 0)",
798 status, fh, access, pc.get_nt_native_path (), file_attributes,
799 shared, create_disposition, options);
801 syscall_printf ("%d = fhandler_base::open(%S, %y)",
802 res, pc.get_nt_native_path (), flags);
803 return res;
806 fhandler_base *
807 fhandler_base::fd_reopen (int, mode_t)
809 /* This is implemented in fhandler_process only. */
810 return NULL;
813 bool
814 fhandler_base::open_setup (int)
816 return true;
819 /* states:
820 open buffer in binary mode? Just do the read.
822 open buffer in text mode? Scan buffer for control zs and handle
823 the first one found. Then scan buffer, converting every \r\n into
824 an \n. If last char is an \r, look ahead one more char, if \n then
825 modify \r, if not, remember char.
827 void
828 fhandler_base::read (void *in_ptr, size_t& len)
830 char *ptr = (char *) in_ptr;
831 ssize_t copied_chars = get_readahead_into_buffer (ptr, len);
833 if (copied_chars || !len)
835 len = (size_t) copied_chars;
836 goto out;
839 raw_read (ptr, len);
841 if (rbinary () || (ssize_t) len <= 0)
842 goto out;
844 /* Scan buffer and turn \r\n into \n */
845 char *src, *dst, *end;
846 src = (char *) ptr;
847 dst = (char *) ptr;
848 end = src + len - 1;
850 /* Read up to the last but one char - the last char needs special handling */
851 while (src < end)
853 if (*src == '\r' && src[1] == '\n')
854 src++;
855 *dst++ = *src++;
858 /* If not beyond end and last char is a '\r' then read one more
859 to see if we should translate this one too */
860 if (src > end)
861 /* nothing */;
862 else if (*src != '\r')
863 *dst++ = *src;
864 else
866 char c1;
867 size_t c1len = 1;
868 raw_read (&c1, c1len);
869 if (c1len <= 0)
870 /* nothing */;
871 else if (c1 == '\n')
872 *dst++ = '\n';
873 else
875 set_readahead_valid (1, c1);
876 *dst++ = *src;
880 len = dst - (char *) ptr;
882 out:
883 debug_printf ("returning %d, %s mode", len, rbinary () ? "binary" : "text");
886 ssize_t
887 fhandler_base::write (const void *ptr, size_t len)
889 ssize_t res;
891 if (did_lseek ())
893 IO_STATUS_BLOCK io;
894 FILE_POSITION_INFORMATION fpi;
895 FILE_STANDARD_INFORMATION fsi;
897 did_lseek (false); /* don't do it again */
899 /* If the file system supports sparse files and the application is
900 writing after a long seek beyond EOF spanning more than one
901 sparsifiable chunk, convert the file to a sparse file. */
902 if (!(get_flags () & O_APPEND)
903 && !has_attribute (FILE_ATTRIBUTE_SPARSE_FILE)
904 && NT_SUCCESS (NtQueryInformationFile (get_output_handle (),
905 &io, &fsi, sizeof fsi,
906 FileStandardInformation))
907 && NT_SUCCESS (NtQueryInformationFile (get_output_handle (),
908 &io, &fpi, sizeof fpi,
909 FilePositionInformation))
910 && span_sparse_chunk (fpi.CurrentByteOffset.QuadPart,
911 fsi.EndOfFile.QuadPart))
913 NTSTATUS status;
914 status = NtFsControlFile (get_output_handle (), NULL, NULL, NULL,
915 &io, FSCTL_SET_SPARSE, NULL, 0, NULL, 0);
916 if (NT_SUCCESS (status))
917 pc.file_attributes (pc.file_attributes ()
918 | FILE_ATTRIBUTE_SPARSE_FILE);
919 debug_printf ("%y = NtFsControlFile(%S, FSCTL_SET_SPARSE)",
920 status, pc.get_nt_native_path ());
924 if (wbinary ())
925 res = raw_write (ptr, len);
926 else
928 debug_printf ("text write");
929 /* This is the Microsoft/DJGPP way. Still not ideal, but it's
930 compatible.
931 Modified slightly by CGF 2000-10-07 */
933 int left_in_data = len;
934 char *data = (char *)ptr;
935 res = 0;
937 while (left_in_data > 0)
939 char buf[CHUNK_SIZE + 1], *buf_ptr = buf;
940 int left_in_buf = CHUNK_SIZE;
942 while (left_in_buf > 0 && left_in_data > 0)
944 char ch = *data++;
945 if (ch == '\n')
947 *buf_ptr++ = '\r';
948 left_in_buf--;
950 *buf_ptr++ = ch;
951 left_in_buf--;
952 left_in_data--;
953 if (left_in_data > 0 && ch == '\r' && *data == '\n')
955 *buf_ptr++ = *data++;
956 left_in_buf--;
957 left_in_data--;
961 /* We've got a buffer-full, or we're out of data. Write it out */
962 ssize_t nbytes;
963 ptrdiff_t want = buf_ptr - buf;
964 if ((nbytes = raw_write (buf, (size_t) want)) == want)
966 /* Keep track of how much written not counting additional \r's */
967 res = data - (char *)ptr;
968 continue;
971 if (nbytes == -1)
972 res = -1; /* Error */
973 else
974 res += nbytes; /* Partial write. Return total bytes written. */
975 break; /* All done */
979 return res;
982 ssize_t
983 fhandler_base::readv (const struct iovec *const iov, const int iovcnt,
984 ssize_t tot)
986 assert (iov);
987 assert (iovcnt >= 1);
989 size_t len = tot;
990 if (iovcnt == 1)
992 len = iov->iov_len;
993 read (iov->iov_base, len);
994 return len;
997 if (tot == -1) // i.e. if not pre-calculated by the caller.
999 len = 0;
1000 const struct iovec *iovptr = iov + iovcnt;
1003 iovptr -= 1;
1004 len += iovptr->iov_len;
1006 while (iovptr != iov);
1009 if (!len)
1010 return 0;
1012 char *buf = (char *) malloc (len);
1014 if (!buf)
1016 set_errno (ENOMEM);
1017 return -1;
1020 read (buf, len);
1021 ssize_t nbytes = (ssize_t) len;
1023 const struct iovec *iovptr = iov;
1025 char *p = buf;
1026 while (nbytes > 0)
1028 const int frag = MIN (nbytes, (ssize_t) iovptr->iov_len);
1029 memcpy (iovptr->iov_base, p, frag);
1030 p += frag;
1031 iovptr += 1;
1032 nbytes -= frag;
1035 free (buf);
1036 return len;
1039 ssize_t
1040 fhandler_base::writev (const struct iovec *const iov, const int iovcnt,
1041 ssize_t tot)
1043 assert (iov);
1044 assert (iovcnt >= 1);
1046 if (iovcnt == 1)
1047 return write (iov->iov_base, iov->iov_len);
1049 if (tot == -1) // i.e. if not pre-calculated by the caller.
1051 tot = 0;
1052 const struct iovec *iovptr = iov + iovcnt;
1055 iovptr -= 1;
1056 tot += iovptr->iov_len;
1058 while (iovptr != iov);
1061 assert (tot >= 0);
1063 if (tot == 0)
1064 return 0;
1066 char *const buf = (char *) malloc (tot);
1068 if (!buf)
1070 set_errno (ENOMEM);
1071 return -1;
1074 char *bufptr = buf;
1075 const struct iovec *iovptr = iov;
1076 int nbytes = tot;
1078 while (nbytes != 0)
1080 const int frag = MIN (nbytes, (ssize_t) iovptr->iov_len);
1081 memcpy (bufptr, iovptr->iov_base, frag);
1082 bufptr += frag;
1083 iovptr += 1;
1084 nbytes -= frag;
1086 ssize_t ret = write (buf, tot);
1087 free (buf);
1088 return ret;
1091 off_t
1092 fhandler_base::lseek (off_t offset, int whence)
1094 NTSTATUS status;
1095 IO_STATUS_BLOCK io;
1096 FILE_POSITION_INFORMATION fpi;
1097 FILE_STANDARD_INFORMATION fsi;
1099 /* Seeks on text files is tough, we rewind and read till we get to the
1100 right place. */
1102 if (whence != SEEK_CUR || offset != 0)
1104 if (whence == SEEK_CUR)
1105 offset -= ralen () - raixget ();
1106 set_readahead_valid (0);
1109 switch (whence)
1111 case SEEK_SET:
1112 fpi.CurrentByteOffset.QuadPart = offset;
1113 break;
1114 case SEEK_CUR:
1115 status = NtQueryInformationFile (get_handle (), &io, &fpi, sizeof fpi,
1116 FilePositionInformation);
1117 if (!NT_SUCCESS (status))
1119 __seterrno_from_nt_status (status);
1120 return -1;
1122 fpi.CurrentByteOffset.QuadPart += offset;
1123 break;
1124 case SEEK_END:
1125 status = NtQueryInformationFile (get_handle (), &io, &fsi, sizeof fsi,
1126 FileStandardInformation);
1127 if (!NT_SUCCESS (status))
1129 __seterrno_from_nt_status (status);
1130 return -1;
1132 fpi.CurrentByteOffset.QuadPart = fsi.EndOfFile.QuadPart + offset;
1133 break;
1134 case SEEK_DATA:
1135 case SEEK_HOLE:
1137 FILE_ALLOCATED_RANGE_BUFFER inp, out;
1139 status = NtQueryInformationFile (get_handle (), &io, &fsi, sizeof fsi,
1140 FileStandardInformation);
1141 if (!NT_SUCCESS (status))
1143 __seterrno_from_nt_status (status);
1144 return -1;
1146 /* Per Linux man page, ENXIO if offset is beyond EOF */
1147 if (offset > fsi.EndOfFile.QuadPart)
1149 set_errno (ENXIO);
1150 return -1;
1152 if (!has_attribute (FILE_ATTRIBUTE_SPARSE_FILE))
1154 /* Default behaviour if sparse files are not supported:
1155 SEEK_DATA: seek to offset
1156 SEEK_HOLE: seek to EOF */
1157 fpi.CurrentByteOffset.QuadPart = (whence == SEEK_DATA)
1158 ? offset
1159 : fsi.EndOfFile.QuadPart;
1160 break;
1162 inp.FileOffset.QuadPart = offset;
1163 inp.Length.QuadPart = fsi.EndOfFile.QuadPart - offset;
1164 /* Note that we only fetch a single region, so we expect the
1165 function to fail with STATUS_BUFFER_OVERFLOW. It still
1166 returns the data region containing offset, or the next
1167 region after offset, if offset is within a hole. */
1168 status = NtFsControlFile (get_output_handle (), NULL, NULL, NULL,
1169 &io, FSCTL_QUERY_ALLOCATED_RANGES,
1170 &inp, sizeof inp,
1171 &out, sizeof out);
1172 if (!NT_SUCCESS (status) && status != STATUS_BUFFER_OVERFLOW)
1174 /* On error, fall back to default behaviour, see above. */
1175 fpi.CurrentByteOffset.QuadPart = (whence == SEEK_DATA)
1176 ? offset
1177 : fsi.EndOfFile.QuadPart;
1178 break;
1180 if (io.Information == 0)
1182 /* No valid region, so offset is within a hole at EOF.
1183 SEEK_DATA: ENXIO
1184 SEEK_HOLE: seek to offset */
1185 if (whence == SEEK_DATA)
1187 set_errno (ENXIO);
1188 return -1;
1190 fpi.CurrentByteOffset.QuadPart = offset;
1192 else if (out.FileOffset.QuadPart == offset)
1194 /* offset within valid data range? In that case, that region
1195 supposedly starts at offset, and the region length is corrected
1196 accordingly. That's quite helpful.
1197 SEEK_DATA: seek to offset
1198 SEEK_HOLE: seek to end of range */
1199 fpi.CurrentByteOffset.QuadPart = offset;
1200 if (whence == SEEK_HOLE)
1201 fpi.CurrentByteOffset.QuadPart += out.Length.QuadPart;
1203 else
1205 /* Is range beyond offset?
1206 SEEK_DATA: seek to start of range
1207 SEEK_HOLE: seek to offset */
1208 fpi.CurrentByteOffset.QuadPart = (whence == SEEK_DATA)
1209 ? out.FileOffset.QuadPart
1210 : offset;
1213 break;
1214 default: /* Should never be reached */
1215 set_errno (EINVAL);
1216 return -1;
1219 debug_printf ("setting file pointer to %U", fpi.CurrentByteOffset.QuadPart);
1220 status = NtSetInformationFile (get_handle (), &io, &fpi, sizeof fpi,
1221 FilePositionInformation);
1222 if (!NT_SUCCESS (status))
1224 __seterrno_from_nt_status (status);
1225 return -1;
1227 off_t res = fpi.CurrentByteOffset.QuadPart;
1229 /* When next we write(), we will check to see if *this* seek went beyond
1230 the end of the file and if so, potentially sparsify the file. */
1231 if (pc.support_sparse ())
1232 did_lseek (true);
1234 /* If this was a SEEK_CUR with offset 0, we still might have
1235 readahead that we have to take into account when calculating
1236 the actual position for the application. */
1237 if (whence == SEEK_CUR)
1238 res -= ralen () - raixget ();
1240 return res;
1243 ssize_t
1244 fhandler_base::pread (void *, size_t, off_t, void *)
1246 set_errno (ESPIPE);
1247 return -1;
1250 ssize_t
1251 fhandler_base::pwrite (void *, size_t, off_t, void *)
1253 set_errno (ESPIPE);
1254 return -1;
1258 fhandler_base::close_with_arch ()
1260 int res;
1261 fhandler_base *fh;
1262 if (usecount)
1264 /* This was the archetype itself. */
1265 if (--usecount)
1267 debug_printf ("not closing passed in archetype %p, usecount %d", archetype, usecount);
1268 return 0;
1270 debug_printf ("closing passed in archetype %p, usecount %d", archetype, usecount);
1271 /* Set archetype temporarily so that it will eventually be deleted. */
1272 archetype = fh = this;
1274 else if (!archetype)
1275 fh = this;
1276 else if (archetype_usecount (-1) == 0)
1278 debug_printf ("closing archetype");
1279 fh = archetype;
1281 else
1283 debug_printf ("not closing archetype");
1284 return 0;
1287 cleanup ();
1288 res = fh->close ();
1289 if (archetype)
1291 cygheap->fdtab.delete_archetype (archetype);
1292 archetype = NULL;
1294 return res;
1297 void
1298 fhandler_base::cleanup ()
1300 /* Delete all POSIX locks on the file. Delete all flock locks on the
1301 file if this is the last reference to this file. */
1302 if (unique_id)
1303 del_my_locks (on_close);
1307 fhandler_base::close ()
1309 int res = -1;
1311 syscall_printf ("closing '%s' handle %p", get_name (), get_handle ());
1312 if (nohandle () || CloseHandle (get_handle ()))
1313 res = 0;
1314 else
1316 paranoid_printf ("CloseHandle failed, %E");
1317 __seterrno ();
1319 clear_getdents ();
1320 return res;
1324 fhandler_base::ioctl (unsigned int cmd, void *buf)
1326 int res;
1328 switch (cmd)
1330 case FIONBIO:
1331 set_nonblocking (*(int *) buf);
1332 res = 0;
1333 break;
1334 case FIONREAD:
1335 case TIOCSCTTY:
1336 set_errno (ENOTTY);
1337 res = -1;
1338 break;
1339 default:
1340 set_errno (EINVAL);
1341 res = -1;
1342 break;
1345 syscall_printf ("%d = ioctl(%x, %p)", res, cmd, buf);
1346 return res;
1350 fhandler_base::fstat (struct stat *buf)
1352 if (is_fs_special ())
1353 return fstat_fs (buf);
1355 switch (get_device ())
1357 case FH_PIPE:
1358 buf->st_mode = S_IFIFO | S_IRUSR | S_IWUSR;
1359 break;
1360 case FH_PIPEW:
1361 buf->st_mode = S_IFIFO | S_IWUSR;
1362 break;
1363 case FH_PIPER:
1364 buf->st_mode = S_IFIFO | S_IRUSR;
1365 break;
1366 default:
1367 buf->st_mode = S_IFCHR | STD_RBITS | STD_WBITS | S_IWGRP | S_IWOTH;
1368 break;
1371 buf->st_uid = geteuid ();
1372 buf->st_gid = getegid ();
1373 buf->st_nlink = 1;
1374 buf->st_blksize = PREFERRED_IO_BLKSIZE;
1376 buf->st_ctim.tv_sec = 1164931200L; /* Arbitrary value: 2006-12-01 */
1377 buf->st_ctim.tv_nsec = 0L;
1378 buf->st_birthtim = buf->st_ctim;
1379 buf->st_mtim.tv_sec = time (NULL); /* Arbitrary value: current time,
1380 like Linux */
1381 buf->st_mtim.tv_nsec = 0L;
1382 buf->st_atim = buf->st_mtim;
1384 return 0;
1388 fhandler_base::fstatvfs (struct statvfs *sfs)
1390 /* If we hit this base implementation, it's some device in /dev.
1391 Just call statvfs on /dev for simplicity. */
1392 path_conv pc ("/dev", PC_KEEP_HANDLE);
1393 fhandler_disk_file fh (pc);
1394 return fh.fstatvfs (sfs);
1398 fhandler_base::init (HANDLE f, DWORD a, mode_t bin)
1400 set_handle (f);
1401 access = a;
1402 a &= GENERIC_READ | GENERIC_WRITE;
1403 int flags = 0;
1404 if (a == GENERIC_READ)
1405 flags = O_RDONLY;
1406 else if (a == GENERIC_WRITE)
1407 flags = O_WRONLY;
1408 else if (a == (GENERIC_READ | GENERIC_WRITE))
1409 flags = O_RDWR;
1410 set_flags (flags | bin);
1411 set_open_status ();
1412 debug_printf ("created new fhandler_base for handle %p, bin %d", f, rbinary ());
1413 return 1;
1417 fhandler_base::dup (fhandler_base *child, int flags)
1419 debug_printf ("in fhandler_base dup");
1421 HANDLE nh;
1422 if (!nohandle () && !archetype)
1424 if (!DuplicateHandle (GetCurrentProcess (), get_handle (),
1425 GetCurrentProcess (), &nh,
1426 0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
1428 debug_printf ("dup(%s) failed, handle %p, %E",
1429 get_name (), get_handle ());
1430 __seterrno ();
1431 return -1;
1434 VerifyHandle (nh);
1435 child->set_handle (nh);
1436 /* Just set to NULL, the struct is potentially still valid
1437 in the parent fhandler. */
1439 child->getdents_dir (NULL);
1440 return 0;
1443 int fhandler_base::fcntl (int cmd, intptr_t arg)
1445 int res;
1447 switch (cmd)
1449 case F_GETFD:
1450 res = close_on_exec () ? FD_CLOEXEC : 0;
1451 break;
1452 case F_SETFD:
1453 set_close_on_exec ((arg & FD_CLOEXEC) ? 1 : 0);
1454 res = 0;
1455 break;
1456 case F_GETFL:
1457 res = get_flags ();
1458 debug_printf ("GETFL: %y", res);
1459 break;
1460 case F_SETFL:
1462 /* Only O_APPEND, O_ASYNC and O_NONBLOCK are allowed.
1463 Each other flag will be ignored.
1464 Since O_ASYNC isn't defined in fcntl.h it's currently
1465 ignored as well. */
1466 const int allowed_flags = O_APPEND | O_NONBLOCK;
1467 int new_flags = arg & allowed_flags;
1468 set_flags ((get_flags () & ~allowed_flags) | new_flags);
1470 res = 0;
1471 break;
1472 case F_GETLK:
1473 case F_SETLK:
1474 case F_SETLKW:
1476 struct flock *fl = (struct flock *) arg;
1477 fl->l_type &= F_RDLCK | F_WRLCK | F_UNLCK;
1478 res = mandatory_locking () ? mand_lock (cmd, fl) : lock (cmd, fl);
1480 break;
1481 default:
1482 set_errno (EINVAL);
1483 res = -1;
1484 break;
1486 return res;
1489 /* Base terminal handlers. These just return errors. */
1492 fhandler_base::tcflush (int)
1494 set_errno (ENOTTY);
1495 return -1;
1499 fhandler_base::tcsendbreak (int)
1501 set_errno (ENOTTY);
1502 return -1;
1506 fhandler_base::tcdrain ()
1508 set_errno (ENOTTY);
1509 return -1;
1513 fhandler_base::tcflow (int)
1515 set_errno (ENOTTY);
1516 return -1;
1520 fhandler_base::tcsetattr (int, const struct termios *)
1522 set_errno (ENOTTY);
1523 return -1;
1527 fhandler_base::tcgetattr (struct termios *)
1529 set_errno (ENOTTY);
1530 return -1;
1534 fhandler_base::tcsetpgrp (const pid_t)
1536 set_errno (ENOTTY);
1537 return -1;
1541 fhandler_base::tcgetpgrp ()
1543 set_errno (ENOTTY);
1544 return -1;
1547 pid_t
1548 fhandler_base::tcgetsid ()
1550 set_errno (ENOTTY);
1551 return -1;
1555 fhandler_base::ptsname_r (char *, size_t)
1557 set_errno (ENOTTY);
1558 return ENOTTY;
1561 /* Normal I/O constructor */
1562 fhandler_base::fhandler_base () :
1563 status (),
1564 open_status (),
1565 access (0),
1566 io_handle (NULL),
1567 ino (0),
1568 _refcnt (0),
1569 openflags (0),
1570 unique_id (0),
1571 select_sem (NULL),
1572 archetype (NULL),
1573 usecount (0)
1575 ra.rabuf = NULL;
1576 ra.ralen = 0;
1577 ra.raixget = 0;
1578 ra.raixput = 0;
1579 ra.rabuflen = 0;
1580 isclosed (false);
1583 /* Normal I/O destructor */
1584 fhandler_base::~fhandler_base ()
1586 if (ra.rabuf)
1587 free (ra.rabuf);
1590 void
1591 fhandler_base::set_no_inheritance (HANDLE &h, bool not_inheriting)
1593 if (!SetHandleInformation (h, HANDLE_FLAG_INHERIT,
1594 not_inheriting ? 0 : HANDLE_FLAG_INHERIT))
1595 debug_printf ("SetHandleInformation failed, %E");
1596 #ifdef DEBUGGING_AND_FDS_PROTECTED
1597 if (h)
1598 setclexec (oh, h, not_inheriting);
1599 #endif
1602 bool
1603 fhandler_base::fork_fixup (HANDLE parent, HANDLE &h, const char *name)
1605 HANDLE oh = h;
1606 bool res = false;
1607 if (!close_on_exec ())
1608 debug_printf ("handle %p already opened", h);
1609 else if (!DuplicateHandle (parent, h, GetCurrentProcess (), &h,
1610 0, !close_on_exec (), DUPLICATE_SAME_ACCESS))
1611 system_printf ("%s - %E, handle %s<%p>", get_name (), name, h);
1612 else
1614 if (oh != h)
1615 VerifyHandle (h);
1616 res = true;
1618 return res;
1621 void
1622 fhandler_base::set_close_on_exec (bool val)
1624 if (!nohandle ())
1625 set_no_inheritance (io_handle, val);
1626 close_on_exec (val);
1627 debug_printf ("set close_on_exec for %s to %d", get_name (), val);
1630 void
1631 fhandler_base::fixup_after_fork (HANDLE parent)
1633 debug_printf ("inheriting '%s' from parent", get_name ());
1634 if (!nohandle ())
1635 fork_fixup (parent, io_handle, "io_handle");
1636 /* POSIX locks are not inherited across fork. */
1637 if (unique_id)
1638 del_my_locks (after_fork);
1639 clear_getdents ();
1642 void
1643 fhandler_base::fixup_after_exec ()
1645 debug_printf ("here for '%s'", get_name ());
1646 if (unique_id && close_on_exec ())
1647 del_my_locks (after_exec);
1648 getdents_dir (NULL);
1649 mandatory_locking (false);
1652 bool
1653 fhandler_base::is_nonblocking ()
1655 return (openflags & O_NONBLOCK) != 0;
1658 void
1659 fhandler_base::set_nonblocking (int yes)
1661 int current = openflags & O_NONBLOCK;
1662 int new_flags = yes ? (!current ? O_NONBLOCK : current) : 0;
1663 openflags = (openflags & ~O_NONBLOCK) | new_flags;
1667 fhandler_base::mkdir (mode_t)
1669 if (exists ())
1670 set_errno (EEXIST);
1671 else
1672 set_errno (EROFS);
1673 return -1;
1677 fhandler_base::rmdir ()
1679 if (!exists ())
1680 set_errno (ENOENT);
1681 else if (!pc.isdir ())
1682 set_errno (ENOTDIR);
1683 else
1684 set_errno (EROFS);
1685 return -1;
1688 DIR *
1689 fhandler_base::opendir (int fd)
1691 set_errno (ENOTDIR);
1692 return NULL;
1696 fhandler_base::readdir (DIR *, dirent *)
1698 return ENOTDIR;
1701 long
1702 fhandler_base::telldir (DIR *)
1704 set_errno (ENOTDIR);
1705 return -1;
1708 void
1709 fhandler_base::seekdir (DIR *, long)
1711 set_errno (ENOTDIR);
1714 void
1715 fhandler_base::rewinddir (DIR *)
1717 set_errno (ENOTDIR);
1721 fhandler_base::closedir (DIR *)
1723 set_errno (ENOTDIR);
1724 return -1;
1728 fhandler_base::fchmod (mode_t mode)
1730 if (pc.is_fs_special ())
1732 fhandler_disk_file fh (pc);
1733 return fh.fchmod (mode);
1735 /* By default, just succeeds. */
1736 return 0;
1740 fhandler_base::fchown (uid_t uid, gid_t gid)
1742 if (pc.is_fs_special ())
1744 fhandler_disk_file fh (pc);
1745 return fh.fchown (uid, gid);
1747 /* By default, just succeeds. */
1748 return 0;
1752 fhandler_base::facl (int cmd, int nentries, aclent_t *aclbufp)
1754 int res = -1;
1755 switch (cmd)
1757 case SETACL:
1758 /* By default, just succeeds. */
1759 res = 0;
1760 break;
1761 case GETACL:
1762 if (!aclbufp)
1763 set_errno(EFAULT);
1764 else if (nentries < MIN_ACL_ENTRIES)
1765 set_errno (ENOSPC);
1766 else
1768 aclbufp[0].a_type = USER_OBJ;
1769 aclbufp[0].a_id = myself->uid;
1770 aclbufp[0].a_perm = (S_IRUSR | S_IWUSR) >> 6;
1771 aclbufp[1].a_type = GROUP_OBJ;
1772 aclbufp[1].a_id = myself->gid;
1773 aclbufp[1].a_perm = (S_IRGRP | S_IWGRP) >> 3;
1774 aclbufp[2].a_type = OTHER_OBJ;
1775 aclbufp[2].a_id = ILLEGAL_GID;
1776 aclbufp[2].a_perm = S_IROTH | S_IWOTH;
1777 res = MIN_ACL_ENTRIES;
1779 break;
1780 case GETACLCNT:
1781 res = MIN_ACL_ENTRIES;
1782 break;
1783 default:
1784 set_errno (EINVAL);
1785 break;
1787 return res;
1790 ssize_t
1791 fhandler_base::fgetxattr (const char *name, void *value, size_t size)
1793 set_errno (ENOTSUP);
1794 return -1;
1798 fhandler_base::fsetxattr (const char *name, const void *value, size_t size,
1799 int flags)
1801 set_errno (ENOTSUP);
1802 return -1;
1806 fhandler_base::fadvise (off_t offset, off_t length, int advice)
1808 set_errno (EINVAL);
1809 return -1;
1813 fhandler_base::fallocate (int mode, off_t offset, off_t length)
1815 return ENODEV;
1819 fhandler_base::link (const char *newpath)
1821 set_errno (EPERM);
1822 return -1;
1826 fhandler_base::utimens (const struct timespec *tvp)
1828 if (is_fs_special ())
1829 return utimens_fs (tvp);
1831 set_errno (EINVAL);
1832 return -1;
1836 fhandler_base::fsync ()
1838 if (!get_handle () || nohandle ()
1839 || (pc.isspecial () && !S_ISBLK (pc.dev.mode ())))
1841 set_errno (EINVAL);
1842 return -1;
1844 if (pc.isdir ()) /* Just succeed. */
1845 return 0;
1846 if (FlushFileBuffers (get_handle ()))
1847 return 0;
1849 /* Ignore ERROR_INVALID_FUNCTION because FlushFileBuffers() always fails
1850 with this code on raw devices which are unbuffered by default. */
1851 DWORD errcode = GetLastError();
1852 if (errcode == ERROR_INVALID_FUNCTION)
1853 return 0;
1855 __seterrno_from_win_error (errcode);
1856 return -1;
1860 fhandler_base::fpathconf (int v)
1862 int ret;
1864 switch (v)
1866 case _PC_LINK_MAX:
1867 return pc.fs_is_ntfs () || pc.fs_is_samba () || pc.fs_is_nfs ()
1868 ? LINK_MAX : 1;
1869 case _PC_MAX_CANON:
1870 if (is_tty ())
1871 return MAX_CANON;
1872 set_errno (EINVAL);
1873 break;
1874 case _PC_MAX_INPUT:
1875 if (is_tty ())
1876 return MAX_INPUT;
1877 set_errno (EINVAL);
1878 break;
1879 case _PC_NAME_MAX:
1880 /* NAME_MAX is without trailing \0 */
1881 if (!pc.isdir ())
1882 return NAME_MAX;
1883 ret = NT_MAX_PATH - strlen (get_name ()) - 2;
1884 return ret < 0 ? 0 : ret > NAME_MAX ? NAME_MAX : ret;
1885 case _PC_PATH_MAX:
1886 /* PATH_MAX is with trailing \0 */
1887 if (!pc.isdir ())
1888 return PATH_MAX;
1889 ret = NT_MAX_PATH - strlen (get_name ()) - 1;
1890 return ret < 0 ? 0 : ret > PATH_MAX ? PATH_MAX : ret;
1891 case _PC_PIPE_BUF:
1892 if (pc.isdir ()
1893 || get_device () == FH_FIFO || get_device () == FH_PIPE
1894 || get_device () == FH_PIPER || get_device () == FH_PIPEW)
1895 return PIPE_BUF;
1896 set_errno (EINVAL);
1897 break;
1898 case _PC_CHOWN_RESTRICTED:
1899 return 1;
1900 case _PC_NO_TRUNC:
1901 return 1;
1902 case _PC_VDISABLE:
1903 if (is_tty ())
1904 return _POSIX_VDISABLE;
1905 set_errno (EINVAL);
1906 break;
1907 case _PC_ASYNC_IO:
1908 return 1;
1909 case _PC_PRIO_IO:
1910 break;
1911 case _PC_SYNC_IO:
1912 return 1;
1913 case _PC_FILESIZEBITS:
1914 return FILESIZEBITS;
1915 case _PC_2_SYMLINKS:
1916 return 1;
1917 case _PC_SYMLINK_MAX:
1918 return SYMLINK_MAX;
1919 case _PC_POSIX_PERMISSIONS:
1920 case _PC_POSIX_SECURITY:
1921 if (get_device () == FH_FS)
1922 return pc.has_acls () || pc.fs_is_nfs ();
1923 set_errno (EINVAL);
1924 break;
1925 case _PC_CASE_INSENSITIVE:
1926 return !!pc.objcaseinsensitive ();
1927 default:
1928 set_errno (EINVAL);
1929 break;
1931 return -1;
1934 NTSTATUS
1935 fhandler_base::npfs_handle (HANDLE &nph)
1937 static NO_COPY SRWLOCK npfs_lock;
1938 static NO_COPY HANDLE npfs_dirh;
1940 NTSTATUS status = STATUS_SUCCESS;
1941 OBJECT_ATTRIBUTES attr;
1942 IO_STATUS_BLOCK io;
1944 /* Lockless after first call. */
1945 if (npfs_dirh)
1947 nph = npfs_dirh;
1948 return STATUS_SUCCESS;
1950 AcquireSRWLockExclusive (&npfs_lock);
1951 if (!npfs_dirh)
1953 InitializeObjectAttributes (&attr, &ro_u_npfs, 0, NULL, NULL);
1954 status = NtOpenFile (&npfs_dirh, FILE_READ_ATTRIBUTES | SYNCHRONIZE,
1955 &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
1958 ReleaseSRWLockExclusive (&npfs_lock);
1959 if (NT_SUCCESS (status))
1960 nph = npfs_dirh;
1961 return status;