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