xref: /qemu/hw/9pfs/9p-util-darwin.c (revision 096af171274cc76c51bf11366ae257391ddfed2a)
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 
81     if (S_ISREG(mode) || !(mode & S_IFMT)) {
82         int fd = openat_file(dirfd, filename, O_CREAT, mode);
83         if (fd == -1) {
84             return fd;
85         }
86         close(fd);
87         return 0;
88     }
89     if (!pthread_fchdir_np) {
90         error_report_once("pthread_fchdir_np() not available on this version of macOS");
91         return -ENOTSUP;
92     }
93     if (pthread_fchdir_np(dirfd) < 0) {
94         return -1;
95     }
96     err = mknod(filename, mode, dev);
97     preserved_errno = errno;
98     /* Stop using the thread-local cwd */
99     pthread_fchdir_np(-1);
100     if (err < 0) {
101         errno = preserved_errno;
102     }
103     return err;
104 }
105 
106 #endif
107