/* Add an MD5 checksum entry for a file or link */ void add_cksum(Package *pkg, PackingList p, const char *fname) { char *cp = NULL, buf[33]; if (issymlink(fname)) { int len; char lnk[FILENAME_MAX]; if ((len = readlink(fname, lnk, FILENAME_MAX)) > 0) cp = MD5Data((unsigned char *)lnk, len, buf); } else if (isfile(fname)) { /* Don't record MD5 checksum for device nodes and such */ cp = MD5File(fname, buf); } if (cp != NULL) { PackingList tmp = new_plist_entry(); tmp->name = copy_string(strconcat("MD5:", cp)); tmp->type = PLIST_COMMENT; tmp->next = p->next; tmp->prev = p; p->next = tmp; if (pkg->tail == p) pkg->tail = tmp; } }
/* Selectively delete a hierarchy */ int delete_hierarchy(const char *dir, Boolean ign_err, Boolean nukedirs) { char *cp1, *cp2; cp1 = cp2 = strdup(dir); if (!fexists(dir) && !issymlink(dir)) { if (!ign_err) warnx("%s '%s' doesn't exist", isdir(dir) ? "directory" : "file", dir); return !ign_err; } else if (nukedirs) { if (vsystem("%s -r%s %s", REMOVE_CMD, (ign_err ? "f" : ""), dir)) return 1; } else if (isdir(dir) && !issymlink(dir)) { if (RMDIR(dir) && !ign_err) return 1; } else { if (REMOVE(dir, ign_err)) return 1; } if (!nukedirs) return 0; while (cp2) { if ((cp2 = strrchr(cp1, '/')) != NULL) *cp2 = '\0'; if (!isemptydir(dir)) return 0; if (RMDIR(dir) && !ign_err) { if (!fexists(dir)) warnx("directory '%s' doesn't exist", dir); else return 1; } /* back up the pathname one component */ if (cp2) { cp1 = strdup(dir); } } return 0; }
/* 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); }
int set_readonly(const char *newname) { mode_t mode; /* Symlinks don't have modes (and it affects instead the files they point to so just ignore the command if this is a symlink. */ if(issymlink(newname)) return 0; mode = getmode(newname); /* Remove all the writable characteristics of this file */ mode = (mode & (~(S_IWGRP | S_IWOTH | S_IWUSR))); /* Change the mode */ chmod(newname, mode); return 0; }
void bs_open_output(struct bitstream_st *bs, char const *fname) { int flags; mode_t perms; bs->blocked = main_runtime.drop_output; bs->byte_p = bs->byte_window; bs->byte_end = AFTER_OF(bs->byte_window); bs->bit_p = bs->bit_window; bs->bit_end = AFTER_OF(bs->bit_window); if (!fname) fname = makeup_output_fname(&input_bs); if (fname[0] == '-' && fname[1] == '\0') { bs->fd = STDOUT_FILENO; bs->fname = "(stdout)"; bs->stdfd = 1; return; } #ifdef CONFIG_FANCY_UI flags = O_CREAT | O_WRONLY | O_APPEND; if (main_runtime.append) ; else if (!main_runtime.overwrite) flags |= O_EXCL; else if (main_runtime.symfollow) flags |= O_TRUNC; perms = makeup_output_perms(&input_bs); if ((bs->fd = open(fname, flags, perms)) < 0) { logf("open: %s: %s", fname, strerror(errno)); goto out0; } if (!main_runtime.symfollow && issymlink(bs->fd, fname)) { logf("%s: is a symlink", fname); goto out1; } if (main_runtime.overwrite && !main_runtime.symfollow && ftruncate(bs->fd, 0) < 0) { logf("ftruncate: %s: %s", fname, strerror(errno)); goto out1; } bs->fname = fname; bs->stdfd = 0; return; out1: close(bs->fd); bs->fd = -1; out0: bs->fname = NULL; throw_exception(EXIT_ERR_OTHER); #endif /* CONFIG_FANCY_UI */ } /* bs_create */
/* * 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; }