diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/convertdb.c | 24 | ||||
-rw-r--r-- | src/db.c | 81 | ||||
-rw-r--r-- | src/db.h | 5 | ||||
-rw-r--r-- | src/list.c | 94 | ||||
-rw-r--r-- | src/list.h | 24 | ||||
-rw-r--r-- | src/md5.h | 3 | ||||
-rw-r--r-- | src/md5driver.c | 3 | ||||
-rw-r--r-- | src/package.c | 129 | ||||
-rw-r--r-- | src/package.h | 5 | ||||
-rw-r--r-- | src/pacman.c | 696 | ||||
-rw-r--r-- | src/pacman.h | 12 | ||||
-rw-r--r-- | src/pacsync.c | 40 | ||||
-rw-r--r-- | src/pacsync.h | 3 | ||||
-rw-r--r-- | src/rpmvercmp.h | 28 | ||||
-rw-r--r-- | src/util.c | 491 | ||||
-rw-r--r-- | src/util.h | 14 | ||||
-rw-r--r-- | src/vercmp.c | 24 |
17 files changed, 896 insertions, 780 deletions
diff --git a/src/convertdb.c b/src/convertdb.c index b3387162..d337dcca 100644 --- a/src/convertdb.c +++ b/src/convertdb.c @@ -29,8 +29,7 @@ #include <sys/stat.h> #include <unistd.h> #include "list.h" - -char* trim(char *str); +#include "util.h" int main(int argc, char* argv[]) { @@ -139,25 +138,4 @@ int main(int argc, char* argv[]) return(0); } -/* Trim whitespace and newlines from a string - */ -char* trim(char *str) -{ - char *pch = str; - while(isspace(*pch)) { - pch++; - } - if(pch != str) { - memmove(str, pch, (strlen(pch) + 1)); - } - - pch = (char*)(str + (strlen(str) - 1)); - while(isspace(*pch)) { - pch--; - } - *++pch = '\0'; - - return str; -} - /* vim: set ts=2 sw=2 noet: */ @@ -24,21 +24,10 @@ #include <stdlib.h> #include <errno.h> #include <string.h> -#include <limits.h> #include <sys/stat.h> -#include <sys/types.h> -#include "list.h" #include "package.h" -#include "db.h" #include "util.h" -#include "pacsync.h" -#include "pacman.h" - -extern PMList *pm_packages; -extern char *pmo_root; -extern unsigned short pmo_upgrade; - -extern int errno; +#include "db.h" /* Verify database integrity and build a list of * installed packages @@ -47,14 +36,14 @@ extern int errno; * 1 if db is not initialized * 2 if db is corrupt */ -pacdb_t* db_open(char *dbpath, char *treename) +pacdb_t* db_open(char *root, char *pkgdir, char *treename) { pacdb_t *db = NULL; - char path[PATH_MAX]; MALLOC(db, sizeof(pacdb_t)); - snprintf(path, PATH_MAX-1, "%s/%s", dbpath, treename); - db->dir = opendir(path); + MALLOC(db->path, strlen(root)+strlen(pkgdir)+strlen(treename)+2); + sprintf(db->path, "%s%s/%s", root, pkgdir, treename); + db->dir = opendir(db->path); if(db->dir == NULL) { return(NULL); } @@ -65,7 +54,14 @@ pacdb_t* db_open(char *dbpath, char *treename) void db_close(pacdb_t* db) { - closedir(db->dir); + if(db) { + if(db->dir) { + closedir(db->dir); + } + FREE(db->path); + } + FREE(db); + return; } @@ -115,6 +111,8 @@ PMList* db_loadpkgs(pacdb_t *db, PMList *pkgcache) cache = list_add(cache, arr[i]); } + free(arr); + return(cache); } @@ -174,19 +172,17 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq) struct stat buf; pkginfo_t *info = NULL; char path[PATH_MAX]; - char topdir[PATH_MAX]; char line[512]; if(ent == NULL) { return(NULL); } - snprintf(topdir, PATH_MAX, "%s%s/%s", pmo_root, PKGDIR, db->treename); info = newpkg(); /* we always load DESC */ inforeq |= INFRQ_DESC; - snprintf(path, PATH_MAX, "%s/%s", topdir, ent->d_name); + snprintf(path, PATH_MAX, "%s/%s", db->path, ent->d_name); if(stat(path, &buf)) { /* directory doesn't exist or can't be opened */ return(NULL); @@ -194,7 +190,7 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq) /* DESC */ if(inforeq & INFRQ_DESC) { - snprintf(path, PATH_MAX, "%s/%s/desc", topdir, ent->d_name); + snprintf(path, PATH_MAX, "%s/%s/desc", db->path, ent->d_name); fp = fopen(path, "r"); if(fp == NULL) { fprintf(stderr, "error: %s: %s\n", path, strerror(errno)); @@ -206,32 +202,37 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq) } trim(line); if(!strcmp(line, "%NAME%")) { - if(fgets(info->name, 256, fp) == NULL) { + if(fgets(info->name, sizeof(info->name), fp) == NULL) { return(NULL); } trim(info->name); } else if(!strcmp(line, "%VERSION%")) { - if(fgets(info->version, 64, fp) == NULL) { + if(fgets(info->version, sizeof(info->version), fp) == NULL) { return(NULL); } trim(info->version); } else if(!strcmp(line, "%DESC%")) { - if(fgets(info->desc, 512, fp) == NULL) { + if(fgets(info->desc, sizeof(info->desc), fp) == NULL) { return(NULL); } trim(info->desc); + } else if(!strcmp(line, "%URL%")) { + if(fgets(info->url, sizeof(info->url), fp) == NULL) { + return(NULL); + } + trim(info->url); } else if(!strcmp(line, "%BUILDDATE%")) { - if(fgets(info->builddate, 32, fp) == NULL) { + if(fgets(info->builddate, sizeof(info->builddate), fp) == NULL) { return(NULL); } trim(info->builddate); } else if(!strcmp(line, "%INSTALLDATE%")) { - if(fgets(info->installdate, 32, fp) == NULL) { + if(fgets(info->installdate, sizeof(info->installdate), fp) == NULL) { return(NULL); } trim(info->installdate); } else if(!strcmp(line, "%PACKAGER%")) { - if(fgets(info->packager, 64, fp) == NULL) { + if(fgets(info->packager, sizeof(info->packager), fp) == NULL) { return(NULL); } trim(info->packager); @@ -249,7 +250,7 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq) /* FILES */ if(inforeq & INFRQ_FILES) { - snprintf(path, PATH_MAX, "%s/%s/files", topdir, ent->d_name); + snprintf(path, PATH_MAX, "%s/%s/files", db->path, ent->d_name); fp = fopen(path, "r"); if(fp == NULL) { fprintf(stderr, "error: %s: %s\n", path, strerror(errno)); @@ -275,7 +276,7 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq) /* DEPENDS */ if(inforeq & INFRQ_DEPENDS) { - snprintf(path, PATH_MAX, "%s/%s/depends", topdir, ent->d_name); + snprintf(path, PATH_MAX, "%s/%s/depends", db->path, ent->d_name); fp = fopen(path, "r"); if(fp == NULL) { fprintf(stderr, "db_read: error: %s: %s\n", path, strerror(errno)); @@ -307,7 +308,7 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq) } /* INSTALL */ - snprintf(path, PATH_MAX, "%s/%s/install", topdir, ent->d_name); + snprintf(path, PATH_MAX, "%s/%s/install", db->path, ent->d_name); if(!stat(path, &buf)) { info->scriptlet = 1; } @@ -317,8 +318,8 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq) int db_write(pacdb_t *db, pkginfo_t *info) { - FILE *fp = NULL; char topdir[PATH_MAX]; + FILE *fp = NULL; char path[PATH_MAX]; mode_t oldmask; PMList *lp = NULL; @@ -326,11 +327,11 @@ int db_write(pacdb_t *db, pkginfo_t *info) if(info == NULL) { return(1); } - snprintf(topdir, PATH_MAX, "%s%s/%s/%s-%s", pmo_root, PKGDIR, db->treename, - info->name, info->version); + snprintf(topdir, PATH_MAX, "%s/%s-%s", db->path, + info->name, info->version); oldmask = umask(0000); - mkdir(topdir, 0755); + mkdir(topdir, 0755); umask(oldmask); /* DESC */ @@ -346,6 +347,8 @@ int db_write(pacdb_t *db, pkginfo_t *info) fprintf(fp, "%s\n\n", info->version); fputs("%DESC%\n", fp); fprintf(fp, "%s\n\n", info->desc); + fputs("%URL%\n", fp); + fprintf(fp, "%s\n\n", info->url); fputs("%BUILDDATE%\n", fp); fprintf(fp, "%s\n\n", info->builddate); fputs("%INSTALLDATE%\n", fp); @@ -406,7 +409,7 @@ int db_write(pacdb_t *db, pkginfo_t *info) } -PMList* db_find_conflicts(pacdb_t *db, PMList *targets) +PMList* db_find_conflicts(pacdb_t *db, PMList *targets, char *root) { PMList *i, *j, *k; char *filestr = NULL; @@ -450,7 +453,7 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets) }*/ /* CHECK 2: check every target against every target */ - vprint("Checking targets against targets...\n"); + /* orelien - vprint("Checking targets against targets...\n"); */ for(i = targets; i; i = i->next) { pkginfo_t *p1 = (pkginfo_t*)i->data; for(j = i; j; j = j->next) { @@ -458,7 +461,7 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets) if(strcmp(p1->name, p2->name)) { for(k = p1->files; k; k = k->next) { filestr = k->data; - if(!strcmp(filestr, "._install")) { + if(!strcmp(filestr, "._install") || !strcmp(filestr, ".INSTALL")) { continue; } if(rindex(filestr, '/') == filestr+strlen(filestr)-1) { @@ -477,13 +480,13 @@ PMList* db_find_conflicts(pacdb_t *db, PMList *targets) } /* CHECK 3: check every target against the filesystem */ - vprint("Checking targets against filesystem...\n"); + /* orelien - vprint("Checking targets against filesystem...\n"); */ for(i = targets; i; i = i->next) { pkginfo_t *p = (pkginfo_t*)i->data; pkginfo_t *dbpkg = NULL; for(j = p->files; j; j = j->next) { filestr = (char*)j->data; - snprintf(path, PATH_MAX, "%s%s", pmo_root, filestr); + snprintf(path, PATH_MAX, "%s%s", root, filestr); if(!stat(path, &buf) && !S_ISDIR(buf.st_mode)) { int ok = 0; if(dbpkg == NULL) { @@ -30,17 +30,18 @@ #define INFRQ_ALL 0xFF typedef struct __pacdb_t { + char *path; char treename[128]; DIR* dir; } pacdb_t; -pacdb_t* db_open(char *dbpath, char *treename); +pacdb_t* db_open(char *root, char *dbpath, char *treename); void db_close(pacdb_t *db); PMList* db_loadpkgs(pacdb_t *db, PMList *pkgcache); 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); -PMList* db_find_conflicts(pacdb_t *db, PMList* targets); +PMList* db_find_conflicts(pacdb_t *db, PMList* targets, char *root); #endif /* vim: set ts=2 sw=2 noet: */ @@ -20,14 +20,9 @@ */ #include "config.h" -#include <stdio.h> #include <stdlib.h> -#include <limits.h> -#include <errno.h> #include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> +#include <stdio.h> #include "list.h" PMList* list_new() @@ -105,6 +100,20 @@ int list_isin(PMList *haystack, void *needle) return(0); } +/* Test for existence of a string in a PMList + */ +int is_in(char *needle, PMList *haystack) +{ + PMList *lp; + + for(lp = haystack; lp; lp = lp->next) { + if(lp->data && !strcmp(lp->data, needle)) { + return(1); + } + } + return(0); +} + /* List one is extended and returned * List two is freed (but not its data) */ @@ -131,4 +140,77 @@ PMList* list_last(PMList *list) return(ptr); } +/* Helper function for sorting a list of strings + */ +int list_strcmp(const void *s1, const void *s2) +{ + char **str1 = (char **)s1; + char **str2 = (char **)s2; + + return(strcmp(*str1, *str2)); +} + +PMList *list_sort(PMList *list) +{ + char **arr = NULL; + PMList *lp; + unsigned int arrct; + int i; + + if(list == NULL) { + return(NULL); + } + + arrct = list_count(list); + arr = (char **)malloc(arrct*sizeof(char*)); + for(lp = list, i = 0; lp; lp = lp->next) { + arr[i++] = (char *)lp->data; + } + + qsort(arr, (size_t)arrct, sizeof(char *), list_strcmp); + + lp = NULL; + for(i = 0; i < arrct; i++) { + lp = list_add(lp, strdup(arr[i])); + } + + free(arr); + + return(lp); +} + +void list_display(const char *title, PMList *list) +{ + PMList *lp; + int cols, len, maxcols = 80; + char *cenv = NULL; + + cenv = getenv("COLUMNS"); + if(cenv) { + maxcols = atoi(cenv); + } + + len = strlen(title); + printf("%s", title); + + if(list) { + for(lp = list, cols = len; lp; lp = lp->next) { + int s = strlen((char*)lp->data)+1; + if(s+cols >= maxcols) { + int i; + cols = len; + printf("\n"); + for (i = 0; i < len; i++) { + printf(" "); + } + } + printf("%s ", (char*)lp->data); + cols += s; + } + printf("\n"); + } else { + printf("None\n"); + } +} + /* vim: set ts=2 sw=2 noet: */ @@ -1,3 +1,23 @@ +/* + * pacman + * + * Copyright (c) 2002 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_LIST_H #define _PAC_LIST_H @@ -13,8 +33,12 @@ void list_free(PMList* list); PMList* list_add(PMList* list, void* data); int list_count(PMList* list); int list_isin(PMList *haystack, void *needle); +int is_in(char *needle, PMList *haystack); PMList* list_merge(PMList *one, PMList *two); PMList* list_last(PMList* list); +int list_strcmp(const void *s1, const void *s2); +PMList *list_sort(PMList *list); +void list_display(const char *title, PMList *list); #endif @@ -45,4 +45,7 @@ void MD5Init(MD5_CTX *); void MD5Update(MD5_CTX *, unsigned char *, unsigned int); void MD5Final(unsigned char [16], MD5_CTX *); +char* MDFile(char *); +void MDPrint(unsigned char [16]); + /* vim: set ts=2 sw=2 noet: */ diff --git a/src/md5driver.c b/src/md5driver.c index 52c7189a..efd43fe6 100644 --- a/src/md5driver.c +++ b/src/md5driver.c @@ -29,9 +29,6 @@ documentation and/or software. #define TEST_BLOCK_LEN 1000 #define TEST_BLOCK_COUNT 1000 -char* MDFile(char *); -void MDPrint(unsigned char [16]); - #define MD_CTX MD5_CTX #define MDInit MD5Init #define MDUpdate MD5Update diff --git a/src/package.c b/src/package.c index 6f41fc58..d41e1d85 100644 --- a/src/package.c +++ b/src/package.c @@ -24,39 +24,45 @@ #include <stdlib.h> #include <limits.h> #include <fcntl.h> -#include <unistd.h> #include <string.h> -#include "list.h" -#include "package.h" -#include "db.h" +#include <libtar.h> +#include <zlib.h> #include "util.h" -#include "pacsync.h" -#include "pacman.h" - -extern tartype_t gztype; +#include "package.h" pkginfo_t* load_pkg(char *pkgfile, unsigned short output) { char *expath; - char *descfile; int i; + int config = 0; + int filelist = 0; TAR *tar; pkginfo_t *info = NULL; PMList *backup = NULL; PMList *lp; + tartype_t gztype = { + (openfunc_t) gzopen_frontend, + (closefunc_t)gzclose, + (readfunc_t) gzread, + (writefunc_t)gzwrite + }; info = newpkg(); - descfile = strdup("/tmp/pacman_XXXXXX"); if(tar_open(&tar, pkgfile, &gztype, O_RDONLY, 0, TAR_GNU) == -1) { perror("could not open package"); return(NULL); } - vprint("load_pkg: loading filelist from package...\n"); for(i = 0; !th_read(tar); i++) { + if(config && filelist) { + /* we have everything we need */ + break; + } if(!strcmp(th_get_pathname(tar), ".PKGINFO")) { + char *descfile; + /* extract this file into /tmp. it has info for us */ - vprint("load_pkg: found package description file.\n"); + descfile = strdup("/tmp/pacman_XXXXXX"); mkstemp(descfile); tar_extract_file(tar, descfile); /* parse the info file */ @@ -74,14 +80,43 @@ pkginfo_t* load_pkg(char *pkgfile, unsigned short output) info->backup = list_add(info->backup, lp->data); } } + config = 1; + FREE(descfile); continue; - } - if(!strcmp(th_get_pathname(tar), "._install")) { + } else if(!strcmp(th_get_pathname(tar), "._install") || !strcmp(th_get_pathname(tar), ".INSTALL")) { info->scriptlet = 1; + } else if(!strcmp(th_get_pathname(tar), ".FILELIST")) { + /* Build info->files from the filelist */ + FILE *fp; + char *fn; + char *str; + + MALLOC(str, PATH_MAX); + fn = strdup("/tmp/pacman_XXXXXX"); + mkstemp(fn); + tar_extract_file(tar, fn); + fp = fopen(fn, "r"); + while(!feof(fp)) { + if(fgets(str, PATH_MAX, fp) == NULL) { + continue; + } + trim(str); + info->files = list_add(info->files, strdup(str)); + } + FREE(str); + fclose(fp); + if(unlink(fn)) { + fprintf(stderr, "warning: could not remove tempfile %s\n", fn); + } + FREE(fn); + filelist = 1; } else { - expath = strdup(th_get_pathname(tar)); - /* add the path to the list */ - info->files = list_add(info->files, expath); + if(!filelist) { + /* no .FILELIST present in this package.. build the filelist the */ + /* old-fashioned way, one at a time */ + expath = strdup(th_get_pathname(tar)); + info->files = list_add(info->files, expath); + } } if(TH_ISREG(tar) && tar_skip_regfile(tar)) { @@ -93,9 +128,8 @@ pkginfo_t* load_pkg(char *pkgfile, unsigned short output) expath = NULL; } tar_close(tar); - FREE(descfile); - if(!strlen(info->name) || !strlen(info->version)) { + if(!config) { fprintf(stderr, "load_pkg: missing package info file in %s\n", pkgfile); return(NULL); } @@ -147,6 +181,8 @@ int parse_descfile(char *descfile, pkginfo_t *info, PMList **backup, int output) strncpy(info->version, ptr, sizeof(info->version)); } else if(!strcmp(key, "PKGDESC")) { strncpy(info->desc, ptr, sizeof(info->desc)); + } else if(!strcmp(key, "URL")) { + strncpy(info->url, ptr, sizeof(info->url)); } else if(!strcmp(key, "BUILDDATE")) { strncpy(info->builddate, ptr, sizeof(info->builddate)); } else if(!strcmp(key, "INSTALLDATE")) { @@ -188,6 +224,7 @@ pkginfo_t* newpkg() pkg->name[0] = '\0'; pkg->version[0] = '\0'; pkg->desc[0] = '\0'; + pkg->url[0] = '\0'; pkg->builddate[0] = '\0'; pkg->installdate[0] = '\0'; pkg->packager[0] = '\0'; @@ -227,4 +264,58 @@ int pkgcmp(const void *p1, const void *p2) return(strcmp(pkg1[0]->name, pkg2[0]->name)); } +/* Test for existence of a package in a PMList* + * of pkginfo_t* + * + * returns: 0 for no match + * 1 for identical match + * -1 for name-only match (version mismatch) + */ +int is_pkgin(pkginfo_t *needle, PMList *haystack) +{ + PMList *lp; + pkginfo_t *info; + + for(lp = haystack; lp; lp = lp->next) { + info = (pkginfo_t*)lp->data; + if(info && !strcmp(info->name, needle->name)) { + if(!strcmp(info->version, needle->version)) { + return(1); + } + return(-1); + } + } + return(0); +} + +/* Display the content of a package + */ +void dump_pkg(pkginfo_t *info) +{ + PMList *pm; + + if(info == NULL) { + return; + } + + printf("Name : %s\n", info->name); + printf("Version : %s\n", info->version); + printf("Packager : %s\n", info->packager); + printf("URL: : %s\n", info->url); + printf("Size : %ld\n", info->size); + printf("Build Date : %s %s\n", info->builddate, strlen(info->builddate) ? "UTC" : ""); + printf("Install Date : %s %s\n", info->installdate, strlen(info->installdate) ? "UTC" : ""); + printf("Install Script: %s\n", (info->scriptlet ? "yes" : "no")); + pm = list_sort(info->depends); + list_display("Depends On : ", pm); + FREE(pm); + pm = list_sort(info->requiredby); + list_display("Required By : ", pm); + FREE(pm); + pm = list_sort(info->conflicts); + list_display("Conflicts With: ", pm); + FREE(pm); + printf("Description : %s\n", info->desc); +} + /* vim: set ts=2 sw=2 noet: */ diff --git a/src/package.h b/src/package.h index f9dc9477..72b015c3 100644 --- a/src/package.h +++ b/src/package.h @@ -21,6 +21,8 @@ #ifndef _PAC_PACKAGE_H #define _PAC_PACKAGE_H +#include "list.h" + /* mods for depend_t.mod */ #define DEP_ANY 0 #define DEP_EQ 1 @@ -33,6 +35,7 @@ typedef struct __pkginfo_t { char name[256]; char version[64]; char desc[512]; + char url[255]; char builddate[32]; char installdate[32]; char packager[64]; @@ -62,6 +65,8 @@ int parse_descfile(char *descfile, pkginfo_t *info, PMList **backup, int output) pkginfo_t* newpkg(); void freepkg(pkginfo_t *pkg); int pkgcmp(const void *p1, const void *p2); +int is_pkgin(pkginfo_t *needle, PMList *haystack); +void dump_pkg(pkginfo_t *info); #endif /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman.c b/src/pacman.c index efbf2c17..79f2f996 100644 --- a/src/pacman.c +++ b/src/pacman.c @@ -24,30 +24,26 @@ #include <stdarg.h> #include <stdlib.h> #include <signal.h> -#include <limits.h> #include <errno.h> #include <fcntl.h> #include <string.h> -#include <dirent.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <time.h> +#include <getopt.h> +#include <zlib.h> +#include <libtar.h> /* pacman */ -#include "list.h" +#include "rpmvercmp.h" #include "md5.h" +#include "list.h" #include "package.h" -#include "db.h" #include "util.h" +#include "db.h" #include "pacsync.h" #include "pacman.h" -extern tartype_t gztype; - -/* other prototypes */ -int rpmvercmp(const char *a, const char *b); -char* MDFile(char *); - /* * GLOBALS * @@ -77,6 +73,7 @@ unsigned short pmo_s_sync = 0; unsigned short pmo_s_search = 0; unsigned short pmo_s_clean = 0; /* configuration file options */ +char *pmo_dbpath = NULL; PMList *pmo_noupgrade = NULL; PMList *pmo_ignorepkg = NULL; unsigned short pmo_nopassiveftp = 0; @@ -91,57 +88,57 @@ PMList *pm_targets = NULL; char *lckfile = "/tmp/pacman.lck"; char *workfile = NULL; +enum {READ_ONLY, READ_WRITE} pm_access; int main(int argc, char *argv[]) { int ret = 0; char *ptr = NULL; - char *dbpath = NULL; char path[PATH_MAX]; pacdb_t *db_local = NULL; - PMList *lp; /* default root */ MALLOC(pmo_root, PATH_MAX); strcpy(pmo_root, "/"); + /* default dbpath */ + MALLOC(pmo_dbpath, PATH_MAX); + strcpy(pmo_dbpath, PKGDIR); if(argc < 2) { usage(PM_MAIN, (char*)basename(argv[0])); return(0); } + /* parse the command line */ ret = parseargs(PM_ADD, argc, argv); if(ret) { return(ret); } /* check for permission */ + pm_access = READ_ONLY; if(pmo_op != PM_MAIN && pmo_op != PM_QUERY && pmo_op != PM_DEPTEST) { if(pmo_op == PM_SYNC && pmo_s_search) { /* special case: PM_SYNC can be used w/ pmo_s_search by any user */ } else { - uid_t uid = geteuid(); - if(uid != 0) { + if(geteuid() != 0) { fprintf(stderr, "error: you cannot perform this operation unless you are root.\n"); return(1); } + pm_access = READ_WRITE; + /* lock */ + if(lckmk(lckfile, 1, 1) == -1) { + fprintf(stderr, "error: unable to lock pacman database.\n"); + fprintf(stderr, " if you're sure pacman is not already running, you\n"); + fprintf(stderr, " can remove %s\n", lckfile); + return(32); + } } } vprint("Installation Root: %s\n", pmo_root); - if(pm_targets) { - vprint("Targets:\n"); - for(lp = pm_targets; lp; lp = lp->next) { - vprint(" %s\n", lp->data); - } - } - - /* lock */ - if(lckmk(lckfile, 1, 1) == -1) { - fprintf(stderr, "error: unable to lock pacman database.\n"); - fprintf(stderr, " if you're sure pacman is not already running, you\n"); - fprintf(stderr, " can remove %s\n", lckfile); - return(32); + if(pmo_verbose) { + list_display("Targets: ", pm_targets); } /* set signal handlers */ @@ -164,28 +161,27 @@ int main(int argc, char *argv[]) pmo_root = ptr; } /* db location */ - MALLOC(dbpath, PATH_MAX); - snprintf(dbpath, PATH_MAX-1, "%s%s", pmo_root, PKGDIR); - vprint("Top-level DB Path: %s\n", dbpath); + vprint("Top-level DB Path: %s%s\n", pmo_root, pmo_dbpath); - db_local = db_open(dbpath, "local"); + db_local = db_open(pmo_root, pmo_dbpath, "local"); if(db_local == NULL) { /* couldn't open the db directory - try creating it */ char path[PATH_MAX]; - snprintf(path, PATH_MAX, "%s/local", dbpath); - vprint("initializing database...\n", path); - ret = makepath(path); + snprintf(path, PATH_MAX, "%s%s/local", pmo_root, pmo_dbpath); + vprint("initializing database %s...\n", path); + ret = makepath(path); if(ret) { fprintf(stderr, "error: could not create database.\n"); cleanup(1); } - if((db_local = db_open(dbpath, "local")) == NULL) { + if((db_local = db_open(pmo_root, pmo_dbpath, "local")) == NULL) { fprintf(stderr, "error: could not open database.\n"); cleanup(1); } } + /* load pm_packages cache */ pm_packages = db_loadpkgs(db_local, pm_packages); @@ -203,7 +199,7 @@ int main(int argc, char *argv[]) } db_close(db_local); FREE(pmo_root); - FREE(dbpath); + FREE(pmo_dbpath); cleanup(ret); /* not reached */ return(0); @@ -284,7 +280,6 @@ int pacman_deptest(pacdb_t *db, PMList *targets) int pacman_sync(pacdb_t *db, PMList *targets) { - char dbpath[PATH_MAX]; int allgood = 1, confirm = 0; int cols; PMList *i, *j, *k; @@ -329,8 +324,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) dbsync_t *dbs = NULL; sync_t *sync = (sync_t*)i->data; - snprintf(dbpath, PATH_MAX, "%s%s", pmo_root, PKGDIR); - db_sync = db_open(dbpath, sync->treename); + db_sync = db_open(pmo_root, PKGDIR, sync->treename); if(db_sync == NULL) { fprintf(stderr, "error: could not open sync database: %s\n", sync->treename); fprintf(stderr, " have you used --refresh yet?\n"); @@ -403,6 +397,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) } if(!found) { /*fprintf(stderr, "%s: not found in sync db. skipping.", local->name);*/ + FREE(sync); continue; } /* compare versions and see if we need to upgrade */ @@ -412,40 +407,32 @@ int pacman_sync(pacdb_t *db, PMList *targets) fprintf(stderr, ":: %s-%s: local version is newer\n", local->name, local->version); newer = 1; + FREE(sync); continue; } else if(cmp == 0) { /* versions are identical */ + FREE(sync); continue; } else if(is_in((char*)i->data, pmo_ignorepkg)) { /* package should be ignored (IgnorePkg) */ fprintf(stderr, ":: %s-%s: ignoring package upgrade (%s)\n", local->name, local->version, sync->pkg->version); ignore = 1; + FREE(sync); continue; - } else { - PMList *lp = NULL; - int found = 0; - /* re-fetch the package record with dependency info */ - sync->pkg = db_scan(sync->dbs->db, sync->pkg->name, INFRQ_DESC | INFRQ_DEPENDS); - /* add to the targets list */ - for(found = 0, lp = final; lp && !found; lp = lp->next) { - syncpkg_t *s = (syncpkg_t*)lp->data; - if(s && !strcmp(s->pkg->name, sync->pkg->name)) { - found = 1; - } - } + } + + /* re-fetch the package record with dependency info */ + sync->pkg = db_scan(sync->dbs->db, sync->pkg->name, INFRQ_DESC | INFRQ_DEPENDS); + + /* add to the targets list */ + found = is_pkginsync(sync, final); + if(!found) { + allgood = !resolvedeps(db, databases, sync, final, trail); + /* check again, as resolvedeps could have added our target for us */ + found = is_pkginsync(sync, final); if(!found) { - allgood = !resolvedeps(db, databases, sync, final, trail); - /* check again, as resolvedeps could have added our target for us */ - for(found = 0, lp = final; lp && !found; lp = lp->next) { - syncpkg_t *s = (syncpkg_t*)lp->data; - if(s && !strcmp(s->pkg->name, sync->pkg->name)) { - found = 1; - } - } - if(!found) { - final = list_add(final, sync); - } + final = list_add(final, sync); } } } @@ -480,6 +467,8 @@ int pacman_sync(pacdb_t *db, PMList *targets) if(!found) { fprintf(stderr, "%s: not found in sync db\n", (char*)i->data); allgood = 0; + freepkg(local); + FREE(sync); continue; } if(local && !pmo_s_downloadonly) { @@ -488,36 +477,31 @@ int pacman_sync(pacdb_t *db, PMList *targets) if(cmp > 0) { /* local version is newer - get confirmation first */ if(!yesno(":: %s-%s: local version is newer. Upgrade anyway? [Y/n] ", local->name, local->version)) { + freepkg(local); + freepkg(sync->pkg); + FREE(sync); continue; } } else if(cmp == 0) { /* versions are identical */ if(!yesno(":: %s-%s: is up to date. Upgrade anyway? [Y/n] ", local->name, local->version)) { + freepkg(local); + freepkg(sync->pkg); + FREE(sync); continue; } } } - /* add to targets list */ - found = 0; - for(j = final; j; j = j->next) { - syncpkg_t *tmp = (syncpkg_t*)j->data; - if(tmp && !strcmp(tmp->pkg->name, sync->pkg->name)) { - found = 1; - } - } - if(!found) { + freepkg(local); + + found = is_pkginsync(sync, final); + if(!found && !pmo_nodeps) { allgood = !resolvedeps(db, databases, sync, final, trail); /* check again, as resolvedeps could have added our target for us */ - found = 0; - for(j = final; j; j = j->next) { - syncpkg_t *tmp = (syncpkg_t*)j->data; - if(tmp && !strcmp(tmp->pkg->name, sync->pkg->name)) { - found = 1; - } - } - if(!found) { - final = list_add(final, sync); - } + found = is_pkginsync(sync, final); + } + if(!found) { + final = list_add(final, sync); } } } @@ -535,33 +519,36 @@ int pacman_sync(pacdb_t *db, PMList *targets) } } - deps = checkdeps(db, PM_UPGRADE, list); - if(deps) { - fprintf(stderr, "error: unresolvable conflicts/dependencies:\n"); - for(i = deps; i; i = i->next) { - depmissing_t *miss = (depmissing_t*)i->data; - if(miss->type == CONFLICT) { - fprintf(stderr, " %s: conflicts with %s\n", miss->target, miss->depend.name); - } else if(miss->type == DEPEND || miss->type == REQUIRED) { - fprintf(stderr, " %s: requires %s", miss->target, miss->depend.name); - switch(miss->depend.mod) { - case DEP_EQ: fprintf(stderr, "=%s", miss->depend.version); break; - case DEP_GE: fprintf(stderr, ">=%s", miss->depend.version); break; - case DEP_LE: fprintf(stderr, "<=%s", miss->depend.version); break; - } - if(miss->type == DEPEND) { - fprintf(stderr, " but it is not in the sync db\n"); - } else { - fprintf(stderr, "\n"); + if(!pmo_nodeps && !pmo_s_upgrade) { + deps = checkdeps(db, PM_UPGRADE, list); + if(deps) { + fprintf(stderr, "error: unresolvable conflicts/dependencies:\n"); + for(i = deps; i; i = i->next) { + depmissing_t *miss = (depmissing_t*)i->data; + if(miss->type == CONFLICT) { + fprintf(stderr, " %s: conflicts with %s\n", miss->target, miss->depend.name); + } else if(miss->type == DEPEND || miss->type == REQUIRED) { + fprintf(stderr, " %s: requires %s", miss->target, miss->depend.name); + switch(miss->depend.mod) { + case DEP_EQ: fprintf(stderr, "=%s", miss->depend.version); break; + case DEP_GE: fprintf(stderr, ">=%s", miss->depend.version); break; + case DEP_LE: fprintf(stderr, "<=%s", miss->depend.version); break; + } + if(miss->type == DEPEND) { + fprintf(stderr, " but it is not in the sync db\n"); + } else { + fprintf(stderr, "\n"); + } } + FREE(miss); + i->data = NULL; } - FREE(miss); - i->data = NULL; + list_free(deps); + /* abort mission */ + allgood = 0; } - list_free(deps); - /* abort mission */ - allgood = 0; } + /* cleanup */ for(i = list; i; i = i->next) { i->data = NULL; @@ -641,6 +628,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) snprintf(path, PATH_MAX, "%s-%s.pkg.tar.gz", sync->pkg->name, sync->pkg->version); files = list_add(files, strdup(path)); } else { + vprint(" %s-%s.pkg.tar.gz is already in the cache\n", sync->pkg->name, sync->pkg->version); count++; } } @@ -719,7 +707,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) for(i = final; i; i = i->next) { syncpkg_t *sync = (syncpkg_t*)i->data; if(sync) freepkg(sync->pkg); - free(sync); + FREE(sync); i->data = NULL; } for(i = trail; i; i = i->next) { @@ -730,7 +718,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) dbsync_t *dbs = (dbsync_t*)i->data; db_close(dbs->db); list_free(dbs->pkgcache); - free(dbs); + FREE(dbs); i->data = NULL; } list_free(databases); @@ -751,6 +739,12 @@ int pacman_add(pacdb_t *db, PMList *targets) PMList *alltargs = NULL; PMList *filenames = NULL; unsigned short real_pmo_upgrade; + tartype_t gztype = { + (openfunc_t) gzopen_frontend, + (closefunc_t)gzclose, + (readfunc_t) gzread, + (writefunc_t)gzwrite + }; if(targets == NULL) { return(0); @@ -766,13 +760,14 @@ int pacman_add(pacdb_t *db, PMList *targets) return(1); } if(pmo_freshen) { - /* only upgrade/install this package if it is already installed */ + /* only upgrade/install this package if it is already installed and at a lesser version */ pkginfo_t *dummy = db_scan(db, info->name, INFRQ_DESC); - if(dummy == NULL) { + if(dummy == NULL || rpmvercmp(dummy->version, info->version) >= 0) { freepkg(info); info = NULL; continue; } + freepkg(dummy); } alltargs = list_add(alltargs, info); filenames = list_add(filenames, strdup(targ->data)); @@ -810,7 +805,7 @@ int pacman_add(pacdb_t *db, PMList *targets) if(!pmo_force) { printf("checking for conflicts... "); fflush(stdout); - lp = db_find_conflicts(db, alltargs); + lp = db_find_conflicts(db, alltargs, pmo_root); if(lp) { printf("\nerror: the following file conflicts were found:\n"); for(j = lp; j; j = j->next) { @@ -884,12 +879,12 @@ int pacman_add(pacdb_t *db, PMList *targets) char pathname[PATH_MAX]; strncpy(pathname, th_get_pathname(tar), PATH_MAX); - if(!strcmp(pathname, ".PKGINFO")) { + if(!strcmp(pathname, ".PKGINFO") || !strcmp(pathname, ".FILELIST")) { tar_skip_regfile(tar); continue; } - if(!strcmp(pathname, "._install")) { + if(!strcmp(pathname, "._install") || !strcmp(pathname, ".INSTALL")) { /* the install script goes inside the db */ snprintf(expath, PATH_MAX, "%s%s/%s/%s-%s/install", pmo_root, PKGDIR, db->treename, info->name, info->version); @@ -1279,7 +1274,7 @@ int pacman_remove(pacdb_t *db, PMList *targets) } } } else { - /*vprint(" unlinking %s\n", line);*/ + vprint(" unlinking %s\n", line); if(unlink(line)) { perror("cannot remove file"); } @@ -1389,13 +1384,12 @@ int pacman_query(pacdb_t *db, PMList *targets) printf("\n"); } else if(pmo_q_list) { for(lp = info->files; lp; lp = lp->next) { - if(strcmp(lp->data, ".PKGINFO")) { - printf("%s %s\n", info->name, (char*)lp->data); - } + printf("%s %s\n", info->name, (char*)lp->data); } - } else if(!pmo_q_info) { + } else { printf("%s %s\n", info->name, info->version); } + freepkg(info); continue; } @@ -1417,6 +1411,7 @@ int pacman_query(pacdb_t *db, PMList *targets) gotcha = 1; } } + freepkg(info); } if(!gotcha) { fprintf(stderr, "No package owns %s\n", package); @@ -1442,6 +1437,7 @@ int pacman_query(pacdb_t *db, PMList *targets) for(q = info->files; q; q = q->next) { printf("%s %s%s\n", info->name, pmo_root, (char*)q->data); } + freepkg(info); } else { printf("%s %s\n", tmpp->name, tmpp->version); } @@ -1449,70 +1445,12 @@ int pacman_query(pacdb_t *db, PMList *targets) } else { /* find a target */ if(pmo_q_info) { - int cols; - info = db_scan(db, package, INFRQ_DESC | INFRQ_DEPENDS); if(info == NULL) { fprintf(stderr, "Package \"%s\" was not found.\n", package); return(2); } - - printf("Name : %s\n", info->name); - printf("Version : %s\n", info->version); - printf("Packager : %s\n", info->packager); - printf("Size : %ld\n", info->size); - printf("Build Date : %s %s\n", info->builddate, strlen(info->builddate) ? "UTC" : ""); - printf("Install Date : %s %s\n", info->installdate, strlen(info->installdate) ? "UTC" : ""); - printf("Install Script: %s\n", (info->scriptlet ? "yes" : "no")); - printf("Depends On : "); - if(info->depends) { - for(lp = info->depends, cols = 16; lp; lp = lp->next) { - int s = strlen((char*)lp->data)+1; - if(s+cols > 79) { - cols = 16; - printf("\n%16s%s ", " ", (char*)lp->data); - } else { - printf("%s ", (char*)lp->data); - } - cols += s; - } - printf("\n"); - } else { - printf("None\n"); - } - printf("Required By : "); - if(info->requiredby) { - for(lp = info->requiredby, cols = 16; lp; lp = lp->next) { - int s = strlen((char*)lp->data)+1; - if(s+cols > 79) { - cols = 16; - printf("\n%16s%s ", " ", (char*)lp->data); - } else { - printf("%s ", (char*)lp->data); - } - cols += s; - } - printf("\n"); - } else { - printf("None\n"); - } - printf("Conflicts With: "); - if(info->conflicts) { - for(lp = info->conflicts, cols = 16; lp; lp = lp->next) { - int s = strlen((char*)lp->data)+1; - if(s+cols > 79) { - cols = 16; - printf("\n%16s%s ", " ", (char*)lp->data); - } else { - printf("%s ", (char*)lp->data); - } - cols += s; - } - printf("\n"); - } else { - printf("None\n"); - } - printf("Description : %s\n", info->desc); + dump_pkg(info); printf("\n"); } else if(pmo_q_list) { info = db_scan(db, package, INFRQ_DESC | INFRQ_FILES); @@ -1531,19 +1469,16 @@ int pacman_query(pacdb_t *db, PMList *targets) } printf("%s %s\n", info->name, info->version); } + freepkg(info); } } - if(info) { - freepkg(info); - } - return(0); } int pacman_upgrade(pacdb_t *db, PMList *targets) { - /* this is basically just a remove,add process. pacman_add() will */ + /* this is basically just a remove-then-add process. pacman_add() will */ /* handle it */ pmo_upgrade = 1; return(pacman_add(db, targets)); @@ -1907,6 +1842,405 @@ int splitdep(char *depstr, depend_t *depend) return(0); } +/* Look for a filename in a pkginfo_t.backup list. If we find it, + * then we return the md5 hash (parsed from the same line) + */ +char* needbackup(char* file, PMList *backup) +{ + PMList *lp; + + /* run through the backup list and parse out the md5 hash for our file */ + for(lp = backup; lp; lp = lp->next) { + char* str = strdup(lp->data); + char* ptr; + + /* tab delimiter */ + ptr = index(str, '\t'); + if(ptr == NULL) { + FREE(str); + continue; + } + *ptr = '\0'; + ptr++; + /* now str points to the filename and ptr points to the md5 hash */ + if(!strcmp(file, str)) { + char *md5 = strdup(ptr); + FREE(str); + return(md5); + } + FREE(str); + } + return(NULL); +} + +/* Parse command-line arguments for each operation + * op: the operation code requested + * argc: argc + * argv: argv + * + * Returns: 0 on success, 1 on error + */ +int parseargs(int op, int argc, char **argv) +{ + int opt; + int option_index = 0; + static struct option opts[] = + { + {"add", no_argument, 0, 'A'}, + {"remove", no_argument, 0, 'R'}, + {"upgrade", no_argument, 0, 'U'}, + {"freshen", no_argument, 0, 'F'}, + {"query", no_argument, 0, 'Q'}, + {"sync", no_argument, 0, 'S'}, + {"deptest", no_argument, 0, 'T'}, + {"vertest", no_argument, 0, 'Y'}, + {"resolve", no_argument, 0, 'D'}, + {"root", required_argument, 0, 'r'}, + {"verbose", no_argument, 0, 'v'}, + {"version", no_argument, 0, 'V'}, + {"help", no_argument, 0, 'h'}, + {"search", no_argument, 0, 's'}, + {"clean", no_argument, 0, 'c'}, + {"force", no_argument, 0, 'f'}, + {"nodeps", no_argument, 0, 'd'}, + {"nosave", no_argument, 0, 'n'}, + {"owns", no_argument, 0, 'o'}, + {"list", no_argument, 0, 'l'}, + {"file", no_argument, 0, 'p'}, + {"info", no_argument, 0, 'i'}, + {"sysupgrade", no_argument, 0, 'u'}, + {"downloadonly", no_argument, 0, 'w'}, + {"refresh", no_argument, 0, 'y'}, + {"cascade", no_argument, 0, 'c'}, + {0, 0, 0, 0} + }; + + while((opt = getopt_long(argc, argv, "ARUFQSTDYr:vhscVfnoldpiuwy", opts, &option_index))) { + if(opt < 0) { + break; + } + switch(opt) { + case 0: break; + case 'A': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_ADD); break; + case 'R': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_REMOVE); break; + case 'U': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_UPGRADE); break; + case 'F': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_UPGRADE); pmo_freshen = 1; break; + case 'Q': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_QUERY); break; + case 'S': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_SYNC); break; + case 'T': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_DEPTEST); break; + case 'Y': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_DEPTEST); pmo_d_vertest = 1; break; + case 'D': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_DEPTEST); pmo_d_resolve = 1; break; + case 'h': pmo_help = 1; break; + case 'V': pmo_version = 1; break; + case 'v': pmo_verbose = 1; break; + case 'f': pmo_force = 1; break; + case 'd': pmo_nodeps = 1; break; + case 'n': pmo_nosave = 1; break; + case 'l': pmo_q_list = 1; break; + case 'p': pmo_q_isfile = 1; break; + case 'i': pmo_q_info = 1; break; + case 'o': pmo_q_owns = 1; break; + case 'u': pmo_s_upgrade = 1; break; + case 'w': pmo_s_downloadonly = 1; break; + case 'y': pmo_s_sync = 1; break; + case 's': pmo_s_search = 1; break; + case 'c': pmo_s_clean = 1; pmo_r_cascade = 1; break; + case 'r': if(realpath(optarg, pmo_root) == NULL) { + perror("bad root path"); + return(1); + } break; + case '?': return(1); + default: return(1); + } + } + + if(pmo_op == 0) { + fprintf(stderr, "error: only one operation may be used at a time\n\n"); + return(1); + } + + if(pmo_help) { + usage(pmo_op, (char*)basename(argv[0])); + return(2); + } + if(pmo_version) { + version(); + return(2); + } + + while(optind < argc) { + /* add the target to our target array */ + char *s = strdup(argv[optind]); + pm_targets = list_add(pm_targets, s); + optind++; + } + + return(0); +} + +int parseconfig(char *configfile) +{ + FILE *fp = NULL; + char line[PATH_MAX+1]; + char *ptr = NULL; + char *key = NULL; + int linenum = 0; + char section[256] = ""; + sync_t *sync = NULL; + + if((fp = fopen(configfile, "r")) == NULL) { + perror(configfile); + return(1); + } + + while(fgets(line, PATH_MAX, fp)) { + linenum++; + trim(line); + if(strlen(line) == 0 || line[0] == '#') { + continue; + } + if(line[0] == '[' && line[strlen(line)-1] == ']') { + /* new config section */ + ptr = line; + ptr++; + strncpy(section, ptr, min(255, strlen(ptr)-1)); + section[min(255, strlen(ptr)-1)] = '\0'; + vprint("config: new section '%s'\n", section); + if(!strlen(section)) { + fprintf(stderr, "config: line %d: bad section name\n", linenum); + return(1); + } + if(!strcmp(section, "local")) { + fprintf(stderr, "config: line %d: %s is reserved and cannot be used as a package tree\n", + linenum, section); + return(1); + } + if(strcmp(section, "options")) { + /* start a new sync record */ + MALLOC(sync, sizeof(sync_t)); + sync->treename = strdup(section); + sync->servers = NULL; + pmc_syncs = list_add(pmc_syncs, sync); + } + } else { + /* directive */ + if(!strlen(section)) { + fprintf(stderr, "config: line %d: all directives must belong to a section\n", linenum); + return(1); + } + ptr = line; + key = strsep(&ptr, "="); + if(key == NULL) { + fprintf(stderr, "config: line %d: syntax error\n", linenum); + return(1); + } + trim(key); + key = strtoupper(key); + if(ptr == NULL) { + if(!strcmp(key, "NOPASSIVEFTP")) { + pmo_nopassiveftp = 1; + vprint("config: nopassiveftp\n"); + } else { + fprintf(stderr, "config: line %d: syntax error\n", linenum); + return(1); + } + } else { + trim(ptr); + if(!strcmp(section, "options")) { + if(!strcmp(key, "NOUPGRADE")) { + char *p = ptr; + char *q; + while((q = strchr(p, ' '))) { + *q = '\0'; + pmo_noupgrade = list_add(pmo_noupgrade, strdup(p)); + vprint("config: noupgrade: %s\n", p); + p = q; + p++; + } + pmo_noupgrade = list_add(pmo_noupgrade, strdup(p)); + vprint("config: noupgrade: %s\n", p); + } else if(!strcmp(key, "IGNOREPKG")) { + char *p = ptr; + char *q; + while((q = strchr(p, ' '))) { + *q = '\0'; + pmo_ignorepkg = list_add(pmo_ignorepkg, strdup(p)); + vprint("config: ignorepkg: %s\n", p); + p = q; + p++; + } + pmo_ignorepkg = list_add(pmo_ignorepkg, strdup(p)); + vprint("config: ignorepkg: %s\n", p); + } else if(!strcmp(key, "DBPATH")) { + /* shave off the leading slash, if there is one */ + if(*ptr == '/') { + ptr++; + } + strncpy(pmo_dbpath, ptr, PATH_MAX); + vprint("config: dbpath: %s\n", pmo_dbpath); + } else { + fprintf(stderr, "config: line %d: syntax error\n", linenum); + return(1); + } + } else { + if(!strcmp(key, "SERVER")) { + /* parse our special url */ + server_t *server; + char *p; + + MALLOC(server, sizeof(server_t)); + server->server = server->path = NULL; + server->islocal = 0; + + p = strstr(ptr, "://"); + if(p == NULL) { + fprintf(stderr, "config: line %d: bad server location\n", linenum); + return(1); + } + *p = '\0'; + p++; p++; p++; + if(p == NULL || *p == '\0') { + fprintf(stderr, "config: line %d: bad server location\n", linenum); + return(1); + } + server->islocal = !strcmp(ptr, "local"); + if(!server->islocal) { + char *slash; + /* no http support yet */ + if(strcmp(ptr, "ftp")) { + fprintf(stderr, "config: line %d: protocol %s is not supported\n", linenum, ptr); + return(1); + } + /* split the url into domain and path */ + slash = strchr(p, '/'); + if(slash == NULL) { + /* no path included, default to / */ + server->path = strdup("/"); + } else { + /* add a trailing slash if we need to */ + if(slash[strlen(slash)-1] == '/') { + server->path = strdup(slash); + } else { + MALLOC(server->path, strlen(slash)+2); + sprintf(server->path, "%s/", slash); + } + *slash = '\0'; + } + server->server = strdup(p); + } else { + /* add a trailing slash if we need to */ + if(p[strlen(p)-1] == '/') { + server->path = strdup(p); + } else { + MALLOC(server->path, strlen(p)+2); + sprintf(server->path, "%s/", p); + } + } + /* add to the list */ + vprint("config: %s: server: %s %s\n", section, server->server, server->path); + sync->servers = list_add(sync->servers, server); + } else { + fprintf(stderr, "config: line %d: syntax error\n", linenum); + return(1); + } + } + line[0] = '\0'; + } + } + } + fclose(fp); + + return(0); +} + +/* Display usage/syntax for the specified operation. + * op: the operation code requested + * myname: basename(argv[0]) + */ +void usage(int op, char *myname) +{ + if(op == PM_MAIN) { + printf("usage: %s {-h --help}\n", myname); + printf(" %s {-V --version}\n", myname); + printf(" %s {-A --add} [options] <file>\n", myname); + printf(" %s {-R --remove} [options] <package>\n", myname); + printf(" %s {-U --upgrade} [options] <file>\n", myname); + printf(" %s {-F --freshen} [options] <file>\n", myname); + printf(" %s {-Q --query} [options] [package]\n", myname); + printf(" %s {-S --sync} [options] [package]\n", myname); + printf("\nuse '%s --help' with other options for more syntax\n\n", myname); + } else { + if(op == PM_ADD) { + printf("usage: %s {-A --add} [options] <file>\n", myname); + printf("options:\n"); + printf(" -d, --nodeps skip dependency checks\n"); + printf(" -f, --force force install, overwrite conflicting files\n"); + } else if(op == PM_REMOVE) { + printf("usage: %s {-R --remove} [options] <package>\n", myname); + printf("options:\n"); + printf(" -c, --cascade remove packages and all packages that depend on them\n"); + printf(" -d, --nodeps skip dependency checks\n"); + printf(" -n, --nosave remove configuration files as well\n"); + } else if(op == PM_UPGRADE) { + if(pmo_freshen) { + printf("usage: %s {-F --freshen} [options] <file>\n", myname); + } else { + printf("usage: %s {-U --upgrade} [options] <file>\n", myname); + } + printf("options:\n"); + printf(" -d, --nodeps skip dependency checks\n"); + printf(" -f, --force force install, overwrite conflicting files\n"); + } else if(op == PM_QUERY) { + printf("usage: %s {-Q --query} [options] [package]\n", myname); + printf("options:\n"); + printf(" -i, --info view package information\n"); + printf(" -l, --list list the contents of the queried package\n"); + printf(" -o, --owns <file> query the package that owns <file>\n"); + printf(" -p, --file pacman will query the package file [package] instead of\n"); + printf(" looking in the database\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(" -d, --nodeps skip dependency checks\n"); + printf(" -f, --force force install, overwrite conflicting files\n"); + printf(" -s, --search search sync database 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(" -v, --verbose be verbose\n"); + printf(" -r, --root <path> set an alternate installation root\n"); + } +} + +/* Version + */ +void version(void) +{ + printf("\n"); + printf(" .--. Pacman v%s\n", PACVER); + printf("/ _.-' .-. .-. .-. Copyright (C) 2002 Judd Vinet <jvinet@zeroflux.org>\n"); + printf("\\ '-. '-' '-' '-' \n"); + printf(" '--' This program may be freely redistributed under\n"); + printf(" the terms of the GNU GPL\n\n"); +} + +/* Check verbosity option and, if set, print the + * string to stdout + */ +int vprint(char *fmt, ...) +{ + va_list args; + if(pmo_verbose) { + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + fflush(stdout); + } + return(0); +} + int lckmk(char *file, int retries, unsigned int sleep_secs) { int fd, count = 0; @@ -1928,7 +2262,7 @@ int lckrm(char *file) void cleanup(int signum) { - if(lckrm(lckfile)) { + if(pm_access == READ_WRITE && lckrm(lckfile)) { fprintf(stderr, "warning: could not remove lock file %s\n", lckfile); } if(workfile) { diff --git a/src/pacman.h b/src/pacman.h index 0f70ffe2..5c1a94dd 100644 --- a/src/pacman.h +++ b/src/pacman.h @@ -22,7 +22,7 @@ #define _PAC_PACMAN_H #ifndef PACVER -#define PACVER "2.4.1" +#define PACVER "2.5" #endif #ifndef PKGDIR @@ -42,6 +42,8 @@ #define PM_SYNC 6 #define PM_DEPTEST 7 +#define min(X, Y) ((X) < (Y) ? (X) : (Y)) + int pacman_add(pacdb_t *db, PMList *targets); int pacman_remove(pacdb_t *db, PMList *targets); int pacman_upgrade(pacdb_t *db, PMList *targets); @@ -53,6 +55,14 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets); int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *sync, PMList *list, PMList *trail); int splitdep(char *depstr, depend_t *depend); +char* needbackup(char *file, PMList *backup); + +int parseargs(int op, int argc, char **argv); +int parseconfig(char *configfile); +void usage(int op, char *myname); +void version(void); + +int vprint(char *fmt, ...); int lckmk(char *file, int retries, unsigned int sleep_secs); int lckrm(char *lckfile); void cleanup(int signum); diff --git a/src/pacsync.c b/src/pacsync.c index fce3a29b..da2f1a9a 100644 --- a/src/pacsync.c +++ b/src/pacsync.c @@ -21,11 +21,8 @@ #include "config.h" #include <stdio.h> -#include <stdlib.h> -#include <limits.h> -#include <errno.h> #include <string.h> -#include <sys/types.h> +#include <sys/stat.h> #include <unistd.h> #include <ftplib.h> /* pacman */ @@ -42,7 +39,7 @@ static int offset; /* pacman options */ extern char *pmo_root; -extern unsigned char pmo_nopassiveftp; +extern unsigned short pmo_nopassiveftp; /* sync servers */ extern PMList *pmc_syncs; @@ -130,6 +127,13 @@ int downloadfiles(PMList *servers, char *localpath, PMList *files) FtpLastResponse(control)); continue; } + if(!pmo_nopassiveftp) { + if(!FtpOptions(FTPLIB_CONNMODE, FTPLIB_PASSIVE, control)) { + fprintf(stderr, "warning: failed to set passive mode\n"); + } + } else { + vprint("FTP passive mode not set\n"); + } } /* get each file in the list */ @@ -151,13 +155,6 @@ int downloadfiles(PMList *servers, char *localpath, PMList *files) sync_fnm[24] = '\0'; if(!server->islocal) { - if(!pmo_nopassiveftp) { - if(!FtpOptions(FTPLIB_CONNMODE, FTPLIB_PASSIVE, control)) { - fprintf(stderr, "warning: failed to set passive mode\n"); - } - } else { - vprint("FTP passive mode not set\n"); - } if(!FtpSize(fn, &fsz, FTPLIB_IMAGE, control)) { fprintf(stderr, "warning: failed to get filesize for %s\n", fn); } @@ -246,4 +243,23 @@ static int log_progress(netbuf *ctl, int xfered, void *arg) return(1); } +/* Test for existence of a package in a PMList* + * of syncpkg_t* + */ +int is_pkginsync(syncpkg_t *needle, PMList *haystack) +{ + PMList *lp; + syncpkg_t *sync; + int found = 0; + + for(lp = haystack; lp && !found; lp = lp->next) { + sync = (syncpkg_t*)lp->data; + if(sync && !strcmp(sync->pkg->name, needle->pkg->name)) { + found = 1; + } + } + + return found; +} + /* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacsync.h b/src/pacsync.h index 1838a684..abb657f8 100644 --- a/src/pacsync.h +++ b/src/pacsync.h @@ -21,12 +21,14 @@ #ifndef _PAC_PACSYNC_H #define _PAC_PACSYNC_H +/* Servers */ typedef struct __server_t { unsigned short islocal; char* server; char* path; } server_t; +/* Repositories */ typedef struct __sync_t { char* treename; PMList *servers; @@ -46,6 +48,7 @@ typedef struct __syncpkg_t { int sync_synctree(); int downloadfiles(PMList *servers, char *localpath, PMList *files); +int is_pkginsync(syncpkg_t *needle, PMList *haystack); #endif diff --git a/src/rpmvercmp.h b/src/rpmvercmp.h new file mode 100644 index 00000000..3b7df650 --- /dev/null +++ b/src/rpmvercmp.h @@ -0,0 +1,28 @@ +/* + * pacman + * + * Copyright (c) 2002 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_RPMVERCMP_H +#define _PAC_RPMVERCMP_H + +int rpmvercmp(const char *a, const char *b); + +#endif + +/* vim: set ts=2 sw=2 noet: */ @@ -24,52 +24,16 @@ #include <stdlib.h> #include <stdarg.h> #include <string.h> -#include <limits.h> #include <errno.h> #include <fcntl.h> -#include <libgen.h> -#include <getopt.h> #include <ctype.h> -#include "list.h" -#include "package.h" -#include "db.h" +#include <dirent.h> +#include <zlib.h> +#include <libtar.h> #include "util.h" -#include "pacsync.h" -#include "pacman.h" -/* command line options */ -extern char* pmo_root; -extern unsigned short pmo_op; -extern unsigned short pmo_version; -extern unsigned short pmo_verbose; -extern unsigned short pmo_help; -extern unsigned short pmo_force; -extern unsigned short pmo_nodeps; -extern unsigned short pmo_upgrade; -extern unsigned short pmo_freshen; -extern unsigned short pmo_nosave; -extern unsigned short pmo_d_vertest; -extern unsigned short pmo_d_resolve; -extern unsigned short pmo_q_isfile; -extern unsigned short pmo_q_info; -extern unsigned short pmo_q_list; -extern unsigned short pmo_q_owns; -extern unsigned short pmo_r_cascade; -extern unsigned short pmo_s_sync; -extern unsigned short pmo_s_search; -extern unsigned short pmo_s_clean; -extern unsigned short pmo_s_upgrade; -extern unsigned short pmo_s_downloadonly; -/* configuration file options */ -extern PMList *pmo_noupgrade; -extern PMList *pmo_ignorepkg; -extern unsigned short pmo_nopassiveftp; - -extern PMList *pmc_syncs; -extern PMList *pm_targets; - -/* borrowed and modifed from Per Liden's pkgutils (http://crux.nu) */ -static int gzopen_frontend(char *pathname, int oflags, int mode) +/* borrowed and modified from Per Liden's pkgutils (http://crux.nu) */ +int gzopen_frontend(char *pathname, int oflags, int mode) { char* gzoflags; int fd; @@ -102,17 +66,16 @@ static int gzopen_frontend(char *pathname, int oflags, int mode) return (int)gzf; } -tartype_t gztype = { - (openfunc_t) gzopen_frontend, - (closefunc_t)gzclose, - (readfunc_t) gzread, - (writefunc_t)gzwrite -}; - int unpack(char *archive, char *prefix) { TAR *tar = NULL; char expath[PATH_MAX]; + tartype_t gztype = { + (openfunc_t) gzopen_frontend, + (closefunc_t)gzclose, + (readfunc_t) gzread, + (writefunc_t)gzwrite + }; /* open the .tar.gz package */ if(tar_open(&tar, archive, &gztype, O_RDONLY, 0, TAR_GNU) == -1) { @@ -130,280 +93,6 @@ int unpack(char *archive, char *prefix) return(0); } -/* Parse command-line arguments for each operation - * op: the operation code requested - * argc: argc - * argv: argv - * - * Returns: 0 on success, 1 on error - */ -int parseargs(int op, int argc, char **argv) -{ - int opt; - int option_index = 0; - static struct option opts[] = - { - {"add", no_argument, 0, 'A'}, - {"remove", no_argument, 0, 'R'}, - {"upgrade", no_argument, 0, 'U'}, - {"freshen", no_argument, 0, 'F'}, - {"query", no_argument, 0, 'Q'}, - {"sync", no_argument, 0, 'S'}, - {"deptest", no_argument, 0, 'T'}, - {"vertest", no_argument, 0, 'Y'}, - {"resolve", no_argument, 0, 'D'}, - {"root", required_argument, 0, 'r'}, - {"verbose", no_argument, 0, 'v'}, - {"version", no_argument, 0, 'V'}, - {"help", no_argument, 0, 'h'}, - {"search", no_argument, 0, 's'}, - {"clean", no_argument, 0, 'c'}, - {"force", no_argument, 0, 'f'}, - {"nodeps", no_argument, 0, 'd'}, - {"nosave", no_argument, 0, 'n'}, - {"owns", no_argument, 0, 'o'}, - {"list", no_argument, 0, 'l'}, - {"file", no_argument, 0, 'p'}, - {"info", no_argument, 0, 'i'}, - {"sysupgrade", no_argument, 0, 'u'}, - {"downloadonly", no_argument, 0, 'w'}, - {"refresh", no_argument, 0, 'y'}, - {"cascade", no_argument, 0, 'c'}, - {0, 0, 0, 0} - }; - - while((opt = getopt_long(argc, argv, "ARUFQSTDYr:vhscVfnoldpiuwy", opts, &option_index))) { - if(opt < 0) { - break; - } - switch(opt) { - case 0: break; - case 'A': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_ADD); break; - case 'R': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_REMOVE); break; - case 'U': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_UPGRADE); break; - case 'F': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_UPGRADE); pmo_freshen = 1; break; - case 'Q': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_QUERY); break; - case 'S': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_SYNC); break; - case 'T': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_DEPTEST); break; - case 'Y': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_DEPTEST); pmo_d_vertest = 1; break; - case 'D': pmo_op = (pmo_op != PM_MAIN ? 0 : PM_DEPTEST); pmo_d_resolve = 1; break; - case 'h': pmo_help = 1; break; - case 'V': pmo_version = 1; break; - case 'v': pmo_verbose = 1; break; - case 'f': pmo_force = 1; break; - case 'd': pmo_nodeps = 1; break; - case 'n': pmo_nosave = 1; break; - case 'l': pmo_q_list = 1; break; - case 'p': pmo_q_isfile = 1; break; - case 'i': pmo_q_info = 1; break; - case 'o': pmo_q_owns = 1; break; - case 'u': pmo_s_upgrade = 1; break; - case 'w': pmo_s_downloadonly = 1; break; - case 'y': pmo_s_sync = 1; break; - case 's': pmo_s_search = 1; break; - case 'c': pmo_s_clean = 1; pmo_r_cascade = 1; break; - case 'r': if(realpath(optarg, pmo_root) == NULL) { - perror("bad root path"); - return(1); - } break; - case '?': return(1); - default: return(1); - } - } - - if(pmo_op == 0) { - fprintf(stderr, "error: only one operation may be used at a time\n\n"); - return(1); - } - - if(pmo_help) { - usage(pmo_op, (char*)basename(argv[0])); - return(2); - } - if(pmo_version) { - version(); - return(2); - } - - while(optind < argc) { - /* add the target to our target array */ - char *s = strdup(argv[optind]); - pm_targets = list_add(pm_targets, s); - optind++; - } - - return(0); -} - -#define min(X, Y) ((X) < (Y) ? (X) : (Y)) -int parseconfig(char *configfile) -{ - FILE *fp = NULL; - char line[PATH_MAX+1]; - char *ptr = NULL; - char *key = NULL; - int linenum = 0; - char section[256] = ""; - sync_t *sync = NULL; - - if((fp = fopen(configfile, "r")) == NULL) { - perror(configfile); - return(1); - } - - while(fgets(line, PATH_MAX, fp)) { - linenum++; - trim(line); - if(strlen(line) == 0 || line[0] == '#') { - continue; - } - if(line[0] == '[' && line[strlen(line)-1] == ']') { - /* new config section */ - ptr = line; - ptr++; - strncpy(section, ptr, min(255, strlen(ptr)-1)); - section[min(255, strlen(ptr)-1)] = '\0'; - vprint("config: new section '%s'\n", section); - if(!strlen(section)) { - fprintf(stderr, "config: line %d: bad section name\n", linenum); - return(1); - } - if(!strcmp(section, "local")) { - fprintf(stderr, "config: line %d: %s is reserved and cannot be used as a package tree\n", - linenum, section); - return(1); - } - if(strcmp(section, "options")) { - /* start a new sync record */ - MALLOC(sync, sizeof(sync_t)); - sync->treename = strdup(section); - sync->servers = NULL; - pmc_syncs = list_add(pmc_syncs, sync); - } - } else { - /* directive */ - if(!strlen(section)) { - fprintf(stderr, "config: line %d: all directives must belong to a section\n", linenum); - return(1); - } - ptr = line; - key = strsep(&ptr, "="); - if(key == NULL) { - fprintf(stderr, "config: line %d: syntax error\n", linenum); - return(1); - } - trim(key); - key = strtoupper(key); - if(ptr == NULL) { - if(!strcmp(key, "NOPASSIVEFTP")) { - pmo_nopassiveftp = 1; - vprint("config: nopassiveftp\n"); - } else { - fprintf(stderr, "config: line %d: syntax error\n", linenum); - return(1); - } - } else { - trim(ptr); - if(!strcmp(section, "options")) { - if(!strcmp(key, "NOUPGRADE")) { - char *p = ptr; - char *q; - while((q = strchr(p, ' '))) { - *q = '\0'; - pmo_noupgrade = list_add(pmo_noupgrade, strdup(p)); - vprint("config: noupgrade: %s\n", p); - p = q; - p++; - } - pmo_noupgrade = list_add(pmo_noupgrade, strdup(p)); - vprint("config: noupgrade: %s\n", p); - } else if(!strcmp(key, "IGNOREPKG")) { - char *p = ptr; - char *q; - while((q = strchr(p, ' '))) { - *q = '\0'; - pmo_ignorepkg = list_add(pmo_ignorepkg, strdup(p)); - vprint("config: ignorepkg: %s\n", p); - p = q; - p++; - } - pmo_ignorepkg = list_add(pmo_ignorepkg, strdup(p)); - vprint("config: ignorepkg: %s\n", p); - } else { - fprintf(stderr, "config: line %d: syntax error\n", linenum); - return(1); - } - } else { - if(!strcmp(key, "SERVER")) { - /* parse our special url */ - server_t *server; - char *p; - - MALLOC(server, sizeof(server_t)); - server->server = server->path = NULL; - server->islocal = 0; - - p = strstr(ptr, "://"); - if(p == NULL) { - fprintf(stderr, "config: line %d: bad server location\n", linenum); - return(1); - } - *p = '\0'; - p++; p++; p++; - if(p == NULL || *p == '\0') { - fprintf(stderr, "config: line %d: bad server location\n", linenum); - return(1); - } - server->islocal = !strcmp(ptr, "local"); - if(!server->islocal) { - char *slash; - /* no http support yet */ - if(strcmp(ptr, "ftp")) { - fprintf(stderr, "config: line %d: protocol %s is not supported\n", linenum, ptr); - return(1); - } - /* split the url into domain and path */ - slash = strchr(p, '/'); - if(slash == NULL) { - /* no path included, default to / */ - server->path = strdup("/"); - } else { - /* add a trailing slash if we need to */ - if(slash[strlen(slash)-1] == '/') { - server->path = strdup(slash); - } else { - MALLOC(server->path, strlen(slash)+2); - sprintf(server->path, "%s/", slash); - } - *slash = '\0'; - } - server->server = strdup(p); - } else { - /* add a trailing slash if we need to */ - if(p[strlen(p)-1] == '/') { - server->path = strdup(p); - } else { - MALLOC(server->path, strlen(p)+2); - sprintf(server->path, "%s/", p); - } - } - /* add to the list */ - vprint("config: %s: server: %s %s\n", section, server->server, server->path); - sync->servers = list_add(sync->servers, server); - } else { - fprintf(stderr, "config: line %d: syntax error\n", linenum); - return(1); - } - } - line[0] = '\0'; - } - } - } - fclose(fp); - - return(0); -} - int copyfile(char *src, char *dest) { FILE *in, *out; @@ -501,94 +190,6 @@ int rmrf(char *path) return(0); } -/* Display usage/syntax for the specified operation. - * op: the operation code requested - * myname: basename(argv[0]) - */ -void usage(int op, char *myname) -{ - if(op == PM_MAIN) { - printf("usage: %s {-h --help}\n", myname); - printf(" %s {-V --version}\n", myname); - printf(" %s {-A --add} [options] <file>\n", myname); - printf(" %s {-R --remove} [options] <package>\n", myname); - printf(" %s {-U --upgrade} [options] <file>\n", myname); - printf(" %s {-F --freshen} [options] <file>\n", myname); - printf(" %s {-Q --query} [options] [package]\n", myname); - printf(" %s {-S --sync} [options] [package]\n", myname); - printf("\nuse '%s --help' with other options for more syntax\n\n", myname); - } else { - if(op == PM_ADD) { - printf("usage: %s {-A --add} [options] <file>\n", myname); - printf("options:\n"); - printf(" -f, --force force install, overwrite conflicting files\n"); - printf(" -d, --nodeps skip dependency checks\n"); - } else if(op == PM_REMOVE) { - printf("usage: %s {-R --remove} [options] <package>\n", myname); - printf("options:\n"); - printf(" -d, --nodeps skip dependency checks\n"); - printf(" -n, --nosave remove configuration files as well\n"); - printf(" -c, --cascade remove packages and all packages that depend on them\n"); - } else if(op == PM_UPGRADE) { - if(pmo_freshen) { - printf("usage: %s {-F --freshen} [options] <file>\n", myname); - } else { - printf("usage: %s {-U --upgrade} [options] <file>\n", myname); - } - printf("options:\n"); - printf(" -f, --force force install, overwrite conflicting files\n"); - printf(" -d, --nodeps skip dependency checks\n"); - } else if(op == PM_QUERY) { - printf("usage: %s {-Q --query} [options] [package]\n", myname); - printf("options:\n"); - printf(" -o, --owns <file> query the package that owns <file>\n"); - printf(" -l, --list list the contents of the queried package\n"); - printf(" -i, --info view package information\n"); - printf(" -p, --file pacman will query the package file [package] instead of\n"); - printf(" looking in the database\n"); - } else if(op == PM_SYNC) { - printf("usage: %s {-S --sync} [options] [package]\n", myname); - printf("options:\n"); - printf(" -s, --search search sync database for matching strings\n"); - printf(" -f, --force force install, overwrite conflicting files\n"); - printf(" -d, --nodeps skip dependency checks\n"); - printf(" -y, --refresh download a fresh package sync database from the server\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(" -c, --clean remove packages from cache directory to free up diskspace\n"); - } - printf(" -v, --verbose be verbose\n"); - printf(" -r, --root <path> set an alternate installation root\n"); - } -} - -/* Version - */ -void version(void) -{ - printf("\n"); - printf(" .--. Pacman v%s\n", PACVER); - printf("/ _.-' .-. .-. .-. Copyright (C) 2002 Judd Vinet <jvinet@zeroflux.org>\n"); - printf("\\ '-. '-' '-' '-' \n"); - printf(" '--' This program may be freely redistributed under\n"); - printf(" the terms of the GNU GPL\n\n"); -} - -/* Check verbosity option and, if set, print the - * string to stdout - */ -int vprint(char *fmt, ...) -{ - va_list args; - if(pmo_verbose) { - va_start(args, fmt); - vprintf(fmt, args); - va_end(args); - fflush(stdout); - } - return(0); -} - int yesno(char *fmt, ...) { char response[32]; @@ -651,76 +252,6 @@ void indentprint(char *str, int indent) } } -/* Test for existence of a string in a PMList - */ -int is_in(char *needle, PMList *haystack) -{ - PMList *lp; - - for(lp = haystack; lp; lp = lp->next) { - if(lp->data && !strcmp(lp->data, needle)) { - return(1); - } - } - return(0); -} - - -/* Look for a filename in a pkginfo_t.backup list. If we find it, - * then we return the md5 hash (parsed from the same line) - */ -char* needbackup(char* file, PMList *backup) -{ - PMList *lp; - - /* run through the backup list and parse out the md5 hash for our file */ - for(lp = backup; lp; lp = lp->next) { - char* str = strdup(lp->data); - char* ptr; - - /* tab delimiter */ - ptr = index(str, '\t'); - if(ptr == NULL) { - FREE(str); - continue; - } - *ptr = '\0'; - ptr++; - /* now str points to the filename and ptr points to the md5 hash */ - if(!strcmp(file, str)) { - char *md5 = strdup(ptr); - FREE(str); - return(md5); - } - FREE(str); - } - return(NULL); -} - -/* Test for existence of a package in a PMList* - * of pkginfo_t* - * - * returns: 0 for no match - * 1 for identical match - * -1 for name-only match (version mismatch) - */ -int is_pkgin(pkginfo_t *needle, PMList *haystack) -{ - PMList *lp; - pkginfo_t *info; - - for(lp = haystack; lp; lp = lp->next) { - info = (pkginfo_t*)lp->data; - if(info && !strcmp(info->name, needle->name)) { - if(!strcmp(info->version, needle->version)) { - return(1); - } - return(-1); - } - } - return(0); -} - /* Convert a string to uppercase */ char* strtoupper(char *str) @@ -21,30 +21,20 @@ #ifndef _PAC_UTIL_H #define _PAC_UTIL_H -#include <libtar.h> -#include <zlib.h> - #define MALLOC(p, b) { if((b) > 0) { \ p = malloc(b); if (!(p)) { \ - fprintf(stderr, "malloc failure: could not allocate %d byets\n", b); \ + fprintf(stderr, "malloc failure: could not allocate %d bytes\n", b); \ exit(1); }} else p = NULL; } #define FREE(p) { if (p) { free(p); (p)= NULL; }} +int gzopen_frontend(char *pathname, int oflags, int mode); int unpack(char *archive, char *prefix); -int parseargs(int op, int argc, char **argv); -int parseconfig(char *configfile); int copyfile(char *src, char *dest); int makepath(char *path); int rmrf(char *path); -int vprint(char *fmt, ...); void indentprint(char *str, int indent); int yesno(char* fmt, ...); -void usage(int op, char *myname); -void version(void); -char* needbackup(char *file, PMList *backup); -int is_in(char *needle, PMList *haystack); -int is_pkgin(pkginfo_t *needle, PMList *haystack); char* trim(char *str); char* strtoupper(char *str); diff --git a/src/vercmp.c b/src/vercmp.c index 850ebea6..43f8deab 100644 --- a/src/vercmp.c +++ b/src/vercmp.c @@ -1,7 +1,27 @@ +/* + * pacman + * + * Copyright (c) 2002 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. + */ + #include <stdio.h> #include <string.h> - -int rpmvercmp(const char *a, const char *b); +#include "rpmvercmp.h" int main(int argc, char *argv[]) { |