Revamp acl_extended_fd/acl_extended_file to avoid open(2) call

Calling open from acl_extended_file{_nofollow} indiscriminately may hang
if the file is a FIFO.  Ultimately the FIFO implementation needs a thorough
rewrite, but for the time being we better do what stat(2) and friends do:
Just create an fhandler directly.

	* sec_posixacl.cc (__acl_extended_fh): New static function calling
	fhandler::facl.
	(acl_extended_fd): Just call __acl_extended_fh.
	(__acl_extended_file): Take just a path_conv as parameter and
	create temporary fhandler to call __acl_extended_fh.
	(acl_extended_file): Create path_conv from incoming path and
	call __acl_extended_file on it.
	(acl_extended_file_nofollow): Ditto.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2016-03-10 10:36:00 +01:00
parent 48511f3d38
commit f368589492

View File

@ -953,6 +953,22 @@ acl_error (int code)
return acl_err_txt[code - ACL_MULTI_ERROR]; return acl_err_txt[code - ACL_MULTI_ERROR];
} }
static int
__acl_extended_fh (fhandler_base *fh)
{
int ret = -1;
if (!fh->pc.has_acls ())
set_errno (ENOTSUP);
else
{
ret = fh->facl (GETACLCNT, 0, NULL);
if (ret >= 0)
ret = (ret > MIN_ACL_ENTRIES) ? 1 : 0;
}
return ret;
}
extern "C" int extern "C" int
acl_extended_fd (int fd) acl_extended_fd (int fd)
{ {
@ -961,12 +977,7 @@ acl_extended_fd (int fd)
cygheap_fdget cfd (fd); cygheap_fdget cfd (fd);
if (cfd < 0) if (cfd < 0)
__leave; __leave;
if (!cfd->pc.has_acls ()) return __acl_extended_fh (cfd);
{
set_errno (ENOTSUP);
__leave;
}
return cfd->facl (GETACLCNT, 0, NULL);
} }
__except (EBADF) {} __except (EBADF) {}
__endtry __endtry
@ -974,26 +985,45 @@ acl_extended_fd (int fd)
} }
static int static int
__acl_extended_file (const char *path_p, mode_t follow) __acl_extended_file (path_conv &pc)
{ {
int fd = open (path_p, O_RDONLY | O_CLOEXEC | follow); int ret = -1;
if (fd < 0)
return -1; __try
int ret = acl_extended_fd (fd); {
close (fd); if (pc.error)
set_errno (pc.error);
else if (!pc.exists ())
set_errno (ENOENT);
else
{
fhandler_base *fh;
if (!(fh = build_fh_pc (pc)))
__leave;
ret = __acl_extended_fh (fh);
delete fh;
}
}
__except (EFAULT) {}
__endtry
return ret; return ret;
} }
extern "C" int extern "C" int
acl_extended_file (const char *path_p) acl_extended_file (const char *path_p)
{ {
return __acl_extended_file (path_p, 0); path_conv pc (path_p, PC_SYM_FOLLOW | PC_POSIX | PC_KEEP_HANDLE,
stat_suffixes);
return __acl_extended_file (pc);
} }
extern "C" int extern "C" int
acl_extended_file_nofollow (const char *path_p) acl_extended_file_nofollow (const char *path_p)
{ {
return __acl_extended_file (path_p, O_NOFOLLOW); path_conv pc (path_p, PC_SYM_NOFOLLOW | PC_POSIX | PC_KEEP_HANDLE,
stat_suffixes);
return __acl_extended_file (pc);
} }
extern "C" acl_t extern "C" acl_t