xref: /openbmc/qemu/hw/9pfs/9p-util-darwin.c (revision 063c75db)
157b3910bSKeno Fischer /*
257b3910bSKeno Fischer  * 9p utilities (Darwin Implementation)
357b3910bSKeno Fischer  *
457b3910bSKeno Fischer  * This work is licensed under the terms of the GNU GPL, version 2 or later.
557b3910bSKeno Fischer  * See the COPYING file in the top-level directory.
657b3910bSKeno Fischer  */
757b3910bSKeno Fischer 
857b3910bSKeno Fischer #include "qemu/osdep.h"
957b3910bSKeno Fischer #include "qemu/xattr.h"
10029ed1bdSKeno Fischer #include "qapi/error.h"
11029ed1bdSKeno Fischer #include "qemu/error-report.h"
1257b3910bSKeno Fischer #include "9p-util.h"
1357b3910bSKeno Fischer 
fgetxattrat_nofollow(int dirfd,const char * filename,const char * name,void * value,size_t size)1457b3910bSKeno Fischer ssize_t fgetxattrat_nofollow(int dirfd, const char *filename, const char *name,
1557b3910bSKeno Fischer                              void *value, size_t size)
1657b3910bSKeno Fischer {
1757b3910bSKeno Fischer     int ret;
1857b3910bSKeno Fischer     int fd = openat_file(dirfd, filename,
1957b3910bSKeno Fischer                          O_RDONLY | O_PATH_9P_UTIL | O_NOFOLLOW, 0);
2057b3910bSKeno Fischer     if (fd == -1) {
2157b3910bSKeno Fischer         return -1;
2257b3910bSKeno Fischer     }
2357b3910bSKeno Fischer     ret = fgetxattr(fd, name, value, size, 0, 0);
2457b3910bSKeno Fischer     close_preserve_errno(fd);
2557b3910bSKeno Fischer     return ret;
2657b3910bSKeno Fischer }
2757b3910bSKeno Fischer 
flistxattrat_nofollow(int dirfd,const char * filename,char * list,size_t size)2857b3910bSKeno Fischer ssize_t flistxattrat_nofollow(int dirfd, const char *filename,
2957b3910bSKeno Fischer                               char *list, size_t size)
3057b3910bSKeno Fischer {
3157b3910bSKeno Fischer     int ret;
3257b3910bSKeno Fischer     int fd = openat_file(dirfd, filename,
3357b3910bSKeno Fischer                          O_RDONLY | O_PATH_9P_UTIL | O_NOFOLLOW, 0);
3457b3910bSKeno Fischer     if (fd == -1) {
3557b3910bSKeno Fischer         return -1;
3657b3910bSKeno Fischer     }
3757b3910bSKeno Fischer     ret = flistxattr(fd, list, size, 0);
3857b3910bSKeno Fischer     close_preserve_errno(fd);
3957b3910bSKeno Fischer     return ret;
4057b3910bSKeno Fischer }
4157b3910bSKeno Fischer 
fremovexattrat_nofollow(int dirfd,const char * filename,const char * name)4257b3910bSKeno Fischer ssize_t fremovexattrat_nofollow(int dirfd, const char *filename,
4357b3910bSKeno Fischer                                 const char *name)
4457b3910bSKeno Fischer {
4557b3910bSKeno Fischer     int ret;
4657b3910bSKeno Fischer     int fd = openat_file(dirfd, filename, O_PATH_9P_UTIL | O_NOFOLLOW, 0);
4757b3910bSKeno Fischer     if (fd == -1) {
4857b3910bSKeno Fischer         return -1;
4957b3910bSKeno Fischer     }
5057b3910bSKeno Fischer     ret = fremovexattr(fd, name, 0);
5157b3910bSKeno Fischer     close_preserve_errno(fd);
5257b3910bSKeno Fischer     return ret;
5357b3910bSKeno Fischer }
5457b3910bSKeno Fischer 
fsetxattrat_nofollow(int dirfd,const char * filename,const char * name,void * value,size_t size,int flags)5557b3910bSKeno Fischer int fsetxattrat_nofollow(int dirfd, const char *filename, const char *name,
5657b3910bSKeno Fischer                          void *value, size_t size, int flags)
5757b3910bSKeno Fischer {
5857b3910bSKeno Fischer     int ret;
5957b3910bSKeno Fischer     int fd = openat_file(dirfd, filename, O_PATH_9P_UTIL | O_NOFOLLOW, 0);
6057b3910bSKeno Fischer     if (fd == -1) {
6157b3910bSKeno Fischer         return -1;
6257b3910bSKeno Fischer     }
6357b3910bSKeno Fischer     ret = fsetxattr(fd, name, value, size, 0, flags);
6457b3910bSKeno Fischer     close_preserve_errno(fd);
6557b3910bSKeno Fischer     return ret;
6657b3910bSKeno Fischer }
67029ed1bdSKeno Fischer 
68029ed1bdSKeno Fischer /*
69029ed1bdSKeno Fischer  * As long as mknodat is not available on macOS, this workaround
70029ed1bdSKeno Fischer  * using pthread_fchdir_np is needed.
71029ed1bdSKeno Fischer  *
72029ed1bdSKeno Fischer  * Radar filed with Apple for implementing mknodat:
73029ed1bdSKeno Fischer  * rdar://FB9862426 (https://openradar.appspot.com/FB9862426)
74029ed1bdSKeno Fischer  */
75029ed1bdSKeno Fischer #if defined CONFIG_PTHREAD_FCHDIR_NP
76029ed1bdSKeno Fischer 
create_socket_file_at_cwd(const char * filename,mode_t mode)77055ab893SChristian Schoenebeck static int create_socket_file_at_cwd(const char *filename, mode_t mode) {
78055ab893SChristian Schoenebeck     int fd, err;
79055ab893SChristian Schoenebeck     struct sockaddr_un addr = {
80055ab893SChristian Schoenebeck         .sun_family = AF_UNIX
81055ab893SChristian Schoenebeck     };
82055ab893SChristian Schoenebeck 
83055ab893SChristian Schoenebeck     err = snprintf(addr.sun_path, sizeof(addr.sun_path), "./%s", filename);
84055ab893SChristian Schoenebeck     if (err < 0 || err >= sizeof(addr.sun_path)) {
85055ab893SChristian Schoenebeck         errno = ENAMETOOLONG;
86055ab893SChristian Schoenebeck         return -1;
87055ab893SChristian Schoenebeck     }
88055ab893SChristian Schoenebeck     fd = socket(PF_UNIX, SOCK_DGRAM, 0);
89055ab893SChristian Schoenebeck     if (fd == -1) {
90055ab893SChristian Schoenebeck         return fd;
91055ab893SChristian Schoenebeck     }
92055ab893SChristian Schoenebeck     err = bind(fd, (struct sockaddr *) &addr, sizeof(addr));
93055ab893SChristian Schoenebeck     if (err == -1) {
94055ab893SChristian Schoenebeck         goto out;
95055ab893SChristian Schoenebeck     }
96055ab893SChristian Schoenebeck     /*
97055ab893SChristian Schoenebeck      * FIXME: Should rather be using descriptor-based fchmod() on the
98055ab893SChristian Schoenebeck      * socket file descriptor above (preferably before bind() call),
99055ab893SChristian Schoenebeck      * instead of path-based fchmodat(), to prevent concurrent transient
100055ab893SChristian Schoenebeck      * state issues between creating the named FIFO file at bind() and
101055ab893SChristian Schoenebeck      * delayed adjustment of permissions at fchmodat(). However currently
102055ab893SChristian Schoenebeck      * macOS (12.x) does not support such operations on socket file
103055ab893SChristian Schoenebeck      * descriptors yet.
104055ab893SChristian Schoenebeck      *
105055ab893SChristian Schoenebeck      * Filed report with Apple: FB9997731
106055ab893SChristian Schoenebeck      */
107055ab893SChristian Schoenebeck     err = fchmodat(AT_FDCWD, filename, mode, AT_SYMLINK_NOFOLLOW);
108055ab893SChristian Schoenebeck out:
109055ab893SChristian Schoenebeck     close_preserve_errno(fd);
110055ab893SChristian Schoenebeck     return err;
111055ab893SChristian Schoenebeck }
112055ab893SChristian Schoenebeck 
qemu_mknodat(int dirfd,const char * filename,mode_t mode,dev_t dev)113029ed1bdSKeno Fischer int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
114029ed1bdSKeno Fischer {
115029ed1bdSKeno Fischer     int preserved_errno, err;
116096af171SChristian Schoenebeck 
117096af171SChristian Schoenebeck     if (S_ISREG(mode) || !(mode & S_IFMT)) {
118096af171SChristian Schoenebeck         int fd = openat_file(dirfd, filename, O_CREAT, mode);
119096af171SChristian Schoenebeck         if (fd == -1) {
120096af171SChristian Schoenebeck             return fd;
121096af171SChristian Schoenebeck         }
122096af171SChristian Schoenebeck         close(fd);
123096af171SChristian Schoenebeck         return 0;
124096af171SChristian Schoenebeck     }
125029ed1bdSKeno Fischer     if (!pthread_fchdir_np) {
126029ed1bdSKeno Fischer         error_report_once("pthread_fchdir_np() not available on this version of macOS");
127*063c75dbSChristian Schoenebeck         errno = ENOTSUP;
128*063c75dbSChristian Schoenebeck         return -1;
129029ed1bdSKeno Fischer     }
130029ed1bdSKeno Fischer     if (pthread_fchdir_np(dirfd) < 0) {
131029ed1bdSKeno Fischer         return -1;
132029ed1bdSKeno Fischer     }
133055ab893SChristian Schoenebeck     if (S_ISSOCK(mode)) {
134055ab893SChristian Schoenebeck         err = create_socket_file_at_cwd(filename, mode);
135055ab893SChristian Schoenebeck     } else {
136029ed1bdSKeno Fischer         err = mknod(filename, mode, dev);
137055ab893SChristian Schoenebeck     }
138029ed1bdSKeno Fischer     preserved_errno = errno;
139029ed1bdSKeno Fischer     /* Stop using the thread-local cwd */
140029ed1bdSKeno Fischer     pthread_fchdir_np(-1);
141029ed1bdSKeno Fischer     if (err < 0) {
142029ed1bdSKeno Fischer         errno = preserved_errno;
143029ed1bdSKeno Fischer     }
144029ed1bdSKeno Fischer     return err;
145029ed1bdSKeno Fischer }
146029ed1bdSKeno Fischer 
147029ed1bdSKeno Fischer #endif
148