diff options
author | Dan McGee <dan@archlinux.org> | 2011-08-19 20:10:17 +0200 |
---|---|---|
committer | Dan McGee <dan@archlinux.org> | 2011-08-19 20:10:17 +0200 |
commit | e07547ee4ed4fd812a7f50b998589fa27c12de4c (patch) | |
tree | 4ab4b3869e7e3cf1ab6bf96e954beea4ab9de276 /lib | |
parent | 6d544984f2418ea34caab4c433580487b760362a (diff) | |
download | pacman-e07547ee4ed4fd812a7f50b998589fa27c12de4c.tar.gz pacman-e07547ee4ed4fd812a7f50b998589fa27c12de4c.tar.xz |
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>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libalpm/util.c | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 27709c64..7e3bc372 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -638,7 +638,7 @@ char *_alpm_filecache_find(alpm_handle_t *handle, const char *filename) struct stat buf; /* 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), filename); 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) { struct stat buf; - alpm_list_t *i, *tmp; - char *cachedir; + alpm_list_t *i; + char *cachedir, *tmpdir; - /* Loop through the cache dirs until we find a writeable dir */ - for(i = alpm_option_get_cachedirs(handle); i; i = i->next) { + /* Loop through the cache dirs until we find a usable directory */ + for(i = handle->cachedirs; i; i = i->next) { cachedir = alpm_list_getdata(i); if(stat(cachedir, &buf) != 0) { /* 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); 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); return cachedir; - } else { - _alpm_log(handle, ALPM_LOG_DEBUG, "skipping cachedir: %s\n", cachedir); } } - /* we didn't find a valid cache directory. use /tmp. */ - tmp = alpm_list_add(NULL, "/tmp/"); - alpm_option_set_cachedirs(handle, tmp); - alpm_list_free(tmp); - _alpm_log(handle, ALPM_LOG_DEBUG, "using cachedir: %s\n", "/tmp/"); - _alpm_log(handle, ALPM_LOG_WARNING, _("couldn't create package cache, using /tmp instead\n")); - return "/tmp/"; + /* we didn't find a valid cache directory. use TMPDIR or /tmp. */ + if((tmpdir = getenv("TMPDIR")) && stat(tmpdir, &buf) && S_ISDIR(buf.st_mode)) { + /* TMPDIR was good, we can use it */ + } else { + tmpdir = "/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. |