lib/path: add ul_path_stat(), fix absolute paths

* add ul_path_stat()

* make sure all paths for ul_path_..() functions are always
interpreted relatively to the context directory and prefix. This is
difference between ul_path_ API and standard libc "at" functions. We
do not use any exception for absolute paths. The reason is that we
need to read from prefixed paths although application assume absolute
path (/dev/sda1 means /prefix/dev/sda1 if a /prefix is defined).

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2019-10-15 11:59:16 +02:00
parent 9ae113ca73
commit b1418ed146
2 changed files with 52 additions and 11 deletions

View File

@ -45,6 +45,7 @@ int ul_path_isopen_dirfd(struct path_cxt *pc);
char *ul_path_get_abspath(struct path_cxt *pc, char *buf, size_t bufsz, const char *path, ...)
__attribute__ ((__format__ (__printf__, 4, 5)));
int ul_path_stat(struct path_cxt *pc, struct stat *sb, const char *path);
int ul_path_access(struct path_cxt *pc, int mode, const char *path);
int ul_path_accessf(struct path_cxt *pc, int mode, const char *path, ...)
__attribute__ ((__format__ (__printf__, 3, 4)));

View File

@ -218,7 +218,7 @@ void ul_path_close_dirfd(struct path_cxt *pc)
assert(pc);
if (pc->dir_fd >= 0) {
DBG(CXT, ul_debugobj(pc, "closing dir: '%s'", pc->dir_path));
DBG(CXT, ul_debugobj(pc, "closing dir"));
close(pc->dir_fd);
pc->dir_fd = -1;
}
@ -289,19 +289,27 @@ char *ul_path_get_abspath(struct path_cxt *pc, char *buf, size_t bufsz, const ch
int ul_path_access(struct path_cxt *pc, int mode, const char *path)
{
int dir, rc;
int rc;
dir = ul_path_get_dirfd(pc);
if (dir < 0)
return dir;
if (!pc) {
rc = access(path, mode);
DBG(CXT, ul_debug("access '%s' [no context, rc=%d]", path, rc));
} else {
int dir = ul_path_get_dirfd(pc);
if (dir < 0)
return dir;
if (*path == '/')
path++;
DBG(CXT, ul_debugobj(pc, "access: '%s'", path));
rc = faccessat(dir, path, mode, 0);
if (rc && errno == ENOENT
&& pc->redirect_on_enoent
&& pc->redirect_on_enoent(pc, path, &dir) == 0)
rc = faccessat(dir, path, mode, 0);
if (rc && errno == ENOENT
&& pc->redirect_on_enoent
&& pc->redirect_on_enoent(pc, path, &dir) == 0)
rc = faccessat(dir, path, mode, 0);
DBG(CXT, ul_debugobj(pc, "access: '%s' [rc=%d]", path, rc));
}
return rc;
}
@ -317,6 +325,32 @@ int ul_path_accessf(struct path_cxt *pc, int mode, const char *path, ...)
return !p ? -errno : ul_path_access(pc, mode, p);
}
int ul_path_stat(struct path_cxt *pc, struct stat *sb, const char *path)
{
int rc;
if (!pc) {
rc = stat(path, sb);
DBG(CXT, ul_debug("stat '%s' [no context, rc=%d]", path, rc));
} else {
int dir = ul_path_get_dirfd(pc);
if (dir < 0)
return dir;
if (*path == '/')
path++;
rc = fstatat(dir, path, sb, 0);
if (rc && errno == ENOENT
&& pc->redirect_on_enoent
&& pc->redirect_on_enoent(pc, path, &dir) == 0)
rc = fstatat(dir, path, sb, 0);
DBG(CXT, ul_debugobj(pc, "stat '%s' [rc=%d]", path, rc));
}
return rc;
}
int ul_path_open(struct path_cxt *pc, int flags, const char *path)
{
int fd;
@ -330,6 +364,9 @@ int ul_path_open(struct path_cxt *pc, int flags, const char *path)
if (dir < 0)
return dir;
if (*path == '/')
path++;
fdx = fd = openat(dir, path, flags);
if (fd < 0 && errno == ENOENT
@ -503,6 +540,9 @@ ssize_t ul_path_readlink(struct path_cxt *pc, char *buf, size_t bufsiz, const ch
if (dirfd < 0)
return dirfd;
if (*path == '/')
path++;
return readlinkat(dirfd, path, buf, bufsiz);
}