diff options
author | Andreas Gruenbacher <andreas.gruenbacher@gmail.com> | 2015-04-15 14:35:13 +0200 |
---|---|---|
committer | Andreas Gruenbacher <andreas.gruenbacher@gmail.com> | 2015-04-15 14:40:56 +0200 |
commit | e5a7637edc68c189b3309d901175ae722f76400e (patch) | |
tree | 4385595363b88a0a0aeecf7c7987ada23e33b0da | |
parent | 7921157890d07858d092f4003ca4c6bae9fd2c38 (diff) | |
download | attr-e5a7637edc68c189b3309d901175ae722f76400e.tar.gz |
Add {list,get,set,remove}xattrat() library functions
Right now, these functions use the normal *xattr() and f*xattr() system calls
where possible. Were both a directory file descriptor != AT_FDCWD and a
non-empty path is specified, the file is opened with openat(O_PATH) resulting
in a file descriptor, and the *xattr() system calls are used on
"/proc/self/fd/%d" for that file descriptor. (The O_PATH file descriptor itself
is not usable in the f*xattr() syscalls right now.)
These functions should probably be system calls instead, or at least they
should be provided by glibc.
-rw-r--r-- | include/libattr.h | 5 | ||||
-rw-r--r-- | libattr/Makemodule.am | 4 | ||||
-rw-r--r-- | libattr/attr_copy_check.c | 1 | ||||
-rw-r--r-- | libattr/getxattrat.c | 31 | ||||
-rw-r--r-- | libattr/listxattrat.c | 30 | ||||
-rw-r--r-- | libattr/removexattrat.c | 30 | ||||
-rw-r--r-- | libattr/setxattrat.c | 31 |
7 files changed, 132 insertions, 0 deletions
diff --git a/include/libattr.h b/include/libattr.h index 81ebc1b..1c1d854 100644 --- a/include/libattr.h +++ b/include/libattr.h @@ -39,6 +39,11 @@ extern int attr_copy_check_permissions(const char *, struct error_context *); extern int attr_copy_action(const char *, struct error_context *); +extern ssize_t listxattrat(int, const char *, char *, size_t); +extern ssize_t getxattrat(int, const char *, const char *, void *, size_t); +extern ssize_t setxattrat(int, const char *, const char *, void *, size_t, int); +extern ssize_t removexattrat(int, const char *, const char *); + #ifdef __cplusplus } #endif diff --git a/libattr/Makemodule.am b/libattr/Makemodule.am index a5a0cdd..9f7b8c7 100644 --- a/libattr/Makemodule.am +++ b/libattr/Makemodule.am @@ -14,6 +14,10 @@ libattr_la_SOURCES = \ libattr/attr_copy_check.c \ libattr/attr_copy_fd.c \ libattr/attr_copy_file.c \ + libattr/listxattrat.c \ + libattr/getxattrat.c \ + libattr/setxattrat.c \ + libattr/removexattrat.c \ libattr/libattr.c \ libattr/libattr.h libattr_la_CFLAGS = -include libattr/libattr.h diff --git a/libattr/attr_copy_check.c b/libattr/attr_copy_check.c index ca0ac72..203f74d 100644 --- a/libattr/attr_copy_check.c +++ b/libattr/attr_copy_check.c @@ -18,6 +18,7 @@ /* Copy extended attributes between files - default check callback */ #include <string.h> +#include <sys/types.h> #include "error_context.h" #include "attr/libattr.h" diff --git a/libattr/getxattrat.c b/libattr/getxattrat.c new file mode 100644 index 0000000..e5a70c3 --- /dev/null +++ b/libattr/getxattrat.c @@ -0,0 +1,31 @@ +#define _GNU_SOURCE +#include <sys/types.h> +#include <sys/xattr.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <limits.h> + +#include "attr/libattr.h" + +ssize_t getxattrat(int dirfd, const char *path, const char *name, + void *value, size_t size) +{ + if (dirfd == AT_FDCWD) + return getxattr(path, name, value, size); + else if (path && !*path) + return fgetxattr(dirfd, name, value, size); + else { + char fd_path[10 * sizeof(int) * CHAR_BIT / 33 + 3]; + ssize_t ret; + int fd; + + fd = openat(dirfd, path, O_PATH | O_CLOEXEC); + if (fd == -1) + return -1; + sprintf(fd_path, "/proc/self/fd/%d", fd); + ret = getxattr(fd_path, name, value, size); + close(fd); + return ret; + } +} diff --git a/libattr/listxattrat.c b/libattr/listxattrat.c new file mode 100644 index 0000000..4612dc7 --- /dev/null +++ b/libattr/listxattrat.c @@ -0,0 +1,30 @@ +#define _GNU_SOURCE +#include <sys/types.h> +#include <sys/xattr.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <limits.h> + +#include "attr/libattr.h" + +ssize_t listxattrat(int dirfd, const char *path, char *list, size_t size) +{ + if (dirfd == AT_FDCWD) + return listxattr(path, list, size); + else if (path && !*path) + return flistxattr(dirfd, list, size); + else { + char fd_path[10 * sizeof(int) * CHAR_BIT / 33 + 3]; + ssize_t ret; + int fd; + + fd = openat(dirfd, path, O_PATH | O_CLOEXEC); + if (fd == -1) + return -1; + sprintf(fd_path, "/proc/self/fd/%d", fd); + ret = listxattr(fd_path, list, size); + close(fd); + return ret; + } +} diff --git a/libattr/removexattrat.c b/libattr/removexattrat.c new file mode 100644 index 0000000..b795de9 --- /dev/null +++ b/libattr/removexattrat.c @@ -0,0 +1,30 @@ +#define _GNU_SOURCE +#include <sys/types.h> +#include <sys/xattr.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <limits.h> + +#include "attr/libattr.h" + +ssize_t removexattrat(int dirfd, const char *path, const char *name) +{ + if (dirfd == AT_FDCWD) + return removexattr(path, name); + else if (path && !*path) + return fremovexattr(dirfd, name); + else { + char fd_path[10 * sizeof(int) * CHAR_BIT / 33 + 3]; + ssize_t ret; + int fd; + + fd = openat(dirfd, path, O_PATH | O_CLOEXEC); + if (fd == -1) + return -1; + sprintf(fd_path, "/proc/self/fd/%d", fd); + ret = removexattr(fd_path, name); + close(fd); + return ret; + } +} diff --git a/libattr/setxattrat.c b/libattr/setxattrat.c new file mode 100644 index 0000000..8f82dbe --- /dev/null +++ b/libattr/setxattrat.c @@ -0,0 +1,31 @@ +#define _GNU_SOURCE +#include <sys/types.h> +#include <sys/xattr.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <limits.h> + +#include "attr/libattr.h" + +ssize_t setxattrat(int dirfd, const char *path, const char *name, + void *value, size_t size, int flags) +{ + if (dirfd == AT_FDCWD) + return setxattr(path, name, value, size, flags); + else if (path && !*path) + return fsetxattr(dirfd, name, value, size, flags); + else { + char fd_path[10 * sizeof(int) * CHAR_BIT / 33 + 3]; + ssize_t ret; + int fd; + + fd = openat(dirfd, path, O_PATH | O_CLOEXEC); + if (fd == -1) + return -1; + sprintf(fd_path, "/proc/self/fd/%d", fd); + ret = setxattr(fd_path, name, value, size, flags); + close(fd); + return ret; + } +} |