summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJudd Vinet <judd@archlinux.org>2004-12-19 04:37:00 +0100
committerJudd Vinet <judd@archlinux.org>2004-12-19 04:37:00 +0100
commitf6b8ed22f40d422e2876be92b215187b5ff7b6e7 (patch)
treeca771d1517967f5e97d4adf238f3825f7ececcad /src
parent4795965caf371a55285678e5860ae66e926ebd95 (diff)
downloadpacman-f6b8ed22f40d422e2876be92b215187b5ff7b6e7.tar.gz
pacman-f6b8ed22f40d422e2876be92b215187b5ff7b6e7.tar.xz
Imported from pacman-2.9.3.tar.gz
Diffstat (limited to 'src')
-rw-r--r--src/convertdb.c7
-rw-r--r--src/db.c127
-rw-r--r--src/list.c104
-rw-r--r--src/list.h2
-rw-r--r--src/pacconf.h46
-rw-r--r--src/package.c3
-rw-r--r--src/pacman.c235
-rw-r--r--src/pacman.h17
-rw-r--r--src/pacsync.c40
-rw-r--r--src/strhash.c195
-rw-r--r--src/strhash.h65
-rw-r--r--src/util.c16
-rw-r--r--src/util.h1
13 files changed, 708 insertions, 150 deletions
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 <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+#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 <libgen.h>
#include <unistd.h>
#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 <stdlib.h>
#include <string.h>
#include <stdio.h>
+#include <assert.h>
#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 <jvinet@zeroflux.org>
+ *
+ * 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 <string.h>
#include <libtar.h>
#include <zlib.h>
+#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 <libtar.h>
#include <dirent.h>
/* 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 <pkg> ignore a package upgrade (can be used more than once)\n");
}
printf(" --config <path> 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 <sys/time.h>
#include <ftplib.h>
/* 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 <tommi.rantala@cs.helsinki.fi>
+ *
+ * Modified for usage in Pacman.
+ */
+
+/*
+** strhash.c -- string hash utility functions
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#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 <tommi.rantala@cs.helsinki.fi>
+ *
+ * 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 <libtar.h>
#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);