/* Detect if chown(2) is supported on the target directory. */ static int is_chown_supported (const char *dir) { CLEANUP_FREE char *buf = NULL; int fd, r, err, saved_errno; /* Create a randomly named file. */ if (asprintf (&buf, "%s%s/XXXXXXXX.XXX", sysroot, dir) == -1) { err = errno; r = cancel_receive (); errno = err; reply_with_perror ("asprintf"); return -1; } if (random_name (buf) == -1) { err = errno; r = cancel_receive (); errno = err; reply_with_perror ("random_name"); return -1; } /* Maybe 'dir' is not a directory or filesystem not writable? */ fd = open (buf, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0666); if (fd == -1) { err = errno; r = cancel_receive (); errno = err; reply_with_perror ("%s", dir); return -1; } /* This is the test. */ r = fchown (fd, 1000, 1000); saved_errno = errno; /* Make sure the test file is removed. */ close (fd); unlink (buf); if (r == -1 && saved_errno == EPERM) { /* This means chown is not supported by the filesystem. */ return 0; } if (r == -1) { /* Some other error? */ err = errno; r = cancel_receive (); errno = err; reply_with_perror_errno (saved_errno, "unexpected error in fchown"); return -1; } /* Else chown is supported. */ return 1; }
/* Detect if chown(2) is supported on the target directory. */ static int is_chown_supported (const char *dir) { size_t len = sysroot_len + strlen (dir) + 64; char buf[len]; int fd, r, saved_errno; /* Create a randomly named file. */ snprintf (buf, len, "%s%s/XXXXXXXX.XXX", sysroot, dir); if (random_name (buf) == -1) { reply_with_perror ("random_name"); return -1; } /* Maybe 'dir' is not a directory or filesystem not writable? */ fd = open (buf, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0666); if (fd == -1) { reply_with_perror ("%s", dir); return -1; } /* This is the test. */ r = fchown (fd, 1000, 1000); saved_errno = errno; /* Make sure the test file is removed. */ close (fd); unlink (buf); if (r == -1 && saved_errno == EPERM) { /* This means chown is not supported by the filesystem. */ return 0; } if (r == -1) { /* Some other error? */ reply_with_perror_errno (saved_errno, "unexpected error in fchown"); return -1; } /* Else chown is supported. */ return 1; }