1 /* $NetBSD: pl.c,v 1.1.1.4 2009/11/05 18:39:03 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.4 2009/11/05 18:39:03 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 *pkgname = NULL; 90 int cc; 91 92 /* Open Package Database for writing */ 93 if (update_pkgdb && !pkgdb_open(ReadWrite)) 94 err(EXIT_FAILURE, "can't open pkgdb"); 95 96 for (p = pkg->head; p; p = p->next) { 97 switch (p->type) { 98 case PLIST_CWD: 99 cwd = p->name; 100 break; 101 case PLIST_NAME: 102 pkgname = p->name; 103 break; 104 case PLIST_IGNORE: 105 p = p->next; 106 break; 107 case PLIST_PKGDIR: 108 if (cwd == NULL) 109 errx(2, "@pkgdir without preceding @cwd found"); 110 if (pkgname == NULL) 111 errx(2, "@pkgdir without preceding @name found"); 112 if (update_pkgdb) { 113 add_pkgdir(pkgname, cwd, p->name); 114 /* mkdir_p(cwd, p->name); */ 115 } 116 break; 117 case PLIST_FILE: 118 /* 119 * pkgdb handling - usually, we enter files 120 * into the pkgdb as soon as they hit the disk, 121 * but as they are present before pkg_create 122 * starts, it's ok to do this somewhere here 123 */ 124 if (cwd == NULL) 125 errx(2, "file without preceding @cwd found"); 126 if (update_pkgdb) { 127 char *s, t[MaxPathSize]; 128 129 (void) snprintf(t, sizeof(t), "%s%s%s", 130 cwd, 131 (strcmp(cwd, "/") == 0) ? "" : "/", 132 p->name); 133 134 s = pkgdb_retrieve(t); 135 if (s && PlistOnly) 136 warnx("Overwriting %s - " 137 "pkg %s bogus/conflicting?", t, s); 138 else { 139 pkgdb_store(t, PkgName); 140 } 141 } 142 143 /* prepend DESTDIR if set? - HF */ 144 (void) snprintf(name, sizeof(name), "%s%s%s", 145 cwd, 146 (strcmp(cwd, "/") == 0) ? "" : "/", 147 p->name); 148 if (lstat(name, &st) < 0) { 149 warnx("can't stat `%s'", name); 150 continue; 151 } 152 switch (st.st_mode & S_IFMT) { 153 case S_IFDIR: 154 warnx("Warning - directory `%s' in PLIST", name); 155 break; 156 case S_IFLNK: 157 if (RelativeLinks) { 158 CheckSymlink(name, cwd, strlen(cwd)); 159 } 160 (void) strlcpy(target, SYMLINK_HEADER, 161 sizeof(target)); 162 if ((cc = readlink(name, &target[SymlinkHeaderLen], 163 sizeof(target) - SymlinkHeaderLen - 1)) < 0) { 164 warnx("can't readlink `%s'", name); 165 continue; 166 } 167 target[SymlinkHeaderLen + cc] = 0x0; 168 tmp = new_plist_entry(); 169 tmp->name = xstrdup(target); 170 tmp->type = PLIST_COMMENT; 171 tmp->next = p->next; 172 tmp->prev = p; 173 if (p == pkg->tail) { 174 pkg->tail = tmp; 175 } 176 p->next = tmp; 177 p = tmp; 178 break; 179 case S_IFCHR: 180 warnx("Warning - char special device `%s' in PLIST", name); 181 break; 182 case S_IFBLK: 183 warnx("Warning - block special device `%s' in PLIST", name); 184 break; 185 default: 186 (void) strlcpy(buf, CHECKSUM_HEADER, 187 sizeof(buf)); 188 if (MD5File(name, &buf[ChecksumHeaderLen]) != (char *) NULL) { 189 tmp = new_plist_entry(); 190 tmp->name = xstrdup(buf); 191 tmp->type = PLIST_COMMENT; /* PLIST_MD5 - HF */ 192 tmp->next = p->next; 193 tmp->prev = p; 194 if (p == pkg->tail) { 195 pkg->tail = tmp; 196 } 197 p->next = tmp; 198 p = tmp; 199 } 200 break; 201 } 202 break; 203 default: 204 break; 205 } 206 } 207 208 if (update_pkgdb) { 209 pkgdb_close(); 210 } 211 } 212