2 * 9p utilities (Darwin Implementation)
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.
8 #include "qemu/osdep.h"
9 #include "qemu/xattr.h"
10 #include "qapi/error.h"
11 #include "qemu/error-report.h"
14 ssize_t
fgetxattrat_nofollow(int dirfd
, const char *filename
, const char *name
,
15 void *value
, size_t size
)
18 int fd
= openat_file(dirfd
, filename
,
19 O_RDONLY
| O_PATH_9P_UTIL
| O_NOFOLLOW
, 0);
23 ret
= fgetxattr(fd
, name
, value
, size
, 0, 0);
24 close_preserve_errno(fd
);
28 ssize_t
flistxattrat_nofollow(int dirfd
, const char *filename
,
29 char *list
, size_t size
)
32 int fd
= openat_file(dirfd
, filename
,
33 O_RDONLY
| O_PATH_9P_UTIL
| O_NOFOLLOW
, 0);
37 ret
= flistxattr(fd
, list
, size
, 0);
38 close_preserve_errno(fd
);
42 ssize_t
fremovexattrat_nofollow(int dirfd
, const char *filename
,
46 int fd
= openat_file(dirfd
, filename
, O_PATH_9P_UTIL
| O_NOFOLLOW
, 0);
50 ret
= fremovexattr(fd
, name
, 0);
51 close_preserve_errno(fd
);
55 int fsetxattrat_nofollow(int dirfd
, const char *filename
, const char *name
,
56 void *value
, size_t size
, int flags
)
59 int fd
= openat_file(dirfd
, filename
, O_PATH_9P_UTIL
| O_NOFOLLOW
, 0);
63 ret
= fsetxattr(fd
, name
, value
, size
, 0, flags
);
64 close_preserve_errno(fd
);
69 * As long as mknodat is not available on macOS, this workaround
70 * using pthread_fchdir_np is needed.
72 * Radar filed with Apple for implementing mknodat:
73 * rdar://FB9862426 (https://openradar.appspot.com/FB9862426)
75 #if defined CONFIG_PTHREAD_FCHDIR_NP
77 static int create_socket_file_at_cwd(const char *filename
, mode_t mode
) {
79 struct sockaddr_un addr
= {
83 err
= snprintf(addr
.sun_path
, sizeof(addr
.sun_path
), "./%s", filename
);
84 if (err
< 0 || err
>= sizeof(addr
.sun_path
)) {
88 fd
= socket(PF_UNIX
, SOCK_DGRAM
, 0);
92 err
= bind(fd
, (struct sockaddr
*) &addr
, sizeof(addr
));
97 * FIXME: Should rather be using descriptor-based fchmod() on the
98 * socket file descriptor above (preferably before bind() call),
99 * instead of path-based fchmodat(), to prevent concurrent transient
100 * state issues between creating the named FIFO file at bind() and
101 * delayed adjustment of permissions at fchmodat(). However currently
102 * macOS (12.x) does not support such operations on socket file
105 * Filed report with Apple: FB9997731
107 err
= fchmodat(AT_FDCWD
, filename
, mode
, AT_SYMLINK_NOFOLLOW
);
109 close_preserve_errno(fd
);
113 int qemu_mknodat(int dirfd
, const char *filename
, mode_t mode
, dev_t dev
)
115 int preserved_errno
, err
;
117 if (S_ISREG(mode
) || !(mode
& S_IFMT
)) {
118 int fd
= openat_file(dirfd
, filename
, O_CREAT
, mode
);
125 if (!pthread_fchdir_np
) {
126 error_report_once("pthread_fchdir_np() not available on this version of macOS");
130 if (pthread_fchdir_np(dirfd
) < 0) {
133 if (S_ISSOCK(mode
)) {
134 err
= create_socket_file_at_cwd(filename
, mode
);
136 err
= mknod(filename
, mode
, dev
);
138 preserved_errno
= errno
;
139 /* Stop using the thread-local cwd */
140 pthread_fchdir_np(-1);
142 errno
= preserved_errno
;