1 /* $NetBSD: pl.c,v 1.5 2021/04/10 19:49:59 nia Exp $ */
2
3 #ifdef HAVE_NBTOOL_CONFIG_H
4 #include "nbtool_config.h"
5 #else
6 #if HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9 #include <nbcompat.h>
10 #if HAVE_SYS_CDEFS_H
11 #include <sys/cdefs.h>
12 #endif
13 #endif
14 __RCSID("$NetBSD: pl.c,v 1.5 2021/04/10 19:49:59 nia Exp $");
15
16 /*
17 * FreeBSD install - a package for the installation and maintainance
18 * of non-core utilities.
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
28 *
29 * Jordan K. Hubbard
30 * 18 July 1993
31 *
32 * Routines for dealing with the packing list.
33 *
34 */
35
36 #include "lib.h"
37 #include "create.h"
38 #if HAVE_ERR_H
39 #include <err.h>
40 #endif
41 #ifndef NETBSD
42 #include <nbcompat/md5.h>
43 #else
44 #include <md5.h>
45 #endif
46
47 /*
48 * Check that any symbolic link is relative to the prefix
49 */
50 static void
CheckSymlink(char * name,char * prefix,size_t prefixcc)51 CheckSymlink(char *name, char *prefix, size_t prefixcc)
52 {
53 char newtgt[MaxPathSize];
54 char oldtgt[MaxPathSize];
55 char *slash;
56 int slashc;
57 int cc;
58 int i;
59
60 if ((cc = readlink(name, oldtgt, sizeof(oldtgt) - 1)) > 0) {
61 oldtgt[cc] = 0;
62 if (strncmp(oldtgt, prefix, prefixcc) == 0 && oldtgt[prefixcc] == '/') {
63 for (slashc = 0, slash = &name[prefixcc + 1]; (slash = strchr(slash, '/')) != (char *) NULL; slash++, slashc++) {
64 }
65 for (cc = i = 0; i < slashc; i++) {
66 strlcpy(&newtgt[cc], "../", sizeof(newtgt) - cc);
67 cc += 3;
68 }
69 strlcpy(&newtgt[cc], &oldtgt[prefixcc + 1], sizeof(newtgt) - cc);
70 (void) fprintf(stderr, "Full pathname symlink `%s' is target of `%s' - adjusting to `%s'\n", oldtgt, name, newtgt);
71 if (unlink(name) != 0) {
72 warn("can't unlink `%s'", name);
73 } else if (symlink(newtgt, name) != 0) {
74 warn("can't symlink `%s' called `%s'", newtgt, name);
75 }
76 }
77 }
78 }
79
80 /*
81 * Check a list for files that require preconversion
82 */
83 void
check_list(package_t * pkg,const char * PkgName)84 check_list(package_t *pkg, const char *PkgName)
85 {
86 struct stat st;
87 plist_t *tmp;
88 plist_t *p;
89 char buf[ChecksumHeaderLen + LegibleChecksumLen];
90 char target[MaxPathSize + SymlinkHeaderLen];
91 char name[MaxPathSize];
92 char *cwd = NULL;
93 char *pkgname = NULL;
94 int cc;
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 break;
113 case PLIST_FILE:
114 if (cwd == NULL)
115 errx(2, "file without preceding @cwd found");
116 (void) snprintf(name, sizeof(name), "%s%s%s",
117 cwd,
118 (strcmp(cwd, "/") == 0) ? "" : "/",
119 p->name);
120 if (lstat(name, &st) < 0) {
121 warnx("can't stat `%s'", name);
122 continue;
123 }
124 switch (st.st_mode & S_IFMT) {
125 case S_IFDIR:
126 warnx("Warning - directory `%s' in PLIST", name);
127 break;
128 case S_IFLNK:
129 if (RelativeLinks) {
130 CheckSymlink(name, cwd, strlen(cwd));
131 }
132 (void) strlcpy(target, SYMLINK_HEADER,
133 sizeof(target));
134 if ((cc = readlink(name, &target[SymlinkHeaderLen],
135 sizeof(target) - SymlinkHeaderLen - 1)) < 0) {
136 warnx("can't readlink `%s'", name);
137 continue;
138 }
139 target[SymlinkHeaderLen + cc] = 0x0;
140 tmp = new_plist_entry();
141 tmp->name = xstrdup(target);
142 tmp->type = PLIST_COMMENT;
143 tmp->next = p->next;
144 tmp->prev = p;
145 if (p == pkg->tail) {
146 pkg->tail = tmp;
147 }
148 p->next = tmp;
149 p = tmp;
150 break;
151 case S_IFCHR:
152 warnx("Warning - char special device `%s' in PLIST", name);
153 break;
154 case S_IFBLK:
155 warnx("Warning - block special device `%s' in PLIST", name);
156 break;
157 default:
158 (void) strlcpy(buf, CHECKSUM_HEADER,
159 sizeof(buf));
160 if (MD5File(name, &buf[ChecksumHeaderLen]) != (char *) NULL) {
161 tmp = new_plist_entry();
162 tmp->name = xstrdup(buf);
163 tmp->type = PLIST_COMMENT; /* PLIST_MD5 - HF */
164 tmp->next = p->next;
165 tmp->prev = p;
166 if (p == pkg->tail) {
167 pkg->tail = tmp;
168 }
169 p->next = tmp;
170 p = tmp;
171 }
172 break;
173 }
174 break;
175 default:
176 break;
177 }
178 }
179 }
180