Return unique inode numbers when calling stat/fstat on pipes and IP sockets
* fhandler.h (class fhandler_base): Convert unique_id to int64_t.
        (fhandler_base::set_ino): New protected inline method.
        (fhandler_base::get_unique_id): Convert to int64_t.
        (fhandler_base::set_unique_id): New inline method taking int64_t.
        (fhandler_pipe::fstat): Declare.
        (fhandler_pipe::init): Take extra parameter.
        (fhandler_pipe::create): Ditto.
        * fhandler_socket.cc (fhandler_socket::init_events): Set inode number
        to serial number.
        (fhandler_socket::fstat): Set device to DEV_TCP_MAJOR.  Create st_ino
        from get_ino.
        * include/cygwin/signal.h (struct _sigcommune): Replace
        _si_pipe_fhandler with _si_pipe_unique_id.
        * pinfo.h (_pinfo::pipe_fhandler): Take unique id instead of HANDLE.
        * pinfo.cc (commune_process): Accommodate change to _si_pipe_unique_id.
        (_pinfo::commune_request): Ditto.
        (_pinfo::pipe_fhandler): Ditto.
        * pipe.cc (fhandler_pipe::init): Take unique id as argument and set
        inode number and unique_id from there.
        (fhandler_pipe::open): Rework to find any matching pipe from unique
        id in filename.
        (fhandler_pipe::get_proc_fd_name): Create filename using inode number.
        (fhandler_pipe::create): Generate and return unique id from process pid
        and pipe_unique_id.  In outer method, call init with additional unique
        id as parameter.
        (fhandler_pipe::fstat): New method.
        (pipe_worker): Accommodate using 64 bit inode number in filename.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
			
			
This commit is contained in:
		
							parent
							
								
									20ddde2f55
								
							
						
					
					
						commit
						a10d969231
					
				|  | @ -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) | ||||
|  |  | |||
|  | @ -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; | ||||
| 	} | ||||
|  |  | |||
|  | @ -188,7 +188,7 @@ struct _sigcommune | |||
|   __extension__ union | ||||
|   { | ||||
|     int _si_fd; | ||||
|     void *_si_pipe_fhandler; | ||||
|     int64_t _si_pipe_unique_id; | ||||
|     char *_si_str; | ||||
|   }; | ||||
| }; | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
|  |  | |||
|  | @ -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 &); | ||||
|  |  | |||
|  | @ -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; | ||||
|     } | ||||
|   if (!fh) | ||||
|     { | ||||
|       /* 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))) | ||||
|     { | ||||
|       set_errno (EACCES); | ||||
|       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; | ||||
|     } | ||||
| 
 | ||||
|  | @ -394,6 +415,21 @@ fhandler_pipe::ioctl (unsigned int cmd, void *p) | |||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
|  | @ -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]; | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue