Imported from pacman-2.9.3.tar.gz

This commit is contained in:
Judd Vinet 2004-12-19 03:37:00 +00:00
parent 4795965caf
commit f6b8ed22f4
18 changed files with 735 additions and 160 deletions

View file

@ -1,5 +1,13 @@
VERSION DESCRIPTION VERSION DESCRIPTION
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
2.9.3 - fixed a couple manpage typos
- added --ignore to -S operations, works just like IgnorePkg
- respect IgnorePkg list when pulling in dependencies
- numerous memleak fixes
- some code changes to improve customizability/branding
- Makefile fix for nonstandard lib search paths (Kevin Piche)
- fixed the leftover directories in /tmp
- speed improvement patches from Tommi Rantala
2.9.2 - bugfix for 2.9.1 2.9.2 - bugfix for 2.9.1
2.9.1 - --refresh now only downloads fresh packages lists if they've 2.9.1 - --refresh now only downloads fresh packages lists if they've
been updated (currently only works with FTP) been updated (currently only works with FTP)

View file

@ -34,7 +34,7 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@ INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
PACVER = 2.9.2 PACVER = 2.9.3
TOPDIR = @srcdir@ TOPDIR = @srcdir@
SRCDIR = $(TOPDIR)/src/ SRCDIR = $(TOPDIR)/src/
@ -55,6 +55,7 @@ SRCS = $(SRCDIR)pacman.c \
$(SRCDIR)pacsync.c \ $(SRCDIR)pacsync.c \
$(SRCDIR)md5.c \ $(SRCDIR)md5.c \
$(SRCDIR)md5driver.c \ $(SRCDIR)md5driver.c \
$(SRCDIR)strhash.c \
$(SRCDIR)vercmp.c \ $(SRCDIR)vercmp.c \
$(SRCDIR)rpmvercmp.c $(SRCDIR)rpmvercmp.c
@ -66,6 +67,7 @@ OBJECTS = $(OBJDIR)pacman.o \
$(OBJDIR)pacsync.o \ $(OBJDIR)pacsync.o \
$(OBJDIR)md5.o \ $(OBJDIR)md5.o \
$(OBJDIR)md5driver.o \ $(OBJDIR)md5driver.o \
$(OBJDIR)strhash.o \
$(OBJDIR)rpmvercmp.o $(OBJDIR)rpmvercmp.o
all: libftp.a pacman vercmp convertdb man all: libftp.a pacman vercmp convertdb man
@ -78,7 +80,7 @@ vercmp: $(OBJDIR)vercmp.o $(OBJDIR)rpmvercmp.o
$(CXX) $(OBJDIR)vercmp.o $(OBJDIR)rpmvercmp.o $(CXXFLAGS) -o $@ $(CXX) $(OBJDIR)vercmp.o $(OBJDIR)rpmvercmp.o $(CXXFLAGS) -o $@
convertdb: $(OBJDIR)convertdb.o $(OBJDIR)list.o $(OBJDIR)util.o convertdb: $(OBJDIR)convertdb.o $(OBJDIR)list.o $(OBJDIR)util.o
$(CXX) $(OBJDIR)convertdb.o $(OBJDIR)list.o $(OBJDIR)util.o $(CXXFLAGS) -lz -ltar -o $@ $(CXX) $(OBJDIR)convertdb.o $(OBJDIR)list.o $(OBJDIR)util.o $(LDFLAGS) -o $@
.c.o: $(SRCS) .c.o: $(SRCS)
$(CXX) $(CXXFLAGS) -o $@ -c $< $(CXX) $(CXXFLAGS) -o $@ -c $<

View file

@ -60,7 +60,7 @@ installed and there are no package conflicts in the system. This
switch disables these checks. switch disables these checks.
.TP .TP
.B "\-f, \-\-force" .B "\-f, \-\-force"
Bypass file conflict checks,, overwriting conflicting files. If the Bypass file conflict checks, overwriting conflicting files. If the
package that is about to be installed contains files that are already package that is about to be installed contains files that are already
installed, this option will cause all those files to be overwritten. installed, this option will cause all those files to be overwritten.
This option should be used with care, ideally not at all. This option should be used with care, ideally not at all.
@ -147,9 +147,9 @@ removed.
.TP .TP
.B "\-s, \-\-recursive" .B "\-s, \-\-recursive"
For each target specified, remove it and all its dependencies, provided For each target specified, remove it and all its dependencies, provided
that (A) they are not required by other packages; and (B) they were that (A) they are not required by other packages; and (B) they were not
explicitly installed by the user and not pulled in as a dependency for explicitly installed by the user.
other packages. This option is analagous to a backwards --sync operation. This option is analagous to a backwards --sync operation.
.SH QUERY OPTIONS .SH QUERY OPTIONS
.TP .TP
.B "\-e, \-\-orphans" .B "\-e, \-\-orphans"

View file

@ -134,6 +134,8 @@ db_write_entry()
done done
echo "" >>depends echo "" >>depends
fi fi
# preserve the modification time
touch -r $1 desc depends
} }
if [ $# -lt 2 ]; then if [ $# -lt 2 ]; then

View file

@ -463,6 +463,7 @@ if [ "$GENMD5" = "0" ]; then
# extract sources # extract sources
msg "Extracting Sources..." msg "Extracting Sources..."
for netfile in ${source[@]}; do for netfile in ${source[@]}; do
unziphack=0
file=`strip_url $netfile` file=`strip_url $netfile`
unset cmd unset cmd
case $file in case $file in
@ -473,6 +474,7 @@ if [ "$GENMD5" = "0" ]; then
*.tar) *.tar)
cmd="tar -xf $file" ;; cmd="tar -xf $file" ;;
*.zip) *.zip)
unziphack=1
cmd="unzip -qqo $file" ;; cmd="unzip -qqo $file" ;;
*.gz) *.gz)
cmd="gunzip $file" ;; cmd="gunzip $file" ;;
@ -483,9 +485,12 @@ if [ "$GENMD5" = "0" ]; then
msg " $cmd" msg " $cmd"
$cmd $cmd
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
error "Failed to extract $file" # unzip will return a 1 as a warning, it is not an error
msg "Aborting..." if [ "$unziphack" != "1" -o $? -ne 1 ]; then
exit 1 error "Failed to extract $file"
msg "Aborting..."
exit 1
fi
fi fi
fi fi
done done

View file

@ -28,15 +28,17 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include "pacconf.h"
#include "list.h" #include "list.h"
#include "util.h" #include "util.h"
unsigned short pmo_verbose = 0;
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
FILE* db = NULL; FILE* db = NULL;
FILE* fp = NULL; FILE* fp = NULL;
char* ptr = NULL; char* ptr = NULL;
char* dbdir = "/var/lib/pacman/pacman.db";
char name[256]; char name[256];
char ver[256]; char ver[256];
char line[PATH_MAX+1]; char line[PATH_MAX+1];
@ -44,6 +46,9 @@ int main(int argc, char* argv[])
char path[PATH_MAX+1]; char path[PATH_MAX+1];
mode_t oldumask; mode_t oldumask;
struct stat buf; struct stat buf;
char dbdir[PATH_MAX];
sprintf(dbdir, "/%s", PACDBDIR);
if(argc < 2) { if(argc < 2) {
printf("converts a pacman 1.x database to a pacman 2.0 format\n"); printf("converts a pacman 1.x database to a pacman 2.0 format\n");

127
src/db.c
View file

@ -29,6 +29,7 @@
#include <libgen.h> #include <libgen.h>
#include <unistd.h> #include <unistd.h>
#include "package.h" #include "package.h"
#include "strhash.h"
#include "util.h" #include "util.h"
#include "db.h" #include "db.h"
@ -131,26 +132,63 @@ pkginfo_t* db_scan(pacdb_t *db, char *target, unsigned int inforeq)
struct dirent *ent = NULL; struct dirent *ent = NULL;
struct stat sbuf; struct stat sbuf;
char path[PATH_MAX]; char path[PATH_MAX];
char name[256]; int path_len = 0;
char *name = NULL;
char *ptr = NULL; char *ptr = NULL;
int found = 0; int found = 0;
/* hash table for caching directory names */
static strhash_t* htable = NULL;
if (!htable)
htable = new_strhash(951);
snprintf(path, PATH_MAX, "%s/", db->path);
path_len = strlen(path);
if(target != NULL) { if(target != NULL) {
/* search for a specific package (by name only) */ /* search for a specific package (by name only) */
/* See if we have the path cached. */
strcat(path, target);
if (strhash_isin(htable, path)) {
struct dirent* pkgdir;
pkginfo_t* pkg;
/* db_read() wants 'struct dirent' so lets give it one.
* Actually it only uses the d_name field. */
MALLOC(pkgdir, sizeof(struct dirent));
strcpy(pkgdir->d_name, strhash_get(htable, path));
pkg = db_read(db, pkgdir, inforeq);
FREE(pkgdir);
return pkg;
}
path[path_len] = '\0';
/* OK the entry was not in cache, so lets look for it manually. */
rewinddir(db->dir); rewinddir(db->dir);
ent = readdir(db->dir); ent = readdir(db->dir);
while(!found && ent != NULL) { while(!found && ent != NULL) {
if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {
ent = readdir(db->dir); ent = readdir(db->dir);
continue; continue;
} }
strncpy(name, ent->d_name, 255);
/* stat the entry, make sure it's a directory */ /* stat the entry, make sure it's a directory */
snprintf(path, PATH_MAX, "%s/%s", db->path, name); path[path_len] = '\0';
strncat(path, ent->d_name, PATH_MAX - path_len);
if(stat(path, &sbuf) || !S_ISDIR(sbuf.st_mode)) { if(stat(path, &sbuf) || !S_ISDIR(sbuf.st_mode)) {
ent = readdir(db->dir); ent = readdir(db->dir);
continue; continue;
} }
name = path + path_len;
/* truncate the string at the second-to-last hyphen, */ /* truncate the string at the second-to-last hyphen, */
/* which will give us the package name */ /* which will give us the package name */
if((ptr = rindex(name, '-'))) { if((ptr = rindex(name, '-'))) {
@ -176,8 +214,11 @@ pkginfo_t* db_scan(pacdb_t *db, char *target, unsigned int inforeq)
if(ent == NULL) { if(ent == NULL) {
return(NULL); return(NULL);
} }
/* stat the entry, make sure it's a directory */ /* stat the entry, make sure it's a directory */
snprintf(path, PATH_MAX, "%s/%s", db->path, ent->d_name); path[path_len] = '\0';
strncat(path, ent->d_name, PATH_MAX - path_len);
if(!stat(path, &sbuf) && S_ISDIR(sbuf.st_mode)) { if(!stat(path, &sbuf) && S_ISDIR(sbuf.st_mode)) {
isdir = 1; isdir = 1;
} }
@ -185,6 +226,25 @@ pkginfo_t* db_scan(pacdb_t *db, char *target, unsigned int inforeq)
isdir = 0; isdir = 0;
continue; continue;
} }
name = path + path_len;
if((ptr = rindex(name, '-'))) {
*ptr = '\0';
}
if((ptr = rindex(name, '-'))) {
*ptr = '\0';
}
/* Add entries like:
*
* key: /var/lib/pacman/extra/xrally
* data: xrally-1.1.1-1
*/
if (!strhash_isin(htable, path)) {
strhash_add(htable, strdup(path), strdup(ent->d_name));
}
} }
} }
return(db_read(db, ent, inforeq)); return(db_read(db, ent, inforeq));
@ -603,6 +663,28 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root)
char *str = NULL; char *str = NULL;
struct stat buf, buf2; struct stat buf, buf2;
PMList *conflicts = NULL; PMList *conflicts = NULL;
strhash_t** htables;
int target_num = 0;
int d = 0;
int e = 0;
/* Create and initialise an array of hash tables.
*
* htables [ 0 ... target_num ] : targets' files
* htables [ target_num ] : used later
*/
target_num = list_count(targets);
MALLOC(htables, (target_num+1) * sizeof(strhash_t*));
for(d = 0, i = targets; i; i = i->next, d++) {
htables[d] = new_strhash(151);
strhash_add_list(htables[d], ((pkginfo_t*)i->data)->files);
}
htables[target_num] = new_strhash(151);
/* CHECK 1: check every db package against every target package */ /* CHECK 1: check every db package against every target package */
/* XXX: I've disabled the database-against-targets check for now, as the /* XXX: I've disabled the database-against-targets check for now, as the
@ -613,34 +695,30 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root)
pkginfo_t *info = NULL; pkginfo_t *info = NULL;
char *dbstr = NULL; char *dbstr = NULL;
rewinddir(db->dir); rewinddir(db->dir);
while((info = db_scan(db, NULL, INFRQ_DESC | INFRQ_FILES)) != NULL) { while((info = db_scan(db, NULL, INFRQ_DESC | INFRQ_FILES)) != NULL) {
for(i = info->files; i; i = i->next) { for(i = info->files; i; i = i->next) {
if(i->data == NULL) continue;
dbstr = (char*)i->data; dbstr = (char*)i->data;
for(j = targets; j; j = j->next) {
if(dbstr == NULL || rindex(dbstr, '/') == dbstr+strlen(dbstr)-1)
continue;
for(d = 0, j = targets; j; j = j->next, d++) {
pkginfo_t *targ = (pkginfo_t*)j->data; pkginfo_t *targ = (pkginfo_t*)j->data;
if(strcmp(info->name, targ->name)) { if(strcmp(info->name, targ->name) && strhash_isin(htables[d], dbstr)) {
for(k = targ->files; k; k = k->next) { MALLOC(str, 512);
filestr = (char*)k->data; snprintf(str, 512, "%s: exists in \"%s\" (target) and \"%s\" (installed)", dbstr,
if(!strcmp(dbstr, filestr)) { targ->name, info->name);
if(rindex(k->data, '/') == filestr+strlen(filestr)-1) { conflicts = list_add(conflicts, str);
continue;
}
MALLOC(str, 512);
snprintf(str, 512, "%s: exists in \"%s\" (target) and \"%s\" (installed)", dbstr,
targ->name, info->name);
conflicts = list_add(conflicts, str);
}
}
} }
} }
} }
}*/ }*/
/* CHECK 2: check every target against every target */ /* CHECK 2: check every target against every target */
for(i = targets; i; i = i->next) { for(d = 0, i = targets; i; i = i->next, d++) {
pkginfo_t *p1 = (pkginfo_t*)i->data; pkginfo_t *p1 = (pkginfo_t*)i->data;
for(j = i; j; j = j->next) { for(e = d, j = i; j; j = j->next, e++) {
pkginfo_t *p2 = (pkginfo_t*)j->data; pkginfo_t *p2 = (pkginfo_t*)j->data;
if(strcmp(p1->name, p2->name)) { if(strcmp(p1->name, p2->name)) {
for(k = p1->files; k; k = k->next) { for(k = p1->files; k; k = k->next) {
@ -652,7 +730,7 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root)
/* this filename has a trailing '/', so it's a directory -- skip it. */ /* this filename has a trailing '/', so it's a directory -- skip it. */
continue; continue;
} }
if(is_in(filestr, p2->files)) { if(strhash_isin(htables[e], filestr)) {
MALLOC(str, 512); MALLOC(str, 512);
snprintf(str, 512, "%s: exists in \"%s\" (target) and \"%s\" (target)", snprintf(str, 512, "%s: exists in \"%s\" (target) and \"%s\" (target)",
filestr, p1->name, p2->name); filestr, p1->name, p2->name);
@ -674,8 +752,11 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root)
int ok = 0; int ok = 0;
if(dbpkg == NULL) { if(dbpkg == NULL) {
dbpkg = db_scan(db, p->name, INFRQ_DESC | INFRQ_FILES); dbpkg = db_scan(db, p->name, INFRQ_DESC | INFRQ_FILES);
if(dbpkg)
strhash_add_list(htables[target_num], dbpkg->files);
} }
if(dbpkg && is_in(j->data, dbpkg->files)) { if(dbpkg && strhash_isin(htables[target_num], filestr)) {
ok = 1; ok = 1;
} }
/* Make sure that the supposedly-conflicting file is not actually just /* Make sure that the supposedly-conflicting file is not actually just

View file

@ -23,8 +23,32 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <assert.h>
#include "list.h" #include "list.h"
/* 1: List seems to be OK.
* 0: We're in deep ...
*/
int CheckList(PMList* list)
{
PMList* it = NULL;
if (list == NULL)
return 1;
if (list->last == NULL)
return 0;
for (it = list; it && it->next; it = it->next)
;
if (it != list->last)
return 0;
return 1;
}
PMList* list_new() PMList* list_new()
{ {
PMList *list = NULL; PMList *list = NULL;
@ -36,6 +60,7 @@ PMList* list_new()
list->data = NULL; list->data = NULL;
list->prev = NULL; list->prev = NULL;
list->next = NULL; list->next = NULL;
list->last = list;
return(list); return(list);
} }
@ -62,6 +87,8 @@ PMList* list_add(PMList *list, void *data)
ptr = list; ptr = list;
if(ptr == NULL) { if(ptr == NULL) {
ptr = list_new(); ptr = list_new();
if (!ptr)
return(NULL);
} }
lp = list_last(ptr); lp = list_last(ptr);
@ -73,12 +100,67 @@ PMList* list_add(PMList *list, void *data)
return(NULL); return(NULL);
} }
lp->next->prev = lp; lp->next->prev = lp;
lp->last = NULL;
lp = lp->next; lp = lp->next;
} }
lp->data = data; lp->data = data;
ptr->last = lp;
return(ptr); return(ptr);
} }
/* list: the beginning of the list
* item: the item in the list to be removed
*
* returns:
* list with item removed
*/
PMList* list_remove(PMList* list, PMList* item)
{
assert(CheckList(list));
if (list == NULL || item == NULL)
return NULL;
/* Remove first item in list. */
if (item == list) {
if (list->next == NULL) { /* Only item in list. */
list_free(item);
return NULL;
} else {
list->next->prev = NULL;
list->next->last = list->last;
list = list->next;
item->prev = item->next = NULL;
list_free(item);
return list;
}
}
/* Remove last item in list. */
if (list->last == item) {
list->last = item->prev;
item->prev->next = NULL;
item->prev = item->next = NULL;
list_free(item);
return list;
}
/* Remove middle item in list. */
assert(item->prev != NULL &&
item->next != NULL);
item->prev->next = item->next;
item->next->prev = item->prev;
item->prev = item->next = NULL;
list_free(item);
assert(CheckList(list));
return list;
}
int list_count(PMList *list) int list_count(PMList *list)
{ {
int i; int i;
@ -141,10 +223,11 @@ PMList* list_merge(PMList *one, PMList *two)
PMList* list_last(PMList *list) PMList* list_last(PMList *list)
{ {
PMList *ptr; if (list == NULL)
return NULL;
for(ptr = list; ptr && ptr->next; ptr = ptr->next); assert(list->last != NULL);
return(ptr); return list->last;
} }
/* Helper function for sorting a list of strings /* Helper function for sorting a list of strings
@ -257,10 +340,23 @@ PMList* list_add_sorted(PMList *list, void *data, cmp_fn sortfunc)
/* Insert node before insertion point. */ /* Insert node before insertion point. */
add->prev = prev; add->prev = prev;
add->next = iter; add->next = iter;
if(iter != NULL) iter->prev = add; /* Not at end. */
if(iter != NULL) {
iter->prev = add; /* Not at end. */
} else {
if (list != NULL)
list->last = add; /* Added new to end, so update the link to last. */
}
if(prev != NULL) { if(prev != NULL) {
prev->next = add; /* In middle. */ prev->next = add; /* In middle. */
} else { } else {
if (list == NULL) {
add->last = add;
} else {
add->last = list->last;
list->last = NULL;
}
list = add; /* Start or empty, new list head. */ list = add; /* Start or empty, new list head. */
} }

View file

@ -28,6 +28,7 @@ typedef struct __pmlist_t {
void* data; void* data;
struct __pmlist_t* prev; struct __pmlist_t* prev;
struct __pmlist_t* next; struct __pmlist_t* next;
struct __pmlist_t* last; /* Quick access to last item in list */
} PMList; } PMList;
@ -38,6 +39,7 @@ typedef int (*cmp_fn) (const void *, const void *);
PMList* list_new(); PMList* list_new();
void list_free(PMList* list); void list_free(PMList* list);
PMList* list_add(PMList* list, void* data); PMList* list_add(PMList* list, void* data);
PMList* list_remove(PMList* list, PMList* item);
int list_count(PMList* list); int list_count(PMList* list);
int list_isin(PMList *haystack, void *needle); int list_isin(PMList *haystack, void *needle);
PMList* is_in(char *needle, PMList *haystack); PMList* is_in(char *needle, PMList *haystack);

46
src/pacconf.h Normal file
View file

@ -0,0 +1,46 @@
/*
* pacconf.h
*
* Copyright (c) 2002-2004 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef _PAC_PACCONF_H
#define _PAC_PACCONF_H
#ifndef PACVER
#define PACVER "2.9.3"
#endif
#ifndef PACDBDIR
#define PACDBDIR "var/lib/pacman"
#endif
#ifndef PKGEXT
#define PKGEXT ".pkg.tar.gz"
#endif
#ifndef PACCONF
#define PACCONF "/etc/pacman.conf"
#endif
#ifndef CACHEDIR
#define CACHEDIR "var/cache/pacman/pkg"
#endif
#endif /* PACCONF_H */
/* vim: set ts=2 sw=2 noet: */

View file

@ -27,6 +27,7 @@
#include <string.h> #include <string.h>
#include <libtar.h> #include <libtar.h>
#include <zlib.h> #include <zlib.h>
#include "pacconf.h"
#include "util.h" #include "util.h"
#include "package.h" #include "package.h"
@ -410,7 +411,7 @@ int split_pkgname(char *pkgfile, char *name, char *version)
} }
strncpy(tmp, p, 512); strncpy(tmp, p, 512);
/* trim file extension (if any) */ /* trim file extension (if any) */
if((p = strstr(tmp, ".pkg.tar.gz"))) { if((p = strstr(tmp, PKGEXT))) {
*p = 0; *p = 0;
} }

View file

@ -37,6 +37,7 @@
#include <libtar.h> #include <libtar.h>
#include <dirent.h> #include <dirent.h>
/* pacman */ /* pacman */
#include "pacconf.h"
#include "rpmvercmp.h" #include "rpmvercmp.h"
#include "md5.h" #include "md5.h"
#include "list.h" #include "list.h"
@ -52,35 +53,36 @@
*/ */
/* command line options */ /* command line options */
char *pmo_root = NULL; char *pmo_root = NULL;
unsigned short pmo_op = PM_MAIN; unsigned short pmo_op = PM_MAIN;
unsigned short pmo_verbose = 0; unsigned short pmo_verbose = 0;
unsigned short pmo_version = 0; unsigned short pmo_version = 0;
unsigned short pmo_help = 0; unsigned short pmo_help = 0;
unsigned short pmo_force = 0; unsigned short pmo_force = 0;
unsigned short pmo_nodeps = 0; unsigned short pmo_nodeps = 0;
unsigned short pmo_upgrade = 0; unsigned short pmo_upgrade = 0;
unsigned short pmo_freshen = 0; unsigned short pmo_freshen = 0;
unsigned short pmo_nosave = 0; unsigned short pmo_nosave = 0;
unsigned short pmo_noconfirm = 0; unsigned short pmo_noconfirm = 0;
unsigned short pmo_d_vertest = 0; unsigned short pmo_d_vertest = 0;
unsigned short pmo_d_resolve = 0; unsigned short pmo_d_resolve = 0;
unsigned short pmo_q_isfile = 0; unsigned short pmo_q_isfile = 0;
unsigned short pmo_q_info = 0; unsigned short pmo_q_info = 0;
unsigned short pmo_q_list = 0; unsigned short pmo_q_list = 0;
unsigned short pmo_q_orphans = 0; unsigned short pmo_q_orphans = 0;
unsigned short pmo_q_owns = 0; unsigned short pmo_q_owns = 0;
unsigned short pmo_q_search = 0; unsigned short pmo_q_search = 0;
unsigned short pmo_r_cascade = 0; unsigned short pmo_r_cascade = 0;
unsigned short pmo_r_dbonly = 0; unsigned short pmo_r_dbonly = 0;
unsigned short pmo_r_recurse = 0; unsigned short pmo_r_recurse = 0;
unsigned short pmo_s_upgrade = 0; unsigned short pmo_s_upgrade = 0;
unsigned short pmo_s_downloadonly = 0; unsigned short pmo_s_downloadonly = 0;
unsigned short pmo_s_printuris = 0; unsigned short pmo_s_printuris = 0;
unsigned short pmo_s_sync = 0; unsigned short pmo_s_sync = 0;
unsigned short pmo_s_search = 0; unsigned short pmo_s_search = 0;
unsigned short pmo_s_clean = 0; unsigned short pmo_s_clean = 0;
unsigned short pmo_group = 0; PMList *pmo_s_ignore = NULL;
unsigned short pmo_group = 0;
/* configuration file options */ /* configuration file options */
char *pmo_dbpath = NULL; char *pmo_dbpath = NULL;
char *pmo_configfile = NULL; char *pmo_configfile = NULL;
@ -91,6 +93,7 @@ char *pmo_xfercommand = NULL;
PMList *pmo_noupgrade = NULL; PMList *pmo_noupgrade = NULL;
PMList *pmo_ignorepkg = NULL; PMList *pmo_ignorepkg = NULL;
PMList *pmo_holdpkg = NULL; PMList *pmo_holdpkg = NULL;
unsigned short pmo_chomp = 0;
unsigned short pmo_usesyslog = 0; unsigned short pmo_usesyslog = 0;
unsigned short pmo_nopassiveftp = 0; unsigned short pmo_nopassiveftp = 0;
@ -132,7 +135,7 @@ int main(int argc, char *argv[])
strcpy(pmo_root, "/"); strcpy(pmo_root, "/");
/* default dbpath */ /* default dbpath */
MALLOC(pmo_dbpath, PATH_MAX); MALLOC(pmo_dbpath, PATH_MAX);
strcpy(pmo_dbpath, PKGDIR); strcpy(pmo_dbpath, PACDBDIR);
/* default configuration file */ /* default configuration file */
MALLOC(pmo_configfile, PATH_MAX); MALLOC(pmo_configfile, PATH_MAX);
strcpy(pmo_configfile, PACCONF); strcpy(pmo_configfile, PACCONF);
@ -152,6 +155,9 @@ int main(int argc, char *argv[])
myuid = 99; myuid = 99;
} }
/* change to / so we can avoid having our CWD removed from under us */
chdir("/");
/* check for permission */ /* check for permission */
pm_access = READ_ONLY; pm_access = READ_ONLY;
if(pmo_op != PM_MAIN && pmo_op != PM_QUERY && pmo_op != PM_DEPTEST) { if(pmo_op != PM_MAIN && pmo_op != PM_QUERY && pmo_op != PM_DEPTEST) {
@ -343,9 +349,12 @@ int pacman_sync(pacdb_t *db, PMList *targets)
PMList *cache = NULL; PMList *cache = NULL;
PMList *clean = NULL; PMList *clean = NULL;
PMList *i, *j; PMList *i, *j;
char dirpath[PATH_MAX];
snprintf(dirpath, PATH_MAX, "%s%s", pmo_root, CACHEDIR);
printf("removing old packages from cache... "); printf("removing old packages from cache... ");
dir = opendir("/var/cache/pacman/pkg"); dir = opendir(dirpath);
if(dir == NULL) { if(dir == NULL) {
fprintf(stderr, "error: could not access cache directory\n"); fprintf(stderr, "error: could not access cache directory\n");
return(1); return(1);
@ -361,14 +370,15 @@ int pacman_sync(pacdb_t *db, PMList *targets)
for(i = cache; i; i = i->next) { for(i = cache; i; i = i->next) {
char *str = (char *)i->data; char *str = (char *)i->data;
char name[256], version[64]; char pkgpart[256], name[256], version[64];
if(strstr(str, ".pkg.tar.gz") == NULL) { if(strstr(str, PKGEXT) == NULL) {
clean = list_add(clean, strdup(str)); clean = list_add(clean, strdup(str));
continue; continue;
} }
snprintf(pkgpart, sizeof(pkgpart), "%s.part", PKGEXT);
/* we keep partially downloaded files */ /* we keep partially downloaded files */
if(strstr(str, ".pkg.tar.gz.part")) { if(strstr(str, pkgpart)) {
continue; continue;
} }
if(split_pkgname(str, name, version) != 0) { if(split_pkgname(str, name, version) != 0) {
@ -379,10 +389,10 @@ int pacman_sync(pacdb_t *db, PMList *targets)
char *s = (char *)j->data; char *s = (char *)j->data;
char n[256], v[64]; char n[256], v[64];
if(strstr(s, ".pkg.tar.gz") == NULL) { if(strstr(s, PKGEXT) == NULL) {
continue; continue;
} }
if(strstr(s, ".pkg.tar.gz.part")) { if(strstr(s, pkgpart)) {
continue; continue;
} }
if(split_pkgname(s, n, v) != 0) { if(split_pkgname(s, n, v) != 0) {
@ -617,7 +627,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
for(m = pm_packages; m; m = m->next) { for(m = pm_packages; m; m = m->next) {
pkginfo_t *p = (pkginfo_t*)m->data; pkginfo_t *p = (pkginfo_t*)m->data;
if(!strcmp(k->data, p->name)) { if(!strcmp(k->data, p->name)) {
if(is_in(p->name, pmo_ignorepkg)) { if(is_in(p->name, pmo_ignorepkg) || is_in(p->name, pmo_s_ignore)) {
fprintf(stderr, ":: %s-%s: ignoring package upgrade (to be replaced by %s-%s)\n", fprintf(stderr, ":: %s-%s: ignoring package upgrade (to be replaced by %s-%s)\n",
p->name, p->version, pkg->name, pkg->version); p->name, p->version, pkg->name, pkg->version);
ignore = 1; ignore = 1;
@ -684,8 +694,8 @@ int pacman_sync(pacdb_t *db, PMList *targets)
cmp = rpmvercmp(local->version, sync->pkg->version); cmp = rpmvercmp(local->version, sync->pkg->version);
if(cmp > 0 && !sync->pkg->force) { if(cmp > 0 && !sync->pkg->force) {
/* local version is newer */ /* local version is newer */
fprintf(stderr, ":: %s-%s: local version is newer\n", fprintf(stderr, ":: %s: local version (%s) is newer than repo version (%s)\n",
local->name, local->version); local->name, local->version, sync->pkg->version);
newer = 1; newer = 1;
FREE(sync); FREE(sync);
continue; continue;
@ -693,7 +703,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
/* versions are identical */ /* versions are identical */
FREE(sync); FREE(sync);
continue; continue;
} else if(is_in((char*)i->data, pmo_ignorepkg)) { } else if(is_in((char*)i->data, pmo_ignorepkg) || is_in((char*)i->data, pmo_s_ignore)) {
/* package should be ignored (IgnorePkg) */ /* package should be ignored (IgnorePkg) */
fprintf(stderr, ":: %s-%s: ignoring package upgrade (%s)\n", fprintf(stderr, ":: %s-%s: ignoring package upgrade (%s)\n",
local->name, local->version, sync->pkg->version); local->name, local->version, sync->pkg->version);
@ -780,8 +790,13 @@ int pacman_sync(pacdb_t *db, PMList *targets)
if(sync->pkg == NULL) { if(sync->pkg == NULL) {
found = 0; found = 0;
} }
/* this package was explicitly requested */ if(pmo_d_resolve) {
sync->pkg->reason = REASON_EXPLICIT; /* looks like we're being called from 'makepkg -s' so these are all deps */
sync->pkg->reason = REASON_DEPEND;
} else {
/* this package was explicitly requested */
sync->pkg->reason = REASON_EXPLICIT;
}
} }
} }
} }
@ -1132,7 +1147,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
PMList *processed = NULL; PMList *processed = NULL;
PMList *files = NULL; PMList *files = NULL;
snprintf(ldir, PATH_MAX, "%svar/cache/pacman/pkg", pmo_root); snprintf(ldir, PATH_MAX, "%s%s", pmo_root, CACHEDIR);
/* group sync records by repository and download */ /* group sync records by repository and download */
while(!done) { while(!done) {
@ -1153,17 +1168,17 @@ int pacman_sync(pacdb_t *db, PMList *targets)
char path[PATH_MAX]; char path[PATH_MAX];
if(pmo_s_printuris) { if(pmo_s_printuris) {
snprintf(path, PATH_MAX, "%s-%s.pkg.tar.gz", sync->pkg->name, sync->pkg->version); snprintf(path, PATH_MAX, "%s-%s%s", sync->pkg->name, sync->pkg->version, PKGEXT);
files = list_add(files, strdup(path)); files = list_add(files, strdup(path));
} else { } else {
snprintf(path, PATH_MAX, "%s/%s-%s.pkg.tar.gz", snprintf(path, PATH_MAX, "%s/%s-%s%s",
ldir, sync->pkg->name, sync->pkg->version); ldir, sync->pkg->name, sync->pkg->version, PKGEXT);
if(stat(path, &buf)) { if(stat(path, &buf)) {
/* file is not in the cache dir, so add it to the list */ /* file is not in the cache dir, so add it to the list */
snprintf(path, PATH_MAX, "%s-%s.pkg.tar.gz", sync->pkg->name, sync->pkg->version); snprintf(path, PATH_MAX, "%s-%s%s", sync->pkg->name, sync->pkg->version, PKGEXT);
files = list_add(files, strdup(path)); files = list_add(files, strdup(path));
} else { } else {
vprint(" %s-%s.pkg.tar.gz is already in the cache\n", sync->pkg->name, sync->pkg->version); vprint(" %s-%s%s is already in the cache\n", sync->pkg->name, sync->pkg->version, PKGEXT);
count++; count++;
} }
} }
@ -1235,7 +1250,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
char *md5sum1, *md5sum2; char *md5sum1, *md5sum2;
sync = (syncpkg_t*)i->data; sync = (syncpkg_t*)i->data;
snprintf(pkgname, PATH_MAX, "%s-%s.pkg.tar.gz", sync->pkg->name, sync->pkg->version); snprintf(pkgname, PATH_MAX, "%s-%s%s", sync->pkg->name, sync->pkg->version, PKGEXT);
md5sum1 = sync->pkg->md5sum; md5sum1 = sync->pkg->md5sum;
if(md5sum1 == NULL || md5sum1[0] == '\0') { if(md5sum1 == NULL || md5sum1[0] == '\0') {
@ -1327,7 +1342,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
syncpkg_t *sync = (syncpkg_t*)i->data; syncpkg_t *sync = (syncpkg_t*)i->data;
if(sync->pkg) { if(sync->pkg) {
MALLOC(str, PATH_MAX); MALLOC(str, PATH_MAX);
snprintf(str, PATH_MAX, "%s/%s-%s.pkg.tar.gz", ldir, sync->pkg->name, sync->pkg->version); snprintf(str, PATH_MAX, "%s/%s-%s%s", ldir, sync->pkg->name, sync->pkg->version, PKGEXT);
files = list_add(files, str); files = list_add(files, str);
if(sync->pkg->reason == REASON_DEPEND) { if(sync->pkg->reason == REASON_DEPEND) {
dependonly = list_add(dependonly, strdup(str)); dependonly = list_add(dependonly, strdup(str));
@ -1978,7 +1993,7 @@ int pacman_add(pacdb_t *db, PMList *targets, PMList *dependonly)
* or installed as a dependency for another package * or installed as a dependency for another package
*/ */
info->reason = REASON_EXPLICIT; info->reason = REASON_EXPLICIT;
if(is_in(file->data, dependonly)) { if(is_in(file->data, dependonly) || pmo_d_resolve) {
info->reason = REASON_DEPEND; info->reason = REASON_DEPEND;
} }
/* make an install date (in UTC) */ /* make an install date (in UTC) */
@ -2254,7 +2269,7 @@ int pacman_remove(pacdb_t *db, PMList *targets)
/* update dependency packages' REQUIREDBY fields */ /* update dependency packages' REQUIREDBY fields */
for(lp = info->depends; lp; lp = lp->next) { for(lp = info->depends; lp; lp = lp->next) {
PMList *last, *j; PMList *j;
if(splitdep((char*)lp->data, &depend)) { if(splitdep((char*)lp->data, &depend)) {
continue; continue;
@ -2280,17 +2295,9 @@ int pacman_remove(pacdb_t *db, PMList *targets)
} }
} }
/* splice out this entry from requiredby */ /* splice out this entry from requiredby */
last = list_last(depinfo->requiredby);
for(j = depinfo->requiredby; j; j = j->next) { for(j = depinfo->requiredby; j; j = j->next) {
if(!strcmp((char*)j->data, info->name)) { if(!strcmp((char*)j->data, info->name)) {
if(j == depinfo->requiredby) { depinfo->requiredby = list_remove(depinfo->requiredby, j);
depinfo->requiredby = j->next;
}
if(j->prev) j->prev->next = j->next;
if(j->next) j->next->prev = j->prev;
/* free the spliced node */
j->prev = j->next = NULL;
list_free(j);
break; break;
} }
} }
@ -2693,7 +2700,7 @@ int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *syncpkg, PMList *l
targ = list_add(targ, syncpkg->pkg); targ = list_add(targ, syncpkg->pkg);
deps = checkdeps(local, PM_ADD, targ); deps = checkdeps(local, PM_ADD, targ);
targ->data = NULL; targ->data = NULL;
list_free(targ); FREELIST(targ);
for(i = deps; i; i = i->next) { for(i = deps; i; i = i->next) {
int found = 0; int found = 0;
depmissing_t *miss = (depmissing_t*)i->data; depmissing_t *miss = (depmissing_t*)i->data;
@ -2737,7 +2744,7 @@ int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *syncpkg, PMList *l
sync->pkg->reason = REASON_DEPEND; sync->pkg->reason = REASON_DEPEND;
sync->dbs = dbs; sync->dbs = dbs;
} }
list_free(provides); FREELIST(provides);
} }
if(!found) { if(!found) {
fprintf(stderr, "error: cannot resolve dependencies for \"%s\":\n", miss->target); fprintf(stderr, "error: cannot resolve dependencies for \"%s\":\n", miss->target);
@ -2753,6 +2760,8 @@ int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *syncpkg, PMList *l
} }
if(found) { if(found) {
/* this dep is already in the target list */ /* this dep is already in the target list */
FREEPKG(sync->pkg);
FREE(sync);
continue; continue;
} }
vprint("resolving %s\n", sync->pkg->name); vprint("resolving %s\n", sync->pkg->name);
@ -2764,15 +2773,41 @@ int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *syncpkg, PMList *l
} }
} }
if(!found) { if(!found) {
list_add(trail, sync); /* check pmo_ignorepkg and pmo_s_ignore to make sure we haven't pulled in
if(resolvedeps(local, databases, sync, list, trail)) { * something we're not supposed to.
*/
int usedep = 1;
found = 0;
for(j = pmo_ignorepkg; j && !found; j = j->next) {
if(!strcmp(j->data, sync->pkg->name)) {
found = 1;
}
}
for(j = pmo_s_ignore; j && !found; j = j->next) {
if(!strcmp(j->data, sync->pkg->name)) {
found = 1;
}
}
if(found) {
usedep = yesno("%s requires %s, but it is in IgnorePkg. Install anyway? [Y/n] ",
miss->target, sync->pkg->name);
}
if(usedep) {
trail = list_add(trail, sync);
if(resolvedeps(local, databases, sync, list, trail)) {
return(1);
}
vprint("adding %s-%s\n", sync->pkg->name, sync->pkg->version);
list = list_add(list, sync);
} else {
fprintf(stderr, "error: cannot resolve dependencies for \"%s\"\n", miss->target);
return(1); return(1);
} }
vprint("adding %s-%s\n", sync->pkg->name, sync->pkg->version);
list_add(list, sync);
} else { } else {
/* cycle detected -- skip it */ /* cycle detected -- skip it */
vprint("dependency cycle detected: %s\n", sync->pkg->name); vprint("dependency cycle detected: %s\n", sync->pkg->name);
FREEPKG(sync->pkg);
FREE(sync);
} }
} }
} }
@ -2820,6 +2855,7 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
} }
if(is_pkgin(p, targets)) { if(is_pkgin(p, targets)) {
/* this package is also in the upgrade list, so don't worry about it */ /* this package is also in the upgrade list, so don't worry about it */
FREEPKG(p);
continue; continue;
} }
for(k = p->depends; k && !found; k = k->next) { for(k = p->depends; k && !found; k = k->next) {
@ -2836,9 +2872,11 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
PMList *provides = whatprovides(db, depend.name); PMList *provides = whatprovides(db, depend.name);
if(provides == NULL) { if(provides == NULL) {
/* not found */ /* not found */
FREEPKG(p);
continue; continue;
} }
/* we found an installed package that provides depend.name */ /* we found an installed package that provides depend.name */
FREELIST(provides);
} }
found = 0; found = 0;
if(depend.mod == DEP_ANY) { if(depend.mod == DEP_ANY) {
@ -2870,8 +2908,9 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
baddeps = list_add(baddeps, miss); baddeps = list_add(baddeps, miss);
} }
} }
FREEPKG(p);
} }
freepkg(oldpkg); FREEPKG(oldpkg);
} }
} }
if(op == PM_ADD || op == PM_UPGRADE) { if(op == PM_ADD || op == PM_UPGRADE) {
@ -2984,6 +3023,7 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
} }
} }
} }
FREEPKG(info);
} }
/* PROVIDES -- check to see if another package already provides what /* PROVIDES -- check to see if another package already provides what
@ -3084,7 +3124,7 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
/* wtf */ /* wtf */
fprintf(stderr, "data error: %s supposedly provides %s, but it was not found in db\n", fprintf(stderr, "data error: %s supposedly provides %s, but it was not found in db\n",
(char*)k->data, depend.name); (char*)k->data, depend.name);
list_free(k); FREELIST(k);
continue; continue;
} }
if(depend.mod == DEP_ANY) { if(depend.mod == DEP_ANY) {
@ -3108,8 +3148,9 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
} }
FREE(ver); FREE(ver);
} }
FREEPKG(p);
FREELIST(k);
} }
list_free(k);
} }
/* else if still not found... */ /* else if still not found... */
if(!found) { if(!found) {
@ -3255,6 +3296,9 @@ int runscriptlet(char *installfn, char *script, char *ver, char *oldver)
if(!grep(scriptfn, script)) { if(!grep(scriptfn, script)) {
/* script not found in scriptlet file */ /* script not found in scriptlet file */
if(strlen(tmpdir) && rmrf(tmpdir)) {
fprintf(stderr, "warning: could not remove tmpdir %s\n", tmpdir);
}
return(0); return(0);
} }
@ -3289,39 +3333,40 @@ int parseargs(int op, int argc, char **argv)
static struct option opts[] = static struct option opts[] =
{ {
{"add", no_argument, 0, 'A'}, {"add", no_argument, 0, 'A'},
{"remove", no_argument, 0, 'R'}, {"resolve", no_argument, 0, 'D'}, /* used by 'makepkg -s' */
{"upgrade", no_argument, 0, 'U'},
{"freshen", no_argument, 0, 'F'}, {"freshen", no_argument, 0, 'F'},
{"query", no_argument, 0, 'Q'}, {"query", no_argument, 0, 'Q'},
{"remove", no_argument, 0, 'R'},
{"sync", no_argument, 0, 'S'}, {"sync", no_argument, 0, 'S'},
{"deptest", no_argument, 0, 'T'}, {"deptest", no_argument, 0, 'T'}, /* used by makepkg */
{"vertest", no_argument, 0, 'Y'}, {"upgrade", no_argument, 0, 'U'},
{"resolve", no_argument, 0, 'D'},
{"root", required_argument, 0, 'r'},
{"dbpath", required_argument, 0, 'b'},
{"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 'V'}, {"version", no_argument, 0, 'V'},
{"help", no_argument, 0, 'h'}, {"vertest", no_argument, 0, 'Y'}, /* does the same as the 'vercmp' binary */
{"search", no_argument, 0, 's'}, {"dbpath", required_argument, 0, 'b'},
{"clean", no_argument, 0, 'c'}, {"clean", no_argument, 0, 'c'},
{"force", no_argument, 0, 'f'}, {"cascade", no_argument, 0, 'c'},
{"nodeps", no_argument, 0, 'd'}, {"nodeps", no_argument, 0, 'd'},
{"orphans", no_argument, 0, 'e'}, {"orphans", no_argument, 0, 'e'},
{"force", no_argument, 0, 'f'},
{"groups", no_argument, 0, 'g'},
{"help", no_argument, 0, 'h'},
{"info", no_argument, 0, 'i'},
{"dbonly", no_argument, 0, 'k'},
{"list", no_argument, 0, 'l'},
{"nosave", no_argument, 0, 'n'}, {"nosave", no_argument, 0, 'n'},
{"owns", no_argument, 0, 'o'}, {"owns", no_argument, 0, 'o'},
{"list", no_argument, 0, 'l'},
{"file", no_argument, 0, 'p'}, {"file", no_argument, 0, 'p'},
{"info", no_argument, 0, 'i'},
{"sysupgrade", no_argument, 0, 'u'},
{"downloadonly", no_argument, 0, 'w'},
{"print-uris", no_argument, 0, 'p'}, {"print-uris", no_argument, 0, 'p'},
{"refresh", no_argument, 0, 'y'}, {"root", required_argument, 0, 'r'},
{"dbonly", no_argument, 0, 'k'}, {"search", no_argument, 0, 's'},
{"cascade", no_argument, 0, 'c'},
{"recursive", no_argument, 0, 's'}, {"recursive", no_argument, 0, 's'},
{"groups", no_argument, 0, 'g'}, {"sysupgrade", no_argument, 0, 'u'},
{"verbose", no_argument, 0, 'v'},
{"downloadonly", no_argument, 0, 'w'},
{"refresh", no_argument, 0, 'y'},
{"noconfirm", no_argument, 0, 1000}, {"noconfirm", no_argument, 0, 1000},
{"config", required_argument, 0, 1001}, {"config", required_argument, 0, 1001},
{"ignore", required_argument, 0, 1002},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
@ -3333,6 +3378,7 @@ int parseargs(int op, int argc, char **argv)
case 0: break; case 0: break;
case 1000: pmo_noconfirm = 1; break; case 1000: pmo_noconfirm = 1; break;
case 1001: strcpy(pmo_configfile, optarg); break; case 1001: strcpy(pmo_configfile, optarg); break;
case 1002: pmo_s_ignore = list_add(pmo_s_ignore, strdup(optarg)); break;
case 'A': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_ADD); break; case 'A': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_ADD); break;
case 'R': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_REMOVE); break; case 'R': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_REMOVE); break;
case 'U': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_UPGRADE); break; case 'U': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_UPGRADE); break;
@ -3469,6 +3515,8 @@ int parseconfig(char *configfile)
} else if(!strcmp(key, "USESYSLOG")) { } else if(!strcmp(key, "USESYSLOG")) {
pmo_usesyslog = 1; pmo_usesyslog = 1;
vprint("config: usesyslog\n"); vprint("config: usesyslog\n");
} else if(!strcmp(key, "ILOVECANDY")) {
pmo_chomp = 1;
} else { } else {
fprintf(stderr, "config: line %d: syntax error\n", linenum); fprintf(stderr, "config: line %d: syntax error\n", linenum);
return(1); return(1);
@ -3691,6 +3739,7 @@ void usage(int op, char *myname)
printf(" -u, --sysupgrade upgrade all packages that are out of date\n"); printf(" -u, --sysupgrade upgrade all packages that are out of date\n");
printf(" -w, --downloadonly download packages but do not install/upgrade anything\n"); printf(" -w, --downloadonly download packages but do not install/upgrade anything\n");
printf(" -y, --refresh download fresh package databases from the server\n"); printf(" -y, --refresh download fresh package databases from the server\n");
printf(" --ignore <pkg> ignore a package upgrade (can be used more than once)\n");
} }
printf(" --config <path> set an alternate configuration file\n"); printf(" --config <path> set an alternate configuration file\n");
printf(" --noconfirm do not ask for any confirmation\n"); printf(" --noconfirm do not ask for any confirmation\n");
@ -3712,20 +3761,6 @@ void version(void)
printf(" the terms of the GNU General Public License\n\n"); printf(" the terms of the GNU General Public License\n\n");
} }
/* Check verbosity option and, if set, print the
* string to stdout
*/
void vprint(char *fmt, ...)
{
va_list args;
if(pmo_verbose) {
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
fflush(stdout);
}
}
/* Output a message to stderr, and (optionally) syslog and/or a logfile */ /* Output a message to stderr, and (optionally) syslog and/or a logfile */
void logaction(FILE *fp, char *fmt, ...) void logaction(FILE *fp, char *fmt, ...)
{ {

View file

@ -21,22 +21,6 @@
#ifndef _PAC_PACMAN_H #ifndef _PAC_PACMAN_H
#define _PAC_PACMAN_H #define _PAC_PACMAN_H
#ifndef PACVER
#define PACVER "2.9.2"
#endif
#ifndef PKGDIR
#define PKGDIR "var/lib/pacman"
#endif
#ifndef PACCONF
#define PACCONF "/etc/pacman.conf"
#endif
#ifndef CACHEDIR
#define CACHEDIR "var/cache/pacman/pkg"
#endif
/* Operations */ /* Operations */
#define PM_MAIN 1 #define PM_MAIN 1
#define PM_ADD 2 #define PM_ADD 2
@ -69,7 +53,6 @@ int parseconfig(char *configfile);
void usage(int op, char *myname); void usage(int op, char *myname);
void version(void); void version(void);
void vprint(char *fmt, ...);
void logaction(FILE *fp, char *fmt, ...); void logaction(FILE *fp, char *fmt, ...);
char* buildstring(PMList *strlist); char* buildstring(PMList *strlist);
int yesno(char* fmt, ...); int yesno(char* fmt, ...);

View file

@ -28,12 +28,12 @@
#include <sys/time.h> #include <sys/time.h>
#include <ftplib.h> #include <ftplib.h>
/* pacman */ /* pacman */
#include "pacconf.h"
#include "list.h" #include "list.h"
#include "package.h" #include "package.h"
#include "db.h" #include "db.h"
#include "util.h" #include "util.h"
#include "pacsync.h" #include "pacsync.h"
#include "pacman.h"
/* progress bar */ /* progress bar */
static int log_progress(netbuf *ctl, int xfered, void *arg); static int log_progress(netbuf *ctl, int xfered, void *arg);
@ -52,6 +52,7 @@ extern char *pmo_xfercommand;
extern unsigned short pmo_proxyport; extern unsigned short pmo_proxyport;
extern unsigned short pmo_nopassiveftp; extern unsigned short pmo_nopassiveftp;
extern unsigned short pmo_chomp;
/* sync servers */ /* sync servers */
extern PMList *pmc_syncs; extern PMList *pmc_syncs;
@ -205,7 +206,7 @@ int downloadfiles_forreal(PMList *servers, const char *localpath,
char *host; char *host;
unsigned port; unsigned port;
host = (pmo_proxyhost) ? pmo_proxyhost : server->server; host = (pmo_proxyhost) ? pmo_proxyhost : server->server;
port = (pmo_proxyhost) ? pmo_proxyport : 80; port = (pmo_proxyport) ? pmo_proxyport : 80;
if(strchr(host, ':')) { if(strchr(host, ':')) {
vprint("connecting to %s\n", host); vprint("connecting to %s\n", host);
} else { } else {
@ -306,7 +307,7 @@ int downloadfiles_forreal(PMList *servers, const char *localpath,
if(ptr && (ptr-fn) < 24) { if(ptr && (ptr-fn) < 24) {
sync_fnm[ptr-fn] = '\0'; sync_fnm[ptr-fn] = '\0';
} }
ptr = strstr(fn, ".pkg.tar.gz"); ptr = strstr(fn, PKGEXT);
if(ptr && (ptr-fn) < 24) { if(ptr && (ptr-fn) < 24) {
sync_fnm[ptr-fn] = '\0'; sync_fnm[ptr-fn] = '\0';
} }
@ -469,6 +470,11 @@ static int log_progress(netbuf *ctl, int xfered, void *arg)
int i, cur; int i, cur;
struct timeval t1; struct timeval t1;
float timediff; float timediff;
/* a little hard to conceal easter eggs in open-source software, but
* they're still fun. ;)
*/
static unsigned short mouth;
static unsigned int lastcur = 0;
gettimeofday(&t1, NULL); gettimeofday(&t1, NULL);
if(xfered+offset == fsz) { if(xfered+offset == fsz) {
@ -501,13 +507,39 @@ static int log_progress(netbuf *ctl, int xfered, void *arg)
printf(" %s [", sync_fnm); printf(" %s [", sync_fnm);
cur = (int)((maxcols-64)*pct/100); cur = (int)((maxcols-64)*pct/100);
for(i = 0; i < maxcols-64; i++) { for(i = 0; i < maxcols-64; i++) {
(i < cur) ? printf("#") : printf(" "); if(pmo_chomp) {
if(i < cur) {
printf("-");
} else {
if(i == cur) {
if(lastcur == cur) {
if(mouth) {
printf("\033[1;33mC\033[m");
} else {
printf("\033[1;33mc\033[m");
}
} else {
mouth = mouth == 1 ? 0 : 1;
if(mouth) {
printf("\033[1;33mC\033[m");
} else {
printf("\033[1;33mc\033[m");
}
}
} else {
printf("\033[0;37m*\033[m");
}
}
} else {
(i < cur) ? printf("#") : printf(" ");
}
} }
if(rate > 1000) { 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 { } 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);
} }
lastcur = cur;
fflush(stdout); fflush(stdout);
return(1); return(1);
} }

195
src/strhash.c Normal file
View file

@ -0,0 +1,195 @@
/* evtgen string hash functions.
Copyright (C) 2003 Julien Olivain and LSV, CNRS UMR 8643 & ENS Cachan.
This file is part of evtgen.
evtgen is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
evtgen is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with evtgen; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Copyright (C) 2004 Tommi Rantala <tommi.rantala@cs.helsinki.fi>
*
* Modified for usage in Pacman.
*/
/*
** strhash.c -- string hash utility functions
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "util.h"
#include "list.h"
#include "strhash.h"
void
strhash_add_list(strhash_t *hash, PMList* list)
{
for(; list; list = list->next)
strhash_add(hash, list->data, NULL);
}
strhash_t *
new_strhash(size_t hsize)
{
strhash_t *h;
MALLOC(h, sizeof (strhash_t));
h->size = hsize;
h->elmts = 0;
h->hash = DEFAULT_STRHASH_FUNCTION;
MALLOC(h->htable, hsize * sizeof (strhash_elmt_t *));
memset(h->htable, 0, hsize * sizeof(strhash_elmt_t *));
return (h);
}
void
clear_strhash(strhash_t *hash)
{
int i;
strhash_elmt_t *tmp;
strhash_elmt_t *tmp_next;
for (i = 0; i < hash->size; i++)
{
tmp = hash->htable[i];
while (tmp)
{
tmp_next = tmp->next;
free(tmp);
tmp = tmp_next;
}
}
hash->elmts = 0;
memset(hash->htable, 0, hash->size * sizeof (void *));
}
void
free_strhash(strhash_t *hash)
{
int i;
strhash_elmt_t *tmp;
strhash_elmt_t *tmp_next;
for (i = 0; i < hash->size; i++)
{
tmp = hash->htable[i];
while (tmp)
{
tmp_next = tmp->next;
free(tmp);
tmp = tmp_next;
}
}
free(hash->htable);
free(hash);
}
void
strhash_add(strhash_t *hash, char *key, char *data)
{
strhash_elmt_t *elmt;
unsigned long hcode;
MALLOC(elmt, sizeof (strhash_elmt_t));
elmt->key = key;
elmt->data = data;
hcode = hash->hash(key) % hash->size;
elmt->next = hash->htable[hcode];
hash->htable[hcode] = elmt;
hash->elmts++;
}
/* 1: Yes, the key exists in the hash table.
* 0: No, its not here.
*/
int
strhash_isin(strhash_t *hash, char* key)
{
strhash_elmt_t *elmt;
elmt = hash->htable[hash->hash(key) % hash->size];
for (; elmt; elmt = elmt->next)
{
if (!strcmp(key, elmt->key))
return 1;
}
return 0;
}
char*
strhash_get(strhash_t *hash, char* key)
{
strhash_elmt_t *elmt;
elmt = hash->htable[hash->hash(key) % hash->size];
for (; elmt; elmt = elmt->next)
{
if (!strcmp(key, elmt->key))
return elmt->data;
}
return NULL;
}
/*
** fast hash function samples
*/
unsigned long
strhash_pjw(char *key)
{
unsigned long h;
unsigned long g;
h = 0;
while (*key)
{
h = (h << 4) + *key++;
if ((g = h & 0xF0000000U) != 0)
{
h = h ^ (g >> 24);
h = h ^ g;
}
}
return (h);
}
int
strhash_collide_count(strhash_t *hash)
{
int count;
int i;
count = 0;
for (i = 0; i < hash->size; i++)
{
strhash_elmt_t *tmp;
for (tmp = hash->htable[i]; tmp; tmp = tmp->next)
if (tmp->next)
count++;
}
return (count);
}

65
src/strhash.h Normal file
View file

@ -0,0 +1,65 @@
/* evtgen string hash headers.
Copyright (C) 2003 Julien Olivain and LSV, CNRS UMR 8643 & ENS Cachan.
This file is part of evtgen.
evtgen is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
evtgen is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with evtgen; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Copyright (C) 2004 Tommi Rantala <tommi.rantala@cs.helsinki.fi>
*
* Modified for usage in Pacman.
*/
/*
** strhash.h --
*/
#ifndef STRHASH_H
#define STRHASH_H
#define DEFAULT_STRHASH_FUNCTION strhash_pjw
typedef struct strhash_elmt_s strhash_elmt_t;
struct strhash_elmt_s
{
char *key;
char *data;
strhash_elmt_t *next;
};
typedef unsigned long (*strhashfunc_t)(char *key);
typedef struct strhash_s strhash_t;
struct strhash_s
{
strhash_elmt_t **htable;
size_t size;
int elmts;
strhashfunc_t hash;
};
void strhash_add_list(strhash_t *hash, PMList* list);
strhash_t *new_strhash(size_t hsize);
void free_strhash(strhash_t *hash);
void clear_strhash(strhash_t *hash);
void strhash_add(strhash_t *hash, char *key, char *data);
int strhash_isin(strhash_t *hash, char* key);
char* strhash_get(strhash_t *hash, char* key);
int strhash_collide_count(strhash_t *hash);
unsigned long strhash_pjw(char *key);
#endif /* STRHASH_H */

View file

@ -32,6 +32,22 @@
#include <libtar.h> #include <libtar.h>
#include "util.h" #include "util.h"
extern unsigned short pmo_verbose;
/* Check verbosity option and, if set, print the
* string to stdout
*/
void vprint(char *fmt, ...)
{
va_list args;
if(pmo_verbose) {
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
fflush(stdout);
}
}
/* borrowed and modified from Per Liden's pkgutils (http://crux.nu) */ /* borrowed and modified from Per Liden's pkgutils (http://crux.nu) */
long gzopen_frontend(char *pathname, int oflags, int mode) long gzopen_frontend(char *pathname, int oflags, int mode)
{ {

View file

@ -28,6 +28,7 @@
#define FREE(p) { if (p) { free(p); (p)= NULL; }} #define FREE(p) { if (p) { free(p); (p)= NULL; }}
void vprint(char *fmt, ...);
long gzopen_frontend(char *pathname, int oflags, int mode); long gzopen_frontend(char *pathname, int oflags, int mode);
int unpack(char *archive, const char *prefix, const char *fn); int unpack(char *archive, const char *prefix, const char *fn);
int copyfile(char *src, char *dest); int copyfile(char *src, char *dest);