summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJudd Vinet <judd@archlinux.org>2004-09-18 20:37:34 +0200
committerJudd Vinet <judd@archlinux.org>2004-09-18 20:37:34 +0200
commit4ffc53b3398ae845183f991a56207459256cc9e9 (patch)
treef71a9fa0c0ab1bc87dd84cf07828fe95efbb849f /src
parentafc0d9a3c45b70edd948ce0be4a5e81d4da00c7e (diff)
downloadpacman-4ffc53b3398ae845183f991a56207459256cc9e9.tar.gz
pacman-4ffc53b3398ae845183f991a56207459256cc9e9.tar.xz
Imported from pacman-2.9.tar.gz
Diffstat (limited to 'src')
-rw-r--r--src/db.c23
-rw-r--r--src/list.c17
-rw-r--r--src/list.h3
-rw-r--r--src/package.c28
-rw-r--r--src/package.h5
-rw-r--r--src/pacman.c341
-rw-r--r--src/pacman.h7
-rw-r--r--src/util.c1
8 files changed, 263 insertions, 162 deletions
diff --git a/src/db.c b/src/db.c
index 428b99e7..0faf5870 100644
--- a/src/db.c
+++ b/src/db.c
@@ -225,6 +225,14 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq)
return(NULL);
}
trim(info->packager);
+ } else if(!strcmp(line, "%REASON%")) {
+ char tmp[32];
+ if(fgets(tmp, sizeof(tmp), fp) == NULL) {
+ FREEPKG(info);
+ return(NULL);
+ }
+ trim(tmp);
+ info->reason = (unsigned short)atoi(tmp);
} else if(!strcmp(line, "%SIZE%")) {
char tmp[32];
if(fgets(tmp, sizeof(tmp), fp) == NULL) {
@@ -232,6 +240,19 @@ pkginfo_t* db_read(pacdb_t *db, struct dirent *ent, unsigned int inforeq)
return(NULL);
}
trim(tmp);
+ info->size = (unsigned long)atol(tmp);
+ } else if(!strcmp(line, "%CSIZE%")) {
+ /* NOTE: the CSIZE and SIZE fields both share the "size" field
+ * in the pkginfo_t struct. This can be done b/c CSIZE
+ * is currently only used in sync databases, and SIZE is
+ * only used in local databases.
+ */
+ char tmp[32];
+ if(fgets(tmp, sizeof(tmp), fp) == NULL) {
+ FREEPKG(info);
+ return(NULL);
+ }
+ trim(tmp);
info->size = atol(tmp);
} else if(!strcmp(line, "%REPLACES%")) {
/* the REPLACES tag is special -- it only appears in sync repositories,
@@ -387,6 +408,8 @@ int db_write(pacdb_t *db, pkginfo_t *info, unsigned int inforeq)
fprintf(fp, "%s\n\n", info->packager);
fputs("%SIZE%\n", fp);
fprintf(fp, "%ld\n\n", info->size);
+ fputs("%REASON%\n", fp);
+ fprintf(fp, "%d\n\n", info->reason);
fclose(fp);
}
diff --git a/src/list.c b/src/list.c
index b07e347f..0ec43353 100644
--- a/src/list.c
+++ b/src/list.c
@@ -102,16 +102,16 @@ int list_isin(PMList *haystack, void *needle)
/* Test for existence of a string in a PMList
*/
-int is_in(char *needle, PMList *haystack)
+PMList* 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(lp);
}
}
- return(0);
+ return(NULL);
}
/* List one is extended and returned
@@ -224,6 +224,17 @@ void list_display(const char *title, PMList *list)
}
+/* Helper function for comparing string nodes.
+ */
+int strlist_cmp(const void *s1, const void *s2)
+{
+ char *str1 = (char *)s1;
+ char *str2 = (char *)s2;
+
+ return(strcmp(str1, str2));
+}
+
+
/* Add items to a list in sorted order. Use the given
* comparision func to determine order.
*/
diff --git a/src/list.h b/src/list.h
index 5d330fe1..655ffc7d 100644
--- a/src/list.h
+++ b/src/list.h
@@ -40,13 +40,14 @@ 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* 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);
+int strlist_cmp(const void *s1, const void *s2);
PMList* list_add_sorted(PMList *list, void *data, cmp_fn sortfunc);
#endif
diff --git a/src/package.c b/src/package.c
index 992110b9..ada6f411 100644
--- a/src/package.c
+++ b/src/package.c
@@ -250,6 +250,7 @@ pkginfo_t* newpkg()
pkg->size = 0;
pkg->scriptlet = 0;
pkg->force = 0;
+ pkg->reason = REASON_EXPLICIT;
pkg->requiredby = NULL;
pkg->conflicts = NULL;
pkg->files = NULL;
@@ -340,6 +341,12 @@ void dump_pkg_full(pkginfo_t *info)
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("Reason: : ");
+ switch(info->reason) {
+ case REASON_EXPLICIT: printf("explicitly installed\n"); break;
+ case REASON_DEPEND: printf("installed as a dependency for another package\n"); break;
+ default: printf("unknown\n"); break;
+ }
pm = list_sort(info->provides);
list_display("Provides :", pm);
FREELIST(pm);
@@ -367,26 +374,27 @@ void dump_pkg_sync(pkginfo_t *info)
return;
}
- printf("Name : %s\n", info->name);
- printf("Version : %s\n", info->version);
+ printf("Name : %s\n", info->name);
+ printf("Version : %s\n", info->version);
pm = list_sort(info->groups);
- list_display("Groups :", pm);
+ list_display("Groups :", pm);
FREELIST(pm);
pm = list_sort(info->provides);
- list_display("Provides :", pm);
+ list_display("Provides :", pm);
FREELIST(pm);
pm = list_sort(info->depends);
- list_display("Depends On :", pm);
+ list_display("Depends On :", pm);
FREELIST(pm);
pm = list_sort(info->conflicts);
- list_display("Conflicts With :", pm);
+ list_display("Conflicts With :", pm);
FREELIST(pm);
pm = list_sort(info->replaces);
- list_display("Replaces :", pm);
+ list_display("Replaces :", pm);
FREELIST(pm);
- printf("Description : ");
- indentprint(info->desc, 17);
- printf("\nMD5 Sum : %s\n", info->md5sum);
+ printf("Size (compressed) : %ld\n", info->size);
+ printf("Description : ");
+ indentprint(info->desc, 20);
+ printf("\nMD5 Sum : %s\n", info->md5sum);
}
int split_pkgname(char *pkgfile, char *name, char *version)
diff --git a/src/package.h b/src/package.h
index 58ef93da..ea9a3248 100644
--- a/src/package.h
+++ b/src/package.h
@@ -33,6 +33,10 @@
FREELIST(p);\
}
+/* reasons -- ie, why the package was installed */
+#define REASON_EXPLICIT 0 /* explicitly requested by the user */
+#define REASON_DEPEND 1 /* installed as a dependency for another package */
+
/* mods for depend_t.mod */
#define DEP_ANY 0
#define DEP_EQ 1
@@ -55,6 +59,7 @@ typedef struct __pkginfo_t {
unsigned long size;
unsigned short scriptlet;
unsigned short force;
+ unsigned short reason;
PMList *replaces;
PMList *groups;
PMList *files;
diff --git a/src/pacman.c b/src/pacman.c
index df0c7454..0e7e83c8 100644
--- a/src/pacman.c
+++ b/src/pacman.c
@@ -235,12 +235,12 @@ int main(int argc, char *argv[])
/* start the requested operation */
switch(pmo_op) {
- case PM_ADD: ret = pacman_add(db_local, pm_targets); break;
- case PM_REMOVE: ret = pacman_remove(db_local, pm_targets); break;
- case PM_UPGRADE: ret = pacman_upgrade(db_local, pm_targets); break;
- case PM_QUERY: ret = pacman_query(db_local, pm_targets); break;
- case PM_SYNC: ret = pacman_sync(db_local, pm_targets); break;
- case PM_DEPTEST: ret = pacman_deptest(db_local, pm_targets); break;
+ case PM_ADD: ret = pacman_add(db_local, pm_targets, NULL); break;
+ case PM_REMOVE: ret = pacman_remove(db_local, pm_targets); break;
+ case PM_UPGRADE: ret = pacman_upgrade(db_local, pm_targets, NULL); break;
+ case PM_QUERY: ret = pacman_query(db_local, pm_targets); break;
+ case PM_SYNC: ret = pacman_sync(db_local, pm_targets); break;
+ case PM_DEPTEST: ret = pacman_deptest(db_local, pm_targets); break;
case PM_MAIN: ret = 0; break;
default: fprintf(stderr, "error: no operation specified (use -h for help)\n\n");
ret = 1;
@@ -484,20 +484,19 @@ int pacman_sync(pacdb_t *db, PMList *targets)
}
} else if(pmo_group) {
PMList *pm, *allgroups, *groups;
- i = NULL;
+ allgroups = NULL;
/* fetch the list of existing groups */
for(j = databases; j; j = j->next) {
dbsync_t *dbs = (dbsync_t*)j->data;
k = find_groups(dbs->db);
for(pm = k; pm; pm = pm->next) {
- if(!is_in((char *)pm->data, i)) {
- i = list_add(i, strdup((char *)pm->data));
+ if(!is_in((char *)pm->data, allgroups)) {
+ allgroups = list_add_sorted(allgroups, strdup((char *)pm->data),
+ strlist_cmp);
}
}
FREELIST(k);
}
- allgroups = list_sort(i);
- FREELIST(i);
if(targets) {
groups = NULL;
for(j = targets; j; j = j->next) {
@@ -705,6 +704,8 @@ int pacman_sync(pacdb_t *db, PMList *targets)
/* re-fetch the package record with dependency info */
sync->pkg = db_scan(sync->dbs->db, sync->pkg->name, INFRQ_DESC | INFRQ_DEPENDS);
+ /* copy over the install reason */
+ sync->pkg->reason = local->reason;
/* add to the targets list */
found = (find_pkginsync(sync->pkg->name, final) != NULL);
@@ -779,6 +780,8 @@ int pacman_sync(pacdb_t *db, PMList *targets)
if(sync->pkg == NULL) {
found = 0;
}
+ /* this package was explicitly requested */
+ sync->pkg->reason = REASON_EXPLICIT;
}
}
}
@@ -1051,6 +1054,8 @@ int pacman_sync(pacdb_t *db, PMList *targets)
if(final && final->data && allgood && !pmo_s_printuris) {
PMList *list = NULL;
char *str;
+ unsigned long totalsize = 0;
+ double mb;
for(i = rmtargs; i; i = i->next) {
list = list_add(list, strdup(i->data));
}
@@ -1076,12 +1081,14 @@ int pacman_sync(pacdb_t *db, PMList *targets)
MALLOC(str, strlen(s->pkg->name)+strlen(s->pkg->version)+2);
sprintf(str, "%s-%s", s->pkg->name, s->pkg->version);
list = list_add(list, str);
+ totalsize += s->pkg->size;
}
}
+ mb = (double)(totalsize / 1048576.0);
printf("\nTargets: ");
str = buildstring(list);
indentprint(str, 9);
- printf("\n");
+ printf("\n\nTotal Package Size: %.1f MB\n", mb);
FREELIST(list);
FREE(str);
}
@@ -1178,14 +1185,11 @@ int pacman_sync(pacdb_t *db, PMList *targets)
fflush(stdout);
if(stat(ldir, &buf)) {
mode_t oldmask;
- char parent[PATH_MAX];
/* no cache directory.... try creating it */
- snprintf(parent, PATH_MAX, "%svar/cache/pacman", pmo_root);
logaction(stderr, "warning: no %s cache exists. creating...", ldir);
oldmask = umask(0000);
- mkdir(parent, 0755);
- if(mkdir(ldir, 0755)) {
+ if(makepath(ldir)) {
/* couldn't mkdir the cache directory, so fall back to /tmp and unlink
* the package afterwards.
*/
@@ -1295,6 +1299,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
}
if(!pmo_s_downloadonly && allgood) {
+ PMList *dependonly = NULL;
/* remove any conflicting packages (WITHOUT dep checks) */
if(rmtargs) {
int retcode;
@@ -1320,6 +1325,9 @@ int pacman_sync(pacdb_t *db, PMList *targets)
MALLOC(str, PATH_MAX);
snprintf(str, PATH_MAX, "%s/%s-%s.pkg.tar.gz", ldir, sync->pkg->name, sync->pkg->version);
files = list_add(files, str);
+ if(sync->pkg->reason == REASON_DEPEND) {
+ dependonly = list_add(dependonly, strdup(str));
+ }
}
for(j = sync->replaces; j; j = j->next) {
pkginfo_t *pkg = (pkginfo_t*)j->data;
@@ -1339,7 +1347,7 @@ int pacman_sync(pacdb_t *db, PMList *targets)
}
/* install targets */
if(allgood) {
- allgood = !pacman_upgrade(db, files);
+ allgood = !pacman_upgrade(db, files, dependonly);
}
/* propagate replaced packages' requiredby fields to their new owners */
if(allgood) {
@@ -1413,7 +1421,7 @@ sync_cleanup:
return(!allgood);
}
-int pacman_add(pacdb_t *db, PMList *targets)
+int pacman_add(pacdb_t *db, PMList *targets, PMList *dependonly)
{
int i, ret = 0, errors = 0;
TAR *tar = NULL;
@@ -1435,6 +1443,10 @@ int pacman_add(pacdb_t *db, PMList *targets)
if(targets == NULL) {
return(0);
}
+ /*
+ * Check for URL targets and process them
+ *
+ */
for(targ = targets; targ; targ = targ->next) {
if(strstr(targ->data, "://")) {
/* this target looks like an URL. download it and then
@@ -1485,6 +1497,10 @@ int pacman_add(pacdb_t *db, PMList *targets)
}
}
+ /*
+ * Load meta-data from package files
+ *
+ */
printf("loading package data... ");
fflush(stdout);
for(targ = targets; targ; targ = targ->next) {
@@ -1494,6 +1510,12 @@ int pacman_add(pacdb_t *db, PMList *targets)
if(info == NULL) {
return(1);
}
+ /* no additional hyphens in version strings */
+ if(strchr(info->version, '-') != strrchr(info->version, '-')) {
+ fprintf(stderr, "\nerror: package \"%s\" has more than one hyphen in its version (%s)\n",
+ info->name, info->version);
+ return(1);
+ }
if(pmo_freshen) {
/* 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);
@@ -1525,6 +1547,11 @@ int pacman_add(pacdb_t *db, PMList *targets)
}
printf("done.\n");
+ /*
+ * Check dependencies
+ *
+ */
+
/* No need to check deps if pacman_add was called during a sync:
* it is already done in pacman_sync. */
if(!pmo_nodeps && pmo_op != PM_SYNC) {
@@ -1636,6 +1663,10 @@ int pacman_add(pacdb_t *db, PMList *targets)
alltargs = lp;
}
+ /*
+ * Check for file conflicts
+ *
+ */
if(!pmo_force) {
printf("checking for file conflicts... ");
fflush(stdout);
@@ -1657,6 +1688,10 @@ int pacman_add(pacdb_t *db, PMList *targets)
/* this can get modified in the next for loop, so we reset it on each iteration */
real_pmo_upgrade = pmo_upgrade;
+ /*
+ * Install packages
+ *
+ */
for(targ = alltargs, file = filenames; targ && file; targ = targ->next, file = file->next) {
pkginfo_t* oldpkg = NULL;
info = (pkginfo_t*)targ->data;
@@ -1682,33 +1717,13 @@ int pacman_add(pacdb_t *db, PMList *targets)
/* pre_upgrade scriptlet */
if(info->scriptlet) {
- char tmpdir[PATH_MAX];
- char *rtmpdir;
- snprintf(tmpdir, PATH_MAX, "%stmp/pacman-XXXXXX", pmo_root);
- if(mkdtemp(tmpdir) == NULL) {
- perror("error creating temp directory");
- return(1);
- }
- /* chop off the pmo_root so we can find the tmpdir in the chroot */
- rtmpdir = tmpdir + strlen(pmo_root) - 1;
- unpack(file->data, tmpdir, ".INSTALL");
- /* run the post-install script if it exists */
- snprintf(pm_install, PATH_MAX, "%s/.INSTALL", tmpdir);
- if(grep(pm_install, "pre_upgrade")) {
- char cmdline[PATH_MAX+1];
- snprintf(pm_install, PATH_MAX, "%s/.INSTALL", rtmpdir);
- vprint("Executing pre-upgrade script...\n");
- snprintf(cmdline, PATH_MAX, "echo \"umask 0022; source %s pre_upgrade %s %s\" | chroot %s /bin/sh",
- pm_install, info->version, (oldpkg ? oldpkg->version : ""), pmo_root);
- system(cmdline);
- }
- if(rmrf(tmpdir)) {
- fprintf(stderr, "warning: could not remove tmpdir %s\n", tmpdir);
- }
+ runscriptlet(file->data, "pre_upgrade", info->version, oldpkg ? oldpkg->version : NULL);
}
if(oldpkg) {
PMList* tmp = list_add(NULL, strdup(info->name));
+ /* copy over the install reason */
+ info->reason = oldpkg->reason;
vprint("removing old package first...\n");
retcode = pacman_remove(db, tmp);
FREELIST(tmp);
@@ -1727,34 +1742,13 @@ int pacman_add(pacdb_t *db, PMList *targets)
pmo_upgrade = 0;
}
}
+
if(!pmo_upgrade) {
printf("installing %s... ", info->name);
neednl = 1;
/* pre_install scriptlet */
if(info->scriptlet) {
- char tmpdir[PATH_MAX];
- char *rtmpdir;
- snprintf(tmpdir, PATH_MAX, "%stmp/pacman-XXXXXX", pmo_root);
- if(mkdtemp(tmpdir) == NULL) {
- perror("error creating temp directory");
- return(1);
- }
- /* chop off the pmo_root so we can find the tmpdir in the chroot */
- rtmpdir = tmpdir + strlen(pmo_root) - 1;
- unpack(file->data, tmpdir, ".INSTALL");
- /* run the post-install script if it exists */
- snprintf(pm_install, PATH_MAX, "%s/.INSTALL", tmpdir);
- if(grep(pm_install, "pre_install")) {
- char cmdline[PATH_MAX+1];
- snprintf(pm_install, PATH_MAX, "%s/.INSTALL", rtmpdir);
- vprint("Executing pre-install script...\n");
- snprintf(cmdline, PATH_MAX, "echo \"umask 0022; source %s pre_install %s\" | chroot %s /bin/sh",
- pm_install, info->version, pmo_root);
- system(cmdline);
- }
- if(rmrf(tmpdir)) {
- fprintf(stderr, "warning: could not remove tmpdir %s\n", tmpdir);
- }
+ runscriptlet(file->data, "pre_install", info->version, NULL);
}
}
fflush(stdout);
@@ -1792,7 +1786,7 @@ int pacman_add(pacdb_t *db, PMList *targets)
notouch = 1;
} else {
if(!pmo_upgrade || oldpkg == NULL) {
- nb = is_in(pathname, info->backup);
+ nb = is_in(pathname, info->backup) ? 1 : 0;
} else {
/* op == PM_UPGRADE */
md5_orig = needbackup(pathname, oldpkg->backup);
@@ -1976,6 +1970,13 @@ int pacman_add(pacdb_t *db, PMList *targets)
}
vprint("Updating database...");
+ /* Figure out whether this package was installed explicitly by the user
+ * or installed as a dependency for another package
+ */
+ info->reason = REASON_EXPLICIT;
+ if(is_in(file->data, dependonly)) {
+ info->reason = REASON_DEPEND;
+ }
/* make an install date (in UTC) */
strncpy(info->installdate, asctime(gmtime(&t)), sizeof(info->installdate));
if(db_write(db, info, INFRQ_ALL)) {
@@ -2019,16 +2020,12 @@ int pacman_add(pacdb_t *db, PMList *targets)
}
printf("done.\n"); fflush(stdout);
- /* run the post-install script if it exists */
+ /* run the post-install/upgrade 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) && (grep(pm_install, "post_install") || grep(pm_install, "post_upgrade"))) {
- char cmdline[PATH_MAX+1];
- snprintf(pm_install, PATH_MAX, "%s/%s/%s-%s/install", pmo_dbpath, db->treename, info->name, info->version);
- vprint("Executing post-install script...\n");
- snprintf(cmdline, PATH_MAX, "echo \"umask 0022; source %s post_%s %s %s\" | chroot %s /bin/sh",
- pm_install, (pmo_upgrade ? "upgrade" : "install"), info->version,
- ((pmo_upgrade && oldpkg) ? oldpkg->version : ""), pmo_root);
- system(cmdline);
+ if(pmo_upgrade) {
+ runscriptlet(pm_install, "post_upgrade", info->version, oldpkg ? oldpkg->version : NULL);
+ } else {
+ runscriptlet(pm_install, "post_install", info->version, NULL);
}
}
@@ -2170,16 +2167,9 @@ int pacman_remove(pacdb_t *db, PMList *targets)
printf("removing %s... ", info->name);
neednl = 1;
fflush(stdout);
- /* run the pre-remove script if it exists */
+ /* run the pre-remove scriptlet 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) && grep(pm_install, "pre_remove")) {
- vprint("Executing pre-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, "echo \"umask 0022; source %s pre_remove %s\" | chroot %s /bin/sh",
- pm_install, info->version, pmo_root);
-
- system(line);
- }
+ runscriptlet(pm_install, "pre_remove", info->version, NULL);
}
if(!pmo_r_dbonly) {
@@ -2236,14 +2226,7 @@ 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) && grep(pm_install, "post_remove")) {
- 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, "echo \"umask 0022; source %s post_remove %s\" | chroot %s /bin/sh",
- pm_install, info->version, pmo_root);
-
- system(line);
- }
+ runscriptlet(pm_install, "post_remove", info->version, NULL);
}
/* remove the package from the database */
@@ -2398,11 +2381,13 @@ int pacman_query(pacdb_t *db, PMList *targets)
if(pmo_q_info) {
dump_pkg_full(info);
printf("\n");
- } else if(pmo_q_list) {
+ }
+ if(pmo_q_list) {
for(lp = info->files; lp; lp = lp->next) {
printf("%s %s\n", info->name, (char*)lp->data);
}
- } else {
+ }
+ if (!pmo_q_info && !pmo_q_list) {
printf("%s %s\n", info->name, info->version);
}
FREEPKG(info);
@@ -2444,23 +2429,21 @@ int pacman_query(pacdb_t *db, PMList *targets)
/* no target */
for(lp = pm_packages; lp; lp = lp->next) {
pkginfo_t *tmpp = (pkginfo_t*)lp->data;
- if(pmo_q_list) {
- info = db_scan(db, tmpp->name, INFRQ_DESC | INFRQ_FILES);
+ if(pmo_q_list || pmo_q_orphans) {
+ info = db_scan(db, tmpp->name, INFRQ_ALL);
if(info == NULL) {
/* something weird happened */
return(1);
}
- for(q = info->files; q; q = q->next) {
- printf("%s %s%s\n", info->name, pmo_root, (char*)q->data);
- }
- FREEPKG(info);
- } else if(pmo_q_orphans) {
- info = db_scan(db, tmpp->name, INFRQ_DESC | INFRQ_DEPENDS);
- if(info == NULL) {
- return(1);
+ if(pmo_q_list) {
+ for(q = info->files; q; q = q->next) {
+ printf("%s %s%s\n", info->name, pmo_root, (char*)q->data);
+ }
}
- if(info->requiredby == NULL) {
- printf("%s %s\n", tmpp->name, tmpp->version);
+ if(pmo_q_orphans) {
+ if(info->requiredby == NULL && info->reason == REASON_EXPLICIT) {
+ printf("%s %s\n", tmpp->name, tmpp->version);
+ }
}
FREEPKG(info);
} else {
@@ -2469,55 +2452,53 @@ int pacman_query(pacdb_t *db, PMList *targets)
}
} else {
/* find a target */
- if(pmo_q_info) {
+ if(pmo_q_info || pmo_q_list) {
info = db_scan(db, package, INFRQ_ALL);
if(info == NULL) {
fprintf(stderr, "Package \"%s\" was not found.\n", package);
return(2);
}
- dump_pkg_full(info);
- if(pmo_q_info > 1 && info->backup) {
- /* extra info */
- printf("\n");
- for(lp = info->backup; lp; lp = lp->next) {
- struct stat buf;
- char path[PATH_MAX];
- char *md5sum;
- char *str = strdup(lp->data);
- char *ptr = index(str, '\t');
- if(ptr == NULL) {
- FREE(str);
- continue;
- }
- *ptr = '\0';
- ptr++;
- snprintf(path, PATH_MAX-1, "%s%s", pmo_root, str);
- if(!stat(path, &buf)) {
- md5sum = MDFile(path);
- if(md5sum == NULL) {
- fprintf(stderr, "error calculating md5sum for %s\n", path);
+ if(pmo_q_info) {
+ dump_pkg_full(info);
+ if(pmo_q_info > 1 && info->backup) {
+ /* extra info */
+ printf("\n");
+ for(lp = info->backup; lp; lp = lp->next) {
+ struct stat buf;
+ char path[PATH_MAX];
+ char *md5sum;
+ char *str = strdup(lp->data);
+ char *ptr = index(str, '\t');
+ if(ptr == NULL) {
+ FREE(str);
continue;
}
- if(strcmp(md5sum, ptr)) {
- printf("MODIFIED\t%s\n", path);
+ *ptr = '\0';
+ ptr++;
+ snprintf(path, PATH_MAX-1, "%s%s", pmo_root, str);
+ if(!stat(path, &buf)) {
+ md5sum = MDFile(path);
+ if(md5sum == NULL) {
+ fprintf(stderr, "error calculating md5sum for %s\n", path);
+ continue;
+ }
+ if(strcmp(md5sum, ptr)) {
+ printf("MODIFIED\t%s\n", path);
+ } else {
+ printf("NOT MODIFIED\t%s\n", path);
+ }
} else {
- printf("NOT MODIFIED\t%s\n", path);
+ printf("MISSING\t\t%s\n", path);
}
- } else {
- printf("MISSING\t\t%s\n", path);
+ FREE(str);
}
- FREE(str);
}
+ printf("\n");
}
- printf("\n");
- } else if(pmo_q_list) {
- info = db_scan(db, package, INFRQ_DESC | INFRQ_FILES);
- if(info == NULL) {
- fprintf(stderr, "Package \"%s\" was not found.\n", package);
- return(2);
- }
- for(lp = info->files; lp; lp = lp->next) {
- printf("%s %s%s\n", info->name, pmo_root, (char*)lp->data);
+ if(pmo_q_list) {
+ for(lp = info->files; lp; lp = lp->next) {
+ printf("%s %s%s\n", info->name, pmo_root, (char*)lp->data);
+ }
}
} else if(pmo_q_orphans) {
info = db_scan(db, package, INFRQ_DESC | INFRQ_DEPENDS);
@@ -2543,12 +2524,12 @@ int pacman_query(pacdb_t *db, PMList *targets)
return(0);
}
-int pacman_upgrade(pacdb_t *db, PMList *targets)
+int pacman_upgrade(pacdb_t *db, PMList *targets, PMList *dependonly)
{
/* this is basically just a remove-then-add process. pacman_add() will */
/* handle it */
pmo_upgrade = 1;
- return(pacman_add(db, targets));
+ return(pacman_add(db, targets, dependonly));
}
/* Re-order a list of target packages with respect to their dependencies.
@@ -2630,6 +2611,10 @@ PMList* sortbydeps(PMList *targets)
* target list, as well as all their un-needed dependencies. By un-needed,
* I mean dependencies that are *only* required for packages in the target
* list, so they can be safely removed. This function is recursive.
+ *
+ * NOTE: as of version 2.9, this will only remove packages that were
+ * not explicitly installed (ie, reason == REASON_DEPEND)
+ *
*/
PMList* removedeps(pacdb_t *db, PMList *targs)
{
@@ -2663,6 +2648,11 @@ PMList* removedeps(pacdb_t *db, PMList *targs)
if(is_pkgin(dep, targs)) {
continue;
}
+ /* see if it was explicitly installed */
+ if(dep->reason == REASON_EXPLICIT) {
+ vprint("excluding %s -- explicitly installed\n", dep->name);
+ needed = 1;
+ }
/* see if other packages need it */
for(k = dep->requiredby; k && !needed; k = k->next) {
pkginfo_t *dummy;
@@ -2726,6 +2716,7 @@ int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *syncpkg, PMList *l
found = 1;
/* re-fetch the package record with dependency info */
sync->pkg = db_scan(dbs->db, pkg->name, INFRQ_DESC | INFRQ_DEPENDS);
+ sync->pkg->reason = REASON_DEPEND;
sync->dbs = dbs;
}
}
@@ -2739,6 +2730,7 @@ int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *syncpkg, PMList *l
found = 1;
/* re-fetch the package record with dependency info */
sync->pkg = db_scan(dbs->db, provides->data, INFRQ_DESC | INFRQ_DEPENDS);
+ sync->pkg->reason = REASON_DEPEND;
sync->dbs = dbs;
}
list_free(provides);
@@ -3222,6 +3214,63 @@ char* needbackup(char* file, PMList *backup)
return(NULL);
}
+/* Executes a scriptlet.
+ */
+int runscriptlet(char *installfn, char *script, char *ver, char *oldver)
+{
+ char scriptfn[PATH_MAX];
+ char cmdline[PATH_MAX];
+ char tmpdir[PATH_MAX] = "";
+ char *scriptpath;
+ struct stat buf;
+
+ if(stat(installfn, &buf)) {
+ /* not found */
+ return(0);
+ }
+
+ if(!strcmp(script, "pre_upgrade") || !strcmp(script, "pre_install")) {
+ snprintf(tmpdir, PATH_MAX, "%stmp/", pmo_root);
+ if(stat(tmpdir, &buf)) {
+ makepath(tmpdir);
+ }
+ snprintf(tmpdir, PATH_MAX, "%stmp/pacman-XXXXXX", pmo_root);
+ if(mkdtemp(tmpdir) == NULL) {
+ perror("error creating temp directory");
+ return(1);
+ }
+ unpack(installfn, tmpdir, ".INSTALL");
+ snprintf(scriptfn, PATH_MAX, "%s/.INSTALL", tmpdir);
+ /* chop off the pmo_root so we can find the tmpdir in the chroot */
+ scriptpath = scriptfn + strlen(pmo_root) - 1;
+ } else {
+ strncpy(scriptfn, installfn, PATH_MAX-1);
+ /* chop off the pmo_root so we can find the tmpdir in the chroot */
+ scriptpath = scriptfn + strlen(pmo_root) - 1;
+ }
+
+ if(!grep(scriptfn, script)) {
+ /* script not found in scriptlet file */
+ return(0);
+ }
+
+ vprint("Executing %s script...\n", script);
+ if(oldver) {
+ snprintf(cmdline, PATH_MAX, "echo \"umask 0022; source %s %s %s %s\" | chroot %s /bin/sh",
+ scriptpath, script, ver, oldver, pmo_root);
+ } else {
+ snprintf(cmdline, PATH_MAX, "echo \"umask 0022; source %s %s %s\" | chroot %s /bin/sh",
+ scriptpath, script, ver, pmo_root);
+ }
+ vprint("%s\n", cmdline);
+ system(cmdline);
+
+ if(strlen(tmpdir) && rmrf(tmpdir)) {
+ fprintf(stderr, "warning: could not remove tmpdir %s\n", tmpdir);
+ }
+ return(0);
+}
+
/* Parse command-line arguments for each operation
* op: the operation code requested
* argc: argc
@@ -3615,8 +3664,10 @@ void usage(int op, char *myname)
} else if(op == PM_QUERY) {
printf("usage: %s {-Q --query} [options] [package]\n", myname);
printf("options:\n");
- printf(" -i, --info view package information (use -ii for more)\n");
+ printf(" -e, --orphans list all packages that were explicitly installed\n");
+ printf(" and are not required by any other packages\n");
printf(" -g, --groups view all members of a package group\n");
+ printf(" -i, --info view package information (use -ii for more)\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");
diff --git a/src/pacman.h b/src/pacman.h
index d7f30fc3..a87f569e 100644
--- a/src/pacman.h
+++ b/src/pacman.h
@@ -22,7 +22,7 @@
#define _PAC_PACMAN_H
#ifndef PACVER
-#define PACVER "2.8.4"
+#define PACVER "2.9"
#endif
#ifndef PKGDIR
@@ -48,9 +48,9 @@
#define min(X, Y) ((X) < (Y) ? (X) : (Y))
-int pacman_add(pacdb_t *db, PMList *targets);
+int pacman_add(pacdb_t *db, PMList *targets, PMList *dependonly);
int pacman_remove(pacdb_t *db, PMList *targets);
-int pacman_upgrade(pacdb_t *db, PMList *targets);
+int pacman_upgrade(pacdb_t *db, PMList *targets, PMList *dependonly);
int pacman_query(pacdb_t *db, PMList *targets);
int pacman_sync(pacdb_t *db, PMList *targets);
int pacman_deptest(pacdb_t *db, PMList *targets);
@@ -62,6 +62,7 @@ int resolvedeps(pacdb_t *local, PMList *databases, syncpkg_t *sync, PMList *list
int splitdep(char *depstr, depend_t *depend);
char* needbackup(char *file, PMList *backup);
+int runscriptlet(char *installfn, char *script, char *ver, char *oldver);
int parseargs(int op, int argc, char **argv);
int parseconfig(char *configfile);
diff --git a/src/util.c b/src/util.c
index d9814210..6d3ed0fa 100644
--- a/src/util.c
+++ b/src/util.c
@@ -147,6 +147,7 @@ int makepath(char *path)
if(stat(full, &buf)) {
if(mkdir(full, 0755)) {
free(orig);
+ umask(oldmask);
return(1);
}
}