| @@ -1,1632 +1,1632 @@ | | | @@ -1,1632 +1,1632 @@ |
1 | /* $NetBSD: perform.c,v 1.117 2020/12/12 01:44:17 gutteridge Exp $ */ | | 1 | /* $NetBSD: perform.c,v 1.118 2020/12/12 04:12:47 gutteridge Exp $ */ |
2 | #if HAVE_CONFIG_H | | 2 | #if HAVE_CONFIG_H |
3 | #include "config.h" | | 3 | #include "config.h" |
4 | #endif | | 4 | #endif |
5 | #include <nbcompat.h> | | 5 | #include <nbcompat.h> |
6 | #if HAVE_SYS_CDEFS_H | | 6 | #if HAVE_SYS_CDEFS_H |
7 | #include <sys/cdefs.h> | | 7 | #include <sys/cdefs.h> |
8 | #endif | | 8 | #endif |
9 | __RCSID("$NetBSD: perform.c,v 1.117 2020/12/12 01:44:17 gutteridge Exp $"); | | 9 | __RCSID("$NetBSD: perform.c,v 1.118 2020/12/12 04:12:47 gutteridge Exp $"); |
10 | | | 10 | |
11 | /*- | | 11 | /*- |
12 | * Copyright (c) 2003 Grant Beattie <grant@NetBSD.org> | | 12 | * Copyright (c) 2003 Grant Beattie <grant@NetBSD.org> |
13 | * Copyright (c) 2005 Dieter Baron <dillo@NetBSD.org> | | 13 | * Copyright (c) 2005 Dieter Baron <dillo@NetBSD.org> |
14 | * Copyright (c) 2007 Roland Illig <rillig@NetBSD.org> | | 14 | * Copyright (c) 2007 Roland Illig <rillig@NetBSD.org> |
15 | * Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg@NetBSD.org> | | 15 | * Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg@NetBSD.org> |
16 | * Copyright (c) 2010 Thomas Klausner <wiz@NetBSD.org> | | 16 | * Copyright (c) 2010 Thomas Klausner <wiz@NetBSD.org> |
17 | * All rights reserved. | | 17 | * All rights reserved. |
18 | * | | 18 | * |
19 | * Redistribution and use in source and binary forms, with or without | | 19 | * Redistribution and use in source and binary forms, with or without |
20 | * modification, are permitted provided that the following conditions | | 20 | * modification, are permitted provided that the following conditions |
21 | * are met: | | 21 | * are met: |
22 | * | | 22 | * |
23 | * 1. Redistributions of source code must retain the above copyright | | 23 | * 1. Redistributions of source code must retain the above copyright |
24 | * notice, this list of conditions and the following disclaimer. | | 24 | * notice, this list of conditions and the following disclaimer. |
25 | * 2. Redistributions in binary form must reproduce the above copyright | | 25 | * 2. Redistributions in binary form must reproduce the above copyright |
26 | * notice, this list of conditions and the following disclaimer in | | 26 | * notice, this list of conditions and the following disclaimer in |
27 | * the documentation and/or other materials provided with the | | 27 | * the documentation and/or other materials provided with the |
28 | * distribution. | | 28 | * distribution. |
29 | * | | 29 | * |
30 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | | 30 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
31 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | | 31 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
32 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | | 32 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
33 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | | 33 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
34 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | | 34 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
35 | * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, | | 35 | * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, |
36 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | | 36 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
37 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | | 37 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
38 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | | 38 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
39 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | | 39 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
40 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 40 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
41 | * SUCH DAMAGE. | | 41 | * SUCH DAMAGE. |
42 | */ | | 42 | */ |
43 | | | 43 | |
44 | #include <sys/utsname.h> | | 44 | #include <sys/utsname.h> |
45 | #include <sys/stat.h> | | 45 | #include <sys/stat.h> |
46 | #if HAVE_ERR_H | | 46 | #if HAVE_ERR_H |
47 | #include <err.h> | | 47 | #include <err.h> |
48 | #endif | | 48 | #endif |
49 | #include <errno.h> | | 49 | #include <errno.h> |
50 | #if HAVE_FCNTL_H | | 50 | #if HAVE_FCNTL_H |
51 | #include <fcntl.h> | | 51 | #include <fcntl.h> |
52 | #endif | | 52 | #endif |
53 | #include <limits.h> | | 53 | #include <limits.h> |
54 | #include <stdlib.h> | | 54 | #include <stdlib.h> |
55 | #include <string.h> | | 55 | #include <string.h> |
56 | #include <unistd.h> | | 56 | #include <unistd.h> |
57 | | | 57 | |
58 | #include <archive.h> | | 58 | #include <archive.h> |
59 | #include <archive_entry.h> | | 59 | #include <archive_entry.h> |
60 | | | 60 | |
61 | #include "lib.h" | | 61 | #include "lib.h" |
62 | #include "add.h" | | 62 | #include "add.h" |
63 | #include "version.h" | | 63 | #include "version.h" |
64 | | | 64 | |
65 | struct pkg_meta { | | 65 | struct pkg_meta { |
66 | char *meta_contents; | | 66 | char *meta_contents; |
67 | char *meta_comment; | | 67 | char *meta_comment; |
68 | char *meta_desc; | | 68 | char *meta_desc; |
69 | char *meta_mtree; | | 69 | char *meta_mtree; |
70 | char *meta_build_version; | | 70 | char *meta_build_version; |
71 | char *meta_build_info; | | 71 | char *meta_build_info; |
72 | char *meta_size_pkg; | | 72 | char *meta_size_pkg; |
73 | char *meta_size_all; | | 73 | char *meta_size_all; |
74 | char *meta_required_by; | | 74 | char *meta_required_by; |
75 | char *meta_display; | | 75 | char *meta_display; |
76 | char *meta_install; | | 76 | char *meta_install; |
77 | char *meta_deinstall; | | 77 | char *meta_deinstall; |
78 | char *meta_preserve; | | 78 | char *meta_preserve; |
79 | char *meta_installed_info; | | 79 | char *meta_installed_info; |
80 | }; | | 80 | }; |
81 | | | 81 | |
82 | struct pkg_task { | | 82 | struct pkg_task { |
83 | char *pkgname; | | 83 | char *pkgname; |
84 | | | 84 | |
85 | const char *prefix; | | 85 | const char *prefix; |
86 | char *install_prefix; | | 86 | char *install_prefix; |
87 | | | 87 | |
88 | char *logdir; | | 88 | char *logdir; |
89 | char *install_logdir; | | 89 | char *install_logdir; |
90 | char *install_logdir_real; | | 90 | char *install_logdir_real; |
91 | char *other_version; | | 91 | char *other_version; |
92 | | | 92 | |
93 | package_t plist; | | 93 | package_t plist; |
94 | | | 94 | |
95 | struct pkg_meta meta_data; | | 95 | struct pkg_meta meta_data; |
96 | | | 96 | |
97 | struct archive *archive; | | 97 | struct archive *archive; |
98 | struct archive_entry *entry; | | 98 | struct archive_entry *entry; |
99 | | | 99 | |
100 | char *buildinfo[BI_ENUM_COUNT]; | | 100 | char *buildinfo[BI_ENUM_COUNT]; |
101 | | | 101 | |
102 | size_t dep_length, dep_allocated; | | 102 | size_t dep_length, dep_allocated; |
103 | char **dependencies; | | 103 | char **dependencies; |
104 | }; | | 104 | }; |
105 | | | 105 | |
106 | static const struct pkg_meta_desc { | | 106 | static const struct pkg_meta_desc { |
107 | size_t entry_offset; | | 107 | size_t entry_offset; |
108 | const char *entry_filename; | | 108 | const char *entry_filename; |
109 | int required_file; | | 109 | int required_file; |
110 | mode_t perm; | | 110 | mode_t perm; |
111 | } pkg_meta_descriptors[] = { | | 111 | } pkg_meta_descriptors[] = { |
112 | { offsetof(struct pkg_meta, meta_contents), CONTENTS_FNAME, 1, 0644 }, | | 112 | { offsetof(struct pkg_meta, meta_contents), CONTENTS_FNAME, 1, 0644 }, |
113 | { offsetof(struct pkg_meta, meta_comment), COMMENT_FNAME, 1, 0444}, | | 113 | { offsetof(struct pkg_meta, meta_comment), COMMENT_FNAME, 1, 0444}, |
114 | { offsetof(struct pkg_meta, meta_desc), DESC_FNAME, 1, 0444}, | | 114 | { offsetof(struct pkg_meta, meta_desc), DESC_FNAME, 1, 0444}, |
115 | { offsetof(struct pkg_meta, meta_install), INSTALL_FNAME, 0, 0555 }, | | 115 | { offsetof(struct pkg_meta, meta_install), INSTALL_FNAME, 0, 0555 }, |
116 | { offsetof(struct pkg_meta, meta_deinstall), DEINSTALL_FNAME, 0, 0555 }, | | 116 | { offsetof(struct pkg_meta, meta_deinstall), DEINSTALL_FNAME, 0, 0555 }, |
117 | { offsetof(struct pkg_meta, meta_display), DISPLAY_FNAME, 0, 0444 }, | | 117 | { offsetof(struct pkg_meta, meta_display), DISPLAY_FNAME, 0, 0444 }, |
118 | { offsetof(struct pkg_meta, meta_mtree), MTREE_FNAME, 0, 0444 }, | | 118 | { offsetof(struct pkg_meta, meta_mtree), MTREE_FNAME, 0, 0444 }, |
119 | { offsetof(struct pkg_meta, meta_build_version), BUILD_VERSION_FNAME, 0, 0444 }, | | 119 | { offsetof(struct pkg_meta, meta_build_version), BUILD_VERSION_FNAME, 0, 0444 }, |
120 | { offsetof(struct pkg_meta, meta_build_info), BUILD_INFO_FNAME, 0, 0444 }, | | 120 | { offsetof(struct pkg_meta, meta_build_info), BUILD_INFO_FNAME, 0, 0444 }, |
121 | { offsetof(struct pkg_meta, meta_size_pkg), SIZE_PKG_FNAME, 0, 0444 }, | | 121 | { offsetof(struct pkg_meta, meta_size_pkg), SIZE_PKG_FNAME, 0, 0444 }, |
122 | { offsetof(struct pkg_meta, meta_size_all), SIZE_ALL_FNAME, 0, 0444 }, | | 122 | { offsetof(struct pkg_meta, meta_size_all), SIZE_ALL_FNAME, 0, 0444 }, |
123 | { offsetof(struct pkg_meta, meta_preserve), PRESERVE_FNAME, 0, 0444 }, | | 123 | { offsetof(struct pkg_meta, meta_preserve), PRESERVE_FNAME, 0, 0444 }, |
124 | { offsetof(struct pkg_meta, meta_required_by), REQUIRED_BY_FNAME, 0, 0644 }, | | 124 | { offsetof(struct pkg_meta, meta_required_by), REQUIRED_BY_FNAME, 0, 0644 }, |
125 | { offsetof(struct pkg_meta, meta_installed_info), INSTALLED_INFO_FNAME, 0, 0644 }, | | 125 | { offsetof(struct pkg_meta, meta_installed_info), INSTALLED_INFO_FNAME, 0, 0644 }, |
126 | { 0, NULL, 0, 0 }, | | 126 | { 0, NULL, 0, 0 }, |
127 | }; | | 127 | }; |
128 | | | 128 | |
129 | static int pkg_do(const char *, int, int); | | 129 | static int pkg_do(const char *, int, int); |
130 | | | 130 | |
131 | static int | | 131 | static int |
132 | end_of_version(const char *opsys, const char *version_end) | | 132 | end_of_version(const char *opsys, const char *version_end) |
133 | { | | 133 | { |
134 | if (*version_end == '\0') | | 134 | if (*version_end == '\0') |
135 | return 1; | | 135 | return 1; |
136 | | | 136 | |
137 | if (strcmp(opsys, "NetBSD") == 0) { | | 137 | if (strcmp(opsys, "NetBSD") == 0) { |
138 | if (strncmp(version_end, "_ALPHA", 6) == 0 | | 138 | if (strncmp(version_end, "_ALPHA", 6) == 0 |
139 | || strncmp(version_end, "_BETA", 5) == 0 | | 139 | || strncmp(version_end, "_BETA", 5) == 0 |
140 | || strncmp(version_end, "_RC", 3) == 0 | | 140 | || strncmp(version_end, "_RC", 3) == 0 |
141 | || strncmp(version_end, "_STABLE", 7) == 0 | | 141 | || strncmp(version_end, "_STABLE", 7) == 0 |
142 | || strncmp(version_end, "_PATCH", 6) == 0) | | 142 | || strncmp(version_end, "_PATCH", 6) == 0) |
143 | return 1; | | 143 | return 1; |
144 | } | | 144 | } |
145 | | | 145 | |
146 | return 0; | | 146 | return 0; |
147 | } | | 147 | } |
148 | | | 148 | |
149 | static int | | 149 | static int |
150 | compatible_platform(const char *opsys, const char *host, const char *package) | | 150 | compatible_platform(const char *opsys, const char *host, const char *package) |
151 | { | | 151 | { |
152 | int i = 0; | | 152 | int i = 0; |
153 | | | 153 | |
154 | /* | | 154 | /* |
155 | * If the user has set the CHECK_OS_VERSION variable to "no" then skip any | | 155 | * If the user has set the CHECK_OS_VERSION variable to "no" then skip any |
156 | * uname version checks and assume they know what they are doing. This can | | 156 | * uname version checks and assume they know what they are doing. This can |
157 | * be useful on OS where the kernel version is not a good indicator of | | 157 | * be useful on OS where the kernel version is not a good indicator of |
158 | * userland compatibility, or differs but retains ABI compatibility. | | 158 | * userland compatibility, or differs but retains ABI compatibility. |
159 | */ | | 159 | */ |
160 | if (strcasecmp(check_os_version, "no") == 0) | | 160 | if (strcasecmp(check_os_version, "no") == 0) |
161 | return 1; | | 161 | return 1; |
162 | | | 162 | |
163 | /* returns 1 if host and package operating system match */ | | 163 | /* returns 1 if host and package operating system match */ |
164 | if (strcmp(host, package) == 0) | | 164 | if (strcmp(host, package) == 0) |
165 | return 1; | | 165 | return 1; |
166 | | | 166 | |
167 | /* accept, if host version is a minor release of package version */ | | 167 | /* accept, if host version is a minor release of package version */ |
168 | if (strncmp(host, package, strlen(package)) == 0) | | 168 | if (strncmp(host, package, strlen(package)) == 0) |
169 | return 1; | | 169 | return 1; |
170 | | | 170 | |
171 | /* find offset of first difference */ | | 171 | /* find offset of first difference */ |
172 | for (i=0; (host[i] != '\0') && (host[i] == package[i]);) | | 172 | for (i=0; (host[i] != '\0') && (host[i] == package[i]);) |
173 | i++; | | 173 | i++; |
174 | | | 174 | |
175 | if (end_of_version(opsys, host+i) && end_of_version(opsys, package+i)) | | 175 | if (end_of_version(opsys, host+i) && end_of_version(opsys, package+i)) |
176 | return 1; | | 176 | return 1; |
177 | | | 177 | |
178 | return 0; | | 178 | return 0; |
179 | } | | 179 | } |
180 | | | 180 | |
181 | static int | | 181 | static int |
182 | mkdir_p(const char *path) | | 182 | mkdir_p(const char *path) |
183 | { | | 183 | { |
184 | char *p, *cur_end; | | 184 | char *p, *cur_end; |
185 | int done, saved_errno; | | 185 | int done, saved_errno; |
186 | struct stat sb; | | 186 | struct stat sb; |
187 | | | 187 | |
188 | /* | | 188 | /* |
189 | * Handle the easy case of direct success or | | 189 | * Handle the easy case of direct success or |
190 | * pre-existing directory first. | | 190 | * pre-existing directory first. |
191 | */ | | 191 | */ |
192 | if (mkdir(path, 0777) == 0) | | 192 | if (mkdir(path, 0777) == 0) |
193 | return 0; | | 193 | return 0; |
194 | if (stat(path, &sb) == 0) { | | 194 | if (stat(path, &sb) == 0) { |
195 | if (S_ISDIR(sb.st_mode)) | | 195 | if (S_ISDIR(sb.st_mode)) |
196 | return 0; | | 196 | return 0; |
197 | errno = ENOTDIR; | | 197 | errno = ENOTDIR; |
198 | return -1; | | 198 | return -1; |
199 | } | | 199 | } |
200 | | | 200 | |
201 | cur_end = p = xstrdup(path); | | 201 | cur_end = p = xstrdup(path); |
202 | | | 202 | |
203 | for (;;) { | | 203 | for (;;) { |
204 | /* | | 204 | /* |
205 | * First skip leading slashes either from / or | | 205 | * First skip leading slashes either from / or |
206 | * from the last iteration. | | 206 | * from the last iteration. |
207 | */ | | 207 | */ |
208 | cur_end += strspn(cur_end, "/"); | | 208 | cur_end += strspn(cur_end, "/"); |
209 | /* Find end of actual directory name. */ | | 209 | /* Find end of actual directory name. */ |
210 | cur_end += strcspn(cur_end, "/"); | | 210 | cur_end += strcspn(cur_end, "/"); |
211 | | | 211 | |
212 | /* | | 212 | /* |
213 | * Remember if this is the last component and | | 213 | * Remember if this is the last component and |
214 | * overwrite / if needed. | | 214 | * overwrite / if needed. |
215 | */ | | 215 | */ |
216 | done = (*cur_end == '\0'); | | 216 | done = (*cur_end == '\0'); |
217 | *cur_end = '\0'; | | 217 | *cur_end = '\0'; |
218 | | | 218 | |
219 | if (mkdir(p, 0777) == -1) { | | 219 | if (mkdir(p, 0777) == -1) { |
220 | saved_errno = errno; | | 220 | saved_errno = errno; |
221 | if (stat(p, &sb) == 0) { | | 221 | if (stat(p, &sb) == 0) { |
222 | if (S_ISDIR(sb.st_mode)) | | 222 | if (S_ISDIR(sb.st_mode)) |
223 | goto pass; | | 223 | goto pass; |
224 | errno = ENOTDIR; | | 224 | errno = ENOTDIR; |
225 | } else { | | 225 | } else { |
226 | errno = saved_errno; | | 226 | errno = saved_errno; |
227 | } | | 227 | } |
228 | free(p); | | 228 | free(p); |
229 | return -1; | | 229 | return -1; |
230 | } | | 230 | } |
231 | pass: | | 231 | pass: |
232 | if (done) | | 232 | if (done) |
233 | break; | | 233 | break; |
234 | *cur_end = '/'; | | 234 | *cur_end = '/'; |
235 | } | | 235 | } |
236 | | | 236 | |
237 | free(p); | | 237 | free(p); |
238 | return 0; | | 238 | return 0; |
239 | } | | 239 | } |
240 | | | 240 | |
241 | /* | | 241 | /* |
242 | * Read meta data from archive. | | 242 | * Read meta data from archive. |
243 | * Bail out if a required entry is missing or entries are in the wrong order. | | 243 | * Bail out if a required entry is missing or entries are in the wrong order. |
244 | */ | | 244 | */ |
245 | static int | | 245 | static int |
246 | read_meta_data(struct pkg_task *pkg) | | 246 | read_meta_data(struct pkg_task *pkg) |
247 | { | | 247 | { |
248 | const struct pkg_meta_desc *descr, *last_descr; | | 248 | const struct pkg_meta_desc *descr, *last_descr; |
249 | const char *fname; | | 249 | const char *fname; |
250 | char **target; | | 250 | char **target; |
251 | int64_t size; | | 251 | int64_t size; |
252 | int r, found_required; | | 252 | int r, found_required; |
253 | | | 253 | |
254 | found_required = 0; | | 254 | found_required = 0; |
255 | | | 255 | |
256 | r = ARCHIVE_OK; | | 256 | r = ARCHIVE_OK; |
257 | last_descr = 0; | | 257 | last_descr = 0; |
258 | | | 258 | |
259 | if (pkg->entry != NULL) | | 259 | if (pkg->entry != NULL) |
260 | goto skip_header; | | 260 | goto skip_header; |
261 | | | 261 | |
262 | for (;;) { | | 262 | for (;;) { |
263 | r = archive_read_next_header(pkg->archive, &pkg->entry); | | 263 | r = archive_read_next_header(pkg->archive, &pkg->entry); |
264 | if (r != ARCHIVE_OK) | | 264 | if (r != ARCHIVE_OK) |
265 | break; | | 265 | break; |
266 | skip_header: | | 266 | skip_header: |
267 | fname = archive_entry_pathname(pkg->entry); | | 267 | fname = archive_entry_pathname(pkg->entry); |
268 | | | 268 | |
269 | for (descr = pkg_meta_descriptors; descr->entry_filename; | | 269 | for (descr = pkg_meta_descriptors; descr->entry_filename; |
270 | ++descr) { | | 270 | ++descr) { |
271 | if (strcmp(descr->entry_filename, fname) == 0) | | 271 | if (strcmp(descr->entry_filename, fname) == 0) |
272 | break; | | 272 | break; |
273 | } | | 273 | } |
274 | if (descr->entry_filename == NULL) | | 274 | if (descr->entry_filename == NULL) |
275 | break; | | 275 | break; |
276 | | | 276 | |
277 | if (descr->required_file) | | 277 | if (descr->required_file) |
278 | ++found_required; | | 278 | ++found_required; |
279 | | | 279 | |
280 | target = (char **)((char *)&pkg->meta_data + | | 280 | target = (char **)((char *)&pkg->meta_data + |
281 | descr->entry_offset); | | 281 | descr->entry_offset); |
282 | if (*target) { | | 282 | if (*target) { |
283 | warnx("duplicate entry, package corrupt"); | | 283 | warnx("duplicate entry, package corrupt"); |
284 | return -1; | | 284 | return -1; |
285 | } | | 285 | } |
286 | if (descr < last_descr) { | | 286 | if (descr < last_descr) { |
287 | warnx("misordered package"); | | 287 | warnx("misordered package"); |
288 | return -1; | | 288 | return -1; |
289 | } | | 289 | } |
290 | last_descr = descr; | | 290 | last_descr = descr; |
291 | | | 291 | |
292 | size = archive_entry_size(pkg->entry); | | 292 | size = archive_entry_size(pkg->entry); |
293 | if (size > SSIZE_MAX - 1) { | | 293 | if (size > SSIZE_MAX - 1) { |
294 | warnx("package meta data too large to process"); | | 294 | warnx("package meta data too large to process"); |
295 | return -1; | | 295 | return -1; |
296 | } | | 296 | } |
297 | *target = xmalloc(size + 1); | | 297 | *target = xmalloc(size + 1); |
298 | if (archive_read_data(pkg->archive, *target, size) != size) { | | 298 | if (archive_read_data(pkg->archive, *target, size) != size) { |
299 | warnx("cannot read package meta data"); | | 299 | warnx("cannot read package meta data"); |
300 | return -1; | | 300 | return -1; |
301 | } | | 301 | } |
302 | (*target)[size] = '\0'; | | 302 | (*target)[size] = '\0'; |
303 | } | | 303 | } |
304 | | | 304 | |
305 | if (r != ARCHIVE_OK) | | 305 | if (r != ARCHIVE_OK) |
306 | pkg->entry = NULL; | | 306 | pkg->entry = NULL; |
307 | if (r == ARCHIVE_EOF) | | 307 | if (r == ARCHIVE_EOF) |
308 | r = ARCHIVE_OK; | | 308 | r = ARCHIVE_OK; |
309 | | | 309 | |
310 | for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { | | 310 | for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { |
311 | if (descr->required_file) | | 311 | if (descr->required_file) |
312 | --found_required; | | 312 | --found_required; |
313 | } | | 313 | } |
314 | | | 314 | |
315 | return !found_required && r == ARCHIVE_OK ? 0 : -1; | | 315 | return !found_required && r == ARCHIVE_OK ? 0 : -1; |
316 | } | | 316 | } |
317 | | | 317 | |
318 | /* | | 318 | /* |
319 | * Free meta data. | | 319 | * Free meta data. |
320 | */ | | 320 | */ |
321 | static void | | 321 | static void |
322 | free_meta_data(struct pkg_task *pkg) | | 322 | free_meta_data(struct pkg_task *pkg) |
323 | { | | 323 | { |
324 | const struct pkg_meta_desc *descr; | | 324 | const struct pkg_meta_desc *descr; |
325 | char **target; | | 325 | char **target; |
326 | | | 326 | |
327 | for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { | | 327 | for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { |
328 | target = (char **)((char *)&pkg->meta_data + | | 328 | target = (char **)((char *)&pkg->meta_data + |
329 | descr->entry_offset); | | 329 | descr->entry_offset); |
330 | free(*target); | | 330 | free(*target); |
331 | *target = NULL; | | 331 | *target = NULL; |
332 | } | | 332 | } |
333 | } | | 333 | } |
334 | | | 334 | |
335 | /* | | 335 | /* |
336 | * Parse PLIST and populate pkg. | | 336 | * Parse PLIST and populate pkg. |
337 | */ | | 337 | */ |
338 | static int | | 338 | static int |
339 | pkg_parse_plist(struct pkg_task *pkg) | | 339 | pkg_parse_plist(struct pkg_task *pkg) |
340 | { | | 340 | { |
341 | plist_t *p; | | 341 | plist_t *p; |
342 | | | 342 | |
343 | parse_plist(&pkg->plist, pkg->meta_data.meta_contents); | | 343 | parse_plist(&pkg->plist, pkg->meta_data.meta_contents); |
344 | if ((p = find_plist(&pkg->plist, PLIST_NAME)) == NULL) { | | 344 | if ((p = find_plist(&pkg->plist, PLIST_NAME)) == NULL) { |
345 | warnx("Invalid PLIST: missing @name"); | | 345 | warnx("Invalid PLIST: missing @name"); |
346 | return -1; | | 346 | return -1; |
347 | } | | 347 | } |
348 | if (pkg->pkgname == NULL) | | 348 | if (pkg->pkgname == NULL) |
349 | pkg->pkgname = xstrdup(p->name); | | 349 | pkg->pkgname = xstrdup(p->name); |
350 | else if (strcmp(pkg->pkgname, p->name) != 0) { | | 350 | else if (strcmp(pkg->pkgname, p->name) != 0) { |
351 | warnx("Signature and PLIST differ on package name"); | | 351 | warnx("Signature and PLIST differ on package name"); |
352 | return -1; | | 352 | return -1; |
353 | } | | 353 | } |
354 | if ((p = find_plist(&pkg->plist, PLIST_CWD)) == NULL) { | | 354 | if ((p = find_plist(&pkg->plist, PLIST_CWD)) == NULL) { |
355 | warnx("Invalid PLIST: missing @cwd"); | | 355 | warnx("Invalid PLIST: missing @cwd"); |
356 | return -1; | | 356 | return -1; |
357 | } | | 357 | } |
358 | | | 358 | |
359 | if (Prefix != NULL && | | 359 | if (Prefix != NULL && |
360 | strcmp(p->name, Prefix) != 0) { | | 360 | strcmp(p->name, Prefix) != 0) { |
361 | size_t len; | | 361 | size_t len; |
362 | | | 362 | |
363 | delete_plist(&pkg->plist, FALSE, PLIST_CWD, NULL); | | 363 | delete_plist(&pkg->plist, FALSE, PLIST_CWD, NULL); |
364 | add_plist_top(&pkg->plist, PLIST_CWD, Prefix); | | 364 | add_plist_top(&pkg->plist, PLIST_CWD, Prefix); |
365 | free(pkg->meta_data.meta_contents); | | 365 | free(pkg->meta_data.meta_contents); |
366 | stringify_plist(&pkg->plist, &pkg->meta_data.meta_contents, &len, | | 366 | stringify_plist(&pkg->plist, &pkg->meta_data.meta_contents, &len, |
367 | Prefix); | | 367 | Prefix); |
368 | pkg->prefix = Prefix; | | 368 | pkg->prefix = Prefix; |
369 | } else | | 369 | } else |
370 | pkg->prefix = p->name; | | 370 | pkg->prefix = p->name; |
371 | | | 371 | |
372 | if (Destdir != NULL) | | 372 | if (Destdir != NULL) |
373 | pkg->install_prefix = xasprintf("%s/%s", Destdir, pkg->prefix); | | 373 | pkg->install_prefix = xasprintf("%s/%s", Destdir, pkg->prefix); |
374 | else | | 374 | else |
375 | pkg->install_prefix = xstrdup(pkg->prefix); | | 375 | pkg->install_prefix = xstrdup(pkg->prefix); |
376 | | | 376 | |
377 | return 0; | | 377 | return 0; |
378 | } | | 378 | } |
379 | | | 379 | |
380 | /* | | 380 | /* |
381 | * Helper function to extract value from a string of the | | 381 | * Helper function to extract value from a string of the |
382 | * form key=value ending at eol. | | 382 | * form key=value ending at eol. |
383 | */ | | 383 | */ |
384 | static char * | | 384 | static char * |
385 | dup_value(const char *line, const char *eol) | | 385 | dup_value(const char *line, const char *eol) |
386 | { | | 386 | { |
387 | const char *key; | | 387 | const char *key; |
388 | char *val; | | 388 | char *val; |
389 | | | 389 | |
390 | key = strchr(line, '='); | | 390 | key = strchr(line, '='); |
391 | val = xmalloc(eol - key); | | 391 | val = xmalloc(eol - key); |
392 | memcpy(val, key + 1, eol - key - 1); | | 392 | memcpy(val, key + 1, eol - key - 1); |
393 | val[eol - key - 1] = '\0'; | | 393 | val[eol - key - 1] = '\0'; |
394 | return val; | | 394 | return val; |
395 | } | | 395 | } |
396 | | | 396 | |
397 | static int | | 397 | static int |
398 | check_already_installed(struct pkg_task *pkg) | | 398 | check_already_installed(struct pkg_task *pkg) |
399 | { | | 399 | { |
400 | char *filename; | | 400 | char *filename; |
401 | int fd; | | 401 | int fd; |
402 | | | 402 | |
403 | filename = pkgdb_pkg_file(pkg->pkgname, CONTENTS_FNAME); | | 403 | filename = pkgdb_pkg_file(pkg->pkgname, CONTENTS_FNAME); |
404 | fd = open(filename, O_RDONLY); | | 404 | fd = open(filename, O_RDONLY); |
405 | free(filename); | | 405 | free(filename); |
406 | if (fd == -1) | | 406 | if (fd == -1) |
407 | return 1; | | 407 | return 1; |
408 | close(fd); | | 408 | close(fd); |
409 | | | 409 | |
410 | if (ReplaceSame) { | | 410 | if (ReplaceSame) { |
411 | struct stat sb; | | 411 | struct stat sb; |
412 | | | 412 | |
413 | pkg->install_logdir_real = pkg->install_logdir; | | 413 | pkg->install_logdir_real = pkg->install_logdir; |
414 | pkg->install_logdir = xasprintf("%s.xxxxxx", pkg->install_logdir); | | 414 | pkg->install_logdir = xasprintf("%s.xxxxxx", pkg->install_logdir); |
415 | if (stat(pkg->install_logdir, &sb) == 0) { | | 415 | if (stat(pkg->install_logdir, &sb) == 0) { |
416 | warnx("package `%s' already has a temporary update " | | 416 | warnx("package `%s' already has a temporary update " |
417 | "directory `%s', remove it manually", | | 417 | "directory `%s', remove it manually", |
418 | pkg->pkgname, pkg->install_logdir); | | 418 | pkg->pkgname, pkg->install_logdir); |
419 | return -1; | | 419 | return -1; |
420 | } | | 420 | } |
421 | return 1; | | 421 | return 1; |
422 | } | | 422 | } |
423 | | | 423 | |
424 | /* We can only arrive here for explicitly requested packages. */ | | 424 | /* We can only arrive here for explicitly requested packages. */ |
425 | if (!Automatic && is_automatic_installed(pkg->pkgname)) { | | 425 | if (!Automatic && is_automatic_installed(pkg->pkgname)) { |
426 | if (Fake || | | 426 | if (Fake || |
427 | mark_as_automatic_installed(pkg->pkgname, 0) == 0) | | 427 | mark_as_automatic_installed(pkg->pkgname, 0) == 0) |
428 | warnx("package `%s' was already installed as " | | 428 | warnx("package `%s' was already installed as " |
429 | "dependency, now marked as installed " | | 429 | "dependency, now marked as installed " |
430 | "manually", pkg->pkgname); | | 430 | "manually", pkg->pkgname); |
431 | } else { | | 431 | } else { |
432 | warnx("package `%s' already recorded as installed", | | 432 | warnx("package `%s' already recorded as installed", |
433 | pkg->pkgname); | | 433 | pkg->pkgname); |
434 | } | | 434 | } |
435 | return 0; | | 435 | return 0; |
436 | | | 436 | |
437 | } | | 437 | } |
438 | | | 438 | |
439 | static int | | 439 | static int |
440 | check_other_installed(struct pkg_task *pkg) | | 440 | check_other_installed(struct pkg_task *pkg) |
441 | { | | 441 | { |
442 | FILE *f, *f_pkg; | | 442 | FILE *f, *f_pkg; |
443 | size_t len; | | 443 | size_t len; |
444 | char *pkgbase, *iter, *filename; | | 444 | char *pkgbase, *iter, *filename; |
445 | package_t plist; | | 445 | package_t plist; |
446 | plist_t *p; | | 446 | plist_t *p; |
447 | int status; | | 447 | int status; |
448 | | | 448 | |
449 | if (pkg->install_logdir_real) { | | 449 | if (pkg->install_logdir_real) { |
450 | pkg->other_version = xstrdup(pkg->pkgname); | | 450 | pkg->other_version = xstrdup(pkg->pkgname); |
451 | return 0; | | 451 | return 0; |
452 | } | | 452 | } |
453 | | | 453 | |
454 | pkgbase = xstrdup(pkg->pkgname); | | 454 | pkgbase = xstrdup(pkg->pkgname); |
455 | | | 455 | |
456 | if ((iter = strrchr(pkgbase, '-')) == NULL) { | | 456 | if ((iter = strrchr(pkgbase, '-')) == NULL) { |
457 | free(pkgbase); | | 457 | free(pkgbase); |
458 | warnx("Invalid package name %s", pkg->pkgname); | | 458 | warnx("Invalid package name %s", pkg->pkgname); |
459 | return -1; | | 459 | return -1; |
460 | } | | 460 | } |
461 | *iter = '\0'; | | 461 | *iter = '\0'; |
462 | pkg->other_version = find_best_matching_installed_pkg(pkgbase, 0); | | 462 | pkg->other_version = find_best_matching_installed_pkg(pkgbase, 0); |
463 | free(pkgbase); | | 463 | free(pkgbase); |
464 | if (pkg->other_version == NULL) | | 464 | if (pkg->other_version == NULL) |
465 | return 0; | | 465 | return 0; |
466 | | | 466 | |
467 | if (!Replace) { | | 467 | if (!Replace) { |
468 | /* XXX This is redundant to the implicit conflict check. */ | | 468 | /* XXX This is redundant to the implicit conflict check. */ |
469 | warnx("A different version of %s is already installed: %s", | | 469 | warnx("A different version of %s is already installed: %s", |
470 | pkg->pkgname, pkg->other_version); | | 470 | pkg->pkgname, pkg->other_version); |
471 | return -1; | | 471 | return -1; |
472 | } | | 472 | } |
473 | | | 473 | |
474 | filename = pkgdb_pkg_file(pkg->other_version, REQUIRED_BY_FNAME); | | 474 | filename = pkgdb_pkg_file(pkg->other_version, REQUIRED_BY_FNAME); |
475 | errno = 0; | | 475 | errno = 0; |
476 | f = fopen(filename, "r"); | | 476 | f = fopen(filename, "r"); |
477 | free(filename); | | 477 | free(filename); |
478 | if (f == NULL) { | | 478 | if (f == NULL) { |
479 | if (errno == ENOENT) { | | 479 | if (errno == ENOENT) { |
480 | /* No packages depend on this, so everything is well. */ | | 480 | /* No packages depend on this, so everything is well. */ |
481 | return 0; | | 481 | return 0; |
482 | } | | 482 | } |
483 | warnx("Can't open +REQUIRED_BY of %s", pkg->other_version); | | 483 | warnx("Can't open +REQUIRED_BY of %s", pkg->other_version); |
484 | return -1; | | 484 | return -1; |
485 | } | | 485 | } |
486 | | | 486 | |
487 | status = 0; | | 487 | status = 0; |
488 | | | 488 | |
489 | while ((iter = fgetln(f, &len)) != NULL) { | | 489 | while ((iter = fgetln(f, &len)) != NULL) { |
490 | if (iter[len - 1] == '\n') | | 490 | if (iter[len - 1] == '\n') |
491 | iter[len - 1] = '\0'; | | 491 | iter[len - 1] = '\0'; |
492 | filename = pkgdb_pkg_file(iter, CONTENTS_FNAME); | | 492 | filename = pkgdb_pkg_file(iter, CONTENTS_FNAME); |
493 | if ((f_pkg = fopen(filename, "r")) == NULL) { | | 493 | if ((f_pkg = fopen(filename, "r")) == NULL) { |
494 | warnx("Can't open +CONTENTS of depending package %s", | | 494 | warnx("Can't open +CONTENTS of depending package %s", |
495 | iter); | | 495 | iter); |
496 | fclose(f); | | 496 | fclose(f); |
497 | return -1; | | 497 | return -1; |
498 | } | | 498 | } |
499 | read_plist(&plist, f_pkg); | | 499 | read_plist(&plist, f_pkg); |
500 | fclose(f_pkg); | | 500 | fclose(f_pkg); |
501 | for (p = plist.head; p != NULL; p = p->next) { | | 501 | for (p = plist.head; p != NULL; p = p->next) { |
502 | if (p->type == PLIST_IGNORE) { | | 502 | if (p->type == PLIST_IGNORE) { |
503 | p = p->next; | | 503 | p = p->next; |
504 | continue; | | 504 | continue; |
505 | } else if (p->type != PLIST_PKGDEP) | | 505 | } else if (p->type != PLIST_PKGDEP) |
506 | continue; | | 506 | continue; |
507 | /* | | 507 | /* |
508 | * XXX This is stricter than necessary. | | 508 | * XXX This is stricter than necessary. |
509 | * XXX One pattern might be fulfilled by | | 509 | * XXX One pattern might be fulfilled by |
510 | * XXX a different package and still need this | | 510 | * XXX a different package and still need this |
511 | * XXX one for a different pattern. | | 511 | * XXX one for a different pattern. |
512 | */ | | 512 | */ |
513 | if (pkg_match(p->name, pkg->other_version) == 0) | | 513 | if (pkg_match(p->name, pkg->other_version) == 0) |
514 | continue; | | 514 | continue; |
515 | if (pkg_match(p->name, pkg->pkgname) == 1) | | 515 | if (pkg_match(p->name, pkg->pkgname) == 1) |
516 | continue; /* Both match, ok. */ | | 516 | continue; /* Both match, ok. */ |
517 | if (!ForceDepending) { | | 517 | if (!ForceDepending) { |
518 | warnx("Dependency of %s fulfilled by %s, " | | 518 | warnx("Dependency of %s fulfilled by %s, " |
519 | "but not by %s", iter, pkg->other_version, | | 519 | "but not by %s", iter, pkg->other_version, |
520 | pkg->pkgname); | | 520 | pkg->pkgname); |
521 | status = -1; | | 521 | status = -1; |
522 | } | | 522 | } |
523 | break; | | 523 | break; |
524 | } | | 524 | } |
525 | free_plist(&plist); | | 525 | free_plist(&plist); |
526 | } | | 526 | } |
527 | | | 527 | |
528 | fclose(f); | | 528 | fclose(f); |
529 | | | 529 | |
530 | return status; | | 530 | return status; |
531 | } | | 531 | } |
532 | | | 532 | |
533 | /* | | 533 | /* |
534 | * Read package build information from meta data. | | 534 | * Read package build information from meta data. |
535 | */ | | 535 | */ |
536 | static int | | 536 | static int |
537 | read_buildinfo(struct pkg_task *pkg) | | 537 | read_buildinfo(struct pkg_task *pkg) |
538 | { | | 538 | { |
539 | const char *data, *eol, *next_line; | | 539 | const char *data, *eol, *next_line; |
540 | | | 540 | |
541 | data = pkg->meta_data.meta_build_info; | | 541 | data = pkg->meta_data.meta_build_info; |
542 | | | 542 | |
543 | for (; data != NULL && *data != '\0'; data = next_line) { | | 543 | for (; data != NULL && *data != '\0'; data = next_line) { |
544 | if ((eol = strchr(data, '\n')) == NULL) { | | 544 | if ((eol = strchr(data, '\n')) == NULL) { |
545 | eol = data + strlen(data); | | 545 | eol = data + strlen(data); |
546 | next_line = eol; | | 546 | next_line = eol; |
547 | } else | | 547 | } else |
548 | next_line = eol + 1; | | 548 | next_line = eol + 1; |
549 | | | 549 | |
550 | if (strncmp(data, "OPSYS=", 6) == 0) | | 550 | if (strncmp(data, "OPSYS=", 6) == 0) |
551 | pkg->buildinfo[BI_OPSYS] = dup_value(data, eol); | | 551 | pkg->buildinfo[BI_OPSYS] = dup_value(data, eol); |
552 | else if (strncmp(data, "OS_VERSION=", 11) == 0) | | 552 | else if (strncmp(data, "OS_VERSION=", 11) == 0) |
553 | pkg->buildinfo[BI_OS_VERSION] = dup_value(data, eol); | | 553 | pkg->buildinfo[BI_OS_VERSION] = dup_value(data, eol); |
554 | else if (strncmp(data, "MACHINE_ARCH=", 13) == 0) | | 554 | else if (strncmp(data, "MACHINE_ARCH=", 13) == 0) |
555 | pkg->buildinfo[BI_MACHINE_ARCH] = dup_value(data, eol); | | 555 | pkg->buildinfo[BI_MACHINE_ARCH] = dup_value(data, eol); |
556 | else if (strncmp(data, "IGNORE_RECOMMENDED=", 19) == 0) | | 556 | else if (strncmp(data, "IGNORE_RECOMMENDED=", 19) == 0) |
557 | pkg->buildinfo[BI_IGNORE_RECOMMENDED] = dup_value(data, | | 557 | pkg->buildinfo[BI_IGNORE_RECOMMENDED] = dup_value(data, |
558 | eol); | | 558 | eol); |
559 | else if (strncmp(data, "USE_ABI_DEPENDS=", 16) == 0) | | 559 | else if (strncmp(data, "USE_ABI_DEPENDS=", 16) == 0) |
560 | pkg->buildinfo[BI_USE_ABI_DEPENDS] = dup_value(data, | | 560 | pkg->buildinfo[BI_USE_ABI_DEPENDS] = dup_value(data, |
561 | eol); | | 561 | eol); |
562 | else if (strncmp(data, "LICENSE=", 8) == 0) | | 562 | else if (strncmp(data, "LICENSE=", 8) == 0) |
563 | pkg->buildinfo[BI_LICENSE] = dup_value(data, eol); | | 563 | pkg->buildinfo[BI_LICENSE] = dup_value(data, eol); |
564 | else if (strncmp(data, "PKGTOOLS_VERSION=", 17) == 0) | | 564 | else if (strncmp(data, "PKGTOOLS_VERSION=", 17) == 0) |
565 | pkg->buildinfo[BI_PKGTOOLS_VERSION] = dup_value(data, | | 565 | pkg->buildinfo[BI_PKGTOOLS_VERSION] = dup_value(data, |
566 | eol); | | 566 | eol); |
567 | } | | 567 | } |
568 | if (pkg->buildinfo[BI_OPSYS] == NULL || | | 568 | if (pkg->buildinfo[BI_OPSYS] == NULL || |
569 | pkg->buildinfo[BI_OS_VERSION] == NULL || | | 569 | pkg->buildinfo[BI_OS_VERSION] == NULL || |
570 | pkg->buildinfo[BI_MACHINE_ARCH] == NULL) { | | 570 | pkg->buildinfo[BI_MACHINE_ARCH] == NULL) { |
571 | warnx("Not all required build information are present."); | | 571 | warnx("Not all required build information are present."); |
572 | return -1; | | 572 | return -1; |
573 | } | | 573 | } |
574 | | | 574 | |
575 | if ((pkg->buildinfo[BI_USE_ABI_DEPENDS] != NULL && | | 575 | if ((pkg->buildinfo[BI_USE_ABI_DEPENDS] != NULL && |
576 | strcasecmp(pkg->buildinfo[BI_USE_ABI_DEPENDS], "YES") != 0) || | | 576 | strcasecmp(pkg->buildinfo[BI_USE_ABI_DEPENDS], "YES") != 0) || |
577 | (pkg->buildinfo[BI_IGNORE_RECOMMENDED] != NULL && | | 577 | (pkg->buildinfo[BI_IGNORE_RECOMMENDED] != NULL && |
578 | strcasecmp(pkg->buildinfo[BI_IGNORE_RECOMMENDED], "NO") != 0)) { | | 578 | strcasecmp(pkg->buildinfo[BI_IGNORE_RECOMMENDED], "NO") != 0)) { |
579 | warnx("%s was built to ignore ABI dependencies", pkg->pkgname); | | 579 | warnx("%s was built to ignore ABI dependencies", pkg->pkgname); |
580 | } | | 580 | } |
581 | | | 581 | |
582 | return 0; | | 582 | return 0; |
583 | } | | 583 | } |
584 | | | 584 | |
585 | /* | | 585 | /* |
586 | * Free buildinfo. | | 586 | * Free buildinfo. |
587 | */ | | 587 | */ |
588 | static void | | 588 | static void |
589 | free_buildinfo(struct pkg_task *pkg) | | 589 | free_buildinfo(struct pkg_task *pkg) |
590 | { | | 590 | { |
591 | size_t i; | | 591 | size_t i; |
592 | | | 592 | |
593 | for (i = 0; i < BI_ENUM_COUNT; ++i) { | | 593 | for (i = 0; i < BI_ENUM_COUNT; ++i) { |
594 | free(pkg->buildinfo[i]); | | 594 | free(pkg->buildinfo[i]); |
595 | pkg->buildinfo[i] = NULL; | | 595 | pkg->buildinfo[i] = NULL; |
596 | } | | 596 | } |
597 | } | | 597 | } |
598 | | | 598 | |
599 | /* | | 599 | /* |
600 | * Write meta data files to pkgdb after creating the directory. | | 600 | * Write meta data files to pkgdb after creating the directory. |
601 | */ | | 601 | */ |
602 | static int | | 602 | static int |
603 | write_meta_data(struct pkg_task *pkg) | | 603 | write_meta_data(struct pkg_task *pkg) |
604 | { | | 604 | { |
605 | const struct pkg_meta_desc *descr; | | 605 | const struct pkg_meta_desc *descr; |
606 | char *filename, **target; | | 606 | char *filename, **target; |
607 | size_t len; | | 607 | size_t len; |
608 | ssize_t ret; | | 608 | ssize_t ret; |
609 | int fd; | | 609 | int fd; |
610 | | | 610 | |
611 | if (Fake) | | 611 | if (Fake) |
612 | return 0; | | 612 | return 0; |
613 | | | 613 | |
614 | if (mkdir_p(pkg->install_logdir)) { | | 614 | if (mkdir_p(pkg->install_logdir)) { |
615 | warn("Can't create pkgdb entry: %s", pkg->install_logdir); | | 615 | warn("Can't create pkgdb entry: %s", pkg->install_logdir); |
616 | return -1; | | 616 | return -1; |
617 | } | | 617 | } |
618 | | | 618 | |
619 | for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { | | 619 | for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { |
620 | target = (char **)((char *)&pkg->meta_data + | | 620 | target = (char **)((char *)&pkg->meta_data + |
621 | descr->entry_offset); | | 621 | descr->entry_offset); |
622 | if (*target == NULL) | | 622 | if (*target == NULL) |
623 | continue; | | 623 | continue; |
624 | filename = xasprintf("%s/%s", pkg->install_logdir, | | 624 | filename = xasprintf("%s/%s", pkg->install_logdir, |
625 | descr->entry_filename); | | 625 | descr->entry_filename); |
626 | (void)unlink(filename); | | 626 | (void)unlink(filename); |
627 | fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, descr->perm); | | 627 | fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, descr->perm); |
628 | if (fd == -1) { | | 628 | if (fd == -1) { |
629 | warn("Can't open meta data file: %s", filename); | | 629 | warn("Can't open meta data file: %s", filename); |
630 | return -1; | | 630 | return -1; |
631 | } | | 631 | } |
632 | len = strlen(*target); | | 632 | len = strlen(*target); |
633 | do { | | 633 | do { |
634 | ret = write(fd, *target, len); | | 634 | ret = write(fd, *target, len); |
635 | if (ret == -1) { | | 635 | if (ret == -1) { |
636 | warn("Can't write meta data file: %s", | | 636 | warn("Can't write meta data file: %s", |
637 | filename); | | 637 | filename); |
638 | free(filename); | | 638 | free(filename); |
639 | close(fd); | | 639 | close(fd); |
640 | return -1; | | 640 | return -1; |
641 | } | | 641 | } |
642 | len -= ret; | | 642 | len -= ret; |
643 | } while (ret > 0); | | 643 | } while (ret > 0); |
644 | if (close(fd) == -1) { | | 644 | if (close(fd) == -1) { |
645 | warn("Can't close meta data file: %s", filename); | | 645 | warn("Can't close meta data file: %s", filename); |
646 | free(filename); | | 646 | free(filename); |
647 | return -1; | | 647 | return -1; |
648 | } | | 648 | } |
649 | free(filename); | | 649 | free(filename); |
650 | } | | 650 | } |
651 | | | 651 | |
652 | return 0; | | 652 | return 0; |
653 | } | | 653 | } |
654 | | | 654 | |
655 | /* | | 655 | /* |
656 | * Helper function for extract_files. | | 656 | * Helper function for extract_files. |
657 | */ | | 657 | */ |
658 | static int | | 658 | static int |
659 | copy_data_to_disk(struct archive *reader, struct archive *writer, | | 659 | copy_data_to_disk(struct archive *reader, struct archive *writer, |
660 | const char *filename) | | 660 | const char *filename) |
661 | { | | 661 | { |
662 | int r; | | 662 | int r; |
663 | const void *buff; | | 663 | const void *buff; |
664 | size_t size; | | 664 | size_t size; |
665 | off_t offset; | | 665 | off_t offset; |
666 | | | 666 | |
667 | for (;;) { | | 667 | for (;;) { |
668 | r = archive_read_data_block(reader, &buff, &size, &offset); | | 668 | r = archive_read_data_block(reader, &buff, &size, &offset); |
669 | if (r == ARCHIVE_EOF) | | 669 | if (r == ARCHIVE_EOF) |
670 | return 0; | | 670 | return 0; |
671 | if (r != ARCHIVE_OK) { | | 671 | if (r != ARCHIVE_OK) { |
672 | warnx("Read error for %s: %s", filename, | | 672 | warnx("Read error for %s: %s", filename, |
673 | archive_error_string(reader)); | | 673 | archive_error_string(reader)); |
674 | return -1; | | 674 | return -1; |
675 | } | | 675 | } |
676 | r = archive_write_data_block(writer, buff, size, offset); | | 676 | r = archive_write_data_block(writer, buff, size, offset); |
677 | if (r != ARCHIVE_OK) { | | 677 | if (r != ARCHIVE_OK) { |
678 | warnx("Write error for %s: %s", filename, | | 678 | warnx("Write error for %s: %s", filename, |
679 | archive_error_string(writer)); | | 679 | archive_error_string(writer)); |
680 | return -1; | | 680 | return -1; |
681 | } | | 681 | } |
682 | } | | 682 | } |
683 | } | | 683 | } |
684 | | | 684 | |
685 | /* | | 685 | /* |
686 | * Extract package. | | 686 | * Extract package. |
687 | * Any misordered, missing or unlisted file in the package is an error. | | 687 | * Any misordered, missing or unlisted file in the package is an error. |
688 | */ | | 688 | */ |
689 | | | 689 | |
690 | static const int extract_flags = ARCHIVE_EXTRACT_OWNER | | | 690 | static const int extract_flags = ARCHIVE_EXTRACT_OWNER | |
691 | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_UNLINK | | | 691 | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_UNLINK | |
692 | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR; | | 692 | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR; |
693 | | | 693 | |
694 | static int | | 694 | static int |
695 | extract_files(struct pkg_task *pkg) | | 695 | extract_files(struct pkg_task *pkg) |
696 | { | | 696 | { |
697 | char cmd[MaxPathSize]; | | 697 | char cmd[MaxPathSize]; |
698 | const char *owner, *group, *permissions; | | 698 | const char *owner, *group, *permissions; |
699 | struct archive *writer; | | 699 | struct archive *writer; |
700 | int r; | | 700 | int r; |
701 | plist_t *p; | | 701 | plist_t *p; |
702 | const char *last_file; | | 702 | const char *last_file; |
703 | char *fullpath; | | 703 | char *fullpath; |
704 | | | 704 | |
705 | if (Fake) | | 705 | if (Fake) |
706 | return 0; | | 706 | return 0; |
707 | | | 707 | |
708 | if (mkdir_p(pkg->install_prefix)) { | | 708 | if (mkdir_p(pkg->install_prefix)) { |
709 | warn("Can't create prefix: %s", pkg->install_prefix); | | 709 | warn("Can't create prefix: %s", pkg->install_prefix); |
710 | return -1; | | 710 | return -1; |
711 | } | | 711 | } |
712 | | | 712 | |
713 | if (!NoRecord && !pkgdb_open(ReadWrite)) { | | 713 | if (!NoRecord && !pkgdb_open(ReadWrite)) { |
714 | warn("Can't open pkgdb for writing"); | | 714 | warn("Can't open pkgdb for writing"); |
715 | return -1; | | 715 | return -1; |
716 | } | | 716 | } |
717 | | | 717 | |
718 | if (chdir(pkg->install_prefix) == -1) { | | 718 | if (chdir(pkg->install_prefix) == -1) { |
719 | warn("Can't change into prefix: %s", pkg->install_prefix); | | 719 | warn("Can't change into prefix: %s", pkg->install_prefix); |
720 | return -1; | | 720 | return -1; |
721 | } | | 721 | } |
722 | | | 722 | |
723 | writer = archive_write_disk_new(); | | 723 | writer = archive_write_disk_new(); |
724 | archive_write_disk_set_options(writer, extract_flags); | | 724 | archive_write_disk_set_options(writer, extract_flags); |
725 | archive_write_disk_set_standard_lookup(writer); | | 725 | archive_write_disk_set_standard_lookup(writer); |
726 | | | 726 | |
727 | owner = NULL; | | 727 | owner = NULL; |
728 | group = NULL; | | 728 | group = NULL; |
729 | permissions = NULL; | | 729 | permissions = NULL; |
730 | last_file = NULL; | | 730 | last_file = NULL; |
731 | | | 731 | |
732 | r = -1; | | 732 | r = -1; |
733 | | | 733 | |
734 | for (p = pkg->plist.head; p != NULL; p = p->next) { | | 734 | for (p = pkg->plist.head; p != NULL; p = p->next) { |
735 | switch (p->type) { | | 735 | switch (p->type) { |
736 | case PLIST_FILE: | | 736 | case PLIST_FILE: |
737 | last_file = p->name; | | 737 | last_file = p->name; |
738 | if (pkg->entry == NULL) { | | 738 | if (pkg->entry == NULL) { |
739 | warnx("PLIST entry not in package (%s)", | | 739 | warnx("PLIST entry not in package (%s)", |
740 | archive_entry_pathname(pkg->entry)); | | 740 | archive_entry_pathname(pkg->entry)); |
741 | goto out; | | 741 | goto out; |
742 | } | | 742 | } |
743 | if (strcmp(p->name, archive_entry_pathname(pkg->entry))) { | | 743 | if (strcmp(p->name, archive_entry_pathname(pkg->entry))) { |
744 | warnx("PLIST entry and package don't match (%s vs %s)", | | 744 | warnx("PLIST entry and package don't match (%s vs %s)", |
745 | p->name, archive_entry_pathname(pkg->entry)); | | 745 | p->name, archive_entry_pathname(pkg->entry)); |
746 | goto out; | | 746 | goto out; |
747 | } | | 747 | } |
748 | fullpath = xasprintf("%s/%s", pkg->prefix, p->name); | | 748 | fullpath = xasprintf("%s/%s", pkg->prefix, p->name); |
749 | pkgdb_store(fullpath, pkg->pkgname); | | 749 | pkgdb_store(fullpath, pkg->pkgname); |
750 | free(fullpath); | | 750 | free(fullpath); |
751 | if (Verbose) | | 751 | if (Verbose) |
752 | printf("%s", p->name); | | 752 | printf("%s", p->name); |
753 | break; | | 753 | break; |
754 | | | 754 | |
755 | case PLIST_PKGDIR: | | 755 | case PLIST_PKGDIR: |
756 | fullpath = xasprintf("%s/%s", pkg->prefix, p->name); | | 756 | fullpath = xasprintf("%s/%s", pkg->prefix, p->name); |
757 | mkdir_p(fullpath); | | 757 | mkdir_p(fullpath); |
758 | free(fullpath); | | 758 | free(fullpath); |
759 | add_pkgdir(pkg->pkgname, pkg->prefix, p->name); | | 759 | add_pkgdir(pkg->pkgname, pkg->prefix, p->name); |
760 | continue; | | 760 | continue; |
761 | | | 761 | |
762 | case PLIST_CMD: | | 762 | case PLIST_CMD: |
763 | if (format_cmd(cmd, sizeof(cmd), p->name, pkg->prefix, last_file)) | | 763 | if (format_cmd(cmd, sizeof(cmd), p->name, pkg->prefix, last_file)) |
764 | return -1; | | 764 | return -1; |
765 | printf("Executing '%s'\n", cmd); | | 765 | printf("Executing '%s'\n", cmd); |
766 | if (!Fake && system(cmd)) | | 766 | if (!Fake && system(cmd)) |
767 | warnx("command '%s' failed", cmd); /* XXX bail out? */ | | 767 | warnx("command '%s' failed", cmd); /* XXX bail out? */ |
768 | continue; | | 768 | continue; |
769 | | | 769 | |
770 | case PLIST_CHMOD: | | 770 | case PLIST_CHMOD: |
771 | permissions = p->name; | | 771 | permissions = p->name; |
772 | continue; | | 772 | continue; |
773 | | | 773 | |
774 | case PLIST_CHOWN: | | 774 | case PLIST_CHOWN: |
775 | owner = p->name; | | 775 | owner = p->name; |
776 | continue; | | 776 | continue; |
777 | | | 777 | |
778 | case PLIST_CHGRP: | | 778 | case PLIST_CHGRP: |
779 | group = p->name; | | 779 | group = p->name; |
780 | continue; | | 780 | continue; |
781 | | | 781 | |
782 | case PLIST_IGNORE: | | 782 | case PLIST_IGNORE: |
783 | p = p->next; | | 783 | p = p->next; |
784 | continue; | | 784 | continue; |
785 | | | 785 | |
786 | default: | | 786 | default: |
787 | continue; | | 787 | continue; |
788 | } | | 788 | } |
789 | | | 789 | |
790 | r = archive_write_header(writer, pkg->entry); | | 790 | r = archive_write_header(writer, pkg->entry); |
791 | if (r != ARCHIVE_OK) { | | 791 | if (r != ARCHIVE_OK) { |
792 | warnx("Failed to write %s for %s: %s", | | 792 | warnx("Failed to write %s for %s: %s", |
793 | archive_entry_pathname(pkg->entry), | | 793 | archive_entry_pathname(pkg->entry), |
794 | pkg->pkgname, | | 794 | pkg->pkgname, |
795 | archive_error_string(writer)); | | 795 | archive_error_string(writer)); |
796 | goto out; | | 796 | goto out; |
797 | } | | 797 | } |
798 | | | 798 | |
799 | if (owner != NULL) | | 799 | if (owner != NULL) |
800 | archive_entry_set_uname(pkg->entry, owner); | | 800 | archive_entry_set_uname(pkg->entry, owner); |
801 | if (group != NULL) | | 801 | if (group != NULL) |
802 | archive_entry_set_uname(pkg->entry, group); | | 802 | archive_entry_set_uname(pkg->entry, group); |
803 | if (permissions != NULL) { | | 803 | if (permissions != NULL) { |
804 | mode_t mode; | | 804 | mode_t mode; |
805 | | | 805 | |
806 | mode = archive_entry_mode(pkg->entry); | | 806 | mode = archive_entry_mode(pkg->entry); |
807 | mode = getmode(setmode(permissions), mode); | | 807 | mode = getmode(setmode(permissions), mode); |
808 | archive_entry_set_mode(pkg->entry, mode); | | 808 | archive_entry_set_mode(pkg->entry, mode); |
809 | } | | 809 | } |
810 | | | 810 | |
811 | r = copy_data_to_disk(pkg->archive, writer, | | 811 | r = copy_data_to_disk(pkg->archive, writer, |
812 | archive_entry_pathname(pkg->entry)); | | 812 | archive_entry_pathname(pkg->entry)); |
813 | if (r) | | 813 | if (r) |
814 | goto out; | | 814 | goto out; |
815 | if (Verbose) | | 815 | if (Verbose) |
816 | printf("\n"); | | 816 | printf("\n"); |
817 | | | 817 | |
818 | r = archive_read_next_header(pkg->archive, &pkg->entry); | | 818 | r = archive_read_next_header(pkg->archive, &pkg->entry); |
819 | if (r == ARCHIVE_EOF) { | | 819 | if (r == ARCHIVE_EOF) { |
820 | pkg->entry = NULL; | | 820 | pkg->entry = NULL; |
821 | continue; | | 821 | continue; |
822 | } | | 822 | } |
823 | if (r != ARCHIVE_OK) { | | 823 | if (r != ARCHIVE_OK) { |
824 | warnx("Failed to read from archive for %s: %s", | | 824 | warnx("Failed to read from archive for %s: %s", |
825 | pkg->pkgname, | | 825 | pkg->pkgname, |
826 | archive_error_string(pkg->archive)); | | 826 | archive_error_string(pkg->archive)); |
827 | goto out; | | 827 | goto out; |
828 | } | | 828 | } |
829 | } | | 829 | } |
830 | | | 830 | |
831 | if (pkg->entry != NULL) { | | 831 | if (pkg->entry != NULL) { |
832 | warnx("Package contains entries not in PLIST: %s", | | 832 | warnx("Package contains entries not in PLIST: %s", |
833 | archive_entry_pathname(pkg->entry)); | | 833 | archive_entry_pathname(pkg->entry)); |
834 | goto out; | | 834 | goto out; |
835 | } | | 835 | } |
836 | | | 836 | |
837 | r = 0; | | 837 | r = 0; |
838 | | | 838 | |
839 | out: | | 839 | out: |
840 | if (!NoRecord) | | 840 | if (!NoRecord) |
841 | pkgdb_close(); | | 841 | pkgdb_close(); |
842 | archive_write_free(writer); | | 842 | archive_write_free(writer); |
843 | | | 843 | |
844 | return r; | | 844 | return r; |
845 | } | | 845 | } |
846 | | | 846 | |
847 | /* | | 847 | /* |
848 | * Register dependencies after sucessfully installing the package. | | 848 | * Register dependencies after sucessfully installing the package. |
849 | */ | | 849 | */ |
850 | static void | | 850 | static void |
851 | pkg_register_depends(struct pkg_task *pkg) | | 851 | pkg_register_depends(struct pkg_task *pkg) |
852 | { | | 852 | { |
853 | int fd; | | 853 | int fd; |
854 | size_t text_len, i; | | 854 | size_t text_len, i; |
855 | char *required_by, *text; | | 855 | char *required_by, *text; |
856 | | | 856 | |
857 | if (Fake) | | 857 | if (Fake) |
858 | return; | | 858 | return; |
859 | | | 859 | |
860 | text = xasprintf("%s\n", pkg->pkgname); | | 860 | text = xasprintf("%s\n", pkg->pkgname); |
861 | text_len = strlen(text); | | 861 | text_len = strlen(text); |
862 | | | 862 | |
863 | for (i = 0; i < pkg->dep_length; ++i) { | | 863 | for (i = 0; i < pkg->dep_length; ++i) { |
864 | required_by = pkgdb_pkg_file(pkg->dependencies[i], REQUIRED_BY_FNAME); | | 864 | required_by = pkgdb_pkg_file(pkg->dependencies[i], REQUIRED_BY_FNAME); |
865 | | | 865 | |
866 | fd = open(required_by, O_WRONLY | O_APPEND | O_CREAT, 0644); | | 866 | fd = open(required_by, O_WRONLY | O_APPEND | O_CREAT, 0644); |
867 | if (fd == -1) { | | 867 | if (fd == -1) { |
868 | warn("can't open dependency file '%s'," | | 868 | warn("can't open dependency file '%s'," |
869 | "registration is incomplete!", required_by); | | 869 | "registration is incomplete!", required_by); |
870 | } else if (write(fd, text, text_len) != (ssize_t)text_len) { | | 870 | } else if (write(fd, text, text_len) != (ssize_t)text_len) { |
871 | warn("can't write to dependency file `%s'", required_by); | | 871 | warn("can't write to dependency file `%s'", required_by); |
872 | close(fd); | | 872 | close(fd); |
873 | } else if (close(fd) == -1) | | 873 | } else if (close(fd) == -1) |
874 | warn("cannot close file %s", required_by); | | 874 | warn("cannot close file %s", required_by); |
875 | | | 875 | |
876 | free(required_by); | | 876 | free(required_by); |
877 | } | | 877 | } |
878 | | | 878 | |
879 | free(text); | | 879 | free(text); |
880 | } | | 880 | } |
881 | | | 881 | |
882 | /* | | 882 | /* |
883 | * Reduce the result from uname(3) to a canonical form. | | 883 | * Reduce the result from uname(3) to a canonical form. |
884 | */ | | 884 | */ |
885 | static void | | 885 | static void |
886 | normalise_platform(struct utsname *host_name) | | 886 | normalise_platform(struct utsname *host_name) |
887 | { | | 887 | { |
888 | #ifdef NUMERIC_VERSION_ONLY | | 888 | #ifdef NUMERIC_VERSION_ONLY |
889 | size_t span; | | 889 | size_t span; |
890 | | | 890 | |
891 | span = strspn(host_name->release, "0123456789."); | | 891 | span = strspn(host_name->release, "0123456789."); |
892 | host_name->release[span] = '\0'; | | 892 | host_name->release[span] = '\0'; |
893 | #endif | | 893 | #endif |
894 | } | | 894 | } |
895 | | | 895 | |
896 | /* | | 896 | /* |
897 | * Check build platform of the package against local host. | | 897 | * Check build platform of the package against local host. |
898 | */ | | 898 | */ |
899 | static int | | 899 | static int |
900 | check_platform(struct pkg_task *pkg) | | 900 | check_platform(struct pkg_task *pkg) |
901 | { | | 901 | { |
902 | struct utsname host_uname; | | 902 | struct utsname host_uname; |
903 | const char *effective_arch; | | 903 | const char *effective_arch; |
904 | int fatal; | | 904 | int fatal; |
905 | | | 905 | |
906 | if (uname(&host_uname) < 0) { | | 906 | if (uname(&host_uname) < 0) { |
907 | if (Force) { | | 907 | if (Force) { |
908 | warnx("uname() failed, continuing."); | | 908 | warnx("uname() failed, continuing."); |
909 | return 0; | | 909 | return 0; |
910 | } else { | | 910 | } else { |
911 | warnx("uname() failed, aborting."); | | 911 | warnx("uname() failed, aborting."); |
912 | return -1; | | 912 | return -1; |
913 | } | | 913 | } |
914 | } | | 914 | } |
915 | | | 915 | |
916 | normalise_platform(&host_uname); | | 916 | normalise_platform(&host_uname); |
917 | | | 917 | |
918 | if (OverrideMachine != NULL) | | 918 | if (OverrideMachine != NULL) |
919 | effective_arch = OverrideMachine; | | 919 | effective_arch = OverrideMachine; |
920 | else | | 920 | else |
921 | effective_arch = PKGSRC_MACHINE_ARCH; | | 921 | effective_arch = PKGSRC_MACHINE_ARCH; |
922 | | | 922 | |
923 | /* If either the OS or arch are different, bomb */ | | 923 | /* If either the OS or arch are different, bomb */ |
924 | if (strcmp(OPSYS_NAME, pkg->buildinfo[BI_OPSYS]) || | | 924 | if (strcmp(OPSYS_NAME, pkg->buildinfo[BI_OPSYS]) || |
925 | strcmp(effective_arch, pkg->buildinfo[BI_MACHINE_ARCH]) != 0) | | 925 | strcmp(effective_arch, pkg->buildinfo[BI_MACHINE_ARCH]) != 0) |
926 | fatal = 1; | | 926 | fatal = 1; |
927 | else | | 927 | else |
928 | fatal = 0; | | 928 | fatal = 0; |
929 | | | 929 | |
930 | if (fatal || | | 930 | if (fatal || |
931 | compatible_platform(OPSYS_NAME, host_uname.release, | | 931 | compatible_platform(OPSYS_NAME, host_uname.release, |
932 | pkg->buildinfo[BI_OS_VERSION]) != 1) { | | 932 | pkg->buildinfo[BI_OS_VERSION]) != 1) { |
933 | warnx("Warning: package `%s' was built for a platform:", | | 933 | warnx("Warning: package `%s' was built for a platform:", |
934 | pkg->pkgname); | | 934 | pkg->pkgname); |
935 | warnx("%s/%s %s (pkg) vs. %s/%s %s (this host)", | | 935 | warnx("%s/%s %s (pkg) vs. %s/%s %s (this host)", |
936 | pkg->buildinfo[BI_OPSYS], | | 936 | pkg->buildinfo[BI_OPSYS], |
937 | pkg->buildinfo[BI_MACHINE_ARCH], | | 937 | pkg->buildinfo[BI_MACHINE_ARCH], |
938 | pkg->buildinfo[BI_OS_VERSION], | | 938 | pkg->buildinfo[BI_OS_VERSION], |
939 | OPSYS_NAME, | | 939 | OPSYS_NAME, |
940 | effective_arch, | | 940 | effective_arch, |
941 | host_uname.release); | | 941 | host_uname.release); |
942 | if (!Force && fatal) | | 942 | if (!Force && fatal) |
943 | return -1; | | 943 | return -1; |
944 | } | | 944 | } |
945 | return 0; | | 945 | return 0; |
946 | } | | 946 | } |
947 | | | 947 | |
948 | static int | | 948 | static int |
949 | check_pkgtools_version(struct pkg_task *pkg) | | 949 | check_pkgtools_version(struct pkg_task *pkg) |
950 | { | | 950 | { |
951 | const char *val = pkg->buildinfo[BI_PKGTOOLS_VERSION]; | | 951 | const char *val = pkg->buildinfo[BI_PKGTOOLS_VERSION]; |
952 | int version; | | 952 | int version; |
953 | | | 953 | |
954 | if (val == NULL) { | | 954 | if (val == NULL) { |
955 | warnx("Warning: package `%s' lacks pkg_install version data", | | 955 | warnx("Warning: package `%s' lacks pkg_install version data", |
956 | pkg->pkgname); | | 956 | pkg->pkgname); |
957 | return 0; | | 957 | return 0; |
958 | } | | 958 | } |
959 | | | 959 | |
960 | if (strlen(val) != 8 || strspn(val, "0123456789") != 8) { | | 960 | if (strlen(val) != 8 || strspn(val, "0123456789") != 8) { |
961 | warnx("Warning: package `%s' contains an invalid pkg_install version", | | 961 | warnx("Warning: package `%s' contains an invalid pkg_install version", |
962 | pkg->pkgname); | | 962 | pkg->pkgname); |
963 | return Force ? 0 : -1; | | 963 | return Force ? 0 : -1; |
964 | } | | 964 | } |
965 | version = atoi(val); | | 965 | version = atoi(val); |
966 | if (version > PKGTOOLS_VERSION) { | | 966 | if (version > PKGTOOLS_VERSION) { |
967 | warnx("%s: package `%s' was built with a newer pkg_install version", | | 967 | warnx("%s: package `%s' was built with a newer pkg_install version", |
968 | Force ? "Warning" : "Error", pkg->pkgname); | | 968 | Force ? "Warning" : "Error", pkg->pkgname); |
969 | return Force ? 0 : -1; | | 969 | return Force ? 0 : -1; |
970 | } | | 970 | } |
971 | return 0; | | 971 | return 0; |
972 | } | | 972 | } |
973 | | | 973 | |
974 | /* | | 974 | /* |
975 | * Run the install script. | | 975 | * Run the install script. |
976 | */ | | 976 | */ |
977 | static int | | 977 | static int |
978 | run_install_script(struct pkg_task *pkg, const char *argument) | | 978 | run_install_script(struct pkg_task *pkg, const char *argument) |
979 | { | | 979 | { |
980 | int ret; | | 980 | int ret; |
981 | char *filename; | | 981 | char *filename; |
982 | | | 982 | |
983 | if (pkg->meta_data.meta_install == NULL || NoInstall) | | 983 | if (pkg->meta_data.meta_install == NULL || NoInstall) |
984 | return 0; | | 984 | return 0; |
985 | | | 985 | |
986 | if (Destdir != NULL) | | 986 | if (Destdir != NULL) |
987 | setenv(PKG_DESTDIR_VNAME, Destdir, 1); | | 987 | setenv(PKG_DESTDIR_VNAME, Destdir, 1); |
988 | setenv(PKG_PREFIX_VNAME, pkg->prefix, 1); | | 988 | setenv(PKG_PREFIX_VNAME, pkg->prefix, 1); |
989 | setenv(PKG_METADATA_DIR_VNAME, pkg->logdir, 1); | | 989 | setenv(PKG_METADATA_DIR_VNAME, pkg->logdir, 1); |
990 | setenv(PKG_REFCOUNT_DBDIR_VNAME, config_pkg_refcount_dbdir, 1); | | 990 | setenv(PKG_REFCOUNT_DBDIR_VNAME, config_pkg_refcount_dbdir, 1); |
991 | | | 991 | |
992 | if (Verbose) | | 992 | if (Verbose) |
993 | printf("Running install with %s for %s.\n", argument, | | 993 | printf("Running install with %s for %s.\n", argument, |
994 | pkg->pkgname); | | 994 | pkg->pkgname); |
995 | if (Fake) | | 995 | if (Fake) |
996 | return 0; | | 996 | return 0; |
997 | | | 997 | |
998 | filename = pkgdb_pkg_file(pkg->pkgname, INSTALL_FNAME); | | 998 | filename = pkgdb_pkg_file(pkg->pkgname, INSTALL_FNAME); |
999 | | | 999 | |
1000 | ret = 0; | | 1000 | ret = 0; |
1001 | errno = 0; | | 1001 | errno = 0; |
1002 | if (fcexec(pkg->install_logdir, filename, pkg->pkgname, argument, | | 1002 | if (fcexec(pkg->install_logdir, filename, pkg->pkgname, argument, |
1003 | (void *)NULL)) { | | 1003 | (void *)NULL)) { |
1004 | if (errno != 0) | | 1004 | if (errno != 0) |
1005 | warn("exec of install script failed"); | | 1005 | warn("exec of install script failed"); |
1006 | else | | 1006 | else |
1007 | warnx("install script returned error status"); | | 1007 | warnx("install script returned error status"); |
1008 | ret = -1; | | 1008 | ret = -1; |
1009 | } | | 1009 | } |
1010 | free(filename); | | 1010 | free(filename); |
1011 | | | 1011 | |
1012 | return ret; | | 1012 | return ret; |
1013 | } | | 1013 | } |
1014 | | | 1014 | |
1015 | struct find_conflict_data { | | 1015 | struct find_conflict_data { |
1016 | const char *pkg; | | 1016 | const char *pkg; |
1017 | const char *old_pkg; | | 1017 | const char *old_pkg; |
1018 | const char *pattern; | | 1018 | const char *pattern; |
1019 | }; | | 1019 | }; |
1020 | | | 1020 | |
1021 | static int | | 1021 | static int |
1022 | check_explicit_conflict_iter(const char *cur_pkg, void *cookie) | | 1022 | check_explicit_conflict_iter(const char *cur_pkg, void *cookie) |
1023 | { | | 1023 | { |
1024 | struct find_conflict_data *data = cookie; | | 1024 | struct find_conflict_data *data = cookie; |
1025 | | | 1025 | |
1026 | if (data->old_pkg && strcmp(data->old_pkg, cur_pkg) == 0) | | 1026 | if (data->old_pkg && strcmp(data->old_pkg, cur_pkg) == 0) |
1027 | return 0; | | 1027 | return 0; |
1028 | | | 1028 | |
1029 | warnx("Package `%s' conflicts with `%s', and `%s' is installed.", | | 1029 | warnx("Package `%s' conflicts with `%s', and `%s' is installed.", |
1030 | data->pkg, data->pattern, cur_pkg); | | 1030 | data->pkg, data->pattern, cur_pkg); |
1031 | | | 1031 | |
1032 | return 1; | | 1032 | return 1; |
1033 | } | | 1033 | } |
1034 | | | 1034 | |
1035 | static int | | 1035 | static int |
1036 | check_explicit_conflict(struct pkg_task *pkg) | | 1036 | check_explicit_conflict(struct pkg_task *pkg) |
1037 | { | | 1037 | { |
1038 | struct find_conflict_data data; | | 1038 | struct find_conflict_data data; |
1039 | char *installed, *installed_pattern; | | 1039 | char *installed, *installed_pattern; |
1040 | plist_t *p; | | 1040 | plist_t *p; |
1041 | int status; | | 1041 | int status; |
1042 | | | 1042 | |
1043 | status = 0; | | 1043 | status = 0; |
1044 | | | 1044 | |
1045 | for (p = pkg->plist.head; p != NULL; p = p->next) { | | 1045 | for (p = pkg->plist.head; p != NULL; p = p->next) { |
1046 | if (p->type == PLIST_IGNORE) { | | 1046 | if (p->type == PLIST_IGNORE) { |
1047 | p = p->next; | | 1047 | p = p->next; |
1048 | continue; | | 1048 | continue; |
1049 | } | | 1049 | } |
1050 | if (p->type != PLIST_PKGCFL) | | 1050 | if (p->type != PLIST_PKGCFL) |
1051 | continue; | | 1051 | continue; |
1052 | data.pkg = pkg->pkgname; | | 1052 | data.pkg = pkg->pkgname; |
1053 | data.old_pkg = pkg->other_version; | | 1053 | data.old_pkg = pkg->other_version; |
1054 | data.pattern = p->name; | | 1054 | data.pattern = p->name; |
1055 | status |= match_installed_pkgs(p->name, | | 1055 | status |= match_installed_pkgs(p->name, |
1056 | check_explicit_conflict_iter, &data); | | 1056 | check_explicit_conflict_iter, &data); |
1057 | } | | 1057 | } |
1058 | | | 1058 | |
1059 | if (some_installed_package_conflicts_with(pkg->pkgname, | | 1059 | if (some_installed_package_conflicts_with(pkg->pkgname, |
1060 | pkg->other_version, &installed, &installed_pattern)) { | | 1060 | pkg->other_version, &installed, &installed_pattern)) { |
1061 | warnx("Installed package `%s' conflicts with `%s' when trying to install `%s'.", | | 1061 | warnx("Installed package `%s' conflicts with `%s' when trying to install `%s'.", |
1062 | installed, installed_pattern, pkg->pkgname); | | 1062 | installed, installed_pattern, pkg->pkgname); |
1063 | free(installed); | | 1063 | free(installed); |
1064 | free(installed_pattern); | | 1064 | free(installed_pattern); |
1065 | status |= -1; | | 1065 | status |= -1; |
1066 | } | | 1066 | } |
1067 | | | 1067 | |
1068 | return status; | | 1068 | return status; |
1069 | } | | 1069 | } |
1070 | | | 1070 | |
1071 | static int | | 1071 | static int |
1072 | check_implicit_conflict(struct pkg_task *pkg) | | 1072 | check_implicit_conflict(struct pkg_task *pkg) |
1073 | { | | 1073 | { |
1074 | plist_t *p; | | 1074 | plist_t *p; |
1075 | char *fullpath, *existing; | | 1075 | char *fullpath, *existing; |
1076 | int status; | | 1076 | int status; |
1077 | | | 1077 | |
1078 | if (!pkgdb_open(ReadOnly)) { | | 1078 | if (!pkgdb_open(ReadOnly)) { |
1079 | #if notyet /* XXX empty pkgdb without database? */ | | 1079 | #if notyet /* XXX empty pkgdb without database? */ |
1080 | warn("Can't open pkgdb for reading"); | | 1080 | warn("Can't open pkgdb for reading"); |
1081 | return -1; | | 1081 | return -1; |
1082 | #else | | 1082 | #else |
1083 | return 0; | | 1083 | return 0; |
1084 | #endif | | 1084 | #endif |
1085 | } | | 1085 | } |
1086 | | | 1086 | |
1087 | status = 0; | | 1087 | status = 0; |
1088 | | | 1088 | |
1089 | for (p = pkg->plist.head; p != NULL; p = p->next) { | | 1089 | for (p = pkg->plist.head; p != NULL; p = p->next) { |
1090 | if (p->type == PLIST_IGNORE) { | | 1090 | if (p->type == PLIST_IGNORE) { |
1091 | p = p->next; | | 1091 | p = p->next; |
1092 | continue; | | 1092 | continue; |
1093 | } else if (p->type != PLIST_FILE) | | 1093 | } else if (p->type != PLIST_FILE) |
1094 | continue; | | 1094 | continue; |
1095 | | | 1095 | |
1096 | fullpath = xasprintf("%s/%s", pkg->prefix, p->name); | | 1096 | fullpath = xasprintf("%s/%s", pkg->prefix, p->name); |
1097 | existing = pkgdb_retrieve(fullpath); | | 1097 | existing = pkgdb_retrieve(fullpath); |
1098 | free(fullpath); | | 1098 | free(fullpath); |
1099 | if (existing == NULL) | | 1099 | if (existing == NULL) |
1100 | continue; | | 1100 | continue; |
1101 | if (pkg->other_version != NULL && | | 1101 | if (pkg->other_version != NULL && |
1102 | strcmp(pkg->other_version, existing) == 0) | | 1102 | strcmp(pkg->other_version, existing) == 0) |
1103 | continue; | | 1103 | continue; |
1104 | | | 1104 | |
1105 | warnx("Conflicting PLIST with %s: %s", existing, p->name); | | 1105 | warnx("Conflicting PLIST with %s: %s", existing, p->name); |
1106 | if (!Force) { | | 1106 | if (!Force) { |
1107 | status = -1; | | 1107 | status = -1; |
1108 | if (!Verbose) | | 1108 | if (!Verbose) |
1109 | break; | | 1109 | break; |
1110 | } | | 1110 | } |
1111 | } | | 1111 | } |
1112 | | | 1112 | |
1113 | pkgdb_close(); | | 1113 | pkgdb_close(); |
1114 | return status; | | 1114 | return status; |
1115 | } | | 1115 | } |
1116 | | | 1116 | |
1117 | /* | | 1117 | /* |
1118 | * Install a required dependency and verify its installation. | | 1118 | * Install a required dependency and verify its installation. |
1119 | */ | | 1119 | */ |
1120 | static int | | 1120 | static int |
1121 | install_depend_pkg(const char *dep) | | 1121 | install_depend_pkg(const char *dep) |
1122 | { | | 1122 | { |
1123 | /* XXX check cyclic dependencies? */ | | 1123 | /* XXX check cyclic dependencies? */ |
1124 | if (Fake || NoRecord) { | | 1124 | if (Fake || NoRecord) { |
1125 | if (!Force) { | | 1125 | if (!Force) { |
1126 | warnx("Missing dependency %s\n", dep); | | 1126 | warnx("Missing dependency %s\n", dep); |
1127 | return 1; | | 1127 | return 1; |
1128 | } | | 1128 | } |
1129 | warnx("Missing dependency %s, continuing", dep); | | 1129 | warnx("Missing dependency %s, continuing", dep); |
1130 | } | | 1130 | } |
1131 | | | 1131 | |
1132 | if (pkg_do(dep, 1, 0)) { | | 1132 | if (pkg_do(dep, 1, 0)) { |
1133 | if (!ForceDepends) { | | 1133 | if (!ForceDepends) { |
1134 | warnx("Can't install dependency %s", dep); | | 1134 | warnx("Can't install dependency %s", dep); |
1135 | return 1; | | 1135 | return 1; |
1136 | } | | 1136 | } |
1137 | warnx("Can't install dependency %s, continuing", dep); | | 1137 | warnx("Can't install dependency %s, continuing", dep); |
1138 | } | | 1138 | } |
1139 | | | 1139 | |
1140 | if (find_best_matching_installed_pkg(dep, 0) == NULL) { | | 1140 | if (find_best_matching_installed_pkg(dep, 0) == NULL) { |
1141 | if (!ForceDepends) { | | 1141 | if (!ForceDepends) { |
1142 | warnx("Just installed dependency %s disappeared", dep); | | 1142 | warnx("Just installed dependency %s disappeared", dep); |
1143 | return 1; | | 1143 | return 1; |
1144 | } | | 1144 | } |
1145 | warnx("Missing dependency %s ignored", dep); | | 1145 | warnx("Missing dependency %s ignored", dep); |
1146 | } | | 1146 | } |
1147 | | | 1147 | |
1148 | return 0; | | 1148 | return 0; |
1149 | } | | 1149 | } |
1150 | | | 1150 | |
1151 | static int | | 1151 | static int |
1152 | check_dependencies(struct pkg_task *pkg) | | 1152 | check_dependencies(struct pkg_task *pkg) |
1153 | { | | 1153 | { |
1154 | plist_t *p; | | 1154 | plist_t *p; |
1155 | char *best_installed; | | 1155 | char *best_installed; |
1156 | int status; | | 1156 | int status; |
1157 | size_t i; | | 1157 | size_t i; |
1158 | | | 1158 | |
1159 | status = 0; | | 1159 | status = 0; |
1160 | | | 1160 | |
1161 | /* | | 1161 | /* |
1162 | * Recursively handle dependencies, installing as required. | | 1162 | * Recursively handle dependencies, installing as required. |
1163 | */ | | 1163 | */ |
1164 | for (p = pkg->plist.head; p != NULL; p = p->next) { | | 1164 | for (p = pkg->plist.head; p != NULL; p = p->next) { |
1165 | if (p->type == PLIST_IGNORE) { | | 1165 | if (p->type == PLIST_IGNORE) { |
1166 | p = p->next; | | 1166 | p = p->next; |
1167 | continue; | | 1167 | continue; |
1168 | } else if (p->type != PLIST_PKGDEP) | | 1168 | } else if (p->type != PLIST_PKGDEP) |
1169 | continue; | | 1169 | continue; |
1170 | | | 1170 | |
1171 | if (find_best_matching_installed_pkg(p->name, 0) == NULL) { | | 1171 | if (find_best_matching_installed_pkg(p->name, 0) == NULL) { |
1172 | if (install_depend_pkg(p->name) != 0) { | | 1172 | if (install_depend_pkg(p->name) != 0) { |
1173 | status = -1; | | 1173 | status = -1; |
1174 | break; | | 1174 | break; |
1175 | } | | 1175 | } |
1176 | } | | 1176 | } |
1177 | } | | 1177 | } |
1178 | | | 1178 | |
1179 | /* | | 1179 | /* |
1180 | * Now that all dependencies have been processed we can find the best | | 1180 | * Now that all dependencies have been processed we can find the best |
1181 | * matches for pkg_register_depends() to store in our +REQUIRED_BY. | | 1181 | * matches for pkg_register_depends() to store in our +REQUIRED_BY. |
1182 | */ | | 1182 | */ |
1183 | for (p = pkg->plist.head; p != NULL; p = p->next) { | | 1183 | for (p = pkg->plist.head; p != NULL; p = p->next) { |
1184 | if (p->type == PLIST_IGNORE) { | | 1184 | if (p->type == PLIST_IGNORE) { |
1185 | p = p->next; | | 1185 | p = p->next; |
1186 | continue; | | 1186 | continue; |
1187 | } else if (p->type != PLIST_PKGDEP) | | 1187 | } else if (p->type != PLIST_PKGDEP) |
1188 | continue; | | 1188 | continue; |
1189 | | | 1189 | |
1190 | best_installed = find_best_matching_installed_pkg(p->name, 0); | | 1190 | best_installed = find_best_matching_installed_pkg(p->name, 0); |
1191 | if (best_installed == NULL) { | | 1191 | if (best_installed == NULL) { |
1192 | warnx("Expected dependency %s still missing", p->name); | | 1192 | warnx("Expected dependency %s still missing", p->name); |
1193 | return -1; | | 1193 | return -1; |
1194 | } | | 1194 | } |
1195 | | | 1195 | |
1196 | for (i = 0; i < pkg->dep_length; ++i) { | | 1196 | for (i = 0; i < pkg->dep_length; ++i) { |
1197 | if (strcmp(best_installed, pkg->dependencies[i]) == 0) | | 1197 | if (strcmp(best_installed, pkg->dependencies[i]) == 0) |
1198 | break; | | 1198 | break; |
1199 | } | | 1199 | } |
1200 | if (i < pkg->dep_length) { | | 1200 | if (i < pkg->dep_length) { |
1201 | /* Already used as dependency, so skip it. */ | | 1201 | /* Already used as dependency, so skip it. */ |
1202 | free(best_installed); | | 1202 | free(best_installed); |
1203 | continue; | | 1203 | continue; |
1204 | } | | 1204 | } |
1205 | if (pkg->dep_length + 1 >= pkg->dep_allocated) { | | 1205 | if (pkg->dep_length + 1 >= pkg->dep_allocated) { |
1206 | char **tmp; | | 1206 | char **tmp; |
1207 | pkg->dep_allocated = 2 * pkg->dep_allocated + 1; | | 1207 | pkg->dep_allocated = 2 * pkg->dep_allocated + 1; |
1208 | pkg->dependencies = xrealloc(pkg->dependencies, | | 1208 | pkg->dependencies = xrealloc(pkg->dependencies, |
1209 | pkg->dep_allocated * sizeof(*tmp)); | | 1209 | pkg->dep_allocated * sizeof(*tmp)); |
1210 | } | | 1210 | } |
1211 | pkg->dependencies[pkg->dep_length++] = best_installed; | | 1211 | pkg->dependencies[pkg->dep_length++] = best_installed; |
1212 | } | | 1212 | } |
1213 | | | 1213 | |
1214 | return status; | | 1214 | return status; |
1215 | } | | 1215 | } |
1216 | | | 1216 | |
1217 | static int | | 1217 | static int |
1218 | preserve_meta_data_file(struct pkg_task *pkg, const char *name) | | 1218 | preserve_meta_data_file(struct pkg_task *pkg, const char *name) |
1219 | { | | 1219 | { |
1220 | char *old_file, *new_file; | | 1220 | char *old_file, *new_file; |
1221 | int rv; | | 1221 | int rv; |
1222 | | | 1222 | |
1223 | if (Fake) | | 1223 | if (Fake) |
1224 | return 0; | | 1224 | return 0; |
1225 | | | 1225 | |
1226 | old_file = pkgdb_pkg_file(pkg->other_version, name); | | 1226 | old_file = pkgdb_pkg_file(pkg->other_version, name); |
1227 | new_file = xasprintf("%s/%s", pkg->install_logdir, name); | | 1227 | new_file = xasprintf("%s/%s", pkg->install_logdir, name); |
1228 | rv = 0; | | 1228 | rv = 0; |
1229 | if (rename(old_file, new_file) == -1 && errno != ENOENT) { | | 1229 | if (rename(old_file, new_file) == -1 && errno != ENOENT) { |
1230 | warn("Can't move %s from %s to %s", name, old_file, new_file); | | 1230 | warn("Can't move %s from %s to %s", name, old_file, new_file); |
1231 | rv = -1; | | 1231 | rv = -1; |
1232 | } | | 1232 | } |
1233 | free(old_file); | | 1233 | free(old_file); |
1234 | free(new_file); | | 1234 | free(new_file); |
1235 | return rv; | | 1235 | return rv; |
1236 | } | | 1236 | } |
1237 | | | 1237 | |
1238 | static int | | 1238 | static int |
1239 | start_replacing(struct pkg_task *pkg) | | 1239 | start_replacing(struct pkg_task *pkg) |
1240 | { | | 1240 | { |
1241 | int result = -1; | | 1241 | int result = -1; |
1242 | | | 1242 | |
1243 | if (preserve_meta_data_file(pkg, REQUIRED_BY_FNAME)) | | 1243 | if (preserve_meta_data_file(pkg, REQUIRED_BY_FNAME)) |
1244 | return -1; | | 1244 | return -1; |
1245 | | | 1245 | |
1246 | if (preserve_meta_data_file(pkg, PRESERVE_FNAME)) | | 1246 | if (preserve_meta_data_file(pkg, PRESERVE_FNAME)) |
1247 | return -1; | | 1247 | return -1; |
1248 | | | 1248 | |
1249 | if (pkg->meta_data.meta_installed_info == NULL && | | 1249 | if (pkg->meta_data.meta_installed_info == NULL && |
1250 | preserve_meta_data_file(pkg, INSTALLED_INFO_FNAME)) | | 1250 | preserve_meta_data_file(pkg, INSTALLED_INFO_FNAME)) |
1251 | return -1; | | 1251 | return -1; |
1252 | | | 1252 | |
1253 | if (Verbose || Fake) { | | 1253 | if (Verbose || Fake) { |
1254 | printf("%s/pkg_delete -K %s -p %s%s%s '%s'\n", | | 1254 | printf("%s/pkg_delete -K %s -p %s%s%s '%s'\n", |
1255 | BINDIR, pkgdb_get_dir(), pkg->prefix, | | 1255 | BINDIR, pkgdb_get_dir(), pkg->prefix, |
1256 | Destdir ? " -P ": "", Destdir ? Destdir : "", | | 1256 | Destdir ? " -P ": "", Destdir ? Destdir : "", |
1257 | pkg->other_version); | | 1257 | pkg->other_version); |
1258 | } | | 1258 | } |
1259 | if (!Fake) { | | 1259 | if (!Fake) { |
1260 | result = fexec_skipempty(BINDIR "/pkg_delete", "-K", pkgdb_get_dir(), | | 1260 | result = fexec_skipempty(BINDIR "/pkg_delete", "-K", pkgdb_get_dir(), |
1261 | "-p", pkg->prefix, | | 1261 | "-p", pkg->prefix, |
1262 | Destdir ? "-P": "", Destdir ? Destdir : "", | | 1262 | Destdir ? "-P": "", Destdir ? Destdir : "", |
1263 | pkg->other_version, NULL); | | 1263 | pkg->other_version, NULL); |
1264 | if (result != 0) { | | 1264 | if (result != 0) { |
1265 | warnx("command failed: %s/pkg_delete -K %s -p %s %s%s%s", | | 1265 | warnx("command failed: %s/pkg_delete -K %s -p %s %s%s%s", |
1266 | BINDIR, pkgdb_get_dir(), pkg->prefix, Destdir ? "-P" : " ", | | 1266 | BINDIR, pkgdb_get_dir(), pkg->prefix, Destdir ? "-P" : " ", |
1267 | Destdir ? Destdir : "", pkg->other_version); | | 1267 | Destdir ? Destdir : "", pkg->other_version); |
1268 | } | | 1268 | } |
1269 | } | | 1269 | } |
1270 | | | 1270 | |
1271 | return result; | | 1271 | return result; |
1272 | } | | 1272 | } |
1273 | | | 1273 | |
1274 | static int check_input(const char *line, size_t len) | | 1274 | static int check_input(const char *line, size_t len) |
1275 | { | | 1275 | { |
1276 | if (line == NULL || len == 0) | | 1276 | if (line == NULL || len == 0) |
1277 | return 1; | | 1277 | return 1; |
1278 | switch (*line) { | | 1278 | switch (*line) { |
1279 | case 'Y': | | 1279 | case 'Y': |
1280 | case 'y': | | 1280 | case 'y': |
1281 | case 'T': | | 1281 | case 'T': |
1282 | case 't': | | 1282 | case 't': |
1283 | case '1': | | 1283 | case '1': |
1284 | return 0; | | 1284 | return 0; |
1285 | default: | | 1285 | default: |
1286 | return 1; | | 1286 | return 1; |
1287 | } | | 1287 | } |
1288 | } | | 1288 | } |
1289 | | | 1289 | |
1290 | static int | | 1290 | static int |
1291 | check_signature(struct pkg_task *pkg, int invalid_sig) | | 1291 | check_signature(struct pkg_task *pkg, int invalid_sig) |
1292 | { | | 1292 | { |
1293 | #ifdef BOOTSTRAP | | 1293 | #ifdef BOOTSTRAP |
1294 | return 0; | | 1294 | return 0; |
1295 | #else | | 1295 | #else |
1296 | char *line; | | 1296 | char *line; |
1297 | size_t len; | | 1297 | size_t len; |
1298 | | | 1298 | |
1299 | if (strcasecmp(verified_installation, "never") == 0) | | 1299 | if (strcasecmp(verified_installation, "never") == 0) |
1300 | return 0; | | 1300 | return 0; |
1301 | if (strcasecmp(verified_installation, "always") == 0) { | | 1301 | if (strcasecmp(verified_installation, "always") == 0) { |
1302 | if (invalid_sig) | | 1302 | if (invalid_sig) |
1303 | warnx("No valid signature found, rejected"); | | 1303 | warnx("No valid signature found, rejected"); |
1304 | return invalid_sig; | | 1304 | return invalid_sig; |
1305 | } | | 1305 | } |
1306 | if (strcasecmp(verified_installation, "trusted") == 0) { | | 1306 | if (strcasecmp(verified_installation, "trusted") == 0) { |
1307 | if (!invalid_sig) | | 1307 | if (!invalid_sig) |
1308 | return 0; | | 1308 | return 0; |
1309 | fprintf(stderr, "No valid signature found for %s.\n", | | 1309 | fprintf(stderr, "No valid signature found for %s.\n", |
1310 | pkg->pkgname); | | 1310 | pkg->pkgname); |
1311 | fprintf(stderr, | | 1311 | fprintf(stderr, |
1312 | "Do you want to proceed with the installation [y/n]?\n"); | | 1312 | "Do you want to proceed with the installation [y/n]?\n"); |
1313 | line = fgetln(stdin, &len); | | 1313 | line = fgetln(stdin, &len); |
1314 | if (check_input(line, len)) { | | 1314 | if (check_input(line, len)) { |
1315 | fprintf(stderr, "Cancelling installation\n"); | | 1315 | fprintf(stderr, "Cancelling installation\n"); |
1316 | return 1; | | 1316 | return 1; |
1317 | } | | 1317 | } |
1318 | return 0; | | 1318 | return 0; |
1319 | } | | 1319 | } |
1320 | if (strcasecmp(verified_installation, "interactive") == 0) { | | 1320 | if (strcasecmp(verified_installation, "interactive") == 0) { |
1321 | fprintf(stderr, "Do you want to proceed with " | | 1321 | fprintf(stderr, "Do you want to proceed with " |
1322 | "the installation of %s [y/n]?\n", pkg->pkgname); | | 1322 | "the installation of %s [y/n]?\n", pkg->pkgname); |
1323 | line = fgetln(stdin, &len); | | 1323 | line = fgetln(stdin, &len); |
1324 | if (check_input(line, len)) { | | 1324 | if (check_input(line, len)) { |
1325 | fprintf(stderr, "Cancelling installation\n"); | | 1325 | fprintf(stderr, "Cancelling installation\n"); |
1326 | return 1; | | 1326 | return 1; |
1327 | } | | 1327 | } |
1328 | return 0; | | 1328 | return 0; |
1329 | } | | 1329 | } |
1330 | warnx("Unknown value of configuration variable VERIFIED_INSTALLATION"); | | 1330 | warnx("Unknown value of configuration variable VERIFIED_INSTALLATION"); |
1331 | return 1; | | 1331 | return 1; |
1332 | #endif | | 1332 | #endif |
1333 | } | | 1333 | } |
1334 | | | 1334 | |
1335 | static int | | 1335 | static int |
1336 | check_vulnerable(struct pkg_task *pkg) | | 1336 | check_vulnerable(struct pkg_task *pkg) |
1337 | { | | 1337 | { |
1338 | #ifdef BOOTSTRAP | | 1338 | #ifdef BOOTSTRAP |
1339 | return 0; | | 1339 | return 0; |
1340 | #else | | 1340 | #else |
1341 | static struct pkg_vulnerabilities *pv; | | 1341 | static struct pkg_vulnerabilities *pv; |
1342 | int require_check; | | 1342 | int require_check; |
1343 | char *line; | | 1343 | char *line; |
1344 | size_t len; | | 1344 | size_t len; |
1345 | | | 1345 | |
1346 | if (strcasecmp(check_vulnerabilities, "never") == 0) | | 1346 | if (strcasecmp(check_vulnerabilities, "never") == 0) |
1347 | return 0; | | 1347 | return 0; |
1348 | else if (strcasecmp(check_vulnerabilities, "always") == 0) | | 1348 | else if (strcasecmp(check_vulnerabilities, "always") == 0) |
1349 | require_check = 1; | | 1349 | require_check = 1; |
1350 | else if (strcasecmp(check_vulnerabilities, "interactive") == 0) | | 1350 | else if (strcasecmp(check_vulnerabilities, "interactive") == 0) |
1351 | require_check = 0; | | 1351 | require_check = 0; |
1352 | else { | | 1352 | else { |
1353 | warnx("Unknown value of the configuration variable" | | 1353 | warnx("Unknown value of the configuration variable" |
1354 | "CHECK_VULNERABILITIES"); | | 1354 | "CHECK_VULNERABILITIES"); |
1355 | return 1; | | 1355 | return 1; |
1356 | } | | 1356 | } |
1357 | | | 1357 | |
1358 | if (pv == NULL) { | | 1358 | if (pv == NULL) { |
1359 | pv = read_pkg_vulnerabilities_file(pkg_vulnerabilities_file, | | 1359 | pv = read_pkg_vulnerabilities_file(pkg_vulnerabilities_file, |
1360 | require_check, 0); | | 1360 | require_check, 0); |
1361 | if (pv == NULL) | | 1361 | if (pv == NULL) |
1362 | return require_check; | | 1362 | return require_check; |
1363 | } | | 1363 | } |
1364 | | | 1364 | |
1365 | if (!audit_package(pv, pkg->pkgname, NULL, 0, 2)) | | 1365 | if (!audit_package(pv, pkg->pkgname, NULL, 0, 2)) |
1366 | return 0; | | 1366 | return 0; |
1367 | | | 1367 | |
1368 | if (require_check) | | 1368 | if (require_check) |
1369 | return 1; | | 1369 | return 1; |
1370 | | | 1370 | |
1371 | fprintf(stderr, "Do you want to proceed with the installation of %s" | | 1371 | fprintf(stderr, "Do you want to proceed with the installation of %s" |
1372 | " [y/n]?\n", pkg->pkgname); | | 1372 | " [y/n]?\n", pkg->pkgname); |
1373 | line = fgetln(stdin, &len); | | 1373 | line = fgetln(stdin, &len); |
1374 | if (check_input(line, len)) { | | 1374 | if (check_input(line, len)) { |
1375 | fprintf(stderr, "Cancelling installation\n"); | | 1375 | fprintf(stderr, "Cancelling installation\n"); |
1376 | return 1; | | 1376 | return 1; |
1377 | } | | 1377 | } |
1378 | return 0; | | 1378 | return 0; |
1379 | #endif | | 1379 | #endif |
1380 | } | | 1380 | } |
1381 | | | 1381 | |
1382 | static int | | 1382 | static int |
1383 | check_license(struct pkg_task *pkg) | | 1383 | check_license(struct pkg_task *pkg) |
1384 | { | | 1384 | { |
1385 | #ifdef BOOTSTRAP | | 1385 | #ifdef BOOTSTRAP |
1386 | return 0; | | 1386 | return 0; |
1387 | #else | | 1387 | #else |
1388 | if (LicenseCheck == 0) | | 1388 | if (LicenseCheck == 0) |
1389 | return 0; | | 1389 | return 0; |
1390 | | | 1390 | |
1391 | if ((pkg->buildinfo[BI_LICENSE] == NULL || | | 1391 | if ((pkg->buildinfo[BI_LICENSE] == NULL || |
1392 | *pkg->buildinfo[BI_LICENSE] == '\0')) { | | 1392 | *pkg->buildinfo[BI_LICENSE] == '\0')) { |
1393 | | | 1393 | |
1394 | if (LicenseCheck == 1) | | 1394 | if (LicenseCheck == 1) |
1395 | return 0; | | 1395 | return 0; |
1396 | warnx("No LICENSE set for package `%s'", pkg->pkgname); | | 1396 | warnx("No LICENSE set for package `%s'", pkg->pkgname); |
1397 | return 1; | | 1397 | return 1; |
1398 | } | | 1398 | } |
1399 | | | 1399 | |
1400 | switch (acceptable_license(pkg->buildinfo[BI_LICENSE])) { | | 1400 | switch (acceptable_license(pkg->buildinfo[BI_LICENSE])) { |
1401 | case 0: | | 1401 | case 0: |
1402 | warnx("License `%s' of package `%s' is not acceptable", | | 1402 | warnx("License `%s' of package `%s' is not acceptable", |
1403 | pkg->buildinfo[BI_LICENSE], pkg->pkgname); | | 1403 | pkg->buildinfo[BI_LICENSE], pkg->pkgname); |
1404 | return 1; | | 1404 | return 1; |
1405 | case 1: | | 1405 | case 1: |
1406 | return 0; | | 1406 | return 0; |
1407 | default: | | 1407 | default: |
1408 | warnx("Invalid LICENSE for package `%s'", pkg->pkgname); | | 1408 | warnx("Invalid LICENSE for package `%s'", pkg->pkgname); |
1409 | return 1; | | 1409 | return 1; |
1410 | } | | 1410 | } |
1411 | #endif | | 1411 | #endif |
1412 | } | | 1412 | } |
1413 | | | 1413 | |
1414 | /* | | 1414 | /* |
1415 | * Install a single package. | | 1415 | * Install a single package. |
1416 | */ | | 1416 | */ |
1417 | static int | | 1417 | static int |
1418 | pkg_do(const char *pkgpath, int mark_automatic, int top_level) | | 1418 | pkg_do(const char *pkgpath, int mark_automatic, int top_level) |
1419 | { | | 1419 | { |
1420 | char *archive_name; | | 1420 | char *archive_name; |
1421 | int status, invalid_sig; | | 1421 | int status, invalid_sig; |
1422 | struct pkg_task *pkg; | | 1422 | struct pkg_task *pkg; |
1423 | | | 1423 | |
1424 | pkg = xcalloc(1, sizeof(*pkg)); | | 1424 | pkg = xcalloc(1, sizeof(*pkg)); |
1425 | | | 1425 | |
1426 | status = -1; | | 1426 | status = -1; |
1427 | | | 1427 | |
1428 | pkg->archive = find_archive(pkgpath, top_level, &archive_name); | | 1428 | pkg->archive = find_archive(pkgpath, top_level, &archive_name); |
1429 | if (pkg->archive == NULL) { | | 1429 | if (pkg->archive == NULL) { |
1430 | warnx("no pkg found for '%s', sorry.", pkgpath); | | 1430 | warnx("no pkg found for '%s', sorry.", pkgpath); |
1431 | goto clean_find_archive; | | 1431 | goto clean_find_archive; |
1432 | } | | 1432 | } |
1433 | | | 1433 | |
1434 | #ifndef BOOTSTRAP | | 1434 | #ifndef BOOTSTRAP |
1435 | invalid_sig = pkg_verify_signature(archive_name, &pkg->archive, &pkg->entry, | | 1435 | invalid_sig = pkg_verify_signature(archive_name, &pkg->archive, &pkg->entry, |
1436 | &pkg->pkgname); | | 1436 | &pkg->pkgname); |
1437 | #else | | 1437 | #else |
1438 | invalid_sig = 0; | | 1438 | invalid_sig = 0; |
1439 | #endif | | 1439 | #endif |
1440 | free(archive_name); | | 1440 | free(archive_name); |
1441 | | | 1441 | |
1442 | if (pkg->archive == NULL) | | 1442 | if (pkg->archive == NULL) |
1443 | goto clean_memory; | | 1443 | goto clean_memory; |
1444 | | | 1444 | |
1445 | if (read_meta_data(pkg)) | | 1445 | if (read_meta_data(pkg)) |
1446 | goto clean_memory; | | 1446 | goto clean_memory; |
1447 | | | 1447 | |
1448 | /* Parse PLIST early, so that messages can use real package name. */ | | 1448 | /* Parse PLIST early, so that messages can use real package name. */ |
1449 | if (pkg_parse_plist(pkg)) | | 1449 | if (pkg_parse_plist(pkg)) |
1450 | goto clean_memory; | | 1450 | goto clean_memory; |
1451 | | | 1451 | |
1452 | if (check_signature(pkg, invalid_sig)) | | 1452 | if (check_signature(pkg, invalid_sig)) |
1453 | goto clean_memory; | | 1453 | goto clean_memory; |
1454 | | | 1454 | |
1455 | if (read_buildinfo(pkg)) | | 1455 | if (read_buildinfo(pkg)) |
1456 | goto clean_memory; | | 1456 | goto clean_memory; |
1457 | | | 1457 | |
1458 | if (check_pkgtools_version(pkg)) | | 1458 | if (check_pkgtools_version(pkg)) |
1459 | goto clean_memory; | | 1459 | goto clean_memory; |
1460 | | | 1460 | |
1461 | if (check_vulnerable(pkg)) | | 1461 | if (check_vulnerable(pkg)) |
1462 | goto clean_memory; | | 1462 | goto clean_memory; |
1463 | | | 1463 | |
1464 | if (check_license(pkg)) | | 1464 | if (check_license(pkg)) |
1465 | goto clean_memory; | | 1465 | goto clean_memory; |
1466 | | | 1466 | |
1467 | if (pkg->meta_data.meta_mtree != NULL) | | 1467 | if (pkg->meta_data.meta_mtree != NULL) |
1468 | warnx("mtree specification in pkg `%s' ignored", pkg->pkgname); | | 1468 | warnx("mtree specification in pkg `%s' ignored", pkg->pkgname); |
1469 | | | 1469 | |
1470 | pkg->logdir = xasprintf("%s/%s", config_pkg_dbdir, pkg->pkgname); | | 1470 | pkg->logdir = xasprintf("%s/%s", config_pkg_dbdir, pkg->pkgname); |
1471 | | | 1471 | |
1472 | if (Destdir != NULL) | | 1472 | if (Destdir != NULL) |
1473 | pkg->install_logdir = xasprintf("%s/%s", Destdir, pkg->logdir); | | 1473 | pkg->install_logdir = xasprintf("%s/%s", Destdir, pkg->logdir); |
1474 | else | | 1474 | else |
1475 | pkg->install_logdir = xstrdup(pkg->logdir); | | 1475 | pkg->install_logdir = xstrdup(pkg->logdir); |
1476 | | | 1476 | |
1477 | if (NoRecord && !Fake) { | | 1477 | if (NoRecord && !Fake) { |
1478 | const char *tmpdir; | | 1478 | const char *tmpdir; |
1479 | | | 1479 | |
1480 | tmpdir = getenv("TMPDIR"); | | 1480 | tmpdir = getenv("TMPDIR"); |
1481 | if (tmpdir == NULL) | | 1481 | if (tmpdir == NULL) |
1482 | tmpdir = "/tmp"; | | 1482 | tmpdir = "/tmp"; |
1483 | | | 1483 | |
1484 | free(pkg->install_logdir); | | 1484 | free(pkg->install_logdir); |
1485 | pkg->install_logdir = xasprintf("%s/pkg_install.XXXXXX", tmpdir); | | 1485 | pkg->install_logdir = xasprintf("%s/pkg_install.XXXXXX", tmpdir); |
1486 | /* XXX pkg_add -u... */ | | 1486 | /* XXX pkg_add -u... */ |
1487 | if (mkdtemp(pkg->install_logdir) == NULL) { | | 1487 | if (mkdtemp(pkg->install_logdir) == NULL) { |
1488 | warn("mkdtemp failed"); | | 1488 | warn("mkdtemp failed"); |
1489 | goto clean_memory; | | 1489 | goto clean_memory; |
1490 | } | | 1490 | } |
1491 | } | | 1491 | } |
1492 | | | 1492 | |
1493 | switch (check_already_installed(pkg)) { | | 1493 | switch (check_already_installed(pkg)) { |
1494 | case 0: | | 1494 | case 0: |
1495 | status = 0; | | 1495 | status = 0; |
1496 | goto clean_memory; | | 1496 | goto clean_memory; |
1497 | case 1: | | 1497 | case 1: |
1498 | break; | | 1498 | break; |
1499 | case -1: | | 1499 | case -1: |
1500 | goto clean_memory; | | 1500 | goto clean_memory; |
1501 | } | | 1501 | } |
1502 | | | 1502 | |
1503 | if (check_platform(pkg)) | | 1503 | if (check_platform(pkg)) |
1504 | goto clean_memory; | | 1504 | goto clean_memory; |
1505 | | | 1505 | |
1506 | if (check_other_installed(pkg)) | | 1506 | if (check_other_installed(pkg)) |
1507 | goto clean_memory; | | 1507 | goto clean_memory; |
1508 | | | 1508 | |
1509 | if (check_explicit_conflict(pkg)) | | 1509 | if (check_explicit_conflict(pkg)) |
1510 | goto clean_memory; | | 1510 | goto clean_memory; |
1511 | | | 1511 | |
1512 | if (check_implicit_conflict(pkg)) | | 1512 | if (check_implicit_conflict(pkg)) |
1513 | goto clean_memory; | | 1513 | goto clean_memory; |
1514 | | | 1514 | |
1515 | if (pkg->other_version != NULL) { | | 1515 | if (pkg->other_version != NULL) { |
1516 | /* | | 1516 | /* |
1517 | * Replacing an existing package. | | 1517 | * Replacing an existing package. |
1518 | * Write meta-data, get rid of the old version, | | 1518 | * Write meta-data, get rid of the old version, |
1519 | * install/update dependencies and finally extract. | | 1519 | * install/update dependencies and finally extract. |
1520 | */ | | 1520 | */ |
1521 | if (write_meta_data(pkg)) | | 1521 | if (write_meta_data(pkg)) |
1522 | goto nuke_pkgdb; | | 1522 | goto nuke_pkgdb; |
1523 | | | 1523 | |
1524 | if (start_replacing(pkg)) | | 1524 | if (start_replacing(pkg)) |
1525 | goto nuke_pkgdb; | | 1525 | goto nuke_pkgdb; |
1526 | | | 1526 | |
1527 | if (pkg->install_logdir_real) { | | 1527 | if (pkg->install_logdir_real) { |
1528 | rename(pkg->install_logdir, pkg->install_logdir_real); | | 1528 | rename(pkg->install_logdir, pkg->install_logdir_real); |
1529 | free(pkg->install_logdir); | | 1529 | free(pkg->install_logdir); |
1530 | pkg->install_logdir = pkg->install_logdir_real; | | 1530 | pkg->install_logdir = pkg->install_logdir_real; |
1531 | pkg->install_logdir_real = NULL; | | 1531 | pkg->install_logdir_real = NULL; |
1532 | } | | 1532 | } |
1533 | | | 1533 | |
1534 | if (check_dependencies(pkg)) | | 1534 | if (check_dependencies(pkg)) |
1535 | goto nuke_pkgdb; | | 1535 | goto nuke_pkgdb; |
1536 | } else { | | 1536 | } else { |
1537 | /* | | 1537 | /* |
1538 | * Normal installation. | | 1538 | * Normal installation. |
1539 | * Install/update dependencies first and | | 1539 | * Install/update dependencies first and |
1540 | * write the current package to disk afterwards. | | 1540 | * write the current package to disk afterwards. |
1541 | */ | | 1541 | */ |
1542 | if (check_dependencies(pkg)) | | 1542 | if (check_dependencies(pkg)) |
1543 | goto clean_memory; | | 1543 | goto clean_memory; |
1544 | | | 1544 | |
1545 | if (write_meta_data(pkg)) | | 1545 | if (write_meta_data(pkg)) |
1546 | goto nuke_pkgdb; | | 1546 | goto nuke_pkgdb; |
1547 | } | | 1547 | } |
1548 | | | 1548 | |
1549 | if (run_install_script(pkg, "PRE-INSTALL")) | | 1549 | if (run_install_script(pkg, "PRE-INSTALL")) |
1550 | goto nuke_pkgdb; | | 1550 | goto nuke_pkgdb; |
1551 | | | 1551 | |
1552 | if (extract_files(pkg)) | | 1552 | if (extract_files(pkg)) |
1553 | goto nuke_pkg; | | 1553 | goto nuke_pkg; |
1554 | | | 1554 | |
1555 | if (run_install_script(pkg, "POST-INSTALL")) | | 1555 | if (run_install_script(pkg, "POST-INSTALL")) |
1556 | goto nuke_pkgdb; | | 1556 | goto nuke_pkgdb; |
1557 | | | 1557 | |
1558 | /* XXX keep +INSTALL_INFO for updates? */ | | 1558 | /* XXX keep +INSTALL_INFO for updates? */ |
1559 | /* XXX keep +PRESERVE for updates? */ | | 1559 | /* XXX keep +PRESERVE for updates? */ |
1560 | if (mark_automatic) | | 1560 | if (mark_automatic) |
1561 | mark_as_automatic_installed(pkg->pkgname, 1); | | 1561 | mark_as_automatic_installed(pkg->pkgname, 1); |
1562 | | | 1562 | |
1563 | pkg_register_depends(pkg); | | 1563 | pkg_register_depends(pkg); |
1564 | | | 1564 | |
1565 | if (Verbose) | | 1565 | if (Verbose) |
1566 | printf("Package %s registered in %s\n", pkg->pkgname, pkg->install_logdir); | | 1566 | printf("Package %s registered in %s\n", pkg->pkgname, pkg->install_logdir); |
1567 | | | 1567 | |
1568 | if (pkg->meta_data.meta_display != NULL) | | 1568 | if (pkg->meta_data.meta_display != NULL) |
1569 | fputs(pkg->meta_data.meta_display, stdout); | | 1569 | fputs(pkg->meta_data.meta_display, stdout); |
1570 | | | 1570 | |
1571 | status = 0; | | 1571 | status = 0; |
1572 | goto clean_memory; | | 1572 | goto clean_memory; |
1573 | | | 1573 | |
1574 | nuke_pkg: | | 1574 | nuke_pkg: |
1575 | if (!Fake) { | | 1575 | if (!Fake) { |
1576 | if (pkg->other_version) { | | 1576 | if (pkg->other_version) { |
1577 | warnx("Updating of %s to %s failed.", | | 1577 | warnx("Updating of %s to %s failed.", |
1578 | pkg->other_version, pkg->pkgname); | | 1578 | pkg->other_version, pkg->pkgname); |
1579 | warnx("Remember to run pkg_admin rebuild-tree after fixing this."); | | 1579 | warnx("Remember to run pkg_admin rebuild-tree after fixing this."); |
1580 | } | | 1580 | } |
1581 | delete_package(FALSE, &pkg->plist, FALSE, Destdir); | | 1581 | delete_package(FALSE, &pkg->plist, FALSE, Destdir); |
1582 | } | | 1582 | } |
1583 | | | 1583 | |
1584 | nuke_pkgdb: | | 1584 | nuke_pkgdb: |
1585 | if (!Fake) { | | 1585 | if (!Fake) { |
1586 | (void) remove_files(pkg->install_logdir, "+*"); | | 1586 | (void) remove_files(pkg->install_logdir, "+*"); |
1587 | if (recursive_remove(pkg->install_logdir, 1)) | | 1587 | if (recursive_remove(pkg->install_logdir, 1)) |
1588 | warn("Couldn't remove %s", pkg->install_logdir); | | 1588 | warn("Couldn't remove %s", pkg->install_logdir); |
1589 | free(pkg->install_logdir_real); | | 1589 | free(pkg->install_logdir_real); |
1590 | free(pkg->install_logdir); | | 1590 | free(pkg->install_logdir); |
1591 | free(pkg->logdir); | | 1591 | free(pkg->logdir); |
1592 | pkg->install_logdir_real = NULL; | | 1592 | pkg->install_logdir_real = NULL; |
1593 | pkg->install_logdir = NULL; | | 1593 | pkg->install_logdir = NULL; |
1594 | pkg->logdir = NULL; | | 1594 | pkg->logdir = NULL; |
1595 | } | | 1595 | } |
1596 | | | 1596 | |
1597 | clean_memory: | | 1597 | clean_memory: |
1598 | if (pkg->logdir != NULL && NoRecord && !Fake) { | | 1598 | if (pkg->logdir != NULL && NoRecord && !Fake) { |
1599 | if (recursive_remove(pkg->install_logdir, 1)) | | 1599 | if (recursive_remove(pkg->install_logdir, 1)) |
1600 | warn("Couldn't remove %s", pkg->install_logdir); | | 1600 | warn("Couldn't remove %s", pkg->install_logdir); |
1601 | } | | 1601 | } |
1602 | free(pkg->install_prefix); | | 1602 | free(pkg->install_prefix); |
1603 | free(pkg->install_logdir_real); | | 1603 | free(pkg->install_logdir_real); |
1604 | free(pkg->install_logdir); | | 1604 | free(pkg->install_logdir); |
1605 | free(pkg->logdir); | | 1605 | free(pkg->logdir); |
1606 | free_buildinfo(pkg); | | 1606 | free_buildinfo(pkg); |
1607 | free_plist(&pkg->plist); | | 1607 | free_plist(&pkg->plist); |
1608 | free_meta_data(pkg); | | 1608 | free_meta_data(pkg); |
1609 | if (pkg->archive) | | 1609 | if (pkg->archive) |
1610 | archive_read_free(pkg->archive); | | 1610 | archive_read_free(pkg->archive); |
1611 | free(pkg->other_version); | | 1611 | free(pkg->other_version); |
1612 | free(pkg->pkgname); | | 1612 | free(pkg->pkgname); |
1613 | clean_find_archive: | | 1613 | clean_find_archive: |
1614 | free(pkg); | | 1614 | free(pkg); |
1615 | return status; | | 1615 | return status; |
1616 | } | | 1616 | } |
1617 | | | 1617 | |
1618 | int | | 1618 | int |
1619 | pkg_perform(lpkg_head_t *pkgs) | | 1619 | pkg_perform(lpkg_head_t *pkgs) |
1620 | { | | 1620 | { |
1621 | int errors = 0; | | 1621 | int errors = 0; |
1622 | lpkg_t *lpp; | | 1622 | lpkg_t *lpp; |
1623 | | | 1623 | |
1624 | while ((lpp = TAILQ_FIRST(pkgs)) != NULL) { | | 1624 | while ((lpp = TAILQ_FIRST(pkgs)) != NULL) { |
1625 | if (pkg_do(lpp->lp_name, Automatic, 1)) | | 1625 | if (pkg_do(lpp->lp_name, Automatic, 1)) |
1626 | ++errors; | | 1626 | ++errors; |
1627 | TAILQ_REMOVE(pkgs, lpp, lp_link); | | 1627 | TAILQ_REMOVE(pkgs, lpp, lp_link); |
1628 | free_lpkg(lpp); | | 1628 | free_lpkg(lpp); |
1629 | } | | 1629 | } |
1630 | | | 1630 | |
1631 | return errors; | | 1631 | return errors; |
1632 | } | | 1632 | } |