qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

9p-util-darwin.c (4109B)


      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 static 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      * 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
    103      * descriptors yet.
    104      *
    105      * Filed report with Apple: FB9997731
    106      */
    107     err = fchmodat(AT_FDCWD, filename, mode, AT_SYMLINK_NOFOLLOW);
    108 out:
    109     close_preserve_errno(fd);
    110     return err;
    111 }
    112 
    113 int 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     /* Stop using the thread-local cwd */
    140     pthread_fchdir_np(-1);
    141     if (err < 0) {
    142         errno = preserved_errno;
    143     }
    144     return err;
    145 }
    146 
    147 #endif