1
0
mirror of https://github.com/moparisthebest/pacman synced 2024-11-15 13:55:09 -05:00

Rework finding a writable cache directory

This is a refactor and refresh of the code used to find where we should
download packages.

* Incorporate suggestions from FS#25435 to use TMPDIR from the
  environment if set, otherwise fall back to /tmp as before.
* Make the writability tests a bit more in depth. We now do a three part
  check consisting of:
  - S_ISDIR(): is this even a directory
  - access(W_OK): is this directory writable by the current user.
    Unfortunately for root, this almost always returns that it is, but
    in the case of a RO mount or NFS share inaccessible to root, this
    check will exclude the directory.
  - mode & (any write bit): is there a writable bit set on this
    directory. This makes it possible to enforce a read-only cache
    directory by setting permissions to 0555, for example.

Signed-off-by: Dan McGee <dan@archlinux.org>
This commit is contained in:
Dan McGee 2011-08-19 13:10:17 -05:00
parent 6d544984f2
commit e07547ee4e

View File

@ -638,7 +638,7 @@ char *_alpm_filecache_find(alpm_handle_t *handle, const char *filename)
struct stat buf; struct stat buf;
/* Loop through the cache dirs until we find a matching file */ /* Loop through the cache dirs until we find a matching file */
for(i = alpm_option_get_cachedirs(handle); i; i = i->next) { for(i = handle->cachedirs; i; i = i->next) {
snprintf(path, PATH_MAX, "%s%s", (char *)alpm_list_getdata(i), snprintf(path, PATH_MAX, "%s%s", (char *)alpm_list_getdata(i),
filename); filename);
if(stat(path, &buf) == 0 && S_ISREG(buf.st_mode)) { if(stat(path, &buf) == 0 && S_ISREG(buf.st_mode)) {
@ -659,11 +659,11 @@ char *_alpm_filecache_find(alpm_handle_t *handle, const char *filename)
const char *_alpm_filecache_setup(alpm_handle_t *handle) const char *_alpm_filecache_setup(alpm_handle_t *handle)
{ {
struct stat buf; struct stat buf;
alpm_list_t *i, *tmp; alpm_list_t *i;
char *cachedir; char *cachedir, *tmpdir;
/* Loop through the cache dirs until we find a writeable dir */ /* Loop through the cache dirs until we find a usable directory */
for(i = alpm_option_get_cachedirs(handle); i; i = i->next) { for(i = handle->cachedirs; i; i = i->next) {
cachedir = alpm_list_getdata(i); cachedir = alpm_list_getdata(i);
if(stat(cachedir, &buf) != 0) { if(stat(cachedir, &buf) != 0) {
/* cache directory does not exist.... try creating it */ /* cache directory does not exist.... try creating it */
@ -673,21 +673,35 @@ const char *_alpm_filecache_setup(alpm_handle_t *handle)
_alpm_log(handle, ALPM_LOG_DEBUG, "using cachedir: %s\n", cachedir); _alpm_log(handle, ALPM_LOG_DEBUG, "using cachedir: %s\n", cachedir);
return cachedir; return cachedir;
} }
} else if(S_ISDIR(buf.st_mode) && (buf.st_mode & S_IWUSR)) { } else if(!S_ISDIR(buf.st_mode)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"skipping cachedir, not a directory: %s\n", cachedir);
} else if(access(cachedir, W_OK) != 0) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"skipping cachedir, not writable: %s\n", cachedir);
} else if(!(buf.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH))) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"skipping cachedir, no write bits set: %s\n", cachedir);
} else {
_alpm_log(handle, ALPM_LOG_DEBUG, "using cachedir: %s\n", cachedir); _alpm_log(handle, ALPM_LOG_DEBUG, "using cachedir: %s\n", cachedir);
return cachedir; return cachedir;
} else {
_alpm_log(handle, ALPM_LOG_DEBUG, "skipping cachedir: %s\n", cachedir);
} }
} }
/* we didn't find a valid cache directory. use /tmp. */ /* we didn't find a valid cache directory. use TMPDIR or /tmp. */
tmp = alpm_list_add(NULL, "/tmp/"); if((tmpdir = getenv("TMPDIR")) && stat(tmpdir, &buf) && S_ISDIR(buf.st_mode)) {
alpm_option_set_cachedirs(handle, tmp); /* TMPDIR was good, we can use it */
alpm_list_free(tmp); } else {
_alpm_log(handle, ALPM_LOG_DEBUG, "using cachedir: %s\n", "/tmp/"); tmpdir = "/tmp";
_alpm_log(handle, ALPM_LOG_WARNING, _("couldn't create package cache, using /tmp instead\n")); }
return "/tmp/"; i = alpm_list_add(NULL, tmpdir);
alpm_option_set_cachedirs(handle, i);
alpm_list_free(i);
cachedir = handle->cachedirs->data;
_alpm_log(handle, ALPM_LOG_DEBUG, "using cachedir: %s\n", cachedir);
_alpm_log(handle, ALPM_LOG_WARNING,
_("couldn't find or create package cache, using %s instead\n"), cachedir);
return cachedir;
} }
/** lstat wrapper that treats /path/dirsymlink/ the same as /path/dirsymlink. /** lstat wrapper that treats /path/dirsymlink/ the same as /path/dirsymlink.