Download to a temporary directory owned by the Download user
Signed-off-by: Remi Gacogne <rgacogne@archlinux.org> Signed-off-by: Allan McRae <allan@archlinux.org>
This commit is contained in:
parent
11c8eca9a6
commit
e1a7b83e8e
7 changed files with 194 additions and 27 deletions
|
@ -208,10 +208,8 @@ Options
|
||||||
stream is used (i.e. downloads happen sequentially).
|
stream is used (i.e. downloads happen sequentially).
|
||||||
|
|
||||||
*DownloadUser =* username::
|
*DownloadUser =* username::
|
||||||
Specifies the user to switch to for downloading files. That user should exist
|
Specifies the user to switch to for downloading files. If this config
|
||||||
on the system and have the permissions to write to the files located in
|
option is not set then the downloads are done as the user running pacman.
|
||||||
`DBPath/sync` and `CacheDir`. If this config option is not set then the
|
|
||||||
downloads are done as the user running pacman.
|
|
||||||
|
|
||||||
|
|
||||||
Repository Sections
|
Repository Sections
|
||||||
|
|
|
@ -138,6 +138,7 @@ valid:
|
||||||
|
|
||||||
int SYMEXPORT alpm_db_update(alpm_handle_t *handle, alpm_list_t *dbs, int force) {
|
int SYMEXPORT alpm_db_update(alpm_handle_t *handle, alpm_list_t *dbs, int force) {
|
||||||
char *syncpath;
|
char *syncpath;
|
||||||
|
char *temporary_syncpath;
|
||||||
const char *dbext = handle->dbext;
|
const char *dbext = handle->dbext;
|
||||||
alpm_list_t *i;
|
alpm_list_t *i;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
@ -152,6 +153,8 @@ int SYMEXPORT alpm_db_update(alpm_handle_t *handle, alpm_list_t *dbs, int force)
|
||||||
|
|
||||||
syncpath = get_sync_dir(handle);
|
syncpath = get_sync_dir(handle);
|
||||||
ASSERT(syncpath != NULL, return -1);
|
ASSERT(syncpath != NULL, return -1);
|
||||||
|
temporary_syncpath = _alpm_temporary_download_dir_setup(syncpath, handle->sandboxuser);
|
||||||
|
ASSERT(temporary_syncpath != NULL, FREE(syncpath); return -1);
|
||||||
|
|
||||||
/* make sure we have a sane umask */
|
/* make sure we have a sane umask */
|
||||||
oldmask = umask(0022);
|
oldmask = umask(0022);
|
||||||
|
@ -193,8 +196,8 @@ int SYMEXPORT alpm_db_update(alpm_handle_t *handle, alpm_list_t *dbs, int force)
|
||||||
STRDUP(payload->remote_name, payload->filepath,
|
STRDUP(payload->remote_name, payload->filepath,
|
||||||
_alpm_dload_payload_reset(payload); FREE(payload);
|
_alpm_dload_payload_reset(payload); FREE(payload);
|
||||||
GOTO_ERR(handle, ALPM_ERR_MEMORY, cleanup));
|
GOTO_ERR(handle, ALPM_ERR_MEMORY, cleanup));
|
||||||
payload->destfile_name = _alpm_get_fullpath(syncpath, payload->remote_name, "");
|
payload->destfile_name = _alpm_get_fullpath(temporary_syncpath, payload->remote_name, "");
|
||||||
payload->tempfile_name = _alpm_get_fullpath(syncpath, payload->remote_name, ".part");
|
payload->tempfile_name = _alpm_get_fullpath(temporary_syncpath, payload->remote_name, ".part");
|
||||||
if(!payload->destfile_name || !payload->tempfile_name) {
|
if(!payload->destfile_name || !payload->tempfile_name) {
|
||||||
_alpm_dload_payload_reset(payload);
|
_alpm_dload_payload_reset(payload);
|
||||||
FREE(payload);
|
FREE(payload);
|
||||||
|
@ -217,7 +220,7 @@ int SYMEXPORT alpm_db_update(alpm_handle_t *handle, alpm_list_t *dbs, int force)
|
||||||
|
|
||||||
event.type = ALPM_EVENT_DB_RETRIEVE_START;
|
event.type = ALPM_EVENT_DB_RETRIEVE_START;
|
||||||
EVENT(handle, &event);
|
EVENT(handle, &event);
|
||||||
ret = _alpm_download(handle, payloads, syncpath);
|
ret = _alpm_download(handle, payloads, syncpath, temporary_syncpath);
|
||||||
if(ret < 0) {
|
if(ret < 0) {
|
||||||
event.type = ALPM_EVENT_DB_RETRIEVE_FAILED;
|
event.type = ALPM_EVENT_DB_RETRIEVE_FAILED;
|
||||||
EVENT(handle, &event);
|
EVENT(handle, &event);
|
||||||
|
@ -265,7 +268,9 @@ cleanup:
|
||||||
alpm_list_free_inner(payloads, (alpm_list_fn_free)_alpm_dload_payload_reset);
|
alpm_list_free_inner(payloads, (alpm_list_fn_free)_alpm_dload_payload_reset);
|
||||||
FREELIST(payloads);
|
FREELIST(payloads);
|
||||||
}
|
}
|
||||||
free(syncpath);
|
_alpm_remove_temporary_download_dir(temporary_syncpath);
|
||||||
|
FREE(temporary_syncpath);
|
||||||
|
FREE(syncpath);
|
||||||
umask(oldmask);
|
umask(oldmask);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#ifdef HAVE_NETINET_IN_H
|
||||||
#include <netinet/in.h> /* IPPROTO_TCP */
|
#include <netinet/in.h> /* IPPROTO_TCP */
|
||||||
|
@ -71,6 +73,20 @@ static mode_t _getumask(void)
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int finalize_download_file(const char *filename)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
ASSERT(filename != NULL, return -1);
|
||||||
|
ASSERT(stat(filename, &st) == 0, return -1);
|
||||||
|
if(st.st_size == 0) {
|
||||||
|
unlink(filename);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ASSERT(chown(filename, 0, 0) != -1, return -1);
|
||||||
|
ASSERT(chmod(filename, ~(_getumask()) & 0666) != -1, return -1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static FILE *create_tempfile(struct dload_payload *payload, const char *localpath)
|
static FILE *create_tempfile(struct dload_payload *payload, const char *localpath)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -1061,20 +1077,72 @@ static int payload_download_fetchcb(struct dload_payload *payload,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int move_file(const char *filepath, const char *directory)
|
||||||
|
{
|
||||||
|
ASSERT(filepath != NULL, return -1);
|
||||||
|
ASSERT(directory != NULL, return -1);
|
||||||
|
int ret = finalize_download_file(filepath);
|
||||||
|
if(ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
const char *filename = mbasename(filepath);
|
||||||
|
char *dest = _alpm_get_fullpath(directory, filename, "");
|
||||||
|
if(rename(filepath, dest)) {
|
||||||
|
FREE(dest);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
FREE(dest);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int finalize_download_locations(alpm_list_t *payloads, const char *localpath)
|
||||||
|
{
|
||||||
|
ASSERT(payloads != NULL, return -1);
|
||||||
|
ASSERT(localpath != NULL, return -1);
|
||||||
|
alpm_list_t *p;
|
||||||
|
int returnvalue = 0;
|
||||||
|
for(p = payloads; p; p = p->next) {
|
||||||
|
struct dload_payload *payload = p->data;
|
||||||
|
if(payload->tempfile_name) {
|
||||||
|
move_file(payload->tempfile_name, localpath);
|
||||||
|
}
|
||||||
|
if(payload->destfile_name) {
|
||||||
|
int ret = move_file(payload->destfile_name, localpath);
|
||||||
|
|
||||||
|
if(ret == -1) {
|
||||||
|
returnvalue = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload->download_signature) {
|
||||||
|
const char sig_suffix[] = ".sig";
|
||||||
|
char *sig_filename = NULL;
|
||||||
|
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);
|
||||||
|
FREE(sig_filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnvalue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns -1 if an error happened for a required file
|
/* Returns -1 if an error happened for a required file
|
||||||
* Returns 0 if a payload was actually downloaded
|
* Returns 0 if a payload was actually downloaded
|
||||||
* Returns 1 if no files were downloaded and all errors were non-fatal
|
* Returns 1 if no files were downloaded and all errors were non-fatal
|
||||||
*/
|
*/
|
||||||
int _alpm_download(alpm_handle_t *handle,
|
int _alpm_download(alpm_handle_t *handle,
|
||||||
alpm_list_t *payloads /* struct dload_payload */,
|
alpm_list_t *payloads /* struct dload_payload */,
|
||||||
const char *localpath)
|
const char *localpath,
|
||||||
|
const char *temporary_localpath)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
if(handle->fetchcb == NULL) {
|
if(handle->fetchcb == NULL) {
|
||||||
#ifdef HAVE_LIBCURL
|
#ifdef HAVE_LIBCURL
|
||||||
if(handle->sandboxuser) {
|
if(handle->sandboxuser) {
|
||||||
return curl_download_internal_sandboxed(handle, payloads, localpath);
|
ret = curl_download_internal_sandboxed(handle, payloads, temporary_localpath);
|
||||||
} else {
|
} else {
|
||||||
return curl_download_internal(handle, payloads);
|
ret = curl_download_internal(handle, payloads);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
RET_ERR(handle, ALPM_ERR_EXTERNAL_DOWNLOAD, -1);
|
RET_ERR(handle, ALPM_ERR_EXTERNAL_DOWNLOAD, -1);
|
||||||
|
@ -1085,10 +1153,10 @@ int _alpm_download(alpm_handle_t *handle,
|
||||||
for(p = payloads; p; p = p->next) {
|
for(p = payloads; p; p = p->next) {
|
||||||
struct dload_payload *payload = p->data;
|
struct dload_payload *payload = p->data;
|
||||||
alpm_list_t *s;
|
alpm_list_t *s;
|
||||||
int ret = -1;
|
ret = -1;
|
||||||
|
|
||||||
if(payload->fileurl) {
|
if(payload->fileurl) {
|
||||||
ret = handle->fetchcb(handle->fetchcb_ctx, payload->fileurl, localpath, payload->force);
|
ret = handle->fetchcb(handle->fetchcb_ctx, payload->fileurl, temporary_localpath, payload->force);
|
||||||
if (ret != -1 && payload->download_signature) {
|
if (ret != -1 && payload->download_signature) {
|
||||||
/* Download signature if requested */
|
/* Download signature if requested */
|
||||||
char *sig_fileurl;
|
char *sig_fileurl;
|
||||||
|
@ -1098,7 +1166,7 @@ int _alpm_download(alpm_handle_t *handle,
|
||||||
MALLOC(sig_fileurl, sig_len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
|
MALLOC(sig_fileurl, sig_len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
|
||||||
snprintf(sig_fileurl, sig_len, "%s.sig", payload->fileurl);
|
snprintf(sig_fileurl, sig_len, "%s.sig", payload->fileurl);
|
||||||
|
|
||||||
retsig = handle->fetchcb(handle->fetchcb_ctx, sig_fileurl, localpath, payload->force);
|
retsig = handle->fetchcb(handle->fetchcb_ctx, sig_fileurl, temporary_localpath, payload->force);
|
||||||
free(sig_fileurl);
|
free(sig_fileurl);
|
||||||
|
|
||||||
if(!payload->signature_optional) {
|
if(!payload->signature_optional) {
|
||||||
|
@ -1107,13 +1175,13 @@ int _alpm_download(alpm_handle_t *handle,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(s = payload->cache_servers; s; s = s->next) {
|
for(s = payload->cache_servers; s; s = s->next) {
|
||||||
ret = payload_download_fetchcb(payload, s->data, localpath);
|
ret = payload_download_fetchcb(payload, s->data, temporary_localpath);
|
||||||
if (ret != -1) {
|
if (ret != -1) {
|
||||||
goto download_signature;
|
goto download_signature;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(s = payload->servers; s; s = s->next) {
|
for(s = payload->servers; s; s = s->next) {
|
||||||
ret = payload_download_fetchcb(payload, s->data, localpath);
|
ret = payload_download_fetchcb(payload, s->data, temporary_localpath);
|
||||||
if (ret != -1) {
|
if (ret != -1) {
|
||||||
goto download_signature;
|
goto download_signature;
|
||||||
}
|
}
|
||||||
|
@ -1129,7 +1197,7 @@ download_signature:
|
||||||
MALLOC(sig_fileurl, sig_len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
|
MALLOC(sig_fileurl, sig_len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
|
||||||
snprintf(sig_fileurl, sig_len, "%s/%s.sig", (const char *)(s->data), payload->filepath);
|
snprintf(sig_fileurl, sig_len, "%s/%s.sig", (const char *)(s->data), payload->filepath);
|
||||||
|
|
||||||
retsig = handle->fetchcb(handle->fetchcb_ctx, sig_fileurl, localpath, payload->force);
|
retsig = handle->fetchcb(handle->fetchcb_ctx, sig_fileurl, temporary_localpath, payload->force);
|
||||||
free(sig_fileurl);
|
free(sig_fileurl);
|
||||||
|
|
||||||
if(!payload->signature_optional) {
|
if(!payload->signature_optional) {
|
||||||
|
@ -1144,8 +1212,13 @@ download_signature:
|
||||||
updated = 1;
|
updated = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return updated ? 0 : 1;
|
ret = updated ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (finalize_download_locations(payloads, localpath) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *filecache_find_url(alpm_handle_t *handle, const char *url)
|
static char *filecache_find_url(alpm_handle_t *handle, const char *url)
|
||||||
|
@ -1168,6 +1241,7 @@ int SYMEXPORT alpm_fetch_pkgurl(alpm_handle_t *handle, const alpm_list_t *urls,
|
||||||
alpm_list_t **fetched)
|
alpm_list_t **fetched)
|
||||||
{
|
{
|
||||||
const char *cachedir;
|
const char *cachedir;
|
||||||
|
char *temporary_cachedir = NULL;
|
||||||
alpm_list_t *payloads = NULL;
|
alpm_list_t *payloads = NULL;
|
||||||
const alpm_list_t *i;
|
const alpm_list_t *i;
|
||||||
alpm_event_t event = {0};
|
alpm_event_t event = {0};
|
||||||
|
@ -1177,6 +1251,8 @@ int SYMEXPORT alpm_fetch_pkgurl(alpm_handle_t *handle, const alpm_list_t *urls,
|
||||||
|
|
||||||
/* find a valid cache dir to download to */
|
/* find a valid cache dir to download to */
|
||||||
cachedir = _alpm_filecache_setup(handle);
|
cachedir = _alpm_filecache_setup(handle);
|
||||||
|
temporary_cachedir = _alpm_temporary_download_dir_setup(cachedir, handle->sandboxuser);
|
||||||
|
ASSERT(temporary_cachedir != NULL, return -1);
|
||||||
|
|
||||||
for(i = urls; i; i = i->next) {
|
for(i = urls; i; i = i->next) {
|
||||||
char *url = i->data;
|
char *url = i->data;
|
||||||
|
@ -1200,8 +1276,8 @@ int SYMEXPORT alpm_fetch_pkgurl(alpm_handle_t *handle, const alpm_list_t *urls,
|
||||||
c = strrchr(url, '/');
|
c = strrchr(url, '/');
|
||||||
if(c != NULL && strstr(c, ".pkg") && payload->remote_name && strlen(payload->remote_name) > 0) {
|
if(c != NULL && strstr(c, ".pkg") && payload->remote_name && strlen(payload->remote_name) > 0) {
|
||||||
/* we probably have a usable package filename to download to */
|
/* we probably have a usable package filename to download to */
|
||||||
payload->destfile_name = _alpm_get_fullpath(cachedir, payload->remote_name, "");
|
payload->destfile_name = _alpm_get_fullpath(temporary_cachedir, payload->remote_name, "");
|
||||||
payload->tempfile_name = _alpm_get_fullpath(cachedir, payload->remote_name, ".part");
|
payload->tempfile_name = _alpm_get_fullpath(temporary_cachedir, payload->remote_name, ".part");
|
||||||
payload->allow_resume = 1;
|
payload->allow_resume = 1;
|
||||||
|
|
||||||
if(!payload->destfile_name || !payload->tempfile_name) {
|
if(!payload->destfile_name || !payload->tempfile_name) {
|
||||||
|
@ -1215,7 +1291,7 @@ int SYMEXPORT alpm_fetch_pkgurl(alpm_handle_t *handle, const alpm_list_t *urls,
|
||||||
payload->unlink_on_fail = 1;
|
payload->unlink_on_fail = 1;
|
||||||
|
|
||||||
payload->tempfile_openmode = "wb";
|
payload->tempfile_openmode = "wb";
|
||||||
payload->localf = create_tempfile(payload, cachedir);
|
payload->localf = create_tempfile(payload, temporary_cachedir);
|
||||||
if(payload->localf == NULL) {
|
if(payload->localf == NULL) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -1232,7 +1308,7 @@ int SYMEXPORT alpm_fetch_pkgurl(alpm_handle_t *handle, const alpm_list_t *urls,
|
||||||
event.type = ALPM_EVENT_PKG_RETRIEVE_START;
|
event.type = ALPM_EVENT_PKG_RETRIEVE_START;
|
||||||
event.pkg_retrieve.num = alpm_list_count(payloads);
|
event.pkg_retrieve.num = alpm_list_count(payloads);
|
||||||
EVENT(handle, &event);
|
EVENT(handle, &event);
|
||||||
if(_alpm_download(handle, payloads, cachedir) == -1) {
|
if(_alpm_download(handle, payloads, cachedir, temporary_cachedir) == -1) {
|
||||||
_alpm_log(handle, ALPM_LOG_WARNING, _("failed to retrieve some files\n"));
|
_alpm_log(handle, ALPM_LOG_WARNING, _("failed to retrieve some files\n"));
|
||||||
event.type = ALPM_EVENT_PKG_RETRIEVE_FAILED;
|
event.type = ALPM_EVENT_PKG_RETRIEVE_FAILED;
|
||||||
EVENT(handle, &event);
|
EVENT(handle, &event);
|
||||||
|
@ -1265,10 +1341,14 @@ int SYMEXPORT alpm_fetch_pkgurl(alpm_handle_t *handle, const alpm_list_t *urls,
|
||||||
FREELIST(payloads);
|
FREELIST(payloads);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_alpm_remove_temporary_download_dir(temporary_cachedir);
|
||||||
|
FREE(temporary_cachedir);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
alpm_list_free_inner(payloads, (alpm_list_fn_free)_alpm_dload_payload_reset);
|
alpm_list_free_inner(payloads, (alpm_list_fn_free)_alpm_dload_payload_reset);
|
||||||
|
_alpm_remove_temporary_download_dir(temporary_cachedir);
|
||||||
|
FREE(temporary_cachedir);
|
||||||
FREELIST(payloads);
|
FREELIST(payloads);
|
||||||
FREELIST(*fetched);
|
FREELIST(*fetched);
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@ void _alpm_dload_payload_reset(struct dload_payload *payload);
|
||||||
|
|
||||||
int _alpm_download(alpm_handle_t *handle,
|
int _alpm_download(alpm_handle_t *handle,
|
||||||
alpm_list_t *payloads /* struct dload_payload */,
|
alpm_list_t *payloads /* struct dload_payload */,
|
||||||
const char *localpath);
|
const char *localpath,
|
||||||
|
const char *temporary_localpath);
|
||||||
|
|
||||||
#endif /* ALPM_DLOAD_H */
|
#endif /* ALPM_DLOAD_H */
|
||||||
|
|
|
@ -773,12 +773,18 @@ static int find_dl_candidates(alpm_handle_t *handle, alpm_list_t **files)
|
||||||
static int download_files(alpm_handle_t *handle)
|
static int download_files(alpm_handle_t *handle)
|
||||||
{
|
{
|
||||||
const char *cachedir;
|
const char *cachedir;
|
||||||
|
char * temporary_cachedir = NULL;
|
||||||
alpm_list_t *i, *files = NULL;
|
alpm_list_t *i, *files = NULL;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
alpm_event_t event = {0};
|
alpm_event_t event = {0};
|
||||||
alpm_list_t *payloads = NULL;
|
alpm_list_t *payloads = NULL;
|
||||||
|
|
||||||
cachedir = _alpm_filecache_setup(handle);
|
cachedir = _alpm_filecache_setup(handle);
|
||||||
|
temporary_cachedir = _alpm_temporary_download_dir_setup(cachedir, handle->sandboxuser);
|
||||||
|
if(temporary_cachedir == NULL) {
|
||||||
|
ret = -1;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
handle->trans->state = STATE_DOWNLOADING;
|
handle->trans->state = STATE_DOWNLOADING;
|
||||||
|
|
||||||
ret = find_dl_candidates(handle, &files);
|
ret = find_dl_candidates(handle, &files);
|
||||||
|
@ -802,7 +808,7 @@ static int download_files(alpm_handle_t *handle)
|
||||||
file_sizes[idx] = pkg->size;
|
file_sizes[idx] = pkg->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = _alpm_check_downloadspace(handle, cachedir, num_files, file_sizes);
|
ret = _alpm_check_downloadspace(handle, temporary_cachedir, num_files, file_sizes);
|
||||||
free(file_sizes);
|
free(file_sizes);
|
||||||
|
|
||||||
if(ret != 0) {
|
if(ret != 0) {
|
||||||
|
@ -830,8 +836,8 @@ static int download_files(alpm_handle_t *handle)
|
||||||
STRDUP(payload->filepath, pkg->filename,
|
STRDUP(payload->filepath, pkg->filename,
|
||||||
_alpm_dload_payload_reset(payload); FREE(payload);
|
_alpm_dload_payload_reset(payload); FREE(payload);
|
||||||
GOTO_ERR(handle, ALPM_ERR_MEMORY, finish));
|
GOTO_ERR(handle, ALPM_ERR_MEMORY, finish));
|
||||||
payload->destfile_name = _alpm_get_fullpath(cachedir, payload->remote_name, "");
|
payload->destfile_name = _alpm_get_fullpath(temporary_cachedir, payload->remote_name, "");
|
||||||
payload->tempfile_name = _alpm_get_fullpath(cachedir, payload->remote_name, ".part");
|
payload->tempfile_name = _alpm_get_fullpath(temporary_cachedir, payload->remote_name, ".part");
|
||||||
if(!payload->destfile_name || !payload->tempfile_name) {
|
if(!payload->destfile_name || !payload->tempfile_name) {
|
||||||
_alpm_dload_payload_reset(payload);
|
_alpm_dload_payload_reset(payload);
|
||||||
FREE(payload);
|
FREE(payload);
|
||||||
|
@ -848,7 +854,7 @@ static int download_files(alpm_handle_t *handle)
|
||||||
payloads = alpm_list_add(payloads, payload);
|
payloads = alpm_list_add(payloads, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = _alpm_download(handle, payloads, cachedir);
|
ret = _alpm_download(handle, payloads, cachedir, temporary_cachedir);
|
||||||
if(ret == -1) {
|
if(ret == -1) {
|
||||||
event.type = ALPM_EVENT_PKG_RETRIEVE_FAILED;
|
event.type = ALPM_EVENT_PKG_RETRIEVE_FAILED;
|
||||||
EVENT(handle, &event);
|
EVENT(handle, &event);
|
||||||
|
@ -874,6 +880,8 @@ finish:
|
||||||
pkg->infolevel &= ~INFRQ_DSIZE;
|
pkg->infolevel &= ~INFRQ_DSIZE;
|
||||||
pkg->download_size = 0;
|
pkg->download_size = 0;
|
||||||
}
|
}
|
||||||
|
_alpm_remove_temporary_download_dir(temporary_cachedir);
|
||||||
|
FREE(temporary_cachedir);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,9 +31,11 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <fnmatch.h>
|
#include <fnmatch.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
#include <pwd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
/* libarchive */
|
/* libarchive */
|
||||||
|
@ -946,6 +948,76 @@ const char *_alpm_filecache_setup(alpm_handle_t *handle)
|
||||||
return cachedir;
|
return cachedir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 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 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)
|
||||||
|
{
|
||||||
|
struct passwd const *pw = NULL;
|
||||||
|
|
||||||
|
ASSERT(dir != NULL, return NULL);
|
||||||
|
if(user != NULL) {
|
||||||
|
ASSERT((pw = getpwnam(user)) != NULL, return NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char template[] = "download-XXXXXX";
|
||||||
|
size_t newdirlen = strlen(dir) + sizeof(template) + 1;
|
||||||
|
char *newdir = NULL;
|
||||||
|
MALLOC(newdir, newdirlen, return NULL);
|
||||||
|
snprintf(newdir, newdirlen - 1, "%s%s", dir, template);
|
||||||
|
newdir = mkdtemp(newdir);
|
||||||
|
if(newdir == NULL) {
|
||||||
|
free(newdir);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(pw != NULL) {
|
||||||
|
if(chown(newdir, pw->pw_uid, pw->pw_gid) == -1) {
|
||||||
|
free(newdir);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newdir[newdirlen-2] = '/';
|
||||||
|
newdir[newdirlen-1] = 0;
|
||||||
|
return newdir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Remove a temporary directory.
|
||||||
|
* The temporary download directory is removed after deleting any
|
||||||
|
* leftover files.
|
||||||
|
* @param dir directory to be removed
|
||||||
|
*/
|
||||||
|
void _alpm_remove_temporary_download_dir(const char *dir)
|
||||||
|
{
|
||||||
|
ASSERT(dir != NULL, return);
|
||||||
|
size_t dirlen = strlen(dir);
|
||||||
|
struct dirent *dp = NULL;
|
||||||
|
DIR *dirp = opendir(dir);
|
||||||
|
if(!dirp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
|
||||||
|
if(strcmp(dp->d_name, "..") != 0 && strcmp(dp->d_name, ".") != 0) {
|
||||||
|
char name[PATH_MAX];
|
||||||
|
if(dirlen + strlen(dp->d_name) + 2 > PATH_MAX) {
|
||||||
|
/* file path is too long to remove, hmm. */
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
sprintf(name, "%s/%s", dir, dp->d_name);
|
||||||
|
if(unlink(name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dirp);
|
||||||
|
rmdir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined HAVE_LIBSSL || defined HAVE_LIBNETTLE
|
#if defined HAVE_LIBSSL || defined HAVE_LIBNETTLE
|
||||||
/** Compute the MD5 message digest of a file.
|
/** Compute the MD5 message digest of a file.
|
||||||
* @param path file path of file to compute MD5 digest of
|
* @param path file path of file to compute MD5 digest of
|
||||||
|
|
|
@ -139,6 +139,9 @@ char *_alpm_filecache_find(alpm_handle_t *handle, const char *filename);
|
||||||
/* Checks whether a file exists in cache */
|
/* Checks whether a file exists in cache */
|
||||||
int _alpm_filecache_exists(alpm_handle_t *handle, const char *filename);
|
int _alpm_filecache_exists(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);
|
||||||
|
char *_alpm_temporary_download_dir_setup(const char *dir, const char *user);
|
||||||
|
void _alpm_remove_temporary_download_dir(const char *dir);
|
||||||
|
|
||||||
/* Unlike many uses of alpm_pkgvalidation_t, _alpm_test_checksum expects
|
/* Unlike many uses of alpm_pkgvalidation_t, _alpm_test_checksum expects
|
||||||
* an enum value rather than a bitfield. */
|
* an enum value rather than a bitfield. */
|
||||||
int _alpm_test_checksum(const char *filepath, const char *expected, alpm_pkgvalidation_t type);
|
int _alpm_test_checksum(const char *filepath, const char *expected, alpm_pkgvalidation_t type);
|
||||||
|
|
Loading…
Add table
Reference in a new issue