| @@ -1,1417 +1,1414 @@ | | | @@ -1,1417 +1,1414 @@ |
1 | /* $NetBSD: perform.c,v 1.104 2013/08/21 11:46:02 jperkin Exp $ */ | | 1 | /* $NetBSD: perform.c,v 1.105 2013/09/02 10:28:44 jperkin 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.104 2013/08/21 11:46:02 jperkin Exp $"); | | 9 | __RCSID("$NetBSD: perform.c,v 1.105 2013/09/02 10:28:44 jperkin 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 <stdlib.h> | | 53 | #include <stdlib.h> |
54 | #include <string.h> | | 54 | #include <string.h> |
55 | #include <unistd.h> | | 55 | #include <unistd.h> |
56 | | | 56 | |
57 | #include <archive.h> | | 57 | #include <archive.h> |
58 | #include <archive_entry.h> | | 58 | #include <archive_entry.h> |
59 | | | 59 | |
60 | #include "lib.h" | | 60 | #include "lib.h" |
61 | #include "add.h" | | 61 | #include "add.h" |
62 | #include "version.h" | | 62 | #include "version.h" |
63 | | | 63 | |
64 | struct pkg_meta { | | 64 | struct pkg_meta { |
65 | char *meta_contents; | | 65 | char *meta_contents; |
66 | char *meta_comment; | | 66 | char *meta_comment; |
67 | char *meta_desc; | | 67 | char *meta_desc; |
68 | char *meta_mtree; | | 68 | char *meta_mtree; |
69 | char *meta_build_version; | | 69 | char *meta_build_version; |
70 | char *meta_build_info; | | 70 | char *meta_build_info; |
71 | char *meta_size_pkg; | | 71 | char *meta_size_pkg; |
72 | char *meta_size_all; | | 72 | char *meta_size_all; |
73 | char *meta_required_by; | | 73 | char *meta_required_by; |
74 | char *meta_display; | | 74 | char *meta_display; |
75 | char *meta_install; | | 75 | char *meta_install; |
76 | char *meta_deinstall; | | 76 | char *meta_deinstall; |
77 | char *meta_preserve; | | 77 | char *meta_preserve; |
78 | char *meta_views; | | 78 | char *meta_views; |
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_views), VIEWS_FNAME, 0, 0444 }, | | 124 | { offsetof(struct pkg_meta, meta_views), VIEWS_FNAME, 0, 0444 }, |
125 | { offsetof(struct pkg_meta, meta_required_by), REQUIRED_BY_FNAME, 0, 0644 }, | | 125 | { offsetof(struct pkg_meta, meta_required_by), REQUIRED_BY_FNAME, 0, 0644 }, |
126 | { offsetof(struct pkg_meta, meta_installed_info), INSTALLED_INFO_FNAME, 0, 0644 }, | | 126 | { offsetof(struct pkg_meta, meta_installed_info), INSTALLED_INFO_FNAME, 0, 0644 }, |
127 | { 0, NULL, 0, 0 }, | | 127 | { 0, NULL, 0, 0 }, |
128 | }; | | 128 | }; |
129 | | | 129 | |
130 | static int pkg_do(const char *, int, int); | | 130 | static int pkg_do(const char *, int, int); |
131 | | | 131 | |
132 | static int | | 132 | static int |
133 | end_of_version(const char *opsys, const char *version_end) | | 133 | end_of_version(const char *opsys, const char *version_end) |
134 | { | | 134 | { |
135 | if (*version_end == '\0') | | 135 | if (*version_end == '\0') |
136 | return 1; | | 136 | return 1; |
137 | | | 137 | |
138 | if (strcmp(opsys, "NetBSD") == 0) { | | 138 | if (strcmp(opsys, "NetBSD") == 0) { |
139 | if (strncmp(version_end, "_ALPHA", 6) == 0 | | 139 | if (strncmp(version_end, "_ALPHA", 6) == 0 |
140 | || strncmp(version_end, "_BETA", 5) == 0 | | 140 | || strncmp(version_end, "_BETA", 5) == 0 |
141 | || strncmp(version_end, "_RC", 3) == 0 | | 141 | || strncmp(version_end, "_RC", 3) == 0 |
142 | || strncmp(version_end, "_STABLE", 7) == 0 | | 142 | || strncmp(version_end, "_STABLE", 7) == 0 |
143 | || strncmp(version_end, "_PATCH", 6) == 0) | | 143 | || strncmp(version_end, "_PATCH", 6) == 0) |
144 | return 1; | | 144 | return 1; |
145 | } | | 145 | } |
146 | | | 146 | |
147 | return 0; | | 147 | return 0; |
148 | } | | 148 | } |
149 | | | 149 | |
150 | static int | | 150 | static int |
151 | compatible_platform(const char *opsys, const char *host, const char *package) | | 151 | compatible_platform(const char *opsys, const char *host, const char *package) |
152 | { | | 152 | { |
153 | int i = 0; | | 153 | int i = 0; |
154 | | | 154 | |
155 | /* returns 1 if host and package operating system match */ | | 155 | /* returns 1 if host and package operating system match */ |
156 | if (strcmp(host, package) == 0) | | 156 | if (strcmp(host, package) == 0) |
157 | return 1; | | 157 | return 1; |
158 | | | 158 | |
159 | /* accept, if host version is a minor release of package version */ | | 159 | /* accept, if host version is a minor release of package version */ |
160 | if (strncmp(host, package, strlen(package)) == 0) | | 160 | if (strncmp(host, package, strlen(package)) == 0) |
161 | return 1; | | 161 | return 1; |
162 | | | 162 | |
163 | /* find offset of first difference */ | | 163 | /* find offset of first difference */ |
164 | for (i=0; (host[i] != '\0') && (host[i] == package[i]);) | | 164 | for (i=0; (host[i] != '\0') && (host[i] == package[i]);) |
165 | i++; | | 165 | i++; |
166 | | | 166 | |
167 | if (end_of_version(opsys, host+i) && end_of_version(opsys, package+i)) | | 167 | if (end_of_version(opsys, host+i) && end_of_version(opsys, package+i)) |
168 | return 1; | | 168 | return 1; |
169 | | | 169 | |
170 | return 0; | | 170 | return 0; |
171 | } | | 171 | } |
172 | | | 172 | |
173 | static int | | 173 | static int |
174 | mkdir_p(const char *path) | | 174 | mkdir_p(const char *path) |
175 | { | | 175 | { |
176 | char *p, *cur_end; | | 176 | char *p, *cur_end; |
177 | int done, saved_errno; | | 177 | int done, saved_errno; |
178 | struct stat sb; | | 178 | struct stat sb; |
179 | | | 179 | |
180 | /* | | 180 | /* |
181 | * Handle the easy case of direct success or | | 181 | * Handle the easy case of direct success or |
182 | * pre-existing directory first. | | 182 | * pre-existing directory first. |
183 | */ | | 183 | */ |
184 | if (mkdir(path, 0777) == 0) | | 184 | if (mkdir(path, 0777) == 0) |
185 | return 0; | | 185 | return 0; |
186 | if (stat(path, &sb) == 0) { | | 186 | if (stat(path, &sb) == 0) { |
187 | if (S_ISDIR(sb.st_mode)) | | 187 | if (S_ISDIR(sb.st_mode)) |
188 | return 0; | | 188 | return 0; |
189 | errno = ENOTDIR; | | 189 | errno = ENOTDIR; |
190 | return -1; | | 190 | return -1; |
191 | } | | 191 | } |
192 | | | 192 | |
193 | cur_end = p = xstrdup(path); | | 193 | cur_end = p = xstrdup(path); |
194 | | | 194 | |
195 | for (;;) { | | 195 | for (;;) { |
196 | /* | | 196 | /* |
197 | * First skip leading slashes either from / or | | 197 | * First skip leading slashes either from / or |
198 | * from the last iteration. | | 198 | * from the last iteration. |
199 | */ | | 199 | */ |
200 | cur_end += strspn(cur_end, "/"); | | 200 | cur_end += strspn(cur_end, "/"); |
201 | /* Find end of actual directory name. */ | | 201 | /* Find end of actual directory name. */ |
202 | cur_end += strcspn(cur_end, "/"); | | 202 | cur_end += strcspn(cur_end, "/"); |
203 | | | 203 | |
204 | /* | | 204 | /* |
205 | * Remember if this is the last component and | | 205 | * Remember if this is the last component and |
206 | * overwrite / if needed. | | 206 | * overwrite / if needed. |
207 | */ | | 207 | */ |
208 | done = (*cur_end == '\0'); | | 208 | done = (*cur_end == '\0'); |
209 | *cur_end = '\0'; | | 209 | *cur_end = '\0'; |
210 | | | 210 | |
211 | if (mkdir(p, 0777) == -1) { | | 211 | if (mkdir(p, 0777) == -1) { |
212 | saved_errno = errno; | | 212 | saved_errno = errno; |
213 | if (stat(p, &sb) == 0) { | | 213 | if (stat(p, &sb) == 0) { |
214 | if (S_ISDIR(sb.st_mode)) | | 214 | if (S_ISDIR(sb.st_mode)) |
215 | goto pass; | | 215 | goto pass; |
216 | errno = ENOTDIR; | | 216 | errno = ENOTDIR; |
217 | } else { | | 217 | } else { |
218 | errno = saved_errno; | | 218 | errno = saved_errno; |
219 | } | | 219 | } |
220 | free(p); | | 220 | free(p); |
221 | return -1; | | 221 | return -1; |
222 | } | | 222 | } |
223 | pass: | | 223 | pass: |
224 | if (done) | | 224 | if (done) |
225 | break; | | 225 | break; |
226 | *cur_end = '/'; | | 226 | *cur_end = '/'; |
227 | } | | 227 | } |
228 | | | 228 | |
229 | free(p); | | 229 | free(p); |
230 | return 0; | | 230 | return 0; |
231 | } | | 231 | } |
232 | | | 232 | |
233 | /* | | 233 | /* |
234 | * Read meta data from archive. | | 234 | * Read meta data from archive. |
235 | * Bail out if a required entry is missing or entries are in the wrong order. | | 235 | * Bail out if a required entry is missing or entries are in the wrong order. |
236 | */ | | 236 | */ |
237 | static int | | 237 | static int |
238 | read_meta_data(struct pkg_task *pkg) | | 238 | read_meta_data(struct pkg_task *pkg) |
239 | { | | 239 | { |
240 | const struct pkg_meta_desc *descr, *last_descr; | | 240 | const struct pkg_meta_desc *descr, *last_descr; |
241 | const char *fname; | | 241 | const char *fname; |
242 | char **target; | | 242 | char **target; |
243 | int64_t size; | | 243 | int64_t size; |
244 | int r, found_required; | | 244 | int r, found_required; |
245 | | | 245 | |
246 | found_required = 0; | | 246 | found_required = 0; |
247 | | | 247 | |
248 | r = ARCHIVE_OK; | | 248 | r = ARCHIVE_OK; |
249 | last_descr = 0; | | 249 | last_descr = 0; |
250 | | | 250 | |
251 | if (pkg->entry != NULL) | | 251 | if (pkg->entry != NULL) |
252 | goto skip_header; | | 252 | goto skip_header; |
253 | | | 253 | |
254 | for (;;) { | | 254 | for (;;) { |
255 | r = archive_read_next_header(pkg->archive, &pkg->entry); | | 255 | r = archive_read_next_header(pkg->archive, &pkg->entry); |
256 | if (r != ARCHIVE_OK) | | 256 | if (r != ARCHIVE_OK) |
257 | break; | | 257 | break; |
258 | skip_header: | | 258 | skip_header: |
259 | fname = archive_entry_pathname(pkg->entry); | | 259 | fname = archive_entry_pathname(pkg->entry); |
260 | | | 260 | |
261 | for (descr = pkg_meta_descriptors; descr->entry_filename; | | 261 | for (descr = pkg_meta_descriptors; descr->entry_filename; |
262 | ++descr) { | | 262 | ++descr) { |
263 | if (strcmp(descr->entry_filename, fname) == 0) | | 263 | if (strcmp(descr->entry_filename, fname) == 0) |
264 | break; | | 264 | break; |
265 | } | | 265 | } |
266 | if (descr->entry_filename == NULL) | | 266 | if (descr->entry_filename == NULL) |
267 | break; | | 267 | break; |
268 | | | 268 | |
269 | if (descr->required_file) | | 269 | if (descr->required_file) |
270 | ++found_required; | | 270 | ++found_required; |
271 | | | 271 | |
272 | target = (char **)((char *)&pkg->meta_data + | | 272 | target = (char **)((char *)&pkg->meta_data + |
273 | descr->entry_offset); | | 273 | descr->entry_offset); |
274 | if (*target) { | | 274 | if (*target) { |
275 | warnx("duplicate entry, package corrupt"); | | 275 | warnx("duplicate entry, package corrupt"); |
276 | return -1; | | 276 | return -1; |
277 | } | | 277 | } |
278 | if (descr < last_descr) { | | 278 | if (descr < last_descr) { |
279 | warnx("misordered package"); | | 279 | warnx("misordered package"); |
280 | return -1; | | 280 | return -1; |
281 | } | | 281 | } |
282 | last_descr = descr; | | 282 | last_descr = descr; |
283 | | | 283 | |
284 | size = archive_entry_size(pkg->entry); | | 284 | size = archive_entry_size(pkg->entry); |
285 | if (size > SSIZE_MAX - 1) { | | 285 | if (size > SSIZE_MAX - 1) { |
286 | warnx("package meta data too large to process"); | | 286 | warnx("package meta data too large to process"); |
287 | return -1; | | 287 | return -1; |
288 | } | | 288 | } |
289 | *target = xmalloc(size + 1); | | 289 | *target = xmalloc(size + 1); |
290 | if (archive_read_data(pkg->archive, *target, size) != size) { | | 290 | if (archive_read_data(pkg->archive, *target, size) != size) { |
291 | warnx("cannot read package meta data"); | | 291 | warnx("cannot read package meta data"); |
292 | return -1; | | 292 | return -1; |
293 | } | | 293 | } |
294 | (*target)[size] = '\0'; | | 294 | (*target)[size] = '\0'; |
295 | } | | 295 | } |
296 | | | 296 | |
297 | if (r != ARCHIVE_OK) | | 297 | if (r != ARCHIVE_OK) |
298 | pkg->entry = NULL; | | 298 | pkg->entry = NULL; |
299 | if (r == ARCHIVE_EOF) | | 299 | if (r == ARCHIVE_EOF) |
300 | r = ARCHIVE_OK; | | 300 | r = ARCHIVE_OK; |
301 | | | 301 | |
302 | for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { | | 302 | for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { |
303 | if (descr->required_file) | | 303 | if (descr->required_file) |
304 | --found_required; | | 304 | --found_required; |
305 | } | | 305 | } |
306 | | | 306 | |
307 | return !found_required && r == ARCHIVE_OK ? 0 : -1; | | 307 | return !found_required && r == ARCHIVE_OK ? 0 : -1; |
308 | } | | 308 | } |
309 | | | 309 | |
310 | /* | | 310 | /* |
311 | * Free meta data. | | 311 | * Free meta data. |
312 | */ | | 312 | */ |
313 | static void | | 313 | static void |
314 | free_meta_data(struct pkg_task *pkg) | | 314 | free_meta_data(struct pkg_task *pkg) |
315 | { | | 315 | { |
316 | const struct pkg_meta_desc *descr; | | 316 | const struct pkg_meta_desc *descr; |
317 | char **target; | | 317 | char **target; |
318 | | | 318 | |
319 | for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { | | 319 | for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { |
320 | target = (char **)((char *)&pkg->meta_data + | | 320 | target = (char **)((char *)&pkg->meta_data + |
321 | descr->entry_offset); | | 321 | descr->entry_offset); |
322 | free(*target); | | 322 | free(*target); |
323 | *target = NULL; | | 323 | *target = NULL; |
324 | } | | 324 | } |
325 | } | | 325 | } |
326 | | | 326 | |
327 | /* | | 327 | /* |
328 | * Parse PLIST and populate pkg. | | 328 | * Parse PLIST and populate pkg. |
329 | */ | | 329 | */ |
330 | static int | | 330 | static int |
331 | pkg_parse_plist(struct pkg_task *pkg) | | 331 | pkg_parse_plist(struct pkg_task *pkg) |
332 | { | | 332 | { |
333 | plist_t *p; | | 333 | plist_t *p; |
334 | | | 334 | |
335 | parse_plist(&pkg->plist, pkg->meta_data.meta_contents); | | 335 | parse_plist(&pkg->plist, pkg->meta_data.meta_contents); |
336 | if ((p = find_plist(&pkg->plist, PLIST_NAME)) == NULL) { | | 336 | if ((p = find_plist(&pkg->plist, PLIST_NAME)) == NULL) { |
337 | warnx("Invalid PLIST: missing @name"); | | 337 | warnx("Invalid PLIST: missing @name"); |
338 | return -1; | | 338 | return -1; |
339 | } | | 339 | } |
340 | if (pkg->pkgname == NULL) | | 340 | if (pkg->pkgname == NULL) |
341 | pkg->pkgname = xstrdup(p->name); | | 341 | pkg->pkgname = xstrdup(p->name); |
342 | else if (strcmp(pkg->pkgname, p->name) != 0) { | | 342 | else if (strcmp(pkg->pkgname, p->name) != 0) { |
343 | warnx("Signature and PLIST differ on package name"); | | 343 | warnx("Signature and PLIST differ on package name"); |
344 | return -1; | | 344 | return -1; |
345 | } | | 345 | } |
346 | if ((p = find_plist(&pkg->plist, PLIST_CWD)) == NULL) { | | 346 | if ((p = find_plist(&pkg->plist, PLIST_CWD)) == NULL) { |
347 | warnx("Invalid PLIST: missing @cwd"); | | 347 | warnx("Invalid PLIST: missing @cwd"); |
348 | return -1; | | 348 | return -1; |
349 | } | | 349 | } |
350 | | | 350 | |
351 | if (Prefix != NULL && | | 351 | if (Prefix != NULL && |
352 | strcmp(p->name, Prefix) != 0) { | | 352 | strcmp(p->name, Prefix) != 0) { |
353 | size_t len; | | 353 | size_t len; |
354 | | | 354 | |
355 | delete_plist(&pkg->plist, FALSE, PLIST_CWD, NULL); | | 355 | delete_plist(&pkg->plist, FALSE, PLIST_CWD, NULL); |
356 | add_plist_top(&pkg->plist, PLIST_CWD, Prefix); | | 356 | add_plist_top(&pkg->plist, PLIST_CWD, Prefix); |
357 | free(pkg->meta_data.meta_contents); | | 357 | free(pkg->meta_data.meta_contents); |
358 | stringify_plist(&pkg->plist, &pkg->meta_data.meta_contents, &len, | | 358 | stringify_plist(&pkg->plist, &pkg->meta_data.meta_contents, &len, |
359 | Prefix); | | 359 | Prefix); |
360 | pkg->prefix = Prefix; | | 360 | pkg->prefix = Prefix; |
361 | } else | | 361 | } else |
362 | pkg->prefix = p->name; | | 362 | pkg->prefix = p->name; |
363 | | | 363 | |
364 | if (Destdir != NULL) | | 364 | if (Destdir != NULL) |
365 | pkg->install_prefix = xasprintf("%s/%s", Destdir, pkg->prefix); | | 365 | pkg->install_prefix = xasprintf("%s/%s", Destdir, pkg->prefix); |
366 | else | | 366 | else |
367 | pkg->install_prefix = xstrdup(pkg->prefix); | | 367 | pkg->install_prefix = xstrdup(pkg->prefix); |
368 | | | 368 | |
369 | return 0; | | 369 | return 0; |
370 | } | | 370 | } |
371 | | | 371 | |
372 | /* | | 372 | /* |
373 | * Helper function to extract value from a string of the | | 373 | * Helper function to extract value from a string of the |
374 | * form key=value ending at eol. | | 374 | * form key=value ending at eol. |
375 | */ | | 375 | */ |
376 | static char * | | 376 | static char * |
377 | dup_value(const char *line, const char *eol) | | 377 | dup_value(const char *line, const char *eol) |
378 | { | | 378 | { |
379 | const char *key; | | 379 | const char *key; |
380 | char *val; | | 380 | char *val; |
381 | | | 381 | |
382 | key = strchr(line, '='); | | 382 | key = strchr(line, '='); |
383 | val = xmalloc(eol - key); | | 383 | val = xmalloc(eol - key); |
384 | memcpy(val, key + 1, eol - key - 1); | | 384 | memcpy(val, key + 1, eol - key - 1); |
385 | val[eol - key - 1] = '\0'; | | 385 | val[eol - key - 1] = '\0'; |
386 | return val; | | 386 | return val; |
387 | } | | 387 | } |
388 | | | 388 | |
389 | static int | | 389 | static int |
390 | check_already_installed(struct pkg_task *pkg) | | 390 | check_already_installed(struct pkg_task *pkg) |
391 | { | | 391 | { |
392 | char *filename; | | 392 | char *filename; |
393 | int fd; | | 393 | int fd; |
394 | | | 394 | |
395 | filename = pkgdb_pkg_file(pkg->pkgname, CONTENTS_FNAME); | | 395 | filename = pkgdb_pkg_file(pkg->pkgname, CONTENTS_FNAME); |
396 | fd = open(filename, O_RDONLY); | | 396 | fd = open(filename, O_RDONLY); |
397 | free(filename); | | 397 | free(filename); |
398 | if (fd == -1) | | 398 | if (fd == -1) |
399 | return 1; | | 399 | return 1; |
400 | close(fd); | | 400 | close(fd); |
401 | | | 401 | |
402 | if (ReplaceSame) { | | 402 | if (ReplaceSame) { |
403 | struct stat sb; | | 403 | struct stat sb; |
404 | | | 404 | |
405 | pkg->install_logdir_real = pkg->install_logdir; | | 405 | pkg->install_logdir_real = pkg->install_logdir; |
406 | pkg->install_logdir = xasprintf("%s.xxxxxx", pkg->install_logdir); | | 406 | pkg->install_logdir = xasprintf("%s.xxxxxx", pkg->install_logdir); |
407 | if (stat(pkg->install_logdir, &sb) == 0) { | | 407 | if (stat(pkg->install_logdir, &sb) == 0) { |
408 | warnx("package `%s' already has a temporary update " | | 408 | warnx("package `%s' already has a temporary update " |
409 | "directory `%s', remove it manually", | | 409 | "directory `%s', remove it manually", |
410 | pkg->pkgname, pkg->install_logdir); | | 410 | pkg->pkgname, pkg->install_logdir); |
411 | return -1; | | 411 | return -1; |
412 | } | | 412 | } |
413 | return 1; | | 413 | return 1; |
414 | } | | 414 | } |
415 | | | 415 | |
416 | if (Force) | | | |
417 | return 1; | | | |
418 | | | | |
419 | /* We can only arrive here for explicitly requested packages. */ | | 416 | /* We can only arrive here for explicitly requested packages. */ |
420 | if (!Automatic && is_automatic_installed(pkg->pkgname)) { | | 417 | if (!Automatic && is_automatic_installed(pkg->pkgname)) { |
421 | if (Fake || | | 418 | if (Fake || |
422 | mark_as_automatic_installed(pkg->pkgname, 0) == 0) | | 419 | mark_as_automatic_installed(pkg->pkgname, 0) == 0) |
423 | warnx("package `%s' was already installed as " | | 420 | warnx("package `%s' was already installed as " |
424 | "dependency, now marked as installed " | | 421 | "dependency, now marked as installed " |
425 | "manually", pkg->pkgname); | | 422 | "manually", pkg->pkgname); |
426 | } else { | | 423 | } else { |
427 | warnx("package `%s' already recorded as installed", | | 424 | warnx("package `%s' already recorded as installed", |
428 | pkg->pkgname); | | 425 | pkg->pkgname); |
429 | } | | 426 | } |
430 | return 0; | | 427 | return 0; |
431 | | | 428 | |
432 | } | | 429 | } |
433 | | | 430 | |
434 | static int | | 431 | static int |
435 | check_other_installed(struct pkg_task *pkg) | | 432 | check_other_installed(struct pkg_task *pkg) |
436 | { | | 433 | { |
437 | FILE *f, *f_pkg; | | 434 | FILE *f, *f_pkg; |
438 | size_t len; | | 435 | size_t len; |
439 | char *pkgbase, *iter, *filename; | | 436 | char *pkgbase, *iter, *filename; |
440 | package_t plist; | | 437 | package_t plist; |
441 | plist_t *p; | | 438 | plist_t *p; |
442 | int status; | | 439 | int status; |
443 | | | 440 | |
444 | if (pkg->install_logdir_real) { | | 441 | if (pkg->install_logdir_real) { |
445 | pkg->other_version = xstrdup(pkg->pkgname); | | 442 | pkg->other_version = xstrdup(pkg->pkgname); |
446 | return 0; | | 443 | return 0; |
447 | } | | 444 | } |
448 | | | 445 | |
449 | pkgbase = xstrdup(pkg->pkgname); | | 446 | pkgbase = xstrdup(pkg->pkgname); |
450 | | | 447 | |
451 | if ((iter = strrchr(pkgbase, '-')) == NULL) { | | 448 | if ((iter = strrchr(pkgbase, '-')) == NULL) { |
452 | free(pkgbase); | | 449 | free(pkgbase); |
453 | warnx("Invalid package name %s", pkg->pkgname); | | 450 | warnx("Invalid package name %s", pkg->pkgname); |
454 | return -1; | | 451 | return -1; |
455 | } | | 452 | } |
456 | *iter = '\0'; | | 453 | *iter = '\0'; |
457 | pkg->other_version = find_best_matching_installed_pkg(pkgbase); | | 454 | pkg->other_version = find_best_matching_installed_pkg(pkgbase); |
458 | free(pkgbase); | | 455 | free(pkgbase); |
459 | if (pkg->other_version == NULL) | | 456 | if (pkg->other_version == NULL) |
460 | return 0; | | 457 | return 0; |
461 | | | 458 | |
462 | if (!Replace) { | | 459 | if (!Replace) { |
463 | /* XXX This is redundant to the implicit conflict check. */ | | 460 | /* XXX This is redundant to the implicit conflict check. */ |
464 | warnx("A different version of %s is already installed: %s", | | 461 | warnx("A different version of %s is already installed: %s", |
465 | pkg->pkgname, pkg->other_version); | | 462 | pkg->pkgname, pkg->other_version); |
466 | return -1; | | 463 | return -1; |
467 | } | | 464 | } |
468 | | | 465 | |
469 | filename = pkgdb_pkg_file(pkg->other_version, REQUIRED_BY_FNAME); | | 466 | filename = pkgdb_pkg_file(pkg->other_version, REQUIRED_BY_FNAME); |
470 | errno = 0; | | 467 | errno = 0; |
471 | f = fopen(filename, "r"); | | 468 | f = fopen(filename, "r"); |
472 | free(filename); | | 469 | free(filename); |
473 | if (f == NULL) { | | 470 | if (f == NULL) { |
474 | if (errno == ENOENT) { | | 471 | if (errno == ENOENT) { |
475 | /* No packages depend on this, so everything is well. */ | | 472 | /* No packages depend on this, so everything is well. */ |
476 | return 0; | | 473 | return 0; |
477 | } | | 474 | } |
478 | warnx("Can't open +REQUIRED_BY of %s", pkg->other_version); | | 475 | warnx("Can't open +REQUIRED_BY of %s", pkg->other_version); |
479 | return -1; | | 476 | return -1; |
480 | } | | 477 | } |
481 | | | 478 | |
482 | status = 0; | | 479 | status = 0; |
483 | | | 480 | |
484 | while ((iter = fgetln(f, &len)) != NULL) { | | 481 | while ((iter = fgetln(f, &len)) != NULL) { |
485 | if (iter[len - 1] == '\n') | | 482 | if (iter[len - 1] == '\n') |
486 | iter[len - 1] = '\0'; | | 483 | iter[len - 1] = '\0'; |
487 | filename = pkgdb_pkg_file(iter, CONTENTS_FNAME); | | 484 | filename = pkgdb_pkg_file(iter, CONTENTS_FNAME); |
488 | if ((f_pkg = fopen(filename, "r")) == NULL) { | | 485 | if ((f_pkg = fopen(filename, "r")) == NULL) { |
489 | warnx("Can't open +CONTENTS of depending package %s", | | 486 | warnx("Can't open +CONTENTS of depending package %s", |
490 | iter); | | 487 | iter); |
491 | fclose(f); | | 488 | fclose(f); |
492 | return -1; | | 489 | return -1; |
493 | } | | 490 | } |
494 | read_plist(&plist, f_pkg); | | 491 | read_plist(&plist, f_pkg); |
495 | fclose(f_pkg); | | 492 | fclose(f_pkg); |
496 | for (p = plist.head; p != NULL; p = p->next) { | | 493 | for (p = plist.head; p != NULL; p = p->next) { |
497 | if (p->type == PLIST_IGNORE) { | | 494 | if (p->type == PLIST_IGNORE) { |
498 | p = p->next; | | 495 | p = p->next; |
499 | continue; | | 496 | continue; |
500 | } else if (p->type != PLIST_PKGDEP) | | 497 | } else if (p->type != PLIST_PKGDEP) |
501 | continue; | | 498 | continue; |
502 | /* | | 499 | /* |
503 | * XXX This is stricter than necessary. | | 500 | * XXX This is stricter than necessary. |
504 | * XXX One pattern might be fulfilled by | | 501 | * XXX One pattern might be fulfilled by |
505 | * XXX a different package and still need this | | 502 | * XXX a different package and still need this |
506 | * XXX one for a different pattern. | | 503 | * XXX one for a different pattern. |
507 | */ | | 504 | */ |
508 | if (pkg_match(p->name, pkg->other_version) == 0) | | 505 | if (pkg_match(p->name, pkg->other_version) == 0) |
509 | continue; | | 506 | continue; |
510 | if (pkg_match(p->name, pkg->pkgname) == 1) | | 507 | if (pkg_match(p->name, pkg->pkgname) == 1) |
511 | continue; /* Both match, ok. */ | | 508 | continue; /* Both match, ok. */ |
512 | warnx("Dependency of %s fulfilled by %s, but not by %s", | | 509 | warnx("Dependency of %s fulfilled by %s, but not by %s", |
513 | iter, pkg->other_version, pkg->pkgname); | | 510 | iter, pkg->other_version, pkg->pkgname); |
514 | if (!ForceDepending) | | 511 | if (!ForceDepending) |
515 | status = -1; | | 512 | status = -1; |
516 | break; | | 513 | break; |
517 | } | | 514 | } |
518 | free_plist(&plist); | | 515 | free_plist(&plist); |
519 | } | | 516 | } |
520 | | | 517 | |
521 | fclose(f); | | 518 | fclose(f); |
522 | | | 519 | |
523 | return status; | | 520 | return status; |
524 | } | | 521 | } |
525 | | | 522 | |
526 | /* | | 523 | /* |
527 | * Read package build information from meta data. | | 524 | * Read package build information from meta data. |
528 | */ | | 525 | */ |
529 | static int | | 526 | static int |
530 | read_buildinfo(struct pkg_task *pkg) | | 527 | read_buildinfo(struct pkg_task *pkg) |
531 | { | | 528 | { |
532 | const char *data, *eol, *next_line; | | 529 | const char *data, *eol, *next_line; |
533 | | | 530 | |
534 | data = pkg->meta_data.meta_build_info; | | 531 | data = pkg->meta_data.meta_build_info; |
535 | | | 532 | |
536 | for (; data != NULL && *data != '\0'; data = next_line) { | | 533 | for (; data != NULL && *data != '\0'; data = next_line) { |
537 | if ((eol = strchr(data, '\n')) == NULL) { | | 534 | if ((eol = strchr(data, '\n')) == NULL) { |
538 | eol = data + strlen(data); | | 535 | eol = data + strlen(data); |
539 | next_line = eol; | | 536 | next_line = eol; |
540 | } else | | 537 | } else |
541 | next_line = eol + 1; | | 538 | next_line = eol + 1; |
542 | | | 539 | |
543 | if (strncmp(data, "OPSYS=", 6) == 0) | | 540 | if (strncmp(data, "OPSYS=", 6) == 0) |
544 | pkg->buildinfo[BI_OPSYS] = dup_value(data, eol); | | 541 | pkg->buildinfo[BI_OPSYS] = dup_value(data, eol); |
545 | else if (strncmp(data, "OS_VERSION=", 11) == 0) | | 542 | else if (strncmp(data, "OS_VERSION=", 11) == 0) |
546 | pkg->buildinfo[BI_OS_VERSION] = dup_value(data, eol); | | 543 | pkg->buildinfo[BI_OS_VERSION] = dup_value(data, eol); |
547 | else if (strncmp(data, "MACHINE_ARCH=", 13) == 0) | | 544 | else if (strncmp(data, "MACHINE_ARCH=", 13) == 0) |
548 | pkg->buildinfo[BI_MACHINE_ARCH] = dup_value(data, eol); | | 545 | pkg->buildinfo[BI_MACHINE_ARCH] = dup_value(data, eol); |
549 | else if (strncmp(data, "IGNORE_RECOMMENDED=", 19) == 0) | | 546 | else if (strncmp(data, "IGNORE_RECOMMENDED=", 19) == 0) |
550 | pkg->buildinfo[BI_IGNORE_RECOMMENDED] = dup_value(data, | | 547 | pkg->buildinfo[BI_IGNORE_RECOMMENDED] = dup_value(data, |
551 | eol); | | 548 | eol); |
552 | else if (strncmp(data, "USE_ABI_DEPENDS=", 16) == 0) | | 549 | else if (strncmp(data, "USE_ABI_DEPENDS=", 16) == 0) |
553 | pkg->buildinfo[BI_USE_ABI_DEPENDS] = dup_value(data, | | 550 | pkg->buildinfo[BI_USE_ABI_DEPENDS] = dup_value(data, |
554 | eol); | | 551 | eol); |
555 | else if (strncmp(data, "LICENSE=", 8) == 0) | | 552 | else if (strncmp(data, "LICENSE=", 8) == 0) |
556 | pkg->buildinfo[BI_LICENSE] = dup_value(data, eol); | | 553 | pkg->buildinfo[BI_LICENSE] = dup_value(data, eol); |
557 | else if (strncmp(data, "PKGTOOLS_VERSION=", 17) == 0) | | 554 | else if (strncmp(data, "PKGTOOLS_VERSION=", 17) == 0) |
558 | pkg->buildinfo[BI_PKGTOOLS_VERSION] = dup_value(data, | | 555 | pkg->buildinfo[BI_PKGTOOLS_VERSION] = dup_value(data, |
559 | eol); | | 556 | eol); |
560 | } | | 557 | } |
561 | if (pkg->buildinfo[BI_OPSYS] == NULL || | | 558 | if (pkg->buildinfo[BI_OPSYS] == NULL || |
562 | pkg->buildinfo[BI_OS_VERSION] == NULL || | | 559 | pkg->buildinfo[BI_OS_VERSION] == NULL || |
563 | pkg->buildinfo[BI_MACHINE_ARCH] == NULL) { | | 560 | pkg->buildinfo[BI_MACHINE_ARCH] == NULL) { |
564 | warnx("Not all required build information are present."); | | 561 | warnx("Not all required build information are present."); |
565 | return -1; | | 562 | return -1; |
566 | } | | 563 | } |
567 | | | 564 | |
568 | if ((pkg->buildinfo[BI_USE_ABI_DEPENDS] != NULL && | | 565 | if ((pkg->buildinfo[BI_USE_ABI_DEPENDS] != NULL && |
569 | strcasecmp(pkg->buildinfo[BI_USE_ABI_DEPENDS], "YES") != 0) || | | 566 | strcasecmp(pkg->buildinfo[BI_USE_ABI_DEPENDS], "YES") != 0) || |
570 | (pkg->buildinfo[BI_IGNORE_RECOMMENDED] != NULL && | | 567 | (pkg->buildinfo[BI_IGNORE_RECOMMENDED] != NULL && |
571 | strcasecmp(pkg->buildinfo[BI_IGNORE_RECOMMENDED], "NO") != 0)) { | | 568 | strcasecmp(pkg->buildinfo[BI_IGNORE_RECOMMENDED], "NO") != 0)) { |
572 | warnx("%s was built to ignore ABI dependencies", pkg->pkgname); | | 569 | warnx("%s was built to ignore ABI dependencies", pkg->pkgname); |
573 | } | | 570 | } |
574 | | | 571 | |
575 | return 0; | | 572 | return 0; |
576 | } | | 573 | } |
577 | | | 574 | |
578 | /* | | 575 | /* |
579 | * Free buildinfo. | | 576 | * Free buildinfo. |
580 | */ | | 577 | */ |
581 | static void | | 578 | static void |
582 | free_buildinfo(struct pkg_task *pkg) | | 579 | free_buildinfo(struct pkg_task *pkg) |
583 | { | | 580 | { |
584 | size_t i; | | 581 | size_t i; |
585 | | | 582 | |
586 | for (i = 0; i < BI_ENUM_COUNT; ++i) { | | 583 | for (i = 0; i < BI_ENUM_COUNT; ++i) { |
587 | free(pkg->buildinfo[i]); | | 584 | free(pkg->buildinfo[i]); |
588 | pkg->buildinfo[i] = NULL; | | 585 | pkg->buildinfo[i] = NULL; |
589 | } | | 586 | } |
590 | } | | 587 | } |
591 | | | 588 | |
592 | /* | | 589 | /* |
593 | * Write meta data files to pkgdb after creating the directory. | | 590 | * Write meta data files to pkgdb after creating the directory. |
594 | */ | | 591 | */ |
595 | static int | | 592 | static int |
596 | write_meta_data(struct pkg_task *pkg) | | 593 | write_meta_data(struct pkg_task *pkg) |
597 | { | | 594 | { |
598 | const struct pkg_meta_desc *descr; | | 595 | const struct pkg_meta_desc *descr; |
599 | char *filename, **target; | | 596 | char *filename, **target; |
600 | size_t len; | | 597 | size_t len; |
601 | ssize_t ret; | | 598 | ssize_t ret; |
602 | int fd; | | 599 | int fd; |
603 | | | 600 | |
604 | if (Fake) | | 601 | if (Fake) |
605 | return 0; | | 602 | return 0; |
606 | | | 603 | |
607 | if (mkdir_p(pkg->install_logdir)) { | | 604 | if (mkdir_p(pkg->install_logdir)) { |
608 | warn("Can't create pkgdb entry: %s", pkg->install_logdir); | | 605 | warn("Can't create pkgdb entry: %s", pkg->install_logdir); |
609 | return -1; | | 606 | return -1; |
610 | } | | 607 | } |
611 | | | 608 | |
612 | for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { | | 609 | for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { |
613 | target = (char **)((char *)&pkg->meta_data + | | 610 | target = (char **)((char *)&pkg->meta_data + |
614 | descr->entry_offset); | | 611 | descr->entry_offset); |
615 | if (*target == NULL) | | 612 | if (*target == NULL) |
616 | continue; | | 613 | continue; |
617 | filename = xasprintf("%s/%s", pkg->install_logdir, | | 614 | filename = xasprintf("%s/%s", pkg->install_logdir, |
618 | descr->entry_filename); | | 615 | descr->entry_filename); |
619 | (void)unlink(filename); | | 616 | (void)unlink(filename); |
620 | fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, descr->perm); | | 617 | fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, descr->perm); |
621 | if (fd == -1) { | | 618 | if (fd == -1) { |
622 | warn("Can't open meta data file: %s", filename); | | 619 | warn("Can't open meta data file: %s", filename); |
623 | return -1; | | 620 | return -1; |
624 | } | | 621 | } |
625 | len = strlen(*target); | | 622 | len = strlen(*target); |
626 | do { | | 623 | do { |
627 | ret = write(fd, *target, len); | | 624 | ret = write(fd, *target, len); |
628 | if (ret == -1) { | | 625 | if (ret == -1) { |
629 | warn("Can't write meta data file: %s", | | 626 | warn("Can't write meta data file: %s", |
630 | filename); | | 627 | filename); |
631 | free(filename); | | 628 | free(filename); |
632 | close(fd); | | 629 | close(fd); |
633 | return -1; | | 630 | return -1; |
634 | } | | 631 | } |
635 | len -= ret; | | 632 | len -= ret; |
636 | } while (ret > 0); | | 633 | } while (ret > 0); |
637 | if (close(fd) == -1) { | | 634 | if (close(fd) == -1) { |
638 | warn("Can't close meta data file: %s", filename); | | 635 | warn("Can't close meta data file: %s", filename); |
639 | free(filename); | | 636 | free(filename); |
640 | return -1; | | 637 | return -1; |
641 | } | | 638 | } |
642 | free(filename); | | 639 | free(filename); |
643 | } | | 640 | } |
644 | | | 641 | |
645 | return 0; | | 642 | return 0; |
646 | } | | 643 | } |
647 | | | 644 | |
648 | /* | | 645 | /* |
649 | * Helper function for extract_files. | | 646 | * Helper function for extract_files. |
650 | */ | | 647 | */ |
651 | static int | | 648 | static int |
652 | copy_data_to_disk(struct archive *reader, struct archive *writer, | | 649 | copy_data_to_disk(struct archive *reader, struct archive *writer, |
653 | const char *filename) | | 650 | const char *filename) |
654 | { | | 651 | { |
655 | int r; | | 652 | int r; |
656 | const void *buff; | | 653 | const void *buff; |
657 | size_t size; | | 654 | size_t size; |
658 | off_t offset; | | 655 | off_t offset; |
659 | | | 656 | |
660 | for (;;) { | | 657 | for (;;) { |
661 | r = archive_read_data_block(reader, &buff, &size, &offset); | | 658 | r = archive_read_data_block(reader, &buff, &size, &offset); |
662 | if (r == ARCHIVE_EOF) | | 659 | if (r == ARCHIVE_EOF) |
663 | return 0; | | 660 | return 0; |
664 | if (r != ARCHIVE_OK) { | | 661 | if (r != ARCHIVE_OK) { |
665 | warnx("Read error for %s: %s", filename, | | 662 | warnx("Read error for %s: %s", filename, |
666 | archive_error_string(reader)); | | 663 | archive_error_string(reader)); |
667 | return -1; | | 664 | return -1; |
668 | } | | 665 | } |
669 | r = archive_write_data_block(writer, buff, size, offset); | | 666 | r = archive_write_data_block(writer, buff, size, offset); |
670 | if (r != ARCHIVE_OK) { | | 667 | if (r != ARCHIVE_OK) { |
671 | warnx("Write error for %s: %s", filename, | | 668 | warnx("Write error for %s: %s", filename, |
672 | archive_error_string(writer)); | | 669 | archive_error_string(writer)); |
673 | return -1; | | 670 | return -1; |
674 | } | | 671 | } |
675 | } | | 672 | } |
676 | } | | 673 | } |
677 | | | 674 | |
678 | /* | | 675 | /* |
679 | * Extract package. | | 676 | * Extract package. |
680 | * Any misordered, missing or unlisted file in the package is an error. | | 677 | * Any misordered, missing or unlisted file in the package is an error. |
681 | */ | | 678 | */ |
682 | | | 679 | |
683 | static const int extract_flags = ARCHIVE_EXTRACT_OWNER | | | 680 | static const int extract_flags = ARCHIVE_EXTRACT_OWNER | |
684 | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_UNLINK | | | 681 | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_UNLINK | |
685 | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR; | | 682 | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR; |
686 | | | 683 | |
687 | static int | | 684 | static int |
688 | extract_files(struct pkg_task *pkg) | | 685 | extract_files(struct pkg_task *pkg) |
689 | { | | 686 | { |
690 | char cmd[MaxPathSize]; | | 687 | char cmd[MaxPathSize]; |
691 | const char *owner, *group, *permissions; | | 688 | const char *owner, *group, *permissions; |
692 | struct archive *writer; | | 689 | struct archive *writer; |
693 | int r; | | 690 | int r; |
694 | plist_t *p; | | 691 | plist_t *p; |
695 | const char *last_file; | | 692 | const char *last_file; |
696 | char *fullpath; | | 693 | char *fullpath; |
697 | | | 694 | |
698 | if (Fake) | | 695 | if (Fake) |
699 | return 0; | | 696 | return 0; |
700 | | | 697 | |
701 | if (mkdir_p(pkg->install_prefix)) { | | 698 | if (mkdir_p(pkg->install_prefix)) { |
702 | warn("Can't create prefix: %s", pkg->install_prefix); | | 699 | warn("Can't create prefix: %s", pkg->install_prefix); |
703 | return -1; | | 700 | return -1; |
704 | } | | 701 | } |
705 | | | 702 | |
706 | if (!NoRecord && !pkgdb_open(ReadWrite)) { | | 703 | if (!NoRecord && !pkgdb_open(ReadWrite)) { |
707 | warn("Can't open pkgdb for writing"); | | 704 | warn("Can't open pkgdb for writing"); |
708 | return -1; | | 705 | return -1; |
709 | } | | 706 | } |
710 | | | 707 | |
711 | if (chdir(pkg->install_prefix) == -1) { | | 708 | if (chdir(pkg->install_prefix) == -1) { |
712 | warn("Can't change into prefix: %s", pkg->install_prefix); | | 709 | warn("Can't change into prefix: %s", pkg->install_prefix); |
713 | return -1; | | 710 | return -1; |
714 | } | | 711 | } |
715 | | | 712 | |
716 | writer = archive_write_disk_new(); | | 713 | writer = archive_write_disk_new(); |
717 | archive_write_disk_set_options(writer, extract_flags); | | 714 | archive_write_disk_set_options(writer, extract_flags); |
718 | archive_write_disk_set_standard_lookup(writer); | | 715 | archive_write_disk_set_standard_lookup(writer); |
719 | | | 716 | |
720 | owner = NULL; | | 717 | owner = NULL; |
721 | group = NULL; | | 718 | group = NULL; |
722 | permissions = NULL; | | 719 | permissions = NULL; |
723 | last_file = NULL; | | 720 | last_file = NULL; |
724 | | | 721 | |
725 | r = -1; | | 722 | r = -1; |
726 | | | 723 | |
727 | for (p = pkg->plist.head; p != NULL; p = p->next) { | | 724 | for (p = pkg->plist.head; p != NULL; p = p->next) { |
728 | switch (p->type) { | | 725 | switch (p->type) { |
729 | case PLIST_FILE: | | 726 | case PLIST_FILE: |
730 | last_file = p->name; | | 727 | last_file = p->name; |
731 | if (pkg->entry == NULL) { | | 728 | if (pkg->entry == NULL) { |
732 | warnx("PLIST entry not in package (%s)", | | 729 | warnx("PLIST entry not in package (%s)", |
733 | archive_entry_pathname(pkg->entry)); | | 730 | archive_entry_pathname(pkg->entry)); |
734 | goto out; | | 731 | goto out; |
735 | } | | 732 | } |
736 | if (strcmp(p->name, archive_entry_pathname(pkg->entry))) { | | 733 | if (strcmp(p->name, archive_entry_pathname(pkg->entry))) { |
737 | warnx("PLIST entry and package don't match (%s vs %s)", | | 734 | warnx("PLIST entry and package don't match (%s vs %s)", |
738 | p->name, archive_entry_pathname(pkg->entry)); | | 735 | p->name, archive_entry_pathname(pkg->entry)); |
739 | goto out; | | 736 | goto out; |
740 | } | | 737 | } |
741 | fullpath = xasprintf("%s/%s", pkg->prefix, p->name); | | 738 | fullpath = xasprintf("%s/%s", pkg->prefix, p->name); |
742 | pkgdb_store(fullpath, pkg->pkgname); | | 739 | pkgdb_store(fullpath, pkg->pkgname); |
743 | free(fullpath); | | 740 | free(fullpath); |
744 | if (Verbose) | | 741 | if (Verbose) |
745 | printf("%s", p->name); | | 742 | printf("%s", p->name); |
746 | break; | | 743 | break; |
747 | | | 744 | |
748 | case PLIST_PKGDIR: | | 745 | case PLIST_PKGDIR: |
749 | fullpath = xasprintf("%s/%s", pkg->prefix, p->name); | | 746 | fullpath = xasprintf("%s/%s", pkg->prefix, p->name); |
750 | mkdir_p(fullpath); | | 747 | mkdir_p(fullpath); |
751 | free(fullpath); | | 748 | free(fullpath); |
752 | add_pkgdir(pkg->pkgname, pkg->prefix, p->name); | | 749 | add_pkgdir(pkg->pkgname, pkg->prefix, p->name); |
753 | continue; | | 750 | continue; |
754 | | | 751 | |
755 | case PLIST_CMD: | | 752 | case PLIST_CMD: |
756 | if (format_cmd(cmd, sizeof(cmd), p->name, pkg->prefix, last_file)) | | 753 | if (format_cmd(cmd, sizeof(cmd), p->name, pkg->prefix, last_file)) |
757 | return -1; | | 754 | return -1; |
758 | printf("Executing '%s'\n", cmd); | | 755 | printf("Executing '%s'\n", cmd); |
759 | if (!Fake && system(cmd)) | | 756 | if (!Fake && system(cmd)) |
760 | warnx("command '%s' failed", cmd); /* XXX bail out? */ | | 757 | warnx("command '%s' failed", cmd); /* XXX bail out? */ |
761 | continue; | | 758 | continue; |
762 | | | 759 | |
763 | case PLIST_CHMOD: | | 760 | case PLIST_CHMOD: |
764 | permissions = p->name; | | 761 | permissions = p->name; |
765 | continue; | | 762 | continue; |
766 | | | 763 | |
767 | case PLIST_CHOWN: | | 764 | case PLIST_CHOWN: |
768 | owner = p->name; | | 765 | owner = p->name; |
769 | continue; | | 766 | continue; |
770 | | | 767 | |
771 | case PLIST_CHGRP: | | 768 | case PLIST_CHGRP: |
772 | group = p->name; | | 769 | group = p->name; |
773 | continue; | | 770 | continue; |
774 | | | 771 | |
775 | case PLIST_IGNORE: | | 772 | case PLIST_IGNORE: |
776 | p = p->next; | | 773 | p = p->next; |
777 | continue; | | 774 | continue; |
778 | | | 775 | |
779 | default: | | 776 | default: |
780 | continue; | | 777 | continue; |
781 | } | | 778 | } |
782 | | | 779 | |
783 | r = archive_write_header(writer, pkg->entry); | | 780 | r = archive_write_header(writer, pkg->entry); |
784 | if (r != ARCHIVE_OK) { | | 781 | if (r != ARCHIVE_OK) { |
785 | warnx("Failed to write %s for %s: %s", | | 782 | warnx("Failed to write %s for %s: %s", |
786 | archive_entry_pathname(pkg->entry), | | 783 | archive_entry_pathname(pkg->entry), |
787 | pkg->pkgname, | | 784 | pkg->pkgname, |
788 | archive_error_string(writer)); | | 785 | archive_error_string(writer)); |
789 | goto out; | | 786 | goto out; |
790 | } | | 787 | } |
791 | | | 788 | |
792 | if (owner != NULL) | | 789 | if (owner != NULL) |
793 | archive_entry_set_uname(pkg->entry, owner); | | 790 | archive_entry_set_uname(pkg->entry, owner); |
794 | if (group != NULL) | | 791 | if (group != NULL) |
795 | archive_entry_set_uname(pkg->entry, group); | | 792 | archive_entry_set_uname(pkg->entry, group); |
796 | if (permissions != NULL) { | | 793 | if (permissions != NULL) { |
797 | mode_t mode; | | 794 | mode_t mode; |
798 | | | 795 | |
799 | mode = archive_entry_mode(pkg->entry); | | 796 | mode = archive_entry_mode(pkg->entry); |
800 | mode = getmode(setmode(permissions), mode); | | 797 | mode = getmode(setmode(permissions), mode); |
801 | archive_entry_set_mode(pkg->entry, mode); | | 798 | archive_entry_set_mode(pkg->entry, mode); |
802 | } | | 799 | } |
803 | | | 800 | |
804 | r = copy_data_to_disk(pkg->archive, writer, | | 801 | r = copy_data_to_disk(pkg->archive, writer, |
805 | archive_entry_pathname(pkg->entry)); | | 802 | archive_entry_pathname(pkg->entry)); |
806 | if (r) | | 803 | if (r) |
807 | goto out; | | 804 | goto out; |
808 | if (Verbose) | | 805 | if (Verbose) |
809 | printf("\n"); | | 806 | printf("\n"); |
810 | | | 807 | |
811 | r = archive_read_next_header(pkg->archive, &pkg->entry); | | 808 | r = archive_read_next_header(pkg->archive, &pkg->entry); |
812 | if (r == ARCHIVE_EOF) { | | 809 | if (r == ARCHIVE_EOF) { |
813 | pkg->entry = NULL; | | 810 | pkg->entry = NULL; |
814 | continue; | | 811 | continue; |
815 | } | | 812 | } |
816 | if (r != ARCHIVE_OK) { | | 813 | if (r != ARCHIVE_OK) { |
817 | warnx("Failed to read from archive for %s: %s", | | 814 | warnx("Failed to read from archive for %s: %s", |
818 | pkg->pkgname, | | 815 | pkg->pkgname, |
819 | archive_error_string(pkg->archive)); | | 816 | archive_error_string(pkg->archive)); |
820 | goto out; | | 817 | goto out; |
821 | } | | 818 | } |
822 | } | | 819 | } |
823 | | | 820 | |
824 | if (pkg->entry != NULL) { | | 821 | if (pkg->entry != NULL) { |
825 | warnx("Package contains entries not in PLIST: %s", | | 822 | warnx("Package contains entries not in PLIST: %s", |
826 | archive_entry_pathname(pkg->entry)); | | 823 | archive_entry_pathname(pkg->entry)); |
827 | goto out; | | 824 | goto out; |
828 | } | | 825 | } |
829 | | | 826 | |
830 | r = 0; | | 827 | r = 0; |
831 | | | 828 | |
832 | out: | | 829 | out: |
833 | if (!NoRecord) | | 830 | if (!NoRecord) |
834 | pkgdb_close(); | | 831 | pkgdb_close(); |
835 | archive_write_close(writer); | | 832 | archive_write_close(writer); |
836 | archive_write_finish(writer); | | 833 | archive_write_finish(writer); |
837 | | | 834 | |
838 | return r; | | 835 | return r; |
839 | } | | 836 | } |
840 | | | 837 | |
841 | /* | | 838 | /* |
842 | * Register dependencies after sucessfully installing the package. | | 839 | * Register dependencies after sucessfully installing the package. |
843 | */ | | 840 | */ |
844 | static void | | 841 | static void |
845 | pkg_register_depends(struct pkg_task *pkg) | | 842 | pkg_register_depends(struct pkg_task *pkg) |
846 | { | | 843 | { |
847 | int fd; | | 844 | int fd; |
848 | size_t text_len, i; | | 845 | size_t text_len, i; |
849 | char *required_by, *text; | | 846 | char *required_by, *text; |
850 | | | 847 | |
851 | if (Fake) | | 848 | if (Fake) |
852 | return; | | 849 | return; |
853 | | | 850 | |
854 | text = xasprintf("%s\n", pkg->pkgname); | | 851 | text = xasprintf("%s\n", pkg->pkgname); |
855 | text_len = strlen(text); | | 852 | text_len = strlen(text); |
856 | | | 853 | |
857 | for (i = 0; i < pkg->dep_length; ++i) { | | 854 | for (i = 0; i < pkg->dep_length; ++i) { |
858 | required_by = pkgdb_pkg_file(pkg->dependencies[i], REQUIRED_BY_FNAME); | | 855 | required_by = pkgdb_pkg_file(pkg->dependencies[i], REQUIRED_BY_FNAME); |
859 | | | 856 | |
860 | fd = open(required_by, O_WRONLY | O_APPEND | O_CREAT, 0644); | | 857 | fd = open(required_by, O_WRONLY | O_APPEND | O_CREAT, 0644); |
861 | if (fd == -1) { | | 858 | if (fd == -1) { |
862 | warn("can't open dependency file '%s'," | | 859 | warn("can't open dependency file '%s'," |
863 | "registration is incomplete!", required_by); | | 860 | "registration is incomplete!", required_by); |
864 | } else if (write(fd, text, text_len) != (ssize_t)text_len) { | | 861 | } else if (write(fd, text, text_len) != (ssize_t)text_len) { |
865 | warn("can't write to dependency file `%s'", required_by); | | 862 | warn("can't write to dependency file `%s'", required_by); |
866 | close(fd); | | 863 | close(fd); |
867 | } else if (close(fd) == -1) | | 864 | } else if (close(fd) == -1) |
868 | warn("cannot close file %s", required_by); | | 865 | warn("cannot close file %s", required_by); |
869 | | | 866 | |
870 | free(required_by); | | 867 | free(required_by); |
871 | } | | 868 | } |
872 | | | 869 | |
873 | free(text); | | 870 | free(text); |
874 | } | | 871 | } |
875 | | | 872 | |
876 | /* | | 873 | /* |
877 | * Reduce the result from uname(3) to a canonical form. | | 874 | * Reduce the result from uname(3) to a canonical form. |
878 | */ | | 875 | */ |
879 | static void | | 876 | static void |
880 | normalise_platform(struct utsname *host_name) | | 877 | normalise_platform(struct utsname *host_name) |
881 | { | | 878 | { |
882 | #ifdef NUMERIC_VERSION_ONLY | | 879 | #ifdef NUMERIC_VERSION_ONLY |
883 | size_t span; | | 880 | size_t span; |
884 | | | 881 | |
885 | span = strspn(host_name->release, "0123456789."); | | 882 | span = strspn(host_name->release, "0123456789."); |
886 | host_name->release[span] = '\0'; | | 883 | host_name->release[span] = '\0'; |
887 | #endif | | 884 | #endif |
888 | } | | 885 | } |
889 | | | 886 | |
890 | /* | | 887 | /* |
891 | * Check build platform of the package against local host. | | 888 | * Check build platform of the package against local host. |
892 | */ | | 889 | */ |
893 | static int | | 890 | static int |
894 | check_platform(struct pkg_task *pkg) | | 891 | check_platform(struct pkg_task *pkg) |
895 | { | | 892 | { |
896 | struct utsname host_uname; | | 893 | struct utsname host_uname; |
897 | const char *effective_arch; | | 894 | const char *effective_arch; |
898 | int fatal; | | 895 | int fatal; |
899 | | | 896 | |
900 | if (uname(&host_uname) < 0) { | | 897 | if (uname(&host_uname) < 0) { |
901 | if (Force) { | | 898 | if (Force) { |
902 | warnx("uname() failed, continuing."); | | 899 | warnx("uname() failed, continuing."); |
903 | return 0; | | 900 | return 0; |
904 | } else { | | 901 | } else { |
905 | warnx("uname() failed, aborting."); | | 902 | warnx("uname() failed, aborting."); |
906 | return -1; | | 903 | return -1; |
907 | } | | 904 | } |
908 | } | | 905 | } |
909 | | | 906 | |
910 | normalise_platform(&host_uname); | | 907 | normalise_platform(&host_uname); |
911 | | | 908 | |
912 | if (OverrideMachine != NULL) | | 909 | if (OverrideMachine != NULL) |
913 | effective_arch = OverrideMachine; | | 910 | effective_arch = OverrideMachine; |
914 | else | | 911 | else |
915 | effective_arch = MACHINE_ARCH; | | 912 | effective_arch = MACHINE_ARCH; |
916 | | | 913 | |
917 | /* If either the OS or arch are different, bomb */ | | 914 | /* If either the OS or arch are different, bomb */ |
918 | if (strcmp(OPSYS_NAME, pkg->buildinfo[BI_OPSYS]) || | | 915 | if (strcmp(OPSYS_NAME, pkg->buildinfo[BI_OPSYS]) || |
919 | strcmp(effective_arch, pkg->buildinfo[BI_MACHINE_ARCH]) != 0) | | 916 | strcmp(effective_arch, pkg->buildinfo[BI_MACHINE_ARCH]) != 0) |
920 | fatal = 1; | | 917 | fatal = 1; |
921 | else | | 918 | else |
922 | fatal = 0; | | 919 | fatal = 0; |
923 | | | 920 | |
924 | if (fatal || | | 921 | if (fatal || |
925 | compatible_platform(OPSYS_NAME, host_uname.release, | | 922 | compatible_platform(OPSYS_NAME, host_uname.release, |
926 | pkg->buildinfo[BI_OS_VERSION]) != 1) { | | 923 | pkg->buildinfo[BI_OS_VERSION]) != 1) { |
927 | warnx("Warning: package `%s' was built for a platform:", | | 924 | warnx("Warning: package `%s' was built for a platform:", |
928 | pkg->pkgname); | | 925 | pkg->pkgname); |
929 | warnx("%s/%s %s (pkg) vs. %s/%s %s (this host)", | | 926 | warnx("%s/%s %s (pkg) vs. %s/%s %s (this host)", |
930 | pkg->buildinfo[BI_OPSYS], | | 927 | pkg->buildinfo[BI_OPSYS], |
931 | pkg->buildinfo[BI_MACHINE_ARCH], | | 928 | pkg->buildinfo[BI_MACHINE_ARCH], |
932 | pkg->buildinfo[BI_OS_VERSION], | | 929 | pkg->buildinfo[BI_OS_VERSION], |
933 | OPSYS_NAME, | | 930 | OPSYS_NAME, |
934 | effective_arch, | | 931 | effective_arch, |
935 | host_uname.release); | | 932 | host_uname.release); |
936 | if (!Force && fatal) | | 933 | if (!Force && fatal) |
937 | return -1; | | 934 | return -1; |
938 | } | | 935 | } |
939 | return 0; | | 936 | return 0; |
940 | } | | 937 | } |
941 | | | 938 | |
942 | static int | | 939 | static int |
943 | check_pkgtools_version(struct pkg_task *pkg) | | 940 | check_pkgtools_version(struct pkg_task *pkg) |
944 | { | | 941 | { |
945 | const char *val = pkg->buildinfo[BI_PKGTOOLS_VERSION]; | | 942 | const char *val = pkg->buildinfo[BI_PKGTOOLS_VERSION]; |
946 | int version; | | 943 | int version; |
947 | | | 944 | |
948 | if (val == NULL) { | | 945 | if (val == NULL) { |
949 | warnx("Warning: package `%s' lacks pkg_install version data", | | 946 | warnx("Warning: package `%s' lacks pkg_install version data", |
950 | pkg->pkgname); | | 947 | pkg->pkgname); |
951 | return 0; | | 948 | return 0; |
952 | } | | 949 | } |
953 | | | 950 | |
954 | if (strlen(val) != 8 || strspn(val, "0123456789") != 8) { | | 951 | if (strlen(val) != 8 || strspn(val, "0123456789") != 8) { |
955 | warnx("Warning: package `%s' contains an invalid pkg_install version", | | 952 | warnx("Warning: package `%s' contains an invalid pkg_install version", |
956 | pkg->pkgname); | | 953 | pkg->pkgname); |
957 | return Force ? 0 : -1; | | 954 | return Force ? 0 : -1; |
958 | } | | 955 | } |
959 | version = atoi(val); | | 956 | version = atoi(val); |
960 | if (version > PKGTOOLS_VERSION) { | | 957 | if (version > PKGTOOLS_VERSION) { |
961 | warnx("%s: package `%s' was built with a newer pkg_install version", | | 958 | warnx("%s: package `%s' was built with a newer pkg_install version", |
962 | Force ? "Warning" : "Error", pkg->pkgname); | | 959 | Force ? "Warning" : "Error", pkg->pkgname); |
963 | return Force ? 0 : -1; | | 960 | return Force ? 0 : -1; |
964 | } | | 961 | } |
965 | return 0; | | 962 | return 0; |
966 | } | | 963 | } |
967 | | | 964 | |
968 | /* | | 965 | /* |
969 | * Run the install script. | | 966 | * Run the install script. |
970 | */ | | 967 | */ |
971 | static int | | 968 | static int |
972 | run_install_script(struct pkg_task *pkg, const char *argument) | | 969 | run_install_script(struct pkg_task *pkg, const char *argument) |
973 | { | | 970 | { |
974 | int ret; | | 971 | int ret; |
975 | char *filename; | | 972 | char *filename; |
976 | | | 973 | |
977 | if (pkg->meta_data.meta_install == NULL || NoInstall) | | 974 | if (pkg->meta_data.meta_install == NULL || NoInstall) |
978 | return 0; | | 975 | return 0; |
979 | | | 976 | |
980 | if (Destdir != NULL) | | 977 | if (Destdir != NULL) |
981 | setenv(PKG_DESTDIR_VNAME, Destdir, 1); | | 978 | setenv(PKG_DESTDIR_VNAME, Destdir, 1); |
982 | setenv(PKG_PREFIX_VNAME, pkg->prefix, 1); | | 979 | setenv(PKG_PREFIX_VNAME, pkg->prefix, 1); |
983 | setenv(PKG_METADATA_DIR_VNAME, pkg->logdir, 1); | | 980 | setenv(PKG_METADATA_DIR_VNAME, pkg->logdir, 1); |
984 | setenv(PKG_REFCOUNT_DBDIR_VNAME, config_pkg_refcount_dbdir, 1); | | 981 | setenv(PKG_REFCOUNT_DBDIR_VNAME, config_pkg_refcount_dbdir, 1); |
985 | | | 982 | |
986 | if (Verbose) | | 983 | if (Verbose) |
987 | printf("Running install with PRE-INSTALL for %s.\n", pkg->pkgname); | | 984 | printf("Running install with PRE-INSTALL for %s.\n", pkg->pkgname); |
988 | if (Fake) | | 985 | if (Fake) |
989 | return 0; | | 986 | return 0; |
990 | | | 987 | |
991 | filename = pkgdb_pkg_file(pkg->pkgname, INSTALL_FNAME); | | 988 | filename = pkgdb_pkg_file(pkg->pkgname, INSTALL_FNAME); |
992 | | | 989 | |
993 | ret = 0; | | 990 | ret = 0; |
994 | errno = 0; | | 991 | errno = 0; |
995 | if (fcexec(pkg->install_logdir, filename, pkg->pkgname, argument, | | 992 | if (fcexec(pkg->install_logdir, filename, pkg->pkgname, argument, |
996 | (void *)NULL)) { | | 993 | (void *)NULL)) { |
997 | if (errno != 0) | | 994 | if (errno != 0) |
998 | warn("exec of install script failed"); | | 995 | warn("exec of install script failed"); |
999 | else | | 996 | else |
1000 | warnx("install script returned error status"); | | 997 | warnx("install script returned error status"); |
1001 | ret = -1; | | 998 | ret = -1; |
1002 | } | | 999 | } |
1003 | free(filename); | | 1000 | free(filename); |
1004 | | | 1001 | |
1005 | return ret; | | 1002 | return ret; |
1006 | } | | 1003 | } |
1007 | | | 1004 | |
1008 | struct find_conflict_data { | | 1005 | struct find_conflict_data { |
1009 | const char *pkg; | | 1006 | const char *pkg; |
1010 | const char *old_pkg; | | 1007 | const char *old_pkg; |
1011 | const char *pattern; | | 1008 | const char *pattern; |
1012 | }; | | 1009 | }; |
1013 | | | 1010 | |
1014 | static int | | 1011 | static int |
1015 | check_explicit_conflict_iter(const char *cur_pkg, void *cookie) | | 1012 | check_explicit_conflict_iter(const char *cur_pkg, void *cookie) |
1016 | { | | 1013 | { |
1017 | struct find_conflict_data *data = cookie; | | 1014 | struct find_conflict_data *data = cookie; |
1018 | | | 1015 | |
1019 | if (data->old_pkg && strcmp(data->old_pkg, cur_pkg) == 0) | | 1016 | if (data->old_pkg && strcmp(data->old_pkg, cur_pkg) == 0) |
1020 | return 0; | | 1017 | return 0; |
1021 | | | 1018 | |
1022 | warnx("Package `%s' conflicts with `%s', and `%s' is installed.", | | 1019 | warnx("Package `%s' conflicts with `%s', and `%s' is installed.", |
1023 | data->pkg, data->pattern, cur_pkg); | | 1020 | data->pkg, data->pattern, cur_pkg); |
1024 | | | 1021 | |
1025 | return 1; | | 1022 | return 1; |
1026 | } | | 1023 | } |
1027 | | | 1024 | |
1028 | static int | | 1025 | static int |
1029 | check_explicit_conflict(struct pkg_task *pkg) | | 1026 | check_explicit_conflict(struct pkg_task *pkg) |
1030 | { | | 1027 | { |
1031 | struct find_conflict_data data; | | 1028 | struct find_conflict_data data; |
1032 | char *installed, *installed_pattern; | | 1029 | char *installed, *installed_pattern; |
1033 | plist_t *p; | | 1030 | plist_t *p; |
1034 | int status; | | 1031 | int status; |
1035 | | | 1032 | |
1036 | status = 0; | | 1033 | status = 0; |
1037 | | | 1034 | |
1038 | for (p = pkg->plist.head; p != NULL; p = p->next) { | | 1035 | for (p = pkg->plist.head; p != NULL; p = p->next) { |
1039 | if (p->type == PLIST_IGNORE) { | | 1036 | if (p->type == PLIST_IGNORE) { |
1040 | p = p->next; | | 1037 | p = p->next; |
1041 | continue; | | 1038 | continue; |
1042 | } | | 1039 | } |
1043 | if (p->type != PLIST_PKGCFL) | | 1040 | if (p->type != PLIST_PKGCFL) |
1044 | continue; | | 1041 | continue; |
1045 | data.pkg = pkg->pkgname; | | 1042 | data.pkg = pkg->pkgname; |
1046 | data.old_pkg = pkg->other_version; | | 1043 | data.old_pkg = pkg->other_version; |
1047 | data.pattern = p->name; | | 1044 | data.pattern = p->name; |
1048 | status |= match_installed_pkgs(p->name, | | 1045 | status |= match_installed_pkgs(p->name, |
1049 | check_explicit_conflict_iter, &data); | | 1046 | check_explicit_conflict_iter, &data); |
1050 | } | | 1047 | } |
1051 | | | 1048 | |
1052 | if (some_installed_package_conflicts_with(pkg->pkgname, | | 1049 | if (some_installed_package_conflicts_with(pkg->pkgname, |
1053 | pkg->other_version, &installed, &installed_pattern)) { | | 1050 | pkg->other_version, &installed, &installed_pattern)) { |
1054 | warnx("Installed package `%s' conflicts with `%s' when trying to install `%s'.", | | 1051 | warnx("Installed package `%s' conflicts with `%s' when trying to install `%s'.", |
1055 | installed, installed_pattern, pkg->pkgname); | | 1052 | installed, installed_pattern, pkg->pkgname); |
1056 | free(installed); | | 1053 | free(installed); |
1057 | free(installed_pattern); | | 1054 | free(installed_pattern); |
1058 | status |= -1; | | 1055 | status |= -1; |
1059 | } | | 1056 | } |
1060 | | | 1057 | |
1061 | return status; | | 1058 | return status; |
1062 | } | | 1059 | } |
1063 | | | 1060 | |
1064 | static int | | 1061 | static int |
1065 | check_implicit_conflict(struct pkg_task *pkg) | | 1062 | check_implicit_conflict(struct pkg_task *pkg) |
1066 | { | | 1063 | { |
1067 | plist_t *p; | | 1064 | plist_t *p; |
1068 | char *fullpath, *existing; | | 1065 | char *fullpath, *existing; |
1069 | int status; | | 1066 | int status; |
1070 | | | 1067 | |
1071 | if (!pkgdb_open(ReadOnly)) { | | 1068 | if (!pkgdb_open(ReadOnly)) { |
1072 | #if notyet /* XXX empty pkgdb without database? */ | | 1069 | #if notyet /* XXX empty pkgdb without database? */ |
1073 | warn("Can't open pkgdb for reading"); | | 1070 | warn("Can't open pkgdb for reading"); |
1074 | return -1; | | 1071 | return -1; |
1075 | #else | | 1072 | #else |
1076 | return 0; | | 1073 | return 0; |
1077 | #endif | | 1074 | #endif |
1078 | } | | 1075 | } |
1079 | | | 1076 | |
1080 | status = 0; | | 1077 | status = 0; |
1081 | | | 1078 | |
1082 | for (p = pkg->plist.head; p != NULL; p = p->next) { | | 1079 | for (p = pkg->plist.head; p != NULL; p = p->next) { |
1083 | if (p->type == PLIST_IGNORE) { | | 1080 | if (p->type == PLIST_IGNORE) { |
1084 | p = p->next; | | 1081 | p = p->next; |
1085 | continue; | | 1082 | continue; |
1086 | } else if (p->type != PLIST_FILE) | | 1083 | } else if (p->type != PLIST_FILE) |
1087 | continue; | | 1084 | continue; |
1088 | | | 1085 | |
1089 | fullpath = xasprintf("%s/%s", pkg->prefix, p->name); | | 1086 | fullpath = xasprintf("%s/%s", pkg->prefix, p->name); |
1090 | existing = pkgdb_retrieve(fullpath); | | 1087 | existing = pkgdb_retrieve(fullpath); |
1091 | free(fullpath); | | 1088 | free(fullpath); |
1092 | if (existing == NULL) | | 1089 | if (existing == NULL) |
1093 | continue; | | 1090 | continue; |
1094 | if (pkg->other_version != NULL && | | 1091 | if (pkg->other_version != NULL && |
1095 | strcmp(pkg->other_version, existing) == 0) | | 1092 | strcmp(pkg->other_version, existing) == 0) |
1096 | continue; | | 1093 | continue; |
1097 | | | 1094 | |
1098 | warnx("Conflicting PLIST with %s: %s", existing, p->name); | | 1095 | warnx("Conflicting PLIST with %s: %s", existing, p->name); |
1099 | if (!Force) { | | 1096 | if (!Force) { |
1100 | status = -1; | | 1097 | status = -1; |
1101 | if (!Verbose) | | 1098 | if (!Verbose) |
1102 | break; | | 1099 | break; |
1103 | } | | 1100 | } |
1104 | } | | 1101 | } |
1105 | | | 1102 | |
1106 | pkgdb_close(); | | 1103 | pkgdb_close(); |
1107 | return status; | | 1104 | return status; |
1108 | } | | 1105 | } |
1109 | | | 1106 | |
1110 | static int | | 1107 | static int |
1111 | check_dependencies(struct pkg_task *pkg) | | 1108 | check_dependencies(struct pkg_task *pkg) |
1112 | { | | 1109 | { |
1113 | plist_t *p; | | 1110 | plist_t *p; |
1114 | char *best_installed; | | 1111 | char *best_installed; |
1115 | int status; | | 1112 | int status; |
1116 | size_t i; | | 1113 | size_t i; |
1117 | | | 1114 | |
1118 | status = 0; | | 1115 | status = 0; |
1119 | | | 1116 | |
1120 | for (p = pkg->plist.head; p != NULL; p = p->next) { | | 1117 | for (p = pkg->plist.head; p != NULL; p = p->next) { |
1121 | if (p->type == PLIST_IGNORE) { | | 1118 | if (p->type == PLIST_IGNORE) { |
1122 | p = p->next; | | 1119 | p = p->next; |
1123 | continue; | | 1120 | continue; |
1124 | } else if (p->type != PLIST_PKGDEP) | | 1121 | } else if (p->type != PLIST_PKGDEP) |
1125 | continue; | | 1122 | continue; |
1126 | | | 1123 | |
1127 | best_installed = find_best_matching_installed_pkg(p->name); | | 1124 | best_installed = find_best_matching_installed_pkg(p->name); |
1128 | | | 1125 | |
1129 | if (best_installed == NULL) { | | 1126 | if (best_installed == NULL) { |
1130 | /* XXX check cyclic dependencies? */ | | 1127 | /* XXX check cyclic dependencies? */ |
1131 | if (Fake || NoRecord) { | | 1128 | if (Fake || NoRecord) { |
1132 | if (!Force) { | | 1129 | if (!Force) { |
1133 | warnx("Missing dependency %s\n", | | 1130 | warnx("Missing dependency %s\n", |
1134 | p->name); | | 1131 | p->name); |
1135 | status = -1; | | 1132 | status = -1; |
1136 | break; | | 1133 | break; |
1137 | } | | 1134 | } |
1138 | warnx("Missing dependency %s, continuing", | | 1135 | warnx("Missing dependency %s, continuing", |
1139 | p->name); | | 1136 | p->name); |
1140 | continue; | | 1137 | continue; |
1141 | } | | 1138 | } |
1142 | if (pkg_do(p->name, 1, 0)) { | | 1139 | if (pkg_do(p->name, 1, 0)) { |
1143 | if (ForceDepends) { | | 1140 | if (ForceDepends) { |
1144 | warnx("Can't install dependency %s, " | | 1141 | warnx("Can't install dependency %s, " |
1145 | "continuing", p->name); | | 1142 | "continuing", p->name); |
1146 | continue; | | 1143 | continue; |
1147 | } else { | | 1144 | } else { |
1148 | warnx("Can't install dependency %s", | | 1145 | warnx("Can't install dependency %s", |
1149 | p->name); | | 1146 | p->name); |
1150 | status = -1; | | 1147 | status = -1; |
1151 | break; | | 1148 | break; |
1152 | } | | 1149 | } |
1153 | } | | 1150 | } |
1154 | best_installed = find_best_matching_installed_pkg(p->name); | | 1151 | best_installed = find_best_matching_installed_pkg(p->name); |
1155 | if (best_installed == NULL && ForceDepends) { | | 1152 | if (best_installed == NULL && ForceDepends) { |
1156 | warnx("Missing dependency %s ignored", p->name); | | 1153 | warnx("Missing dependency %s ignored", p->name); |
1157 | continue; | | 1154 | continue; |
1158 | } else if (best_installed == NULL) { | | 1155 | } else if (best_installed == NULL) { |
1159 | warnx("Just installed dependency %s disappeared", p->name); | | 1156 | warnx("Just installed dependency %s disappeared", p->name); |
1160 | status = -1; | | 1157 | status = -1; |
1161 | break; | | 1158 | break; |
1162 | } | | 1159 | } |
1163 | } | | 1160 | } |
1164 | for (i = 0; i < pkg->dep_length; ++i) { | | 1161 | for (i = 0; i < pkg->dep_length; ++i) { |
1165 | if (strcmp(best_installed, pkg->dependencies[i]) == 0) | | 1162 | if (strcmp(best_installed, pkg->dependencies[i]) == 0) |
1166 | break; | | 1163 | break; |
1167 | } | | 1164 | } |
1168 | if (i < pkg->dep_length) { | | 1165 | if (i < pkg->dep_length) { |
1169 | /* Already used as dependency, so skip it. */ | | 1166 | /* Already used as dependency, so skip it. */ |
1170 | free(best_installed); | | 1167 | free(best_installed); |
1171 | continue; | | 1168 | continue; |
1172 | } | | 1169 | } |
1173 | if (pkg->dep_length + 1 >= pkg->dep_allocated) { | | 1170 | if (pkg->dep_length + 1 >= pkg->dep_allocated) { |
1174 | char **tmp; | | 1171 | char **tmp; |
1175 | pkg->dep_allocated = 2 * pkg->dep_allocated + 1; | | 1172 | pkg->dep_allocated = 2 * pkg->dep_allocated + 1; |
1176 | pkg->dependencies = xrealloc(pkg->dependencies, | | 1173 | pkg->dependencies = xrealloc(pkg->dependencies, |
1177 | pkg->dep_allocated * sizeof(*tmp)); | | 1174 | pkg->dep_allocated * sizeof(*tmp)); |
1178 | } | | 1175 | } |
1179 | pkg->dependencies[pkg->dep_length++] = best_installed; | | 1176 | pkg->dependencies[pkg->dep_length++] = best_installed; |
1180 | } | | 1177 | } |
1181 | | | 1178 | |
1182 | return status; | | 1179 | return status; |
1183 | } | | 1180 | } |
1184 | | | 1181 | |
1185 | /* | | 1182 | /* |
1186 | * If this package uses pkg_views, register it in the default view. | | 1183 | * If this package uses pkg_views, register it in the default view. |
1187 | */ | | 1184 | */ |
1188 | static void | | 1185 | static void |
1189 | pkg_register_views(struct pkg_task *pkg) | | 1186 | pkg_register_views(struct pkg_task *pkg) |
1190 | { | | 1187 | { |
1191 | if (Fake || NoView || pkg->meta_data.meta_views == NULL) | | 1188 | if (Fake || NoView || pkg->meta_data.meta_views == NULL) |
1192 | return; | | 1189 | return; |
1193 | | | 1190 | |
1194 | if (Verbose) { | | 1191 | if (Verbose) { |
1195 | printf("%s/pkg_view -d %s %s%s %s%s %sadd %s\n", | | 1192 | printf("%s/pkg_view -d %s %s%s %s%s %sadd %s\n", |
1196 | BINDIR, pkgdb_get_dir(), | | 1193 | BINDIR, pkgdb_get_dir(), |
1197 | View ? "-w " : "", View ? View : "", | | 1194 | View ? "-w " : "", View ? View : "", |
1198 | Viewbase ? "-W " : "", Viewbase ? Viewbase : "", | | 1195 | Viewbase ? "-W " : "", Viewbase ? Viewbase : "", |
1199 | Verbose ? "-v " : "", pkg->pkgname); | | 1196 | Verbose ? "-v " : "", pkg->pkgname); |
1200 | } | | 1197 | } |
1201 | | | 1198 | |
1202 | fexec_skipempty(BINDIR "/pkg_view", "-d", pkgdb_get_dir(), | | 1199 | fexec_skipempty(BINDIR "/pkg_view", "-d", pkgdb_get_dir(), |
1203 | View ? "-w " : "", View ? View : "", | | 1200 | View ? "-w " : "", View ? View : "", |
1204 | Viewbase ? "-W " : "", Viewbase ? Viewbase : "", | | 1201 | Viewbase ? "-W " : "", Viewbase ? Viewbase : "", |
1205 | Verbose ? "-v " : "", "add", pkg->pkgname, | | 1202 | Verbose ? "-v " : "", "add", pkg->pkgname, |
1206 | (void *)NULL); | | 1203 | (void *)NULL); |
1207 | } | | 1204 | } |
1208 | | | 1205 | |
1209 | static int | | 1206 | static int |
1210 | preserve_meta_data_file(struct pkg_task *pkg, const char *name) | | 1207 | preserve_meta_data_file(struct pkg_task *pkg, const char *name) |
1211 | { | | 1208 | { |
1212 | char *old_file, *new_file; | | 1209 | char *old_file, *new_file; |
1213 | int rv; | | 1210 | int rv; |
1214 | | | 1211 | |
1215 | if (Fake) | | 1212 | if (Fake) |
1216 | return 0; | | 1213 | return 0; |
1217 | | | 1214 | |
1218 | old_file = pkgdb_pkg_file(pkg->other_version, name); | | 1215 | old_file = pkgdb_pkg_file(pkg->other_version, name); |
1219 | new_file = xasprintf("%s/%s", pkg->install_logdir, name); | | 1216 | new_file = xasprintf("%s/%s", pkg->install_logdir, name); |
1220 | rv = 0; | | 1217 | rv = 0; |
1221 | if (rename(old_file, new_file) == -1 && errno != ENOENT) { | | 1218 | if (rename(old_file, new_file) == -1 && errno != ENOENT) { |
1222 | warn("Can't move %s from %s to %s", name, old_file, new_file); | | 1219 | warn("Can't move %s from %s to %s", name, old_file, new_file); |
1223 | rv = -1; | | 1220 | rv = -1; |
1224 | } | | 1221 | } |
1225 | free(old_file); | | 1222 | free(old_file); |
1226 | free(new_file); | | 1223 | free(new_file); |
1227 | return rv; | | 1224 | return rv; |
1228 | } | | 1225 | } |
1229 | | | 1226 | |
1230 | static int | | 1227 | static int |
1231 | start_replacing(struct pkg_task *pkg) | | 1228 | start_replacing(struct pkg_task *pkg) |
1232 | { | | 1229 | { |
1233 | if (preserve_meta_data_file(pkg, REQUIRED_BY_FNAME)) | | 1230 | if (preserve_meta_data_file(pkg, REQUIRED_BY_FNAME)) |
1234 | return -1; | | 1231 | return -1; |
1235 | | | 1232 | |
1236 | if (preserve_meta_data_file(pkg, PRESERVE_FNAME)) | | 1233 | if (preserve_meta_data_file(pkg, PRESERVE_FNAME)) |
1237 | return -1; | | 1234 | return -1; |
1238 | | | 1235 | |
1239 | if (pkg->meta_data.meta_installed_info == NULL && | | 1236 | if (pkg->meta_data.meta_installed_info == NULL && |
1240 | preserve_meta_data_file(pkg, INSTALLED_INFO_FNAME)) | | 1237 | preserve_meta_data_file(pkg, INSTALLED_INFO_FNAME)) |
1241 | return -1; | | 1238 | return -1; |
1242 | | | 1239 | |
1243 | if (Verbose || Fake) { | | 1240 | if (Verbose || Fake) { |
1244 | printf("%s/pkg_delete -K %s -p %s%s%s '%s'\n", | | 1241 | printf("%s/pkg_delete -K %s -p %s%s%s '%s'\n", |
1245 | BINDIR, pkgdb_get_dir(), pkg->prefix, | | 1242 | BINDIR, pkgdb_get_dir(), pkg->prefix, |
1246 | Destdir ? " -P ": "", Destdir ? Destdir : "", | | 1243 | Destdir ? " -P ": "", Destdir ? Destdir : "", |
1247 | pkg->other_version); | | 1244 | pkg->other_version); |
1248 | } | | 1245 | } |
1249 | if (!Fake) | | 1246 | if (!Fake) |
1250 | fexec_skipempty(BINDIR "/pkg_delete", "-K", pkgdb_get_dir(), | | 1247 | fexec_skipempty(BINDIR "/pkg_delete", "-K", pkgdb_get_dir(), |
1251 | "-p", pkg->prefix, | | 1248 | "-p", pkg->prefix, |
1252 | Destdir ? "-P": "", Destdir ? Destdir : "", | | 1249 | Destdir ? "-P": "", Destdir ? Destdir : "", |
1253 | pkg->other_version, NULL); | | 1250 | pkg->other_version, NULL); |
1254 | | | 1251 | |
1255 | /* XXX Check return value and do what? */ | | 1252 | /* XXX Check return value and do what? */ |
1256 | return 0; | | 1253 | return 0; |
1257 | } | | 1254 | } |
1258 | | | 1255 | |
1259 | static int check_input(const char *line, size_t len) | | 1256 | static int check_input(const char *line, size_t len) |
1260 | { | | 1257 | { |
1261 | if (line == NULL || len == 0) | | 1258 | if (line == NULL || len == 0) |
1262 | return 1; | | 1259 | return 1; |
1263 | switch (*line) { | | 1260 | switch (*line) { |
1264 | case 'Y': | | 1261 | case 'Y': |
1265 | case 'y': | | 1262 | case 'y': |
1266 | case 'T': | | 1263 | case 'T': |
1267 | case 't': | | 1264 | case 't': |
1268 | case '1': | | 1265 | case '1': |
1269 | return 0; | | 1266 | return 0; |
1270 | default: | | 1267 | default: |
1271 | return 1; | | 1268 | return 1; |
1272 | } | | 1269 | } |
1273 | } | | 1270 | } |
1274 | | | 1271 | |
1275 | static int | | 1272 | static int |
1276 | check_signature(struct pkg_task *pkg, int invalid_sig) | | 1273 | check_signature(struct pkg_task *pkg, int invalid_sig) |
1277 | { | | 1274 | { |
1278 | char *line; | | 1275 | char *line; |
1279 | size_t len; | | 1276 | size_t len; |
1280 | | | 1277 | |
1281 | if (strcasecmp(verified_installation, "never") == 0) | | 1278 | if (strcasecmp(verified_installation, "never") == 0) |
1282 | return 0; | | 1279 | return 0; |
1283 | if (strcasecmp(verified_installation, "always") == 0) { | | 1280 | if (strcasecmp(verified_installation, "always") == 0) { |
1284 | if (invalid_sig) | | 1281 | if (invalid_sig) |
1285 | warnx("No valid signature found, rejected"); | | 1282 | warnx("No valid signature found, rejected"); |
1286 | return invalid_sig; | | 1283 | return invalid_sig; |
1287 | } | | 1284 | } |
1288 | if (strcasecmp(verified_installation, "trusted") == 0) { | | 1285 | if (strcasecmp(verified_installation, "trusted") == 0) { |
1289 | if (!invalid_sig) | | 1286 | if (!invalid_sig) |
1290 | return 0; | | 1287 | return 0; |
1291 | fprintf(stderr, "No valid signature found for %s.\n", | | 1288 | fprintf(stderr, "No valid signature found for %s.\n", |
1292 | pkg->pkgname); | | 1289 | pkg->pkgname); |
1293 | fprintf(stderr, | | 1290 | fprintf(stderr, |
1294 | "Do you want to proceed with the installation [y/n]?\n"); | | 1291 | "Do you want to proceed with the installation [y/n]?\n"); |
1295 | line = fgetln(stdin, &len); | | 1292 | line = fgetln(stdin, &len); |
1296 | if (check_input(line, len)) { | | 1293 | if (check_input(line, len)) { |
1297 | fprintf(stderr, "Cancelling installation\n"); | | 1294 | fprintf(stderr, "Cancelling installation\n"); |
1298 | return 1; | | 1295 | return 1; |
1299 | } | | 1296 | } |
1300 | return 0; | | 1297 | return 0; |
1301 | } | | 1298 | } |
1302 | if (strcasecmp(verified_installation, "interactive") == 0) { | | 1299 | if (strcasecmp(verified_installation, "interactive") == 0) { |
1303 | fprintf(stderr, "Do you want to proceed with " | | 1300 | fprintf(stderr, "Do you want to proceed with " |
1304 | "the installation of %s [y/n]?\n", pkg->pkgname); | | 1301 | "the installation of %s [y/n]?\n", pkg->pkgname); |
1305 | line = fgetln(stdin, &len); | | 1302 | line = fgetln(stdin, &len); |
1306 | if (check_input(line, len)) { | | 1303 | if (check_input(line, len)) { |
1307 | fprintf(stderr, "Cancelling installation\n"); | | 1304 | fprintf(stderr, "Cancelling installation\n"); |
1308 | return 1; | | 1305 | return 1; |
1309 | } | | 1306 | } |
1310 | return 0; | | 1307 | return 0; |
1311 | } | | 1308 | } |
1312 | warnx("Unknown value of configuration variable VERIFIED_INSTALLATION"); | | 1309 | warnx("Unknown value of configuration variable VERIFIED_INSTALLATION"); |
1313 | return 1; | | 1310 | return 1; |
1314 | } | | 1311 | } |
1315 | | | 1312 | |
1316 | static int | | 1313 | static int |
1317 | check_vulnerable(struct pkg_task *pkg) | | 1314 | check_vulnerable(struct pkg_task *pkg) |
1318 | { | | 1315 | { |
1319 | static struct pkg_vulnerabilities *pv; | | 1316 | static struct pkg_vulnerabilities *pv; |
1320 | int require_check; | | 1317 | int require_check; |
1321 | char *line; | | 1318 | char *line; |
1322 | size_t len; | | 1319 | size_t len; |
1323 | | | 1320 | |
1324 | if (strcasecmp(check_vulnerabilities, "never") == 0) | | 1321 | if (strcasecmp(check_vulnerabilities, "never") == 0) |
1325 | return 0; | | 1322 | return 0; |
1326 | else if (strcasecmp(check_vulnerabilities, "always") == 0) | | 1323 | else if (strcasecmp(check_vulnerabilities, "always") == 0) |
1327 | require_check = 1; | | 1324 | require_check = 1; |
1328 | else if (strcasecmp(check_vulnerabilities, "interactive") == 0) | | 1325 | else if (strcasecmp(check_vulnerabilities, "interactive") == 0) |
1329 | require_check = 0; | | 1326 | require_check = 0; |
1330 | else { | | 1327 | else { |
1331 | warnx("Unknown value of the configuration variable" | | 1328 | warnx("Unknown value of the configuration variable" |
1332 | "CHECK_VULNERABILITIES"); | | 1329 | "CHECK_VULNERABILITIES"); |
1333 | return 1; | | 1330 | return 1; |
1334 | } | | 1331 | } |
1335 | | | 1332 | |
1336 | if (pv == NULL) { | | 1333 | if (pv == NULL) { |
1337 | pv = read_pkg_vulnerabilities_file(pkg_vulnerabilities_file, | | 1334 | pv = read_pkg_vulnerabilities_file(pkg_vulnerabilities_file, |
1338 | require_check, 0); | | 1335 | require_check, 0); |
1339 | if (pv == NULL) | | 1336 | if (pv == NULL) |
1340 | return require_check; | | 1337 | return require_check; |
1341 | } | | 1338 | } |
1342 | | | 1339 | |
1343 | if (!audit_package(pv, pkg->pkgname, NULL, 2)) | | 1340 | if (!audit_package(pv, pkg->pkgname, NULL, 2)) |
1344 | return 0; | | 1341 | return 0; |
1345 | | | 1342 | |
1346 | if (require_check) | | 1343 | if (require_check) |
1347 | return 1; | | 1344 | return 1; |
1348 | | | 1345 | |
1349 | fprintf(stderr, "Do you want to proceed with the installation of %s" | | 1346 | fprintf(stderr, "Do you want to proceed with the installation of %s" |
1350 | " [y/n]?\n", pkg->pkgname); | | 1347 | " [y/n]?\n", pkg->pkgname); |
1351 | line = fgetln(stdin, &len); | | 1348 | line = fgetln(stdin, &len); |
1352 | if (check_input(line, len)) { | | 1349 | if (check_input(line, len)) { |
1353 | fprintf(stderr, "Cancelling installation\n"); | | 1350 | fprintf(stderr, "Cancelling installation\n"); |
1354 | return 1; | | 1351 | return 1; |
1355 | } | | 1352 | } |
1356 | return 0; | | 1353 | return 0; |
1357 | } | | 1354 | } |
1358 | | | 1355 | |
1359 | static int | | 1356 | static int |
1360 | check_license(struct pkg_task *pkg) | | 1357 | check_license(struct pkg_task *pkg) |
1361 | { | | 1358 | { |
1362 | if (LicenseCheck == 0) | | 1359 | if (LicenseCheck == 0) |
1363 | return 0; | | 1360 | return 0; |
1364 | | | 1361 | |
1365 | if ((pkg->buildinfo[BI_LICENSE] == NULL || | | 1362 | if ((pkg->buildinfo[BI_LICENSE] == NULL || |
1366 | *pkg->buildinfo[BI_LICENSE] == '\0')) { | | 1363 | *pkg->buildinfo[BI_LICENSE] == '\0')) { |
1367 | | | 1364 | |
1368 | if (LicenseCheck == 1) | | 1365 | if (LicenseCheck == 1) |
1369 | return 0; | | 1366 | return 0; |
1370 | warnx("No LICENSE set for package `%s'", pkg->pkgname); | | 1367 | warnx("No LICENSE set for package `%s'", pkg->pkgname); |
1371 | return 1; | | 1368 | return 1; |
1372 | } | | 1369 | } |
1373 | | | 1370 | |
1374 | switch (acceptable_license(pkg->buildinfo[BI_LICENSE])) { | | 1371 | switch (acceptable_license(pkg->buildinfo[BI_LICENSE])) { |
1375 | case 0: | | 1372 | case 0: |
1376 | warnx("License `%s' of package `%s' is not acceptable", | | 1373 | warnx("License `%s' of package `%s' is not acceptable", |
1377 | pkg->buildinfo[BI_LICENSE], pkg->pkgname); | | 1374 | pkg->buildinfo[BI_LICENSE], pkg->pkgname); |
1378 | return 1; | | 1375 | return 1; |
1379 | case 1: | | 1376 | case 1: |
1380 | return 0; | | 1377 | return 0; |
1381 | default: | | 1378 | default: |
1382 | warnx("Invalid LICENSE for package `%s'", pkg->pkgname); | | 1379 | warnx("Invalid LICENSE for package `%s'", pkg->pkgname); |
1383 | return 1; | | 1380 | return 1; |
1384 | } | | 1381 | } |
1385 | } | | 1382 | } |
1386 | | | 1383 | |
1387 | /* | | 1384 | /* |
1388 | * Install a single package. | | 1385 | * Install a single package. |
1389 | */ | | 1386 | */ |
1390 | static int | | 1387 | static int |
1391 | pkg_do(const char *pkgpath, int mark_automatic, int top_level) | | 1388 | pkg_do(const char *pkgpath, int mark_automatic, int top_level) |
1392 | { | | 1389 | { |
1393 | char *archive_name; | | 1390 | char *archive_name; |
1394 | int status, invalid_sig; | | 1391 | int status, invalid_sig; |
1395 | struct pkg_task *pkg; | | 1392 | struct pkg_task *pkg; |
1396 | | | 1393 | |
1397 | pkg = xcalloc(1, sizeof(*pkg)); | | 1394 | pkg = xcalloc(1, sizeof(*pkg)); |
1398 | | | 1395 | |
1399 | status = -1; | | 1396 | status = -1; |
1400 | | | 1397 | |
1401 | pkg->archive = find_archive(pkgpath, top_level, &archive_name); | | 1398 | pkg->archive = find_archive(pkgpath, top_level, &archive_name); |
1402 | if (pkg->archive == NULL) { | | 1399 | if (pkg->archive == NULL) { |
1403 | warnx("no pkg found for '%s', sorry.", pkgpath); | | 1400 | warnx("no pkg found for '%s', sorry.", pkgpath); |
1404 | goto clean_find_archive; | | 1401 | goto clean_find_archive; |
1405 | } | | 1402 | } |
1406 | | | 1403 | |
1407 | invalid_sig = pkg_verify_signature(archive_name, &pkg->archive, &pkg->entry, | | 1404 | invalid_sig = pkg_verify_signature(archive_name, &pkg->archive, &pkg->entry, |
1408 | &pkg->pkgname); | | 1405 | &pkg->pkgname); |
1409 | free(archive_name); | | 1406 | free(archive_name); |
1410 | | | 1407 | |
1411 | if (pkg->archive == NULL) | | 1408 | if (pkg->archive == NULL) |
1412 | goto clean_memory; | | 1409 | goto clean_memory; |
1413 | | | 1410 | |
1414 | if (read_meta_data(pkg)) | | 1411 | if (read_meta_data(pkg)) |
1415 | goto clean_memory; | | 1412 | goto clean_memory; |
1416 | | | 1413 | |
1417 | /* Parse PLIST early, so that messages can use real package name. */ | | 1414 | /* Parse PLIST early, so that messages can use real package name. */ |