Compare commits

...
Sign in to create a new pull request.

4 commits

Author SHA1 Message Date
morganamilo
3612510ee0
libalpm: add new errno for download initialization
The error string "failed to retrieve some files" implies that the
download may have begun and some files may have been partially
downloaded.

If we know no download actually took place we can be more clear about
this.
2025-05-20 13:54:05 +01:00
morganamilo
a1ff7d8c72
libalpm: set errno and log when setting up temp download dir
Before:
	% pacman -Syy
	:: Synchronising package databases...
	error: failed to synchronize all databases (unexpected error)

After:
	% pacman -Syy
	:: Synchronising package databases...
	error: failed to create temporary download directory /var/lib/pacman/sync/download-P77oXs: Permission denied
	error: failed to synchronize all databases (failed to retrieve some files)
2025-05-20 13:54:01 +01:00
morganamilo
f6aa79c10a
libalpm: pass handle to alpm_temporary_download_dir_setup 2025-05-20 13:53:58 +01:00
morganamilo
3370dd586a
libalpm: don't chown download dir if not root
Commit 7bc5d55b56 disbaled the chown after
downloading if the current user is not root. It only makes sense for us
to do the same on this side otherwise files would end up stuck as the
download user.

This is also important for other alpm tools that configure themselves
via pacman.conf but download to user directories.
2025-05-20 13:53:45 +01:00
7 changed files with 38 additions and 12 deletions

View file

@ -308,6 +308,8 @@ typedef enum _alpm_errno_t {
/** Files conflict */
ALPM_ERR_FILE_CONFLICTS,
/* Misc */
/** Download setup failed */
ALPM_ERR_RETRIEVE_PREPARE,
/** Download failed */
ALPM_ERR_RETRIEVE,
/** Invalid Regex */

View file

@ -153,7 +153,7 @@ int SYMEXPORT alpm_db_update(alpm_handle_t *handle, alpm_list_t *dbs, int force)
syncpath = get_sync_dir(handle);
ASSERT(syncpath != NULL, return -1);
temporary_syncpath = _alpm_temporary_download_dir_setup(syncpath, handle->sandboxuser);
temporary_syncpath = _alpm_temporary_download_dir_setup(handle, syncpath);
ASSERT(temporary_syncpath != NULL, FREE(syncpath); return -1);
/* make sure we have a sane umask */

View file

@ -1304,7 +1304,7 @@ int SYMEXPORT alpm_fetch_pkgurl(alpm_handle_t *handle, const alpm_list_t *urls,
/* find a valid cache dir to download to */
cachedir = _alpm_filecache_setup(handle);
temporary_cachedir = _alpm_temporary_download_dir_setup(cachedir, handle->sandboxuser);
temporary_cachedir = _alpm_temporary_download_dir_setup(handle, cachedir);
ASSERT(temporary_cachedir != NULL, return -1);
for(i = urls; i; i = i->next) {

View file

@ -138,6 +138,8 @@ const char SYMEXPORT *alpm_strerror(alpm_errno_t err)
case ALPM_ERR_FILE_CONFLICTS:
return _("conflicting files");
/* Miscellaneous */
case ALPM_ERR_RETRIEVE_PREPARE:
return _("failed to initialize download");
case ALPM_ERR_RETRIEVE:
return _("failed to retrieve some files");
case ALPM_ERR_INVALID_REGEX:

View file

@ -780,7 +780,7 @@ static int download_files(alpm_handle_t *handle)
alpm_list_t *payloads = NULL;
cachedir = _alpm_filecache_setup(handle);
temporary_cachedir = _alpm_temporary_download_dir_setup(cachedir, handle->sandboxuser);
temporary_cachedir = _alpm_temporary_download_dir_setup(handle, cachedir);
if(temporary_cachedir == NULL) {
ret = -1;
goto finish;

View file

@ -23,6 +23,7 @@
*/
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <dirent.h>
@ -949,32 +950,53 @@ const char *_alpm_filecache_setup(alpm_handle_t *handle)
/** Create a temporary directory under the supplied directory.
* The new directory is writable by the download user, and will be
* removed after the download operation has completed.
* @param handle an alpm handle
* @param dir existing sync or cache directory
* @param user download user name
* @return pointer to a sub-directory writable by the download user inside the existing directory.
*/
char *_alpm_temporary_download_dir_setup(const char *dir, const char *user)
char *_alpm_temporary_download_dir_setup(alpm_handle_t *handle, const char *dir)
{
const char *user = handle->sandboxuser;
uid_t myuid = getuid();
struct passwd const *pw = NULL;
ASSERT(dir != NULL, return NULL);
if(user != NULL) {
ASSERT((pw = getpwnam(user)) != NULL, return NULL);
ASSERT(dir != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, NULL));
if(myuid == 0 && user != NULL) {
errno = 0;
pw = getpwnam(user);
if(pw == NULL) {
if(errno == 0) {
_alpm_log(handle, ALPM_LOG_ERROR,
_("download user '%s' does not exist\n"), user);
} else {
_alpm_log(handle, ALPM_LOG_ERROR,
_("failed to get download user '%s': %s\n"),
user, strerror(errno));
}
RET_ERR(handle, ALPM_ERR_RETRIEVE_PREPARE, NULL);
}
}
const char template[] = "download-XXXXXX";
size_t newdirlen = strlen(dir) + sizeof(template) + 1;
char *newdir = NULL;
MALLOC(newdir, newdirlen, return NULL);
MALLOC(newdir, newdirlen, RET_ERR(handle, ALPM_ERR_MEMORY, NULL));
snprintf(newdir, newdirlen - 1, "%s%s", dir, template);
if(mkdtemp(newdir) == NULL) {
_alpm_log(handle, ALPM_LOG_ERROR,
_("failed to create temporary download directory %s: %s\n"),
newdir, strerror(errno));
free(newdir);
return NULL;
RET_ERR(handle, ALPM_ERR_RETRIEVE_PREPARE, NULL);
}
if(pw != NULL) {
if(chown(newdir, pw->pw_uid, pw->pw_gid) == -1) {
_alpm_log(handle, ALPM_LOG_ERROR,
_("failed to chown temporary download directory %s: %s\n"),
newdir, strerror(errno));
free(newdir);
return NULL;
RET_ERR(handle, ALPM_ERR_RETRIEVE_PREPARE, NULL);
}
}
newdir[newdirlen-2] = '/';

View file

@ -139,7 +139,7 @@ char *_alpm_filecache_find(alpm_handle_t *handle, const char *filename);
/* Checks whether a file exists in cache */
int _alpm_filecache_exists(alpm_handle_t *handle, const char *filename);
const char *_alpm_filecache_setup(alpm_handle_t *handle);
char *_alpm_temporary_download_dir_setup(const char *dir, const char *user);
char *_alpm_temporary_download_dir_setup(alpm_handle_t *handle, const char *dir);
void _alpm_remove_temporary_download_dir(const char *dir);
/* Unlike many uses of alpm_pkgvalidation_t, _alpm_test_checksum expects