/* Show files that don't match the recorded checksum */ int show_cksum(const char *title, Package *plist) { PackingList p; const char *dir = "."; char *prefix = NULL; char tmp[FILENAME_MAX]; int errcode = 0; if (!Quiet) { printf("%s%s", InfoPrefix, title); fflush(stdout); } for (p = plist->head; p != NULL; p = p->next) if (p->type == PLIST_CWD) { if (!prefix) prefix = p->name; if (p->name == NULL) dir = prefix; else dir = p->name; } else if (p->type == PLIST_FILE) { snprintf(tmp, FILENAME_MAX, "%s/%s", elide_root(dir), p->name); if (!fexists(tmp)) { warnx("%s doesn't exist", tmp); errcode = 1; } else if (p->next && p->next->type == PLIST_COMMENT && (strncmp(p->next->name, "MD5:", 4) == 0)) { char *cp = NULL, buf[33]; /* * For packing lists whose version is 1.1 or greater, the md5 * hash for a symlink is calculated on the string returned * by readlink(). */ if (issymlink(tmp) && verscmp(plist, 1, 0) > 0) { int len; char linkbuf[FILENAME_MAX]; if ((len = readlink(tmp, linkbuf, FILENAME_MAX)) > 0) cp = MD5Data((unsigned char *)linkbuf, len, buf); } else if (isfile(tmp) || verscmp(plist, 1, 1) < 0) cp = MD5File(tmp, buf); if (cp != NULL) { /* Mismatch? */ if (strcmp(cp, p->next->name + 4)) printf("%s fails the original MD5 checksum\n", tmp); else if (Verbose) printf("%s matched the original MD5 checksum\n", tmp); } } } return (errcode); }
/* Read a packing list from a file */ void read_plist(Package *pkg, FILE *fp) { char *cp, pline[FILENAME_MAX]; int cmd, major, minor; pkg->fmtver_maj = 1; pkg->fmtver_mnr = 0; pkg->origin = NULL; while (fgets(pline, FILENAME_MAX, fp)) { int len = strlen(pline); while (len && isspace(pline[len - 1])) pline[--len] = '\0'; if (!len) continue; cp = pline; if (pline[0] != CMD_CHAR) { cmd = PLIST_FILE; goto bottom; } cmd = plist_cmd(pline + 1, &cp); if (cmd == FAIL) { warnx("%s: unknown command '%s' (package tools out of date?)", __func__, pline); goto bottom; } if (*cp == '\0') { cp = NULL; if (cmd == PLIST_PKGDEP) { warnx("corrupted record for package %s (pkgdep line without " "argument), ignoring", pkg->name); cmd = FAIL; } goto bottom; } if (cmd == PLIST_COMMENT && sscanf(cp, "PKG_FORMAT_REVISION:%d.%d\n", &major, &minor) == 2) { pkg->fmtver_maj = major; pkg->fmtver_mnr = minor; if (verscmp(pkg, PLIST_FMT_VER_MAJOR, PLIST_FMT_VER_MINOR) <= 0) goto bottom; warnx("plist format revision (%d.%d) is higher than supported" "(%d.%d)", pkg->fmtver_maj, pkg->fmtver_mnr, PLIST_FMT_VER_MAJOR, PLIST_FMT_VER_MINOR); if (pkg->fmtver_maj > PLIST_FMT_VER_MAJOR) { cleanup(0); exit(2); } } bottom: add_plist(pkg, cmd, cp); } }
static int ckinst(char *pkginst, char *pkgarch, char *pkgvers, char *ckarch, char *ckvers) { if (ckarch && archcmp(ckarch, pkgarch)) return (-1); if (ckvers) { /* Check for exact version match */ if (verscmp(ckvers, pkgvers)) { /* Check for compatable version */ if (compver(pkginst, ckvers)) return (-1); } } return (0); }
static int compver(char *pkginst, char *version) { FILE *fp; char temp[256]; (void) sprintf(temp, "%s/%s/install/compver", get_PKGLOC(), pkginst); if ((fp = fopen(temp, "r")) == NULL) return (-1); while (fgets(temp, 256, fp)) { if (*temp == '#') continue; if (verscmp(temp, version) == 0) { (void) fclose(fp); return (0); } } (void) fclose(fp); return (-1); }
/* * Delete the results of a package installation. * * This is here rather than in the pkg_delete code because pkg_add needs to * run it too in cases of failure. */ int delete_package(Boolean ign_err, Boolean nukedirs, Package *pkg) { PackingList p; const char *Where = ".", *last_file = ""; Boolean fail = SUCCESS; Boolean preserve; char tmp[FILENAME_MAX], *name = NULL; char *prefix = NULL; preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE; for (p = pkg->head; p; p = p->next) { switch (p->type) { case PLIST_NAME: name = p->name; break; case PLIST_IGNORE: p = p->next; break; case PLIST_CWD: if (!prefix) prefix = p->name; Where = (p->name == NULL) ? prefix : p->name; if (Verbose) printf("Change working directory to %s\n", Where); break; case PLIST_UNEXEC: format_cmd(tmp, FILENAME_MAX, p->name, Where, last_file); if (Verbose) printf("Execute '%s'\n", tmp); if (!Fake && system(tmp)) { warnx("unexec command for '%s' failed", tmp); fail = FAIL; } break; case PLIST_FILE: last_file = p->name; if (*p->name == '/') strlcpy(tmp, p->name, FILENAME_MAX); else sprintf(tmp, "%s/%s", Where, p->name); if (isdir(tmp) && fexists(tmp) && !issymlink(tmp)) { warnx("cannot delete specified file '%s' - it is a directory!\n" "this packing list is incorrect - ignoring delete request", tmp); } else { if (p->next && p->next->type == PLIST_COMMENT && !strncmp(p->next->name, "MD5:", 4)) { char *cp = NULL, buf[33]; /* * For packing lists whose version is 1.1 or greater, the md5 * hash for a symlink is calculated on the string returned * by readlink(). */ if (issymlink(tmp) && verscmp(pkg, 1, 0) > 0) { int len; char linkbuf[FILENAME_MAX]; if ((len = readlink(tmp, linkbuf, FILENAME_MAX)) > 0) cp = MD5Data((unsigned char *)linkbuf, len, buf); } else if (isfile(tmp) || verscmp(pkg, 1, 1) < 0) cp = MD5File(tmp, buf); if (cp != NULL) { /* Mismatch? */ if (strcmp(cp, p->next->name + 4)) { warnx("'%s' fails original MD5 checksum - %s", tmp, Force ? "deleted anyway." : "not deleted."); if (!Force) { fail = FAIL; continue; } } } } if (Verbose) printf("Delete file %s\n", tmp); if (!Fake) { if (delete_hierarchy(tmp, ign_err, nukedirs)) fail = FAIL; if (preserve && name) { char tmp2[FILENAME_MAX]; if (make_preserve_name(tmp2, FILENAME_MAX, name, tmp)) { if (fexists(tmp2)) { if (rename(tmp2, tmp)) warn("preserve: unable to restore %s as %s", tmp2, tmp); } } } } } break; case PLIST_DIR_RM: sprintf(tmp, "%s/%s", Where, p->name); if (!isdir(tmp) && fexists(tmp)) { warnx("cannot delete specified directory '%s' - it is a file!\n" "this packing list is incorrect - ignoring delete request", tmp); } else { if (Verbose) printf("Delete directory %s\n", tmp); if (!Fake && delete_hierarchy(tmp, ign_err, FALSE)) { warnx("unable to completely remove directory '%s'", tmp); fail = FAIL; } } last_file = p->name; break; default: break; } } return fail; }
static int svr4info(struct pkginfo *info, char *pkginst, char *ckvers) { static DIR *pdirfp; struct stat64 status; FILE *fp; char *pt, path[128], line[128]; char temp[PKGSIZ+1]; if (strcmp(pkginst, "all")) { if (pdirfp) { (void) closedir(pdirfp); pdirfp = NULL; } /* determine pkginst - remove '.*' extension, if any */ (void) strncpy(temp, pkginst, PKGSIZ); if (((pt = strchr(temp, '.')) != NULL) && strcmp(pt, ".*") == 0) *pt = '\0'; } /* look in /usr/options direcotry for 'name' file */ (void) sprintf(path, "%s/%s.name", get_PKGOLD(), temp); if (lstat64(path, &status)) { errno = (errno == ENOENT) ? ESRCH : EACCES; return (-1); } if ((status.st_mode & S_IFMT) != S_IFREG) { errno = ESRCH; return (-1); } if ((fp = fopen(path, "r")) == NULL) { errno = (errno == ENOENT) ? ESRCH : EACCES; return (-1); } /* /usr/options/xxx.name exists */ (void) fgets(line, 128, fp); (void) fclose(fp); if (pt = strchr(line, '\n')) *pt = '\0'; /* remove trailing newline */ if (pt = strchr(line, ':')) *pt++ = '\0'; /* assumed version specification */ if (info) { info->name = strdup(line); info->pkginst = strdup(temp); if (!info->name || !info->pkginst) { errno = ENOMEM; return (-1); } info->status = PI_PRESVR4; info->version = NULL; } if (pt) { /* eat leading space off of version spec */ while (isspace((unsigned char)*pt)) pt++; } if (ckvers && verscmp(ckvers, pt)) { errno = ESRCH; return (-1); } if (info && *pt) info->version = strdup(pt); return (0); }