diff options
Diffstat (limited to 'src/pacman.c')
-rw-r--r-- | src/pacman.c | 176 |
1 files changed, 136 insertions, 40 deletions
diff --git a/src/pacman.c b/src/pacman.c index 2670ede5..96a9a7f4 100644 --- a/src/pacman.c +++ b/src/pacman.c @@ -1,7 +1,7 @@ /* * pacman.c * - * Copyright (c) 2002 by Judd Vinet <jvinet@zeroflux.org> + * Copyright (c) 2002-2004 by Judd Vinet <jvinet@zeroflux.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -143,7 +143,7 @@ int main(int argc, char *argv[]) pm_access = READ_ONLY; if(pmo_op != PM_MAIN && pmo_op != PM_QUERY && pmo_op != PM_DEPTEST) { if(pmo_op == PM_SYNC && !pmo_s_sync && - (pmo_s_search || pmo_group || pmo_q_list || pmo_q_info)) { + (pmo_s_search || pmo_s_printuris || pmo_group || pmo_q_list || pmo_q_info)) { /* special case: PM_SYNC can be used w/ pmo_s_search by any user */ } else { if(geteuid() != 0) { @@ -349,23 +349,31 @@ int pacman_sync(pacdb_t *db, PMList *targets) for(i = cache; i; i = i->next) { char *str = (char *)i->data; - char *name, *version; + char name[256], version[64]; - if(split_pkgname(str, &name, &version) != 0) { + if(strstr(str, ".pkg.tar.gz") == NULL) { clean = list_add(clean, strdup(str)); continue; } /* we keep partially downloaded files */ if(strstr(str, ".pkg.tar.gz.part")) { - FREE(name); - FREE(version); + continue; + } + if(split_pkgname(str, name, version) != 0) { + clean = list_add(clean, strdup(str)); continue; } for(j = i->next; j; j = j->next) { char *s = (char *)j->data; - char *n, *v; + char n[256], v[64]; - if(split_pkgname(s, &n, &v) != 0) { + if(strstr(s, ".pkg.tar.gz") == NULL) { + continue; + } + if(strstr(s, ".pkg.tar.gz.part")) { + continue; + } + if(split_pkgname(s, n, v) != 0) { continue; } if(!strcmp(name, n)) { @@ -379,11 +387,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) clean = list_add(clean, strdup(ptr)); } } - FREE(n); - FREE(v); } - FREE(name); - FREE(version); } FREELIST(cache); @@ -805,7 +809,7 @@ int pacman_sync(pacdb_t *db, PMList *targets) continue; } local = db_scan(db, targ, INFRQ_DESC); - if(local && !pmo_s_downloadonly) { + if(local && !pmo_s_downloadonly && !pmo_s_printuris) { /* this is an upgrade, compare versions and determine if it is necessary */ cmp = rpmvercmp(local->version, sync->pkg->version); if(cmp > 0) { @@ -1282,7 +1286,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->replaces) { - pkginfo_t *new = db_scan(db, sync->pkg->name, INFRQ_ALL); + pkginfo_t *new = db_scan(db, sync->pkg->name, INFRQ_DEPENDS); for(j = sync->replaces; j; j = j->next) { pkginfo_t *old = (pkginfo_t*)j->data; /* merge lists */ @@ -1290,21 +1294,21 @@ int pacman_sync(pacdb_t *db, PMList *targets) if(!is_in(k->data, new->requiredby)) { /* replace old's name with new's name in the requiredby's dependency list */ PMList *m; - pkginfo_t *depender = db_scan(db, k->data, INFRQ_ALL); + pkginfo_t *depender = db_scan(db, k->data, INFRQ_DEPENDS); for(m = depender->depends; m; m = m->next) { if(!strcmp(m->data, old->name)) { FREE(m->data); m->data = strdup(new->name); } } - db_write(db, depender); + db_write(db, depender, INFRQ_DEPENDS); /* add the new requiredby */ new->requiredby = list_add(new->requiredby, strdup(k->data)); } } } - db_write(db, new); + db_write(db, new, INFRQ_DEPENDS); FREEPKG(new); } } @@ -1376,8 +1380,9 @@ int pacman_add(pacdb_t *db, PMList *targets) /* this target looks like an URL. download it and then * strip the URL portion from the target. */ + char spath[PATH_MAX]; char url[PATH_MAX]; - server_t server; + server_t *server; PMList *servers = NULL; PMList *files = NULL; char *host, *path, *fn; @@ -1389,12 +1394,23 @@ int pacman_add(pacdb_t *db, PMList *targets) *path = '\0'; path++; fn = strrchr(path, '/'); - *fn = '\0'; - fn++; - server.protocol = url; - server.server = host; - server.path = path; - servers = list_add(servers, &server); + if(fn) { + *fn = '\0'; + if(path[0] == '/') { + snprintf(spath, PATH_MAX, "%s/", path); + } else { + snprintf(spath, PATH_MAX, "/%s/", path); + } + fn++; + } else { + fn = path; + strcpy(spath, "/"); + } + MALLOC(server, sizeof(server_t)); + server->protocol = url; + server->server = host; + server->path = spath; + servers = list_add(servers, server); files = list_add(files, fn); if(downloadfiles(servers, ".", files)) { fprintf(stderr, "error: failed to download %s\n", (char*)targ->data); @@ -1600,9 +1616,37 @@ int pacman_add(pacdb_t *db, PMList *targets) printf("upgrading %s... ", info->name); neednl = 1; + /* we'll need the full record for backup checks later */ oldpkg = db_scan(db, info->name, INFRQ_ALL); + /* 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); + } + } + if(oldpkg) { list_add(tmp, strdup(info->name)); vprint("removing old package first...\n"); @@ -1626,6 +1670,32 @@ int pacman_add(pacdb_t *db, PMList *targets) 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); + } + } } fflush(stdout); @@ -1781,6 +1851,14 @@ int pacman_add(pacdb_t *db, PMList *targets) logaction(stderr, "warning: extracting %s%s as %s", pmo_root, pathname, expath); /*tar_skip_regfile(tar);*/ } + if(pmo_force) { + /* if pmo_force was used, then unlink() each file (whether it's there + * or not) before extracting. this prevents the old "Text file busy" + * error that crops up if one tries to --force a glibc or pacman + * upgrade. + */ + unlink(expath); + } if(tar_extract_file(tar, expath)) { logaction(stderr, "could not extract %s: %s", pathname, strerror(errno)); errors++; @@ -1821,7 +1899,7 @@ int pacman_add(pacdb_t *db, PMList *targets) pkginfo_t *tmpp = NULL; PMList *tmppm = NULL; - tmpp = db_scan(db, ((pkginfo_t*)lp->data)->name, INFRQ_DEPENDS); + tmpp = db_scan(db, ((pkginfo_t*)lp->data)->name, INFRQ_DESC | INFRQ_DEPENDS); if(tmpp == NULL) { continue; } @@ -1840,7 +1918,7 @@ int pacman_add(pacdb_t *db, PMList *targets) vprint("Updating database..."); /* make an install date (in UTC) */ strncpy(info->installdate, asctime(gmtime(&t)), sizeof(info->installdate)); - if(db_write(db, info)) { + if(db_write(db, info, INFRQ_ALL)) { logaction(stderr, "error updating database for %s!", info->name); return(1); } @@ -1860,13 +1938,13 @@ int pacman_add(pacdb_t *db, PMList *targets) if(splitdep(lp->data, &depend)) { continue; } - depinfo = db_scan(db, depend.name, INFRQ_ALL); + depinfo = db_scan(db, depend.name, INFRQ_DEPENDS); if(depinfo == NULL) { /* look for a provides package */ PMList *provides = whatprovides(db, depend.name); if(provides) { /* use the first one */ - depinfo = db_scan(db, provides->data, INFRQ_ALL); + depinfo = db_scan(db, provides->data, INFRQ_DEPENDS); if(depinfo == NULL) { /* wtf */ continue; @@ -1876,19 +1954,20 @@ int pacman_add(pacdb_t *db, PMList *targets) } } depinfo->requiredby = list_add(depinfo->requiredby, strdup(info->name)); - db_write(db, depinfo); + db_write(db, depinfo, INFRQ_DEPENDS); freepkg(depinfo); } printf("done.\n"); fflush(stdout); /* run the post-install 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)) { + 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, "chroot %s /bin/sh %s post_%s %s %s", pmo_root, pm_install, - (pmo_upgrade ? "upgrade" : "install"), info->version, ((pmo_upgrade && oldpkg) ? oldpkg->version : "")); + 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); } } @@ -2021,10 +2100,11 @@ int pacman_remove(pacdb_t *db, PMList *targets) fflush(stdout); /* run the pre-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)) { + 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, "chroot %s /bin/sh %s pre_remove %s", pmo_root, pm_install, 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); } @@ -2084,10 +2164,11 @@ 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)) { + 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, "chroot %s /bin/sh %s post_remove %s", pmo_root, pm_install, 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); } @@ -2119,7 +2200,7 @@ int pacman_remove(pacdb_t *db, PMList *targets) if(splitdep((char*)lp->data, &depend)) { continue; } - depinfo = db_scan(db, depend.name, INFRQ_ALL); + depinfo = db_scan(db, depend.name, INFRQ_DEPENDS); if(depinfo == NULL) { /* look for a provides package */ PMList *provides = whatprovides(db, depend.name); @@ -2128,7 +2209,7 @@ int pacman_remove(pacdb_t *db, PMList *targets) * the first one. */ /* use the first one */ - depinfo = db_scan(db, provides->data, INFRQ_ALL); + depinfo = db_scan(db, provides->data, INFRQ_DEPENDS); list_free(provides); if(depinfo == NULL) { /* wtf */ @@ -2154,7 +2235,7 @@ int pacman_remove(pacdb_t *db, PMList *targets) break; } } - db_write(db, depinfo); + db_write(db, depinfo, INFRQ_DEPENDS); freepkg(depinfo); } if(!pmo_upgrade) { @@ -2493,12 +2574,27 @@ PMList* removedeps(pacdb_t *db, PMList *targs) continue; } dep = db_scan(db, depend.name, INFRQ_DESC | INFRQ_DEPENDS); + if(dep == NULL) { + /* package not found... look for a provisio instead */ + k = whatprovides(db, depend.name); + if(k == NULL) { + fprintf(stderr, "warning: cannot find package \"%s\" or anything that provides it!\n", depend.name); + continue; + } + dep = db_scan(db, k->data, INFRQ_DESC | INFRQ_DEPENDS); + if(dep == NULL) { + fprintf(stderr, "dep is NULL!\n"); + fflush(stderr); + } + FREELIST(k); + } if(is_pkgin(dep, targs)) { continue; } /* see if other packages need it */ for(k = dep->requiredby; k && !needed; k = k->next) { - pkginfo_t *dummy = db_scan(db, k->data, INFRQ_DESC); + pkginfo_t *dummy; + dummy = db_scan(db, k->data, INFRQ_DESC); if(!is_pkgin(dummy, targs)) { needed = 1; } |