From d37ad048732fbcef38aec001993553896dbe4198 Mon Sep 17 00:00:00 2001 From: Aaron Griffin Date: Sun, 15 Oct 2006 19:31:03 +0000 Subject: Merged frugalware changes (too many to list). Also added some config file handling changes (support [sections] to carry over to included files - this helps with backwards compatibility with existing pacman config files) --- lib/libalpm/alpm.c | 609 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 525 insertions(+), 84 deletions(-) (limited to 'lib/libalpm/alpm.c') diff --git a/lib/libalpm/alpm.c b/lib/libalpm/alpm.c index 96d8536e..cd6beea5 100644 --- a/lib/libalpm/alpm.c +++ b/lib/libalpm/alpm.c @@ -2,6 +2,9 @@ * alpm.c * * Copyright (c) 2002-2006 by Judd Vinet + * Copyright (c) 2005 by Aurelien Foret + * Copyright (c) 2005 by Christian Hamar + * Copyright (c) 2005, 2006 by Miklos Vajna * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,6 +40,7 @@ #include "error.h" #include "versioncmp.h" #include "md5.h" +#include "sha1.h" #include "list.h" #include "package.h" #include "group.h" @@ -50,8 +54,12 @@ #include "remove.h" #include "sync.h" #include "handle.h" +#include "provide.h" +#include "server.h" #include "alpm.h" +#define min(X, Y) ((X) < (Y) ? (X) : (Y)) + /* Globals */ pmhandle_t *handle = NULL; enum __pmerrno_t pm_errno; @@ -72,7 +80,7 @@ int alpm_initialize(char *root) ASSERT(handle == NULL, RET_ERR(PM_ERR_HANDLE_NOT_NULL, -1)); - handle = handle_new(); + handle = _alpm_handle_new(); if(handle == NULL) { RET_ERR(PM_ERR_MEMORY, -1); } @@ -133,7 +141,7 @@ int alpm_set_option(unsigned char parm, unsigned long data) /* Sanity checks */ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - return(handle_set_option(handle, parm, data)); + return(_alpm_handle_set_option(handle, parm, data)); } /** Get the value of a library option. @@ -147,7 +155,7 @@ int alpm_get_option(unsigned char parm, long *data) ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); ASSERT(data != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - return(handle_get_option(handle, parm, data)); + return(_alpm_handle_get_option(handle, parm, data)); } /** @} */ @@ -158,13 +166,13 @@ int alpm_get_option(unsigned char parm, long *data) /** Register a package database * @param treename the name of the repository + * @param callback a function to be called upon new database creation * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -pmdb_t *alpm_db_register(char *treename) +pmdb_t *alpm_db_register(char *treename, alpm_cb_db_register callback) { struct stat buf; pmdb_t *db; - int found = 0; char path[PATH_MAX]; /* Sanity checks */ @@ -175,21 +183,20 @@ pmdb_t *alpm_db_register(char *treename) if(strcmp(treename, "local") == 0) { if(handle->db_local != NULL) { - found = 1; + _alpm_log(PM_LOG_WARNING, _("attempt to re-register the 'local' DB\n")); + RET_ERR(PM_ERR_DB_NOT_NULL, NULL); } } else { PMList *i; - for(i = handle->dbs_sync; i && !found; i = i->next) { + for(i = handle->dbs_sync; i; i = i->next) { pmdb_t *sdb = i->data; if(strcmp(treename, sdb->treename) == 0) { - found = 1; + _alpm_log(PM_LOG_DEBUG, _("attempt to re-register the '%s' databse, using existing\n"), sdb->treename); + return sdb; } } } - if(found) { - RET_ERR(PM_ERR_DB_NOT_NULL, NULL); - } - + _alpm_log(PM_LOG_FLOW1, _("registering database '%s'"), treename); /* make sure the database directory exists */ @@ -203,15 +210,18 @@ pmdb_t *alpm_db_register(char *treename) db = _alpm_db_new(handle->root, handle->dbpath, treename); if(db == NULL) { - return(NULL); + RET_ERR(PM_ERR_DB_CREATE, NULL); } _alpm_log(PM_LOG_DEBUG, _("opening database '%s'"), db->treename); - if(_alpm_db_open(db, DB_O_CREATE) == -1) { + if(_alpm_db_open(db) == -1) { _alpm_db_free(db); RET_ERR(PM_ERR_DB_OPEN, NULL); } + /* Only call callback on NEW registration. */ + if(callback) callback(treename, db); + if(strcmp(treename, "local") == 0) { handle->db_local = db; } else { @@ -271,6 +281,8 @@ int alpm_db_unregister(pmdb_t *db) void *alpm_db_getinfo(PM_DB *db, unsigned char parm) { void *data = NULL; + char path[PATH_MAX]; + pmserver_t *server; /* Sanity checks */ ASSERT(handle != NULL, return(NULL)); @@ -278,6 +290,16 @@ void *alpm_db_getinfo(PM_DB *db, unsigned char parm) switch(parm) { case PM_DB_TREENAME: data = db->treename; break; + case PM_DB_FIRSTSERVER: + server = (pmserver_t*)db->servers->data; + if(!strcmp(server->protocol, "file")) { + snprintf(path, PATH_MAX, "%s://%s", server->protocol, server->path); + } else { + snprintf(path, PATH_MAX, "%s://%s%s", server->protocol, + server->server, server->path); + } + data = strdup(path); + break; default: data = NULL; } @@ -285,14 +307,66 @@ void *alpm_db_getinfo(PM_DB *db, unsigned char parm) return(data); } +/** Set the serverlist of a database. + * @param db database pointer + * @param url url of the server + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int alpm_db_setserver(pmdb_t *db, char *url) +{ + int found = 0; + + /* Sanity checks */ + ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); + + if(strcmp(db->treename, "local") == 0) { + if(handle->db_local != NULL) { + found = 1; + } + } else { + PMList *i; + for(i = handle->dbs_sync; i && !found; i = i->next) { + pmdb_t *sdb = i->data; + if(strcmp(db->treename, sdb->treename) == 0) { + found = 1; + } + } + } + if(!found) { + RET_ERR(PM_ERR_DB_NOT_FOUND, -1); + } + + if(url && strlen(url)) { + pmserver_t *server; + if((server = _alpm_server_new(url)) == NULL) { + /* pm_errno is set by _alpm_server_new */ + return(-1); + } + db->servers = _alpm_list_add(db->servers, server); + _alpm_log(PM_LOG_FLOW2, _("adding new server to database '%s': protocol '%s', server '%s', path '%s'"), + db->treename, server->protocol, server->server, server->path); + } else { + FREELIST(db->servers); + _alpm_log(PM_LOG_FLOW2, _("serverlist flushed for '%s'"), db->treename); + } + + return(0); +} + /** Update a package database + * @param level control for checking lastupdate time * @param db pointer to the package database to update - * @param archive path to the new package database tarball - * @return 0 on success, -1 on error (pm_errno is set accordingly) + * @return 0 on success, > 0 on error (pm_errno is set accordingly), < 0 if up + * to date */ -int alpm_db_update(PM_DB *db, char *archive) +int alpm_db_update(int level, PM_DB *db) { PMList *lp; + char path[PATH_MAX]; + PMList *files = NULL; + char newmtime[16] = ""; + char lastupdate[16] = ""; + int ret; /* Sanity checks */ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); @@ -304,28 +378,60 @@ int alpm_db_update(PM_DB *db, char *archive) RET_ERR(PM_ERR_DB_NOT_FOUND, -1); } - /* remove the old dir */ - _alpm_log(PM_LOG_FLOW2, _("flushing database %s/%s"), handle->dbpath, db->treename); - for(lp = _alpm_db_get_pkgcache(db); lp; lp = lp->next) { - if(_alpm_db_remove(db, lp->data) == -1) { - if(lp->data) { - _alpm_log(PM_LOG_ERROR, _("could not remove database entry %s/%s"), db->treename, - ((pmpkg_t *)lp->data)->name); - } - RET_ERR(PM_ERR_DB_REMOVE, -1); + if(level < 2) { + /* get the lastupdate time */ + _alpm_db_getlastupdate(db, lastupdate); + if(strlen(lastupdate) == 0) { + _alpm_log(PM_LOG_DEBUG, _("failed to get lastupdate time for %s (no big deal)\n"), db->treename); } } - /* Cache needs to be rebuild */ - _alpm_db_free_pkgcache(db); + /* build a one-element list */ + snprintf(path, PATH_MAX, "%s" PM_EXT_DB, db->treename); + files = _alpm_list_add(files, strdup(path)); - /* uncompress the sync database */ - /* ORE - we should not simply unpack the archive, but better parse it and - db_write each entry (see sync_load_dbarchive to get archive content) */ - _alpm_log(PM_LOG_FLOW2, _("unpacking %s"), archive); - if(_alpm_unpack(archive, db->path, NULL)) { - RET_ERR(PM_ERR_SYSTEM, -1); + snprintf(path, PATH_MAX, "%s%s", handle->root, handle->dbpath); + + ret = _alpm_downloadfiles_forreal(db->servers, path, files, lastupdate, newmtime); + FREELIST(files); + if(ret != 0) { + if(ret > 0) { + _alpm_log(PM_LOG_DEBUG, _("failed to sync db: %s [%d]\n"), alpm_strerror(ret), ret); + pm_errno = PM_ERR_DB_SYNC; + } + return(ret); + } else { + if(strlen(newmtime)) { + _alpm_log(PM_LOG_DEBUG, _("sync: new mtime for %s: %s\n"), db->treename, newmtime); + _alpm_db_setlastupdate(db, newmtime); + } + snprintf(path, PATH_MAX, "%s%s/%s" PM_EXT_DB, handle->root, handle->dbpath, db->treename); + + /* remove the old dir */ + _alpm_log(PM_LOG_FLOW2, _("flushing database %s/%s"), handle->dbpath, db->treename); + for(lp = _alpm_db_get_pkgcache(db); lp; lp = lp->next) { + if(_alpm_db_remove(db, lp->data) == -1) { + if(lp->data) { + _alpm_log(PM_LOG_ERROR, _("could not remove database entry %s/%s"), db->treename, + ((pmpkg_t *)lp->data)->name); + } + RET_ERR(PM_ERR_DB_REMOVE, 1); + } + } + + /* Cache needs to be rebuild */ + _alpm_db_free_pkgcache(db); + + /* uncompress the sync database */ + /* ORE + we should not simply unpack the archive, but better parse it and + db_write each entry (see sync_load_dbarchive to get archive content) */ + _alpm_log(PM_LOG_FLOW2, _("unpacking %s"), path); + if(_alpm_unpack(path, db->path, NULL)) { + RET_ERR(PM_ERR_SYSTEM, 1); + } + /* remove the .tar.gz */ + unlink(path); } return(0); @@ -359,6 +465,21 @@ PMList *alpm_db_getpkgcache(pmdb_t *db) return(_alpm_db_get_pkgcache(db)); } +/** Get the list of packages that a package provides + * @param db pointer to the package database to get the package from + * @param name name of the package + * @return the list of packages on success, NULL on error + */ +PMList *alpm_db_whatprovides(pmdb_t *db, char *name) +{ + /* Sanity checks */ + ASSERT(handle != NULL, return(NULL)); + ASSERT(db != NULL, return(NULL)); + ASSERT(name != NULL && strlen(name) != 0, return(NULL)); + + return(_alpm_db_whatprovides(db, name)); +} + /** Get a group entry from a package database * @param db pointer to the package database to get the group from * @param name of the group @@ -386,6 +507,7 @@ PMList *alpm_db_getgrpcache(pmdb_t *db) return(_alpm_db_get_grpcache(db)); } + /** @} */ /** @defgroup alpm_packages Package Functions @@ -396,7 +518,7 @@ PMList *alpm_db_getgrpcache(pmdb_t *db) /** Get informations about a package. * @param pkg package pointer * @param parm name of the info to get - * @return a void* on success (the value), NULL on error + * @return a char* on success (the value), NULL on error */ void *alpm_pkg_getinfo(pmpkg_t *pkg, unsigned char parm) { @@ -421,8 +543,10 @@ void *alpm_pkg_getinfo(pmpkg_t *pkg, unsigned char parm) case PM_PKG_INSTALLDATE: case PM_PKG_PACKAGER: case PM_PKG_SIZE: + case PM_PKG_USIZE: case PM_PKG_REASON: case PM_PKG_MD5SUM: + case PM_PKG_SHA1SUM: if(!(pkg->infolevel & INFRQ_DESC)) { _alpm_log(PM_LOG_DEBUG, _("loading DESC info for '%s'"), pkg->name); _alpm_db_read(pkg->data, INFRQ_DESC, pkg); @@ -466,20 +590,24 @@ void *alpm_pkg_getinfo(pmpkg_t *pkg, unsigned char parm) case PM_PKG_URL: data = pkg->url; break; case PM_PKG_ARCH: data = pkg->arch; break; case PM_PKG_BUILDDATE: data = pkg->builddate; break; + case PM_PKG_BUILDTYPE: data = pkg->buildtype; break; case PM_PKG_INSTALLDATE: data = pkg->installdate; break; case PM_PKG_PACKAGER: data = pkg->packager; break; - case PM_PKG_SIZE: data = (void *)pkg->size; break; - case PM_PKG_REASON: data = (void *)(int)pkg->reason; break; + case PM_PKG_SIZE: data = (void *)(long)pkg->size; break; + case PM_PKG_USIZE: data = (void *)(long)pkg->usize; break; + case PM_PKG_REASON: data = (void *)(long)pkg->reason; break; case PM_PKG_LICENSE: data = pkg->license; break; case PM_PKG_REPLACES: data = pkg->replaces; break; case PM_PKG_MD5SUM: data = pkg->md5sum; break; + case PM_PKG_SHA1SUM: data = pkg->sha1sum; break; case PM_PKG_DEPENDS: data = pkg->depends; break; + case PM_PKG_REMOVES: data = pkg->removes; break; case PM_PKG_REQUIREDBY: data = pkg->requiredby; break; case PM_PKG_PROVIDES: data = pkg->provides; break; case PM_PKG_CONFLICTS: data = pkg->conflicts; break; case PM_PKG_FILES: data = pkg->files; break; case PM_PKG_BACKUP: data = pkg->backup; break; - case PM_PKG_SCRIPLET: data = (void *)(int)pkg->scriptlet; break; + case PM_PKG_SCRIPLET: data = (void *)(long)pkg->scriptlet; break; case PM_PKG_DATA: data = pkg->data; break; default: data = NULL; @@ -525,13 +653,60 @@ int alpm_pkg_free(pmpkg_t *pkg) return(0); } -/** Check the integrity of a package from the sync cache. +/** Check the integrity (with sha1) of a package from the sync cache. + * @param pkg package pointer + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int alpm_pkg_checksha1sum(pmpkg_t *pkg) +{ + char path[PATH_MAX]; + char *sha1sum = NULL; + int retval = 0; + + ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); + /* We only inspect packages from sync repositories */ + ASSERT(pkg->origin == PKG_FROM_CACHE, RET_ERR(PM_ERR_PKG_INVALID, -1)); + ASSERT(pkg->data != handle->db_local, RET_ERR(PM_ERR_PKG_INVALID, -1)); + + snprintf(path, PATH_MAX, "%s%s/%s-%s" PM_EXT_PKG, + handle->root, handle->cachedir, + pkg->name, pkg->version); + + sha1sum = _alpm_SHAFile(path); + if(sha1sum == NULL) { + _alpm_log(PM_LOG_ERROR, _("could not get sha1 checksum for package %s-%s\n"), + pkg->name, pkg->version); + pm_errno = PM_ERR_NOT_A_FILE; + retval = -1; + } else { + if(!(pkg->infolevel & INFRQ_DESC)) { + _alpm_log(PM_LOG_DEBUG, _("loading DESC info for '%s'"), pkg->name); + _alpm_db_read(pkg->data, INFRQ_DESC, pkg); + } + + if(strcmp(sha1sum, pkg->sha1sum) == 0) { + _alpm_log(PM_LOG_FLOW1, _("checksums for package %s-%s are matching"), + pkg->name, pkg->version); + } else { + _alpm_log(PM_LOG_ERROR, _("sha1sums do not match for package %s-%s\n"), + pkg->name, pkg->version); + pm_errno = PM_ERR_PKG_INVALID; + retval = -1; + } + } + + FREE(sha1sum); + + return(retval); +} + +/** Check the integrity (with md5) of a package from the sync cache. * @param pkg package pointer * @return 0 on success, -1 on error (pm_errno is set accordingly) */ int alpm_pkg_checkmd5sum(pmpkg_t *pkg) { - char *path = NULL; + char path[PATH_MAX]; char *md5sum = NULL; int retval = 0; @@ -540,11 +715,11 @@ int alpm_pkg_checkmd5sum(pmpkg_t *pkg) ASSERT(pkg->origin == PKG_FROM_CACHE, RET_ERR(PM_ERR_PKG_INVALID, -1)); ASSERT(pkg->data != handle->db_local, RET_ERR(PM_ERR_PKG_INVALID, -1)); - asprintf(&path, "%s%s/%s-%s" PM_EXT_PKG, + snprintf(path, PATH_MAX, "%s%s/%s-%s" PM_EXT_PKG, handle->root, handle->cachedir, pkg->name, pkg->version); - md5sum = MDFile(path); + md5sum = _alpm_MDFile(path); if(md5sum == NULL) { _alpm_log(PM_LOG_ERROR, _("could not get md5 checksum for package %s-%s\n"), pkg->name, pkg->version); @@ -567,7 +742,6 @@ int alpm_pkg_checkmd5sum(pmpkg_t *pkg) } } - FREE(path); FREE(md5sum); return(retval); @@ -583,6 +757,7 @@ int alpm_pkg_vercmp(const char *ver1, const char *ver2) { return(_alpm_versioncmp(ver1, ver2)); } + /** @} */ /** @defgroup alpm_groups Group Functions @@ -593,7 +768,7 @@ int alpm_pkg_vercmp(const char *ver1, const char *ver2) /** Get informations about a group. * @param grp group pointer * @param parm name of the info to get - * @return a void* on success (the value), NULL on error + * @return a char* on success (the value), NULL on error */ void *alpm_grp_getinfo(pmgrp_t *grp, unsigned char parm) { @@ -620,9 +795,9 @@ void *alpm_grp_getinfo(pmgrp_t *grp, unsigned char parm) */ /** Get informations about a sync. - * @param sync package pointer + * @param sync pointer * @param parm name of the info to get - * @return a void* on success (the value), NULL on error + * @return a char* on success (the value), NULL on error */ void *alpm_sync_getinfo(pmsyncpkg_t *sync, unsigned char parm) { @@ -632,7 +807,7 @@ void *alpm_sync_getinfo(pmsyncpkg_t *sync, unsigned char parm) ASSERT(sync != NULL, return(NULL)); switch(parm) { - case PM_SYNC_TYPE: data = (void *)(int)sync->type; break; + case PM_SYNC_TYPE: data = (void *)(long)sync->type; break; case PM_SYNC_PKG: data = sync->pkg; break; case PM_SYNC_DATA: data = sync->data; break; default: @@ -642,6 +817,21 @@ void *alpm_sync_getinfo(pmsyncpkg_t *sync, unsigned char parm) return(data); } + +/** Searches a database + * @param db pointer to the package database to search in + * @return the list of packages on success, NULL on error + */ +PMList *alpm_db_search(pmdb_t *db) +{ + /* Sanity checks */ + ASSERT(handle != NULL, return(NULL)); + ASSERT(handle->needles != NULL, return(NULL)); + ASSERT(handle->needles->data != NULL, return(NULL)); + ASSERT(db != NULL, return(NULL)); + + return(_alpm_db_search(db, handle->needles)); +} /** @} */ /** @defgroup alpm_trans Transaction Functions @@ -651,7 +841,7 @@ void *alpm_sync_getinfo(pmsyncpkg_t *sync, unsigned char parm) /** Get informations about the transaction. * @param parm name of the info to get - * @return a void* on success (the value), NULL on error + * @return a char* on success (the value), NULL on error */ void *alpm_trans_getinfo(unsigned char parm) { @@ -665,8 +855,8 @@ void *alpm_trans_getinfo(unsigned char parm) trans = handle->trans; switch(parm) { - case PM_TRANS_TYPE: data = (void *)(int)trans->type; break; - case PM_TRANS_FLAGS: data = (void *)(int)trans->flags; break; + case PM_TRANS_TYPE: data = (void *)(long)trans->type; break; + case PM_TRANS_FLAGS: data = (void *)(long)trans->flags; break; case PM_TRANS_TARGETS: data = trans->targets; break; case PM_TRANS_PACKAGES: data = trans->packages; break; default: @@ -681,21 +871,22 @@ void *alpm_trans_getinfo(unsigned char parm) * @param type type of the transaction * @param flags flags of the transaction (like nodeps, etc) * @param event event callback function pointer - * @param conv conversation callback function pointer + * @param conv question callback function pointer + * @param progress progress callback function pointer * @return 0 on success, -1 on error (pm_errno is set accordingly) */ -int alpm_trans_init(unsigned char type, unsigned int flags, alpm_trans_cb_event event, alpm_trans_cb_conv conv) +int alpm_trans_init(unsigned char type, unsigned int flags, alpm_trans_cb_event event, alpm_trans_cb_conv conv, alpm_trans_cb_progress progress) { + char path[PATH_MAX]; + /* Sanity checks */ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - ASSERT(handle->trans == NULL, RET_ERR(PM_ERR_TRANS_NOT_NULL, -1)); - /* ORE - * perform sanity checks on type and flags: - * for instance, we can't set UPGRADE and FRESHEN at the same time */ + ASSERT(handle->trans == NULL, RET_ERR(PM_ERR_TRANS_NOT_NULL, -1)); /* lock db */ - handle->lckfd = _alpm_lckmk(PM_LOCK); + snprintf(path, PATH_MAX, "%s/%s", handle->root, PM_LOCK); + handle->lckfd = _alpm_lckmk(path); if(handle->lckfd == -1) { RET_ERR(PM_ERR_HANDLE_LOCK, -1); } @@ -705,7 +896,7 @@ int alpm_trans_init(unsigned char type, unsigned int flags, alpm_trans_cb_event RET_ERR(PM_ERR_MEMORY, -1); } - return(_alpm_trans_init(handle->trans, type, flags, event, conv)); + return(_alpm_trans_init(handle->trans, type, flags, event, conv, progress)); } /** Search for packages to upgrade and add them to the transaction. @@ -751,14 +942,12 @@ int alpm_trans_addtarget(char *target) */ int alpm_trans_prepare(PMList **data) { - pmtrans_t *trans; - /* Sanity checks */ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); + ASSERT(data != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - trans = handle->trans; - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); + ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); + ASSERT(handle->trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1)); return(_alpm_trans_prepare(handle->trans, data)); } @@ -770,14 +959,11 @@ int alpm_trans_prepare(PMList **data) */ int alpm_trans_commit(PMList **data) { - pmtrans_t *trans; - /* 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_PREPARED, RET_ERR(PM_ERR_TRANS_NOT_PREPARED, -1)); + 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 */ ASSERT(handle->access == PM_ACCESS_RW, RET_ERR(PM_ERR_BADPERMS, -1)); @@ -791,6 +977,7 @@ int alpm_trans_commit(PMList **data) int alpm_trans_release() { pmtrans_t *trans; + char path[PATH_MAX]; /* Sanity checks */ ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); @@ -799,11 +986,12 @@ int 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_COMMITTING || trans->state == STATE_INTERRUPTED) { - if(trans->state == STATE_COMMITTING) { + /* during a commit do not interrupt inmediatelly, 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); } @@ -814,9 +1002,10 @@ int alpm_trans_release() close(handle->lckfd); handle->lckfd = -1; } - if(_alpm_lckrm(PM_LOCK) == -1) { - _alpm_log(PM_LOG_WARNING, _("could not remove lock file %s"), PM_LOCK); - alpm_logaction(_("warning: could not remove lock file %s"), PM_LOCK); + snprintf(path, PATH_MAX, "%s/%s", handle->root, PM_LOCK); + if(_alpm_lckrm(path)) { + _alpm_log(PM_LOG_WARNING, _("could not remove lock file %s"), path); + alpm_logaction(_("warning: could not remove lock file %s"), path); } return(0); @@ -829,9 +1018,9 @@ int alpm_trans_release() */ /** Get informations about a dependency. - * @param db dependency pointer + * @param miss dependency pointer * @param parm name of the info to get - * @return a void* on success (the value), NULL on error + * @return a char* on success (the value), NULL on error */ void *alpm_dep_getinfo(pmdepmissing_t *miss, unsigned char parm) { @@ -841,9 +1030,9 @@ void *alpm_dep_getinfo(pmdepmissing_t *miss, unsigned char parm) ASSERT(miss != NULL, return(NULL)); switch(parm) { - case PM_DEP_TARGET: data = (void *)(int)miss->target; break; - case PM_DEP_TYPE: data = (void *)(int)miss->type; break; - case PM_DEP_MOD: data = (void *)(int)miss->depend.mod; break; + case PM_DEP_TARGET: data = (void *)(long)miss->target; break; + case PM_DEP_TYPE: data = (void *)(long)miss->type; break; + case PM_DEP_MOD: data = (void *)(long)miss->depend.mod; break; case PM_DEP_NAME: data = miss->depend.name; break; case PM_DEP_VERSION: data = miss->depend.version; break; default: @@ -861,9 +1050,9 @@ void *alpm_dep_getinfo(pmdepmissing_t *miss, unsigned char parm) */ /** Get informations about a file conflict. - * @param db conflict pointer + * @param conflict database conflict structure * @param parm name of the info to get - * @return a void* on success (the value), NULL on error + * @return a char* on success (the value), NULL on error */ void *alpm_conflict_getinfo(pmconflict_t *conflict, unsigned char parm) { @@ -874,7 +1063,7 @@ void *alpm_conflict_getinfo(pmconflict_t *conflict, unsigned char parm) switch(parm) { case PM_CONFLICT_TARGET: data = conflict->target; break; - case PM_CONFLICT_TYPE: data = (void *)(int)conflict->type; break; + case PM_CONFLICT_TYPE: data = (void *)(long)conflict->type; break; case PM_CONFLICT_FILE: data = conflict->file; break; case PM_CONFLICT_CTARGET: data = conflict->ctarget; break; default: @@ -979,6 +1168,8 @@ int alpm_list_free(PMList *entry) */ int alpm_list_count(PMList *list) { + ASSERT(list != NULL, return(-1)); + return(_alpm_list_count(list)); } /** @} */ @@ -996,8 +1187,258 @@ char *alpm_get_md5sum(char *name) { ASSERT(name != NULL, return(NULL)); - return(MDFile(name)); + return(_alpm_MDFile(name)); +} + +/** Get the sha1 sum of file. + * @param name name of the file + * @return the checksum on success, NULL on error + */ +char *alpm_get_sha1sum(char *name) +{ + ASSERT(name != NULL, return(NULL)); + + return(_alpm_SHAFile(name)); +} + +/** Fetch a remote pkg. + * @param url + * @return the downloaded filename on success, NULL on error + */ +char *alpm_fetch_pkgurl(char *url) +{ + ASSERT(strstr(url, "://"), return(NULL)); + + return(_alpm_fetch_pkgurl(url)); +} + +/** Parses a configuration file. + * @param file path to the config file. + * @param callback a function to be called upon new database creation + * @param this_section the config current section being parsed + * @return 0 on success, -1 on error (pm_errno is set accordingly) + */ +int alpm_parse_config(char *file, alpm_cb_db_register callback, const char *this_section) +{ + FILE *fp = NULL; + char line[PATH_MAX+1]; + char *ptr = NULL; + char *key = NULL; + int linenum = 0; + char section[256] = ""; + PM_DB *db = NULL; + + fp = fopen(file, "r"); + if(fp == NULL) { + return(0); + } + + if(this_section != NULL && strlen(this_section) > 0) { + strncpy(section, this_section, min(255, strlen(this_section))); + db = alpm_db_register(section, callback); + } + + while(fgets(line, PATH_MAX, fp)) { + linenum++; + _alpm_strtrim(line); + if(strlen(line) == 0 || line[0] == '#') { + continue; + } + if(line[0] == '[' && line[strlen(line)-1] == ']') { + /* new config section */ + ptr = line; + ptr++; + strncpy(section, ptr, min(255, strlen(ptr)-1)); + section[min(255, strlen(ptr)-1)] = '\0'; + _alpm_log(PM_LOG_DEBUG, _("config: new section '%s'\n"), section); + if(!strlen(section)) { + RET_ERR(PM_ERR_CONF_BAD_SECTION, -1); + } + if(!strcmp(section, "local")) { + RET_ERR(PM_ERR_CONF_LOCAL, -1); + } + if(strcmp(section, "options")) { + db = alpm_db_register(section, callback); + if(db == NULL) { + /* pm_errno is set by alpm_db_register */ + return(-1); + } + } + } else { + /* directive */ + ptr = line; + key = strsep(&ptr, "="); + if(key == NULL) { + RET_ERR(PM_ERR_CONF_BAD_SYNTAX, -1); + } + _alpm_strtrim(key); + key = _alpm_strtoupper(key); + if(!strlen(section) && strcmp(key, "INCLUDE")) { + RET_ERR(PM_ERR_CONF_DIRECTIVE_OUTSIDE_SECTION, -1); + } + if(ptr == NULL) { + if(!strcmp(key, "NOPASSIVEFTP")) { + alpm_set_option(PM_OPT_NOPASSIVEFTP, (long)1); + } else if(!strcmp(key, "USESYSLOG")) { + alpm_set_option(PM_OPT_USESYSLOG, (long)1); + _alpm_log(PM_LOG_DEBUG, _("config: usesyslog\n")); + } else if(!strcmp(key, "ILOVECANDY")) { + alpm_set_option(PM_OPT_CHOMP, (long)1); + } else { + RET_ERR(PM_ERR_CONF_BAD_SYNTAX, -1); + } + } else { + _alpm_strtrim(ptr); + if(!strcmp(key, "INCLUDE")) { + char conf[PATH_MAX]; + strncpy(conf, ptr, PATH_MAX); + _alpm_log(PM_LOG_DEBUG, _("config: including %s\n"), conf); + alpm_parse_config(conf, callback, section); + } else if(!strcmp(section, "options")) { + if(!strcmp(key, "NOUPGRADE")) { + char *p = ptr; + char *q; + while((q = strchr(p, ' '))) { + *q = '\0'; + if(alpm_set_option(PM_OPT_NOUPGRADE, (long)p) == -1) { + /* pm_errno is set by alpm_set_option */ + return(-1); + } + _alpm_log(PM_LOG_DEBUG, _("config: noupgrade: %s\n"), p); + p = q; + p++; + } + if(alpm_set_option(PM_OPT_NOUPGRADE, (long)p) == -1) { + /* pm_errno is set by alpm_set_option */ + return(-1); + } + _alpm_log(PM_LOG_DEBUG, _("config: noupgrade: %s\n"), p); + } else if(!strcmp(key, "NOEXTRACT")) { + char *p = ptr; + char *q; + while((q = strchr(p, ' '))) { + *q = '\0'; + if(alpm_set_option(PM_OPT_NOEXTRACT, (long)p) == -1) { + /* pm_errno is set by alpm_set_option */ + return(-1); + } + _alpm_log(PM_LOG_DEBUG, _("config: noextract: %s\n"), p); + p = q; + p++; + } + if(alpm_set_option(PM_OPT_NOEXTRACT, (long)p) == -1) { + /* pm_errno is set by alpm_set_option */ + return(-1); + } + _alpm_log(PM_LOG_DEBUG, _("config: noextract: %s\n"), p); + } else if(!strcmp(key, "IGNOREPKG")) { + char *p = ptr; + char *q; + while((q = strchr(p, ' '))) { + *q = '\0'; + if(alpm_set_option(PM_OPT_IGNOREPKG, (long)p) == -1) { + /* pm_errno is set by alpm_set_option */ + return(-1); + } + _alpm_log(PM_LOG_DEBUG, _("config: ignorepkg: %s\n"), p); + p = q; + p++; + } + if(alpm_set_option(PM_OPT_IGNOREPKG, (long)p) == -1) { + /* pm_errno is set by alpm_set_option */ + return(-1); + } + _alpm_log(PM_LOG_DEBUG, _("config: ignorepkg: %s\n"), p); + } else if(!strcmp(key, "HOLDPKG")) { + char *p = ptr; + char *q; + while((q = strchr(p, ' '))) { + *q = '\0'; + if(alpm_set_option(PM_OPT_HOLDPKG, (long)p) == -1) { + /* pm_errno is set by alpm_set_option */ + return(-1); + } + _alpm_log(PM_LOG_DEBUG, _("config: holdpkg: %s\n"), p); + p = q; + p++; + } + if(alpm_set_option(PM_OPT_HOLDPKG, (long)p) == -1) { + /* pm_errno is set by alpm_set_option */ + return(-1); + } + _alpm_log(PM_LOG_DEBUG, _("config: holdpkg: %s\n"), p); + } else if(!strcmp(key, "DBPATH")) { + /* shave off the leading slash, if there is one */ + if(*ptr == '/') { + ptr++; + } + if(alpm_set_option(PM_OPT_DBPATH, (long)ptr) == -1) { + /* pm_errno is set by alpm_set_option */ + return(-1); + } + _alpm_log(PM_LOG_DEBUG, _("config: dbpath: %s\n"), ptr); + } else if(!strcmp(key, "CACHEDIR")) { + /* shave off the leading slash, if there is one */ + if(*ptr == '/') { + ptr++; + } + if(alpm_set_option(PM_OPT_CACHEDIR, (long)ptr) == -1) { + /* pm_errno is set by alpm_set_option */ + return(-1); + } + _alpm_log(PM_LOG_DEBUG, _("config: cachedir: %s\n"), ptr); + } else if (!strcmp(key, "LOGFILE")) { + if(alpm_set_option(PM_OPT_LOGFILE, (long)ptr) == -1) { + /* pm_errno is set by alpm_set_option */ + return(-1); + } + _alpm_log(PM_LOG_DEBUG, _("config: log file: %s\n"), ptr); + } else if (!strcmp(key, "XFERCOMMAND")) { + if(alpm_set_option(PM_OPT_XFERCOMMAND, (long)ptr) == -1) { + /* pm_errno is set by alpm_set_option */ + return(-1); + } + } else if (!strcmp(key, "UPGRADEDELAY")) { + /* The config value is in days, we use seconds */ + _alpm_log(PM_LOG_DEBUG, _("config: UpgradeDelay: %i\n"), (60*60*24) * atol(ptr)); + if(alpm_set_option(PM_OPT_UPGRADEDELAY, (60*60*24) * atol(ptr)) == -1) { + /* pm_errno is set by alpm_set_option */ + return(-1); + } + } else if (!strcmp(key, "PROXYSERVER")) { + if(alpm_set_option(PM_OPT_PROXYHOST, (long)ptr) == -1) { + /* pm_errno is set by alpm_set_option */ + return(-1); + } + } else if (!strcmp(key, "PROXYPORT")) { + if(alpm_set_option(PM_OPT_PROXYPORT, (long)atoi(ptr)) == -1) { + /* pm_errno is set by alpm_set_option */ + return(-1); + } + } else { + RET_ERR(PM_ERR_CONF_BAD_SYNTAX, -1); + } + } else { + if(!strcmp(key, "SERVER")) { + /* add to the list */ + _alpm_log(PM_LOG_DEBUG, _("config: %s: server: %s\n"), section, ptr); + if(alpm_db_setserver(db, strdup(ptr)) != 0) { + /* pm_errno is set by alpm_set_option */ + return(-1); + } + } else { + RET_ERR(PM_ERR_CONF_BAD_SYNTAX, -1); + } + } + line[0] = '\0'; + } + } + } + fclose(fp); + + return(0); } + /* @} */ /* vim: set ts=2 sw=2 noet: */ -- cgit v1.2.3-24-g4f1b