* devices.in (dev_storage): Map /dev/zero and /dev/full to \Device\Null.

* devices.cc: Regenerate.
	* dtable.h (struct dtable): Make fhandler_base friend, rather
	than fhandler_disk_file.
	* fhandler.cc (fhandler_base::open_with_arch): Create unique id.
	(fhandler_base::cleanup): Call del_my_locks.
	(fhandler_base::fcntl): Handle F_GETLK, F_SETLK and F_SETLKW.
	* fhandler.h (fhandler_base::get_dev): Return real device number.
	(fhandler_base::set_unique_id): New inline method.
	(fhandler_disk_file::lock): Drop declaration.
	(fhandler_disk_file::get_dev): New method, return pc.fs_serial_number.
	(fhandler_dev_zero::open): Drop declaration.
	* fhandler_disk_file.cc (fhandler_disk_file::close): Move
	del_my_locks call to fhandler_base::open_with_arch.
	(fhandler_disk_file::fcntl): Move handling of locking commands to
	fhandler_base::fcntl.
	(fhandler_base::open_fs): Drop call to NtAllocateLocallyUniqueId.
	* fhandler_zero.cc (fhandler_dev_zero::open): Remove so that default
	fhandler_base::open is used to open \Device\Null.
	* flock.cc (fixup_lockf_after_exec): Finding a single fhandler is
	enough here.
	(fhandler_base::lock): Replace fhandler_disk_file::lock.  Refuse to lock
	nohandle devices.  Handle read/write test using POSIX flags.  Explain
	why.  Never fail on SEEK_CUR or SEEK_END, rather assume position 0,
	just as Linux.
	* net.cc (fdsock): Create unique id.
This commit is contained in:
Corinna Vinschen 2013-10-24 09:41:17 +00:00
parent 72a386373e
commit 95ff6fc6da
11 changed files with 109 additions and 64 deletions

View File

@ -1,3 +1,32 @@
2013-10-24 Corinna Vinschen <corinna@vinschen.de>
* devices.in (dev_storage): Map /dev/zero and /dev/full to \Device\Null.
* devices.cc: Regenerate.
* dtable.h (struct dtable): Make fhandler_base friend, rather
than fhandler_disk_file.
* fhandler.cc (fhandler_base::open_with_arch): Create unique id.
(fhandler_base::cleanup): Call del_my_locks.
(fhandler_base::fcntl): Handle F_GETLK, F_SETLK and F_SETLKW.
* fhandler.h (fhandler_base::get_dev): Return real device number.
(fhandler_base::set_unique_id): New inline method.
(fhandler_disk_file::lock): Drop declaration.
(fhandler_disk_file::get_dev): New method, return pc.fs_serial_number.
(fhandler_dev_zero::open): Drop declaration.
* fhandler_disk_file.cc (fhandler_disk_file::close): Move
del_my_locks call to fhandler_base::open_with_arch.
(fhandler_disk_file::fcntl): Move handling of locking commands to
fhandler_base::fcntl.
(fhandler_base::open_fs): Drop call to NtAllocateLocallyUniqueId.
* fhandler_zero.cc (fhandler_dev_zero::open): Remove so that default
fhandler_base::open is used to open \Device\Null.
* flock.cc (fixup_lockf_after_exec): Finding a single fhandler is
enough here.
(fhandler_base::lock): Replace fhandler_disk_file::lock. Refuse to lock
nohandle devices. Handle read/write test using POSIX flags. Explain
why. Never fail on SEEK_CUR or SEEK_END, rather assume position 0,
just as Linux.
* net.cc (fdsock): Create unique id.
2013-10-23 Corinna Vinschen <corinna@vinschen.de>
* include /cygwin/config.h (_READ_WRITE_BUFSIZE_TYPE): Define.

View File

@ -243,7 +243,7 @@ const _RDATA device dev_storage[] =
{"/dev/fd13", BRACK(FHDEV(DEV_FLOPPY_MAJOR, 13)), "\\Device\\Floppy13", exists_ntdev, S_IFBLK, true},
{"/dev/fd14", BRACK(FHDEV(DEV_FLOPPY_MAJOR, 14)), "\\Device\\Floppy14", exists_ntdev, S_IFBLK, true},
{"/dev/fd15", BRACK(FHDEV(DEV_FLOPPY_MAJOR, 15)), "\\Device\\Floppy15", exists_ntdev, S_IFBLK, true},
{"/dev/full", BRACK(FH_FULL), "/dev/full", exists, S_IFCHR, true},
{"/dev/full", BRACK(FH_FULL), "\\Device\\Null", exists_ntdev, S_IFCHR, true},
{"/dev/kmsg", BRACK(FH_KMSG), "\\Device\\MailSlot\\cygwin\\dev\\kmsg", exists_ntdev, S_IFCHR, true},
{"/dev/nst0", BRACK(FHDEV(DEV_TAPE_MAJOR, 128)), "\\Device\\Tape0", exists_ntdev, S_IFBLK, true},
{"/dev/nst1", BRACK(FHDEV(DEV_TAPE_MAJOR, 129)), "\\Device\\Tape1", exists_ntdev, S_IFBLK, true},
@ -2715,7 +2715,7 @@ const _RDATA device dev_storage[] =
{"/dev/ttyS63", BRACK(FHDEV(DEV_SERIAL_MAJOR, 63)), "\\??\\COM64", exists_ntdev, S_IFCHR, true},
{"/dev/urandom", BRACK(FH_URANDOM), "/dev/urandom", exists, S_IFCHR, true},
{"/dev/windows", BRACK(FH_WINDOWS), "/dev/windows", exists, S_IFCHR, true},
{"/dev/zero", BRACK(FH_ZERO), "/dev/zero", exists, S_IFCHR, true},
{"/dev/zero", BRACK(FH_ZERO), "\\Device\\Null", exists_ntdev, S_IFCHR, true},
{":fifo", BRACK(FH_FIFO), "/dev/fifo", exists_internal, S_IFCHR, false},
{":pipe", BRACK(FH_PIPE), "/dev/pipe", exists_internal, S_IFCHR, false},
{":ptym0", BRACK(FHDEV(DEV_PTYM_MAJOR, 0)), "/dev/ptym0", exists_internal, S_IFCHR, false},

View File

@ -152,8 +152,8 @@ const device dev_error_storage =
"/dev/conin", BRACK(FH_CONIN), "/dev/conin", exists_console, S_IFCHR
"/dev/conout", BRACK(FH_CONOUT), "/dev/conout", exists_console, S_IFCHR
"/dev/null", BRACK(FH_NULL), "\\Device\\Null", exists_ntdev, S_IFCHR
"/dev/zero", BRACK(FH_ZERO), "/dev/zero", exists, S_IFCHR
"/dev/full", BRACK(FH_FULL), "/dev/full", exists, S_IFCHR
"/dev/zero", BRACK(FH_ZERO), "\\Device\\Null", exists_ntdev, S_IFCHR
"/dev/full", BRACK(FH_FULL), "\\Device\\Null", exists_ntdev, S_IFCHR
"/dev/random", BRACK(FH_RANDOM), "/dev/random", exists, S_IFCHR
"/dev/urandom", BRACK(FH_URANDOM), "/dev/urandom", exists, S_IFCHR, =urandom_dev
"/dev/clipboard", BRACK(FH_CLIPBOARD), "/dev/clipboard", exists, S_IFCHR

View File

@ -90,7 +90,7 @@ public:
friend void dtable_init ();
friend void __stdcall close_all_files (bool);
friend int dup_finish (int, int, int);
friend class fhandler_disk_file;
friend class fhandler_base;
friend class cygheap_fdmanip;
friend class cygheap_fdget;
friend class cygheap_fdnew;

View File

@ -498,6 +498,12 @@ fhandler_base::open_with_arch (int flags, mode_t mode)
}
close_on_exec (flags & O_CLOEXEC);
/* A unique ID is necessary to recognize fhandler entries which are
duplicated by dup(2) or fork(2). This is used in BSD flock calls
to identify the descriptor. Skip nohandle fhandlers since advisory
locking is unusable for those anyway. */
if (!nohandle ())
set_unique_id ();
return res;
}
@ -1112,6 +1118,10 @@ fhandler_base::close_with_arch ()
void
fhandler_base::cleanup ()
{
/* Delete all POSIX locks on the file. Delete all flock locks on the
file if this is the last reference to this file. */
if (unique_id)
del_my_locks (on_close);
}
int
@ -1366,6 +1376,15 @@ int fhandler_base::fcntl (int cmd, intptr_t arg)
}
res = 0;
break;
case F_GETLK:
case F_SETLK:
case F_SETLKW:
{
struct flock *fl = (struct flock *) arg;
fl->l_type &= F_RDLCK | F_WRLCK | F_UNLCK;
res = mandatory_locking () ? mand_lock (cmd, fl) : lock (cmd, fl);
}
break;
default:
set_errno (EINVAL);
res = -1;

View File

@ -296,7 +296,7 @@ class fhandler_base
bool has_attribute (DWORD x) const {return pc.has_attribute (x);}
const char *get_name () const { return pc.normalized_path; }
const char *get_win32_name () { return pc.get_win32 (); }
dev_t get_dev () { return pc.fs_serial_number (); }
virtual dev_t get_dev () { return get_device (); }
ino_t get_ino () { return ino ?: ino = hash_path_name (0, pc.get_nt_native_path ()); }
long long get_unique_id () const { return unique_id; }
/* Returns name used for /proc/<pid>/fd in buf. */
@ -312,6 +312,7 @@ class fhandler_base
int open_with_arch (int, mode_t = 0);
virtual int open (int, mode_t);
virtual void open_setup (int flags) { return; }
void set_unique_id () { NtAllocateLocallyUniqueId ((PLUID) &unique_id); }
int close_with_arch ();
virtual int close ();
@ -979,7 +980,6 @@ class fhandler_disk_file: public fhandler_base
int fcntl (int cmd, intptr_t);
int dup (fhandler_base *child, int);
void fixup_after_fork (HANDLE parent);
int lock (int, struct flock *);
int mand_lock (int, struct flock *);
bool isdevice () const { return false; }
int __reg2 fstat (struct stat *buf);
@ -1012,6 +1012,7 @@ class fhandler_disk_file: public fhandler_base
ssize_t __reg3 pwrite (void *, size_t, off_t);
fhandler_disk_file (void *) {}
dev_t get_dev () { return pc.fs_serial_number (); }
void copyto (fhandler_base *x)
{
@ -1618,7 +1619,6 @@ class fhandler_dev_zero: public fhandler_base
{
public:
fhandler_dev_zero ();
int open (int flags, mode_t mode = 0);
ssize_t __stdcall write (const void *ptr, size_t len);
void __reg3 read (void *ptr, size_t& len);
off_t lseek (off_t offset, int whence);

View File

@ -1401,9 +1401,6 @@ fhandler_disk_file::close ()
/* Close extra pread/pwrite handle, if it exists. */
if (prw_handle)
NtClose (prw_handle);
/* Delete all POSIX locks on the file. Delete all flock locks on the
file if this is the last reference to this file. */
del_my_locks (on_close);
return fhandler_base::close ();
}
@ -1414,20 +1411,11 @@ fhandler_disk_file::fcntl (int cmd, intptr_t arg)
switch (cmd)
{
case F_LCK_MANDATORY:
case F_LCK_MANDATORY: /* Mandatory locking only works on files. */
mandatory_locking (!!arg);
need_fork_fixup (true);
res = 0;
break;
case F_GETLK:
case F_SETLK:
case F_SETLKW:
{
struct flock *fl = (struct flock *) arg;
fl->l_type &= F_RDLCK | F_WRLCK | F_UNLCK;
res = mandatory_locking () ? mand_lock (cmd, fl) : lock (cmd, fl);
}
break;
default:
res = fhandler_base::fcntl (cmd, arg);
break;
@ -1487,9 +1475,6 @@ fhandler_base::open_fs (int flags, mode_t mode)
}
ino = pc.get_ino_by_handle (get_handle ());
/* A unique ID is necessary to recognize fhandler entries which are
duplicated by dup(2) or fork(2). */
NtAllocateLocallyUniqueId ((PLUID) &unique_id);
out:
syscall_printf ("%d = fhandler_disk_file::open(%S, %y)", res,

View File

@ -1,6 +1,6 @@
/* fhandler_dev_zero.cc: code to access /dev/zero
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009 Red Hat, Inc.
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2013 Red Hat, Inc.
Written by DJ Delorie (dj@cygnus.com)
@ -21,15 +21,6 @@ fhandler_dev_zero::fhandler_dev_zero ()
{
}
int
fhandler_dev_zero::open (int flags, mode_t)
{
set_flags ((flags & ~O_TEXT) | O_BINARY);
nohandle (true);
set_open_status ();
return 1;
}
ssize_t __stdcall
fhandler_dev_zero::write (const void *, size_t len)
{

View File

@ -454,7 +454,7 @@ fixup_lockf_after_exec ()
while (cfd.next () >= 0)
if (cfd->get_dev () == node->i_dev
&& cfd->get_ino () == node->i_ino
&& ++cnt > 1)
&& ++cnt >= 1)
break;
if (cnt == 0)
{
@ -919,14 +919,7 @@ static void lf_wakelock (lockf_t *, HANDLE);
of mandatory locks using the Windows mandatory locking functions, see the
fhandler_disk_file::mand_lock method at the end of this file. */
int
fhandler_base::lock (int, struct flock *)
{
set_errno (EINVAL);
return -1;
}
int
fhandler_disk_file::lock (int a_op, struct flock *fl)
fhandler_base::lock (int a_op, struct flock *fl)
{
off_t start, end, oadd;
int error = 0;
@ -934,6 +927,13 @@ fhandler_disk_file::lock (int a_op, struct flock *fl)
short a_flags = fl->l_type & (F_POSIX | F_FLOCK);
short type = fl->l_type & (F_RDLCK | F_WRLCK | F_UNLCK);
if (nohandle ())
{
set_errno (EINVAL);
debug_printf ("Locking on nohandle device, return EINVAL.");
return -1;
}
if (!a_flags)
a_flags = F_POSIX; /* default */
if (a_op == F_SETLKW)
@ -952,16 +952,24 @@ fhandler_disk_file::lock (int a_op, struct flock *fl)
been opened with a specific open mode, in contrast to POSIX locks
which require that a file is opened for reading to place a read
lock and opened for writing to place a write lock. */
if ((a_flags & F_POSIX) && !(get_access () & GENERIC_READ))
/* CV 2013-10-22: Test POSIX R/W mode flags rather than Windows R/W
access flags. The reason is that POSIX mode flags are set for
all types of fhandlers, while Windows access flags are only set
for most of the actual Windows device backed fhandlers. */
if ((a_flags & F_POSIX)
&& ((get_flags () & O_ACCMODE) == O_WRONLY))
{
system_printf ("get_access() == %x", get_access ());
set_errno (EBADF);
return -1;
}
break;
case F_WRLCK:
/* See above comment. */
if ((a_flags & F_POSIX) && !(get_access () & GENERIC_WRITE))
if ((a_flags & F_POSIX)
&& ((get_flags () & O_ACCMODE) == O_RDONLY))
{
system_printf ("get_access() == %x", get_access ());
set_errno (EBADF);
return -1;
}
@ -982,29 +990,32 @@ fhandler_disk_file::lock (int a_op, struct flock *fl)
case SEEK_CUR:
if ((start = lseek (0, SEEK_CUR)) == ILLEGAL_SEEK)
return -1;
start = 0;
break;
case SEEK_END:
{
NTSTATUS status;
IO_STATUS_BLOCK io;
FILE_STANDARD_INFORMATION fsi;
if (get_device () != FH_FS)
start = 0;
else
{
NTSTATUS status;
IO_STATUS_BLOCK io;
FILE_STANDARD_INFORMATION fsi;
status = NtQueryInformationFile (get_handle (), &io, &fsi, sizeof fsi,
FileStandardInformation);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
return -1;
}
if (fl->l_start > 0 && fsi.EndOfFile.QuadPart > OFF_MAX - fl->l_start)
{
set_errno (EOVERFLOW);
return -1;
}
start = fsi.EndOfFile.QuadPart + fl->l_start;
}
status = NtQueryInformationFile (get_handle (), &io, &fsi, sizeof fsi,
FileStandardInformation);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
return -1;
}
if (fl->l_start > 0 && fsi.EndOfFile.QuadPart > OFF_MAX - fl->l_start)
{
set_errno (EOVERFLOW);
return -1;
}
start = fsi.EndOfFile.QuadPart + fl->l_start;
}
break;
default:

View File

@ -636,6 +636,11 @@ fdsock (cygheap_fdmanip& fd, const device *dev, SOCKET soc)
system_printf ("getsockopt(SO_SNDBUF) failed, %u", WSAGetLastError ());
}
/* A unique ID is necessary to recognize fhandler entries which are
duplicated by dup(2) or fork(2). This is used in BSD flock calls
to identify the descriptor. */
((fhandler_socket *) fd)->set_unique_id ();
return true;
}

View File

@ -7,6 +7,11 @@ What changed:
- Slightly improve randomness of /dev/random emulation.
- Allow to use advisory locking on any device which is backed by an OS handle.
Right now this excludes /dev/clipboard, /dev/dsp, /dev/random, /dev/urandom,
as well as almost all virtual files under /proc.
Bug fixes:
----------