summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJudd Vinet <judd@archlinux.org>2005-06-10 23:31:25 +0200
committerJudd Vinet <judd@archlinux.org>2005-06-10 23:31:25 +0200
commitd05f0047a02a2b3b3f1a07c0feb980837a3496a3 (patch)
tree5b2414521eecf5065caf41c7c5208317f1602158
parentd48cc3bf5d0bc9aef5e816c81d3a0f6b8e2680c7 (diff)
downloadpacman-d05f0047a02a2b3b3f1a07c0feb980837a3496a3.tar.gz
pacman-d05f0047a02a2b3b3f1a07c0feb980837a3496a3.tar.xz
Imported from pacman-2.9.6.tar.gz
-rw-r--r--ChangeLog11
-rw-r--r--Makefile.in3
-rw-r--r--doc/pacman.8.in2
-rw-r--r--etc/makepkg.conf6
-rwxr-xr-xscripts/gensync4
-rwxr-xr-xscripts/makepkg9
-rwxr-xr-xscripts/makeworld8
-rwxr-xr-xscripts/pacman-optimize114
-rwxr-xr-xscripts/updatesync4
-rw-r--r--src/db.c125
-rw-r--r--src/db.h7
-rw-r--r--src/list.c17
-rw-r--r--src/pacconf.h2
-rw-r--r--src/pacman.c158
-rw-r--r--src/pacman.h2
-rw-r--r--src/pacsync.c7
-rw-r--r--src/strhash.c273
-rw-r--r--src/strhash.h1
18 files changed, 494 insertions, 259 deletions
diff --git a/ChangeLog b/ChangeLog
index c6b9e42d..6f92d4ed 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
VERSION DESCRIPTION
-----------------------------------------------------------------------------
+2.9.6 - added a pacman-optimize script to try and defragment the DB
+ - modified NoUpgrade behaviour to avoid extracting files
+ that are missing from the filesystem -- this helps in
+ situations where the admin does not want the file there, eg,
+ remove index.html so index.php takes precedence
+ - fixed a bug where files would sometimes go missing if they
+ moved from one package to another
+ - add db_remove() which is responsible for clearing out stale
+ hash table entries when packages are removed
+ - added cache support to makepkg
+ - patch from Aurelien Foret fixes a few memory leaks
2.9.5 - bugfix: missing files after re-ordering packages wrt
deps with --upgrade
- added "Repository" line to -Si output
diff --git a/Makefile.in b/Makefile.in
index cd6b18bb..34c463f7 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.5
+PACVER = 2.9.6
TOPDIR = @srcdir@
SRCDIR = $(TOPDIR)/src/
@@ -106,6 +106,7 @@ install: pacman vercmp convertdb man
$(INSTALL) -D -m0755 $(SCRDIR)makeworld $(DESTDIR)$(BINDIR)/makeworld
$(INSTALL) -D -m0755 $(SCRDIR)gensync $(DESTDIR)$(BINDIR)/gensync
$(INSTALL) -D -m0755 $(SCRDIR)updatesync $(DESTDIR)$(BINDIR)/updatesync
+ $(INSTALL) -D -m0755 $(SCRDIR)pacman-optimize $(DESTDIR)$(BINDIR)/pacman-optimize
$(INSTALL) -D -m0644 $(MANSRC)pacman.8 $(DESTDIR)$(MANDIR)/man8/pacman.8
$(INSTALL) -D -m0644 $(MANSRC)makepkg.8 $(DESTDIR)$(MANDIR)/man8/makepkg.8
$(INSTALL) -D -m0644 etc/pacman.conf $(DESTDIR)/etc/pacman.conf
diff --git a/doc/pacman.8.in b/doc/pacman.8.in
index 27787c15..09c47d50 100644
--- a/doc/pacman.8.in
+++ b/doc/pacman.8.in
@@ -81,7 +81,7 @@ Output more status and error messages.
Specify an alternate configuration file.
.TP
.B "\-\-noconfirm"
-Bypass any and all "Are you sure?" messages. It's not a good to do this
+Bypass any and all "Are you sure?" messages. It's not a good idea to do this
unless you want to run pacman from a script.
.SH SYNC OPTIONS
.TP
diff --git a/etc/makepkg.conf b/etc/makepkg.conf
index 0d0809a0..d43b0e67 100644
--- a/etc/makepkg.conf
+++ b/etc/makepkg.conf
@@ -12,8 +12,8 @@ export CHOST="i686-pc-linux-gnu"
# Pentium Pro/Pentium II/Pentium III+/Pentium 4/Athlon exclusive (binaries
# will use the P6 instruction set and only run on P6+ systems)
-export CFLAGS="-march=i686 -O2 -pipe"
-export CXXFLAGS="-march=i686 -O2 -pipe"
+export CFLAGS="-march=i686 -O2 -pipe -Wl,-O1"
+export CXXFLAGS="-march=i686 -O2 -pipe -Wl,-O1"
# Pentium Pro/Pentium II/Pentium III+/Pentium 4/Athlon optimized (but binaries
# will run on any x86 system)
#export CFLAGS="-mcpu=i686 -O2 -pipe"
@@ -26,7 +26,7 @@ export CXXFLAGS="-march=i686 -O2 -pipe"
export USE_FAKEROOT="y"
# Enable colorized output messages
-export USE_COLOR="n"
+export USE_COLOR="y"
# Specify a fixed directory where all packages will be placed
#export PKGDEST=/home/packages
diff --git a/scripts/gensync b/scripts/gensync
index 49a2939a..0ebc1386 100755
--- a/scripts/gensync
+++ b/scripts/gensync
@@ -2,7 +2,7 @@
#
# gensync
#
-# Copyright (c) 2002-2004 by Judd Vinet <jvinet@zeroflux.org>
+# Copyright (c) 2002-2005 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
@@ -20,7 +20,7 @@
# USA.
#
-myver='2.9.2'
+myver='2.9.6'
usage() {
echo "gensync $myver"
diff --git a/scripts/makepkg b/scripts/makepkg
index a4c4d23a..31e78f97 100755
--- a/scripts/makepkg
+++ b/scripts/makepkg
@@ -2,7 +2,7 @@
#
# makepkg
#
-# Copyright (c) 2002-2004 by Judd Vinet <jvinet@zeroflux.org>
+# Copyright (c) 2002-2005 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
@@ -20,7 +20,7 @@
# USA.
#
-myver='2.9.2'
+myver='2.9.6'
startdir=`pwd`
PKGDEST=$startdir
USE_COLOR="n"
@@ -357,7 +357,7 @@ if [ "`id -u`" != "0" ]; then
fi
fi
-msg "Making package: $pkgname (`date`)"
+msg "Making package: $pkgname $pkgver-$pkgrel (`date`)"
unset deplist makedeplist
if [ `type -p pacman` -a "$NODEPS" = "0" ]; then
@@ -552,6 +552,9 @@ if [ "$NOBUILD" = "1" ]; then
exit 0
fi
+# use ccache if it's available
+[ -d /usr/lib/ccache/bin ] && export PATH=/usr/lib/ccache/bin:$PATH
+
# build
msg "Starting build()..."
build 2>&1
diff --git a/scripts/makeworld b/scripts/makeworld
index c42013c7..30418afd 100755
--- a/scripts/makeworld
+++ b/scripts/makeworld
@@ -2,7 +2,7 @@
#
# makeworld
#
-# Copyright (c) 2002-2004 by Judd Vinet <jvinet@zeroflux.org>
+# Copyright (c) 2002-2005 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
@@ -20,8 +20,8 @@
# USA.
#
+version="2.9.6"
toplevel=`pwd`
-version="2.9.2"
usage() {
echo "makeworld version $version"
@@ -106,12 +106,12 @@ fi
# convert a (possibly) relative path to absolute
cd $dest
dest=`pwd`
-cd -
+cd - &>/dev/null
sd=`date +"[%b %d %H:%M]"`
for category in $*; do
- for port in `find $toplevel/$category -type d -maxdepth 1 -mindepth 1 | sort`; do
+ for port in `find $toplevel/$category -maxdepth 1 -mindepth 1 -type d | sort`; do
cd $port
if [ -f PKGBUILD ]; then
. PKGBUILD
diff --git a/scripts/pacman-optimize b/scripts/pacman-optimize
new file mode 100755
index 00000000..b9573cbb
--- /dev/null
+++ b/scripts/pacman-optimize
@@ -0,0 +1,114 @@
+#!/bin/bash
+#
+# pacman-optimize
+#
+# Copyright (c) 2002-2005 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.
+#
+
+myver='2.9.6'
+
+usage() {
+ echo "pacman-optimize $myver"
+ echo "usage: $0 [pacman_db_root]"
+ echo
+ echo "pacman-optimize is a little hack that should improve the performance"
+ echo "of pacman when reading/writing to its filesystem-based database."
+ echo
+ echo "Because pacman uses many small files to keep track of packages,"
+ echo "there is a tendency for these files to become fragmented over time."
+ echo "This script attempts to relocate these small files into one"
+ echo "contiguous location on your hard drive. The result is that the hard"
+ echo "drive should be able to read them faster, since the hard drive head"
+ echo "does not have to move around the disk as much."
+ echo
+}
+
+die() {
+ echo "pacman-optimize: $*" >&2
+ exit 1
+}
+
+die_r() {
+ rm -f /tmp/pacman.lck
+ die $*
+}
+
+
+dbroot="/var/lib/pacman"
+
+if [ "$1" != "" ]; then
+ if [ "$1" = "-h" -o "$1" = "--help" ]; then
+ usage
+ exit 0
+ fi
+ dbroot=$1
+fi
+
+if [ "`id -u`" != 0 ]; then
+ die "You must be root to optimize the database"
+fi
+
+# make sure pacman isn't running
+if [ -f /tmp/pacman.lck ]; then
+ die "Pacman lockfile was found. Cannot run while pacman is running."
+fi
+
+if [ ! -d $dbroot ]; then
+ die "$dbroot does not exist or is not a directory"
+fi
+
+# don't let pacman run while we do this
+touch /tmp/pacman.lck
+
+# step 1: sum the old db
+echo "==> md5sum'ing the old database..."
+tar c $dbroot 2>/dev/null | md5sum >/tmp/pacsums.old
+
+# step 1: copy the entire db directory to a new one
+echo "==> copying $dbroot..."
+cp -a $dbroot $dbroot.new || die_r "error copying $dbroot"
+
+# step 2: switch the directory names and sum the new one
+echo "==> md5sum'ing the new database..."
+mv $dbroot $dbroot.bak || die_r "error renaming $dbroot"
+mv $dbroot.new $dbroot || die_r "error renaming $dbroot.new"
+tar c $dbroot 2>/dev/null | md5sum >/tmp/pacsums.new
+
+# step 3: compare sums
+echo "==> checking integrity..."
+diff /tmp/pacsums.old /tmp/pacsums.new >/dev/null 2>&1
+if [ $? -ne 0 ]; then
+ # failed, move the old one back into place
+ rm -rf $dbroot
+ mv $dbroot.bak $dbroot
+ die_r "integrity check FAILED, reverting to old databse"
+fi
+
+# step 4: remove the backup
+echo "==> removing old database..."
+rm -rf $dbroot.bak || die_r "error removing backup $dbroot.bak"
+
+# remove the lock and sum files
+rm -f /tmp/pacman.lck /tmp/pacsums.old /tmp/pacsums.new
+
+echo
+echo "Finished. Your pacman database has been optimized."
+echo
+
+exit 0
+
diff --git a/scripts/updatesync b/scripts/updatesync
index 943af8a5..e36d25e7 100755
--- a/scripts/updatesync
+++ b/scripts/updatesync
@@ -3,7 +3,7 @@
# updatesync
#
# Copyright (c) 2004 by Jason Chu <jason@archlinux.org>
-# Derived from gensync (c) 2002-2004 Judd Vinet <jvinet@zeroflux.org>
+# Derived from gensync (c) 2002-2005 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
@@ -21,7 +21,7 @@
# USA.
#
-myver='2.9.2'
+myver='2.9.6'
usage() {
echo "updatesync $myver"
diff --git a/src/db.c b/src/db.c
index 8dd12c98..005498c4 100644
--- a/src/db.c
+++ b/src/db.c
@@ -137,21 +137,32 @@ pkginfo_t* db_scan(pacdb_t *db, char *target, unsigned int inforeq)
char *ptr = NULL;
int found = 0;
- /* hash table for caching directory names */
- static strhash_t* htable = NULL;
-
- if (!htable)
- htable = new_strhash(951);
+ /* initialize the hash table */
+ if(!db_htable) {
+ db_htable = new_strhash(951);
+ }
snprintf(path, PATH_MAX, "%s/", db->path);
path_len = strlen(path);
+ /* TODO:
+ *
+ * Currently we're using a hash table to cache the directory
+ * name of each package we db_scan() for. This saves us from
+ * having to scan the db directory for the full
+ * pkgname-pkgver-pkgrel dir name, but we still have to issue
+ * a db_read() call to get the actual package data.
+ *
+ * A more efficient method may be to cache the package data
+ * itself.
+ */
+
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)) {
+ if(strhash_isin(db_htable, path)) {
struct dirent* pkgdir;
pkginfo_t* pkg;
@@ -159,7 +170,7 @@ pkginfo_t* db_scan(pacdb_t *db, char *target, unsigned int inforeq)
* Actually it only uses the d_name field. */
MALLOC(pkgdir, sizeof(struct dirent));
- strcpy(pkgdir->d_name, strhash_get(htable, path));
+ strcpy(pkgdir->d_name, strhash_get(db_htable, path));
pkg = db_read(db, pkgdir, inforeq);
FREE(pkgdir);
@@ -242,8 +253,8 @@ pkginfo_t* db_scan(pacdb_t *db, char *target, unsigned int inforeq)
* data: xrally-1.1.1-1
*/
- if (!strhash_isin(htable, path)) {
- strhash_add(htable, strdup(path), strdup(ent->d_name));
+ if(!strhash_isin(db_htable, path)) {
+ strhash_add(db_htable, strdup(path), strdup(ent->d_name));
}
}
}
@@ -595,6 +606,40 @@ int db_write(pacdb_t *db, pkginfo_t *info, unsigned int inforeq)
return(0);
}
+/*
+ * Remove a package record from the database
+ */
+void db_remove(pacdb_t *db, pkginfo_t *target)
+{
+ char topdir[PATH_MAX];
+ char path[PATH_MAX];
+
+ snprintf(topdir, PATH_MAX, "%s/%s-%s", db->path,
+ target->name, target->version);
+
+ /* DESC */
+ snprintf(path, PATH_MAX, "%s/desc", topdir);
+ unlink(path);
+ /* FILES */
+ snprintf(path, PATH_MAX, "%s/files", topdir);
+ unlink(path);
+ /* DEPENDS */
+ snprintf(path, PATH_MAX, "%s/depends", topdir);
+ unlink(path);
+ /* INSTALL */
+ snprintf(path, PATH_MAX, "%s/install", topdir);
+ unlink(path);
+ /* directory */
+ rmdir(topdir);
+
+ /* remove the entry from the hash table */
+ if(db_htable) {
+ /*clear_strhash(db_htable);*/
+ snprintf(topdir, PATH_MAX, "%s/%s", db->path, target->name);
+ strhash_remove(db_htable, topdir);
+ }
+}
+
void db_search(pacdb_t *db, PMList *cache, const char *treename, PMList *needles)
{
PMList *i, *j;
@@ -655,7 +700,7 @@ void db_search(pacdb_t *db, PMList *cache, const char *treename, PMList *needles
}
-PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root)
+PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root, PMList **skip_list)
{
PMList *i, *j, *k;
char *filestr = NULL;
@@ -663,6 +708,7 @@ 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;
@@ -680,42 +726,12 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root)
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
- * many many strcmp() calls slow it down heavily and most of the
- * checking is redundant to the targets-against-filesystem check.
- * This will be re-enabled if I can improve performance significantly.
- *
- 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) {
- dbstr = (char*)i->data;
-
- 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) && 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 */
+ /* CHECK 1: check every target against every target */
for(d = 0, i = targets; i; i = i->next, d++) {
pkginfo_t *p1 = (pkginfo_t*)i->data;
for(e = d, j = i; j; j = j->next, e++) {
@@ -741,7 +757,7 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root)
}
}
- /* CHECK 3: check every target against the filesystem */
+ /* CHECK 2: check every target against the filesystem */
for(i = targets; i; i = i->next) {
pkginfo_t *p = (pkginfo_t*)i->data;
pkginfo_t *dbpkg = NULL;
@@ -769,6 +785,7 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root)
snprintf(str, PATH_MAX, "%s%s", root, (char*)k->data);
stat(str, &buf2);
if(buf.st_ino == buf2.st_ino && buf.st_dev == buf2.st_dev) {
+ printf("inodes match: %s and %s\n", path, str);
ok = 1;
}
}
@@ -785,7 +802,26 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root)
dbpkg2 = db_scan(db, p1->name, INFRQ_DESC | INFRQ_FILES);
/* If it used to exist in there, but doesn't anymore */
if(dbpkg2 && !is_in(filestr, p1->files) && is_in(filestr, dbpkg2->files)) {
+ /*printf("file %s moved from %s to %s\n", filestr, p1->name, p->name);*/
+
ok = 1;
+ /* Add to the "skip list" of files that we shouldn't remove during an upgrade.
+ *
+ * This is a workaround for the following scenario:
+ *
+ * - the old package A provides file X
+ * - the new package A does not
+ * - the new package B provides file X
+ * - package A depends on B, so B is upgraded first
+ *
+ * Package B is upgraded, so file X is installed. Then package A
+ * is upgraded, and it *removes* file X, since it no longer exists
+ * in package A.
+ *
+ * Our workaround is to scan through all "old" packages and all "new"
+ * ones, looking for files that jump to different packages.
+ */
+ *skip_list = list_add(*skip_list, filestr);
}
FREEPKG(dbpkg2);
}
@@ -801,6 +837,11 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root)
FREEPKG(dbpkg);
}
+ /* free up the hash tables */
+ for(d = 0; d <= target_num; d++) {
+ free_strhash(htables[d]);
+ }
+
return(conflicts);
}
diff --git a/src/db.h b/src/db.h
index 402280f8..f7d2a1a7 100644
--- a/src/db.h
+++ b/src/db.h
@@ -22,6 +22,7 @@
#define _PAC_DB_H
#include <dirent.h>
+#include "strhash.h"
/* info requests for db_read */
#define INFRQ_DESC 0x01
@@ -35,6 +36,9 @@ typedef struct __pacdb_t {
DIR* dir;
} pacdb_t;
+/* hash table for caching db_scan() results */
+static strhash_t* db_htable;
+
pacdb_t* db_open(char *root, char *dbpath, char *treename);
void db_close(pacdb_t *db);
int db_getlastupdate(const char *dbpath, char *ts);
@@ -43,8 +47,9 @@ PMList* db_loadpkgs(pacdb_t *db);
pkginfo_t* db_scan(pacdb_t *db, char *target, unsigned int inforeq);
pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq);
int db_write(pacdb_t *db, pkginfo_t *info, unsigned int inforeq);
+void db_remove(pacdb_t *db, pkginfo_t *target);
void db_search(pacdb_t *db, PMList *cache, const char *treename, PMList *needles);
-PMList* db_find_conflicts(pacdb_t *db, PMList* targets, char *root);
+PMList* db_find_conflicts(pacdb_t *db, PMList* targets, char *root, PMList **skip_list);
PMList *whatprovides(pacdb_t *db, char* package);
PMList *find_groups(pacdb_t *db);
PMList *pkg_ingroup(pacdb_t *db, char *group);
diff --git a/src/list.c b/src/list.c
index 689a17d3..49c07f51 100644
--- a/src/list.c
+++ b/src/list.c
@@ -67,17 +67,14 @@ PMList* list_new()
void list_free(PMList *list)
{
- if(list == NULL) {
- return;
- }
- if(list->data != NULL) {
- free(list->data);
- list->data = NULL;
- }
- if(list->next != NULL) {
- list_free(list->next);
+ PMList *ptr, *it = list;
+
+ while(it) {
+ ptr = it->next;
+ free(it->data);
+ free(it);
+ it = ptr;
}
- free(list);
return;
}
diff --git a/src/pacconf.h b/src/pacconf.h
index ceab2044..2274b9ec 100644
--- a/src/pacconf.h
+++ b/src/pacconf.h
@@ -22,7 +22,7 @@
#define _PAC_PACCONF_H
#ifndef PACVER
-#define PACVER "2.9.5"
+#define PACVER "2.9.6"
#endif
#ifndef PACDBDIR
diff --git a/src/pacman.c b/src/pacman.c
index f12643e5..3daa1fe4 100644
--- a/src/pacman.c
+++ b/src/pacman.c
@@ -240,7 +240,7 @@ int main(int argc, char *argv[])
/* start the requested operation */
switch(pmo_op) {
case PM_ADD: ret = pacman_add(db_local, pm_targets, NULL); break;
- case PM_REMOVE: ret = pacman_remove(db_local, pm_targets); break;
+ case PM_REMOVE: ret = pacman_remove(db_local, pm_targets, NULL); break;
case PM_UPGRADE: ret = pacman_upgrade(db_local, pm_targets, NULL); break;
case PM_QUERY: ret = pacman_query(db_local, pm_targets); break;
case PM_SYNC: ret = pacman_sync(db_local, pm_targets); break;
@@ -1323,7 +1323,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
int oldval = pmo_nodeps;
/* we make pacman_remove() skip dependency checks by setting pmo_nodeps high */
pmo_nodeps = 1;
- retcode = pacman_remove(db, rmtargs);
+ retcode = pacman_remove(db, rmtargs, NULL);
pmo_nodeps = oldval;
FREELIST(rmtargs);
if(retcode == 1) {
@@ -1356,7 +1356,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
int oldval = pmo_nodeps;
/* we make pacman_remove() skip dependency checks by setting pmo_nodeps high */
pmo_nodeps = 1;
- allgood = !pacman_remove(db, rmtargs);
+ allgood = !pacman_remove(db, rmtargs, NULL);
pmo_nodeps = oldval;
if(!allgood) {
fprintf(stderr, "package removal failed. aborting...\n");
@@ -1367,11 +1367,17 @@ int pacman_sync(pacdb_t *db, PMList *targets)
allgood = !pacman_upgrade(db, files, dependonly);
}
/* propagate replaced packages' requiredby fields to their new owners */
+ /* XXX: segfault */
if(allgood) {
for(i = final; i; i = i->next) {
syncpkg_t *sync = (syncpkg_t*)i->data;
if(sync->replaces) {
- pkginfo_t *new = db_scan(db, sync->pkg->name, INFRQ_DEPENDS);
+ pkginfo_t *new;
+ new = db_scan(db, sync->pkg->name, INFRQ_DEPENDS);
+ if(!new) {
+ fprintf(stderr, "Something has gone terribly wrong. I'll probably segfault now.\n");
+ fflush(stderr);
+ }
for(j = sync->replaces; j; j = j->next) {
pkginfo_t *old = (pkginfo_t*)j->data;
/* merge lists */
@@ -1448,6 +1454,8 @@ int pacman_add(pacdb_t *db, PMList *targets, PMList *dependonly)
struct stat buf;
PMList *targ, *lp, *j, *k;
PMList *alltargs = NULL;
+ PMList *skiplist = NULL;
+
unsigned short real_pmo_upgrade;
tartype_t gztype = {
(openfunc_t) gzopen_frontend,
@@ -1646,7 +1654,7 @@ int pacman_add(pacdb_t *db, PMList *targets, PMList *dependonly)
alltargs = k;
/* make sure pacman_remove does it's own dependency check */
pmo_upgrade = 0;
- retcode = pacman_remove(db, rmtargs);
+ retcode = pacman_remove(db, rmtargs, NULL);
list_free(rmtargs);
if(retcode == 1) {
fprintf(stderr, "\n%s aborted.\n", oldupg ? "upgrade" : "install");
@@ -1683,7 +1691,7 @@ int pacman_add(pacdb_t *db, PMList *targets, PMList *dependonly)
if(!pmo_force) {
printf("checking for file conflicts... ");
fflush(stdout);
- lp = db_find_conflicts(db, alltargs, pmo_root);
+ lp = db_find_conflicts(db, alltargs, pmo_root, &skiplist);
if(lp) {
printf("\nerror: the following file conflicts were found:\n");
for(j = lp; j; j = j->next) {
@@ -1738,7 +1746,7 @@ int pacman_add(pacdb_t *db, PMList *targets, PMList *dependonly)
/* copy over the install reason */
info->reason = oldpkg->reason;
vprint("removing old package first...\n");
- retcode = pacman_remove(db, tmp);
+ retcode = pacman_remove(db, tmp, skiplist);
FREELIST(tmp);
if(retcode == 1) {
fprintf(stderr, "\nupgrade aborted.\n");
@@ -1793,7 +1801,20 @@ int pacman_add(pacdb_t *db, PMList *targets, PMList *dependonly)
snprintf(expath, PATH_MAX, "%s%s", pmo_root, pathname);
}
- if(!stat(expath, &buf) && !S_ISDIR(buf.st_mode)) {
+ /* if a file is in NoUpgrade and missing from the filesystem,
+ * then we never extract it.
+ *
+ * eg, /home/httpd/html/index.html may be removed so index.php
+ * could be used
+ */
+ if(stat(expath, &buf) && is_in(pathname, pmo_noupgrade)) {
+ vprint("%s is in NoUpgrade - skipping\n", pathname);
+ logaction(stderr, "warning: %s is in NoUpgrade -- skipping extraction", pathname);
+ tar_skip_regfile(tar);
+ continue;
+ }
+
+ if(!notouch && !stat(expath, &buf) && !S_ISDIR(buf.st_mode)) {
/* file already exists */
if(is_in(pathname, pmo_noupgrade)) {
notouch = 1;
@@ -1916,7 +1937,6 @@ int pacman_add(pacdb_t *db, PMList *targets, PMList *dependonly)
vprint("%s is in NoUpgrade - skipping\n", pathname);
strncat(expath, ".pacnew", PATH_MAX);
logaction(stderr, "warning: extracting %s%s as %s", pmo_root, pathname, expath);
- /*tar_skip_regfile(tar);*/
}
if(pmo_force) {
/* if pmo_force was used, then unlink() each file (whether it's there
@@ -1980,6 +2000,7 @@ int pacman_add(pacdb_t *db, PMList *targets, PMList *dependonly)
continue;
}
}
+ FREEPKG(tmpp);
}
vprint("Updating database...");
@@ -2019,6 +2040,7 @@ int pacman_add(pacdb_t *db, PMList *targets, PMList *dependonly)
if(provides) {
/* use the first one */
depinfo = db_scan(db, provides->data, INFRQ_DEPENDS);
+ FREELIST(provides);
if(depinfo == NULL) {
/* wtf */
continue;
@@ -2066,7 +2088,7 @@ int pacman_add(pacdb_t *db, PMList *targets, PMList *dependonly)
return(ret);
}
-int pacman_remove(pacdb_t *db, PMList *targets)
+int pacman_remove(pacdb_t *db, PMList *targets, PMList *skiplist)
{
char line[PATH_MAX+1];
char pm_install[PATH_MAX+1];
@@ -2137,8 +2159,17 @@ int pacman_remove(pacdb_t *db, PMList *targets)
for(j = lp; j; j = j->next) {
depmissing_t* miss = (depmissing_t*)j->data;
info = db_scan(db, miss->depend.name, INFRQ_ALL);
+ if(info == NULL) {
+ fprintf(stderr, "error: %s is not installed, even though it is required\n", miss->depend.name);
+ fprintf(stderr, " by an installed package (%s)\n\n", miss->target);
+ fprintf(stderr, "cannot complete a cascade removal with a broken dependency chain\n");
+ FREELISTPKGS(alltargs);
+ return(1);
+ }
if(!is_pkgin(info, alltargs)) {
alltargs = list_add(alltargs, info);
+ } else {
+ FREEPKG(info);
}
}
list_free(lp);
@@ -2198,16 +2229,19 @@ int pacman_remove(pacdb_t *db, PMList *targets)
/* iterate through the list backwards, unlinking files */
for(lp = list_last(info->files); lp; lp = lp->prev) {
int nb = 0;
- if(needbackup((char*)lp->data, info->backup)) {
+ char *file;
+
+ file = (char*)lp->data;
+ if(needbackup(file, info->backup)) {
nb = 1;
}
if(!nb && pmo_upgrade) {
/* check pmo_noupgrade */
- if(is_in((char*)lp->data, pmo_noupgrade)) {
+ if(is_in(file, pmo_noupgrade)) {
nb = 1;
}
}
- snprintf(line, PATH_MAX, "%s%s", pmo_root, (char*)lp->data);
+ snprintf(line, PATH_MAX, "%s%s", pmo_root, file);
if(lstat(line, &buf)) {
vprint("file %s does not exist\n", line);
continue;
@@ -2218,27 +2252,41 @@ int pacman_remove(pacdb_t *db, PMList *targets)
/* this is okay, other packages are probably using it. */
}
} else {
- /* if the file is flagged, back it up to .pacsave */
- if(nb) {
- if(pmo_upgrade) {
- /* we're upgrading so just leave the file as is. pacman_add() will handle it */
- } else {
- if(!pmo_nosave) {
- newpath = (char*)realloc(newpath, strlen(line)+strlen(".pacsave")+1);
- sprintf(newpath, "%s.pacsave", line);
- rename(line, newpath);
- logaction(stderr, "warning: %s saved as %s", line, newpath);
+ /* check the "skip list" before removing the file
+ *
+ * see the big comment block in db_find_conflicts() for an explanation
+ */
+ int skipit = 0;
+ for(j = skiplist; j; j = j->next) {
+ if(!strcmp(file, (char*)j->data)) {
+ skipit = 1;
+ }
+ }
+ if(skipit) {
+ vprint("skipping removal of %s (it has moved to another package)\n", file);
+ } else {
+ /* if the file is flagged, back it up to .pacsave */
+ if(nb) {
+ if(pmo_upgrade) {
+ /* we're upgrading so just leave the file as is. pacman_add() will handle it */
} else {
- /*vprint(" unlinking %s\n", line);*/
- if(unlink(line)) {
- perror("cannot remove file");
+ if(!pmo_nosave) {
+ newpath = (char*)realloc(newpath, strlen(line)+strlen(".pacsave")+1);
+ sprintf(newpath, "%s.pacsave", line);
+ rename(line, newpath);
+ logaction(stderr, "warning: %s saved as %s", line, newpath);
+ } else {
+ /*vprint(" unlinking %s\n", line);*/
+ if(unlink(line)) {
+ perror("cannot remove file");
+ }
}
}
- }
- } else {
- /*vprint(" unlinking %s\n", line);*/
- if(unlink(line)) {
- perror("cannot remove file");
+ } else {
+ /*vprint(" unlinking %s\n", line);*/
+ if(unlink(line)) {
+ perror("cannot remove file");
+ }
}
}
}
@@ -2252,27 +2300,11 @@ int pacman_remove(pacdb_t *db, PMList *targets)
}
/* remove the package from the database */
- snprintf(line, PATH_MAX, "%s%s/%s/%s-%s", pmo_root, pmo_dbpath, db->treename,
- info->name, info->version);
-
- /* DESC */
- snprintf(pm_install, PATH_MAX, "%s/desc", line);
- unlink(pm_install);
- /* FILES */
- snprintf(pm_install, PATH_MAX, "%s/files", line);
- unlink(pm_install);
- /* DEPENDS */
- snprintf(pm_install, PATH_MAX, "%s/depends", line);
- unlink(pm_install);
- /* INSTALL */
- snprintf(pm_install, PATH_MAX, "%s/install", line);
- unlink(pm_install);
- /* directory */
- rmdir(line);
+ db_remove(db, info);
/* update dependency packages' REQUIREDBY fields */
for(lp = info->depends; lp; lp = lp->next) {
- PMList *j;
+ PMList *k;
if(splitdep((char*)lp->data, &depend)) {
continue;
@@ -2298,9 +2330,9 @@ int pacman_remove(pacdb_t *db, PMList *targets)
}
}
/* splice out this entry from requiredby */
- for(j = depinfo->requiredby; j; j = j->next) {
- if(!strcmp((char*)j->data, info->name)) {
- depinfo->requiredby = list_remove(depinfo->requiredby, j);
+ for(k = depinfo->requiredby; k; k = k->next) {
+ if(!strcmp((char*)k->data, info->name)) {
+ depinfo->requiredby = list_remove(depinfo->requiredby, k);
break;
}
}
@@ -2673,6 +2705,7 @@ PMList* removedeps(pacdb_t *db, PMList *targs)
FREELIST(k);
}
if(is_pkgin(dep, targs)) {
+ FREEPKG(dep);
continue;
}
/* see if it was explicitly installed */
@@ -2687,10 +2720,11 @@ PMList* removedeps(pacdb_t *db, PMList *targs)
if(!is_pkgin(dummy, targs)) {
needed = 1;
}
+ FREEPKG(dummy);
}
+ FREEPKG(dep);
if(!needed) {
/* add it to the target list */
- freepkg(dep);
dep = db_scan(db, depend.name, INFRQ_ALL);
newtargs = list_add(newtargs, dep);
newtargs = removedeps(db, newtargs);
@@ -2922,6 +2956,8 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
strncpy(miss->depend.version, depend.version, 64);
if(!list_isin(baddeps, miss)) {
baddeps = list_add(baddeps, miss);
+ } else {
+ FREE(miss);
}
}
FREEPKG(p);
@@ -2969,6 +3005,8 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
strncpy(miss->depend.name, dp->name, 256);
if(!list_isin(baddeps, miss)) {
baddeps = list_add(baddeps, miss);
+ } else {
+ FREE(miss);
}
}
}
@@ -3002,6 +3040,8 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
strncpy(miss->depend.name, otp->name, 256);
if(!list_isin(baddeps, miss)) {
baddeps = list_add(baddeps, miss);
+ } else {
+ FREE(miss);
}
}
}
@@ -3036,6 +3076,8 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
strncpy(miss->depend.name, info->name, 256);
if(!list_isin(baddeps, miss)) {
baddeps = list_add(baddeps, miss);
+ } else {
+ FREE(miss);
}
}
}
@@ -3063,6 +3105,8 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
strncpy(miss->depend.name, k->data, 256);
if(!list_isin(baddeps, miss)) {
baddeps = list_add(baddeps, miss);
+ } else {
+ FREE(miss);
}
}
}*/
@@ -3178,6 +3222,8 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
strncpy(miss->depend.version, depend.version, 64);
if(!list_isin(baddeps, miss)) {
baddeps = list_add(baddeps, miss);
+ } else {
+ FREE(miss);
}
}
}
@@ -3200,6 +3246,8 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
strncpy(miss->depend.name, (char*)j->data, 256);
if(!list_isin(baddeps, miss)) {
baddeps = list_add(baddeps, miss);
+ } else {
+ FREE(miss);
}
}
}
@@ -3326,10 +3374,10 @@ int runscriptlet(char *installfn, char *script, char *ver, char *oldver)
vprint("Executing %s script...\n", script);
if(oldver) {
- snprintf(cmdline, PATH_MAX, "echo \"umask 0022; source %s %s %s %s\" | chroot %s /bin/sh",
+ snprintf(cmdline, PATH_MAX, "echo \"umask 0022; source %s %s %s %s\" | /usr/sbin/chroot %s /bin/sh",
scriptpath, script, ver, oldver, pmo_root);
} else {
- snprintf(cmdline, PATH_MAX, "echo \"umask 0022; source %s %s %s\" | chroot %s /bin/sh",
+ snprintf(cmdline, PATH_MAX, "echo \"umask 0022; source %s %s %s\" | /usr/sbin/chroot %s /bin/sh",
scriptpath, script, ver, pmo_root);
}
vprint("%s\n", cmdline);
diff --git a/src/pacman.h b/src/pacman.h
index 9e22bb31..79106eb1 100644
--- a/src/pacman.h
+++ b/src/pacman.h
@@ -33,7 +33,7 @@
#define min(X, Y) ((X) < (Y) ? (X) : (Y))
int pacman_add(pacdb_t *db, PMList *targets, PMList *dependonly);
-int pacman_remove(pacdb_t *db, PMList *targets);
+int pacman_remove(pacdb_t *db, PMList *targets, PMList *skiplist);
int pacman_upgrade(pacdb_t *db, PMList *targets, PMList *dependonly);
int pacman_query(pacdb_t *db, PMList *targets);
int pacman_sync(pacdb_t *db, PMList *targets);
diff --git a/src/pacsync.c b/src/pacsync.c
index c2ff4bee..4b1f1b53 100644
--- a/src/pacsync.c
+++ b/src/pacsync.c
@@ -441,6 +441,13 @@ int downloadfiles_forreal(PMList *servers, const char *localpath,
snprintf(completefile, PATH_MAX, "%s/%s", localpath, fn);
rename(output, completefile);
} else if(filedone < 0) {
+ if(!pmo_xfercommand) {
+ if(!strcmp(server->protocol, "ftp") && !pmo_proxyhost) {
+ FtpQuit(control);
+ } else if(!strcmp(server->protocol, "http") || (pmo_proxyhost && strcmp(server->protocol, "file"))) {
+ HttpQuit(control);
+ }
+ }
return(-1);
}
printf("\n");
diff --git a/src/strhash.c b/src/strhash.c
index 1ee5498c..01e172a4 100644
--- a/src/strhash.c
+++ b/src/strhash.c
@@ -1,22 +1,22 @@
/* evtgen string hash functions.
- Copyright (C) 2003 Julien Olivain and LSV, CNRS UMR 8643 & ENS Cachan.
+ Copyright (C) 2003 Julien Olivain and LSV, CNRS UMR 8643 & ENS Cachan.
- This file is part of evtgen.
+ 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 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.
+ 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.
-*/
+ 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>
*
@@ -24,8 +24,8 @@
*/
/*
-** strhash.c -- string hash utility functions
-*/
+ ** strhash.c -- string hash utility functions
+ */
#include <stdlib.h>
#include <stdio.h>
@@ -35,161 +35,168 @@
#include "list.h"
#include "strhash.h"
-void
-strhash_add_list(strhash_t *hash, PMList* list)
+void strhash_add_list(strhash_t *hash, PMList* list)
{
- for(; list; list = list->next)
+ for(; list; list = list->next) {
strhash_add(hash, list->data, NULL);
+ }
}
-strhash_t *
-new_strhash(size_t hsize)
+strhash_t* new_strhash(size_t hsize)
{
- strhash_t *h;
+ 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 *));
+ 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);
+ return(h);
}
-void
-clear_strhash(strhash_t *hash)
+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 *));
+ 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)
+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);
+ 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)
+void strhash_add(strhash_t *hash, char *key, char *data)
{
- strhash_elmt_t *elmt;
- unsigned long hcode;
+ strhash_elmt_t *elmt;
+ unsigned long hcode;
- MALLOC(elmt, sizeof (strhash_elmt_t));
- elmt->key = key;
- elmt->data = data;
+ 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++;
+}
- hcode = hash->hash(key) % hash->size;
- elmt->next = hash->htable[hcode];
- hash->htable[hcode] = elmt;
- hash->elmts++;
+void strhash_remove(strhash_t *hash, char *key)
+{
+ unsigned long hcode;
+ strhash_elmt_t *elmt;
+ strhash_elmt_t *prev = NULL;
+
+ hcode = hash->hash(key) % hash->size;
+
+ elmt = hash->htable[hcode];
+ for(; elmt; elmt = elmt->next) {
+ if(!strcmp(key, elmt->key)) {
+ if(prev) {
+ prev->next = elmt->next;
+ } else {
+ hash->htable[hcode] = elmt->next;
+ }
+ FREE(elmt);
+ return;
+ }
+ prev = elmt;
+ }
}
/* 1: Yes, the key exists in the hash table.
- * 0: No, its not here.
+ * 0: No, it's not here.
*/
-
-int
-strhash_isin(strhash_t *hash, char* key)
+int strhash_isin(strhash_t *hash, char* key)
{
- strhash_elmt_t *elmt;
+ strhash_elmt_t *elmt;
- elmt = hash->htable[hash->hash(key) % hash->size];
- for (; elmt; elmt = elmt->next)
- {
- if (!strcmp(key, elmt->key))
- return 1;
- }
+ elmt = hash->htable[hash->hash(key) % hash->size];
+ for(; elmt; elmt = elmt->next) {
+ if(!strcmp(key, elmt->key)) {
+ return 1;
+ }
+ }
- return 0;
+ return 0;
}
-char*
-strhash_get(strhash_t *hash, char* key)
+char* strhash_get(strhash_t *hash, char* key)
{
- strhash_elmt_t *elmt;
+ 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;
- }
+ elmt = hash->htable[hash->hash(key) % hash->size];
+ for(; elmt; elmt = elmt->next) {
+ if(!strcmp(key, elmt->key)) {
+ return elmt->data;
+ }
+ }
- return NULL;
+ return NULL;
}
/*
-** fast hash function samples
-*/
-
-unsigned long
-strhash_pjw(char *key)
+ ** 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);
+ 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 strhash_collide_count(strhash_t *hash)
{
- int count;
- int i;
+ int count;
+ int i;
- count = 0;
- for (i = 0; i < hash->size; i++)
- {
- strhash_elmt_t *tmp;
+ 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++;
- }
+ for(tmp = hash->htable[i]; tmp; tmp = tmp->next) {
+ if(tmp->next) {
+ count++;
+ }
+ }
+ }
- return (count);
+ return(count);
}
diff --git a/src/strhash.h b/src/strhash.h
index 65b7f4e1..9c2d63ec 100644
--- a/src/strhash.h
+++ b/src/strhash.h
@@ -55,6 +55,7 @@ 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_remove(strhash_t *hash, char *key);
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);