diff options
Diffstat (limited to 'lib/libalpm/trans.c')
-rw-r--r-- | lib/libalpm/trans.c | 97 |
1 files changed, 74 insertions, 23 deletions
diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c index 02612ec1..4b29f9a8 100644 --- a/lib/libalpm/trans.c +++ b/lib/libalpm/trans.c @@ -1,7 +1,7 @@ /* * trans.c * - * Copyright (c) 2006-2010 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> @@ -31,6 +31,8 @@ #include <sys/stat.h> #include <sys/statvfs.h> #include <errno.h> +#include <limits.h> +#include <fcntl.h> /* libalpm */ #include "trans.h" @@ -44,13 +46,57 @@ #include "sync.h" #include "alpm.h" #include "deps.h" -#include "cache.h" /** \addtogroup alpm_trans Transaction Functions * @brief Functions to manipulate libalpm transactions * @{ */ +/* Create a lock file */ +static int make_lock(pmhandle_t *handle) +{ + int fd; + char *dir, *ptr; + + /* create the dir of the lockfile first */ + dir = strdup(handle->lockfile); + ptr = strrchr(dir, '/'); + if(ptr) { + *ptr = '\0'; + } + if(_alpm_makepath(dir)) { + FREE(dir); + return(-1); + } + FREE(dir); + + do { + fd = open(handle->lockfile, O_WRONLY | O_CREAT | O_EXCL, 0000); + } while (fd == -1 && errno == EINTR); + if(fd > 0) { + FILE *f = fdopen(fd, "w"); + fprintf(f, "%ld\n", (long)getpid()); + fflush(f); + fsync(fd); + handle->lckstream = f; + return(0); + } + return(-1); +} + +/* Remove a lock file */ +static int remove_lock(pmhandle_t *handle) +{ + if(handle->lckstream != NULL) { + fclose(handle->lckstream); + handle->lckstream = NULL; + } + if(unlink(handle->lockfile) == -1 && errno != ENOENT) { + return(-1); + } + return(0); +} + /** Initialize the transaction. * @param flags flags of the transaction (like nodeps, etc) * @param event event callback function pointer @@ -59,10 +105,12 @@ * @return 0 on success, -1 on error (pm_errno is set accordingly) */ int SYMEXPORT alpm_trans_init(pmtransflag_t flags, - alpm_trans_cb_event event, alpm_trans_cb_conv conv, - alpm_trans_cb_progress progress) + alpm_trans_cb_event event, alpm_trans_cb_conv conv, + alpm_trans_cb_progress progress) { pmtrans_t *trans; + const int required_db_version = 2; + int db_version; ALPM_LOG_FUNC; @@ -73,12 +121,20 @@ int SYMEXPORT alpm_trans_init(pmtransflag_t flags, /* lock db */ if(!(flags & PM_TRANS_FLAG_NOLOCK)) { - handle->lckfd = _alpm_lckmk(); - if(handle->lckfd == -1) { + if(make_lock(handle)) { RET_ERR(PM_ERR_HANDLE_LOCK, -1); } } + /* check database version */ + db_version = _alpm_db_version(handle->db_local); + if(db_version < required_db_version) { + _alpm_log(PM_LOG_ERROR, + _("%s database version is too old\n"), handle->db_local->treename); + remove_lock(handle); + RET_ERR(PM_ERR_DB_VERSION, -1); + } + trans = _alpm_trans_new(); if(trans == NULL) { RET_ERR(PM_ERR_MEMORY, -1); @@ -218,7 +274,7 @@ int SYMEXPORT alpm_trans_commit(alpm_list_t **data) /** Interrupt a transaction. * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int SYMEXPORT alpm_trans_interrupt() +int SYMEXPORT alpm_trans_interrupt(void) { pmtrans_t *trans; @@ -240,7 +296,7 @@ int SYMEXPORT alpm_trans_interrupt() /** Release a transaction. * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int SYMEXPORT alpm_trans_release() +int SYMEXPORT alpm_trans_release(void) { pmtrans_t *trans; @@ -260,14 +316,7 @@ int SYMEXPORT alpm_trans_release() /* unlock db */ if(!nolock_flag) { - if(handle->lckfd != -1) { - int fd; - do { - fd = close(handle->lckfd); - } while(fd == -1 && errno == EINTR); - handle->lckfd = -1; - } - if(_alpm_lckrm()) { + if(remove_lock(handle)) { _alpm_log(PM_LOG_WARNING, _("could not remove lock file %s\n"), alpm_option_get_lockfile()); alpm_logaction("warning: could not remove lock file %s\n", @@ -280,7 +329,7 @@ int SYMEXPORT alpm_trans_release() /** @} */ -pmtrans_t *_alpm_trans_new() +pmtrans_t *_alpm_trans_new(void) { pmtrans_t *trans; @@ -305,7 +354,6 @@ void _alpm_trans_free(pmtrans_t *trans) alpm_list_free_inner(trans->remove, (alpm_list_fn_free)_alpm_pkg_free); alpm_list_free(trans->remove); - FREELIST(trans->skip_add); FREELIST(trans->skip_remove); FREE(trans); @@ -323,11 +371,11 @@ static int grep(const char *fn, const char *needle) } while(!feof(fp)) { char line[1024]; - int sline = sizeof(line)-1; - fgets(line, sline, fp); - if(feof(fp)) { + if(fgets(line, sizeof(line), fp) == NULL) { continue; } + /* TODO: this will not work if the search string + * ends up being split across line reads */ if(strstr(line, needle)) { fclose(fp); return(1); @@ -344,6 +392,7 @@ int _alpm_runscriptlet(const char *root, const char *installfn, char scriptfn[PATH_MAX]; char cmdline[PATH_MAX]; char tmpdir[PATH_MAX]; + char *argv[] = { "sh", "-c", cmdline, NULL }; char *scriptpath; int clean_tmpdir = 0; int retval = 0; @@ -371,7 +420,7 @@ int _alpm_runscriptlet(const char *root, const char *installfn, /* either extract or copy the scriptlet */ snprintf(scriptfn, PATH_MAX, "%s/.INSTALL", tmpdir); - if(!strcmp(script, "pre_upgrade") || !strcmp(script, "pre_install")) { + if(strcmp(script, "pre_upgrade") == 0 || strcmp(script, "pre_install") == 0) { if(_alpm_unpack_single(installfn, tmpdir, ".INSTALL")) { retval = 1; } @@ -401,7 +450,9 @@ int _alpm_runscriptlet(const char *root, const char *installfn, scriptpath, script, ver); } - retval = _alpm_run_chroot(root, cmdline); + _alpm_log(PM_LOG_DEBUG, "executing \"%s\"\n", cmdline); + + retval = _alpm_run_chroot(root, "/bin/sh", argv); cleanup: if(clean_tmpdir && _alpm_rmrf(tmpdir)) { |