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