master
c 132 lines 3.45 KB
Raw
1 /*
2 * 9p utilities (FreeBSD Implementation)
3 *
4 * This work is licensed under the terms of the GNU GPL, version 2 or later.
5 * See the COPYING file in the top-level directory.
6 */
7
8 /*
9 * Not so fast! You might want to read the 9p developer docs first:
10 * https://wiki.qemu.org/Documentation/9p
11 */
12
13 #include "qemu/osdep.h"
14 #include "qemu/xattr.h"
15 #include "9p-util.h"
16
17 static int mangle_xattr_name(const char **namep)
18 {
19 const char *name = *namep;
20
21 /*
22 * ZFS forbids attributes in starting with "user." or "system.".
23 */
24 if (strncmp(name, "system.", 7) == 0) {
25 *namep = name + 7;
26 return EXTATTR_NAMESPACE_SYSTEM;
27 }
28 if (strncmp(name, "user.", 5) == 0) {
29 *namep = name + 5;
30 }
31 return EXTATTR_NAMESPACE_USER;
32 }
33
34 ssize_t fgetxattr(int fd, const char *name, void *value, size_t size)
35 {
36 int namespace;
37
38 namespace = mangle_xattr_name(&name);
39 return extattr_get_fd(fd, namespace, name, value, size);
40 }
41
42 ssize_t fgetxattrat_nofollow(int dirfd, const char *filename, const char *name,
43 void *value, size_t size)
44 {
45 ssize_t ret;
46 int fd, namespace;
47
48 fd = openat_file(dirfd, filename,
49 O_RDONLY | O_PATH_9P_UTIL | O_NOFOLLOW, 0);
50 if (fd == -1) {
51 return -1;
52 }
53 namespace = mangle_xattr_name(&name);
54 ret = extattr_get_fd(fd, namespace, name, value, size);
55 close_preserve_errno(fd);
56 return ret;
57 }
58
59 ssize_t flistxattrat_nofollow(int dirfd, const char *filename,
60 char *list, size_t size)
61 {
62 ssize_t ret;
63 int fd;
64
65 fd = openat_file(dirfd, filename,
66 O_RDONLY | O_PATH_9P_UTIL | O_NOFOLLOW, 0);
67 if (fd == -1) {
68 return -1;
69 }
70 ret = extattr_list_fd(fd, EXTATTR_NAMESPACE_USER, list, size);
71 close_preserve_errno(fd);
72 return ret;
73 }
74
75 ssize_t fremovexattrat_nofollow(int dirfd, const char *filename,
76 const char *name)
77 {
78 int fd, namespace, ret;
79
80 fd = openat_file(dirfd, filename,
81 O_RDONLY | O_PATH_9P_UTIL | O_NOFOLLOW, 0);
82 if (fd == -1) {
83 return -1;
84 }
85 namespace = mangle_xattr_name(&name);
86 ret = extattr_delete_fd(fd, namespace, name);
87 close_preserve_errno(fd);
88 return ret;
89 }
90
91 int fsetxattrat_nofollow(int dirfd, const char *filename, const char *name,
92 void *value, size_t size, int flags)
93 {
94 ssize_t ret;
95 int fd, namespace;
96
97 namespace = mangle_xattr_name(&name);
98 if (flags == (XATTR_CREATE | XATTR_REPLACE)) {
99 errno = EINVAL;
100 return -1;
101 }
102 fd = openat_file(dirfd, filename,
103 O_RDONLY | O_PATH_9P_UTIL | O_NOFOLLOW, 0);
104 if (fd == -1) {
105 return -1;
106 }
107 if (flags & (XATTR_CREATE | XATTR_REPLACE)) {
108 ret = extattr_get_fd(fd, namespace, name, NULL, 0);
109 if (ret == -1 && errno != ENOATTR) {
110 close_preserve_errno(fd);
111 return -1;
112 }
113 if (ret >= 0 && (flags & XATTR_CREATE)) {
114 errno = EEXIST;
115 close_preserve_errno(fd);
116 return -1;
117 }
118 if (ret == -1 && (flags & XATTR_REPLACE)) {
119 errno = ENOATTR;
120 close_preserve_errno(fd);
121 return -1;
122 }
123 }
124 ret = extattr_set_fd(fd, namespace, name, value, size);
125 close_preserve_errno(fd);
126 return ret;
127 }
128
129 int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
130 {
131 return mknodat(dirfd, filename, mode, dev);
132 }