* dtable.cc (dtable::build_fhandler_from_name): Set some fhandler
data on sockets to evaluate AF_LOCAL sockets correctly. (dtable::build_fhandler): Set unit number on sockets. * fhandler.h (fhandler_socket): Add unit number. (fhandler_socket::get_unit): New method. * fhandler_socket.cc (fhandler_socket::fhandler_socket): Set unit number. (fhandler_socket::fstat): Reorganize to return more Linux-like values. * net.cc: include ctype.h. (fdsock): Set unit number when building fhandler. * path.cc (path_conv::check): Set device type to FH_SOCKET if file is a AF_UNIX socket. (get_devn): Evaluate unit for virtual socket devices. (win32_device_name): Set windows path for sockets to unix_path with just backslashes to keep the different names. * syscalls.cc (fstat64): Don't override st_ino, st_dev and st_rdev for sockets. (stat_worker): Ditto. From Pierre Humblet: * autoload.cc (AccessCheck): Add. (DuplicateToken): Add. * security.h (check_file_access): Declare. * syscalls.cc (access): Convert path to Windows, check existence and readonly attribute. Call check_file_access instead of acl_access. * security.cc (check_file_access): Create. * sec_acl (acl_access): Delete.
This commit is contained in:
		@@ -1,3 +1,35 @@
 | 
			
		||||
2003-02-21  Corinna Vinschen  <corinna@vinschen.de>
 | 
			
		||||
 | 
			
		||||
	* dtable.cc (dtable::build_fhandler_from_name): Set some fhandler
 | 
			
		||||
	data on sockets to evaluate AF_LOCAL sockets correctly.
 | 
			
		||||
	(dtable::build_fhandler): Set unit number on sockets.
 | 
			
		||||
	* fhandler.h (fhandler_socket): Add unit number.
 | 
			
		||||
	(fhandler_socket::get_unit): New method.
 | 
			
		||||
	* fhandler_socket.cc (fhandler_socket::fhandler_socket): Set unit
 | 
			
		||||
	number.
 | 
			
		||||
	(fhandler_socket::fstat): Reorganize to return more Linux-like
 | 
			
		||||
	values.
 | 
			
		||||
	* net.cc: include ctype.h.
 | 
			
		||||
	(fdsock): Set unit number when building fhandler.
 | 
			
		||||
	* path.cc (path_conv::check): Set device type to FH_SOCKET if file
 | 
			
		||||
	is a AF_UNIX socket.
 | 
			
		||||
	(get_devn): Evaluate unit for virtual socket devices.
 | 
			
		||||
	(win32_device_name): Set windows path for sockets to unix_path with
 | 
			
		||||
	just backslashes to keep the different names.
 | 
			
		||||
	* syscalls.cc (fstat64): Don't override st_ino, st_dev and st_rdev
 | 
			
		||||
	for sockets.
 | 
			
		||||
	(stat_worker): Ditto.
 | 
			
		||||
 | 
			
		||||
2003-02-21  Pierre Humblet  <pierre.humblet@ieee.org>
 | 
			
		||||
 | 
			
		||||
	* autoload.cc (AccessCheck): Add.
 | 
			
		||||
	(DuplicateToken): Add.
 | 
			
		||||
	* security.h (check_file_access): Declare.
 | 
			
		||||
	* syscalls.cc (access): Convert path to Windows, check existence
 | 
			
		||||
	and readonly attribute. Call check_file_access instead of acl_access.
 | 
			
		||||
	* security.cc (check_file_access): Create.
 | 
			
		||||
	* sec_acl (acl_access): Delete.
 | 
			
		||||
 | 
			
		||||
2003-02-19  Christopher Faylor  <cgf@redhat.com>
 | 
			
		||||
 | 
			
		||||
	* fhandler.cc (fhandler_base::open): Move some filesystem specific
 | 
			
		||||
 
 | 
			
		||||
@@ -307,6 +307,7 @@ wsock_init ()
 | 
			
		||||
LoadDLLprime (wsock32, wsock_init)
 | 
			
		||||
LoadDLLprime (ws2_32, wsock_init)
 | 
			
		||||
 | 
			
		||||
LoadDLLfunc (AccessCheck, 32, advapi32)
 | 
			
		||||
LoadDLLfunc (AddAccessAllowedAce, 16, advapi32)
 | 
			
		||||
LoadDLLfunc (AddAccessDeniedAce, 16, advapi32)
 | 
			
		||||
LoadDLLfunc (AddAce, 20, advapi32)
 | 
			
		||||
@@ -318,6 +319,7 @@ LoadDLLfuncEx (CryptAcquireContextA, 20, advapi32, 1)
 | 
			
		||||
LoadDLLfuncEx (CryptGenRandom, 12, advapi32, 1)
 | 
			
		||||
LoadDLLfuncEx (CryptReleaseContext, 8, advapi32, 1)
 | 
			
		||||
LoadDLLfunc (DeregisterEventSource, 4, advapi32)
 | 
			
		||||
LoadDLLfunc (DuplicateToken, 12, advapi32)
 | 
			
		||||
LoadDLLfuncEx (DuplicateTokenEx, 24, advapi32, 1)
 | 
			
		||||
LoadDLLfunc (EqualSid, 8, advapi32)
 | 
			
		||||
LoadDLLfunc (GetAce, 12, advapi32)
 | 
			
		||||
 
 | 
			
		||||
@@ -299,9 +299,15 @@ dtable::build_fhandler_from_name (int fd, const char *name, HANDLE handle,
 | 
			
		||||
  if (!pc.exists () && handle)
 | 
			
		||||
    pc.fillin (handle);
 | 
			
		||||
 | 
			
		||||
  fhandler_base *fh = build_fhandler (fd, pc.get_devn (),
 | 
			
		||||
				      pc.return_and_clear_normalized_path (),
 | 
			
		||||
  char *posix_path = pc.return_and_clear_normalized_path ();
 | 
			
		||||
  fhandler_base *fh = build_fhandler (fd, pc.get_devn (), posix_path,
 | 
			
		||||
				      pc, pc.get_unitn ());
 | 
			
		||||
  if (pc.issocket ()) /* Only true for files pretending an AF_LOCAL socket. */
 | 
			
		||||
    {
 | 
			
		||||
      fhandler_socket * fhs = (fhandler_socket *) fh;
 | 
			
		||||
      fhs->set_addr_family (AF_LOCAL);
 | 
			
		||||
      fhs->set_sun_path (posix_path);
 | 
			
		||||
    }
 | 
			
		||||
  return fh;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -352,7 +358,7 @@ dtable::build_fhandler (int fd, DWORD dev, char *unix_name,
 | 
			
		||||
	fh = cnew (fhandler_pipe) (dev);
 | 
			
		||||
	break;
 | 
			
		||||
      case FH_SOCKET:
 | 
			
		||||
	if ((fh = cnew (fhandler_socket) ()))
 | 
			
		||||
	if ((fh = cnew (fhandler_socket) (unit)))
 | 
			
		||||
	  inc_need_fixup_before ();
 | 
			
		||||
	break;
 | 
			
		||||
      case FH_DISK:
 | 
			
		||||
 
 | 
			
		||||
@@ -385,12 +385,14 @@ class fhandler_socket: public fhandler_base
 | 
			
		||||
  struct _WSAPROTOCOL_INFOA *prot_info_ptr;
 | 
			
		||||
  char *sun_path;
 | 
			
		||||
  int had_connect_or_listen;
 | 
			
		||||
  int unit;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  fhandler_socket ();
 | 
			
		||||
  fhandler_socket (int unit);
 | 
			
		||||
  ~fhandler_socket ();
 | 
			
		||||
  int get_socket () { return (int) get_handle(); }
 | 
			
		||||
  fhandler_socket * is_socket () { return this; }
 | 
			
		||||
  int get_unit () { return unit; }
 | 
			
		||||
 | 
			
		||||
  bool saw_shutdown_read () const {return FHISSETF (SHUTRD);}
 | 
			
		||||
  bool saw_shutdown_write () const {return FHISSETF (SHUTWR);}
 | 
			
		||||
 
 | 
			
		||||
@@ -94,8 +94,8 @@ get_inet_addr (const struct sockaddr *in, int inlen,
 | 
			
		||||
/**********************************************************************/
 | 
			
		||||
/* fhandler_socket */
 | 
			
		||||
 | 
			
		||||
fhandler_socket::fhandler_socket ()
 | 
			
		||||
  : fhandler_base (FH_SOCKET), sun_path (NULL)
 | 
			
		||||
fhandler_socket::fhandler_socket (int nunit)
 | 
			
		||||
  : fhandler_base (FH_SOCKET), unit (nunit), sun_path (NULL)
 | 
			
		||||
{
 | 
			
		||||
  set_need_fork_fixup ();
 | 
			
		||||
  prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF,
 | 
			
		||||
@@ -309,12 +309,47 @@ fhandler_socket::dup (fhandler_base *child)
 | 
			
		||||
int __stdcall
 | 
			
		||||
fhandler_socket::fstat (struct __stat64 *buf, path_conv *pc)
 | 
			
		||||
{
 | 
			
		||||
  int res = fhandler_base::fstat (buf, pc);
 | 
			
		||||
  int res;
 | 
			
		||||
  if (get_addr_family () == AF_LOCAL && get_sun_path ())
 | 
			
		||||
    {
 | 
			
		||||
      path_conv spc (get_sun_path (),
 | 
			
		||||
                     PC_SYM_NOFOLLOW | PC_NULLEMPTY | PC_FULL | PC_POSIX,
 | 
			
		||||
		     NULL);
 | 
			
		||||
      fhandler_base *fh = cygheap->fdtab.build_fhandler (-1, FH_DISK,
 | 
			
		||||
      							 get_sun_path (),
 | 
			
		||||
							 spc, 0);
 | 
			
		||||
      if (fh)
 | 
			
		||||
        {
 | 
			
		||||
	  res = fh->fstat (buf, &spc);
 | 
			
		||||
	  /* Faking Linux like values on top of the file specific values. */
 | 
			
		||||
	  if (get_socket_type ()) /* fstat() */
 | 
			
		||||
	    {
 | 
			
		||||
	      buf->st_dev = 0;
 | 
			
		||||
	      buf->st_mode |= S_IRWXU | S_IRWXG | S_IRWXO;
 | 
			
		||||
	      buf->st_ino = (ino_t) get_handle ();
 | 
			
		||||
	    }
 | 
			
		||||
	  buf->st_rdev = buf->st_size = buf->st_blocks = 0;
 | 
			
		||||
	  return res;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  res = fhandler_base::fstat (buf, pc);
 | 
			
		||||
  if (!res)
 | 
			
		||||
    {
 | 
			
		||||
      buf->st_mode &= ~_IFMT;
 | 
			
		||||
      buf->st_mode |= _IFSOCK;
 | 
			
		||||
      buf->st_ino = (ino_t) get_handle ();
 | 
			
		||||
      if (get_socket_type ()) /* fstat */
 | 
			
		||||
        {
 | 
			
		||||
	  buf->st_ino = (ino_t) get_handle ();
 | 
			
		||||
	  buf->st_mode &= ~S_IFMT;
 | 
			
		||||
	  buf->st_mode |= S_IFSOCK;
 | 
			
		||||
	}
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
	  path_conv spc ("/dev", PC_SYM_NOFOLLOW | PC_NULLEMPTY, NULL);
 | 
			
		||||
	  buf->st_dev = spc.volser ();
 | 
			
		||||
	  buf->st_ino = (ino_t) get_namehash ();
 | 
			
		||||
	  buf->st_mode &= ~S_IRWXO;
 | 
			
		||||
	  buf->st_rdev = (get_device () << 16) | get_unit ();
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
  return res;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ details. */
 | 
			
		||||
 | 
			
		||||
#include "winsup.h"
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/un.h>
 | 
			
		||||
#include <iphlpapi.h>
 | 
			
		||||
@@ -521,8 +522,9 @@ fdsock (int &fd, const char *name, SOCKET soc)
 | 
			
		||||
  else
 | 
			
		||||
    debug_printf ("not setting socket inheritance since winsock2_active %d",
 | 
			
		||||
		  winsock2_active);
 | 
			
		||||
  fhandler_socket *fh =
 | 
			
		||||
    (fhandler_socket *) cygheap->fdtab.build_fhandler (fd, FH_SOCKET, name);
 | 
			
		||||
  fhandler_socket *fh = (fhandler_socket *)
 | 
			
		||||
  	cygheap->fdtab.build_fhandler (fd, FH_SOCKET, name, NULL,
 | 
			
		||||
				       tolower (name[5]) - 'a');
 | 
			
		||||
  if (!fh)
 | 
			
		||||
    return NULL;
 | 
			
		||||
  fh->set_io_handle ((HANDLE) soc);
 | 
			
		||||
 
 | 
			
		||||
@@ -799,10 +799,8 @@ out:
 | 
			
		||||
	  set_has_buggy_open (strcmp (fs.name, "SUNWNFS") == 0);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
#if 0
 | 
			
		||||
  if (issocket ())
 | 
			
		||||
    devn = FH_SOCKET;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (!(opt & PC_FULL))
 | 
			
		||||
    {
 | 
			
		||||
@@ -954,7 +952,10 @@ get_devn (const char *name, int &unit)
 | 
			
		||||
    devn = FH_PIPEW;
 | 
			
		||||
  else if (deveq ("tcp") || deveq ("udp") || deveq ("streamsocket")
 | 
			
		||||
	   || deveq ("dgsocket"))
 | 
			
		||||
    devn = FH_SOCKET;
 | 
			
		||||
    {
 | 
			
		||||
      devn = FH_SOCKET;
 | 
			
		||||
      unit = tolower (*name) - 'a';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return devn;
 | 
			
		||||
}
 | 
			
		||||
@@ -1118,6 +1119,12 @@ win32_device_name (const char *src_path, char *win32_path,
 | 
			
		||||
    return false;
 | 
			
		||||
  switch (devn)
 | 
			
		||||
    {
 | 
			
		||||
      case FH_SOCKET:
 | 
			
		||||
	char *c;
 | 
			
		||||
	strcpy (win32_path, src_path);
 | 
			
		||||
	while (c = strchr (win32_path, '/'))
 | 
			
		||||
	  *c = '\\';
 | 
			
		||||
        break;
 | 
			
		||||
      case FH_RANDOM:
 | 
			
		||||
	__small_sprintf (win32_path, devfmt, unit == 8 ? "" : "u");
 | 
			
		||||
	break;
 | 
			
		||||
 
 | 
			
		||||
@@ -413,69 +413,6 @@ getacl (const char *file, DWORD attr, int nentries, __aclent32_t *aclbufp)
 | 
			
		||||
  return pos;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
acl_access (const char *path, int flags)
 | 
			
		||||
{
 | 
			
		||||
  __aclent32_t acls[MAX_ACL_ENTRIES];
 | 
			
		||||
  int cnt;
 | 
			
		||||
 | 
			
		||||
  if ((cnt = acl32 (path, GETACL, MAX_ACL_ENTRIES, acls)) < 1)
 | 
			
		||||
    return -1;
 | 
			
		||||
 | 
			
		||||
  /* Only check existence. */
 | 
			
		||||
  if (!(flags & (R_OK | W_OK | X_OK)))
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < cnt; ++i)
 | 
			
		||||
    {
 | 
			
		||||
      switch (acls[i].a_type)
 | 
			
		||||
	{
 | 
			
		||||
	case USER_OBJ:
 | 
			
		||||
	case USER:
 | 
			
		||||
	  if (acls[i].a_id != myself->uid)
 | 
			
		||||
	    {
 | 
			
		||||
	      /*
 | 
			
		||||
	       * Check if user is a NT group:
 | 
			
		||||
	       * Take SID from passwd, search SID in token groups
 | 
			
		||||
	       */
 | 
			
		||||
	      cygsid owner;
 | 
			
		||||
	      struct passwd *pw;
 | 
			
		||||
 | 
			
		||||
	      if ((pw = internal_getpwuid (acls[i].a_id)) != NULL
 | 
			
		||||
		  && owner.getfrompw (pw)
 | 
			
		||||
		  && internal_getgroups (0, NULL, &owner) > 0)
 | 
			
		||||
		break;
 | 
			
		||||
	      continue;
 | 
			
		||||
	    }
 | 
			
		||||
	  break;
 | 
			
		||||
	case GROUP_OBJ:
 | 
			
		||||
	case GROUP:
 | 
			
		||||
	  if (acls[i].a_id != myself->gid)
 | 
			
		||||
            {
 | 
			
		||||
	      cygsid group;
 | 
			
		||||
	      struct __group32 *gr = NULL;
 | 
			
		||||
 | 
			
		||||
	      if ((gr = internal_getgrgid (acls[i].a_id)) != NULL
 | 
			
		||||
		  && group.getfromgr (gr)
 | 
			
		||||
		  && internal_getgroups (0, NULL, &group) > 0)
 | 
			
		||||
		break;
 | 
			
		||||
	      continue;
 | 
			
		||||
	    }
 | 
			
		||||
	  break;
 | 
			
		||||
	case OTHER_OBJ:
 | 
			
		||||
	  break;
 | 
			
		||||
	default:
 | 
			
		||||
	  continue;
 | 
			
		||||
	}
 | 
			
		||||
      if ((!(flags & R_OK) || (acls[i].a_perm & S_IROTH))
 | 
			
		||||
	  && (!(flags & W_OK) || (acls[i].a_perm & S_IWOTH))
 | 
			
		||||
	  && (!(flags & X_OK) || (acls[i].a_perm & S_IXOTH)))
 | 
			
		||||
	return 0;
 | 
			
		||||
    }
 | 
			
		||||
  set_errno (EACCES);
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
int
 | 
			
		||||
acl_worker (const char *path, int cmd, int nentries, __aclent32_t *aclbufp,
 | 
			
		||||
 
 | 
			
		||||
@@ -1918,3 +1918,54 @@ set_file_attribute (int use_ntsec, const char *file, int attribute)
 | 
			
		||||
  return set_file_attribute (use_ntsec, file,
 | 
			
		||||
			     myself->uid, myself->gid, attribute);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
check_file_access (const char *fn, int flags)
 | 
			
		||||
{
 | 
			
		||||
  int ret = -1;
 | 
			
		||||
  char sd_buf[4096];
 | 
			
		||||
  DWORD sd_size = sizeof sd_buf;
 | 
			
		||||
  PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf;
 | 
			
		||||
  HANDLE hToken, hIToken;
 | 
			
		||||
  BOOL status;
 | 
			
		||||
  char pbuf[sizeof (PRIVILEGE_SET) + 3 * sizeof (LUID_AND_ATTRIBUTES)];
 | 
			
		||||
  DWORD desired = 0, granted, plength = sizeof pbuf;
 | 
			
		||||
  static GENERIC_MAPPING NO_COPY mapping = { FILE_GENERIC_READ,
 | 
			
		||||
					     FILE_GENERIC_WRITE,
 | 
			
		||||
					     FILE_GENERIC_EXECUTE,
 | 
			
		||||
					     FILE_ALL_ACCESS };
 | 
			
		||||
  if (read_sd (fn, psd, &sd_size) <= 0)
 | 
			
		||||
    goto done;
 | 
			
		||||
 | 
			
		||||
  if (cygheap->user.issetuid ())
 | 
			
		||||
    hToken = cygheap->user.token;
 | 
			
		||||
  else if (!OpenProcessToken (hMainProc, TOKEN_DUPLICATE, &hToken))
 | 
			
		||||
    {
 | 
			
		||||
      __seterrno ();
 | 
			
		||||
      goto done;
 | 
			
		||||
    }
 | 
			
		||||
  if (!(status = DuplicateToken (hToken, SecurityIdentification, &hIToken)))
 | 
			
		||||
    __seterrno ();
 | 
			
		||||
  if (hToken != cygheap->user.token)
 | 
			
		||||
    CloseHandle (hToken);
 | 
			
		||||
  if (!status)
 | 
			
		||||
    goto done;
 | 
			
		||||
 | 
			
		||||
  if (flags & R_OK)
 | 
			
		||||
    desired |= FILE_READ_DATA;
 | 
			
		||||
  if (flags & W_OK)
 | 
			
		||||
    desired |= FILE_WRITE_DATA;
 | 
			
		||||
  if (flags & X_OK)
 | 
			
		||||
    desired |= FILE_EXECUTE;
 | 
			
		||||
  if (!AccessCheck (psd, hIToken, desired, &mapping,
 | 
			
		||||
		    (PPRIVILEGE_SET) pbuf, &plength, &granted, &status))
 | 
			
		||||
    __seterrno ();
 | 
			
		||||
  else if (!status)
 | 
			
		||||
    set_errno (EACCES);
 | 
			
		||||
  else
 | 
			
		||||
    ret = 0;
 | 
			
		||||
  CloseHandle (hIToken);
 | 
			
		||||
 done:
 | 
			
		||||
  debug_printf ("flags %x, ret %d", flags, ret);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -225,6 +225,7 @@ LONG __stdcall read_sd(const char *file, PSECURITY_DESCRIPTOR sd_buf, LPDWORD sd
 | 
			
		||||
LONG __stdcall write_sd(const char *file, PSECURITY_DESCRIPTOR sd_buf, DWORD sd_size);
 | 
			
		||||
BOOL __stdcall add_access_allowed_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit);
 | 
			
		||||
BOOL __stdcall add_access_denied_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit);
 | 
			
		||||
int __stdcall check_file_access (const char *, int);
 | 
			
		||||
 | 
			
		||||
void set_security_attribute (int attribute, PSECURITY_ATTRIBUTES psa,
 | 
			
		||||
			     void *sd_buf, DWORD sd_buf_size);
 | 
			
		||||
 
 | 
			
		||||
@@ -1016,7 +1016,7 @@ fstat64 (int fd, struct __stat64 *buf)
 | 
			
		||||
      path_conv pc (cfd->get_win32_name (), PC_SYM_NOFOLLOW);
 | 
			
		||||
      memset (buf, 0, sizeof (struct __stat64));
 | 
			
		||||
      res = cfd->fstat (buf, &pc);
 | 
			
		||||
      if (!res)
 | 
			
		||||
      if (!res && cfd->get_device () != FH_SOCKET)
 | 
			
		||||
	{
 | 
			
		||||
	  if (!buf->st_ino)
 | 
			
		||||
	    buf->st_ino = hash_path_name (0, cfd->get_win32_name ());
 | 
			
		||||
@@ -1106,7 +1106,7 @@ stat_worker (const char *name, struct __stat64 *buf, int nofollow,
 | 
			
		||||
		    pc, (DWORD) real_path);
 | 
			
		||||
      memset (buf, 0, sizeof (*buf));
 | 
			
		||||
      res = fh->fstat (buf, pc);
 | 
			
		||||
      if (!res)
 | 
			
		||||
      if (!res && fh->get_device () != FH_SOCKET)
 | 
			
		||||
	{
 | 
			
		||||
	  if (!buf->st_ino)
 | 
			
		||||
	    buf->st_ino = hash_path_name (0, fh->get_win32_name ());
 | 
			
		||||
@@ -1163,8 +1163,6 @@ cygwin_lstat (const char *name, struct __stat32 *buf)
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern int acl_access (const char *, int);
 | 
			
		||||
 | 
			
		||||
extern "C" int
 | 
			
		||||
access (const char *fn, int flags)
 | 
			
		||||
{
 | 
			
		||||
@@ -1176,11 +1174,33 @@ access (const char *fn, int flags)
 | 
			
		||||
      return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (allow_ntsec)
 | 
			
		||||
    return acl_access (fn, flags);
 | 
			
		||||
  path_conv real_path (fn, PC_SYM_FOLLOW | PC_FULL, stat_suffixes);
 | 
			
		||||
  if (real_path.error)
 | 
			
		||||
    {
 | 
			
		||||
      set_errno (real_path.error);
 | 
			
		||||
      return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!real_path.exists ())
 | 
			
		||||
    {
 | 
			
		||||
      set_errno (ENOENT);
 | 
			
		||||
      return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!(flags & (R_OK | W_OK | X_OK)))
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
  if (real_path.has_attribute (FILE_ATTRIBUTE_READONLY) && (flags & W_OK))
 | 
			
		||||
    {
 | 
			
		||||
      set_errno (EACCES);
 | 
			
		||||
      return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (real_path.has_acls () && allow_ntsec)
 | 
			
		||||
    return check_file_access (real_path, flags);
 | 
			
		||||
 | 
			
		||||
  struct __stat64 st;
 | 
			
		||||
  int r = stat_worker (fn, &st, 0);
 | 
			
		||||
  int r = stat_worker (real_path, &st, 0);
 | 
			
		||||
  if (r)
 | 
			
		||||
    return -1;
 | 
			
		||||
  r = -1;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user