1
2
3
4
5
6
7
8#include "qemu/osdep.h"
9#include "qemu/xattr.h"
10#include "qapi/error.h"
11#include "qemu/error-report.h"
12#include "9p-util.h"
13
14ssize_t fgetxattrat_nofollow(int dirfd, const char *filename, const char *name,
15 void *value, size_t size)
16{
17 int ret;
18 int fd = openat_file(dirfd, filename,
19 O_RDONLY | O_PATH_9P_UTIL | O_NOFOLLOW, 0);
20 if (fd == -1) {
21 return -1;
22 }
23 ret = fgetxattr(fd, name, value, size, 0, 0);
24 close_preserve_errno(fd);
25 return ret;
26}
27
28ssize_t flistxattrat_nofollow(int dirfd, const char *filename,
29 char *list, size_t size)
30{
31 int ret;
32 int fd = openat_file(dirfd, filename,
33 O_RDONLY | O_PATH_9P_UTIL | O_NOFOLLOW, 0);
34 if (fd == -1) {
35 return -1;
36 }
37 ret = flistxattr(fd, list, size, 0);
38 close_preserve_errno(fd);
39 return ret;
40}
41
42ssize_t fremovexattrat_nofollow(int dirfd, const char *filename,
43 const char *name)
44{
45 int ret;
46 int fd = openat_file(dirfd, filename, O_PATH_9P_UTIL | O_NOFOLLOW, 0);
47 if (fd == -1) {
48 return -1;
49 }
50 ret = fremovexattr(fd, name, 0);
51 close_preserve_errno(fd);
52 return ret;
53}
54
55int fsetxattrat_nofollow(int dirfd, const char *filename, const char *name,
56 void *value, size_t size, int flags)
57{
58 int ret;
59 int fd = openat_file(dirfd, filename, O_PATH_9P_UTIL | O_NOFOLLOW, 0);
60 if (fd == -1) {
61 return -1;
62 }
63 ret = fsetxattr(fd, name, value, size, 0, flags);
64 close_preserve_errno(fd);
65 return ret;
66}
67
68
69
70
71
72
73
74
75#if defined CONFIG_PTHREAD_FCHDIR_NP
76
77static int create_socket_file_at_cwd(const char *filename, mode_t mode) {
78 int fd, err;
79 struct sockaddr_un addr = {
80 .sun_family = AF_UNIX
81 };
82
83 err = snprintf(addr.sun_path, sizeof(addr.sun_path), "./%s", filename);
84 if (err < 0 || err >= sizeof(addr.sun_path)) {
85 errno = ENAMETOOLONG;
86 return -1;
87 }
88 fd = socket(PF_UNIX, SOCK_DGRAM, 0);
89 if (fd == -1) {
90 return fd;
91 }
92 err = bind(fd, (struct sockaddr *) &addr, sizeof(addr));
93 if (err == -1) {
94 goto out;
95 }
96
97
98
99
100
101
102
103
104
105
106
107 err = fchmodat(AT_FDCWD, filename, mode, AT_SYMLINK_NOFOLLOW);
108out:
109 close_preserve_errno(fd);
110 return err;
111}
112
113int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
114{
115 int preserved_errno, err;
116
117 if (S_ISREG(mode) || !(mode & S_IFMT)) {
118 int fd = openat_file(dirfd, filename, O_CREAT, mode);
119 if (fd == -1) {
120 return fd;
121 }
122 close(fd);
123 return 0;
124 }
125 if (!pthread_fchdir_np) {
126 error_report_once("pthread_fchdir_np() not available on this version of macOS");
127 errno = ENOTSUP;
128 return -1;
129 }
130 if (pthread_fchdir_np(dirfd) < 0) {
131 return -1;
132 }
133 if (S_ISSOCK(mode)) {
134 err = create_socket_file_at_cwd(filename, mode);
135 } else {
136 err = mknod(filename, mode, dev);
137 }
138 preserved_errno = errno;
139
140 pthread_fchdir_np(-1);
141 if (err < 0) {
142 errno = preserved_errno;
143 }
144 return err;
145}
146
147#endif
148