From 4ffc53b3398ae845183f991a56207459256cc9e9 Mon Sep 17 00:00:00 2001 From: Judd Vinet Date: Sat, 18 Sep 2004 18:37:34 +0000 Subject: Imported from pacman-2.9.tar.gz --- src/db.c | 23 ++++ src/list.c | 17 ++- src/list.h | 3 +- src/package.c | 28 +++-- src/package.h | 5 + src/pacman.c | 341 +++++++++++++++++++++++++++++++++------------------------- src/pacman.h | 7 +- src/util.c | 1 + 8 files changed, 263 insertions(+), 162 deletions(-) (limited to 'src') 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 query the package that owns \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); } } -- cgit v1.2.3-24-g4f1b