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:
parent
7a6abbe937
commit
5ce46344fd
@ -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 dirfd,
|
||||
const char *filename,
|
||||
@ -114,24 +151,11 @@ int fgetxattrat_fake(
|
||||
char fn[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
|
||||
_cleanup_close_ int fd = -1;
|
||||
ssize_t l;
|
||||
int r;
|
||||
|
||||
/* 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;
|
||||
|
||||
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);
|
||||
}
|
||||
r = getxattrat_fake_prepare(dirfd, filename, flags, fn, &fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
l = getxattr(fn, attribute, value, size);
|
||||
if (l < 0)
|
||||
@ -141,6 +165,24 @@ int fgetxattrat_fake(
|
||||
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) {
|
||||
uint64_t u;
|
||||
|
||||
|
@ -17,6 +17,12 @@ int fgetxattrat_fake(
|
||||
void *value, size_t size,
|
||||
int flags,
|
||||
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);
|
||||
|
||||
|
@ -17,12 +17,15 @@
|
||||
|
||||
static void test_fgetxattrat_fake(void) {
|
||||
char t[] = "/var/tmp/xattrtestXXXXXX";
|
||||
_cleanup_free_ char *value = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
const char *x;
|
||||
char v[3];
|
||||
int r;
|
||||
size_t size;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
assert_se(mkdtemp(t));
|
||||
x = strjoina(t, "/test");
|
||||
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);
|
||||
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:
|
||||
assert_se(unlink(x) >= 0);
|
||||
assert_se(rmdir(t) >= 0);
|
||||
@ -56,6 +66,8 @@ static void test_getcrtime(void) {
|
||||
usec_t usec, k;
|
||||
int r;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
assert_se(tmp_dir(&vt) >= 0);
|
||||
|
||||
fd = open_tmpfile_unlinkable(vt, O_RDWR);
|
||||
|
Loading…
Reference in New Issue
Block a user