From 5ef51b3e266cf43411947248886372001fdb207a Mon Sep 17 00:00:00 2001 From: Judd Vinet Date: Fri, 7 Oct 2005 23:29:49 +0000 Subject: Merging in recent fixes/additions from 2.9.7 --- lib/libalpm/add.c | 30 +++++++++-- lib/libalpm/alpm.h | 1 + lib/libalpm/conflict.c | 138 +++++++++++++++++++++++++------------------------ lib/libalpm/conflict.h | 2 +- lib/libalpm/handle.c | 10 ++++ lib/libalpm/handle.h | 1 + lib/libalpm/list.c | 18 +++++++ lib/libalpm/list.h | 1 + lib/libalpm/md5.h | 2 +- lib/libalpm/remove.c | 52 ++++++++++++------- lib/libalpm/trans.c | 2 + lib/libalpm/trans.h | 1 + lib/libalpm/util.c | 19 +++++++ lib/libftp/Makefile | 16 ++---- src/pacman/Makefile | 2 +- src/pacman/conf.c | 18 +++++++ src/pacman/db.c | 103 ++++++++++++++++++++++-------------- src/pacman/db.h | 2 +- src/pacman/pacman.c | 23 +++++++++ src/pacman/query.c | 4 +- src/pacman/sync.c | 6 +-- src/pacman/util.c | 16 ++++++ src/pacman/util.h | 1 + 23 files changed, 316 insertions(+), 152 deletions(-) diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index af7d6b0b..327b5407 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -191,6 +191,7 @@ error: int add_prepare(pmtrans_t *trans, pmdb_t *db, PMList **data) { PMList *lp; + PMList *skiplist; ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); @@ -269,12 +270,17 @@ int add_prepare(pmtrans_t *trans, pmdb_t *db, PMList **data) EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL); _alpm_log(PM_LOG_FLOW1, "looking for file conflicts"); - lp = db_find_conflicts(db, trans->packages, handle->root); + lp = db_find_conflicts(db, trans->packages, handle->root, &skiplist); if(lp != NULL) { *data = lp; RET_ERR(PM_ERR_FILE_CONFLICTS, -1); } + /* copy the file skiplist into the transaction */ + for(lp = skiplist; lp; lp = lp->next) { + trans->skiplist = pm_list_add(trans->skiplist, lp->data); + } + EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_DONE, NULL, NULL); } @@ -354,6 +360,10 @@ int add_commit(pmtrans_t *trans, pmdb_t *db) FREETRANS(tr); RET_ERR(PM_ERR_TRANS_ABORT, -1); } + /* copy the skiplist over */ + for(lp = trans->skiplist; lp; lp = lp->next) { + pm_list_add(tr->skiplist, lp->data); + } if(remove_commit(tr, db) == -1) { FREETRANS(tr); RET_ERR(PM_ERR_TRANS_ABORT, -1); @@ -361,9 +371,8 @@ int add_commit(pmtrans_t *trans, pmdb_t *db) FREETRANS(tr); } } else { - /* no previous package version is installed, so this is actually just an - * install - */ + /* no previous package version is installed, so this is actually + * just an install. */ pmo_upgrade = 0; } } @@ -409,6 +418,17 @@ int add_commit(pmtrans_t *trans, pmdb_t *db) snprintf(expath, PATH_MAX, "%s%s", handle->root, pathname); } + /* if a file is in NoExtract then we never extract it. + * + * eg, /home/httpd/html/index.html may be removed so index.php + * could be used. + */ + if(pm_list_is_strin(pathname, handle->noextract)) { + alpm_logaction("notice: %s is in NoExtract -- skipping extraction", pathname); + tar_skip_regfile(tar); + continue; + } + if(!stat(expath, &buf) && !S_ISDIR(buf.st_mode)) { /* file already exists */ if(pm_list_is_strin(pathname, handle->noupgrade)) { @@ -589,7 +609,7 @@ int add_commit(pmtrans_t *trans, pmdb_t *db) /* Add the package to the database */ t = time(NULL); - /* Update the requiredby field by scaning the whole database + /* Update the requiredby field by scanning the whole database * looking for packages depending on the package to add */ for(lp = db_get_pkgcache(db); lp; lp = lp->next) { pmpkg_t *tmpp = lp->data; diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 989bca25..75493365 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -84,6 +84,7 @@ enum { PM_OPT_LOCALDB, PM_OPT_SYNCDB, PM_OPT_NOUPGRADE, + PM_OPT_NOEXTRACT, PM_OPT_IGNOREPKG, PM_OPT_HOLDPKG }; diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index 3408c676..1c9cd309 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -31,7 +31,7 @@ #include "util.h" #include "conflict.h" -PMList *db_find_conflicts(pmdb_t *db, PMList *targets, char *root) +PMList *db_find_conflicts(pmdb_t *db, PMList *targets, char *root, PMList **skip_list) { PMList *i, *j, *k; char *filestr = NULL; @@ -44,41 +44,7 @@ PMList *db_find_conflicts(pmdb_t *db, PMList *targets, char *root) return(NULL); } - /* CHECK 1: check every db package against every target package */ - /* XXX: I've disabled the database-against-targets check for now, as the - * many many strcmp() calls slow it down heavily and most of the - * checking is redundant to the targets-against-filesystem check. - * This will be re-enabled if I can improve performance significantly. - * - pmpkg_t *info = NULL; - char *dbstr = NULL; - db_rewind(db); - while((info = db_scan(db, NULL, INFRQ_DESC | INFRQ_FILES)) != NULL) { - for(i = info->files; i; i = i->next) { - if(i->data == NULL) continue; - dbstr = (char*)i->data; - for(j = targets; j; j = j->next) { - pmpkg_t *targ = (pmpkg_t*)j->data; - if(strcmp(info->name, targ->name)) { - for(k = targ->files; k; k = k->next) { - filestr = (char*)k->data; - if(!strcmp(dbstr, filestr)) { - if(rindex(k->data, '/') == filestr+strlen(filestr)-1) { - continue; - } - MALLOC(str, 512); - snprintf(str, 512, "%s: exists in \"%s\" (target) and \"%s\" (installed)", dbstr, - targ->name, info->name); - conflicts = pm_list_add(conflicts, str); - } - } - } - } - } - FREEPKG(info); - }*/ - - /* CHECK 2: check every target against every target */ + /* CHECK 1: check every target against every target */ for(i = targets; i; i = i->next) { pmpkg_t *p1 = (pmpkg_t*)i->data; for(j = i; j; j = j->next) { @@ -104,52 +70,90 @@ PMList *db_find_conflicts(pmdb_t *db, PMList *targets, char *root) } } - /* CHECK 3: check every target against the filesystem */ + /* CHECK 2: check every target against the filesystem */ for(i = targets; i; i = i->next) { pmpkg_t *p = (pmpkg_t*)i->data; pmpkg_t *dbpkg = NULL; for(j = p->files; j; j = j->next) { + int isdir = 0; filestr = (char*)j->data; snprintf(path, PATH_MAX, "%s%s", root, filestr); - if(!stat(path, &buf) && !S_ISDIR(buf.st_mode)) { + /* is this target a file or directory? */ + if(path[strlen(path)-1] == '/') { + isdir = 1; + path[strlen(path)-1] = '\0'; + } + if(!lstat(path, &buf)) { int ok = 0; - if(dbpkg == NULL) { - dbpkg = db_scan(db, p->name, INFRQ_DESC | INFRQ_FILES); + if(!S_ISLNK(buf.st_mode) && ((isdir && !S_ISDIR(buf.st_mode)) || (!isdir && S_ISDIR(buf.st_mode)))) { + /* if the package target is a directory, and the filesystem target + * is not (or vice versa) then it's a conflict + */ + ok = 0; + goto donecheck; } - if(dbpkg && pm_list_is_strin(j->data, dbpkg->files)) { + /* re-fetch with stat() instead of lstat() */ + stat(path, &buf); + if(S_ISDIR(buf.st_mode)) { + /* if it's a directory, then we have no conflict */ ok = 1; - } - /* Make sure that the supposedly-conflicting file is not actually just - * a symlink that points to a path that used to exist in the package. - */ - /* Check if any part of the conflicting file's path is a symlink */ - if(dbpkg && !ok) { - char str[PATH_MAX]; - for(k = dbpkg->files; k; k = k->next) { - snprintf(str, PATH_MAX, "%s%s", root, (char*)k->data); - stat(str, &buf2); - if(buf.st_ino == buf2.st_ino) { - ok = 1; - } + } else { + if(dbpkg == NULL) { + dbpkg = db_scan(db, p->name, INFRQ_DESC | INFRQ_FILES); } - } - /* Check if the conflicting file has been moved to another package/target */ - if(!ok) { - /* Look at all the targets */ - for(k = targets; k && !ok; k = k->next) { - pmpkg_t *p1 = (pmpkg_t *)k->data; - /* As long as they're not the current package */ - if(strcmp(p1->name, p->name)) { - pmpkg_t *dbpkg2 = NULL; - dbpkg2 = db_scan(db, p1->name, INFRQ_DESC | INFRQ_FILES); - /* If it used to exist in there, but doesn't anymore */ - if(dbpkg2 && !pm_list_is_strin(filestr, p1->files) && pm_list_is_strin(filestr, dbpkg2->files)) { + if(dbpkg && pm_list_is_strin(j->data, dbpkg->files)) { + ok = 1; + } + /* Make sure that the supposedly-conflicting file is not actually just + * a symlink that points to a path that used to exist in the package. + */ + /* Check if any part of the conflicting file's path is a symlink */ + if(dbpkg && !ok) { + char str[PATH_MAX]; + for(k = dbpkg->files; k; k = k->next) { + snprintf(str, PATH_MAX, "%s%s", root, (char*)k->data); + stat(str, &buf2); + if(buf.st_ino == buf2.st_ino) { ok = 1; } - FREEPKG(dbpkg2); + } + } + /* Check if the conflicting file has been moved to another package/target */ + if(!ok) { + /* Look at all the targets */ + for(k = targets; k && !ok; k = k->next) { + pmpkg_t *p1 = (pmpkg_t *)k->data; + /* As long as they're not the current package */ + if(strcmp(p1->name, p->name)) { + pmpkg_t *dbpkg2 = NULL; + dbpkg2 = db_scan(db, p1->name, INFRQ_DESC | INFRQ_FILES); + /* If it used to exist in there, but doesn't anymore */ + if(dbpkg2 && !pm_list_is_strin(filestr, p1->files) && pm_list_is_strin(filestr, dbpkg2->files)) { + ok = 1; + /* Add to the "skip list" of files that we shouldn't remove during an upgrade. + * + * This is a workaround for the following scenario: + * + * - the old package A provides file X + * - the new package A does not + * - the new package B provides file X + * - package A depends on B, so B is upgraded first + * + * Package B is upgraded, so file X is installed. Then package A + * is upgraded, and it *removes* file X, since it no longer exists + * in package A. + * + * Our workaround is to scan through all "old" packages and all "new" + * ones, looking for files that jump to different packages. + */ + *skip_list = pm_list_add(*skip_list, filestr); + } + FREEPKG(dbpkg2); + } } } } +donecheck: if(!ok) { MALLOC(str, 512); snprintf(str, 512, "%s: %s: exists in filesystem", p->name, path); diff --git a/lib/libalpm/conflict.h b/lib/libalpm/conflict.h index 133d714d..83bf55ca 100644 --- a/lib/libalpm/conflict.h +++ b/lib/libalpm/conflict.h @@ -23,7 +23,7 @@ #include "db.h" -PMList *db_find_conflicts(pmdb_t *db, PMList *targets, char *root); +PMList *db_find_conflicts(pmdb_t *db, PMList *targets, char *root, PMList **skip_list); #endif /* _ALPM_CONFLICT_H */ diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c index 6e855793..8567b87d 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -139,6 +139,15 @@ int handle_set_option(pmhandle_t *handle, unsigned char val, unsigned long data) _alpm_log(PM_LOG_FLOW2, "PM_OPT_NOUPGRADE flushed"); } break; + case PM_OPT_NOEXTRACT: + if((char *)data && strlen((char *)data) != 0) { + handle->noextract = pm_list_add(handle->noextract, strdup((char *)data)); + _alpm_log(PM_LOG_FLOW2, "'%s' added to PM_OPT_NOEXTRACT", (char *)data); + } else { + FREELIST(handle->noextract); + _alpm_log(PM_LOG_FLOW2, "PM_OPT_NOEXTRACT flushed"); + } + break; case PM_OPT_IGNOREPKG: if((char *)data && strlen((char *)data) != 0) { handle->ignorepkg = pm_list_add(handle->ignorepkg, strdup((char *)data)); @@ -189,6 +198,7 @@ int handle_get_option(pmhandle_t *handle, unsigned char val, long *data) case PM_OPT_SYNCDB: *data = (long)handle->dbs_sync; break; case PM_OPT_LOGFILE: *data = (long)handle->logfile; break; case PM_OPT_NOUPGRADE: *data = (long)handle->noupgrade; break; + case PM_OPT_NOEXTRACT: *data = (long)handle->noextract; break; case PM_OPT_IGNOREPKG: *data = (long)handle->ignorepkg; break; case PM_OPT_USESYSLOG: *data = handle->usesyslog; break; case PM_OPT_LOGCB: *data = (long)pm_logcb; break; diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h index 5f3e8e8e..a37ee0fd 100644 --- a/lib/libalpm/handle.h +++ b/lib/libalpm/handle.h @@ -44,6 +44,7 @@ typedef struct __pmhandle_t { char *dbpath; char *logfile; PMList *noupgrade; /* List of strings */ + PMList *noextract; /* List of strings */ PMList *ignorepkg; /* List of strings */ unsigned char usesyslog; } pmhandle_t; diff --git a/lib/libalpm/list.c b/lib/libalpm/list.c index 9d3f4005..8bf0d702 100644 --- a/lib/libalpm/list.c +++ b/lib/libalpm/list.c @@ -256,6 +256,24 @@ PMList* pm_list_last(PMList *list) return(list->last); } +/* Filter out any duplicate strings in a list. + * + * Not the most efficient way, but simple to implement -- we assemble + * a new list, using is_in() to check for dupes at each iteration. + * + */ +PMList *_alpm_list_remove_dupes(PMList *list) +{ + PMList *i, *newlist = NULL; + + for(i = list; i; i = i->next) { + if(!pm_list_is_strin(i->data, newlist)) { + newlist = pm_list_add(newlist, strdup(i->data)); + } + } + return newlist; +} + /* Reverse the order of a list * * The caller is responsible for freeing the old list diff --git a/lib/libalpm/list.h b/lib/libalpm/list.h index 35bacd00..e625dbff 100644 --- a/lib/libalpm/list.h +++ b/lib/libalpm/list.h @@ -55,6 +55,7 @@ int pm_list_count(PMList *list); int pm_list_is_in(void *needle, PMList *haystack); PMList *pm_list_is_strin(char *needle, PMList *haystack); PMList *pm_list_last(PMList *list); +PMList *_alpm_list_remove_dupes(PMList *list); PMList *_alpm_list_reverse(PMList *list); PMList *_alpm_list_strdup(PMList *list); diff --git a/lib/libalpm/md5.h b/lib/libalpm/md5.h index e6e4ea64..20aae92b 100644 --- a/lib/libalpm/md5.h +++ b/lib/libalpm/md5.h @@ -31,7 +31,7 @@ typedef unsigned char *POINTER; typedef unsigned short int UINT2; /* UINT4 defines a four byte word */ -typedef unsigned long int UINT4; +typedef unsigned int UINT4; /* MD5 context. */ diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index fd00eae1..0e335906 100644 --- a/lib/libalpm/remove.c +++ b/lib/libalpm/remove.c @@ -191,28 +191,42 @@ int remove_commit(pmtrans_t *trans, pmdb_t *db) _alpm_log(PM_LOG_FLOW2, "removing directory %s", file); } } else { - /* if the file is flagged, back it up to .pacsave */ - if(nb) { - if(trans->type == PM_TRANS_TYPE_UPGRADE) { - /* we're upgrading so just leave the file as is. pacman_add() will handle it */ - } else { - if(!(trans->flags & PM_TRANS_FLAG_NOSAVE)) { - char newpath[PATH_MAX]; - snprintf(newpath, PATH_MAX, "%s.pacsave", line); - rename(line, newpath); - _alpm_log(PM_LOG_WARNING, "%s saved as %s", file, newpath); - alpm_logaction("%s saved as %s", line, newpath); + /* check the "skip list" before removing the file. + * see the big comment block in db_find_conflicts() for an + * explanation. */ + int skipit = 0; + PMList *j; + for(j = trans->skiplist; j; j = j->next) { + if(!strcmp(file, (char*)j->data)) { + skipit = 1; + } + } + if(skipit) { + _alpm_log(PM_LOG_FLOW2, "skipping removal of %s as it has moved to another package\n", file); + } else { + /* if the file is flagged, back it up to .pacsave */ + if(nb) { + if(trans->type == PM_TRANS_TYPE_UPGRADE) { + /* we're upgrading so just leave the file as is. pacman_add() will handle it */ } else { - _alpm_log(PM_LOG_FLOW2, "unlinking %s", file); - if(unlink(line)) { - _alpm_log(PM_LOG_ERROR, "cannot remove file %s", file); + if(!(trans->flags & PM_TRANS_FLAG_NOSAVE)) { + char newpath[PATH_MAX]; + snprintf(newpath, PATH_MAX, "%s.pacsave", line); + rename(line, newpath); + _alpm_log(PM_LOG_WARNING, "%s saved as %s", file, newpath); + alpm_logaction("%s saved as %s", line, newpath); + } else { + _alpm_log(PM_LOG_FLOW2, "unlinking %s", file); + if(unlink(line)) { + _alpm_log(PM_LOG_ERROR, "cannot remove file %s", file); + } } } - } - } else { - _alpm_log(PM_LOG_FLOW2, "unlinking %s", file); - if(unlink(line)) { - _alpm_log(PM_LOG_ERROR, "cannot remove file %s", file); + } else { + _alpm_log(PM_LOG_FLOW2, "unlinking %s", file); + if(unlink(line)) { + _alpm_log(PM_LOG_ERROR, "cannot remove file %s", file); + } } } } diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c index c7c4448f..43f134e0 100644 --- a/lib/libalpm/trans.c +++ b/lib/libalpm/trans.c @@ -46,6 +46,7 @@ pmtrans_t *trans_new() trans->targets = NULL; trans->packages = NULL; + trans->skiplist = NULL; trans->type = 0; trans->flags = 0; trans->cb_event = NULL; @@ -68,6 +69,7 @@ void trans_free(pmtrans_t *trans) i->data = NULL; } FREELIST(trans->packages); + FREELIST(trans->skiplist); } else { FREELISTPKGS(trans->packages); } diff --git a/lib/libalpm/trans.h b/lib/libalpm/trans.h index 96b9083b..8518e5aa 100644 --- a/lib/libalpm/trans.h +++ b/lib/libalpm/trans.h @@ -36,6 +36,7 @@ typedef struct __pmtrans_t { unsigned char state; PMList *targets; /* PMList of (char *) */ PMList *packages; /* PMList of (pmpkg_t *) or (pmsyncpkg_t *) */ + PMList *skiplist; /* PMList of (char *) */ alpm_trans_cb_event cb_event; } pmtrans_t; diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 4836812e..6b2b60a6 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -40,6 +40,8 @@ #include "util.h" #include "alpm.h" +static char *chrootbin = NULL; + /* borrowed and modified from Per Liden's pkgutils (http://crux.nu) */ long _alpm_gzopen_frontend(char *pathname, int oflags, int mode) { @@ -366,6 +368,23 @@ int _alpm_runscriptlet(char *root, char *installfn, char *script, char *ver, cha return(0); } + if(chrootbin == NULL) { + char *dirs[] = {"/usr/sbin","/usr/bin","/sbin","/bin"}; + int i; + for(i = 0; i < 4 && !chrootbin; i++) { + char cpath[PATH_MAX]; + snprintf(cpath, PATH_MAX, "%s/chroot", dirs[i]); + if(!stat(cpath, &buf)) { + chrootbin = strdup(cpath); + _alpm_log(PM_LOG_DEBUG, "found chroot binary: %s", chrootbin); + } + } + if(chrootbin == NULL) { + _alpm_log(PM_LOG_ERROR, "cannot find chroot binary - unable to run scriptlet"); + return(1); + } + } + if(!strcmp(script, "pre_upgrade") || !strcmp(script, "pre_install")) { snprintf(tmpdir, PATH_MAX, "%stmp/", root); if(stat(tmpdir, &buf)) { diff --git a/lib/libftp/Makefile b/lib/libftp/Makefile index c68bf2b5..bf17940c 100644 --- a/lib/libftp/Makefile +++ b/lib/libftp/Makefile @@ -10,15 +10,16 @@ DEFINES = -DFTPLIB_DEFMODE=FTPLIB_PORT SONAME = 3 SOVERSION = $(SONAME).1 -TARGETS = qftp libftp.a libftp.so -OBJECTS = qftp.o ftplib.o -SOURCES = qftp.c ftplib.c +TARGETS = libftp.a libftp.so +OBJECTS = ftplib.o +SOURCES = ftplib.c CFLAGS = -Wall $(DEBUG) -I. $(INCLUDES) $(DEFINES) LDFLAGS = -L. DEPFLAGS = -all : $(TARGETS) +#all : $(TARGETS) +all : libftp.a clean : rm -f $(OBJECTS) core *.bak @@ -29,15 +30,11 @@ clobber : clean rm -f libftp.so.* install : all - install qftp /usr/local/bin install -m 644 libftp.so.$(SOVERSION) /usr/local/lib install -m 644 ftplib.h /usr/local/include (cd /usr/local/lib && \ ln -sf libftp.so.$(SOVERSION) libftp.so.$(SONAME) && \ ln -sf libftp.so.$(SONAME) libftp.so) - -(cd /usr/local/bin && \ - for f in ftpdir ftpget ftplist ftprm ftpsend; \ - do ln -s qftp $$f; done) depend : $(CC) $(CFLAGS) -M $(SOURCES) > .depend @@ -60,9 +57,6 @@ libftp.so: libftp.so.$(SOVERSION) ln -sf $< libftp.so.$(SONAME) ln -sf $< $@ -qftp : qftp.o libftp.so ftplib.h - $(CC) $(LDFLAGS) -o $@ $< -lftp - ifeq (.depend,$(wildcard .depend)) include .depend endif diff --git a/src/pacman/Makefile b/src/pacman/Makefile index 9aebc67c..a6b6cad2 100644 --- a/src/pacman/Makefile +++ b/src/pacman/Makefile @@ -25,7 +25,7 @@ all: pacman %.o: %.c %.h $(CC) -c $(CFLAGS) -o $@ $< -pacman: $(OBJECTS) ../../lib/libalpm/libalpm.a +pacman: $(OBJECTS) ../../lib/libalpm/libalpm.a ../../lib/libftp/libftp.a $(CC) $(OBJECTS) -o $@ $(CFLAGS) $(LDFLAGS) # $(CC) $(OBJECTS) -o $@.static $(CFLAGS) $(LDFLAGS) diff --git a/src/pacman/conf.c b/src/pacman/conf.c index 7bf02d03..0aceecf2 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -159,6 +159,24 @@ int parseconfig(char *file) return(1); } vprint("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) { + ERR(NL, "failed to set option NOEXTRACT (%s)\n", alpm_strerror(pm_errno)); + return(1); + } + vprint("config: noextract: %s\n", p); + p = q; + p++; + } + if(alpm_set_option(PM_OPT_NOEXTRACT, (long)p) == -1) { + ERR(NL, "failed to set option NOEXTRACT (%s)\n", alpm_strerror(pm_errno)); + return(1); + } + vprint("config: noextract: %s\n", p); } else if(!strcmp(key, "IGNOREPKG")) { char *p = ptr; char *q; diff --git a/src/pacman/db.c b/src/pacman/db.c index e6e17775..a00aaad4 100644 --- a/src/pacman/db.c +++ b/src/pacman/db.c @@ -34,63 +34,86 @@ #include "sync.h" #include "db.h" -int db_search(PM_DB *db, char *treename, char *needle) +int db_search(PM_DB *db, const char *treename, list_t *needles) { - PM_LIST *lp; - char *targ; + list_t *i; - targ = strdup(needle); - strtoupper(targ); + if(needles == NULL || needles->data == NULL) { + return(0); + } + + for(i = needles; i; i = i->next) { + PM_LIST *j; + char *targ; + int ret; - for(lp = alpm_db_getpkgcache(db); lp; lp = alpm_list_next(lp)) { - PM_PKG *pkg = alpm_list_getdata(lp); - char *haystack; - char *pkgname, *pkgdesc; - int match = 0; + if(i->data == NULL) { + continue; + } + targ = strdup(i->data); - pkgname = alpm_pkg_getinfo(pkg, PM_PKG_NAME); - pkgdesc = alpm_pkg_getinfo(pkg, PM_PKG_DESC); + for(j = alpm_db_getpkgcache(db); j; j = alpm_list_next(j)) { + PM_PKG *pkg = alpm_list_getdata(j); + char *haystack; + char *pkgname, *pkgdesc; + int match = 0; - /* check name */ - haystack = strdup(pkgname); - strtoupper(haystack); - if(strstr(haystack, targ)) { - match = 1; - } - FREE(haystack); + pkgname = alpm_pkg_getinfo(pkg, PM_PKG_NAME); + pkgdesc = alpm_pkg_getinfo(pkg, PM_PKG_DESC); - /* check description */ - if(!match) { - haystack = strdup(pkgdesc); - strtoupper(haystack); - if(strstr(haystack, targ)) { + /* check name */ + haystack = strdup(pkgname); + ret = reg_match(haystack, targ); + if(ret < 0) { + /* bad regexp */ + FREE(haystack); + return(1); + } else if(ret) { match = 1; } FREE(haystack); - } - - /* check provides */ - if(!match) { - PM_LIST *m; - for(m = alpm_pkg_getinfo(pkg, PM_PKG_PROVIDES); m; m = alpm_list_next(m)) { - haystack = strdup(alpm_list_getdata(m)); - strtoupper(haystack); - if(strstr(haystack, targ)) { + /* check description */ + if(!match) { + haystack = strdup(pkgdesc); + ret = reg_match(haystack, targ); + if(ret < 0) { + /* bad regexp */ + FREE(haystack); + return(1); + } else if(ret) { match = 1; } FREE(haystack); } - } - if(match) { - printf("%s/%s %s\n ", treename, pkgname, (char *)alpm_pkg_getinfo(pkg, PM_PKG_VERSION)); - indentprint(pkgdesc, 4); - printf("\n"); + /* check provides */ + if(!match) { + PM_LIST *m; + + for(m = alpm_pkg_getinfo(pkg, PM_PKG_PROVIDES); m; m = alpm_list_next(m)) { + haystack = strdup(alpm_list_getdata(m)); + ret = reg_match(haystack, targ); + if(ret < 0) { + /* bad regexp */ + FREE(haystack); + return(1); + } else if(ret) { + match = 1; + } + FREE(haystack); + } + } + + if(match) { + printf("%s/%s %s\n ", treename, pkgname, (char *)alpm_pkg_getinfo(pkg, PM_PKG_VERSION)); + indentprint(pkgdesc, 4); + printf("\n"); + } } - } - FREE(targ); + FREE(targ); + } return(0); } diff --git a/src/pacman/db.h b/src/pacman/db.h index 7b38719f..d28b0976 100644 --- a/src/pacman/db.h +++ b/src/pacman/db.h @@ -21,7 +21,7 @@ #ifndef _PM_DB_H #define _PM_DB_H -int db_search(PM_DB *db, char *treename, char *needle); +int db_search(PM_DB *db, const char *treename, list_t *needles); #endif /* _PM_DB_H */ diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index 89033813..eb5a8da8 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -26,6 +26,7 @@ #include #include #include +#include #ifndef CYGWIN #include /* debug */ #else @@ -96,6 +97,7 @@ int main(int argc, char *argv[]) { int ret = 0; char *cenv = NULL; + uid_t myuid; #ifndef CYGWIN /* debug */ @@ -122,6 +124,27 @@ int main(int argc, char *argv[]) exit(ret); } + /* see if we're root or not */ + myuid = geteuid(); + if(!myuid && getenv("FAKEROOTKEY")) { + /* fakeroot doesn't count, we're non-root */ + myuid = 99; + } + + /* check if we have sufficient permission for the requested operation */ + if(myuid > 0) { + if(pmo_op != PM_OP_MAIN && pmo_op != PM_OP_QUERY && pmo_op != PM_OP_DEPTEST) { + if((pmo_op == PM_OP_SYNC && !pmo_s_sync && + (pmo_s_search || pmo_s_printuris || pmo_group || pmo_q_list || + pmo_q_info)) || (pmo_op == PM_OP_DEPTEST && !pmo_d_resolve)) { + /* special case: PM_OP_SYNC can be used w/ pmo_s_search by any user */ + } else { + ERR(NL, "you cannot perform this operation unless you are root.\n"); + exit(1); + } + } + } + if(pmo_root == NULL) { pmo_root = strdup("/"); } diff --git a/src/pacman/query.c b/src/pacman/query.c index 6f4f7c4c..71c02c71 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -106,8 +106,8 @@ int pacman_query(list_t *targets) int done = 0; if(pmo_q_search) { - for(targ = targets; targ; targ = targ->next) { - db_search(db_local, "local", targ->data); + if(db_search(db_local, "local", targets)) { + return(1); } return(0); } diff --git a/src/pacman/sync.c b/src/pacman/sync.c index 17b9b3a2..4d1c5143 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -219,10 +219,8 @@ static int sync_search(list_t *syncs, list_t *targets) for(i = syncs; i; i = i->next) { sync_t *sync = i->data; if(targets) { - list_t *j; - - for(j = targets; j; j = j->next) { - db_search(sync->db, sync->treename, j->data); + if(db_search(sync->db, sync->treename, targets)) { + return(1); } } else { PM_LIST *lp; diff --git a/src/pacman/util.c b/src/pacman/util.c index 1d3844a3..5a60070b 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef CYGWIN #include /* PATH_MAX */ #endif @@ -224,4 +225,19 @@ int yesno(char *fmt, ...) return(0); } +/* match a string against a regular expression */ +int reg_match(char *string, char *pattern) +{ + int result; + regex_t reg; + + if(regcomp(®, pattern, REG_EXTENDED | REG_NOSUB | REG_ICASE) != 0) { + fprintf(stderr, "error: %s is not a valid regular expression.\n", pattern); + return(-1); + } + result = regexec(®, string, 0, 0, 0); + regfree(®); + return(!(result)); +} + /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/util.h b/src/pacman/util.h index b181dbd1..755f0b96 100644 --- a/src/pacman/util.h +++ b/src/pacman/util.h @@ -34,6 +34,7 @@ void indentprint(char *str, int indent); char *strtrim(char *str); char *strtoupper(char *str); int yesno(char *fmt, ...); +int reg_match(char *string, char *pattern); #endif /* _PM_UTIL_H */ -- cgit v1.2.3-70-g09d2