summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/convertdb.c24
-rw-r--r--src/db.c81
-rw-r--r--src/db.h5
-rw-r--r--src/list.c94
-rw-r--r--src/list.h24
-rw-r--r--src/md5.h3
-rw-r--r--src/md5driver.c3
-rw-r--r--src/package.c129
-rw-r--r--src/package.h5
-rw-r--r--src/pacman.c696
-rw-r--r--src/pacman.h12
-rw-r--r--src/pacsync.c40
-rw-r--r--src/pacsync.h3
-rw-r--r--src/rpmvercmp.h28
-rw-r--r--src/util.c491
-rw-r--r--src/util.h14
-rw-r--r--src/vercmp.c24
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: */
diff --git a/src/db.c b/src/db.c
index b2489bb1..bf7be9f9 100644
--- a/src/db.c
+++ b/src/db.c
@@ -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) {
diff --git a/src/db.h b/src/db.h
index 7428e270..11404134 100644
--- a/src/db.h
+++ b/src/db.h
@@ -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: */
diff --git a/src/list.c b/src/list.c
index 717aab2b..dfb8f630 100644
--- a/src/list.c
+++ b/src/list.c
@@ -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: */
diff --git a/src/list.h b/src/list.h
index 68ff5651..edfc6f97 100644
--- a/src/list.h
+++ b/src/list.h
@@ -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
diff --git a/src/md5.h b/src/md5.h
index b5ce6fd9..e6e4ea64 100644
--- a/src/md5.h
+++ b/src/md5.h
@@ -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: */
diff --git a/src/util.c b/src/util.c
index 2b0aa0d9..cd7978e9 100644
--- a/src/util.c
+++ b/src/util.c
@@ -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)
diff --git a/src/util.h b/src/util.h
index 222c00fa..be2c6089 100644
--- a/src/util.h
+++ b/src/util.h
@@ -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[])
{