Imported from pacman-2.9.6.tar.gz
This commit is contained in:
parent
d48cc3bf5d
commit
d05f0047a0
18 changed files with 489 additions and 254 deletions
11
ChangeLog
11
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
114
scripts/pacman-optimize
Executable file
114
scripts/pacman-optimize
Executable file
|
@ -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
|
||||
|
|
@ -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"
|
||||
|
|
125
src/db.c
125
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);
|
||||
}
|
||||
|
||||
|
|
7
src/db.h
7
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);
|
||||
|
|
17
src/list.c
17
src/list.c
|
@ -67,17 +67,14 @@ PMList* list_new()
|
|||
|
||||
void list_free(PMList *list)
|
||||
{
|
||||
if(list == NULL) {
|
||||
return;
|
||||
PMList *ptr, *it = list;
|
||||
|
||||
while(it) {
|
||||
ptr = it->next;
|
||||
free(it->data);
|
||||
free(it);
|
||||
it = ptr;
|
||||
}
|
||||
if(list->data != NULL) {
|
||||
free(list->data);
|
||||
list->data = NULL;
|
||||
}
|
||||
if(list->next != NULL) {
|
||||
list_free(list->next);
|
||||
}
|
||||
free(list);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#define _PAC_PACCONF_H
|
||||
|
||||
#ifndef PACVER
|
||||
#define PACVER "2.9.5"
|
||||
#define PACVER "2.9.6"
|
||||
#endif
|
||||
|
||||
#ifndef PACDBDIR
|
||||
|
|
122
src/pacman.c
122
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;
|
||||
|
@ -2217,6 +2251,19 @@ int pacman_remove(pacdb_t *db, PMList *targets)
|
|||
if(rmdir(line)) {
|
||||
/* this is okay, other packages are probably using it. */
|
||||
}
|
||||
} else {
|
||||
/* 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) {
|
||||
|
@ -2244,6 +2291,7 @@ int pacman_remove(pacdb_t *db, PMList *targets)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!pmo_upgrade) {
|
||||
/* run the post-remove script if it exists */
|
||||
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -35,15 +35,14 @@
|
|||
#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;
|
||||
|
||||
|
@ -57,18 +56,15 @@ new_strhash(size_t hsize)
|
|||
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++)
|
||||
{
|
||||
for(i = 0; i < hash->size; i++) {
|
||||
tmp = hash->htable[i];
|
||||
while (tmp)
|
||||
{
|
||||
while(tmp) {
|
||||
tmp_next = tmp->next;
|
||||
free(tmp);
|
||||
tmp = tmp_next;
|
||||
|
@ -78,19 +74,15 @@ clear_strhash(strhash_t *hash)
|
|||
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++)
|
||||
{
|
||||
for(i = 0; i < hash->size; i++) {
|
||||
tmp = hash->htable[i];
|
||||
while (tmp)
|
||||
{
|
||||
while(tmp) {
|
||||
tmp_next = tmp->next;
|
||||
free(tmp);
|
||||
tmp = tmp_next;
|
||||
|
@ -101,8 +93,7 @@ free_strhash(strhash_t *hash)
|
|||
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;
|
||||
|
@ -117,36 +108,56 @@ strhash_add(strhash_t *hash, char *key, char *data)
|
|||
hash->elmts++;
|
||||
}
|
||||
|
||||
/* 1: Yes, the key exists in the hash table.
|
||||
* 0: No, its not here.
|
||||
*/
|
||||
void strhash_remove(strhash_t *hash, char *key)
|
||||
{
|
||||
unsigned long hcode;
|
||||
strhash_elmt_t *elmt;
|
||||
strhash_elmt_t *prev = NULL;
|
||||
|
||||
int
|
||||
strhash_isin(strhash_t *hash, char* key)
|
||||
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, it's 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))
|
||||
for(; elmt; elmt = elmt->next) {
|
||||
if(!strcmp(key, elmt->key)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char*
|
||||
strhash_get(strhash_t *hash, char* key)
|
||||
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))
|
||||
for(; elmt; elmt = elmt->next) {
|
||||
if(!strcmp(key, elmt->key)) {
|
||||
return elmt->data;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -154,19 +165,15 @@ strhash_get(strhash_t *hash, char* key)
|
|||
/*
|
||||
** fast hash function samples
|
||||
*/
|
||||
|
||||
unsigned long
|
||||
strhash_pjw(char *key)
|
||||
unsigned long strhash_pjw(char *key)
|
||||
{
|
||||
unsigned long h;
|
||||
unsigned long g;
|
||||
|
||||
h = 0;
|
||||
while (*key)
|
||||
{
|
||||
while(*key) {
|
||||
h = (h << 4) + *key++;
|
||||
if ((g = h & 0xF0000000U) != 0)
|
||||
{
|
||||
if((g = h & 0xF0000000U) != 0) {
|
||||
h = h ^ (g >> 24);
|
||||
h = h ^ g;
|
||||
}
|
||||
|
@ -175,21 +182,21 @@ strhash_pjw(char *key)
|
|||
return (h);
|
||||
}
|
||||
|
||||
int
|
||||
strhash_collide_count(strhash_t *hash)
|
||||
int strhash_collide_count(strhash_t *hash)
|
||||
{
|
||||
int count;
|
||||
int i;
|
||||
|
||||
count = 0;
|
||||
for (i = 0; i < hash->size; i++)
|
||||
{
|
||||
for(i = 0; i < hash->size; i++) {
|
||||
strhash_elmt_t *tmp;
|
||||
|
||||
for (tmp = hash->htable[i]; tmp; tmp = tmp->next)
|
||||
if (tmp->next)
|
||||
for(tmp = hash->htable[i]; tmp; tmp = tmp->next) {
|
||||
if(tmp->next) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(count);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue