diff options
Diffstat (limited to 'src/pacman.c')
-rw-r--r-- | src/pacman.c | 696 |
1 files changed, 515 insertions, 181 deletions
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) { |