summaryrefslogtreecommitdiffstats
path: root/winsup
diff options
context:
space:
mode:
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/fhandler.h11
-rw-r--r--winsup/cygwin/fhandler_socket.cc5
-rw-r--r--winsup/cygwin/include/cygwin/signal.h2
-rw-r--r--winsup/cygwin/pinfo.cc10
-rw-r--r--winsup/cygwin/pinfo.h2
-rw-r--r--winsup/cygwin/pipe.cc100
-rw-r--r--winsup/cygwin/release/2.4.03
7 files changed, 88 insertions, 45 deletions
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index adb84414e..8bcf83f0e 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -182,8 +182,9 @@ class fhandler_base
size_t rabuflen;
/* Used for advisory file locking. See flock.cc. */
- long long unique_id;
+ int64_t unique_id;
void del_my_locks (del_lock_called_from);
+ void set_ino (ino_t i) { ino = i; }
HANDLE read_state;
@@ -304,7 +305,7 @@ class fhandler_base
const char *get_win32_name () { return pc.get_win32 (); }
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; }
+ int64_t get_unique_id () const { return unique_id; }
/* Returns name used for /proc/<pid>/fd in buf. */
virtual char *get_proc_fd_name (char *buf);
@@ -319,6 +320,7 @@ class fhandler_base
int open_null (int flags);
virtual int open (int, mode_t);
virtual void open_setup (int flags);
+ void set_unique_id (int64_t u) { unique_id = u; }
void set_unique_id () { NtAllocateLocallyUniqueId ((PLUID) &unique_id); }
int close_with_arch ();
@@ -731,13 +733,14 @@ public:
int open (int flags, mode_t mode = 0);
int dup (fhandler_base *child, int);
int ioctl (unsigned int cmd, void *);
+ int __reg2 fstat (struct stat *buf);
int __reg2 fstatvfs (struct statvfs *buf);
int __reg3 fadvise (off_t, off_t, int);
int __reg3 ftruncate (off_t, bool);
- int init (HANDLE, DWORD, mode_t);
+ int init (HANDLE, DWORD, mode_t, int64_t);
static int create (fhandler_pipe *[2], unsigned, int);
static DWORD create (LPSECURITY_ATTRIBUTES, HANDLE *, HANDLE *, DWORD,
- const char *, DWORD);
+ const char *, DWORD, int64_t *unique_id = NULL);
fhandler_pipe (void *) {}
void copyto (fhandler_base *x)
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 21bc7316e..094cc65e8 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -594,6 +594,7 @@ fhandler_socket::init_events ()
InterlockedIncrement (&socket_serial_number);
if (!new_serial_number) /* 0 is reserved for global mutex */
InterlockedIncrement (&socket_serial_number);
+ set_ino (new_serial_number);
RtlInitUnicodeString (&uname, sock_shared_name (name, new_serial_number));
InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT | OBJ_OPENIF,
get_session_parent_dir (),
@@ -937,8 +938,8 @@ fhandler_socket::fstat (struct stat *buf)
res = fhandler_base::fstat (buf);
if (!res)
{
- buf->st_dev = 0;
- buf->st_ino = (ino_t) ((uintptr_t) get_handle ());
+ buf->st_dev = FHDEV (DEV_TCP_MAJOR, 0);
+ buf->st_ino = (ino_t) get_ino ();
buf->st_mode = S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO;
buf->st_size = 0;
}
diff --git a/winsup/cygwin/include/cygwin/signal.h b/winsup/cygwin/include/cygwin/signal.h
index 350a91219..04ddb69d7 100644
--- a/winsup/cygwin/include/cygwin/signal.h
+++ b/winsup/cygwin/include/cygwin/signal.h
@@ -188,7 +188,7 @@ struct _sigcommune
__extension__ union
{
int _si_fd;
- void *_si_pipe_fhandler;
+ int64_t _si_pipe_unique_id;
char *_si_str;
};
};
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index d0b4cd9a4..be32cfd59 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -622,11 +622,11 @@ commune_process (void *arg)
case PICOM_PIPE_FHANDLER:
{
sigproc_printf ("processing PICOM_FDS");
- HANDLE hdl = si._si_commune._si_pipe_fhandler;
+ int64_t unique_id = si._si_commune._si_pipe_unique_id;
unsigned int n = 0;
cygheap_fdenum cfd;
while (cfd.next () >= 0)
- if (cfd->get_handle () == hdl)
+ if (cfd->get_unique_id () == unique_id)
{
fhandler_pipe *fh = cfd;
n = sizeof *fh;
@@ -701,7 +701,7 @@ _pinfo::commune_request (__uint32_t code, ...)
switch (code)
{
case PICOM_PIPE_FHANDLER:
- si._si_commune._si_pipe_fhandler = va_arg (args, HANDLE);
+ si._si_commune._si_pipe_unique_id = va_arg (args, int64_t);
break;
case PICOM_FD:
@@ -781,13 +781,13 @@ out:
}
fhandler_pipe *
-_pinfo::pipe_fhandler (HANDLE hdl, size_t &n)
+_pinfo::pipe_fhandler (int64_t unique_id, size_t &n)
{
if (!this || !pid)
return NULL;
if (pid == myself->pid)
return NULL;
- commune_result cr = commune_request (PICOM_PIPE_FHANDLER, hdl);
+ commune_result cr = commune_request (PICOM_PIPE_FHANDLER, unique_id);
n = cr.n;
return (fhandler_pipe *) cr.s;
}
diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h
index 1d6a72cfa..65a9e89ff 100644
--- a/winsup/cygwin/pinfo.h
+++ b/winsup/cygwin/pinfo.h
@@ -103,7 +103,7 @@ public:
commune_result commune_request (__uint32_t, ...);
bool alive ();
- fhandler_pipe *pipe_fhandler (HANDLE, size_t &);
+ fhandler_pipe *pipe_fhandler (int64_t, size_t &);
char *fd (int fd, size_t &);
char *fds (size_t &);
char *root (size_t &);
diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc
index 945c8fc24..4ec4fa48e 100644
--- a/winsup/cygwin/pipe.cc
+++ b/winsup/cygwin/pipe.cc
@@ -31,7 +31,7 @@ fhandler_pipe::fhandler_pipe ()
}
int
-fhandler_pipe::init (HANDLE f, DWORD a, mode_t mode)
+fhandler_pipe::init (HANDLE f, DWORD a, mode_t mode, int64_t uniq_id)
{
/* FIXME: Have to clean this up someday
FIXME: Do we have to check for both !get_win32_name() and
@@ -54,6 +54,8 @@ fhandler_pipe::init (HANDLE f, DWORD a, mode_t mode)
a &= ~FILE_CREATE_PIPE_INSTANCE;
fhandler_base::init (f, a, mode);
close_on_exec (mode & O_CLOEXEC);
+ set_ino (uniq_id);
+ set_unique_id (uniq_id | !!(mode & GENERIC_WRITE));
if (opened_properly)
setup_overlapped ();
else
@@ -66,27 +68,33 @@ extern "C" int sscanf (const char *, const char *, ...);
int
fhandler_pipe::open (int flags, mode_t mode)
{
- HANDLE proc, pipe_hdl, nio_hdl = NULL;
- fhandler_pipe *fh = NULL;
+ HANDLE proc, nio_hdl = NULL;
+ int64_t uniq_id;
+ fhandler_pipe *fh = NULL, *fhr = NULL, *fhw = NULL;
size_t size;
int pid, rwflags = (flags & O_ACCMODE);
bool inh;
+ bool got_one = false;
- sscanf (get_name (), "/proc/%d/fd/pipe:[%lu]",
- &pid, (unsigned long *) &pipe_hdl);
+ sscanf (get_name (), "/proc/%d/fd/pipe:[%lld]",
+ &pid, (long long *) &uniq_id);
if (pid == myself->pid)
{
cygheap_fdenum cfd (true);
while (cfd.next () >= 0)
{
- if (cfd->get_handle () != pipe_hdl)
+ /* Windows doesn't allow to copy a pipe HANDLE with another access
+ mode. So we check for read and write side of pipe and try to
+ find the one matching the requested access mode. */
+ if (cfd->get_unique_id () == uniq_id)
+ got_one = true;
+ else if (cfd->get_unique_id () == uniq_id + 1)
+ got_one = true;
+ else
continue;
if ((rwflags == O_RDONLY && !(cfd->get_access () & GENERIC_READ))
|| (rwflags == O_WRONLY && !(cfd->get_access () & GENERIC_WRITE)))
- {
- set_errno (EACCES);
- return 0;
- }
+ continue;
cfd->copyto (this);
set_io_handle (NULL);
pc.reset_conv_handle ();
@@ -94,7 +102,9 @@ fhandler_pipe::open (int flags, mode_t mode)
return 1;
return 0;
}
- set_errno (ENOENT);
+ /* Found the pipe but access mode didn't match? EACCES.
+ Otherwise ENOENT */
+ set_errno (got_one ? EACCES : ENOENT);
return 0;
}
@@ -109,27 +119,30 @@ fhandler_pipe::open (int flags, mode_t mode)
__seterrno ();
return 0;
}
- if (!(fh = p->pipe_fhandler (pipe_hdl, size)) || !size)
+ fhr = p->pipe_fhandler (uniq_id, size);
+ if (fhr && rwflags == O_RDONLY)
+ fh = fhr;
+ else
{
- set_errno (ENOENT);
- goto out;
+ fhw = p->pipe_fhandler (uniq_id + 1, size);
+ if (fhw && rwflags == O_WRONLY)
+ fh = fhw;
}
- /* Too bad, but Windows only allows the same access mode when dup'ing
- the pipe. */
- if ((rwflags == O_RDONLY && !(fh->get_access () & GENERIC_READ))
- || (rwflags == O_WRONLY && !(fh->get_access () & GENERIC_WRITE)))
+ if (!fh)
{
- set_errno (EACCES);
+ /* Too bad, but Windows only allows the same access mode when dup'ing
+ the pipe. */
+ set_errno (fhr || fhw ? EACCES : ENOENT);
goto out;
}
inh = !(flags & O_CLOEXEC);
- if (!DuplicateHandle (proc, pipe_hdl, GetCurrentProcess (), &nio_hdl,
- 0, inh, DUPLICATE_SAME_ACCESS))
+ if (!DuplicateHandle (proc, fh->get_handle (), GetCurrentProcess (),
+ &nio_hdl, 0, inh, DUPLICATE_SAME_ACCESS))
{
__seterrno ();
goto out;
}
- init (nio_hdl, fh->get_access (), mode & O_TEXT ?: O_BINARY);
+ init (nio_hdl, fh->get_access (), mode & O_TEXT ?: O_BINARY, fh->get_ino ());
cfree (fh);
CloseHandle (proc);
return 1;
@@ -168,7 +181,7 @@ fhandler_pipe::ftruncate (off_t length, bool allow_truncate)
char *
fhandler_pipe::get_proc_fd_name (char *buf)
{
- __small_sprintf (buf, "pipe:[%lu]", get_handle ());
+ __small_sprintf (buf, "pipe:[%D]", get_ino ());
return buf;
}
@@ -199,7 +212,8 @@ fhandler_pipe::dup (fhandler_base *child, int flags)
unlike CreatePipe, which returns a bool for success or failure. */
DWORD
fhandler_pipe::create (LPSECURITY_ATTRIBUTES sa_ptr, PHANDLE r, PHANDLE w,
- DWORD psize, const char *name, DWORD open_mode)
+ DWORD psize, const char *name, DWORD open_mode,
+ int64_t *unique_id)
{
/* Default to error. */
if (r)
@@ -241,8 +255,12 @@ fhandler_pipe::create (LPSECURITY_ATTRIBUTES sa_ptr, PHANDLE r, PHANDLE w,
{
static volatile ULONG pipe_unique_id;
if (!name)
- __small_sprintf (pipename + len, "pipe-%p",
- InterlockedIncrement ((LONG *) &pipe_unique_id));
+ {
+ LONG id = InterlockedIncrement ((LONG *) &pipe_unique_id);
+ __small_sprintf (pipename + len, "pipe-%p", id);
+ if (unique_id)
+ *unique_id = ((int64_t) id << 32 | GetCurrentProcessId ());
+ }
debug_printf ("name %s, size %u, mode %s", pipename, psize,
(pipe_mode & PIPE_TYPE_MESSAGE)
@@ -341,8 +359,9 @@ fhandler_pipe::create (fhandler_pipe *fhs[2], unsigned psize, int mode)
HANDLE r, w;
SECURITY_ATTRIBUTES *sa = sec_none_cloexec (mode);
int res = -1;
+ int64_t unique_id;
- int ret = create (sa, &r, &w, psize, NULL, FILE_FLAG_OVERLAPPED);
+ int ret = create (sa, &r, &w, psize, NULL, FILE_FLAG_OVERLAPPED, &unique_id);
if (ret)
__seterrno_from_win_error (ret);
else if ((fhs[0] = (fhandler_pipe *) build_fh_dev (*piper_dev)) == NULL)
@@ -358,8 +377,10 @@ fhandler_pipe::create (fhandler_pipe *fhs[2], unsigned psize, int mode)
else
{
mode |= mode & O_TEXT ?: O_BINARY;
- fhs[0]->init (r, FILE_CREATE_PIPE_INSTANCE | GENERIC_READ, mode);
- fhs[1]->init (w, FILE_CREATE_PIPE_INSTANCE | GENERIC_WRITE, mode);
+ fhs[0]->init (r, FILE_CREATE_PIPE_INSTANCE | GENERIC_READ, mode,
+ unique_id);
+ fhs[1]->init (w, FILE_CREATE_PIPE_INSTANCE | GENERIC_WRITE, mode,
+ unique_id);
res = 0;
}
@@ -395,6 +416,21 @@ fhandler_pipe::ioctl (unsigned int cmd, void *p)
}
int __reg2
+fhandler_pipe::fstat (struct stat *buf)
+{
+ int ret = fhandler_base::fstat (buf);
+ if (!ret)
+ {
+ buf->st_dev = FH_PIPE;
+ /* Don't use get_ino, it doesn't return 0 but a hash instead. */
+ if (!(buf->st_ino = get_unique_id ()))
+ sscanf (get_name (), "/proc/%*d/fd/pipe:[%lld]",
+ (long long *) &buf->st_ino);
+ }
+ return ret;
+}
+
+int __reg2
fhandler_pipe::fstatvfs (struct statvfs *sfs)
{
set_errno (EBADF);
@@ -410,10 +446,10 @@ pipe_worker (int filedes[2], unsigned int psize, int mode)
{
cygheap_fdnew fdin;
cygheap_fdnew fdout (fdin, false);
- char buf[sizeof ("/dev/fd/pipe:[2147483647]")];
- __small_sprintf (buf, "/dev/fd/pipe:[%d]", (int) fdin);
+ char buf[sizeof ("/dev/fd/pipe:[9223372036854775807]")];
+ __small_sprintf (buf, "/dev/fd/pipe:[%D]", fhs[0]->get_ino ());
fhs[0]->pc.set_posix (buf);
- __small_sprintf (buf, "pipe:[%d]", (int) fdout);
+ __small_sprintf (buf, "pipe:[%D]", fhs[1]->get_ino ());
fhs[1]->pc.set_posix (buf);
fdin = fhs[0];
fdout = fhs[1];
diff --git a/winsup/cygwin/release/2.4.0 b/winsup/cygwin/release/2.4.0
index ed035af5c..6247fb8f4 100644
--- a/winsup/cygwin/release/2.4.0
+++ b/winsup/cygwin/release/2.4.0
@@ -81,3 +81,6 @@ Bug Fixes
- *Always* zero out descriptor arrays when returning from select due to
timeout, per POSIX.
Addresses: https://cygwin.com/ml/cygwin/2015-12/msg00332.html
+
+- Return unique inode numbers when calling stat/fstat on pipes and IP sockets.
+ Addresses: https://cygwin.com/ml/cygwin/2015-12/msg00310.html