1 /* $NetBSD: pl.c,v 1.1.1.3 2009/04/24 14:16:59 joerg Exp $ */ 2 3 #if HAVE_CONFIG_H 4 #include "config.h" 5 #endif 6 #include <nbcompat.h> 7 #if HAVE_SYS_CDEFS_H 8 #include <sys/cdefs.h> 9 #endif 10 __RCSID("$NetBSD: pl.c,v 1.1.1.3 2009/04/24 14:16:59 joerg Exp $"); 11 12 /* 13 * FreeBSD install - a package for the installation and maintainance 14 * of non-core utilities. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 25 * Jordan K. Hubbard 26 * 18 July 1993 27 * 28 * Routines for dealing with the packing list. 29 * 30 */ 31 32 #include "lib.h" 33 #include "create.h" 34 #if HAVE_ERR_H 35 #include <err.h> 36 #endif 37 #ifndef NETBSD 38 #include <nbcompat/md5.h> 39 #else 40 #include <md5.h> 41 #endif 42 43 /* 44 * Check that any symbolic link is relative to the prefix 45 */ 46 static void 47 CheckSymlink(char *name, char *prefix, size_t prefixcc) 48 { 49 char newtgt[MaxPathSize]; 50 char oldtgt[MaxPathSize]; 51 char *slash; 52 int slashc; 53 int cc; 54 int i; 55 56 if ((cc = readlink(name, oldtgt, sizeof(oldtgt) - 1)) > 0) { 57 oldtgt[cc] = 0; 58 if (strncmp(oldtgt, prefix, prefixcc) == 0 && oldtgt[prefixcc] == '/') { 59 for (slashc = 0, slash = &name[prefixcc + 1]; (slash = strchr(slash, '/')) != (char *) NULL; slash++, slashc++) { 60 } 61 for (cc = i = 0; i < slashc; i++) { 62 strlcpy(&newtgt[cc], "../", sizeof(newtgt) - cc); 63 cc += 3; 64 } 65 strlcpy(&newtgt[cc], &oldtgt[prefixcc + 1], sizeof(newtgt) - cc); 66 (void) fprintf(stderr, "Full pathname symlink `%s' is target of `%s' - adjusting to `%s'\n", oldtgt, name, newtgt); 67 if (unlink(name) != 0) { 68 warn("can't unlink `%s'", name); 69 } else if (symlink(newtgt, name) != 0) { 70 warn("can't symlink `%s' called `%s'", newtgt, name); 71 } 72 } 73 } 74 } 75 76 /* 77 * Check a list for files that require preconversion 78 */ 79 void 80 check_list(package_t *pkg, const char *PkgName) 81 { 82 struct stat st; 83 plist_t *tmp; 84 plist_t *p; 85 char buf[ChecksumHeaderLen + LegibleChecksumLen]; 86 char target[MaxPathSize + SymlinkHeaderLen]; 87 char name[MaxPathSize]; 88 char *cwd = NULL; 89 char *srcdir = NULL; 90 char *pkgname = NULL; 91 int cc; 92 93 /* Open Package Database for writing */ 94 if (update_pkgdb && !pkgdb_open(ReadWrite)) 95 err(EXIT_FAILURE, "can't open pkgdb"); 96 97 for (p = pkg->head; p; p = p->next) { 98 switch (p->type) { 99 case PLIST_CWD: 100 cwd = p->name; 101 break; 102 case PLIST_NAME: 103 pkgname = p->name; 104 break; 105 case PLIST_IGNORE: 106 p = p->next; 107 break; 108 case PLIST_SRC: 109 srcdir = p->name; 110 break; 111 case PLIST_PKGDIR: 112 if (cwd == NULL) 113 errx(2, "@pkgdir without preceding @cwd found"); 114 if (pkgname == NULL) 115 errx(2, "@pkgdir without preceding @name found"); 116 if (update_pkgdb) { 117 add_pkgdir(pkgname, cwd, p->name); 118 /* mkdir_p(cwd, p->name); */ 119 } 120 break; 121 case PLIST_FILE: 122 /* 123 * pkgdb handling - usually, we enter files 124 * into the pkgdb as soon as they hit the disk, 125 * but as they are present before pkg_create 126 * starts, it's ok to do this somewhere here 127 */ 128 if (cwd == NULL) 129 errx(2, "file without preceding @cwd found"); 130 if (update_pkgdb) { 131 char *s, t[MaxPathSize]; 132 133 (void) snprintf(t, sizeof(t), "%s%s%s", 134 cwd, 135 (strcmp(cwd, "/") == 0) ? "" : "/", 136 p->name); 137 138 s = pkgdb_retrieve(t); 139 if (s && PlistOnly) 140 warnx("Overwriting %s - " 141 "pkg %s bogus/conflicting?", t, s); 142 else { 143 pkgdb_store(t, PkgName); 144 } 145 } 146 147 /* prepend DESTDIR if set? - HF */ 148 (void) snprintf(name, sizeof(name), "%s%s%s", 149 cwd, 150 (strcmp(cwd, "/") == 0) ? "" : "/", 151 p->name); 152 if (lstat(name, &st) < 0) { 153 warnx("can't stat `%s'", name); 154 continue; 155 } 156 switch (st.st_mode & S_IFMT) { 157 case S_IFDIR: 158 warnx("Warning - directory `%s' in PLIST", name); 159 break; 160 case S_IFLNK: 161 if (RelativeLinks) { 162 CheckSymlink(name, cwd, strlen(cwd)); 163 } 164 (void) strlcpy(target, SYMLINK_HEADER, 165 sizeof(target)); 166 if ((cc = readlink(name, &target[SymlinkHeaderLen], 167 sizeof(target) - SymlinkHeaderLen - 1)) < 0) { 168 warnx("can't readlink `%s'", name); 169 continue; 170 } 171 target[SymlinkHeaderLen + cc] = 0x0; 172 tmp = new_plist_entry(); 173 tmp->name = xstrdup(target); 174 tmp->type = PLIST_COMMENT; 175 tmp->next = p->next; 176 tmp->prev = p; 177 if (p == pkg->tail) { 178 pkg->tail = tmp; 179 } 180 p->next = tmp; 181 p = tmp; 182 break; 183 case S_IFCHR: 184 warnx("Warning - char special device `%s' in PLIST", name); 185 break; 186 case S_IFBLK: 187 warnx("Warning - block special device `%s' in PLIST", name); 188 break; 189 default: 190 (void) strlcpy(buf, CHECKSUM_HEADER, 191 sizeof(buf)); 192 if (MD5File(name, &buf[ChecksumHeaderLen]) != (char *) NULL) { 193 tmp = new_plist_entry(); 194 tmp->name = xstrdup(buf); 195 tmp->type = PLIST_COMMENT; /* PLIST_MD5 - HF */ 196 tmp->next = p->next; 197 tmp->prev = p; 198 if (p == pkg->tail) { 199 pkg->tail = tmp; 200 } 201 p->next = tmp; 202 p = tmp; 203 } 204 break; 205 } 206 break; 207 default: 208 break; 209 } 210 } 211 212 if (update_pkgdb) { 213 pkgdb_close(); 214 } 215 } 216