From 4ad864462043c61d19861e4b7cacf6610ae9ce7f Mon Sep 17 00:00:00 2001 From: Judd Vinet Date: Thu, 29 Apr 2004 19:43:18 +0000 Subject: Imported from pacman-2.7.8.tar.gz --- ChangeLog | 20 +++++ Makefile.in | 2 +- doc/makepkg.8.in | 17 +++- doc/pacman.8.in | 17 +++- etc/makepkg.conf | 5 +- etc/pacman.conf | 2 +- libftp/ftplib.c | 6 +- scripts/gensync | 25 +++--- scripts/makepkg | 10 ++- scripts/makeworld | 2 +- src/db.c | 79 ++++++++++++++--- src/db.h | 1 + src/package.c | 33 +++++++- src/package.h | 3 +- src/pacman.c | 249 ++++++++++++++++++++++++++++++++++++++---------------- src/pacman.h | 6 +- src/pacsync.c | 35 ++++++-- 17 files changed, 388 insertions(+), 124 deletions(-) diff --git a/ChangeLog b/ChangeLog index e82b3e16..8c511a06 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,25 @@ VERSION DESCRIPTION ----------------------------------------------------------------------------- +2.7.8 - added post_remove scriptlet support + - added -Qs option (bug #854) + - a provisio does not imply conflict, to make a provisio target + conflict with anything else that provides the same thing, you + can now do this by specifying the provisio target as both a + provides and a conflict, eg: + conflicts=('x-server') + provides=('x-server') + - cleaned up the download progress bar a bit + - added %o parameter to XferCommand so wget can resume properly + - fixed a segfault in downloadfiles() (bug #787) + - patches from Oliver Burnett-Hall + - gensync uses a better temp dir (bug #774) + - PKGDEST can be set in makepkg.conf (bug #783) + - patches from Aurelien Foret + - segfault fix, couple memory leaks + - more sanity checks in "provides" searches + - fixed a little display bug in the progress bar + - made -Qip look like -Qi + - -Sc now removes OLD packages from cache, use -Scc for all 2.7.7 - added an XferCommand directive that will make pacman use an external download utility like wget - added a license field to package meta-data diff --git a/Makefile.in b/Makefile.in index dcf070f3..8bfeae36 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.7.7 +PACVER = 2.7.8 TOPDIR = @srcdir@ SRCDIR = $(TOPDIR)/src/ diff --git a/doc/makepkg.8.in b/doc/makepkg.8.in index 041d4fd1..6547cb7e 100644 --- a/doc/makepkg.8.in +++ b/doc/makepkg.8.in @@ -1,4 +1,4 @@ -.TH makepkg 8 "December 20, 2003" "makepkg #VERSION#" "" +.TH makepkg 8 "April 27, 2004" "makepkg #VERSION#" "" .SH NAME makepkg \- package build utility .SH SYNOPSIS @@ -131,6 +131,10 @@ script is run after all files have been upgraded. .B pre_remove script is run right before files are removed. +.TP +.B post_remove +script is run right after files are removed. + .RE To use this feature, just create a file (eg, pkgname.install) and put it in the same directory as the PKGBUILD script. Then use the \fIinstall\fP directive: @@ -172,14 +176,21 @@ pre_remove() { /bin/true } +# arg 1: the old package version +post_remove() { + # + # do post-remove stuff here + # + /bin/true +} + op=$1 shift - $op $* .fi .RE -This template is also available in your ABS tree (/usr/abs/install.proto). +This template is also available in your ABS tree (/var/abs/install.proto). .SH PKGBUILD Directives .TP diff --git a/doc/pacman.8.in b/doc/pacman.8.in index 33b43636..32cd42db 100644 --- a/doc/pacman.8.in +++ b/doc/pacman.8.in @@ -1,4 +1,4 @@ -.TH pacman 8 "April 14, 2004" "pacman #VERSION#" "" +.TH pacman 8 "April 29, 2004" "pacman #VERSION#" "" .SH NAME pacman \- package manager utility .SH SYNOPSIS @@ -101,9 +101,11 @@ Output more status and error messages. .SH SYNC OPTIONS .TP .B "\-c, \-\-clean" -Remove packages from the cache. When pacman downloads packages, +Remove old packages from the cache. When pacman downloads packages, it saves them in \fI/var/cache/pacman/pkg\fP. If you need to free up diskspace, you can remove these packages by using the --clean option. +Using one --clean (or -c) switch will only remove \fIold\fP packages. +Use it twice to remove \fIall\fP packages from the cache. .TP .B "\-g, \-\-groups" Display all the members for each package group specified. If no group @@ -163,6 +165,10 @@ Search for the package that owns . Tells pacman that the package supplied on the command line is a file, not an entry in the database. Pacman will decompress the file and query it. This is useful with \fB--info\fP and \fB--list\fP. +.TP +.B "\-s, \-\-search " +This will search each locally-installed package for names or descriptions +that contains . .SH HANDLING CONFIG FILES pacman uses the same logic as rpm to determine action against files that are designated to be backed up. During an upgrade, it uses 3 @@ -230,8 +236,11 @@ If set, pacman will use this proxy server for all ftp/http transfers. .TP .B "XferCommand = /path/to/command %u" If set, pacman will use this external program to download all remote files. -All instances of \fB%u\fP will be replaced with the URL to be downloaded. -This is useful for users who experience problems with pacman's built-in http/ftp +All instances of \fB%u\fP will be replaced with the URL to be downloaded. If +present, instances of \fB%o\fP will be replaced with the local filename, plus a +".part" extension, which allows programs like wget to do file resumes properly. + +This option is useful for users who experience problems with pacman's built-in http/ftp support, or need the more advanced proxy support that comes with utilities like wget. .TP diff --git a/etc/makepkg.conf b/etc/makepkg.conf index af29d74d..0d0809a0 100644 --- a/etc/makepkg.conf +++ b/etc/makepkg.conf @@ -28,6 +28,9 @@ export USE_FAKEROOT="y" # Enable colorized output messages export USE_COLOR="n" -# if you want your name to show up in the packages you build, set this. +# Specify a fixed directory where all packages will be placed +#export PKGDEST=/home/packages + +# If you want your name to show up in the packages you build, set this. #export PACKAGER="John Doe " diff --git a/etc/pacman.conf b/etc/pacman.conf index 07ef718d..6ecb832a 100644 --- a/etc/pacman.conf +++ b/etc/pacman.conf @@ -23,7 +23,7 @@ NoUpgrade = etc/fstab etc/raidtab NoUpgrade = etc/rc.conf etc/rc.local NoUpgrade = etc/modprobe.conf etc/modules.conf NoUpgrade = etc/lilo.conf boot/grub/menu.lst -#XferCommand = /usr/bin/wget --passive-ftp -c %u +#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u # # REPOSITORIES diff --git a/libftp/ftplib.c b/libftp/ftplib.c index 68165100..1e299b5b 100644 --- a/libftp/ftplib.c +++ b/libftp/ftplib.c @@ -1562,6 +1562,8 @@ GLOBALREF int HttpGet(const char *host, const char *outputfile, const char *path */ GLOBALREF void HttpQuit(netbuf *nControl) { - net_close(nControl->handle); - free(nControl); + if(nControl) { + net_close(nControl->handle); + free(nControl); + } } diff --git a/scripts/gensync b/scripts/gensync index e7c7724c..23347630 100755 --- a/scripts/gensync +++ b/scripts/gensync @@ -20,15 +20,15 @@ # USA. # -myver='2.7.7' +myver='2.7.8' usage() { echo "gensync $myver" echo "usage: $0 [package_directory]" echo echo "gensync will generate a sync database by reading all PKGBUILD files" - echo "from . gensync builds the database in /tmp/.gensync and then" - echo "compresses it to ." + echo "from . gensync builds the database in a temporary directory" + echo "and then compresses it to ." echo echo "gensync will calculate md5sums of packages in , unless an" echo "alternate [package_directory] is specified." @@ -66,7 +66,7 @@ db_write_entry() unset pkgname pkgver pkgrel pkgdesc unset groups replaces provides depends conflicts source $1 || return 1 - cd /tmp/.gensync + cd $gstmpdir mkdir $pkgname-$pkgver-$pkgrel cd $pkgname-$pkgver-$pkgrel # desc @@ -143,43 +143,40 @@ pkgdir= if [ "$3" != "" ]; then pkgdir=$3 fi - -rm -rf /tmp/.gensync || exit 1 -mkdir -p /tmp/.gensync || exit 1 +gstmpdir=$(mktemp -dt gensync.XXXXXXXXXX) || exit 1 if [ ! -d $rootdir ]; then echo "gensync: invalid root dir: $rootdir" >&2 - rm -rf /tmp/.gensync + rm -rf $gstmpdir exit 1 fi echo "gensync: building database entries, generating md5sums..." >&2 cd `dirname $2` -#for category in `find $rootdir/* -type d -maxdepth 0`; do for file in `find $rootdir/* -name PKGBUILD`; do pkgmd5sum=`get_md5checksum $file $pkgdir` if [ -z $pkgmd5sum ]; then echo "gensync: error generating checksum for $file" >&2 - rm -rf /tmp/.gensync + rm -rf $gstmpdir exit 1 fi db_write_entry $file if [ $? -gt 0 ]; then echo "gensync: error writing entry for $file" >&2 - rm -rf /tmp/.gensync + rm -rf $gstmpdir exit 1 fi done echo "gensync: compressing to $destfile..." >&2 -cd /tmp/.gensync +cd $gstmpdir tar c * | gzip -9 >$destfile if [ $? -gt 0 ]; then echo "gensync: error writing to $destfile" >&2 - rm -rf /tmp/.gensync + rm -rf $gstmpdir exit 1 fi -rm -rf /tmp/.gensync +rm -rf $gstmpdir exit 0 diff --git a/scripts/makepkg b/scripts/makepkg index d53bdd17..c0977b9f 100755 --- a/scripts/makepkg +++ b/scripts/makepkg @@ -20,8 +20,9 @@ # USA. # -myver='2.7.7' +myver='2.7.8' startdir=`pwd` +PKGDEST=$startdir USE_COLOR="n" # source Arch's abs.conf if it's present @@ -208,7 +209,6 @@ FORCE=0 NOEXTRACT=0 NOSTRIP=0 RMDEPS=0 -PKGDEST=$startdir BUILDSCRIPT="./PKGBUILD" ARGLIST=$@ @@ -275,7 +275,11 @@ while [ "$#" -ne "0" ]; do done # convert a (possibly) relative path to absolute -cd $PKGDEST +cd $PKGDEST 2>/dev/null +if [ $? -ne 0 ]; then + error "Package destination directory does not exist or permission denied." + exit 1 +fi PKGDEST=`pwd` cd - diff --git a/scripts/makeworld b/scripts/makeworld index 1e6c7e6b..0397aa56 100755 --- a/scripts/makeworld +++ b/scripts/makeworld @@ -21,7 +21,7 @@ # toplevel=`pwd` -version="2.7.7" +version="2.7.8" usage() { echo "makeworld version $version" diff --git a/src/db.c b/src/db.c index 29135afd..3a208bea 100644 --- a/src/db.c +++ b/src/db.c @@ -71,7 +71,7 @@ PMList* db_loadpkgs(pacdb_t *db) PMList *cache = NULL; rewinddir(db->dir); - while((info = db_scan(db, NULL, INFRQ_DESC)) != NULL) { + while((info = db_scan(db, NULL, INFRQ_DESC | INFRQ_DEPENDS)) != NULL) { /* add to the collective */ /* we load all package names into a linear array first, so qsort can handle it */ if(arr == NULL) { @@ -110,12 +110,12 @@ pkginfo_t* db_scan(pacdb_t *db, char *target, unsigned int inforeq) if(target != NULL) { /* search for a specific package (by name only) */ rewinddir(db->dir); - /* read the . and .. first */ - ent = readdir(db->dir); - ent = readdir(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); /* truncate the string at the second-to-last hyphen, */ /* which will give us the package name */ @@ -137,14 +137,14 @@ pkginfo_t* db_scan(pacdb_t *db, char *target, unsigned int inforeq) } else { /* normal iteration */ ent = readdir(db->dir); - if(ent && !strcmp(ent->d_name, ".")) { - ent = readdir(db->dir); + if(ent == NULL) { + return(NULL); } - if(ent && !strcmp(ent->d_name, "..")) { + if(!strcmp(ent->d_name, ".")) { ent = readdir(db->dir); } - if(ent == NULL) { - return(NULL); + if(!strcmp(ent->d_name, "..")) { + ent = readdir(db->dir); } } return(db_read(db, ent, inforeq)); @@ -454,6 +454,65 @@ int db_write(pacdb_t *db, pkginfo_t *info) return(0); } +void db_search(pacdb_t *db, PMList *cache, const char *treename, PMList *needles) +{ + PMList *i, *j; + if(needles == NULL || needles->data == NULL) { + return; + } + + for(i = needles; i; i = i->next) { + char *targ = strdup(i->data); + strtoupper(targ); + for(j = cache; j; j = j->next) { + pkginfo_t *pkg = (pkginfo_t*)j->data; + char *haystack; + int match = 0; + /* check name */ + haystack = strdup(pkg->name); + strtoupper(haystack); + if(strstr(haystack, targ)) { + match = 1; + } + FREE(haystack); + + /* check description */ + if(!match) { + haystack = strdup(pkg->desc); + strtoupper(haystack); + if(strstr(haystack, targ)) { + match = 1; + } + FREE(haystack); + } + + /* check provides */ + if(!match) { + PMList *m; + pkginfo_t *info = db_scan(db, pkg->name, INFRQ_DESC | INFRQ_DEPENDS); + if(info != NULL) { + for(m = info->provides; m; m = m->next) { + haystack = strdup(m->data); + strtoupper(haystack); + if(strstr(haystack, targ)) { + match = 1; + } + FREE(haystack); + } + FREEPKG(info); + } + } + + if(match) { + printf("%s/%s %s\n ", treename, pkg->name, pkg->version); + indentprint(pkg->desc, 4); + printf("\n"); + } + } + FREE(targ); + } +} + PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root) { diff --git a/src/db.h b/src/db.h index 8d5282cf..6160a5f0 100644 --- a/src/db.h +++ b/src/db.h @@ -41,6 +41,7 @@ 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); +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 *whatprovides(pacdb_t *db, char* package); PMList *find_groups(pacdb_t *db); diff --git a/src/package.c b/src/package.c index 04153fb1..e7567d23 100644 --- a/src/package.c +++ b/src/package.c @@ -30,7 +30,7 @@ #include "util.h" #include "package.h" -pkginfo_t* load_pkg(char *pkgfile, unsigned short output) +pkginfo_t* load_pkg(char *pkgfile) { char *expath; int i; @@ -66,7 +66,7 @@ pkginfo_t* load_pkg(char *pkgfile, unsigned short output) mkstemp(descfile); tar_extract_file(tar, descfile); /* parse the info file */ - parse_descfile(descfile, info, &backup, output); + parse_descfile(descfile, info, &backup, 0); if(!strlen(info->name)) { fprintf(stderr, "load_pkg: missing package name in %s.\n", pkgfile); FREEPKG(info); @@ -379,4 +379,33 @@ void dump_pkg_sync(pkginfo_t *info) printf("\nMD5 Sum : %s\n", info->md5sum); } +int split_pkgname(char *pkg, char **name, char **version) +{ + char tmp[256]; + char *p, *q; + + strncpy(tmp, pkg, 256); + + p = strstr(tmp, ".pkg.tar.gz"); + if(p == NULL) { + return(-1); + } + *p = 0; + + for(q = --p; *q && *q != '-'; q--); + if(*q != '-' || q == tmp) { + return(-1); + } + for(p = --q; *p && *p != '-'; p--); + if(*p != '-' || p == tmp) { + return(-1); + } + *version = strdup(p+1); + *p = 0; + + *name = strdup(tmp); + + return(0); +} + /* vim: set ts=2 sw=2 noet: */ diff --git a/src/package.h b/src/package.h index 8d6f458c..6dcd8cf3 100644 --- a/src/package.h +++ b/src/package.h @@ -75,7 +75,7 @@ typedef struct __depmissing_t { depend_t depend; } depmissing_t; -pkginfo_t* load_pkg(char *pkgfile, unsigned short output); +pkginfo_t* load_pkg(char *pkgfile); int parse_descfile(char *descfile, pkginfo_t *info, PMList **backup, int output); pkginfo_t* newpkg(); void freepkg(pkginfo_t *pkg); @@ -83,6 +83,7 @@ int pkgcmp(const void *p1, const void *p2); int is_pkgin(pkginfo_t *needle, PMList *haystack); void dump_pkg_full(pkginfo_t *info); void dump_pkg_sync(pkginfo_t *info); +int split_pkgname(char *pkg, char **name, char **version); #endif /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman.c b/src/pacman.c index e2db8721..3b5d3ddb 100644 --- a/src/pacman.c +++ b/src/pacman.c @@ -35,6 +35,7 @@ #include #include #include +#include /* pacman */ #include "rpmvercmp.h" #include "md5.h" @@ -68,6 +69,7 @@ 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; @@ -322,21 +324,96 @@ int pacman_sync(pacdb_t *db, PMList *targets) } if(pmo_s_clean) { - mode_t oldmask; + if(pmo_s_clean == 1) { + /* incomplete cleanup: we keep latest packages and partial downloads */ + DIR *dir; + struct dirent *ent; + PMList *cache = NULL; + PMList *clean = NULL; + PMList *i, *j; + + printf("removing old packages from cache... "); + dir = opendir("/var/cache/pacman/pkg"); + if(dir == NULL) { + fprintf(stderr, "error: could not access cache directory\n"); + return(1); + } + rewinddir(dir); + while((ent = readdir(dir)) != NULL) { + if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { + continue; + } + cache = list_add(cache, strdup(ent->d_name)); + } + closedir(dir); - printf("removing packages from cache... "); - if(rmrf("/var/cache/pacman/pkg")) { - fprintf(stderr, "error: could not remove cache directory: %s\n", strerror(errno)); - return(1); - } + for(i = cache; i; i = i->next) { + char *str = (char *)i->data; + char *name, *version; - oldmask = umask(0000); - if(makepath("/var/cache/pacman/pkg")) { - fprintf(stderr, "error: could not create new cache directory: %s\n", strerror(errno)); - return(1); - } - umask(oldmask); + if(split_pkgname(str, &name, &version) != 0) { + clean = list_add(clean, strdup(str)); + continue; + } + /* we keep partially downloaded files */ + if(strstr(str, ".pkg.tar.gz.part")) { + FREE(name); + FREE(version); + continue; + } + for(j = i->next; j; j = j->next) { + char *s = (char *)j->data; + char *n, *v; + if(split_pkgname(s, &n, &v) != 0) { + continue; + } + if(!strcmp(name, n)) { + char *ptr; + if(rpmvercmp(version, v) < 0) { + ptr = str; + } else { + ptr = s; + } + if(!is_in(ptr, clean)) { + clean = list_add(clean, strdup(ptr)); + } + } + FREE(n); + FREE(v); + } + FREE(name); + FREE(version); + } + FREELIST(cache); + + for(i = clean; i; i = i->next) { + char path[PATH_MAX]; + + snprintf(path, PATH_MAX, "%s%s/%s", pmo_root, CACHEDIR, (char *)i->data); + unlink(path); + } + FREELIST(clean); + } else { + /* full cleanup */ + mode_t oldmask; + char path[PATH_MAX]; + + snprintf(path, PATH_MAX, "%s%s", pmo_root, CACHEDIR); + + printf("removing all packages from cache... "); + if(rmrf(path)) { + fprintf(stderr, "error: could not remove cache directory: %s\n", strerror(errno)); + return(1); + } + + oldmask = umask(0000); + if(makepath(path)) { + fprintf(stderr, "error: could not create new cache directory: %s\n", strerror(errno)); + return(1); + } + umask(oldmask); + } printf("done.\n"); return(0); } @@ -374,53 +451,9 @@ int pacman_sync(pacdb_t *db, PMList *targets) if(pmo_s_search) { /* search sync databases */ if(targets) { - for(i = targets; i; i = i->next) { - char *targ = strdup(i->data); - strtoupper(targ); - for(j = databases; j; j = j->next) { - dbsync_t *dbs = (dbsync_t*)j->data; - for(k = dbs->pkgcache; k; k = k->next) { - pkginfo_t *pkg = (pkginfo_t*)k->data; - char *haystack; - PMList *m; - int match = 0; - /* check name */ - haystack = strdup(pkg->name); - strtoupper(haystack); - if(strstr(haystack, targ)) { - match = 1; - } - FREE(haystack); - - /* check description */ - haystack = strdup(pkg->desc); - strtoupper(haystack); - if(strstr(haystack, targ)) { - match = 1; - } - FREE(haystack); - - if(!match) { - pkg = db_scan(dbs->db, pkg->name, INFRQ_DESC | INFRQ_DEPENDS); - /* check provides */ - for(m = pkg->provides; m; m = m->next) { - haystack = strdup(m->data); - strtoupper(haystack); - if(strstr(haystack, targ)) { - match = 1; - } - FREE(haystack); - } - } - - if(match) { - printf("%s/%s %s\n ", dbs->sync->treename, pkg->name, pkg->version); - indentprint(pkg->desc, 4); - printf("\n"); - } - } - } - FREE(targ); + for(j = databases; j; j = j->next) { + dbsync_t *dbs = (dbsync_t*)j->data; + db_search(dbs->db, dbs->pkgcache, dbs->sync->treename, targets); } } else { for(j = databases; j; j = j->next) { @@ -1381,7 +1414,7 @@ int pacman_add(pacdb_t *db, PMList *targets) for(targ = targets; targ; targ = targ->next) { /* Populate the package struct */ vprint("reading %s... ", (char*)targ->data); - info = load_pkg((char*)targ->data, 0); + info = load_pkg((char*)targ->data); if(info == NULL) { return(1); } @@ -1957,7 +1990,7 @@ int pacman_remove(pacdb_t *db, PMList *targets) depmissing_t* miss = (depmissing_t*)j->data; printf(" %s: is required by %s\n", miss->target, miss->depend.name); } - list_free(alltargs); + FREELISTPKGS(alltargs); list_free(lp); return(1); } @@ -1973,7 +2006,7 @@ int pacman_remove(pacdb_t *db, PMList *targets) list_display("\nTargets:", alltargs); /* get confirmation */ if(yesno("\nDo you want to remove these packages? [Y/n] ") == 0) { - list_free(alltargs); + FREELISTPKGS(alltargs); return(1); } } @@ -2048,6 +2081,18 @@ int pacman_remove(pacdb_t *db, PMList *targets) } } + if(!pmo_upgrade) { + /* run the post-remove script if it exists */ + snprintf(pm_install, PATH_MAX, "%s%s/%s/%s-%s/install", pmo_root, pmo_dbpath, db->treename, info->name, info->version); + if(!stat(pm_install, &buf)) { + vprint("Executing post-remove script...\n"); + snprintf(pm_install, PATH_MAX, "%s/%s/%s-%s/install", pmo_dbpath, db->treename, info->name, info->version); + snprintf(line, PATH_MAX, "chroot %s /bin/sh %s post_remove %s", pmo_root, pm_install, info->version); + + system(line); + } + } + /* 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); @@ -2118,7 +2163,7 @@ int pacman_remove(pacdb_t *db, PMList *targets) } } - FREELIST(alltargs); + FREELISTPKGS(alltargs); /* run ldconfig if it exists */ snprintf(line, PATH_MAX, "%setc/ld.so.conf", pmo_root); @@ -2143,6 +2188,11 @@ int pacman_query(pacdb_t *db, PMList *targets) PMList *targ, *lp, *q; int done = 0; + if(pmo_q_search) { + db_search(db, pm_packages, "local", targets); + return(0); + } + for(targ = targets; !done; targ = (targ ? targ->next : NULL)) { if(targets == NULL) { done = 1; @@ -2187,12 +2237,13 @@ int pacman_query(pacdb_t *db, PMList *targets) fprintf(stderr, "error: no package file was specified for --file\n"); return(1); } - info = load_pkg(package, pmo_q_info); + info = load_pkg(package); if(info == NULL) { fprintf(stderr, "error: %s is not a package\n", package); return(1); } if(pmo_q_info) { + dump_pkg_full(info); printf("\n"); } else if(pmo_q_list) { for(lp = info->files; lp; lp = lp->next) { @@ -2670,8 +2721,26 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets) for(j = tp->conflicts; j; j = j->next) { /* check targets against database */ for(k = pm_packages; k; k = k->next) { + int conflict = 0; pkginfo_t *dp = (pkginfo_t*)k->data; + if(!strcmp(dp->name, tp->name)) { + /* a package cannot conflict with itself -- that's just not nice */ + continue; + } if(!strcmp(j->data, dp->name)) { + /* dp is listed in tp's conflict list */ + conflict = 1; + } else { + /* see if dp provides something in tp's conflict list */ + PMList *m; + for(m = dp->provides; m; m = m->next) { + if(!strcmp(m->data, j->data)) { + conflict = 1; + break; + } + } + } + if(conflict) { MALLOC(miss, sizeof(depmissing_t)); miss->type = CONFLICT; miss->depend.mod = DEP_ANY; @@ -2685,14 +2754,32 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets) } /* check targets against targets */ for(k = targets; k; k = k->next) { - pkginfo_t *a = (pkginfo_t*)k->data; - if(!strcmp(a->name, (char*)j->data)) { + int conflict = 0; + pkginfo_t *otp = (pkginfo_t*)k->data; + if(!strcmp(otp->name, tp->name)) { + /* a package cannot conflict with itself -- that's just not nice */ + continue; + } + if(!strcmp(otp->name, (char*)j->data)) { + /* otp is listed in tp's conflict list */ + conflict = 1; + } else { + /* see if otp provides something in tp's conflict list */ + PMList *m; + for(m = otp->provides; m; m = m->next) { + if(!strcmp(m->data, j->data)) { + conflict = 1; + break; + } + } + } + if(conflict) { MALLOC(miss, sizeof(depmissing_t)); miss->type = CONFLICT; miss->depend.mod = DEP_ANY; miss->depend.version[0] = '\0'; strncpy(miss->target, tp->name, 256); - strncpy(miss->depend.name, a->name, 256); + strncpy(miss->depend.name, otp->name, 256); if(!list_isin(baddeps, miss)) { baddeps = list_add(baddeps, miss); } @@ -2703,7 +2790,24 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets) rewinddir(db->dir); while((info = db_scan(db, NULL, INFRQ_DESC | INFRQ_DEPENDS)) != NULL) { for(j = info->conflicts; j; j = j->next) { + int conflict = 0; + if(!strcmp(info->name, tp->name)) { + /* a package cannot conflict with itself -- that's just not nice */ + continue; + } if(!strcmp((char*)j->data, tp->name)) { + conflict = 1; + } else { + /* see if tp provides something in info's conflict list */ + PMList *m; + for(m = tp->provides; m; m = m->next) { + if(!strcmp(m->data, j->data)) { + conflict = 1; + break; + } + } + } + if(conflict) { MALLOC(miss, sizeof(depmissing_t)); miss->type = CONFLICT; miss->depend.mod = DEP_ANY; @@ -3015,7 +3119,7 @@ int parseargs(int op, int argc, char **argv) case 'h': pmo_help = 1; break; case 'V': pmo_version = 1; break; case 'b': strcpy(pmo_dbpath, optarg); break; - case 'c': pmo_s_clean = 1; pmo_r_cascade = 1; break; + case 'c': pmo_s_clean++; pmo_r_cascade = 1; break; case 'd': pmo_nodeps = 1; break; case 'e': pmo_q_orphans = 1; break; case 'f': pmo_force = 1; break; @@ -3030,7 +3134,7 @@ int parseargs(int op, int argc, char **argv) perror("bad root path"); return(1); } break; - case 's': pmo_s_search = 1; pmo_r_recurse = 1; break; + case 's': pmo_s_search = 1; pmo_q_search = 1; pmo_r_recurse = 1; break; case 'u': pmo_s_upgrade = 1; break; case 'v': pmo_verbose = 1; break; case 'w': pmo_s_downloadonly = 1; break; @@ -3317,20 +3421,21 @@ void usage(int op, char *myname) printf(" -o, --owns query the package that owns \n"); printf(" -p, --file pacman will query the package file [package] instead of\n"); printf(" looking in the database\n"); + printf(" -s, --search search locally-installed packages for matching strings\n"); } else if(op == PM_SYNC) { printf("usage: %s {-S --sync} [options] [package]\n", myname); printf("options:\n"); - printf(" -c, --clean remove packages from cache directory to free up diskspace\n"); + printf(" -c, --clean remove old packages from cache directory (use -cc for all)\n"); printf(" -d, --nodeps skip dependency checks\n"); printf(" -f, --force force install, overwrite conflicting files\n"); printf(" -g, --groups view all members of a package group\n"); printf(" -i, --info view package information\n"); printf(" -l, --list list all packages belonging to the specified repository\n"); printf(" -p, --print-uris print out download URIs for each package to be installed\n"); - printf(" -s, --search search sync database for matching strings\n"); + printf(" -s, --search search remote repositories for matching strings\n"); 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 a fresh package sync database from the server\n"); + printf(" -y, --refresh download fresh package databases from the server\n"); } printf(" -v, --verbose be verbose\n"); printf(" -r, --root set an alternate installation root\n"); diff --git a/src/pacman.h b/src/pacman.h index 3bc7eb3b..bc8e530e 100644 --- a/src/pacman.h +++ b/src/pacman.h @@ -22,7 +22,7 @@ #define _PAC_PACMAN_H #ifndef PACVER -#define PACVER "2.7.7" +#define PACVER "2.7.8" #endif #ifndef PKGDIR @@ -33,6 +33,10 @@ #define PACCONF "etc/pacman.conf" #endif +#ifndef CACHEDIR +#define CACHEDIR "var/cache/pacman/pkg" +#endif + /* Operations */ #define PM_MAIN 1 #define PM_ADD 2 diff --git a/src/pacsync.c b/src/pacsync.c index 0c41f543..d1045a63 100644 --- a/src/pacsync.c +++ b/src/pacsync.c @@ -182,6 +182,7 @@ int downloadfiles(PMList *servers, const char *localpath, PMList *files) if(pmo_xfercommand) { int ret; + int usepart = 0; char *ptr1, *ptr2; char origCmd[PATH_MAX]; char parsedCmd[PATH_MAX] = ""; @@ -190,9 +191,22 @@ int downloadfiles(PMList *servers, const char *localpath, PMList *files) /* build the full download url */ snprintf(url, PATH_MAX, "%s://%s%s%s", server->protocol, server->server, server->path, fn); - /* replace all occurrences of %u with the download URL */ + /* replace all occurrences of %o with fn.part */ strncpy(origCmd, pmo_xfercommand, sizeof(origCmd)); ptr1 = origCmd; + while((ptr2 = strstr(ptr1, "%o"))) { + usepart = 1; + ptr2[0] = '\0'; + strcat(parsedCmd, ptr1); + strcat(parsedCmd, fn); + strcat(parsedCmd, ".part"); + ptr1 = ptr2 + 2; + } + strcat(parsedCmd, ptr1); + /* replace all occurrences of %u with the download URL */ + strncpy(origCmd, parsedCmd, sizeof(origCmd)); + parsedCmd[0] = '\0'; + ptr1 = origCmd; while((ptr2 = strstr(ptr1, "%u"))) { ptr2[0] = '\0'; strcat(parsedCmd, ptr1); @@ -214,11 +228,16 @@ int downloadfiles(PMList *servers, const char *localpath, PMList *files) return(1); } else if(ret != 0) { /* download failed */ - vprint("XferCommand command returned non-zero status code (%d)\n", - WEXITSTATUS(ret)); + vprint("XferCommand command returned non-zero status code (%d)\n", ret); } else { /* download was successful */ complete = list_add(complete, fn); + if(usepart) { + char fnpart[PATH_MAX]; + /* rename "output.part" file to "output" file */ + snprintf(fnpart, PATH_MAX, "%s.part", fn); + rename(fnpart, fn); + } } chdir(cwd); } else { @@ -337,7 +356,7 @@ int downloadfiles(PMList *servers, const char *localpath, PMList *files) for(j = strlen(out); j < maxcols-64; j++) { printf(" "); } - fputs("] 100% | LOCAL |", stdout); + fputs("] 100% LOCAL ", stdout); } else { log_progress(control, fsz-offset, &fsz); } @@ -351,9 +370,9 @@ int downloadfiles(PMList *servers, const char *localpath, PMList *files) } } if(!pmo_xfercommand) { - if(!strcmp(server->protocol, "ftp")) { + if(!strcmp(server->protocol, "ftp") && !pmo_proxyhost) { FtpQuit(control); - } else if(!strcmp(server->protocol, "http")) { + } else if(!strcmp(server->protocol, "http") || pmo_proxyhost) { HttpQuit(control); } } @@ -408,9 +427,9 @@ static int log_progress(netbuf *ctl, int xfered, void *arg) (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); + 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); + printf("] %3d%% %6dK %6.1fK/s %02d:%02d:%02d\r", pct, ((xfered+offset) / 1024), rate, eta_h, eta_m, eta_s); } fflush(stdout); return(1); -- cgit v1.2.3-24-g4f1b