1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-23 21:35:11 +03:00

xattr-util: add fgetxattrat_fake_malloc variant

This commit is contained in:
Luca Boccassi 2021-08-16 15:58:09 +01:00
parent 7a6abbe937
commit 5ce46344fd
3 changed files with 77 additions and 17 deletions

View File

@ -103,6 +103,43 @@ int fgetxattr_malloc(
} }
} }
/* Note: ret_fn should already be allocated for the usual xsprintf and /proc/self/fd/%i pattern. */
static int getxattrat_fake_prepare(
int dirfd,
const char *filename,
int flags,
char ret_fn[static STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1],
int *ret_fd) {
_cleanup_close_ int fd = -1;
assert(ret_fn);
assert(ret_fd);
/* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */
if (flags & ~(AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH))
return -EINVAL;
if (isempty(filename)) {
if (!(flags & AT_EMPTY_PATH))
return -EINVAL;
snprintf(ret_fn, STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1, "/proc/self/fd/%i", dirfd);
} else {
fd = openat(dirfd, filename, O_CLOEXEC|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
if (fd < 0)
return -errno;
snprintf(ret_fn, STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1, "/proc/self/fd/%i", fd);
}
/* Pass the FD to the caller, since in case we do openat() the filename depends on it. */
*ret_fd = TAKE_FD(fd);
return 0;
}
int fgetxattrat_fake( int fgetxattrat_fake(
int dirfd, int dirfd,
const char *filename, const char *filename,
@ -114,24 +151,11 @@ int fgetxattrat_fake(
char fn[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; char fn[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
_cleanup_close_ int fd = -1; _cleanup_close_ int fd = -1;
ssize_t l; ssize_t l;
int r;
/* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */ r = getxattrat_fake_prepare(dirfd, filename, flags, fn, &fd);
if (r < 0)
if (flags & ~(AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH)) return r;
return -EINVAL;
if (isempty(filename)) {
if (!(flags & AT_EMPTY_PATH))
return -EINVAL;
xsprintf(fn, "/proc/self/fd/%i", dirfd);
} else {
fd = openat(dirfd, filename, O_CLOEXEC|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
if (fd < 0)
return -errno;
xsprintf(fn, "/proc/self/fd/%i", fd);
}
l = getxattr(fn, attribute, value, size); l = getxattr(fn, attribute, value, size);
if (l < 0) if (l < 0)
@ -141,6 +165,24 @@ int fgetxattrat_fake(
return 0; return 0;
} }
int fgetxattrat_fake_malloc(
int dirfd,
const char *filename,
const char *attribute,
int flags,
char **value) {
char fn[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
_cleanup_close_ int fd = -1;
int r;
r = getxattrat_fake_prepare(dirfd, filename, flags, fn, &fd);
if (r < 0)
return r;
return getxattr_malloc(fn, attribute, value, false);
}
static int parse_crtime(le64_t le, usec_t *usec) { static int parse_crtime(le64_t le, usec_t *usec) {
uint64_t u; uint64_t u;

View File

@ -17,6 +17,12 @@ int fgetxattrat_fake(
void *value, size_t size, void *value, size_t size,
int flags, int flags,
size_t *ret_size); size_t *ret_size);
int fgetxattrat_fake_malloc(
int dirfd,
const char *filename,
const char *attribute,
int flags,
char **value);
int fd_setcrtime(int fd, usec_t usec); int fd_setcrtime(int fd, usec_t usec);

View File

@ -17,12 +17,15 @@
static void test_fgetxattrat_fake(void) { static void test_fgetxattrat_fake(void) {
char t[] = "/var/tmp/xattrtestXXXXXX"; char t[] = "/var/tmp/xattrtestXXXXXX";
_cleanup_free_ char *value = NULL;
_cleanup_close_ int fd = -1; _cleanup_close_ int fd = -1;
const char *x; const char *x;
char v[3]; char v[3];
int r; int r;
size_t size; size_t size;
log_info("/* %s */", __func__);
assert_se(mkdtemp(t)); assert_se(mkdtemp(t));
x = strjoina(t, "/test"); x = strjoina(t, "/test");
assert_se(touch(x) >= 0); assert_se(touch(x) >= 0);
@ -45,6 +48,13 @@ static void test_fgetxattrat_fake(void) {
r = fgetxattrat_fake(fd, "usr", "user.idontexist", v, 3, 0, &size); r = fgetxattrat_fake(fd, "usr", "user.idontexist", v, 3, 0, &size);
assert_se(r == -ENODATA || ERRNO_IS_NOT_SUPPORTED(r)); assert_se(r == -ENODATA || ERRNO_IS_NOT_SUPPORTED(r));
safe_close(fd);
fd = open(x, O_PATH|O_CLOEXEC);
assert_se(fd >= 0);
r = fgetxattrat_fake_malloc(fd, NULL, "user.foo", AT_EMPTY_PATH, &value);
assert_se(r == 3);
assert_se(streq(value, "bar"));
cleanup: cleanup:
assert_se(unlink(x) >= 0); assert_se(unlink(x) >= 0);
assert_se(rmdir(t) >= 0); assert_se(rmdir(t) >= 0);
@ -56,6 +66,8 @@ static void test_getcrtime(void) {
usec_t usec, k; usec_t usec, k;
int r; int r;
log_info("/* %s */", __func__);
assert_se(tmp_dir(&vt) >= 0); assert_se(tmp_dir(&vt) >= 0);
fd = open_tmpfile_unlinkable(vt, O_RDWR); fd = open_tmpfile_unlinkable(vt, O_RDWR);