summaryrefslogtreecommitdiff
path: root/lib/libalpm/trans.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/trans.c')
-rw-r--r--lib/libalpm/trans.c175
1 files changed, 71 insertions, 104 deletions
diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c
index 82f11f3d..9eb27c30 100644
--- a/lib/libalpm/trans.c
+++ b/lib/libalpm/trans.c
@@ -33,9 +33,6 @@
#include <sys/statvfs.h>
#include <unistd.h>
#include <errno.h>
-#ifndef __sun__
-#include <mntent.h>
-#endif
/* libalpm */
#include "trans.h"
@@ -165,15 +162,31 @@ int SYMEXPORT alpm_trans_commit(alpm_list_t **data)
ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
ASSERT(handle->trans->state == STATE_PREPARED, RET_ERR(PM_ERR_TRANS_NOT_PREPARED, -1));
- /* Check for database R/W permission */
- if(!(handle->trans->flags & PM_TRANS_FLAG_PRINTURIS)) {
- /* The print-uris operation is a bit odd. So we explicitly check for it */
- ASSERT(handle->access == PM_ACCESS_RW, RET_ERR(PM_ERR_BADPERMS, -1));
- }
-
return(_alpm_trans_commit(handle->trans, data));
}
+/** Interrupt a transaction.
+ * @return 0 on success, -1 on error (pm_errno is set accordingly)
+ */
+int SYMEXPORT alpm_trans_interrupt()
+{
+ pmtrans_t *trans;
+
+ ALPM_LOG_FUNC;
+
+ /* Sanity checks */
+ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
+
+ trans = handle->trans;
+ ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
+ ASSERT(trans->state == STATE_COMMITING || trans->state == STATE_INTERRUPTED,
+ RET_ERR(PM_ERR_TRANS_TYPE, -1));
+
+ trans->state = STATE_INTERRUPTED;
+
+ return(0);
+}
+
/** Release a transaction.
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
@@ -190,15 +203,6 @@ int SYMEXPORT alpm_trans_release()
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
ASSERT(trans->state != STATE_IDLE, RET_ERR(PM_ERR_TRANS_NULL, -1));
- /* during a commit do not interrupt immediately, just after a target */
- if(trans->state == STATE_COMMITING || trans->state == STATE_INTERRUPTED) {
- if(trans->state == STATE_COMMITING) {
- trans->state = STATE_INTERRUPTED;
- }
- pm_errno = PM_ERR_TRANS_COMMITING;
- return(-1);
- }
-
_alpm_trans_free(trans);
handle->trans = NULL;
@@ -208,7 +212,7 @@ int SYMEXPORT alpm_trans_release()
handle->lckfd = -1;
}
if(_alpm_lckrm()) {
- _alpm_log(PM_LOG_WARNING, _("could not remove lock file %s"),
+ _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",
alpm_option_get_lockfile());
@@ -226,7 +230,7 @@ pmtrans_t *_alpm_trans_new()
ALPM_LOG_FUNC;
if((trans = malloc(sizeof(pmtrans_t))) == NULL) {
- _alpm_log(PM_LOG_ERROR, _("malloc failure: could not allocate %d bytes"), sizeof(pmtrans_t));
+ _alpm_log(PM_LOG_ERROR, _("malloc failure: could not allocate %d bytes\n"), sizeof(pmtrans_t));
return(NULL);
}
@@ -304,6 +308,11 @@ int _alpm_trans_sysupgrade(pmtrans_t *trans)
return(_alpm_sync_sysupgrade(trans, handle->db_local, handle->dbs_sync));
}
+/** Add a target to the transaction.
+ * @param trans the current transaction
+ * @param target the name of the target to add
+ * @return 0 on success, -1 on error (pm_errno is set accordingly)
+ */
int _alpm_trans_addtarget(pmtrans_t *trans, char *target)
{
ALPM_LOG_FUNC;
@@ -326,14 +335,15 @@ int _alpm_trans_addtarget(pmtrans_t *trans, char *target)
}
break;
case PM_TRANS_TYPE_REMOVE:
+ case PM_TRANS_TYPE_REMOVEUPGRADE:
if(_alpm_remove_loadtarget(trans, handle->db_local, target) == -1) {
- /* pm_errno is set by remove_loadtarget() */
+ /* pm_errno is set by _alpm_remove_loadtarget() */
return(-1);
}
break;
case PM_TRANS_TYPE_SYNC:
if(_alpm_sync_addtarget(trans, handle->db_local, handle->dbs_sync, target) == -1) {
- /* pm_errno is set by sync_loadtarget() */
+ /* pm_errno is set by _alpm_sync_loadtarget() */
return(-1);
}
break;
@@ -367,6 +377,7 @@ int _alpm_trans_prepare(pmtrans_t *trans, alpm_list_t **data)
}
break;
case PM_TRANS_TYPE_REMOVE:
+ case PM_TRANS_TYPE_REMOVEUPGRADE:
if(_alpm_remove_prepare(trans, handle->db_local, data) == -1) {
/* pm_errno is set by _alpm_remove_prepare() */
return(-1);
@@ -406,13 +417,14 @@ int _alpm_trans_commit(pmtrans_t *trans, alpm_list_t **data)
case PM_TRANS_TYPE_ADD:
case PM_TRANS_TYPE_UPGRADE:
if(_alpm_add_commit(trans, handle->db_local) == -1) {
- /* pm_errno is set by _alpm_add_prepare() */
+ /* pm_errno is set by _alpm_add_commit() */
return(-1);
}
break;
case PM_TRANS_TYPE_REMOVE:
+ case PM_TRANS_TYPE_REMOVEUPGRADE:
if(_alpm_remove_commit(trans, handle->db_local) == -1) {
- /* pm_errno is set by _alpm_remove_prepare() */
+ /* pm_errno is set by _alpm_remove_commit() */
return(-1);
}
break;
@@ -429,6 +441,8 @@ int _alpm_trans_commit(pmtrans_t *trans, alpm_list_t **data)
return(0);
}
+/* A depends on B through n depends <=> A listed in B's requiredby n times
+ * n == 0 or 1 in almost all cases */
int _alpm_trans_update_depends(pmtrans_t *trans, pmpkg_t *pkg)
{
alpm_list_t *i, *j;
@@ -437,7 +451,7 @@ int _alpm_trans_update_depends(pmtrans_t *trans, pmpkg_t *pkg)
pmdb_t *localdb;
ALPM_LOG_FUNC;
-
+
/* Sanity checks */
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
ASSERT(pkg != NULL, RET_ERR(PM_ERR_PKG_INVALID, -1));
@@ -446,95 +460,48 @@ int _alpm_trans_update_depends(pmtrans_t *trans, pmpkg_t *pkg)
depends = alpm_pkg_get_depends(pkg);
if(depends) {
- _alpm_log(PM_LOG_DEBUG, _("updating dependency packages 'requiredby' fields for %s-%s"),
+ _alpm_log(PM_LOG_DEBUG, "updating dependency packages 'requiredby' fields for %s-%s\n",
pkgname, pkg->version);
} else {
- _alpm_log(PM_LOG_DEBUG, _("package has no dependencies, no other packages to update"));
+ _alpm_log(PM_LOG_DEBUG, "package has no dependencies, no other packages to update\n");
}
localdb = alpm_option_get_localdb();
for(i = depends; i; i = i->next) {
+ if(!i->data) {
+ continue;
+ }
pmdepend_t* dep = alpm_splitdep(i->data);
if(dep == NULL) {
continue;
}
-
- if(trans->packages && trans->type == PM_TRANS_TYPE_REMOVE) {
- if(_alpm_pkg_find(dep->name, handle->trans->packages)) {
- continue;
- }
- }
-
- pmpkg_t *deppkg = _alpm_db_get_pkgfromcache(localdb, dep->name);
- if(!deppkg) {
- int found_provides = 0;
- /* look for a provides package */
- alpm_list_t *provides = _alpm_db_whatprovides(localdb, dep->name);
- for(j = provides; j; j = j->next) {
- if(!j->data) {
- continue;
- }
- pmpkg_t *provpkg = j->data;
- deppkg = _alpm_db_get_pkgfromcache(localdb, alpm_pkg_get_name(provpkg));
-
- if(!deppkg) {
- continue;
- }
-
- found_provides = 1;
-
+ for(j = _alpm_db_get_pkgcache(localdb); j; j = j->next) {
+ pmpkg_t *deppkg = j->data;
+ if(deppkg && alpm_depcmp(deppkg, dep)) {
/* this is cheating... we call this function to populate the package */
alpm_list_t *rqdby = alpm_pkg_get_requiredby(deppkg);
- _alpm_log(PM_LOG_DEBUG, _("updating 'requiredby' field for package '%s'"),
+ _alpm_log(PM_LOG_DEBUG, "updating 'requiredby' field for package '%s'\n",
alpm_pkg_get_name(deppkg));
- if(trans->type == PM_TRANS_TYPE_REMOVE) {
+
+ if(trans->type == PM_TRANS_TYPE_REMOVE
+ || trans->type == PM_TRANS_TYPE_REMOVEUPGRADE) {
void *data = NULL;
rqdby = alpm_list_remove(rqdby, pkgname, _alpm_str_cmp, &data);
FREE(data);
deppkg->requiredby = rqdby;
} else {
- if(!alpm_list_find_str(rqdby, pkgname)) {
- rqdby = alpm_list_add(rqdby, strdup(pkgname));
- deppkg->requiredby = rqdby;
- }
+ rqdby = alpm_list_add(rqdby, strdup(pkgname));
+ deppkg->requiredby = rqdby;
}
if(_alpm_db_write(localdb, deppkg, INFRQ_DEPENDS)) {
- _alpm_log(PM_LOG_ERROR, _("could not update 'requiredby' database entry %s-%s"),
+ _alpm_log(PM_LOG_ERROR, _("could not update 'requiredby' database entry %s-%s\n"),
alpm_pkg_get_name(deppkg), alpm_pkg_get_version(deppkg));
}
}
- alpm_list_free(provides);
-
- if(!found_provides) {
- _alpm_log(PM_LOG_DEBUG, _("could not find dependency '%s'"), dep->name);
- continue;
- }
- }
-
- /* this is cheating... we call this function to populate the package */
- alpm_list_t *rqdby = alpm_pkg_get_requiredby(deppkg);
-
- _alpm_log(PM_LOG_DEBUG, _("updating 'requiredby' field for package '%s'"),
- alpm_pkg_get_name(deppkg));
- if(trans->type == PM_TRANS_TYPE_REMOVE) {
- void *data = NULL;
- rqdby = alpm_list_remove(rqdby, pkgname, _alpm_str_cmp, &data);
- FREE(data);
- deppkg->requiredby = rqdby;
- } else {
- if(!alpm_list_find_str(rqdby, pkgname)) {
- rqdby = alpm_list_add(rqdby, strdup(pkgname));
- deppkg->requiredby = rqdby;
- }
- }
-
- if(_alpm_db_write(localdb, deppkg, INFRQ_DEPENDS)) {
- _alpm_log(PM_LOG_ERROR, _("could not update 'requiredby' database entry %s-%s"),
- alpm_pkg_get_name(deppkg), alpm_pkg_get_version(deppkg));
}
- free(dep);
+ FREE(dep);
}
return(0);
}
@@ -566,7 +533,7 @@ static int grep(const char *fn, const char *needle)
int _alpm_runscriptlet(const char *root, const char *installfn,
const char *script, const char *ver,
- const char *oldver, pmtrans_t *trans)
+ const char *oldver)
{
char scriptfn[PATH_MAX];
char cmdline[PATH_MAX];
@@ -581,7 +548,7 @@ int _alpm_runscriptlet(const char *root, const char *installfn,
if(stat(installfn, &buf)) {
/* not found */
- _alpm_log(PM_LOG_DEBUG, "scriptlet '%s' not found", installfn);
+ _alpm_log(PM_LOG_DEBUG, "scriptlet '%s' not found\n", installfn);
return(0);
}
@@ -592,7 +559,7 @@ int _alpm_runscriptlet(const char *root, const char *installfn,
}
snprintf(tmpdir, PATH_MAX, "%stmp/alpm_XXXXXX", root);
if(mkdtemp(tmpdir) == NULL) {
- _alpm_log(PM_LOG_ERROR, _("could not create temp directory"));
+ _alpm_log(PM_LOG_ERROR, _("could not create temp directory\n"));
return(1);
}
_alpm_unpack(installfn, tmpdir, ".INSTALL");
@@ -612,18 +579,18 @@ int _alpm_runscriptlet(const char *root, const char *installfn,
/* save the cwd so we can restore it later */
if(getcwd(cwd, PATH_MAX) == NULL) {
- _alpm_log(PM_LOG_ERROR, _("could not get current working directory"));
+ _alpm_log(PM_LOG_ERROR, _("could not get current working directory\n"));
/* in case of error, cwd content is undefined: so we set it to something */
cwd[0] = 0;
}
/* just in case our cwd was removed in the upgrade operation */
if(chdir(root) != 0) {
- _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)"), root, strerror(errno));
+ _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)\n"), root, strerror(errno));
goto cleanup;
}
- _alpm_log(PM_LOG_DEBUG, _("executing %s script..."), script);
+ _alpm_log(PM_LOG_DEBUG, "executing %s script...\n", script);
if(oldver) {
snprintf(cmdline, PATH_MAX, "source %s %s %s %s",
@@ -632,32 +599,32 @@ int _alpm_runscriptlet(const char *root, const char *installfn,
snprintf(cmdline, PATH_MAX, "source %s %s %s",
scriptpath, script, ver);
}
- _alpm_log(PM_LOG_DEBUG, "%s", cmdline);
+ _alpm_log(PM_LOG_DEBUG, "%s\n", cmdline);
pid = fork();
if(pid == -1) {
- _alpm_log(PM_LOG_ERROR, _("could not fork a new process (%s)"), strerror(errno));
+ _alpm_log(PM_LOG_ERROR, _("could not fork a new process (%s)\n"), strerror(errno));
retval = 1;
goto cleanup;
}
if(pid == 0) {
- _alpm_log(PM_LOG_DEBUG, _("chrooting in %s"), root);
+ _alpm_log(PM_LOG_DEBUG, "chrooting in %s\n", root);
if(chroot(root) != 0) {
- _alpm_log(PM_LOG_ERROR, _("could not change the root directory (%s)"), strerror(errno));
- return(1);
+ _alpm_log(PM_LOG_ERROR, _("could not change the root directory (%s)\n"), strerror(errno));
+ exit(1);
}
if(chdir("/") != 0) {
- _alpm_log(PM_LOG_ERROR, _("could not change directory to / (%s)"), strerror(errno));
- return(1);
+ _alpm_log(PM_LOG_ERROR, _("could not change directory to / (%s)\n"), strerror(errno));
+ exit(1);
}
umask(0022);
- _alpm_log(PM_LOG_DEBUG, _("executing \"%s\""), cmdline);
+ _alpm_log(PM_LOG_DEBUG, "executing \"%s\"\n", cmdline);
execl("/bin/sh", "sh", "-c", cmdline, (char *)NULL);
exit(0);
} else {
if(waitpid(pid, 0, 0) == -1) {
- _alpm_log(PM_LOG_ERROR, _("call to waitpid failed (%s)"),
+ _alpm_log(PM_LOG_ERROR, _("call to waitpid failed (%s)\n"),
strerror(errno));
retval = 1;
goto cleanup;
@@ -666,7 +633,7 @@ int _alpm_runscriptlet(const char *root, const char *installfn,
cleanup:
if(strlen(tmpdir) && _alpm_rmrf(tmpdir)) {
- _alpm_log(PM_LOG_WARNING, _("could not remove tmpdir %s"), tmpdir);
+ _alpm_log(PM_LOG_WARNING, _("could not remove tmpdir %s\n"), tmpdir);
}
if(strlen(cwd)) {
chdir(cwd);