diff --git a/lib/libalpm/Makefile.am b/lib/libalpm/Makefile.am index f4c73337..076f7f67 100644 --- a/lib/libalpm/Makefile.am +++ b/lib/libalpm/Makefile.am @@ -22,6 +22,7 @@ TARGETS = md5driver.c \ remove.c \ sync.c \ handle.c \ + be_files.c \ alpm.c lib_LTLIBRARIES = libalpm.la diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index e3c5174c..2cd88bc6 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -25,9 +25,7 @@ #include #include #include -#ifdef CYGWIN -#include /* PATH_MAX */ -#endif +#include #include #include /* pacman */ @@ -314,10 +312,8 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db) oldpkg = _alpm_pkg_new(local->name, local->version); if(oldpkg) { if(!(local->infolevel & INFRQ_FILES)) { - char name[PKG_FULLNAME_LEN]; - snprintf(name, PKG_FULLNAME_LEN, "%s-%s", local->name, local->version); - _alpm_log(PM_LOG_DEBUG, "loading FILES info for %s", local->name); - _alpm_db_read(db, name, INFRQ_FILES, local); + _alpm_log(PM_LOG_DEBUG, "loading FILES info for '%s'", local->name); + _alpm_db_read(db, INFRQ_FILES, local); } oldpkg->backup = _alpm_list_strdup(local->backup); } diff --git a/lib/libalpm/alpm.c b/lib/libalpm/alpm.c index 8dacc61e..19e26363 100644 --- a/lib/libalpm/alpm.c +++ b/lib/libalpm/alpm.c @@ -102,12 +102,12 @@ int alpm_release() /* close local database */ if(handle->db_local) { - _alpm_db_close(handle->db_local); + alpm_db_unregister(handle->db_local); handle->db_local = NULL; } /* and also sync ones */ for(i = handle->dbs_sync; i; i = i->next) { - _alpm_db_close(i->data); + alpm_db_unregister(i->data); i->data = NULL; } @@ -161,7 +161,6 @@ int alpm_get_option(unsigned char parm, long *data) */ pmdb_t *alpm_db_register(char *treename) { - char path[PATH_MAX]; struct stat buf; pmdb_t *db; int found = 0; @@ -189,16 +188,23 @@ pmdb_t *alpm_db_register(char *treename) RET_ERR(PM_ERR_DB_NOT_NULL, NULL); } + _alpm_log(PM_LOG_FLOW1, "registering database '%s'", treename); + + db = _alpm_db_new(handle->root, handle->dbpath, treename); + if(db == NULL) { + return(NULL); + } + /* make sure the database directory exists */ - snprintf(path, PATH_MAX, "%s%s", handle->root, handle->dbpath); - if(stat(path, &buf) != 0 || !S_ISDIR(buf.st_mode)) { - if(_alpm_makepath(path) != 0) { + if(stat(db->path, &buf) != 0 || !S_ISDIR(buf.st_mode)) { + if(_alpm_makepath(db->path) != 0) { RET_ERR(PM_ERR_SYSTEM, NULL); } } - db = _alpm_db_open(path, treename, DB_O_CREATE); - if(db == NULL) { + _alpm_log(PM_LOG_DEBUG, "opening database '%s'", db->treename); + if(_alpm_db_open(db, DB_O_CREATE) == -1) { + _alpm_db_free(db); RET_ERR(PM_ERR_DB_OPEN, NULL); } @@ -238,14 +244,12 @@ int alpm_db_unregister(pmdb_t *db) ASSERT(handle->trans == NULL, RET_ERR(PM_ERR_TRANS_NOT_NULL, -1)); if(db == handle->db_local) { - _alpm_db_close(handle->db_local); handle->db_local = NULL; found = 1; } else { pmdb_t *data; handle->dbs_sync = _alpm_list_remove(handle->dbs_sync, db, db_cmp, (void **)&data); if(data) { - _alpm_db_close(data); found = 1; } } @@ -254,6 +258,16 @@ int alpm_db_unregister(pmdb_t *db) RET_ERR(PM_ERR_DB_NOT_FOUND, -1); } + _alpm_log(PM_LOG_FLOW1, "unregistering database '%s'", db->treename); + + /* Cleanup */ + _alpm_db_free_pkgcache(db); + + _alpm_log(PM_LOG_DEBUG, "closing database '%s'", db->treename); + _alpm_db_close(db); + + _alpm_db_free(db); + return(0); } @@ -419,9 +433,8 @@ void *alpm_pkg_getinfo(pmpkg_t *pkg, unsigned char parm) case PM_PKG_REASON: case PM_PKG_MD5SUM: if(!(pkg->infolevel & INFRQ_DESC)) { - char target[PKG_FULLNAME_LEN]; - snprintf(target, PKG_FULLNAME_LEN, "%s-%s", pkg->name, pkg->version); - _alpm_db_read(pkg->data, target, INFRQ_DESC, pkg); + _alpm_log(PM_LOG_DEBUG, "loading DESC info for '%s'", pkg->name); + _alpm_db_read(pkg->data, INFRQ_DESC, pkg); } break;*/ /* Depends entry */ @@ -432,26 +445,23 @@ void *alpm_pkg_getinfo(pmpkg_t *pkg, unsigned char parm) case PM_PKG_PROVIDES: case PM_PKG_REPLACES: if(!(pkg->infolevel & INFRQ_DEPENDS)) { - char target[PKG_FULLNAME_LEN]; - snprintf(target, PKG_FULLNAME_LEN, "%s-%s", pkg->name, pkg->version); - _alpm_db_read(pkg->data, target, INFRQ_DEPENDS, pkg); + _alpm_log(PM_LOG_DEBUG, "loading DEPENDS info for '%s'", pkg->name); + _alpm_db_read(pkg->data, INFRQ_DEPENDS, pkg); } break;*/ /* Files entry */ case PM_PKG_FILES: case PM_PKG_BACKUP: if(pkg->data == handle->db_local && !(pkg->infolevel & INFRQ_FILES)) { - char target[PKG_FULLNAME_LEN]; - snprintf(target, PKG_FULLNAME_LEN, "%s-%s", pkg->name, pkg->version); - _alpm_db_read(pkg->data, target, INFRQ_FILES, pkg); + _alpm_log(PM_LOG_DEBUG, "loading FILES info for '%s'", pkg->name); + _alpm_db_read(pkg->data, INFRQ_FILES, pkg); } break; /* Scriptlet */ case PM_PKG_SCRIPLET: if(pkg->data == handle->db_local && !(pkg->infolevel & INFRQ_SCRIPLET)) { - char target[PKG_FULLNAME_LEN]; - snprintf(target, PKG_FULLNAME_LEN, "%s-%s", pkg->name, pkg->version); - _alpm_db_read(pkg->data, target, INFRQ_SCRIPLET, pkg); + _alpm_log(PM_LOG_DEBUG, "loading SCRIPLET info for '%s'", pkg->name); + _alpm_db_read(pkg->data, INFRQ_SCRIPLET, pkg); } break; } @@ -535,6 +545,7 @@ int alpm_pkg_checkmd5sum(pmpkg_t *pkg) 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)); @@ -550,9 +561,8 @@ int alpm_pkg_checkmd5sum(pmpkg_t *pkg) retval = -1; } else { if(!(pkg->infolevel & INFRQ_DESC)) { - char target[PKG_FULLNAME_LEN]; - snprintf(target, PKG_FULLNAME_LEN, "%s-%s", pkg->name, pkg->version); - _alpm_db_read(pkg->data, target, INFRQ_DESC, pkg); + _alpm_log(PM_LOG_DEBUG, "loading DESC info for '%s'", pkg->name); + _alpm_db_read(pkg->data, INFRQ_DESC, pkg); } if(strcmp(md5sum, pkg->md5sum) == 0) { diff --git a/lib/libalpm/be_files.c b/lib/libalpm/be_files.c new file mode 100644 index 00000000..fd675c31 --- /dev/null +++ b/lib/libalpm/be_files.c @@ -0,0 +1,586 @@ +/* + * be_files.c + * + * Copyright (c) 2002-2006 by Judd Vinet + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#ifdef CYGWIN +#include /* PATH_MAX */ +#endif +/* pacman */ +#include "log.h" +#include "util.h" +#include "db.h" +#include "alpm.h" + +int _alpm_db_open(pmdb_t *db, int mode) +{ + char path[PATH_MAX]; + + if(db == NULL) { + return(-1); + } + + snprintf(path, PATH_MAX, "%s/%s", db->path, db->treename); + + db->handle = opendir(path); + if(db->handle == NULL) { + if(mode & DB_O_CREATE) { + _alpm_log(PM_LOG_WARNING, "could not open database '%s' -- try creating it", db->treename); + _alpm_log(PM_LOG_DEBUG, "creating database '%s'", db->treename); + if(mkdir(path, 0755) == 0) { + db->handle = opendir(path); + } + } + if(!(mode & DB_O_CREATE) || db->handle == NULL) { + return(-1); + } + } + + return(0); +} + +void _alpm_db_close(pmdb_t *db) +{ + if(db == NULL) { + return; + } + + if(db->handle) { + closedir(db->handle); + db->handle = NULL; + } +} + +void _alpm_db_rewind(pmdb_t *db) +{ + if(db == NULL || db->handle == NULL) { + return; + } + + rewinddir(db->handle); +} + +pmpkg_t *_alpm_db_scan(pmdb_t *db, char *target, unsigned int inforeq) +{ + struct dirent *ent = NULL; + struct stat sbuf; + char path[PATH_MAX]; + char name[PKG_FULLNAME_LEN]; + char *ptr = NULL; + int found = 0; + pmpkg_t *pkg; + + if(db == NULL) { + return(NULL); + } + + if(target != NULL) { + /* search for a specific package (by name only) */ + rewinddir(db->handle); + while(!found && (ent = readdir(db->handle)) != NULL) { + if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { + continue; + } + /* stat the entry, make sure it's a directory */ + snprintf(path, PATH_MAX, "%s/%s/%s", db->path, db->treename, ent->d_name); + if(stat(path, &sbuf) || !S_ISDIR(sbuf.st_mode)) { + continue; + } + STRNCPY(name, ent->d_name, PKG_FULLNAME_LEN); + /* truncate the string at the second-to-last hyphen, */ + /* which will give us the package name */ + if((ptr = rindex(name, '-'))) { + *ptr = '\0'; + } + if((ptr = rindex(name, '-'))) { + *ptr = '\0'; + } + if(!strcmp(name, target)) { + found = 1; + } + } + if(!found) { + return(NULL); + } + } else { + /* normal iteration */ + int isdir = 0; + while(!isdir) { + ent = readdir(db->handle); + if(ent == NULL) { + return(NULL); + } + if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { + isdir = 0; + continue; + } + /* stat the entry, make sure it's a directory */ + snprintf(path, PATH_MAX, "%s/%s/%s", db->path, db->treename, ent->d_name); + if(!stat(path, &sbuf) && S_ISDIR(sbuf.st_mode)) { + isdir = 1; + } + } + } + + pkg = _alpm_pkg_new(NULL, NULL); + if(pkg == NULL) { + return(NULL); + } + if(_alpm_pkg_splitname(ent->d_name, pkg->name, pkg->version) == -1) { + _alpm_log(PM_LOG_ERROR, "invalid name for dabatase entry '%s'", ent->d_name); + return(NULL); + } + if(_alpm_db_read(db, inforeq, pkg) == -1) { + FREEPKG(pkg); + } + + return(pkg); +} + +int _alpm_db_read(pmdb_t *db, unsigned int inforeq, pmpkg_t *info) +{ + FILE *fp = NULL; + struct stat buf; + char path[PATH_MAX]; + char line[512]; + + if(db == NULL || info == NULL || info->name[0] == 0 || info->version[0] == 0) { + return(-1); + } + + snprintf(path, PATH_MAX, "%s/%s/%s-%s", db->path, db->treename, info->name, info->version); + if(stat(path, &buf)) { + /* directory doesn't exist or can't be opened */ + return(-1); + } + + /* DESC */ + if(inforeq & INFRQ_DESC) { + snprintf(path, PATH_MAX, "%s/%s/%s-%s/desc", db->path, db->treename, info->name, info->version); + fp = fopen(path, "r"); + if(fp == NULL) { + _alpm_log(PM_LOG_ERROR, "%s (%s)", path, strerror(errno)); + goto error; + } + while(!feof(fp)) { + if(fgets(line, 256, fp) == NULL) { + break; + } + _alpm_strtrim(line); + if(!strcmp(line, "%DESC%")) { + if(fgets(info->desc, sizeof(info->desc), fp) == NULL) { + goto error; + } + _alpm_strtrim(info->desc); + } else if(!strcmp(line, "%GROUPS%")) { + while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + info->groups = _alpm_list_add(info->groups, strdup(line)); + } + } else if(!strcmp(line, "%URL%")) { + if(fgets(info->url, sizeof(info->url), fp) == NULL) { + goto error; + } + _alpm_strtrim(info->url); + } else if(!strcmp(line, "%LICENSE%")) { + while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + info->license = _alpm_list_add(info->license, strdup(line)); + } + } else if(!strcmp(line, "%ARCH%")) { + if(fgets(info->arch, sizeof(info->arch), fp) == NULL) { + goto error; + } + _alpm_strtrim(info->arch); + } else if(!strcmp(line, "%BUILDDATE%")) { + if(fgets(info->builddate, sizeof(info->builddate), fp) == NULL) { + goto error; + } + _alpm_strtrim(info->builddate); + } else if(!strcmp(line, "%INSTALLDATE%")) { + if(fgets(info->installdate, sizeof(info->installdate), fp) == NULL) { + goto error; + } + _alpm_strtrim(info->installdate); + } else if(!strcmp(line, "%PACKAGER%")) { + if(fgets(info->packager, sizeof(info->packager), fp) == NULL) { + goto error; + } + _alpm_strtrim(info->packager); + } else if(!strcmp(line, "%REASON%")) { + char tmp[32]; + if(fgets(tmp, sizeof(tmp), fp) == NULL) { + goto error; + } + _alpm_strtrim(tmp); + info->reason = atol(tmp); + } else if(!strcmp(line, "%SIZE%") || !strcmp(line, "%CSIZE%")) { + /* NOTE: the CSIZE and SIZE fields both share the "size" field + * in the pkginfo_t struct. This can be done b/c CSIZE + * is currently only used in sync databases, and SIZE is + * only used in local databases. + */ + char tmp[32]; + if(fgets(tmp, sizeof(tmp), fp) == NULL) { + goto error; + } + _alpm_strtrim(tmp); + info->size = atol(tmp); + } else if(!strcmp(line, "%MD5SUM%")) { + /* MD5SUM tag only appears in sync repositories, + * not the local one. */ + if(fgets(info->md5sum, sizeof(info->md5sum), fp) == NULL) { + goto error; + } + /* XXX: these are only here as backwards-compatibility for pacman 2.x + * sync repos.... in pacman3, they have been moved to DEPENDS. + * Remove this when we move to pacman3 repos. + */ + } else if(!strcmp(line, "%REPLACES%")) { + /* the REPLACES tag is special -- it only appears in sync repositories, + * not the local one. */ + while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + info->replaces = _alpm_list_add(info->replaces, strdup(line)); + } + } else if(!strcmp(line, "%FORCE%")) { + /* FORCE tag only appears in sync repositories, + * not the local one. */ + info->force = 1; + } + } + fclose(fp); + fp = NULL; + } + + /* FILES */ + if(inforeq & INFRQ_FILES) { + snprintf(path, PATH_MAX, "%s/%s/%s-%s/files", db->path, db->treename, info->name, info->version); + fp = fopen(path, "r"); + if(fp == NULL) { + _alpm_log(PM_LOG_ERROR, "%s (%s)", path, strerror(errno)); + goto error; + } + while(fgets(line, 256, fp)) { + _alpm_strtrim(line); + if(!strcmp(line, "%FILES%")) { + while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + info->files = _alpm_list_add(info->files, strdup(line)); + } + } else if(!strcmp(line, "%BACKUP%")) { + while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + info->backup = _alpm_list_add(info->backup, strdup(line)); + } + } + } + fclose(fp); + fp = NULL; + } + + /* DEPENDS */ + if(inforeq & INFRQ_DEPENDS) { + snprintf(path, PATH_MAX, "%s/%s/%s-%s/depends", db->path, db->treename, info->name, info->version); + fp = fopen(path, "r"); + if(fp == NULL) { + _alpm_log(PM_LOG_ERROR, "%s (%s)", path, strerror(errno)); + goto error; + } + while(!feof(fp)) { + fgets(line, 255, fp); + _alpm_strtrim(line); + if(!strcmp(line, "%DEPENDS%")) { + while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + info->depends = _alpm_list_add(info->depends, strdup(line)); + } + } else if(!strcmp(line, "%REQUIREDBY%")) { + while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + info->requiredby = _alpm_list_add(info->requiredby, strdup(line)); + } + } else if(!strcmp(line, "%CONFLICTS%")) { + while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + info->conflicts = _alpm_list_add(info->conflicts, strdup(line)); + } + } else if(!strcmp(line, "%PROVIDES%")) { + while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + info->provides = _alpm_list_add(info->provides, strdup(line)); + } + } else if(!strcmp(line, "%REPLACES%")) { + /* the REPLACES tag is special -- it only appears in sync repositories, + * not the local one. */ + while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { + info->replaces = _alpm_list_add(info->replaces, strdup(line)); + } + } else if(!strcmp(line, "%FORCE%")) { + /* FORCE tag only appears in sync repositories, + * not the local one. */ + info->force = 1; + } + } + fclose(fp); + fp = NULL; + } + + /* INSTALL */ + if(inforeq & INFRQ_SCRIPLET) { + snprintf(path, PATH_MAX, "%s/%s/%s-%s/install", db->path, db->treename, info->name, info->version); + if(!stat(path, &buf)) { + info->scriptlet = 1; + } + } + + /* internal */ + info->infolevel |= inforeq; + + return(0); + +error: + if(fp) { + fclose(fp); + } + return(-1); +} + +int _alpm_db_write(pmdb_t *db, pmpkg_t *info, unsigned int inforeq) +{ + FILE *fp = NULL; + char path[PATH_MAX]; + mode_t oldmask; + PMList *lp = NULL; + int retval = 0; + int local = 0; + + if(db == NULL || info == NULL) { + return(-1); + } + + snprintf(path, PATH_MAX, "%s/%s/%s-%s", db->path, db->treename, info->name, info->version); + oldmask = umask(0000); + mkdir(path, 0755); + /* make sure we have a sane umask */ + umask(0022); + + if(strcmp(db->treename, "local") == 0) { + local = 1; + } + + /* DESC */ + if(inforeq & INFRQ_DESC) { + snprintf(path, PATH_MAX, "%s/%s/%s-%s/desc", db->path, db->treename, info->name, info->version); + if((fp = fopen(path, "w")) == NULL) { + _alpm_log(PM_LOG_ERROR, "db_write: could not open file %s/desc", db->treename); + retval = 1; + goto cleanup; + } + fprintf(fp, "%%NAME%%\n%s\n\n" + "%%VERSION%%\n%s\n\n", info->name, info->version); + if(info->desc[0]) { + fprintf(fp, "%%DESC%%\n" + "%s\n\n", info->desc); + } + if(info->groups) { + fputs("%GROUPS%\n", fp); + for(lp = info->groups; lp; lp = lp->next) { + fprintf(fp, "%s\n", (char *)lp->data); + } + fprintf(fp, "\n"); + } + if(local) { + if(info->url[0]) { + fprintf(fp, "%%URL%%\n" + "%s\n\n", info->url); + } + if(info->license) { + fputs("%LICENSE%\n", fp); + for(lp = info->license; lp; lp = lp->next) { + fprintf(fp, "%s\n", (char *)lp->data); + } + fprintf(fp, "\n"); + } + if(info->arch[0]) { + fprintf(fp, "%%ARCH%%\n" + "%s\n\n", info->arch); + } + if(info->builddate[0]) { + fprintf(fp, "%%BUILDDATE%%\n" + "%s\n\n", info->builddate); + } + if(info->installdate[0]) { + fprintf(fp, "%%INSTALLDATE%%\n" + "%s\n\n", info->installdate); + } + if(info->packager[0]) { + fprintf(fp, "%%PACKAGER%%\n" + "%s\n\n", info->packager); + } + if(info->size) { + fprintf(fp, "%%SIZE%%\n" + "%ld\n\n", info->size); + } + if(info->reason) { + fprintf(fp, "%%REASON%%\n" + "%d\n\n", info->reason); + } + } else { + if(info->size) { + fprintf(fp, "%%CSIZE%%\n" + "%ld\n\n", info->size); + } + if(info->reason) { + fprintf(fp, "%%MD5SUM%%\n" + "%s\n\n", info->md5sum); + } + } + fclose(fp); + fp = NULL; + } + + /* FILES */ + if(local && (inforeq & INFRQ_FILES)) { + snprintf(path, PATH_MAX, "%s/%s/%s-%s/files", db->path, db->treename, info->name, info->version); + if((fp = fopen(path, "w")) == NULL) { + _alpm_log(PM_LOG_ERROR, "db_write: could not open file %s/files", db->treename); + retval = -1; + goto cleanup; + } + if(info->files) { + fprintf(fp, "%%FILES%%\n"); + for(lp = info->files; lp; lp = lp->next) { + fprintf(fp, "%s\n", (char *)lp->data); + } + fprintf(fp, "\n"); + } + if(info->backup) { + fprintf(fp, "%%BACKUP%%\n"); + for(lp = info->backup; lp; lp = lp->next) { + fprintf(fp, "%s\n", (char *)lp->data); + } + fprintf(fp, "\n"); + } + fclose(fp); + fp = NULL; + } + + /* DEPENDS */ + if(inforeq & INFRQ_DEPENDS) { + snprintf(path, PATH_MAX, "%s/%s/%s-%s/depends", db->path, db->treename, info->name, info->version); + if((fp = fopen(path, "w")) == NULL) { + _alpm_log(PM_LOG_ERROR, "db_write: could not open file %s/depends", db->treename); + retval = -1; + goto cleanup; + } + if(info->depends) { + fputs("%DEPENDS%\n", fp); + for(lp = info->depends; lp; lp = lp->next) { + fprintf(fp, "%s\n", (char *)lp->data); + } + fprintf(fp, "\n"); + } + if(local && info->requiredby) { + fputs("%REQUIREDBY%\n", fp); + for(lp = info->requiredby; lp; lp = lp->next) { + fprintf(fp, "%s\n", (char *)lp->data); + } + fprintf(fp, "\n"); + } + if(info->conflicts) { + fputs("%CONFLICTS%\n", fp); + for(lp = info->conflicts; lp; lp = lp->next) { + fprintf(fp, "%s\n", (char *)lp->data); + } + fprintf(fp, "\n"); + } + if(info->provides) { + fputs("%PROVIDES%\n", fp); + for(lp = info->provides; lp; lp = lp->next) { + fprintf(fp, "%s\n", (char *)lp->data); + } + fprintf(fp, "\n"); + } + if(!local) { + if(info->replaces) { + fputs("%REPLACES%\n", fp); + for(lp = info->replaces; lp; lp = lp->next) { + fprintf(fp, "%s\n", (char *)lp->data); + } + fprintf(fp, "\n"); + } + if(info->force) { + fprintf(fp, "%%FORCE%%\n" + "\n"); + } + } + fclose(fp); + fp = NULL; + } + + /* INSTALL */ + /* nothing needed here (script is automatically extracted) */ + +cleanup: + umask(oldmask); + + if(fp) { + fclose(fp); + } + + return(retval); +} + +int _alpm_db_remove(pmdb_t *db, pmpkg_t *info) +{ + char path[PATH_MAX]; + + if(db == NULL || info == NULL) { + return(-1); + } + + + /* DESC */ + snprintf(path, PATH_MAX, "%s/%s/%s-%s/desc", + db->path, db->treename, info->name, info->version); + unlink(path); + /* FILES */ + snprintf(path, PATH_MAX, "%s/%s/%s-%s/files", + db->path, db->treename, info->name, info->version); + unlink(path); + /* DEPENDS */ + snprintf(path, PATH_MAX, "%s/%s/%s-%s/depends", + db->path, db->treename, info->name, info->version); + unlink(path); + /* INSTALL */ + snprintf(path, PATH_MAX, "%s/%s/%s-%s/install", + db->path, db->treename, info->name, info->version); + unlink(path); + + /* Package directory */ + snprintf(path, PATH_MAX, "%s/%s/%s-%s", + db->path, db->treename, info->name, info->version); + if(rmdir(path) == -1) { + return(-1); + } + + return(0); +} + +/* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c index 437715e8..6b1ceffe 100644 --- a/lib/libalpm/db.c +++ b/lib/libalpm/db.c @@ -26,6 +26,7 @@ #include #include #include +#include #ifdef CYGWIN #include /* PATH_MAX */ #endif @@ -33,48 +34,28 @@ #include "log.h" #include "util.h" #include "error.h" -#include "group.h" -#include "cache.h" #include "db.h" #include "alpm.h" -/* Open a database and return a pmdb_t handle */ -pmdb_t *_alpm_db_open(char *dbpath, char *treename, int mode) +pmdb_t *_alpm_db_new(char *root, char* dbpath, char *treename) { pmdb_t *db; - if(dbpath == NULL || treename == NULL) { - return(NULL); - } - - _alpm_log(PM_LOG_DEBUG, "opening database '%s'", treename); - db = (pmdb_t *)malloc(sizeof(pmdb_t)); if(db == NULL) { + _alpm_log(PM_LOG_ERROR, "malloc failed: could not allocate %d bytes", + sizeof(pmdb_t)); RET_ERR(PM_ERR_MEMORY, NULL); } - db->path = (char *)malloc(strlen(dbpath)+strlen(treename)+2); + db->path = (char *)malloc(strlen(root)+strlen(dbpath)+1); if(db->path == NULL) { + _alpm_log(PM_LOG_ERROR, "malloc failed: could not allocate %d bytes", + strlen(root)+strlen(dbpath)+1); + FREE(db); RET_ERR(PM_ERR_MEMORY, NULL); } - sprintf(db->path, "%s/%s", dbpath, treename); - - db->dir = opendir(db->path); - if(db->dir == NULL) { - if(mode & DB_O_CREATE) { - _alpm_log(PM_LOG_WARNING, "could not open database '%s' -- try creating it", treename); - _alpm_log(PM_LOG_DEBUG, "creating database '%s'", treename); - if(mkdir(db->path, 0755) == 0) { - db->dir = opendir(db->path); - } - } - if(!(mode & DB_O_CREATE) || db->dir == NULL) { - FREE(db->path); - FREE(db); - return(NULL); - } - } + sprintf(db->path, "%s%s", root, dbpath); STRNCPY(db->treename, treename, DB_TREENAME_LEN); @@ -84,7 +65,7 @@ pmdb_t *_alpm_db_open(char *dbpath, char *treename, int mode) return(db); } -void _alpm_db_close(void *data) +void _alpm_db_free(void *data) { pmdb_t *db = data; @@ -92,527 +73,8 @@ void _alpm_db_close(void *data) return; } - _alpm_log(PM_LOG_DEBUG, "closing database '%s'", db->treename); - - if(db->dir) { - closedir(db->dir); - db->dir = NULL; - } - FREE(db->path); - - _alpm_db_free_pkgcache(db); - _alpm_db_free_grpcache(db); - + free(db->path); free(db); - - return; -} - -void _alpm_db_rewind(pmdb_t *db) -{ - if(db == NULL || db->dir == NULL) { - return; - } - - rewinddir(db->dir); -} - -pmpkg_t *_alpm_db_scan(pmdb_t *db, char *target, unsigned int inforeq) -{ - struct dirent *ent = NULL; - struct stat sbuf; - char path[PATH_MAX]; - char name[PKG_FULLNAME_LEN]; - char *ptr = NULL; - int found = 0; - pmpkg_t *pkg; - - if(db == NULL) { - return(NULL); - } - - if(target != NULL) { - /* search for a specific package (by name only) */ - _alpm_db_rewind(db); - while(!found && (ent = readdir(db->dir)) != NULL) { - if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { - continue; - } - STRNCPY(name, ent->d_name, PKG_FULLNAME_LEN); - /* stat the entry, make sure it's a directory */ - snprintf(path, PATH_MAX, "%s/%s", db->path, name); - if(stat(path, &sbuf) || !S_ISDIR(sbuf.st_mode)) { - continue; - } - /* truncate the string at the second-to-last hyphen, */ - /* which will give us the package name */ - if((ptr = rindex(name, '-'))) { - *ptr = '\0'; - } - if((ptr = rindex(name, '-'))) { - *ptr = '\0'; - } - if(!strcmp(name, target)) { - found = 1; - } - } - if(!found) { - return(NULL); - } - } else { - /* normal iteration */ - int isdir = 0; - while(!isdir) { - ent = readdir(db->dir); - if(ent == NULL) { - return(NULL); - } - /* stat the entry, make sure it's a directory */ - snprintf(path, PATH_MAX, "%s/%s", db->path, ent->d_name); - if(!stat(path, &sbuf) && S_ISDIR(sbuf.st_mode)) { - isdir = 1; - } - if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { - isdir = 0; - continue; - } - } - } - - pkg = _alpm_pkg_new(NULL, NULL); - if(pkg == NULL) { - return(NULL); - } - if(_alpm_db_read(db, ent->d_name, inforeq, pkg) == -1) { - FREEPKG(pkg); - } - - return(pkg); -} - -int _alpm_db_read(pmdb_t *db, char *name, unsigned int inforeq, pmpkg_t *info) -{ - FILE *fp = NULL; - struct stat buf; - char path[PATH_MAX]; - char line[512]; - - if(db == NULL || name == NULL || info == NULL) { - return(-1); - } - - snprintf(path, PATH_MAX, "%s/%s", db->path, name); - if(stat(path, &buf)) { - /* directory doesn't exist or can't be opened */ - return(-1); - } - - if(info->name[0] == 0) { - if(_alpm_pkg_splitname(name, info->name, info->version) == -1) { - return(-1); - } - } - - /* DESC */ - if(inforeq & INFRQ_DESC) { - snprintf(path, PATH_MAX, "%s/%s/desc", db->path, name); - fp = fopen(path, "r"); - if(fp == NULL) { - _alpm_log(PM_LOG_ERROR, "%s (%s)", path, strerror(errno)); - goto error; - } - while(!feof(fp)) { - if(fgets(line, 256, fp) == NULL) { - break; - } - _alpm_strtrim(line); - if(!strcmp(line, "%DESC%")) { - if(fgets(info->desc, sizeof(info->desc), fp) == NULL) { - goto error; - } - _alpm_strtrim(info->desc); - } else if(!strcmp(line, "%GROUPS%")) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { - info->groups = _alpm_list_add(info->groups, strdup(line)); - } - } else if(!strcmp(line, "%URL%")) { - if(fgets(info->url, sizeof(info->url), fp) == NULL) { - goto error; - } - _alpm_strtrim(info->url); - } else if(!strcmp(line, "%LICENSE%")) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { - info->license = _alpm_list_add(info->license, strdup(line)); - } - } else if(!strcmp(line, "%ARCH%")) { - if(fgets(info->arch, sizeof(info->arch), fp) == NULL) { - goto error; - } - _alpm_strtrim(info->arch); - } else if(!strcmp(line, "%BUILDDATE%")) { - if(fgets(info->builddate, sizeof(info->builddate), fp) == NULL) { - goto error; - } - _alpm_strtrim(info->builddate); - } else if(!strcmp(line, "%INSTALLDATE%")) { - if(fgets(info->installdate, sizeof(info->installdate), fp) == NULL) { - goto error; - } - _alpm_strtrim(info->installdate); - } else if(!strcmp(line, "%PACKAGER%")) { - if(fgets(info->packager, sizeof(info->packager), fp) == NULL) { - goto error; - } - _alpm_strtrim(info->packager); - } else if(!strcmp(line, "%REASON%")) { - char tmp[32]; - if(fgets(tmp, sizeof(tmp), fp) == NULL) { - goto error; - } - _alpm_strtrim(tmp); - info->reason = atol(tmp); - } else if(!strcmp(line, "%SIZE%") || !strcmp(line, "%CSIZE%")) { - /* NOTE: the CSIZE and SIZE fields both share the "size" field - * in the pkginfo_t struct. This can be done b/c CSIZE - * is currently only used in sync databases, and SIZE is - * only used in local databases. - */ - char tmp[32]; - if(fgets(tmp, sizeof(tmp), fp) == NULL) { - goto error; - } - _alpm_strtrim(tmp); - info->size = atol(tmp); - } else if(!strcmp(line, "%MD5SUM%")) { - /* MD5SUM tag only appears in sync repositories, - * not the local one. */ - if(fgets(info->md5sum, sizeof(info->md5sum), fp) == NULL) { - goto error; - } - /* XXX: these are only here as backwards-compatibility for pacman 2.x - * sync repos.... in pacman3, they have been moved to DEPENDS. - * Remove this when we move to pacman3 repos. - */ - } else if(!strcmp(line, "%REPLACES%")) { - /* the REPLACES tag is special -- it only appears in sync repositories, - * not the local one. */ - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { - info->replaces = _alpm_list_add(info->replaces, strdup(line)); - } - } else if(!strcmp(line, "%FORCE%")) { - /* FORCE tag only appears in sync repositories, - * not the local one. */ - info->force = 1; - } - } - fclose(fp); - fp = NULL; - } - - /* FILES */ - if(inforeq & INFRQ_FILES) { - snprintf(path, PATH_MAX, "%s/%s/files", db->path, name); - fp = fopen(path, "r"); - if(fp == NULL) { - _alpm_log(PM_LOG_ERROR, "%s (%s)", path, strerror(errno)); - goto error; - } - while(fgets(line, 256, fp)) { - _alpm_strtrim(line); - if(!strcmp(line, "%FILES%")) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { - info->files = _alpm_list_add(info->files, strdup(line)); - } - } else if(!strcmp(line, "%BACKUP%")) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { - info->backup = _alpm_list_add(info->backup, strdup(line)); - } - } - } - fclose(fp); - fp = NULL; - } - - /* DEPENDS */ - if(inforeq & INFRQ_DEPENDS) { - snprintf(path, PATH_MAX, "%s/%s/depends", db->path, name); - fp = fopen(path, "r"); - if(fp == NULL) { - _alpm_log(PM_LOG_ERROR, "%s (%s)", path, strerror(errno)); - goto error; - } - while(!feof(fp)) { - fgets(line, 255, fp); - _alpm_strtrim(line); - if(!strcmp(line, "%DEPENDS%")) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { - info->depends = _alpm_list_add(info->depends, strdup(line)); - } - } else if(!strcmp(line, "%REQUIREDBY%")) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { - info->requiredby = _alpm_list_add(info->requiredby, strdup(line)); - } - } else if(!strcmp(line, "%CONFLICTS%")) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { - info->conflicts = _alpm_list_add(info->conflicts, strdup(line)); - } - } else if(!strcmp(line, "%PROVIDES%")) { - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { - info->provides = _alpm_list_add(info->provides, strdup(line)); - } - } else if(!strcmp(line, "%REPLACES%")) { - /* the REPLACES tag is special -- it only appears in sync repositories, - * not the local one. */ - while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) { - info->replaces = _alpm_list_add(info->replaces, strdup(line)); - } - } else if(!strcmp(line, "%FORCE%")) { - /* FORCE tag only appears in sync repositories, - * not the local one. */ - info->force = 1; - } - } - fclose(fp); - fp = NULL; - } - - /* INSTALL */ - if(inforeq & INFRQ_SCRIPLET) { - snprintf(path, PATH_MAX, "%s/%s/install", db->path, name); - if(!stat(path, &buf)) { - info->scriptlet = 1; - } - } - - /* internal */ - info->infolevel |= inforeq; - - return(0); - -error: - if(fp) { - fclose(fp); - } - return(-1); -} - -int _alpm_db_write(pmdb_t *db, pmpkg_t *info, unsigned int inforeq) -{ - char topdir[PATH_MAX]; - FILE *fp = NULL; - char path[PATH_MAX]; - mode_t oldmask; - PMList *lp = NULL; - int retval = 0; - int local = 0; - - if(db == NULL || info == NULL) { - return(-1); - } - - snprintf(topdir, PATH_MAX, "%s/%s-%s", db->path, info->name, info->version); - oldmask = umask(0000); - mkdir(topdir, 0755); - /* make sure we have a sane umask */ - umask(0022); - - if(strcmp(db->treename, "local") == 0) { - local = 1; - } - - /* DESC */ - if(inforeq & INFRQ_DESC) { - snprintf(path, PATH_MAX, "%s/desc", topdir); - if((fp = fopen(path, "w")) == NULL) { - _alpm_log(PM_LOG_ERROR, "db_write: could not open file %s/desc", db->treename); - retval = 1; - goto cleanup; - } - fprintf(fp, "%%NAME%%\n%s\n\n" - "%%VERSION%%\n%s\n\n", info->name, info->version); - if(info->desc[0]) { - fprintf(fp, "%%DESC%%\n" - "%s\n\n", info->desc); - } - if(info->groups) { - fputs("%GROUPS%\n", fp); - for(lp = info->groups; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); - } - fprintf(fp, "\n"); - } - if(local) { - if(info->url[0]) { - fprintf(fp, "%%URL%%\n" - "%s\n\n", info->url); - } - if(info->license) { - fputs("%LICENSE%\n", fp); - for(lp = info->license; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); - } - fprintf(fp, "\n"); - } - if(info->arch[0]) { - fprintf(fp, "%%ARCH%%\n" - "%s\n\n", info->arch); - } - if(info->builddate[0]) { - fprintf(fp, "%%BUILDDATE%%\n" - "%s\n\n", info->builddate); - } - if(info->installdate[0]) { - fprintf(fp, "%%INSTALLDATE%%\n" - "%s\n\n", info->installdate); - } - if(info->packager[0]) { - fprintf(fp, "%%PACKAGER%%\n" - "%s\n\n", info->packager); - } - if(info->size) { - fprintf(fp, "%%SIZE%%\n" - "%ld\n\n", info->size); - } - if(info->reason) { - fprintf(fp, "%%REASON%%\n" - "%d\n\n", info->reason); - } - } else { - if(info->size) { - fprintf(fp, "%%CSIZE%%\n" - "%ld\n\n", info->size); - } - if(info->reason) { - fprintf(fp, "%%MD5SUM%%\n" - "%s\n\n", info->md5sum); - } - } - fclose(fp); - fp = NULL; - } - - /* FILES */ - if(local && (inforeq & INFRQ_FILES)) { - snprintf(path, PATH_MAX, "%s/files", topdir); - if((fp = fopen(path, "w")) == NULL) { - _alpm_log(PM_LOG_ERROR, "db_write: could not open file %s/files", db->treename); - retval = -1; - goto cleanup; - } - if(info->files) { - fprintf(fp, "%%FILES%%\n"); - for(lp = info->files; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); - } - fprintf(fp, "\n"); - } - if(info->backup) { - fprintf(fp, "%%BACKUP%%\n"); - for(lp = info->backup; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); - } - fprintf(fp, "\n"); - } - fclose(fp); - fp = NULL; - } - - /* DEPENDS */ - if(inforeq & INFRQ_DEPENDS) { - snprintf(path, PATH_MAX, "%s/depends", topdir); - if((fp = fopen(path, "w")) == NULL) { - _alpm_log(PM_LOG_ERROR, "db_write: could not open file %s/depends", db->treename); - retval = -1; - goto cleanup; - } - if(info->depends) { - fputs("%DEPENDS%\n", fp); - for(lp = info->depends; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); - } - fprintf(fp, "\n"); - } - if(local && info->requiredby) { - fputs("%REQUIREDBY%\n", fp); - for(lp = info->requiredby; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); - } - fprintf(fp, "\n"); - } - if(info->conflicts) { - fputs("%CONFLICTS%\n", fp); - for(lp = info->conflicts; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); - } - fprintf(fp, "\n"); - } - if(info->provides) { - fputs("%PROVIDES%\n", fp); - for(lp = info->provides; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); - } - fprintf(fp, "\n"); - } - if(!local) { - if(info->replaces) { - fputs("%REPLACES%\n", fp); - for(lp = info->replaces; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); - } - fprintf(fp, "\n"); - } - if(info->force) { - fprintf(fp, "%%FORCE%%\n" - "\n"); - } - } - fclose(fp); - fp = NULL; - } - - /* INSTALL */ - /* nothing needed here (script is automatically extracted) */ - -cleanup: - umask(oldmask); - - if(fp) { - fclose(fp); - } - - return(retval); -} - -int _alpm_db_remove(pmdb_t *db, pmpkg_t *info) -{ - char topdir[PATH_MAX]; - char file[PATH_MAX]; - - if(db == NULL || info == NULL) { - return(-1); - } - - snprintf(topdir, PATH_MAX, "%s/%s-%s", db->path, info->name, info->version); - - /* DESC */ - snprintf(file, PATH_MAX, "%s/desc", topdir); - unlink(file); - /* FILES */ - snprintf(file, PATH_MAX, "%s/files", topdir); - unlink(file); - /* DEPENDS */ - snprintf(file, PATH_MAX, "%s/depends", topdir); - unlink(file); - /* INSTALL */ - snprintf(file, PATH_MAX, "%s/install", topdir); - unlink(file); - - /* Package directory */ - if(rmdir(topdir) == -1) { - return(-1); - } - - return(0); } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h index dbade3b0..6d885efd 100644 --- a/lib/libalpm/db.h +++ b/lib/libalpm/db.h @@ -21,9 +21,6 @@ #ifndef _ALPM_DB_H #define _ALPM_DB_H -#include - -#include "list.h" #include "package.h" /* Database entries */ @@ -42,16 +39,20 @@ typedef struct __pmdb_t { char *path; char treename[DB_TREENAME_LEN]; - DIR *dir; + void *handle; PMList *pkgcache; PMList *grpcache; } pmdb_t; -pmdb_t *_alpm_db_open(char *path, char *treename, int mode); -void _alpm_db_close(void *data); + +pmdb_t *_alpm_db_new(char *root, char *dbpath, char *treename); +void _alpm_db_free(void *data); +/* Prototypes for backends functions */ +int _alpm_db_open(pmdb_t *db, int mode); +void _alpm_db_close(pmdb_t *db); void _alpm_db_rewind(pmdb_t *db); pmpkg_t *_alpm_db_scan(pmdb_t *db, char *target, unsigned int inforeq); -int _alpm_db_read(pmdb_t *db, char *name, unsigned int inforeq, pmpkg_t *info); +int _alpm_db_read(pmdb_t *db, unsigned int inforeq, pmpkg_t *info); int _alpm_db_write(pmdb_t *db, pmpkg_t *info, unsigned int inforeq); int _alpm_db_remove(pmdb_t *db, pmpkg_t *info); diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 08e15d38..1edb96e3 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -38,7 +38,7 @@ extern pmhandle_t *handle; pmdepmissing_t *_alpm_depmiss_new(const char *target, unsigned char type, unsigned char depmod, - const char *depname, const char *depversion) + const char *depname, const char *depversion) { pmdepmissing_t *miss; @@ -433,7 +433,7 @@ int _alpm_splitdep(char *depstr, pmdepend_t *depend) * I mean dependencies that are *only* required for packages in the target * list, so they can be safely removed. This function is recursive. */ -PMList* _alpm_removedeps(pmdb_t *db, PMList *targs) +PMList *_alpm_removedeps(pmdb_t *db, PMList *targs) { PMList *i, *j, *k; PMList *newtargs = targs; @@ -486,19 +486,17 @@ PMList* _alpm_removedeps(pmdb_t *db, PMList *targs) } } if(!needed) { - char *name; pmpkg_t *pkg = _alpm_pkg_new(dep->name, dep->version); if(pkg == NULL) { _alpm_log(PM_LOG_ERROR, "could not allocate memory for a package structure"); continue; } - asprintf(&name, "%s-%s", dep->name, dep->version); /* add it to the target list */ - _alpm_db_read(db, name, INFRQ_ALL, pkg); + _alpm_log(PM_LOG_DEBUG, "loading ALL info for '%s'", pkg->name); + _alpm_db_read(db, INFRQ_ALL, pkg); newtargs = _alpm_list_add(newtargs, pkg); - _alpm_log(PM_LOG_FLOW2, "adding %s to the targets", pkg->name); + _alpm_log(PM_LOG_FLOW2, "adding '%s' to the targets", pkg->name); newtargs = _alpm_removedeps(db, newtargs); - FREE(name); } } } @@ -512,7 +510,7 @@ PMList* _alpm_removedeps(pmdb_t *db, PMList *targs) * make sure *list and *trail are already initialized */ int _alpm_resolvedeps(pmdb_t *local, PMList *dbs_sync, pmpkg_t *syncpkg, PMList *list, - PMList *trail, pmtrans_t *trans, PMList **data) + PMList *trail, pmtrans_t *trans, PMList **data) { PMList *i, *j; PMList *targ;