summaryrefslogtreecommitdiffstats
path: root/src/pacman.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pacman.c')
-rw-r--r--src/pacman.c249
1 files changed, 177 insertions, 72 deletions
diff --git a/src/pacman.c b/src/pacman.c
index e2db8721..3b5d3ddb 100644
--- a/src/pacman.c
+++ b/src/pacman.c
@@ -35,6 +35,7 @@
#include <zlib.h>
#include <syslog.h>
#include <libtar.h>
+#include <dirent.h>
/* pacman */
#include "rpmvercmp.h"
#include "md5.h"
@@ -68,6 +69,7 @@ unsigned short pmo_q_info = 0;
unsigned short pmo_q_list = 0;
unsigned short pmo_q_orphans = 0;
unsigned short pmo_q_owns = 0;
+unsigned short pmo_q_search = 0;
unsigned short pmo_r_cascade = 0;
unsigned short pmo_r_dbonly = 0;
unsigned short pmo_r_recurse = 0;
@@ -322,21 +324,96 @@ int pacman_sync(pacdb_t *db, PMList *targets)
}
if(pmo_s_clean) {
- mode_t oldmask;
+ if(pmo_s_clean == 1) {
+ /* incomplete cleanup: we keep latest packages and partial downloads */
+ DIR *dir;
+ struct dirent *ent;
+ PMList *cache = NULL;
+ PMList *clean = NULL;
+ PMList *i, *j;
+
+ printf("removing old packages from cache... ");
+ dir = opendir("/var/cache/pacman/pkg");
+ if(dir == NULL) {
+ fprintf(stderr, "error: could not access cache directory\n");
+ return(1);
+ }
+ rewinddir(dir);
+ while((ent = readdir(dir)) != NULL) {
+ if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {
+ continue;
+ }
+ cache = list_add(cache, strdup(ent->d_name));
+ }
+ closedir(dir);
- printf("removing packages from cache... ");
- if(rmrf("/var/cache/pacman/pkg")) {
- fprintf(stderr, "error: could not remove cache directory: %s\n", strerror(errno));
- return(1);
- }
+ for(i = cache; i; i = i->next) {
+ char *str = (char *)i->data;
+ char *name, *version;
- oldmask = umask(0000);
- if(makepath("/var/cache/pacman/pkg")) {
- fprintf(stderr, "error: could not create new cache directory: %s\n", strerror(errno));
- return(1);
- }
- umask(oldmask);
+ if(split_pkgname(str, &name, &version) != 0) {
+ clean = list_add(clean, strdup(str));
+ continue;
+ }
+ /* we keep partially downloaded files */
+ if(strstr(str, ".pkg.tar.gz.part")) {
+ FREE(name);
+ FREE(version);
+ continue;
+ }
+ for(j = i->next; j; j = j->next) {
+ char *s = (char *)j->data;
+ char *n, *v;
+ if(split_pkgname(s, &n, &v) != 0) {
+ continue;
+ }
+ if(!strcmp(name, n)) {
+ char *ptr;
+ if(rpmvercmp(version, v) < 0) {
+ ptr = str;
+ } else {
+ ptr = s;
+ }
+ if(!is_in(ptr, clean)) {
+ clean = list_add(clean, strdup(ptr));
+ }
+ }
+ FREE(n);
+ FREE(v);
+ }
+ FREE(name);
+ FREE(version);
+ }
+ FREELIST(cache);
+
+ for(i = clean; i; i = i->next) {
+ char path[PATH_MAX];
+
+ snprintf(path, PATH_MAX, "%s%s/%s", pmo_root, CACHEDIR, (char *)i->data);
+ unlink(path);
+ }
+ FREELIST(clean);
+ } else {
+ /* full cleanup */
+ mode_t oldmask;
+ char path[PATH_MAX];
+
+ snprintf(path, PATH_MAX, "%s%s", pmo_root, CACHEDIR);
+
+ printf("removing all packages from cache... ");
+ if(rmrf(path)) {
+ fprintf(stderr, "error: could not remove cache directory: %s\n", strerror(errno));
+ return(1);
+ }
+
+ oldmask = umask(0000);
+ if(makepath(path)) {
+ fprintf(stderr, "error: could not create new cache directory: %s\n", strerror(errno));
+ return(1);
+ }
+ umask(oldmask);
+ }
printf("done.\n");
return(0);
}
@@ -374,53 +451,9 @@ int pacman_sync(pacdb_t *db, PMList *targets)
if(pmo_s_search) {
/* search sync databases */
if(targets) {
- for(i = targets; i; i = i->next) {
- char *targ = strdup(i->data);
- strtoupper(targ);
- for(j = databases; j; j = j->next) {
- dbsync_t *dbs = (dbsync_t*)j->data;
- for(k = dbs->pkgcache; k; k = k->next) {
- pkginfo_t *pkg = (pkginfo_t*)k->data;
- char *haystack;
- PMList *m;
- int match = 0;
- /* check name */
- haystack = strdup(pkg->name);
- strtoupper(haystack);
- if(strstr(haystack, targ)) {
- match = 1;
- }
- FREE(haystack);
-
- /* check description */
- haystack = strdup(pkg->desc);
- strtoupper(haystack);
- if(strstr(haystack, targ)) {
- match = 1;
- }
- FREE(haystack);
-
- if(!match) {
- pkg = db_scan(dbs->db, pkg->name, INFRQ_DESC | INFRQ_DEPENDS);
- /* check provides */
- for(m = pkg->provides; m; m = m->next) {
- haystack = strdup(m->data);
- strtoupper(haystack);
- if(strstr(haystack, targ)) {
- match = 1;
- }
- FREE(haystack);
- }
- }
-
- if(match) {
- printf("%s/%s %s\n ", dbs->sync->treename, pkg->name, pkg->version);
- indentprint(pkg->desc, 4);
- printf("\n");
- }
- }
- }
- FREE(targ);
+ for(j = databases; j; j = j->next) {
+ dbsync_t *dbs = (dbsync_t*)j->data;
+ db_search(dbs->db, dbs->pkgcache, dbs->sync->treename, targets);
}
} else {
for(j = databases; j; j = j->next) {
@@ -1381,7 +1414,7 @@ int pacman_add(pacdb_t *db, PMList *targets)
for(targ = targets; targ; targ = targ->next) {
/* Populate the package struct */
vprint("reading %s... ", (char*)targ->data);
- info = load_pkg((char*)targ->data, 0);
+ info = load_pkg((char*)targ->data);
if(info == NULL) {
return(1);
}
@@ -1957,7 +1990,7 @@ int pacman_remove(pacdb_t *db, PMList *targets)
depmissing_t* miss = (depmissing_t*)j->data;
printf(" %s: is required by %s\n", miss->target, miss->depend.name);
}
- list_free(alltargs);
+ FREELISTPKGS(alltargs);
list_free(lp);
return(1);
}
@@ -1973,7 +2006,7 @@ int pacman_remove(pacdb_t *db, PMList *targets)
list_display("\nTargets:", alltargs);
/* get confirmation */
if(yesno("\nDo you want to remove these packages? [Y/n] ") == 0) {
- list_free(alltargs);
+ FREELISTPKGS(alltargs);
return(1);
}
}
@@ -2048,6 +2081,18 @@ int pacman_remove(pacdb_t *db, PMList *targets)
}
}
+ if(!pmo_upgrade) {
+ /* run the post-remove script if it exists */
+ snprintf(pm_install, PATH_MAX, "%s%s/%s/%s-%s/install", pmo_root, pmo_dbpath, db->treename, info->name, info->version);
+ if(!stat(pm_install, &buf)) {
+ vprint("Executing post-remove script...\n");
+ snprintf(pm_install, PATH_MAX, "%s/%s/%s-%s/install", pmo_dbpath, db->treename, info->name, info->version);
+ snprintf(line, PATH_MAX, "chroot %s /bin/sh %s post_remove %s", pmo_root, pm_install, info->version);
+
+ system(line);
+ }
+ }
+
/* remove the package from the database */
snprintf(line, PATH_MAX, "%s%s/%s/%s-%s", pmo_root, pmo_dbpath, db->treename,
info->name, info->version);
@@ -2118,7 +2163,7 @@ int pacman_remove(pacdb_t *db, PMList *targets)
}
}
- FREELIST(alltargs);
+ FREELISTPKGS(alltargs);
/* run ldconfig if it exists */
snprintf(line, PATH_MAX, "%setc/ld.so.conf", pmo_root);
@@ -2143,6 +2188,11 @@ int pacman_query(pacdb_t *db, PMList *targets)
PMList *targ, *lp, *q;
int done = 0;
+ if(pmo_q_search) {
+ db_search(db, pm_packages, "local", targets);
+ return(0);
+ }
+
for(targ = targets; !done; targ = (targ ? targ->next : NULL)) {
if(targets == NULL) {
done = 1;
@@ -2187,12 +2237,13 @@ int pacman_query(pacdb_t *db, PMList *targets)
fprintf(stderr, "error: no package file was specified for --file\n");
return(1);
}
- info = load_pkg(package, pmo_q_info);
+ info = load_pkg(package);
if(info == NULL) {
fprintf(stderr, "error: %s is not a package\n", package);
return(1);
}
if(pmo_q_info) {
+ dump_pkg_full(info);
printf("\n");
} else if(pmo_q_list) {
for(lp = info->files; lp; lp = lp->next) {
@@ -2670,8 +2721,26 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
for(j = tp->conflicts; j; j = j->next) {
/* check targets against database */
for(k = pm_packages; k; k = k->next) {
+ int conflict = 0;
pkginfo_t *dp = (pkginfo_t*)k->data;
+ if(!strcmp(dp->name, tp->name)) {
+ /* a package cannot conflict with itself -- that's just not nice */
+ continue;
+ }
if(!strcmp(j->data, dp->name)) {
+ /* dp is listed in tp's conflict list */
+ conflict = 1;
+ } else {
+ /* see if dp provides something in tp's conflict list */
+ PMList *m;
+ for(m = dp->provides; m; m = m->next) {
+ if(!strcmp(m->data, j->data)) {
+ conflict = 1;
+ break;
+ }
+ }
+ }
+ if(conflict) {
MALLOC(miss, sizeof(depmissing_t));
miss->type = CONFLICT;
miss->depend.mod = DEP_ANY;
@@ -2685,14 +2754,32 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
}
/* check targets against targets */
for(k = targets; k; k = k->next) {
- pkginfo_t *a = (pkginfo_t*)k->data;
- if(!strcmp(a->name, (char*)j->data)) {
+ int conflict = 0;
+ pkginfo_t *otp = (pkginfo_t*)k->data;
+ if(!strcmp(otp->name, tp->name)) {
+ /* a package cannot conflict with itself -- that's just not nice */
+ continue;
+ }
+ if(!strcmp(otp->name, (char*)j->data)) {
+ /* otp is listed in tp's conflict list */
+ conflict = 1;
+ } else {
+ /* see if otp provides something in tp's conflict list */
+ PMList *m;
+ for(m = otp->provides; m; m = m->next) {
+ if(!strcmp(m->data, j->data)) {
+ conflict = 1;
+ break;
+ }
+ }
+ }
+ if(conflict) {
MALLOC(miss, sizeof(depmissing_t));
miss->type = CONFLICT;
miss->depend.mod = DEP_ANY;
miss->depend.version[0] = '\0';
strncpy(miss->target, tp->name, 256);
- strncpy(miss->depend.name, a->name, 256);
+ strncpy(miss->depend.name, otp->name, 256);
if(!list_isin(baddeps, miss)) {
baddeps = list_add(baddeps, miss);
}
@@ -2703,7 +2790,24 @@ PMList* checkdeps(pacdb_t *db, unsigned short op, PMList *targets)
rewinddir(db->dir);
while((info = db_scan(db, NULL, INFRQ_DESC | INFRQ_DEPENDS)) != NULL) {
for(j = info->conflicts; j; j = j->next) {
+ int conflict = 0;
+ if(!strcmp(info->name, tp->name)) {
+ /* a package cannot conflict with itself -- that's just not nice */
+ continue;
+ }
if(!strcmp((char*)j->data, tp->name)) {
+ conflict = 1;
+ } else {
+ /* see if tp provides something in info's conflict list */
+ PMList *m;
+ for(m = tp->provides; m; m = m->next) {
+ if(!strcmp(m->data, j->data)) {
+ conflict = 1;
+ break;
+ }
+ }
+ }
+ if(conflict) {
MALLOC(miss, sizeof(depmissing_t));
miss->type = CONFLICT;
miss->depend.mod = DEP_ANY;
@@ -3015,7 +3119,7 @@ int parseargs(int op, int argc, char **argv)
case 'h': pmo_help = 1; break;
case 'V': pmo_version = 1; break;
case 'b': strcpy(pmo_dbpath, optarg); break;
- case 'c': pmo_s_clean = 1; pmo_r_cascade = 1; break;
+ case 'c': pmo_s_clean++; pmo_r_cascade = 1; break;
case 'd': pmo_nodeps = 1; break;
case 'e': pmo_q_orphans = 1; break;
case 'f': pmo_force = 1; break;
@@ -3030,7 +3134,7 @@ int parseargs(int op, int argc, char **argv)
perror("bad root path");
return(1);
} break;
- case 's': pmo_s_search = 1; pmo_r_recurse = 1; break;
+ case 's': pmo_s_search = 1; pmo_q_search = 1; pmo_r_recurse = 1; break;
case 'u': pmo_s_upgrade = 1; break;
case 'v': pmo_verbose = 1; break;
case 'w': pmo_s_downloadonly = 1; break;
@@ -3317,20 +3421,21 @@ void usage(int op, char *myname)
printf(" -o, --owns <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");
+ printf(" -s, --search search locally-installed packages for matching strings\n");
} else if(op == PM_SYNC) {
printf("usage: %s {-S --sync} [options] [package]\n", myname);
printf("options:\n");
- printf(" -c, --clean remove packages from cache directory to free up diskspace\n");
+ printf(" -c, --clean remove old packages from cache directory (use -cc for all)\n");
printf(" -d, --nodeps skip dependency checks\n");
printf(" -f, --force force install, overwrite conflicting files\n");
printf(" -g, --groups view all members of a package group\n");
printf(" -i, --info view package information\n");
printf(" -l, --list list all packages belonging to the specified repository\n");
printf(" -p, --print-uris print out download URIs for each package to be installed\n");
- printf(" -s, --search search sync database for matching strings\n");
+ printf(" -s, --search search remote repositories for matching strings\n");
printf(" -u, --sysupgrade upgrade all packages that are out of date\n");
printf(" -w, --downloadonly download packages, but do not install/upgrade anything\n");
- printf(" -y, --refresh download a fresh package sync database from the server\n");
+ printf(" -y, --refresh download fresh package databases from the server\n");
}
printf(" -v, --verbose be verbose\n");
printf(" -r, --root <path> set an alternate installation root\n");