xref: /qemu/hw/9pfs/9p-util-darwin.c (revision 49f95221)
1 /*
2  * 9p utilities (Darwin 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 #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 
14 ssize_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 
28 ssize_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 
42 ssize_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 
55 int 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  * As long as mknodat is not available on macOS, this workaround
70  * using pthread_fchdir_np is needed.
71  *
72  * Radar filed with Apple for implementing mknodat:
73  * rdar://FB9862426 (https://openradar.appspot.com/FB9862426)
74  */
75 #if defined CONFIG_PTHREAD_FCHDIR_NP
76 
77 int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
78 {
79     int preserved_errno, err;
80     if (!pthread_fchdir_np) {
81         error_report_once("pthread_fchdir_np() not available on this version of macOS");
82         return -ENOTSUP;
83     }
84     if (pthread_fchdir_np(dirfd) < 0) {
85         return -1;
86     }
87     err = mknod(filename, mode, dev);
88     preserved_errno = errno;
89     /* Stop using the thread-local cwd */
90     pthread_fchdir_np(-1);
91     if (err < 0) {
92         errno = preserved_errno;
93     }
94     return err;
95 }
96 
97 #endif
98