|
@@ -74,17 +74,67 @@ int fsetxattrat_nofollow(int dirfd, const char *filename, const char *name,
|
|
*/
|
|
*/
|
|
#if defined CONFIG_PTHREAD_FCHDIR_NP
|
|
#if defined CONFIG_PTHREAD_FCHDIR_NP
|
|
|
|
|
|
|
|
+static int create_socket_file_at_cwd(const char *filename, mode_t mode) {
|
|
|
|
+ int fd, err;
|
|
|
|
+ struct sockaddr_un addr = {
|
|
|
|
+ .sun_family = AF_UNIX
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ err = snprintf(addr.sun_path, sizeof(addr.sun_path), "./%s", filename);
|
|
|
|
+ if (err < 0 || err >= sizeof(addr.sun_path)) {
|
|
|
|
+ errno = ENAMETOOLONG;
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ fd = socket(PF_UNIX, SOCK_DGRAM, 0);
|
|
|
|
+ if (fd == -1) {
|
|
|
|
+ return fd;
|
|
|
|
+ }
|
|
|
|
+ err = bind(fd, (struct sockaddr *) &addr, sizeof(addr));
|
|
|
|
+ if (err == -1) {
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ /*
|
|
|
|
+ * FIXME: Should rather be using descriptor-based fchmod() on the
|
|
|
|
+ * socket file descriptor above (preferably before bind() call),
|
|
|
|
+ * instead of path-based fchmodat(), to prevent concurrent transient
|
|
|
|
+ * state issues between creating the named FIFO file at bind() and
|
|
|
|
+ * delayed adjustment of permissions at fchmodat(). However currently
|
|
|
|
+ * macOS (12.x) does not support such operations on socket file
|
|
|
|
+ * descriptors yet.
|
|
|
|
+ *
|
|
|
|
+ * Filed report with Apple: FB9997731
|
|
|
|
+ */
|
|
|
|
+ err = fchmodat(AT_FDCWD, filename, mode, AT_SYMLINK_NOFOLLOW);
|
|
|
|
+out:
|
|
|
|
+ close_preserve_errno(fd);
|
|
|
|
+ return err;
|
|
|
|
+}
|
|
|
|
+
|
|
int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
|
|
int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
|
|
{
|
|
{
|
|
int preserved_errno, err;
|
|
int preserved_errno, err;
|
|
|
|
+
|
|
|
|
+ if (S_ISREG(mode) || !(mode & S_IFMT)) {
|
|
|
|
+ int fd = openat_file(dirfd, filename, O_CREAT, mode);
|
|
|
|
+ if (fd == -1) {
|
|
|
|
+ return fd;
|
|
|
|
+ }
|
|
|
|
+ close(fd);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
if (!pthread_fchdir_np) {
|
|
if (!pthread_fchdir_np) {
|
|
error_report_once("pthread_fchdir_np() not available on this version of macOS");
|
|
error_report_once("pthread_fchdir_np() not available on this version of macOS");
|
|
- return -ENOTSUP;
|
|
|
|
|
|
+ errno = ENOTSUP;
|
|
|
|
+ return -1;
|
|
}
|
|
}
|
|
if (pthread_fchdir_np(dirfd) < 0) {
|
|
if (pthread_fchdir_np(dirfd) < 0) {
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
- err = mknod(filename, mode, dev);
|
|
|
|
|
|
+ if (S_ISSOCK(mode)) {
|
|
|
|
+ err = create_socket_file_at_cwd(filename, mode);
|
|
|
|
+ } else {
|
|
|
|
+ err = mknod(filename, mode, dev);
|
|
|
|
+ }
|
|
preserved_errno = errno;
|
|
preserved_errno = errno;
|
|
/* Stop using the thread-local cwd */
|
|
/* Stop using the thread-local cwd */
|
|
pthread_fchdir_np(-1);
|
|
pthread_fchdir_np(-1);
|