From a60bbf1a4590ae7ca359e1456f67e7a992698fd7 Mon Sep 17 00:00:00 2001 From: Allan McRae Date: Thu, 8 May 2025 23:00:57 +1000 Subject: [PATCH] Do not chown downloads when DownloadUser is unset On NFS caches, using chown to change file permissions to the UID 0 user will fail due to root_squash. When DownloadUser is unset, or set to the UID 0 user (root), avoid the unneeded chown calls providing a workaround. Fixes #194 Signed-off-by: Allan McRae --- lib/libalpm/dload.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c index 6db187d7..c5de0e6e 100644 --- a/lib/libalpm/dload.c +++ b/lib/libalpm/dload.c @@ -73,17 +73,21 @@ static mode_t _getumask(void) return mask; } -static int finalize_download_file(const char *filename) +static int finalize_download_file(const char *filename, const char *user) { struct stat st; uid_t myuid = getuid(); + struct passwd const *pw = NULL; + ASSERT(filename != NULL, return -1); ASSERT(stat(filename, &st) == 0, return -1); + ASSERT((pw = getpwuid(0)) != NULL, return -1); + if(st.st_size == 0) { unlink(filename); return 1; } - if(myuid == 0) { + if(myuid == 0 && strcmp(user, pw->pw_name) != 0) { ASSERT(chown(filename, 0, 0) != -1, return -1); } ASSERT(chmod(filename, ~(_getumask()) & 0666) != -1, return -1); @@ -1080,11 +1084,11 @@ static int payload_download_fetchcb(struct dload_payload *payload, return ret; } -static int move_file(const char *filepath, const char *directory) +static int move_file(const char *filepath, const char *directory, const char *user) { ASSERT(filepath != NULL, return -1); ASSERT(directory != NULL, return -1); - int ret = finalize_download_file(filepath); + int ret = finalize_download_file(filepath, user); if(ret != 0) { return ret; } @@ -1098,7 +1102,7 @@ static int move_file(const char *filepath, const char *directory) return 0; } -static int finalize_download_locations(alpm_list_t *payloads, const char *localpath) +static int finalize_download_locations(alpm_list_t *payloads, const char *localpath, const char *user) { ASSERT(payloads != NULL, return -1); ASSERT(localpath != NULL, return -1); @@ -1107,10 +1111,10 @@ static int finalize_download_locations(alpm_list_t *payloads, const char *localp for(p = payloads; p; p = p->next) { struct dload_payload *payload = p->data; if(payload->tempfile_name) { - move_file(payload->tempfile_name, localpath); + move_file(payload->tempfile_name, localpath, user); } if(payload->destfile_name) { - int ret = move_file(payload->destfile_name, localpath); + int ret = move_file(payload->destfile_name, localpath, user); if(ret == -1) { /* ignore error if the file already existed - only signature file was downloaded */ @@ -1127,7 +1131,7 @@ static int finalize_download_locations(alpm_list_t *payloads, const char *localp size_t sig_filename_len = strlen(payload->destfile_name) + sizeof(sig_suffix); MALLOC(sig_filename, sig_filename_len, continue); snprintf(sig_filename, sig_filename_len, "%s%s", payload->destfile_name, sig_suffix); - move_file(sig_filename, localpath); + move_file(sig_filename, localpath, user); FREE(sig_filename); } } @@ -1170,7 +1174,7 @@ static void prepare_resumable_downloads(alpm_list_t *payloads, const char *local FREE(src); continue; } - if(pw != NULL) { + if(pw != NULL && pw->pw_uid != 0) { ASSERT(chown(payload->tempfile_name, pw->pw_uid, pw->pw_gid), return); } FREE(src); @@ -1267,7 +1271,7 @@ download_signature: ret = updated ? 0 : 1; } - if (finalize_download_locations(payloads, localpath) != 0 && ret == 0) { + if (finalize_download_locations(payloads, localpath, handle->sandboxuser) != 0 && ret == 0) { RET_ERR(handle, ALPM_ERR_RETRIEVE, -1); } return ret;