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