[pacman-dev] [PATCH] Download sync database into temporary directory
Dave Reisner
d at falconindy.com
Wed Jan 8 13:31:30 UTC 2020
On Wed, Jan 8, 2020, 07:30 Allan McRae <allan at archlinux.org> wrote:
> Sync databases (and signatures) are downloaded into a temporary directory.
> On success, they are copied into the sync directory.
>
Why not use a temporary file in the sync dir? That allows you to rename
atomically instead of copy+unlink. My guess is it's less code, too.
Currently, this achieves nothing but adding complexity, but it does open
> up the possibility of validating sync databases on download before
> replacing
> the old version.
>
> Signed-off-by: Allan McRae <allan at archlinux.org>
> ---
>
> This patch was long enough, and there is still quite a bit to do to
> validate
> the download sync databases before replacing the old ones, so best to stop
> here.
>
> lib/libalpm/be_sync.c | 90 +++++++++++++++++++++++++++++++++----------
> 1 file changed, 69 insertions(+), 21 deletions(-)
>
> diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c
> index f1caddd8..99bdba54 100644
> --- a/lib/libalpm/be_sync.c
> +++ b/lib/libalpm/be_sync.c
> @@ -173,8 +173,9 @@ valid:
> */
> int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)
> {
> - char *syncpath;
> - const char *dbext;
> + char *syncpath, *sigpath = NULL;
> + char *tmpdir = NULL, *tmppath = NULL, *tmpsig = NULL;
> + const char *dbpath, *dbext;
> alpm_list_t *i;
> int updated = 0;
> int ret = -1;
> @@ -193,11 +194,22 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t
> *db)
> return 0;
> }
>
> + /* attempt to grab a lock */
> + if(_alpm_handle_lock(handle)) {
> + RET_ERR(handle, ALPM_ERR_HANDLE_LOCK, -1);
> + }
> +
> syncpath = get_sync_dir(handle);
> if(!syncpath) {
> return -1;
> }
>
> + /* create temporary directory to download databases into */
> + if(_alpm_mkdtemp(handle, &tmpdir) == 0) {
> + free(syncpath);
> + return -1;
> + }
> +
> /* force update of invalid databases to fix potential mismatched
> database/signature */
> if(db->status & DB_STATUS_INVALID) {
> force = 1;
> @@ -207,15 +219,41 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t
> *db)
> oldmask = umask(0022);
>
> siglevel = alpm_db_get_siglevel(db);
> + dbext = handle->dbext;
>
> - /* attempt to grab a lock */
> - if(_alpm_handle_lock(handle)) {
> - free(syncpath);
> - umask(oldmask);
> - RET_ERR(handle, ALPM_ERR_HANDLE_LOCK, -1);
> + dbpath = _alpm_db_path(db);
> + if(dbpath == NULL) {
> + /* pm_errno set in _alpm_db_path() */
> + ret = -1;
> + goto cleanup;
> }
>
> - dbext = handle->dbext;
> + if((sigpath = _alpm_sigpath(handle, _alpm_db_path(db))) == NULL) {
> + /* pm_errno is set by _alpm_sigpath */
> + ret = -1;
> + goto cleanup;
> + }
> +
> + if(asprintf(&tmppath, "%s%s%s", tmpdir, db->treename, dbext) ==
> -1) {
> + handle->pm_errno = ALPM_ERR_MEMORY;
> + ret = -1;
> + goto cleanup;
> + }
> +
> + if(asprintf(&tmpsig, "%s%s%s.sig", tmpdir, db->treename, dbext) ==
> -1) {
> + handle->pm_errno = ALPM_ERR_MEMORY;
> + ret = -1;
> + goto cleanup;
> + }
> +
> + /* copy current db into tempdir to allow up-to-date db handling */
> + if(force == 0) {
> + if(_alpm_copyfile_with_time(dbpath, tmppath) != 0) {
> + handle->pm_errno = ALPM_ERR_SYSTEM;
> + ret = -1;
> + goto cleanup;
> + };
> + }
>
> for(i = db->servers; i; i = i->next) {
> const char *server = i->data, *final_db_url = NULL;
> @@ -240,22 +278,11 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t
> *db)
> payload.force = force;
> payload.unlink_on_fail = 1;
>
> - ret = _alpm_download(&payload, syncpath, NULL,
> &final_db_url);
> + ret = _alpm_download(&payload, tmpdir, NULL,
> &final_db_url);
> _alpm_dload_payload_reset(&payload);
> updated = (updated || ret == 0);
>
> if(ret != -1 && updated && (siglevel & ALPM_SIG_DATABASE))
> {
> - /* an existing sig file is no good at this point */
> - char *sigpath = _alpm_sigpath(handle,
> _alpm_db_path(db));
> - if(!sigpath) {
> - /* pm_errno is set by _alpm_sigpath */
> - ret = -1;
> - goto cleanup;
> - }
> - unlink(sigpath);
> - free(sigpath);
> -
> -
> /* check if the final URL from internal downloader
> looks reasonable */
> if(final_db_url != NULL) {
> if(strlen(final_db_url) < 3
> @@ -295,7 +322,7 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)
> /* set hard upper limit of 16KiB */
> payload.max_size = 16 * 1024;
>
> - sig_ret = _alpm_download(&payload, syncpath, NULL,
> NULL);
> + sig_ret = _alpm_download(&payload, tmpdir, NULL,
> NULL);
> /* errors_ok suppresses error messages, but not
> the return code */
> sig_ret = payload.errors_ok ? 0 : sig_ret;
> _alpm_dload_payload_reset(&payload);
> @@ -306,6 +333,15 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)
> }
> }
>
> + /* copy the downloaded database into the sync directory */
> + unlink(dbpath);
> + _alpm_copyfile_with_time(tmppath, dbpath);
> +
> + unlink(sigpath);
> + if(_alpm_access(handle, NULL, sigpath, R_OK) == 0) {
> + _alpm_copyfile_with_time(tmpsig, sigpath);
> + }
> +
> cleanup:
> if(updated) {
> /* Cache needs to be rebuilt */
> @@ -332,8 +368,20 @@ cleanup:
> handle->pm_errno = ALPM_ERR_OK;
> }
>
> + /* clean-up temporary directory */
> + unlink(tmppath);
> + unlink(tmpsig);
> + if(rmdir(tmpdir)) {
> + _alpm_log(handle, ALPM_LOG_WARNING,
> + _("could not remove tmpdir %s\n"), tmpdir);
> + }
> + free(tmpdir);
> + free(tmppath);
> + free(tmpsig);
> +
> _alpm_handle_unlock(handle);
> free(syncpath);
> + free(sigpath);
> umask(oldmask);
> return ret;
> }
> --
> 2.24.1
>
More information about the pacman-dev
mailing list