From f6b8ed22f40d422e2876be92b215187b5ff7b6e7 Mon Sep 17 00:00:00 2001 From: Judd Vinet Date: Sun, 19 Dec 2004 03:37:00 +0000 Subject: Imported from pacman-2.9.3.tar.gz --- src/convertdb.c | 7 +- src/db.c | 127 ++++++++++++++++++++++++------ src/list.c | 104 ++++++++++++++++++++++++- src/list.h | 2 + src/pacconf.h | 46 +++++++++++ src/package.c | 3 +- src/pacman.c | 235 ++++++++++++++++++++++++++++++++------------------------ src/pacman.h | 17 ---- src/pacsync.c | 40 +++++++++- src/strhash.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++ src/strhash.h | 65 ++++++++++++++++ src/util.c | 16 ++++ src/util.h | 1 + 13 files changed, 708 insertions(+), 150 deletions(-) create mode 100644 src/pacconf.h create mode 100644 src/strhash.c create mode 100644 src/strhash.h (limited to 'src') diff --git a/src/convertdb.c b/src/convertdb.c index cd6be3db..af083fb1 100644 --- a/src/convertdb.c +++ b/src/convertdb.c @@ -28,15 +28,17 @@ #include #include #include +#include "pacconf.h" #include "list.h" #include "util.h" +unsigned short pmo_verbose = 0; + int main(int argc, char* argv[]) { FILE* db = NULL; FILE* fp = NULL; char* ptr = NULL; - char* dbdir = "/var/lib/pacman/pacman.db"; char name[256]; char ver[256]; char line[PATH_MAX+1]; @@ -44,6 +46,9 @@ int main(int argc, char* argv[]) char path[PATH_MAX+1]; mode_t oldumask; struct stat buf; + char dbdir[PATH_MAX]; + + sprintf(dbdir, "/%s", PACDBDIR); if(argc < 2) { printf("converts a pacman 1.x database to a pacman 2.0 format\n"); diff --git a/src/db.c b/src/db.c index 4d856479..8fb96fed 100644 --- a/src/db.c +++ b/src/db.c @@ -29,6 +29,7 @@ #include #include #include "package.h" +#include "strhash.h" #include "util.h" #include "db.h" @@ -131,26 +132,63 @@ pkginfo_t* db_scan(pacdb_t *db, char *target, unsigned int inforeq) struct dirent *ent = NULL; struct stat sbuf; char path[PATH_MAX]; - char name[256]; + int path_len = 0; + char *name = NULL; char *ptr = NULL; int found = 0; + /* hash table for caching directory names */ + static strhash_t* htable = NULL; + + if (!htable) + htable = new_strhash(951); + + snprintf(path, PATH_MAX, "%s/", db->path); + path_len = strlen(path); + if(target != NULL) { /* search for a specific package (by name only) */ + + /* See if we have the path cached. */ + strcat(path, target); + if (strhash_isin(htable, path)) { + struct dirent* pkgdir; + pkginfo_t* pkg; + + /* db_read() wants 'struct dirent' so lets give it one. + * Actually it only uses the d_name field. */ + + MALLOC(pkgdir, sizeof(struct dirent)); + strcpy(pkgdir->d_name, strhash_get(htable, path)); + + pkg = db_read(db, pkgdir, inforeq); + FREE(pkgdir); + return pkg; + } + path[path_len] = '\0'; + + /* OK the entry was not in cache, so lets look for it manually. */ + rewinddir(db->dir); ent = readdir(db->dir); + while(!found && ent != NULL) { if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { ent = readdir(db->dir); continue; } - strncpy(name, ent->d_name, 255); + /* stat the entry, make sure it's a directory */ - snprintf(path, PATH_MAX, "%s/%s", db->path, name); + path[path_len] = '\0'; + strncat(path, ent->d_name, PATH_MAX - path_len); + if(stat(path, &sbuf) || !S_ISDIR(sbuf.st_mode)) { ent = readdir(db->dir); continue; } + + name = path + path_len; + /* truncate the string at the second-to-last hyphen, */ /* which will give us the package name */ if((ptr = rindex(name, '-'))) { @@ -176,8 +214,11 @@ pkginfo_t* db_scan(pacdb_t *db, char *target, unsigned int inforeq) 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); + path[path_len] = '\0'; + strncat(path, ent->d_name, PATH_MAX - path_len); + if(!stat(path, &sbuf) && S_ISDIR(sbuf.st_mode)) { isdir = 1; } @@ -185,6 +226,25 @@ pkginfo_t* db_scan(pacdb_t *db, char *target, unsigned int inforeq) isdir = 0; continue; } + + name = path + path_len; + + if((ptr = rindex(name, '-'))) { + *ptr = '\0'; + } + if((ptr = rindex(name, '-'))) { + *ptr = '\0'; + } + + /* Add entries like: + * + * key: /var/lib/pacman/extra/xrally + * data: xrally-1.1.1-1 + */ + + if (!strhash_isin(htable, path)) { + strhash_add(htable, strdup(path), strdup(ent->d_name)); + } } } return(db_read(db, ent, inforeq)); @@ -603,6 +663,28 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root) char *str = NULL; struct stat buf, buf2; PMList *conflicts = NULL; + strhash_t** htables; + int target_num = 0; + int d = 0; + int e = 0; + + /* Create and initialise an array of hash tables. + * + * htables [ 0 ... target_num ] : targets' files + * htables [ target_num ] : used later + */ + + target_num = list_count(targets); + + MALLOC(htables, (target_num+1) * sizeof(strhash_t*)); + + for(d = 0, i = targets; i; i = i->next, d++) { + htables[d] = new_strhash(151); + + strhash_add_list(htables[d], ((pkginfo_t*)i->data)->files); + } + + htables[target_num] = new_strhash(151); /* CHECK 1: check every db package against every target package */ /* XXX: I've disabled the database-against-targets check for now, as the @@ -613,34 +695,30 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root) pkginfo_t *info = NULL; char *dbstr = NULL; rewinddir(db->dir); + 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) { + + if(dbstr == NULL || rindex(dbstr, '/') == dbstr+strlen(dbstr)-1) + continue; + + for(d = 0, j = targets; j; j = j->next, d++) { pkginfo_t *targ = (pkginfo_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 = list_add(conflicts, str); - } - } + if(strcmp(info->name, targ->name) && strhash_isin(htables[d], dbstr)) { + MALLOC(str, 512); + snprintf(str, 512, "%s: exists in \"%s\" (target) and \"%s\" (installed)", dbstr, + targ->name, info->name); + conflicts = list_add(conflicts, str); } } } }*/ /* CHECK 2: check every target against every target */ - for(i = targets; i; i = i->next) { + for(d = 0, i = targets; i; i = i->next, d++) { pkginfo_t *p1 = (pkginfo_t*)i->data; - for(j = i; j; j = j->next) { + for(e = d, j = i; j; j = j->next, e++) { pkginfo_t *p2 = (pkginfo_t*)j->data; if(strcmp(p1->name, p2->name)) { for(k = p1->files; k; k = k->next) { @@ -652,7 +730,7 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root) /* this filename has a trailing '/', so it's a directory -- skip it. */ continue; } - if(is_in(filestr, p2->files)) { + if(strhash_isin(htables[e], filestr)) { MALLOC(str, 512); snprintf(str, 512, "%s: exists in \"%s\" (target) and \"%s\" (target)", filestr, p1->name, p2->name); @@ -674,8 +752,11 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root) int ok = 0; if(dbpkg == NULL) { dbpkg = db_scan(db, p->name, INFRQ_DESC | INFRQ_FILES); + + if(dbpkg) + strhash_add_list(htables[target_num], dbpkg->files); } - if(dbpkg && is_in(j->data, dbpkg->files)) { + if(dbpkg && strhash_isin(htables[target_num], filestr)) { ok = 1; } /* Make sure that the supposedly-conflicting file is not actually just diff --git a/src/list.c b/src/list.c index 0ec43353..6abc0719 100644 --- a/src/list.c +++ b/src/list.c @@ -23,8 +23,32 @@ #include #include #include +#include #include "list.h" +/* 1: List seems to be OK. + * 0: We're in deep ... + */ + +int CheckList(PMList* list) +{ + PMList* it = NULL; + + if (list == NULL) + return 1; + + if (list->last == NULL) + return 0; + + for (it = list; it && it->next; it = it->next) + ; + + if (it != list->last) + return 0; + + return 1; +} + PMList* list_new() { PMList *list = NULL; @@ -36,6 +60,7 @@ PMList* list_new() list->data = NULL; list->prev = NULL; list->next = NULL; + list->last = list; return(list); } @@ -62,6 +87,8 @@ PMList* list_add(PMList *list, void *data) ptr = list; if(ptr == NULL) { ptr = list_new(); + if (!ptr) + return(NULL); } lp = list_last(ptr); @@ -73,12 +100,67 @@ PMList* list_add(PMList *list, void *data) return(NULL); } lp->next->prev = lp; + lp->last = NULL; lp = lp->next; } + lp->data = data; + ptr->last = lp; + return(ptr); } +/* list: the beginning of the list + * item: the item in the list to be removed + * + * returns: + * list with item removed + */ + +PMList* list_remove(PMList* list, PMList* item) +{ + assert(CheckList(list)); + + if (list == NULL || item == NULL) + return NULL; + + /* Remove first item in list. */ + if (item == list) { + if (list->next == NULL) { /* Only item in list. */ + list_free(item); + return NULL; + } else { + list->next->prev = NULL; + list->next->last = list->last; + list = list->next; + item->prev = item->next = NULL; + list_free(item); + return list; + } + } + + /* Remove last item in list. */ + if (list->last == item) { + list->last = item->prev; + item->prev->next = NULL; + item->prev = item->next = NULL; + list_free(item); + return list; + } + + /* Remove middle item in list. */ + assert(item->prev != NULL && + item->next != NULL); + + item->prev->next = item->next; + item->next->prev = item->prev; + item->prev = item->next = NULL; + list_free(item); + + assert(CheckList(list)); + return list; +} + int list_count(PMList *list) { int i; @@ -141,10 +223,11 @@ PMList* list_merge(PMList *one, PMList *two) PMList* list_last(PMList *list) { - PMList *ptr; + if (list == NULL) + return NULL; - for(ptr = list; ptr && ptr->next; ptr = ptr->next); - return(ptr); + assert(list->last != NULL); + return list->last; } /* Helper function for sorting a list of strings @@ -257,10 +340,23 @@ PMList* list_add_sorted(PMList *list, void *data, cmp_fn sortfunc) /* Insert node before insertion point. */ add->prev = prev; add->next = iter; - if(iter != NULL) iter->prev = add; /* Not at end. */ + + if(iter != NULL) { + iter->prev = add; /* Not at end. */ + } else { + if (list != NULL) + list->last = add; /* Added new to end, so update the link to last. */ + } + if(prev != NULL) { prev->next = add; /* In middle. */ } else { + if (list == NULL) { + add->last = add; + } else { + add->last = list->last; + list->last = NULL; + } list = add; /* Start or empty, new list head. */ } diff --git a/src/list.h b/src/list.h index 655ffc7d..4f8d917a 100644 --- a/src/list.h +++ b/src/list.h @@ -28,6 +28,7 @@ typedef struct __pmlist_t { void* data; struct __pmlist_t* prev; struct __pmlist_t* next; + struct __pmlist_t* last; /* Quick access to last item in list */ } PMList; @@ -38,6 +39,7 @@ typedef int (*cmp_fn) (const void *, const void *); PMList* list_new(); void list_free(PMList* list); PMList* list_add(PMList* list, void* data); +PMList* list_remove(PMList* list, PMList* item); int list_count(PMList* list); int list_isin(PMList *haystack, void *needle); PMList* is_in(char *needle, PMList *haystack); diff --git a/src/pacconf.h b/src/pacconf.h new file mode 100644 index 00000000..befe46bf --- /dev/null +++ b/src/pacconf.h @@ -0,0 +1,46 @@ +/* + * pacconf.h + * + * Copyright (c) 2002-2004 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. + */ +#ifndef _PAC_PACCONF_H +#define _PAC_PACCONF_H + +#ifndef PACVER +#define PACVER "2.9.3" +#endif + +#ifndef PACDBDIR +#define PACDBDIR "var/lib/pacman" +#endif + +#ifndef PKGEXT +#define PKGEXT ".pkg.tar.gz" +#endif + +#ifndef PACCONF +#define PACCONF "/etc/pacman.conf" +#endif + +#ifndef CACHEDIR +#define CACHEDIR "var/cache/pacman/pkg" +#endif + +#endif /* PACCONF_H */ + +/* vim: set ts=2 sw=2 noet: */ diff --git a/src/package.c b/src/package.c index ada6f411..644eea17 100644 --- a/src/package.c +++ b/src/package.c @@ -27,6 +27,7 @@ #include #include #include +#include "pacconf.h" #include "util.h" #include "package.h" @@ -410,7 +411,7 @@ int split_pkgname(char *pkgfile, char *name, char *version) } strncpy(tmp, p, 512); /* trim file extension (if any) */ - if((p = strstr(tmp, ".pkg.tar.gz"))) { + if((p = strstr(tmp, PKGEXT))) { *p = 0; } diff --git a/src/pacman.c b/src/pacman.c index ef0995e4..f9c2da2f 100644 --- a/src/pacman.c +++ b/src/pacman.c @@ -37,6 +37,7 @@ #include #include /* pacman */ +#include "pacconf.h" #include "rpmvercmp.h" #include "md5.h" #include "list.h" @@ -52,35 +53,36 @@ */ /* command line options */ -char *pmo_root = NULL; -unsigned short pmo_op = PM_MAIN; -unsigned short pmo_verbose = 0; -unsigned short pmo_version = 0; -unsigned short pmo_help = 0; -unsigned short pmo_force = 0; -unsigned short pmo_nodeps = 0; -unsigned short pmo_upgrade = 0; -unsigned short pmo_freshen = 0; -unsigned short pmo_nosave = 0; -unsigned short pmo_noconfirm = 0; -unsigned short pmo_d_vertest = 0; -unsigned short pmo_d_resolve = 0; -unsigned short pmo_q_isfile = 0; -unsigned short pmo_q_info = 0; -unsigned short pmo_q_list = 0; -unsigned short pmo_q_orphans = 0; -unsigned short pmo_q_owns = 0; -unsigned short pmo_q_search = 0; -unsigned short pmo_r_cascade = 0; -unsigned short pmo_r_dbonly = 0; -unsigned short pmo_r_recurse = 0; -unsigned short pmo_s_upgrade = 0; +char *pmo_root = NULL; +unsigned short pmo_op = PM_MAIN; +unsigned short pmo_verbose = 0; +unsigned short pmo_version = 0; +unsigned short pmo_help = 0; +unsigned short pmo_force = 0; +unsigned short pmo_nodeps = 0; +unsigned short pmo_upgrade = 0; +unsigned short pmo_freshen = 0; +unsigned short pmo_nosave = 0; +unsigned short pmo_noconfirm = 0; +unsigned short pmo_d_vertest = 0; +unsigned short pmo_d_resolve = 0; +unsigned short pmo_q_isfile = 0; +unsigned short pmo_q_info = 0; +unsigned short pmo_q_list = 0; +unsigned short pmo_q_orphans = 0; +unsigned short pmo_q_owns = 0; +unsigned short pmo_q_search = 0; +unsigned short pmo_r_cascade = 0; +unsigned short pmo_r_dbonly = 0; +unsigned short pmo_r_recurse = 0; +unsigned short pmo_s_upgrade = 0; unsigned short pmo_s_downloadonly = 0; unsigned short pmo_s_printuris = 0; -unsigned short pmo_s_sync = 0; -unsigned short pmo_s_search = 0; -unsigned short pmo_s_clean = 0; -unsigned short pmo_group = 0; +unsigned short pmo_s_sync = 0; +unsigned short pmo_s_search = 0; +unsigned short pmo_s_clean = 0; +PMList *pmo_s_ignore = NULL; +unsigned short pmo_group = 0; /* configuration file options */ char *pmo_dbpath = NULL; char *pmo_configfile = NULL; @@ -91,6 +93,7 @@ char *pmo_xfercommand = NULL; PMList *pmo_noupgrade = NULL; PMList *pmo_ignorepkg = NULL; PMList *pmo_holdpkg = NULL; +unsigned short pmo_chomp = 0; unsigned short pmo_usesyslog = 0; unsigned short pmo_nopassiveftp = 0; @@ -132,7 +135,7 @@ int main(int argc, char *argv[]) strcpy(pmo_root, "/"); /* default dbpath */ MALLOC(pmo_dbpath, PATH_MAX); - strcpy(pmo_dbpath, PKGDIR); + strcpy(pmo_dbpath, PACDBDIR); /* default configuration file */ MALLOC(pmo_configfile, PATH_MAX); strcpy(pmo_configfile, PACCONF); @@ -152,6 +155,9 @@ int main(int argc, char *argv[]) myuid = 99; } + /* change to / so we can avoid having our CWD removed from under us */ + chdir("/"); + /* check for permission */ pm_access = READ_ONLY; if(pmo_op != PM_MAIN && pmo_op != PM_QUERY && pmo_op != PM_DEPTEST) { @@ -343,9 +349,12 @@ int pacman_sync(pacdb_t *db, PMList *targets) PMList *cache = NULL; PMList *clean = NULL; PMList *i, *j; + char dirpath[PATH_MAX]; + + snprintf(dirpath, PATH_MAX, "%s%s", pmo_root, CACHEDIR); printf("removing old packages from cache... "); - dir = opendir("/var/cache/pacman/pkg"); + dir = opendir(dirpath); if(dir == NULL) { fprintf(stderr, "error: could not access cache directory\n"); return(1); @@ -361,14 +370,15 @@ int pacman_sync(pacdb_t *db, PMList *targets) for(i = cache; i; i = i->next) { char *str = (char *)i->data; - char name[256], version[64]; + char pkgpart[256], name[256], version[64]; - if(strstr(str, ".pkg.tar.gz") == NULL) { + if(strstr(str, PKGEXT) == NULL) { clean = list_add(clean, strdup(str)); continue; } + snprintf(pkgpart, sizeof(pkgpart), "%s.part", PKGEXT); /* we keep partially downloaded files */ - if(strstr(str, ".pkg.tar.gz.part")) { + if(strstr(str, pkgpart)) { continue; } if(split_pkgname(str, name, version) != 0) { @@ -379,10 +389,10 @@ int pacman_sync(pacdb_t *db, PMList *targets) char *s = (char *)j->data; char n[256], v[64]; - if(strstr(s, ".pkg.tar.gz") == NULL) { + if(strstr(s, PKGEXT) == NULL) { continue; } - if(strstr(s, ".pkg.tar.gz.part")) { + if(strstr(s, pkgpart)) { continue; } if(split_pkgname(s, n, v) != 0) { @@ -617,7 +627,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) for(m = pm_packages; m; m = m->next) { pkginfo_t *p = (pkginfo_t*)m->data; if(!strcmp(k->data, p->name)) { - if(is_in(p->name, pmo_ignorepkg)) { + if(is_in(p->name, pmo_ignorepkg) || is_in(p->name, pmo_s_ignore)) { fprintf(stderr, ":: %s-%s: ignoring package upgrade (to be replaced by %s-%s)\n", p->name, p->version, pkg->name, pkg->version); ignore = 1; @@ -684,8 +694,8 @@ int pacman_sync(pacdb_t *db, PMList *targets) cmp = rpmvercmp(local->version, sync->pkg->version); if(cmp > 0 && !sync->pkg->force) { /* local version is newer */ - fprintf(stderr, ":: %s-%s: local version is newer\n", - local->name, local->version); + fprintf(stderr, ":: %s: local version (%s) is newer than repo version (%s)\n", + local->name, local->version, sync->pkg->version); newer = 1; FREE(sync); continue; @@ -693,7 +703,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) /* versions are identical */ FREE(sync); continue; - } else if(is_in((char*)i->data, pmo_ignorepkg)) { + } else if(is_in((char*)i->data, pmo_ignorepkg) || is_in((char*)i->data, pmo_s_ignore)) { /* package should be ignored (IgnorePkg) */ fprintf(stderr, ":: %s-%s: ignoring package upgrade (%s)\n", local->name, local->version, sync->pkg->version); @@ -780,8 +790,13 @@ int pacman_sync(pacdb_t *db, PMList *targets) if(sync->pkg == NULL) { found = 0; } - /* this package was explicitly requested */ - sync->pkg->reason = REASON_EXPLICIT; + if(pmo_d_resolve) { + /* looks like we're being called from 'makepkg -s' so these are all deps */ + sync->pkg->reason = REASON_DEPEND; + } else { + /* this package was explicitly requested */ + sync->pkg->reason = REASON_EXPLICIT; + } } } } @@ -1132,7 +1147,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) PMList *processed = NULL; PMList *files = NULL; - snprintf(ldir, PATH_MAX, "%svar/cache/pacman/pkg", pmo_root); + snprintf(ldir, PATH_MAX, "%s%s", pmo_root, CACHEDIR); /* group sync records by repository and download */ while(!done) { @@ -1153,17 +1168,17 @@ int pacman_sync(pacdb_t *db, PMList *targets) char path[PATH_MAX]; if(pmo_s_printuris) { - snprintf(path, PATH_MAX, "%s-%s.pkg.tar.gz", sync->pkg->name, sync->pkg->version); + snprintf(path, PATH_MAX, "%s-%s%s", sync->pkg->name, sync->pkg->version, PKGEXT); files = list_add(files, strdup(path)); } else { - snprintf(path, PATH_MAX, "%s/%s-%s.pkg.tar.gz", - ldir, sync->pkg->name, sync->pkg->version); + snprintf(path, PATH_MAX, "%s/%s-%s%s", + ldir, sync->pkg->name, sync->pkg->version, PKGEXT); if(stat(path, &buf)) { /* file is not in the cache dir, so add it to the list */ - snprintf(path, PATH_MAX, "%s-%s.pkg.tar.gz", sync->pkg->name, sync->pkg->version); + snprintf(path, PATH_MAX, "%s-%s%s", sync->pkg->name, sync->pkg->version, PKGEXT); files = list_add(files, strdup(path)); } else { - vprint(" %s-%s.pkg.tar.gz is already in the cache\n", sync->pkg->name, sync->pkg->version); + vprint(" %s-%s%s is already in the cache\n", sync->pkg->name, sync->pkg->version, PKGEXT); count++; } } @@ -1235,7 +1250,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) char *md5sum1, *md5sum2; sync = (syncpkg_t*)i->data; - snprintf(pkgname, PATH_MAX, "%s-%s.pkg.tar.gz", sync->pkg->name, sync->pkg->version); + snprintf(pkgname, PATH_MAX, "%s-%s%s", sync->pkg->name, sync->pkg->version, PKGEXT); md5sum1 = sync->pkg->md5sum; if(md5sum1 == NULL || md5sum1[0] == '\0') { @@ -1327,7 +1342,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) syncpkg_t *sync = (syncpkg_t*)i->data; if(sync->pkg) { MALLOC(str, PATH_MAX); - snprintf(str, PATH_MAX, "%s/%s-%s.pkg.tar.gz", ldir, sync->pkg->name, sync->pkg->version); + snprintf(str, PATH_MAX, "%s/%s-%s%s", ldir, sync->pkg->name, sync->pkg->version, PKGEXT); files = list_add(files, str); if(sync->pkg->reason == REASON_DEPEND) { dependonly = list_add(dependonly, strdup(str)); @@ -1978,7 +1993,7 @@ int pacman_add(pacdb_t *db, PMList *targets, PMList *dependonly) * or installed as a dependency for another package */ info->reason = REASON_EXPLICIT; - if(is_in(file->data, dependonly)) { + if(is_in(file->data, dependonly) || pmo_d_resolve) { info->reason = REASON_DEPEND; } /* make an install date (in UTC) */ @@ -2254,7 +2269,7 @@ int pacman_remove(pacdb_t *db, PMList *targets) /* update dependency packages' REQUIREDBY fields */ for(lp = info->depends; lp; lp = lp->next) { - PMList *last, *j; + PMList *j; if(splitdep((char*)lp->data, &depend)) { continue; @@ -2280,17 +2295,9 @@ int pacman_remove(pacdb_t *db, PMList *targets) } } /* splice out this entry from requiredby */ - last = list_last(depinfo->requiredby); for(j = depinfo->requiredby; j; j = j->next) { if(!strcmp((char*)j->data, info->name)) { - if(j == depinfo->requiredby) { - depinfo->requiredby = j->next; - } - if(j->prev) j->prev->next = j->next; - if(j->next) j->next->prev = j->prev; - /* free the spliced node */ - j->prev = j->next = NULL; - list_free(j); + depinfo->requiredby = list_remove(depinfo->requiredby, j); break; } } @@ -2693,7 +2700,7 @@ int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *syncpkg, PMList *l targ = list_add(targ, syncpkg->pkg); deps = checkdeps(local, PM_ADD, targ); targ->data = NULL; - list_free(targ); + FREELIST(targ); for(i = deps; i; i = i->next) { int found = 0; depmissing_t *miss = (depmissing_t*)i->data; @@ -2737,7 +2744,7 @@ int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *syncpkg, PMList *l sync->pkg->reason = REASON_DEPEND; sync->dbs = dbs; } - list_free(provides); + FREELIST(provides); } if(!found) { fprintf(stderr, "error: cannot resolve dependencies for \"%s\":\n", miss->target); @@ -2753,6 +2760,8 @@ int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *syncpkg, PMList *l } if(found) { /* this dep is already in the target list */ + FREEPKG(sync->pkg); + FREE(sync); continue; } vprint("resolving %s\n", sync->pkg->name); @@ -2764,15 +2773,41 @@ int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *syncpkg, PMList *l } } if(!found) { - list_add(trail, sync); - if(resolvedeps(local, databases, sync, list, trail)) { + /* check pmo_ignorepkg and pmo_s_ignore to make sure we haven't pulled in + * something we're not supposed to. + */ + int usedep = 1; + found = 0; + for(j = pmo_ignorepkg; j && !found; j = j->next) { + if(!strcmp(j->data, sync->pkg->name)) { + found = 1; + } + } + for(j = pmo_s_ignore; j && !found; j = j->next) { + if(!strcmp(j->data, sync->pkg->name)) { + found = 1; + } + } + if(found) { + usedep = yesno("%s requires %s, but it is in IgnorePkg. Install anyway? [Y/n] ", + miss->target, sync->pkg->name); + } + if(usedep) { + trail = list_add(trail, sync); + if(resolvedeps(local, databases, sync, list, trail)) { + return(1); + } + vprint("adding %s-%s\n", sync->pkg->name, sync->pkg->version); + list = list_add(list, sync); + } else { + fprintf(stderr, "error: cannot resolve dependencies for \"%s\"\n", miss->target); return(1); } - vprint("adding %s-%s\n", sync->pkg->name, sync->pkg->version); - list_add(list, sync); } else { /* cycle detected -- skip it */ vprint("dependency cycle detected: %s\n", sync->pkg->name); + FREEPKG(sync->pkg); + FREE(sync); } } } @@ -2820,6 +2855,7 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets) } if(is_pkgin(p, targets)) { /* this package is also in the upgrade list, so don't worry about it */ + FREEPKG(p); continue; } for(k = p->depends; k && !found; k = k->next) { @@ -2836,9 +2872,11 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets) PMList *provides = whatprovides(db, depend.name); if(provides == NULL) { /* not found */ + FREEPKG(p); continue; } /* we found an installed package that provides depend.name */ + FREELIST(provides); } found = 0; if(depend.mod == DEP_ANY) { @@ -2870,8 +2908,9 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets) baddeps = list_add(baddeps, miss); } } + FREEPKG(p); } - freepkg(oldpkg); + FREEPKG(oldpkg); } } if(op == PM_ADD || op == PM_UPGRADE) { @@ -2984,6 +3023,7 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets) } } } + FREEPKG(info); } /* PROVIDES -- check to see if another package already provides what @@ -3084,7 +3124,7 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets) /* wtf */ fprintf(stderr, "data error: %s supposedly provides %s, but it was not found in db\n", (char*)k->data, depend.name); - list_free(k); + FREELIST(k); continue; } if(depend.mod == DEP_ANY) { @@ -3108,8 +3148,9 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets) } FREE(ver); } + FREEPKG(p); + FREELIST(k); } - list_free(k); } /* else if still not found... */ if(!found) { @@ -3255,6 +3296,9 @@ int runscriptlet(char *installfn, char *script, char *ver, char *oldver) if(!grep(scriptfn, script)) { /* script not found in scriptlet file */ + if(strlen(tmpdir) && rmrf(tmpdir)) { + fprintf(stderr, "warning: could not remove tmpdir %s\n", tmpdir); + } return(0); } @@ -3289,39 +3333,40 @@ int parseargs(int op, int argc, char **argv) static struct option opts[] = { {"add", no_argument, 0, 'A'}, - {"remove", no_argument, 0, 'R'}, - {"upgrade", no_argument, 0, 'U'}, + {"resolve", no_argument, 0, 'D'}, /* used by 'makepkg -s' */ {"freshen", no_argument, 0, 'F'}, {"query", no_argument, 0, 'Q'}, + {"remove", no_argument, 0, 'R'}, {"sync", no_argument, 0, 'S'}, - {"deptest", no_argument, 0, 'T'}, - {"vertest", no_argument, 0, 'Y'}, - {"resolve", no_argument, 0, 'D'}, - {"root", required_argument, 0, 'r'}, - {"dbpath", required_argument, 0, 'b'}, - {"verbose", no_argument, 0, 'v'}, + {"deptest", no_argument, 0, 'T'}, /* used by makepkg */ + {"upgrade", no_argument, 0, 'U'}, {"version", no_argument, 0, 'V'}, - {"help", no_argument, 0, 'h'}, - {"search", no_argument, 0, 's'}, + {"vertest", no_argument, 0, 'Y'}, /* does the same as the 'vercmp' binary */ + {"dbpath", required_argument, 0, 'b'}, {"clean", no_argument, 0, 'c'}, - {"force", no_argument, 0, 'f'}, + {"cascade", no_argument, 0, 'c'}, {"nodeps", no_argument, 0, 'd'}, {"orphans", no_argument, 0, 'e'}, + {"force", no_argument, 0, 'f'}, + {"groups", no_argument, 0, 'g'}, + {"help", no_argument, 0, 'h'}, + {"info", no_argument, 0, 'i'}, + {"dbonly", no_argument, 0, 'k'}, + {"list", no_argument, 0, 'l'}, {"nosave", no_argument, 0, 'n'}, {"owns", no_argument, 0, 'o'}, - {"list", no_argument, 0, 'l'}, {"file", no_argument, 0, 'p'}, - {"info", no_argument, 0, 'i'}, + {"print-uris", no_argument, 0, 'p'}, + {"root", required_argument, 0, 'r'}, + {"search", no_argument, 0, 's'}, + {"recursive", no_argument, 0, 's'}, {"sysupgrade", no_argument, 0, 'u'}, + {"verbose", no_argument, 0, 'v'}, {"downloadonly", no_argument, 0, 'w'}, - {"print-uris", no_argument, 0, 'p'}, {"refresh", no_argument, 0, 'y'}, - {"dbonly", no_argument, 0, 'k'}, - {"cascade", no_argument, 0, 'c'}, - {"recursive", no_argument, 0, 's'}, - {"groups", no_argument, 0, 'g'}, {"noconfirm", no_argument, 0, 1000}, {"config", required_argument, 0, 1001}, + {"ignore", required_argument, 0, 1002}, {0, 0, 0, 0} }; @@ -3333,6 +3378,7 @@ int parseargs(int op, int argc, char **argv) case 0: break; case 1000: pmo_noconfirm = 1; break; case 1001: strcpy(pmo_configfile, optarg); break; + case 1002: pmo_s_ignore = list_add(pmo_s_ignore, strdup(optarg)); break; case 'A': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_ADD); break; case 'R': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_REMOVE); break; case 'U': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_UPGRADE); break; @@ -3469,6 +3515,8 @@ int parseconfig(char *configfile) } else if(!strcmp(key, "USESYSLOG")) { pmo_usesyslog = 1; vprint("config: usesyslog\n"); + } else if(!strcmp(key, "ILOVECANDY")) { + pmo_chomp = 1; } else { fprintf(stderr, "config: line %d: syntax error\n", linenum); return(1); @@ -3691,6 +3739,7 @@ void usage(int op, char *myname) printf(" -u, --sysupgrade upgrade all packages that are out of date\n"); printf(" -w, --downloadonly download packages but do not install/upgrade anything\n"); printf(" -y, --refresh download fresh package databases from the server\n"); + printf(" --ignore ignore a package upgrade (can be used more than once)\n"); } printf(" --config set an alternate configuration file\n"); printf(" --noconfirm do not ask for any confirmation\n"); @@ -3712,20 +3761,6 @@ void version(void) printf(" the terms of the GNU General Public License\n\n"); } -/* Check verbosity option and, if set, print the - * string to stdout - */ -void vprint(char *fmt, ...) -{ - va_list args; - if(pmo_verbose) { - va_start(args, fmt); - vprintf(fmt, args); - va_end(args); - fflush(stdout); - } -} - /* Output a message to stderr, and (optionally) syslog and/or a logfile */ void logaction(FILE *fp, char *fmt, ...) { diff --git a/src/pacman.h b/src/pacman.h index d0b5a5a1..e1a01e14 100644 --- a/src/pacman.h +++ b/src/pacman.h @@ -21,22 +21,6 @@ #ifndef _PAC_PACMAN_H #define _PAC_PACMAN_H -#ifndef PACVER -#define PACVER "2.9.2" -#endif - -#ifndef PKGDIR -#define PKGDIR "var/lib/pacman" -#endif - -#ifndef PACCONF -#define PACCONF "/etc/pacman.conf" -#endif - -#ifndef CACHEDIR -#define CACHEDIR "var/cache/pacman/pkg" -#endif - /* Operations */ #define PM_MAIN 1 #define PM_ADD 2 @@ -69,7 +53,6 @@ int parseconfig(char *configfile); void usage(int op, char *myname); void version(void); -void vprint(char *fmt, ...); void logaction(FILE *fp, char *fmt, ...); char* buildstring(PMList *strlist); int yesno(char* fmt, ...); diff --git a/src/pacsync.c b/src/pacsync.c index bb1ad2ac..2b6e5b05 100644 --- a/src/pacsync.c +++ b/src/pacsync.c @@ -28,12 +28,12 @@ #include #include /* pacman */ +#include "pacconf.h" #include "list.h" #include "package.h" #include "db.h" #include "util.h" #include "pacsync.h" -#include "pacman.h" /* progress bar */ static int log_progress(netbuf *ctl, int xfered, void *arg); @@ -52,6 +52,7 @@ extern char *pmo_xfercommand; extern unsigned short pmo_proxyport; extern unsigned short pmo_nopassiveftp; +extern unsigned short pmo_chomp; /* sync servers */ extern PMList *pmc_syncs; @@ -205,7 +206,7 @@ int downloadfiles_forreal(PMList *servers, const char *localpath, char *host; unsigned port; host = (pmo_proxyhost) ? pmo_proxyhost : server->server; - port = (pmo_proxyhost) ? pmo_proxyport : 80; + port = (pmo_proxyport) ? pmo_proxyport : 80; if(strchr(host, ':')) { vprint("connecting to %s\n", host); } else { @@ -306,7 +307,7 @@ int downloadfiles_forreal(PMList *servers, const char *localpath, if(ptr && (ptr-fn) < 24) { sync_fnm[ptr-fn] = '\0'; } - ptr = strstr(fn, ".pkg.tar.gz"); + ptr = strstr(fn, PKGEXT); if(ptr && (ptr-fn) < 24) { sync_fnm[ptr-fn] = '\0'; } @@ -469,6 +470,11 @@ static int log_progress(netbuf *ctl, int xfered, void *arg) int i, cur; struct timeval t1; float timediff; + /* a little hard to conceal easter eggs in open-source software, but + * they're still fun. ;) + */ + static unsigned short mouth; + static unsigned int lastcur = 0; gettimeofday(&t1, NULL); if(xfered+offset == fsz) { @@ -501,13 +507,39 @@ static int log_progress(netbuf *ctl, int xfered, void *arg) printf(" %s [", sync_fnm); cur = (int)((maxcols-64)*pct/100); for(i = 0; i < maxcols-64; i++) { - (i < cur) ? printf("#") : printf(" "); + if(pmo_chomp) { + if(i < cur) { + printf("-"); + } else { + if(i == cur) { + if(lastcur == cur) { + if(mouth) { + printf("\033[1;33mC\033[m"); + } else { + printf("\033[1;33mc\033[m"); + } + } else { + mouth = mouth == 1 ? 0 : 1; + if(mouth) { + printf("\033[1;33mC\033[m"); + } else { + printf("\033[1;33mc\033[m"); + } + } + } else { + printf("\033[0;37m*\033[m"); + } + } + } else { + (i < cur) ? printf("#") : printf(" "); + } } if(rate > 1000) { printf("] %3d%% %6dK %6.0fK/s %02d:%02d:%02d\r", pct, ((xfered+offset) / 1024), rate, eta_h, eta_m, eta_s); } else { printf("] %3d%% %6dK %6.1fK/s %02d:%02d:%02d\r", pct, ((xfered+offset) / 1024), rate, eta_h, eta_m, eta_s); } + lastcur = cur; fflush(stdout); return(1); } diff --git a/src/strhash.c b/src/strhash.c new file mode 100644 index 00000000..1ee5498c --- /dev/null +++ b/src/strhash.c @@ -0,0 +1,195 @@ +/* evtgen string hash functions. + Copyright (C) 2003 Julien Olivain and LSV, CNRS UMR 8643 & ENS Cachan. + + This file is part of evtgen. + + evtgen 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, or (at your option) + any later version. + + evtgen 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 evtgen; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* Copyright (C) 2004 Tommi Rantala + * + * Modified for usage in Pacman. + */ + +/* +** strhash.c -- string hash utility functions +*/ + +#include +#include +#include + +#include "util.h" +#include "list.h" +#include "strhash.h" + +void +strhash_add_list(strhash_t *hash, PMList* list) +{ + for(; list; list = list->next) + strhash_add(hash, list->data, NULL); +} + +strhash_t * +new_strhash(size_t hsize) +{ + strhash_t *h; + + MALLOC(h, sizeof (strhash_t)); + h->size = hsize; + h->elmts = 0; + h->hash = DEFAULT_STRHASH_FUNCTION; + MALLOC(h->htable, hsize * sizeof (strhash_elmt_t *)); + memset(h->htable, 0, hsize * sizeof(strhash_elmt_t *)); + + return (h); +} + +void +clear_strhash(strhash_t *hash) +{ + int i; + strhash_elmt_t *tmp; + strhash_elmt_t *tmp_next; + + for (i = 0; i < hash->size; i++) + { + tmp = hash->htable[i]; + while (tmp) + { + tmp_next = tmp->next; + free(tmp); + tmp = tmp_next; + } + } + hash->elmts = 0; + memset(hash->htable, 0, hash->size * sizeof (void *)); +} + + +void +free_strhash(strhash_t *hash) +{ + int i; + strhash_elmt_t *tmp; + strhash_elmt_t *tmp_next; + + for (i = 0; i < hash->size; i++) + { + tmp = hash->htable[i]; + while (tmp) + { + tmp_next = tmp->next; + free(tmp); + tmp = tmp_next; + } + } + + free(hash->htable); + free(hash); +} + +void +strhash_add(strhash_t *hash, char *key, char *data) +{ + strhash_elmt_t *elmt; + unsigned long hcode; + + MALLOC(elmt, sizeof (strhash_elmt_t)); + elmt->key = key; + elmt->data = data; + + hcode = hash->hash(key) % hash->size; + elmt->next = hash->htable[hcode]; + hash->htable[hcode] = elmt; + hash->elmts++; +} + +/* 1: Yes, the key exists in the hash table. + * 0: No, its not here. + */ + +int +strhash_isin(strhash_t *hash, char* key) +{ + strhash_elmt_t *elmt; + + elmt = hash->htable[hash->hash(key) % hash->size]; + for (; elmt; elmt = elmt->next) + { + if (!strcmp(key, elmt->key)) + return 1; + } + + return 0; +} + +char* +strhash_get(strhash_t *hash, char* key) +{ + strhash_elmt_t *elmt; + + elmt = hash->htable[hash->hash(key) % hash->size]; + for (; elmt; elmt = elmt->next) + { + if (!strcmp(key, elmt->key)) + return elmt->data; + } + + return NULL; +} + +/* +** fast hash function samples +*/ + +unsigned long +strhash_pjw(char *key) +{ + unsigned long h; + unsigned long g; + + h = 0; + while (*key) + { + h = (h << 4) + *key++; + if ((g = h & 0xF0000000U) != 0) + { + h = h ^ (g >> 24); + h = h ^ g; + } + } + + return (h); +} + +int +strhash_collide_count(strhash_t *hash) +{ + int count; + int i; + + count = 0; + for (i = 0; i < hash->size; i++) + { + strhash_elmt_t *tmp; + + for (tmp = hash->htable[i]; tmp; tmp = tmp->next) + if (tmp->next) + count++; + } + + return (count); +} diff --git a/src/strhash.h b/src/strhash.h new file mode 100644 index 00000000..65b7f4e1 --- /dev/null +++ b/src/strhash.h @@ -0,0 +1,65 @@ +/* evtgen string hash headers. + Copyright (C) 2003 Julien Olivain and LSV, CNRS UMR 8643 & ENS Cachan. + + This file is part of evtgen. + + evtgen 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, or (at your option) + any later version. + + evtgen 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 evtgen; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* Copyright (C) 2004 Tommi Rantala + * + * Modified for usage in Pacman. + */ + +/* +** strhash.h -- +*/ + +#ifndef STRHASH_H +#define STRHASH_H + +#define DEFAULT_STRHASH_FUNCTION strhash_pjw + +typedef struct strhash_elmt_s strhash_elmt_t; +struct strhash_elmt_s +{ + char *key; + char *data; + strhash_elmt_t *next; +}; + +typedef unsigned long (*strhashfunc_t)(char *key); + +typedef struct strhash_s strhash_t; +struct strhash_s +{ + strhash_elmt_t **htable; + size_t size; + int elmts; + strhashfunc_t hash; +}; + +void strhash_add_list(strhash_t *hash, PMList* list); +strhash_t *new_strhash(size_t hsize); +void free_strhash(strhash_t *hash); +void clear_strhash(strhash_t *hash); +void strhash_add(strhash_t *hash, char *key, char *data); +int strhash_isin(strhash_t *hash, char* key); +char* strhash_get(strhash_t *hash, char* key); +int strhash_collide_count(strhash_t *hash); + +unsigned long strhash_pjw(char *key); + +#endif /* STRHASH_H */ diff --git a/src/util.c b/src/util.c index 6d3ed0fa..0c922096 100644 --- a/src/util.c +++ b/src/util.c @@ -32,6 +32,22 @@ #include #include "util.h" +extern unsigned short pmo_verbose; + +/* Check verbosity option and, if set, print the + * string to stdout + */ +void vprint(char *fmt, ...) +{ + va_list args; + if(pmo_verbose) { + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + fflush(stdout); + } +} + /* borrowed and modified from Per Liden's pkgutils (http://crux.nu) */ long gzopen_frontend(char *pathname, int oflags, int mode) { diff --git a/src/util.h b/src/util.h index 71292bc2..c2b9f250 100644 --- a/src/util.h +++ b/src/util.h @@ -28,6 +28,7 @@ #define FREE(p) { if (p) { free(p); (p)= NULL; }} +void vprint(char *fmt, ...); long gzopen_frontend(char *pathname, int oflags, int mode); int unpack(char *archive, const char *prefix, const char *fn); int copyfile(char *src, char *dest); -- cgit v1.2.3-24-g4f1b