diff options
Diffstat (limited to 'pkgtools/pkg_install/files/create/pl.c')
-rw-r--r-- | pkgtools/pkg_install/files/create/pl.c | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/pkgtools/pkg_install/files/create/pl.c b/pkgtools/pkg_install/files/create/pl.c new file mode 100644 index 00000000000..54b763d3337 --- /dev/null +++ b/pkgtools/pkg_install/files/create/pl.c @@ -0,0 +1,238 @@ +/* $NetBSD: pl.c,v 1.1.1.1 2002/12/20 18:14:11 schmonz Exp $ */ + +#if 0 +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static const char *rcsid = "from FreeBSD Id: pl.c,v 1.11 1997/10/08 07:46:35 charnier Exp"; +#else +__RCSID("$NetBSD: pl.c,v 1.1.1.1 2002/12/20 18:14:11 schmonz Exp $"); +#endif +#endif +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Routines for dealing with the packing list. + * + */ + +#include "lib.h" +#include "create.h" + +#ifdef HAVE_ERR_H +#include <err.h> +#endif + +#ifdef HAVE_MD5GLOBAL_H +#include <md5global.h> +#endif + +#ifdef HAVE_MD5_H +#include <md5.h> +#endif + +/* + * Check that any symbolic link is relative to the prefix + */ +static void +CheckSymlink(char *name, char *prefix, size_t prefixcc) +{ + char newtgt[MAXPATHLEN]; + char oldtgt[MAXPATHLEN]; + char *slash; + int slashc; + int cc; + int i; + + if ((cc = readlink(name, oldtgt, sizeof(oldtgt) - 1)) > 0) { + oldtgt[cc] = 0; + if (strncmp(oldtgt, prefix, prefixcc) == 0 && oldtgt[prefixcc] == '/') { + for (slashc = 0, slash = &name[prefixcc + 1]; (slash = strchr(slash, '/')) != (char *) NULL; slash++, slashc++) { + } + for (cc = i = 0; i < slashc; i++) { + strnncpy(&newtgt[cc], sizeof(newtgt) - cc, "../", 3); + cc += 3; + } + strnncpy(&newtgt[cc], sizeof(newtgt) - cc, &oldtgt[prefixcc + 1], strlen(&oldtgt[prefixcc + 1])); + (void) fprintf(stderr, "Full pathname symlink `%s' is target of `%s' - adjusting to `%s'\n", oldtgt, name, newtgt); + if (unlink(name) != 0) { + warn("can't unlink `%s'", name); + } else if (symlink(newtgt, name) != 0) { + warn("can't symlink `%s' called `%s'", newtgt, name); + } + } + } +} + +/* + * (Reversed) comparison routine for directory name sorting + */ +static int +dircmp(const void *vp1, const void *vp2) +{ + return strcmp((const char *) vp2, (const char *) vp1); +} + +/* + * Re-order the PLIST_DIR_RM entries into reverse alphabetic order + */ +static void +reorder(package_t *pkg, int dirc) +{ + plist_t *p; + char **dirv; + int i; + + if ((dirv = (char **) calloc(dirc, sizeof(char *))) == (char **) NULL) { + warn("No directory re-ordering will be done"); + } else { + for (p = pkg->head, i = 0; p; p = p->next) { + if (p->type == PLIST_DIR_RM) { + dirv[i++] = p->name; + } + } + qsort(dirv, dirc, sizeof(char *), dircmp); + for (p = pkg->head, i = 0; p; p = p->next) { + if (p->type == PLIST_DIR_RM) { + p->name = dirv[i++]; + } + } + (void) free(dirv); + } +} + +/* + * Check a list for files that require preconversion + */ +void +check_list(char *home, package_t *pkg, const char *PkgName) +{ + struct stat st; + plist_t *tmp; + plist_t *p; + char name[FILENAME_MAX]; + char buf[ChecksumHeaderLen + LegibleChecksumLen]; + char *cwd = home; + char *srcdir = NULL; + int dirc; + + /* Open Package Database for writing */ + if (update_pkgdb && pkgdb_open(0) == -1) { + cleanup(0); + err(1, "can't open pkgdb"); + } + + for (dirc = 0, p = pkg->head; p; p = p->next) { + switch (p->type) { + case PLIST_CWD: + cwd = p->name; + break; + case PLIST_IGNORE: + p = p->next; + break; + case PLIST_SRC: + srcdir = p->name; + break; + case PLIST_DIR_RM: + dirc++; + break; + case PLIST_FILE: + /* + * pkgdb handling - usually, we enter files + * into the pkgdb as soon as they hit the disk, + * but as they are present before pkg_create + * starts, it's ok to do this somewhere here + */ + if (update_pkgdb) { + char *s, t[FILENAME_MAX]; + + (void) snprintf(t, sizeof(t), "%s/%s", cwd, p->name); + + s = pkgdb_retrieve(t); +#ifdef PKGDB_DEBUG + fprintf(stderr, "pkgdb_retrieve(\"%s\")=\"%s\"\n", t, s); /* pkgdb-debug - HF */ +#endif + if (s && PlistOnly) + warnx("Overwriting %s - " + "pkg %s bogus/conflicting?", t, s); + else { + pkgdb_store(t, PkgName); +#ifdef PKGDB_DEBUG + fprintf(stderr, "pkgdb_store(\"%s\", \"%s\")\n", t, PkgName); /* pkgdb-debug - HF */ +#endif + } + } + + if (cwd == home) { + /* no @cwd yet */ + (void) snprintf(name, sizeof(name), "%s/%s", srcdir ? srcdir : cwd, p->name); + } else { + /* after @cwd */ + /* prepend DESTDIR if set? - HF */ + (void) snprintf(name, sizeof(name), "%s/%s", cwd, p->name); + } + if (lstat(name, &st) < 0) { + warnx("can't stat `%s'", name); + continue; + } + switch (st.st_mode & S_IFMT) { + case S_IFDIR: + p->type = PLIST_DIR_RM; + dirc++; + continue; + case S_IFLNK: + if (RelativeLinks) { + CheckSymlink(name, cwd, strlen(cwd)); + } + break; + case S_IFCHR: + warnx("Warning - char special device `%s' in PLIST", name); + break; + case S_IFBLK: + warnx("Warning - block special device `%s' in PLIST", name); + break; + default: + (void) strcpy(buf, CHECKSUM_HEADER); + if (MD5File(name, &buf[ChecksumHeaderLen]) != (char *) NULL) { + tmp = new_plist_entry(); + tmp->name = strdup(buf); + tmp->type = PLIST_COMMENT; /* PLIST_MD5 - HF */ + tmp->next = p->next; + tmp->prev = p; + if (p == pkg->tail) { + pkg->tail = tmp; + } + p->next = tmp; + p = tmp; + } + break; + } + break; + default: + break; + } + } + + if (update_pkgdb) { + pkgdb_close(); + } + + if (ReorderDirs && dirc > 0) { + reorder(pkg, dirc); + } +} |