summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Gruenbacher <andreas.gruenbacher@gmail.com>2015-04-15 14:35:13 +0200
committerAndreas Gruenbacher <andreas.gruenbacher@gmail.com>2015-04-15 14:40:56 +0200
commite5a7637edc68c189b3309d901175ae722f76400e (patch)
tree4385595363b88a0a0aeecf7c7987ada23e33b0da
parent7921157890d07858d092f4003ca4c6bae9fd2c38 (diff)
downloadattr-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.h5
-rw-r--r--libattr/Makemodule.am4
-rw-r--r--libattr/attr_copy_check.c1
-rw-r--r--libattr/getxattrat.c31
-rw-r--r--libattr/listxattrat.c30
-rw-r--r--libattr/removexattrat.c30
-rw-r--r--libattr/setxattrat.c31
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;
+ }
+}