summaryrefslogtreecommitdiffstats
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
parent4795965caf371a55285678e5860ae66e926ebd95 (diff)
downloadpacman-f6b8ed22f40d422e2876be92b215187b5ff7b6e7.tar.gz
pacman-f6b8ed22f40d422e2876be92b215187b5ff7b6e7.tar.xz
Imported from pacman-2.9.3.tar.gz
-rw-r--r--ChangeLog8
-rw-r--r--Makefile.in6
-rw-r--r--doc/pacman.8.in8
-rwxr-xr-xscripts/gensync2
-rwxr-xr-xscripts/makepkg11
-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
18 files changed, 734 insertions, 159 deletions
diff --git a/ChangeLog b/ChangeLog
index bbf9158a..4a03d651 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
VERSION DESCRIPTION
-----------------------------------------------------------------------------
+2.9.3 - fixed a couple manpage typos
+ - added --ignore to -S operations, works just like IgnorePkg
+ - respect IgnorePkg list when pulling in dependencies
+ - numerous memleak fixes
+ - some code changes to improve customizability/branding
+ - Makefile fix for nonstandard lib search paths (Kevin Piche)
+ - fixed the leftover directories in /tmp
+ - speed improvement patches from Tommi Rantala
2.9.2 - bugfix for 2.9.1
2.9.1 - --refresh now only downloads fresh packages lists if they've
been updated (currently only works with FTP)
diff --git a/Makefile.in b/Makefile.in
index d79c1fb7..c7997318 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -34,7 +34,7 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
-PACVER = 2.9.2
+PACVER = 2.9.3
TOPDIR = @srcdir@
SRCDIR = $(TOPDIR)/src/
@@ -55,6 +55,7 @@ SRCS = $(SRCDIR)pacman.c \
$(SRCDIR)pacsync.c \
$(SRCDIR)md5.c \
$(SRCDIR)md5driver.c \
+ $(SRCDIR)strhash.c \
$(SRCDIR)vercmp.c \
$(SRCDIR)rpmvercmp.c
@@ -66,6 +67,7 @@ OBJECTS = $(OBJDIR)pacman.o \
$(OBJDIR)pacsync.o \
$(OBJDIR)md5.o \
$(OBJDIR)md5driver.o \
+ $(OBJDIR)strhash.o \
$(OBJDIR)rpmvercmp.o
all: libftp.a pacman vercmp convertdb man
@@ -78,7 +80,7 @@ vercmp: $(OBJDIR)vercmp.o $(OBJDIR)rpmvercmp.o
$(CXX) $(OBJDIR)vercmp.o $(OBJDIR)rpmvercmp.o $(CXXFLAGS) -o $@
convertdb: $(OBJDIR)convertdb.o $(OBJDIR)list.o $(OBJDIR)util.o
- $(CXX) $(OBJDIR)convertdb.o $(OBJDIR)list.o $(OBJDIR)util.o $(CXXFLAGS) -lz -ltar -o $@
+ $(CXX) $(OBJDIR)convertdb.o $(OBJDIR)list.o $(OBJDIR)util.o $(LDFLAGS) -o $@
.c.o: $(SRCS)
$(CXX) $(CXXFLAGS) -o $@ -c $<
diff --git a/doc/pacman.8.in b/doc/pacman.8.in
index 52099522..9490b554 100644
--- a/doc/pacman.8.in
+++ b/doc/pacman.8.in
@@ -60,7 +60,7 @@ installed and there are no package conflicts in the system. This
switch disables these checks.
.TP
.B "\-f, \-\-force"
-Bypass file conflict checks,, overwriting conflicting files. If the
+Bypass file conflict checks, overwriting conflicting files. If the
package that is about to be installed contains files that are already
installed, this option will cause all those files to be overwritten.
This option should be used with care, ideally not at all.
@@ -147,9 +147,9 @@ removed.
.TP
.B "\-s, \-\-recursive"
For each target specified, remove it and all its dependencies, provided
-that (A) they are not required by other packages; and (B) they were
-explicitly installed by the user and not pulled in as a dependency for
-other packages. This option is analagous to a backwards --sync operation.
+that (A) they are not required by other packages; and (B) they were not
+explicitly installed by the user.
+This option is analagous to a backwards --sync operation.
.SH QUERY OPTIONS
.TP
.B "\-e, \-\-orphans"
diff --git a/scripts/gensync b/scripts/gensync
index ed6a0680..49a2939a 100755
--- a/scripts/gensync
+++ b/scripts/gensync
@@ -134,6 +134,8 @@ db_write_entry()
done
echo "" >>depends
fi
+ # preserve the modification time
+ touch -r $1 desc depends
}
if [ $# -lt 2 ]; then
diff --git a/scripts/makepkg b/scripts/makepkg
index efc750d2..a4c4d23a 100755
--- a/scripts/makepkg
+++ b/scripts/makepkg
@@ -463,6 +463,7 @@ if [ "$GENMD5" = "0" ]; then
# extract sources
msg "Extracting Sources..."
for netfile in ${source[@]}; do
+ unziphack=0
file=`strip_url $netfile`
unset cmd
case $file in
@@ -473,6 +474,7 @@ if [ "$GENMD5" = "0" ]; then
*.tar)
cmd="tar -xf $file" ;;
*.zip)
+ unziphack=1
cmd="unzip -qqo $file" ;;
*.gz)
cmd="gunzip $file" ;;
@@ -483,9 +485,12 @@ if [ "$GENMD5" = "0" ]; then
msg " $cmd"
$cmd
if [ $? -ne 0 ]; then
- error "Failed to extract $file"
- msg "Aborting..."
- exit 1
+ # unzip will return a 1 as a warning, it is not an error
+ if [ "$unziphack" != "1" -o $? -ne 1 ]; then
+ error "Failed to extract $file"
+ msg "Aborting..."
+ exit 1
+ fi
fi
fi
done
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);