Branch data Line data Source code
1 : : /*-
2 : : * Copyright (c) 2011-2021 Baptiste Daroussin <bapt@FreeBSD.org>
3 : : * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
4 : : * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
5 : : * Copyright (c) 2012-2013 Matthew Seaman <matthew@FreeBSD.org>
6 : : * Copyright (c) 2014 Vsevolod Stakhov <vsevolod@FreeBSD.org>
7 : : *
8 : : * All rights reserved.
9 : : *
10 : : * Redistribution and use in source and binary forms, with or without
11 : : * modification, are permitted provided that the following conditions
12 : : * are met:
13 : : * 1. Redistributions of source code must retain the above copyright
14 : : * notice, this list of conditions and the following disclaimer
15 : : * in this position and unchanged.
16 : : * 2. Redistributions in binary form must reproduce the above copyright
17 : : * notice, this list of conditions and the following disclaimer in the
18 : : * documentation and/or other materials provided with the distribution.
19 : : *
20 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
21 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 : : * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
24 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 : : */
31 : : #include "pkg_config.h"
32 : :
33 : : #include <sys/types.h>
34 : : #include <sys/stat.h>
35 : : #include <sys/wait.h>
36 : : #include <sys/socket.h>
37 : : #include <sys/file.h>
38 : : #include <sys/time.h>
39 : :
40 : : #include <archive_entry.h>
41 : : #include <assert.h>
42 : : #include <fts.h>
43 : : #include <libgen.h>
44 : : #include <sqlite3.h>
45 : : #include <string.h>
46 : : #include <stdio.h>
47 : : #include <stdbool.h>
48 : : #include <unistd.h>
49 : : #include <errno.h>
50 : : #include <fcntl.h>
51 : : #include <math.h>
52 : : #include <poll.h>
53 : : #include <sys/uio.h>
54 : : #include <msgpuck.h>
55 : :
56 : : #include "pkg.h"
57 : : #include "private/event.h"
58 : : #include "private/utils.h"
59 : : #include "private/pkg.h"
60 : : #include "private/pkgdb.h"
61 : :
62 : : enum {
63 : : MSG_PKG_DONE=0,
64 : : MSG_PKG_READY,
65 : : MSG_DIGEST,
66 : : };
67 : :
68 : : struct digest_list_entry {
69 : : char *origin;
70 : : char *digest;
71 : : long manifest_pos;
72 : : long files_pos;
73 : : long manifest_length;
74 : : char *checksum;
75 : : struct digest_list_entry *prev, *next;
76 : : };
77 : :
78 : : struct pkg_conflict_bulk {
79 : : struct pkg_conflict *conflicts;
80 : : pkghash *conflictshash;
81 : : char *file;
82 : : };
83 : :
84 : : static int
85 : 0 : hash_file(struct pkg_repo_meta *meta, struct pkg *pkg, char *path)
86 : : {
87 : 0 : char tmp_repo[MAXPATHLEN] = { 0 };
88 : 0 : char tmp_name[MAXPATHLEN] = { 0 };
89 : 0 : char repo_name[MAXPATHLEN] = { 0 };
90 : 0 : char hash_name[MAXPATHLEN] = { 0 };
91 : 0 : char link_name[MAXPATHLEN] = { 0 };
92 : 0 : char *rel_repo = NULL;
93 : 0 : char *rel_dir = NULL;
94 : 0 : char *rel_link = NULL;
95 : 0 : char *ext = NULL;
96 : :
97 : : /* Don't rename symlinks */
98 [ # # ]: 0 : if (is_link(path))
99 : 0 : return (EPKG_OK);
100 : :
101 : 0 : ext = strrchr(path, '.');
102 : :
103 : 0 : strlcpy(tmp_name, path, sizeof(tmp_name));
104 : 0 : rel_dir = get_dirname(tmp_name);
105 [ # # ]: 0 : while (strstr(rel_dir, "/Hashed") != NULL) {
106 : 0 : rel_dir = get_dirname(rel_dir);
107 : : }
108 : 0 : strlcpy(tmp_name, rel_dir, sizeof(tmp_name));
109 : 0 : rel_dir = (char *)&tmp_name;
110 : :
111 : 0 : rel_repo = path;
112 : 0 : if (strncmp(rel_repo, meta->repopath, strlen(meta->repopath)) == 0) {
113 : 0 : rel_repo += strlen(meta->repopath);
114 [ # # ]: 0 : while (rel_repo[0] == '/')
115 : 0 : rel_repo++;
116 : 0 : }
117 : 0 : strlcpy(tmp_repo, rel_repo, sizeof(tmp_repo));
118 : 0 : rel_repo = get_dirname(tmp_repo);
119 [ # # ]: 0 : while (strstr(rel_repo, "/Hashed") != NULL) {
120 : 0 : rel_repo = get_dirname(rel_repo);
121 : : }
122 : 0 : strlcpy(tmp_repo, rel_repo, sizeof(tmp_repo));
123 : 0 : rel_repo = (char *)&tmp_repo;
124 : :
125 : 0 : pkg_snprintf(repo_name, sizeof(repo_name), "%S/%S/%n-%v%S%z%S",
126 : 0 : rel_repo, PKG_HASH_DIR, pkg, pkg, PKG_HASH_SEPSTR, pkg, ext);
127 : 0 : pkg_snprintf(link_name, sizeof(repo_name), "%S/%n-%v%S",
128 : 0 : rel_dir, pkg, pkg, ext);
129 : 0 : pkg_snprintf(hash_name, sizeof(hash_name), "%S/%S/%n-%v%S%z%S",
130 : 0 : rel_dir, PKG_HASH_DIR, pkg, pkg, PKG_HASH_SEPSTR, pkg, ext);
131 : 0 : rel_link = (char *)&hash_name;
132 : 0 : rel_link += strlen(rel_dir);
133 [ # # ]: 0 : while (rel_link[0] == '/')
134 : 0 : rel_link++;
135 : :
136 : 0 : snprintf(tmp_name, sizeof(tmp_name), "%s/%s", rel_dir, PKG_HASH_DIR);
137 : 0 : rel_dir = (char *)&tmp_name;
138 : 0 : if (!is_dir(rel_dir)) {
139 : 0 : pkg_debug(1, "Making directory: %s", rel_dir);
140 : 0 : (void)mkdirs(rel_dir);
141 : 0 : }
142 : :
143 : 0 : if (strcmp(path, hash_name) != 0) {
144 : 0 : pkg_debug(1, "Rename the pkg from: %s to: %s", path, hash_name);
145 [ # # ]: 0 : if (rename(path, hash_name) == -1) {
146 : 0 : pkg_emit_errno("rename", hash_name);
147 : 0 : return (EPKG_FATAL);
148 : : }
149 : 0 : }
150 : 0 : if (meta->hash_symlink) {
151 : 0 : pkg_debug(1, "Symlinking pkg file from: %s to: %s", rel_link,
152 : 0 : link_name);
153 : 0 : (void)unlink(link_name);
154 [ # # ]: 0 : if (symlink(rel_link, link_name) == -1) {
155 : 0 : pkg_emit_errno("symlink", link_name);
156 : 0 : return (EPKG_FATAL);
157 : : }
158 : 0 : }
159 : 0 : free(pkg->repopath);
160 : 0 : pkg->repopath = xstrdup(repo_name);
161 : :
162 : 0 : return (EPKG_OK);
163 : 0 : }
164 : :
165 : : static int
166 : 4 : pkg_digest_sort_compare_func(struct digest_list_entry *d1,
167 : : struct digest_list_entry *d2)
168 : : {
169 : 4 : return strcmp(d1->origin, d2->origin);
170 : : }
171 : :
172 : : struct pkg_fts_item {
173 : : char *fts_accpath;
174 : : char *pkg_path;
175 : : char *fts_name;
176 : : off_t fts_size;
177 : : int fts_info;
178 : : struct pkg_fts_item *next;
179 : : };
180 : :
181 : : static struct pkg_fts_item*
182 : 534 : pkg_create_repo_fts_new(FTSENT *fts, const char *root_path)
183 : : {
184 : : struct pkg_fts_item *item;
185 : : char *pkg_path;
186 : :
187 : 534 : item = xmalloc(sizeof(*item));
188 : 534 : item->fts_accpath = xstrdup(fts->fts_accpath);
189 : 534 : item->fts_name = xstrdup(fts->fts_name);
190 : 534 : item->fts_size = fts->fts_statp->st_size;
191 : 534 : item->fts_info = fts->fts_info;
192 : :
193 : 534 : pkg_path = fts->fts_path;
194 : 534 : pkg_path += strlen(root_path);
195 [ + + ]: 1068 : while (pkg_path[0] == '/')
196 : 534 : pkg_path++;
197 : :
198 : 534 : item->pkg_path = xstrdup(pkg_path);
199 : :
200 : 534 : return (item);
201 : : }
202 : :
203 : : static void
204 : 0 : pkg_create_repo_fts_free(struct pkg_fts_item *item)
205 : : {
206 : 0 : free(item->fts_accpath);
207 : 0 : free(item->pkg_path);
208 : 0 : free(item->fts_name);
209 : 0 : free(item);
210 : 0 : }
211 : :
212 : : static int
213 : 277 : pkg_create_repo_read_fts(struct pkg_fts_item **items, FTS *fts,
214 : : const char *repopath, size_t *plen, struct pkg_repo_meta *meta)
215 : : {
216 : : FTSENT *fts_ent;
217 : : struct pkg_fts_item *fts_cur;
218 : : char *ext;
219 : 277 : int linklen = 0;
220 : 277 : char tmp_name[MAXPATHLEN] = { 0 };
221 : : char repo_path[MAXPATHLEN];
222 : : size_t repo_path_len;
223 : :
224 [ - + ]: 277 : if (realpath(repopath, repo_path) == NULL) {
225 : 0 : pkg_emit_errno("invalid repo path", repopath);
226 : 0 : return (EPKG_FATAL);
227 : : }
228 : 277 : repo_path_len = strlen(repo_path);
229 : 277 : errno = 0;
230 : :
231 [ + + ]: 4027 : while ((fts_ent = fts_read(fts)) != NULL) {
232 : : /*
233 : : * Skip directories starting with '.' to avoid Poudriere
234 : : * symlinks.
235 : : */
236 : 4826 : if ((fts_ent->fts_info == FTS_D ||
237 : 2994 : fts_ent->fts_info == FTS_DP) &&
238 : 1076 : fts_ent->fts_namelen > 2 &&
239 : 1076 : fts_ent->fts_name[0] == '.') {
240 : 0 : fts_set(fts, fts_ent, FTS_SKIP);
241 : 0 : continue;
242 : : }
243 : : /*
244 : : * Ignore 'Latest' directory as it is just symlinks back to
245 : : * already-processed packages.
246 : : */
247 : 2994 : if ((fts_ent->fts_info == FTS_D ||
248 : 2994 : fts_ent->fts_info == FTS_DP ||
249 : 2238 : fts_ent->fts_info == FTS_SL) &&
250 : 16 : strcmp(fts_ent->fts_name, "Latest") == 0) {
251 : 16 : fts_set(fts, fts_ent, FTS_SKIP);
252 : 16 : continue;
253 : : }
254 : : /* Follow symlinks. */
255 [ + + ]: 3734 : if (fts_ent->fts_info == FTS_SL) {
256 : : /*
257 : : * Skip symlinks pointing inside the repo
258 : : * and dead symlinks
259 : : */
260 [ + + ]: 82 : if (realpath(fts_ent->fts_path, tmp_name) == NULL)
261 : 14 : continue;
262 [ + + ]: 68 : if (strncmp(repo_path, tmp_name, repo_path_len) == 0)
263 : 64 : continue;
264 : : /* Skip symlinks to hashed packages */
265 : 4 : if (meta->hash) {
266 : 0 : linklen = readlink(fts_ent->fts_path,
267 : 0 : (char *)&tmp_name, MAXPATHLEN);
268 [ # # ]: 0 : if (linklen < 0)
269 : 0 : continue;
270 : 0 : tmp_name[linklen] = '\0';
271 [ # # ]: 0 : if (strstr(tmp_name, PKG_HASH_DIR) != NULL)
272 : 0 : continue;
273 : 0 : }
274 : 4 : fts_set(fts, fts_ent, FTS_FOLLOW);
275 : : /* Restart. Next entry will be the resolved file. */
276 : 4 : continue;
277 : : }
278 : : /* Skip everything that is not a file */
279 [ + + ]: 3652 : if (fts_ent->fts_info != FTS_F)
280 : 1496 : continue;
281 : :
282 : 2156 : ext = strrchr(fts_ent->fts_name, '.');
283 : :
284 [ + + ]: 2156 : if (ext == NULL)
285 : 530 : continue;
286 : :
287 [ + + ]: 1626 : if (!packing_is_valid_format(ext + 1))
288 : 1044 : continue;
289 : :
290 : : /* skip all files which are not .pkg */
291 : 582 : if (!ctx.repo_accept_legacy_pkg && strcmp(ext + 1, "pkg") != 0)
292 : 0 : continue;
293 : :
294 : :
295 : 582 : *ext = '\0';
296 : :
297 [ + + ]: 582 : if (pkg_repo_meta_is_old_file(fts_ent->fts_name, meta)) {
298 : 4 : unlink(fts_ent->fts_path);
299 : 4 : continue;
300 : : }
301 : 578 : if (strcmp(fts_ent->fts_name, "meta") == 0 ||
302 : 558 : pkg_repo_meta_is_special_file(fts_ent->fts_name, meta)) {
303 : 44 : *ext = '.';
304 : 44 : continue;
305 : : }
306 : :
307 : 534 : *ext = '.';
308 : 534 : fts_cur = pkg_create_repo_fts_new(fts_ent, repopath);
309 [ - + ]: 534 : if (fts_cur == NULL)
310 : 0 : return (EPKG_FATAL);
311 : :
312 : 534 : LL_PREPEND(*items, fts_cur);
313 : 534 : (*plen) ++;
314 : : }
315 : :
316 [ - + ]: 277 : if (errno != 0) {
317 : 0 : pkg_emit_errno("fts_read", "pkg_create_repo_read_fts");
318 : 0 : return (EPKG_FATAL);
319 : : }
320 : :
321 : 277 : return (EPKG_OK);
322 : 277 : }
323 : :
324 : : static void
325 : 1068 : tell_parent(int fd, char *buf, size_t len)
326 : : {
327 : : struct iovec iov[2];
328 : : struct msghdr msg;
329 : :
330 : 1068 : iov[0].iov_base = buf;
331 : 1068 : iov[0].iov_len = len;
332 : 1068 : memset(&msg, 0, sizeof(msg));
333 : 1068 : msg.msg_iov = iov;
334 : 1068 : msg.msg_iovlen = 1;
335 : 1068 : sendmsg(fd, &msg, MSG_EOR);
336 : 1068 : }
337 : :
338 : : static int
339 : 534 : pkg_create_repo_worker(int mfd, int ffd, int pip,
340 : : struct pkg_repo_meta *meta)
341 : : {
342 : : pid_t pid;
343 : 534 : struct pollfd *pfd = NULL;
344 : 534 : int flags, ret = EPKG_OK;
345 : : size_t sz;
346 : 534 : struct pkg *pkg = NULL;
347 : 534 : struct pkg_manifest_key *keys = NULL;
348 : 534 : char *mdigest = NULL;
349 : : char digestbuf[1024];
350 : : xstring *b;
351 : : struct iovec iov[2];
352 : : uint32_t len;
353 : : char buf[1024];
354 : : char *w, *path;
355 : : const char *rbuf, *c, *repopath;
356 : :
357 : 534 : b = xstring_new();
358 : :
359 : 534 : pid = fork();
360 [ - - + ]: 534 : switch(pid) {
361 : : case -1:
362 : 0 : pkg_emit_errno("pkg_create_repo_worker", "fork");
363 : 0 : xstring_free(b);
364 : 0 : return (EPKG_FATAL);
365 : : break;
366 : : case 0:
367 : 0 : break;
368 : : default:
369 : : /* Parent */
370 : 534 : xstring_free(b);
371 : 534 : return (EPKG_OK);
372 : : break;
373 : : }
374 : :
375 : 0 : pkg_manifest_keys_new(&keys);
376 : 0 : pkg_debug(1, "start worker to parse packages");
377 : :
378 [ # # ]: 0 : if (ffd != -1)
379 : 0 : flags = PKG_OPEN_MANIFEST_ONLY;
380 : : else
381 : 0 : flags = PKG_OPEN_MANIFEST_ONLY | PKG_OPEN_MANIFEST_COMPACT;
382 : :
383 : : /* We are reading to digest buf but it's only to check the socketpair */
384 [ # # ]: 0 : if (read(pip, digestbuf, 1) == -1) {
385 : 0 : pkg_emit_errno("pkg_create_repo_worker", "read");
386 : 0 : goto cleanup;
387 : : }
388 : :
389 : 0 : pfd = xcalloc(1, sizeof(struct pollfd));
390 : 0 : pfd[0].fd = pip;
391 : 0 : pfd[0].events = POLLIN;
392 : :
393 : 0 : for (;;) {
394 : 0 : w = buf;
395 : 0 : w = mp_encode_array(w, 1);
396 : 0 : w = mp_encode_uint(w, MSG_PKG_READY);
397 : 0 : tell_parent(pip, buf, w - buf);
398 [ # # ]: 0 : if (poll(pfd, 1, -1) == -1) {
399 [ # # ]: 0 : if (errno == EINTR)
400 : 0 : continue;
401 : : else
402 : 0 : goto cleanup;
403 : : }
404 [ # # ]: 0 : if (pfd[0].revents & (POLLIN|POLLHUP|POLLERR)) {
405 : 0 : for (;;) {
406 : : ssize_t r;
407 : 0 : r = read(pfd[0].fd, buf, sizeof(buf));
408 [ # # ]: 0 : if (r == -1) {
409 [ # # ]: 0 : if (errno == EINTR)
410 : 0 : continue;
411 : 0 : else if (errno == EAGAIN || errno == EWOULDBLOCK) {
412 : 0 : return (EPKG_OK);
413 : : }
414 : 0 : pkg_emit_errno("pkg_repo_worker", "read");
415 : 0 : return (EPKG_FATAL);
416 [ # # ]: 0 : } else if (r == 0)
417 : 0 : return (EPKG_END);
418 : : else
419 : 0 : break;
420 : : }
421 : 0 : } else {
422 : 0 : continue;
423 : : }
424 : 0 : rbuf = buf;
425 : 0 : sz = mp_decode_array(&rbuf);
426 [ # # ]: 0 : if (sz < 1)
427 : 0 : continue;
428 : 0 : c = mp_decode_str(&rbuf, &len);
429 [ # # ]: 0 : if (len == 0) /* empty package name means ends of repo */
430 : 0 : break;
431 : 0 : path = xstrndup(c, len);
432 : 0 : repopath = mp_decode_str(&rbuf, &len);
433 [ # # ]: 0 : if (len == 0) /* empty package name means ends of repo */
434 : 0 : break;
435 : 0 : if (pkg_open(&pkg, path, keys, flags) == EPKG_OK) {
436 : 0 : off_t mpos, fpos = 0;
437 : : size_t mlen;
438 : : struct stat st;
439 : :
440 : 0 : pkg->sum = pkg_checksum_file(path, PKG_HASH_TYPE_SHA256_HEX);
441 : 0 : stat(path, &st);
442 : 0 : pkg->pkgsize = st.st_size;
443 [ # # ]: 0 : if (meta->hash) {
444 : 0 : ret = hash_file(meta, pkg, path);
445 [ # # ]: 0 : if (ret != EPKG_OK)
446 : 0 : goto cleanup;
447 : 0 : } else {
448 : 0 : pkg->repopath = xstrdup(repopath);
449 : : }
450 : :
451 : : /*
452 : : * TODO: use pkg_checksum for new manifests
453 : : */
454 : 0 : xstring_reset(b);
455 : 0 : mdigest = xmalloc(pkg_checksum_type_size(meta->digest_format));
456 : :
457 : 0 : pkg_emit_manifest_buf(pkg, b, PKG_MANIFEST_EMIT_COMPACT, NULL);
458 : : /* Only version 1 needs the digest */
459 : 0 : if (meta->version == 1) {
460 [ # # # # : 0 : if (pkg_checksum_generate(pkg, mdigest,
# # ]
461 : 0 : pkg_checksum_type_size(meta->digest_format),
462 : 0 : meta->digest_format, false, true, false) != EPKG_OK) {
463 : 0 : pkg_emit_error("Cannot generate digest for a package");
464 : 0 : ret = EPKG_FATAL;
465 : :
466 : 0 : goto cleanup;
467 : : }
468 : 0 : }
469 : 0 : fflush(b->fp);
470 : 0 : mlen = strlen(b->buf);
471 : :
472 [ # # ]: 0 : if (flock(mfd, LOCK_EX) == -1) {
473 : 0 : pkg_emit_errno("pkg_create_repo_worker", "flock");
474 : 0 : ret = EPKG_FATAL;
475 : 0 : goto cleanup;
476 : : }
477 : :
478 : 0 : mpos = lseek(mfd, 0, SEEK_END);
479 : :
480 : 0 : iov[0].iov_base = b->buf;
481 : 0 : iov[0].iov_len = mlen;
482 : 0 : iov[1].iov_base = (void *)"\n";
483 : 0 : iov[1].iov_len = 1;
484 : :
485 [ # # ]: 0 : if (writev(mfd, iov, 2) == -1) {
486 : 0 : pkg_emit_errno("pkg_create_repo_worker", "write");
487 : 0 : ret = EPKG_FATAL;
488 : 0 : flock(mfd, LOCK_UN);
489 : 0 : goto cleanup;
490 : : }
491 : :
492 : 0 : flock(mfd, LOCK_UN);
493 : :
494 : 0 : if (ffd != -1) {
495 : : FILE *fl;
496 : :
497 [ # # ]: 0 : if (flock(ffd, LOCK_EX) == -1) {
498 : 0 : pkg_emit_errno("pkg_create_repo_worker", "flock");
499 : 0 : ret = EPKG_FATAL;
500 : 0 : goto cleanup;
501 : : }
502 : 0 : fpos = lseek(ffd, 0, SEEK_END);
503 : 0 : fl = fdopen(dup(ffd), "a");
504 : 0 : pkg_emit_filelist(pkg, fl);
505 : 0 : fclose(fl);
506 : :
507 : 0 : flock(ffd, LOCK_UN);
508 : 0 : }
509 : :
510 : 0 : if (meta->version == 1) {
511 : 0 : w = buf;
512 : 0 : w = mp_encode_array(w, 7);
513 : 0 : w = mp_encode_uint(w, MSG_DIGEST);
514 : 0 : w = mp_encode_str(w, pkg->origin, strlen(pkg->origin));
515 : 0 : w = mp_encode_str(w, mdigest, strlen(mdigest));
516 : 0 : w = mp_encode_uint(w, mpos);
517 : 0 : w = mp_encode_uint(w, fpos);
518 : 0 : w = mp_encode_uint(w, mlen);
519 : 0 : w = mp_encode_str(w, pkg->sum, strlen(pkg->sum));
520 : 0 : tell_parent(pip, buf, w - buf);
521 : 0 : }
522 : : /* send a tick */
523 : 0 : w = buf;
524 : 0 : w = mp_encode_array(w, 1);
525 : 0 : w = mp_encode_uint(w, MSG_PKG_DONE);
526 : 0 : tell_parent(pip, buf, w - buf);
527 : 0 : }
528 : 0 : free(path);
529 : 0 : }
530 : :
531 : : cleanup:
532 : 0 : pkg_manifest_keys_free(keys);
533 : 0 : xstring_free(b);
534 : 0 : close(pip);
535 : 0 : free(mdigest);
536 : :
537 : 0 : pkg_debug(1, "worker done");
538 : 0 : _exit(ret);
539 : 534 : }
540 : :
541 : : static int
542 : 1859 : pkg_create_repo_read_pipe(int fd, struct digest_list_entry **dlist, struct pkg_fts_item **items)
543 : : {
544 : 1859 : struct digest_list_entry *dig = NULL;
545 : : char buf[1024];
546 : : int r;
547 : : size_t sz;
548 : : uint32_t len;
549 : : uint64_t msgtype;
550 : : const char *rbuf;
551 : :
552 : 2939 : for (;;) {
553 : 2939 : dig = NULL;
554 : 2939 : r = read(fd, buf, sizeof(buf));
555 [ + + ]: 2939 : if (r == -1) {
556 [ - + ]: 791 : if (errno == EINTR)
557 : 0 : continue;
558 [ - + ]: 791 : else if (errno == ECONNRESET) {
559 : : /* Treat it as the end of a connection */
560 : 0 : return (EPKG_END);
561 : : }
562 : 791 : else if (errno == EAGAIN || errno == EWOULDBLOCK) {
563 : 791 : return (EPKG_OK);
564 : : }
565 : :
566 : 0 : pkg_emit_errno("pkg_create_repo_read_pipe", "read");
567 : 0 : return (EPKG_FATAL);
568 : : }
569 [ + + ]: 2148 : else if (r == 0)
570 : 534 : return (EPKG_END);
571 : :
572 : 1614 : rbuf = buf;
573 : 1614 : sz = mp_decode_array(&rbuf);
574 [ - + ]: 1614 : if (sz < 1)
575 : 0 : continue;
576 : 1614 : msgtype = mp_decode_uint(&rbuf);
577 : :
578 [ + + ]: 1614 : if (msgtype == MSG_PKG_DONE) {
579 : 534 : return (EPKG_OK);
580 : : }
581 : :
582 : 1080 : if (msgtype == MSG_DIGEST) {
583 : : const char *c;
584 : 12 : dig = xcalloc(1, sizeof(*dig));
585 : 12 : c = mp_decode_str(&rbuf, &len);
586 : 12 : dig->origin = xstrndup(c, len);
587 : 12 : c = mp_decode_str(&rbuf, &len);
588 : 12 : dig->digest = xstrndup(c, len);
589 : 12 : dig->manifest_pos = mp_decode_uint(&rbuf);
590 : 12 : dig->files_pos = mp_decode_uint(&rbuf);
591 : 12 : dig->manifest_length = mp_decode_uint(&rbuf);
592 : 12 : c = mp_decode_str(&rbuf, &len);
593 : 12 : dig->checksum = xstrndup(c, len);
594 [ + + ]: 12 : DL_APPEND(*dlist, dig);
595 : 12 : }
596 : :
597 : 1068 : if (msgtype == MSG_PKG_READY) {
598 : : char *w;
599 [ + + ]: 1068 : const char *str = (*items) != NULL ? (*items)->fts_accpath : "";
600 [ + + ]: 1068 : const char *str2 = (*items) != NULL ? (*items)->pkg_path : "";
601 : 1068 : w = buf;
602 : 1068 : w = mp_encode_array(w, 2);
603 : 1068 : w = mp_encode_str(w, str, strlen(str));
604 : 1068 : w = mp_encode_str(w, str2, strlen(str2) + 1);
605 : 1068 : if (*items != NULL)
606 [ + - # # ]: 534 : LL_DELETE((*items), (*items));
607 : 1068 : tell_parent(fd, buf, w - buf);
608 : 1068 : }
609 : : }
610 : :
611 : : /*
612 : : * Never reached
613 : : */
614 : : return (EPKG_OK);
615 : 1859 : }
616 : :
617 : : #ifdef __linux__
618 : : typedef const FTSENT *FTSENTP;
619 : : #else
620 : : typedef const FTSENT *const FTSENTP;
621 : : #endif
622 : :
623 : : static int
624 : 5501 : fts_compare(FTSENTP *a, FTSENTP *b)
625 : : {
626 : : /* Sort files before directories, then alpha order */
627 : 5501 : if ((*a)->fts_info != FTS_D && (*b)->fts_info == FTS_D)
628 : 251 : return -1;
629 : 888 : if ((*a)->fts_info == FTS_D && (*b)->fts_info != FTS_D)
630 : 758 : return 1;
631 : 4492 : return (strcmp((*a)->fts_name, (*b)->fts_name));
632 : 5501 : }
633 : :
634 : : int
635 : 277 : pkg_create_repo(char *path, const char *output_dir, bool filelist,
636 : : const char *metafile, bool hash, bool hash_symlink)
637 : : {
638 : 277 : FTS *fts = NULL;
639 : 277 : struct pkg_fts_item *fts_items = NULL;
640 : 277 : pkghash *conflicts = NULL;
641 : : struct pkg_conflict_bulk *curcb;
642 : : int num_workers, i, remaining_workers;
643 : : size_t len, ntask;
644 : 277 : struct digest_list_entry *dlist = NULL, *cur_dig, *dtmp;
645 : 277 : struct pollfd *pfd = NULL;
646 : : int cur_pipe[2], fd, outputdir_fd, mfd, ffd;
647 : 277 : struct pkg_repo_meta *meta = NULL;
648 : 277 : int retcode = EPKG_FATAL;
649 : : ucl_object_t *meta_dump;
650 : : FILE *mfile;
651 : : pkghash_it it;
652 : :
653 : : char *repopath[2];
654 : : char repodb[MAXPATHLEN];
655 : 277 : FILE *mandigests = NULL;
656 : :
657 : 277 : mfd = ffd = -1;
658 : :
659 [ - + ]: 277 : if (!is_dir(path)) {
660 : 0 : pkg_emit_error("%s is not a directory", path);
661 : 0 : return (EPKG_FATAL);
662 : : }
663 : :
664 : 277 : errno = 0;
665 : 277 : if (!is_dir(output_dir)) {
666 : : /* Try to create dir */
667 [ # # ]: 0 : if (errno == ENOENT) {
668 : 0 : if (mkdir(output_dir, 00755) == -1) {
669 : 0 : pkg_fatal_errno("cannot create output directory %s",
670 : : output_dir);
671 : 0 : }
672 : 0 : }
673 : : else {
674 : 0 : pkg_emit_error("%s is not a directory", output_dir);
675 : 0 : return (EPKG_FATAL);
676 : : }
677 : 0 : }
678 [ - + ]: 277 : if ((outputdir_fd = open(output_dir, O_DIRECTORY)) == -1) {
679 : 0 : pkg_emit_error("Cannot open %s", output_dir);
680 : 0 : return (EPKG_FATAL);
681 : : }
682 : :
683 [ + + ]: 277 : if (metafile != NULL) {
684 : 16 : fd = open(metafile, O_RDONLY);
685 [ - + ]: 16 : if (fd == -1) {
686 : 0 : pkg_emit_error("meta loading error while trying %s", metafile);
687 : 0 : return (EPKG_FATAL);
688 : : }
689 [ - + ]: 16 : if (pkg_repo_meta_load(fd, &meta) != EPKG_OK) {
690 : 0 : pkg_emit_error("meta loading error while trying %s", metafile);
691 : 0 : close(fd);
692 : 0 : return (EPKG_FATAL);
693 : : }
694 : 16 : close(fd);
695 : 16 : } else {
696 : 261 : meta = pkg_repo_meta_default();
697 : : }
698 : 277 : meta->repopath = path;
699 : 277 : meta->hash = hash;
700 : 277 : meta->hash_symlink = hash_symlink;
701 : :
702 : 277 : repopath[0] = path;
703 : 277 : repopath[1] = NULL;
704 : :
705 : 277 : num_workers = pkg_object_int(pkg_config_get("WORKERS_COUNT"));
706 : 277 : if (num_workers <= 0) {
707 : 277 : num_workers = (int)sysconf(_SC_NPROCESSORS_ONLN);
708 : 277 : if (num_workers == -1)
709 : 0 : num_workers = 6;
710 : 277 : }
711 : :
712 [ - + ]: 277 : if ((fts = fts_open(repopath, FTS_PHYSICAL|FTS_NOCHDIR, fts_compare)) == NULL) {
713 : 0 : pkg_emit_errno("fts_open", path);
714 : 0 : goto cleanup;
715 : : }
716 : :
717 [ - + - + ]: 554 : if ((mfd = openat(outputdir_fd, meta->manifests,
718 : 277 : O_CREAT|O_TRUNC|O_WRONLY, 00644)) == -1) {
719 : 0 : goto cleanup;
720 : : }
721 : 277 : if (filelist) {
722 [ # # # # ]: 0 : if ((ffd = openat(outputdir_fd, meta->filesite,
723 : 0 : O_CREAT|O_TRUNC|O_WRONLY, 00644)) == -1) {
724 : 0 : goto cleanup;
725 : : }
726 : 0 : }
727 : 8 : if (meta->version == 1) {
728 [ - + ]: 8 : if ((fd = openat(outputdir_fd, meta->digests, O_CREAT|O_TRUNC|O_RDWR, 00644)) == -1) {
729 : 0 : goto cleanup;
730 : : }
731 [ - + ]: 8 : if ((mandigests = fdopen(fd, "w")) == NULL) {
732 : 0 : goto cleanup;
733 : : }
734 : 8 : }
735 : :
736 : 277 : len = 0;
737 : :
738 : 277 : pkg_create_repo_read_fts(&fts_items, fts, path, &len, meta);
739 : :
740 [ - + ]: 277 : if (len == 0) {
741 : : /* Nothing to do */
742 : 0 : pkg_emit_error("No package files have been found");
743 : 0 : goto cleanup;
744 : : }
745 : :
746 : : /* Split items over all workers */
747 [ - + ]: 277 : num_workers = MIN(num_workers, len);
748 : :
749 : : /* Launch workers */
750 : 277 : pkg_emit_progress_start("Creating repository in %s", output_dir);
751 : :
752 : 277 : pfd = xcalloc(num_workers, sizeof(struct pollfd));
753 : 277 : ntask = 0;
754 : :
755 [ + + ]: 811 : for (int i = 0; i < num_workers; i++) {
756 : : /* Create new worker */
757 : : int ofl;
758 : :
759 [ - + ]: 534 : if (get_socketpair(cur_pipe) == -1) {
760 : 0 : pkg_emit_errno("pkg_create_repo", "pipe");
761 : 0 : goto cleanup;
762 : : }
763 : :
764 [ - + - + : 1602 : if (pkg_create_repo_worker(mfd,
- + ]
765 : 1068 : ffd, cur_pipe[1], meta) == EPKG_FATAL) {
766 : 0 : close(cur_pipe[0]);
767 : 0 : close(cur_pipe[1]);
768 : 0 : goto cleanup;
769 : : }
770 : :
771 : 534 : pfd[i].fd = cur_pipe[0];
772 : 534 : pfd[i].events = POLLIN;
773 : 534 : close(cur_pipe[1]);
774 : : /* Make our end of the pipe non-blocking */
775 : 534 : ofl = fcntl(cur_pipe[0], F_GETFL, 0);
776 : 534 : fcntl(cur_pipe[0], F_SETFL, ofl | O_NONBLOCK);
777 : 534 : }
778 : :
779 : : /* Send start marker to all workers */
780 [ + + ]: 811 : for (i = 0; i < num_workers; i ++) {
781 : 534 : if (write(pfd[i].fd, ".", 1) == -1)
782 : 0 : pkg_emit_errno("pkg_create_repo", "write");
783 : 534 : }
784 : :
785 : 277 : ntask = 0;
786 : 277 : remaining_workers = num_workers;
787 [ + + ]: 1964 : while(remaining_workers > 0) {
788 : : int st;
789 : :
790 : 1687 : pkg_debug(1, "checking for %d workers", remaining_workers);
791 : 1687 : retcode = poll(pfd, num_workers, -1);
792 [ - + ]: 1687 : if (retcode == -1) {
793 [ # # ]: 0 : if (errno == EINTR) {
794 : 0 : continue;
795 : : }
796 : : else {
797 : 0 : goto cleanup;
798 : : }
799 : : }
800 : 1687 : else if (retcode > 0) {
801 [ + + ]: 5610 : for (i = 0; i < num_workers; i ++) {
802 : 3923 : if (pfd[i].fd != -1 &&
803 : 3365 : (pfd[i].revents & (POLLIN|POLLHUP|POLLERR))) {
804 [ + + ]: 1859 : if (pkg_create_repo_read_pipe(pfd[i].fd, &dlist, &fts_items) != EPKG_OK) {
805 : : /*
806 : : * Wait for the worker finished
807 : : */
808 : 534 : while (wait(&st) == -1) {
809 [ # # ]: 0 : if (errno == EINTR)
810 : 0 : continue;
811 : :
812 : 0 : pkg_emit_errno("pkg_create_repo", "wait");
813 : 0 : break;
814 : : }
815 : :
816 : 534 : remaining_workers --;
817 : 534 : pkg_debug(1, "finished worker, %d remaining",
818 : 534 : remaining_workers);
819 : 534 : pfd[i].events = 0;
820 : 534 : pfd[i].revents = 0;
821 : 534 : close(pfd[i].fd);
822 : 534 : pfd[i].fd = -1;
823 : 534 : } else {
824 : 1325 : if (errno == EAGAIN || errno == EWOULDBLOCK) {
825 : 791 : errno = 0;
826 : 791 : continue;
827 : : }
828 : 534 : pkg_emit_progress_tick(ntask++, len);
829 : : }
830 : 1068 : }
831 : 3132 : }
832 : 1687 : }
833 : : }
834 : :
835 : 277 : pkg_emit_progress_tick(len, len);
836 : :
837 : : /* Now sort all digests */
838 : 277 : if (meta->version == 1)
839 [ + + + + : 36 : DL_SORT(dlist, pkg_digest_sort_compare_func);
+ + + + +
+ + - +
+ ]
840 : :
841 : : /* Write metafile */
842 : 277 : snprintf(repodb, sizeof(repodb), "%s/%s", output_dir,
843 : : "meta");
844 [ + - ]: 277 : if ((mfile = fopen(repodb, "we")) != NULL) {
845 : 277 : meta_dump = pkg_repo_meta_to_ucl(meta);
846 : 277 : ucl_object_emit_file(meta_dump, UCL_EMIT_CONFIG, mfile);
847 : 277 : fclose(mfile);
848 : 277 : strlcat(repodb, ".conf", sizeof(repodb));
849 [ + - ]: 277 : if ((mfile = fopen(repodb, "we")) != NULL) {
850 : 277 : ucl_object_emit_file(meta_dump, UCL_EMIT_CONFIG, mfile);
851 : 277 : fclose(mfile);
852 : 277 : } else {
853 : 0 : pkg_emit_notice("cannot create metafile at %s", repodb);
854 : : }
855 : 277 : ucl_object_unref(meta_dump);
856 : 277 : }
857 : : else {
858 : 0 : pkg_emit_notice("cannot create metafile at %s", repodb);
859 : : }
860 : 277 : retcode = EPKG_OK;
861 : : cleanup:
862 : 277 : if (outputdir_fd != -1)
863 : 277 : close(outputdir_fd);
864 : 277 : if (mfd != -1)
865 : 277 : close(mfd);
866 : 554 : if (ffd != -1)
867 : 0 : close(ffd);
868 : 277 : it = pkghash_iterator(conflicts);
869 [ - + ]: 277 : while (pkghash_next(&it)) {
870 : 0 : curcb = (struct pkg_conflict_bulk *)it.value;
871 [ # # # # : 0 : LL_FREE(curcb->conflicts, pkg_conflict_free);
# # ]
872 : 0 : pkghash_destroy(curcb->conflictshash);
873 : 0 : curcb->conflictshash = NULL;
874 : 0 : free(curcb);
875 : : }
876 : 277 : pkghash_destroy(conflicts);
877 : :
878 : 277 : if (pfd != NULL)
879 : 277 : free(pfd);
880 : 277 : if (fts != NULL)
881 : 277 : fts_close(fts);
882 : :
883 [ - + # # : 277 : LL_FREE(fts_items, pkg_create_repo_fts_free);
# # ]
884 : :
885 : 277 : if (meta->version == 1) {
886 [ + + ]: 20 : LL_FOREACH_SAFE(dlist, cur_dig, dtmp) {
887 [ + - ]: 12 : if (cur_dig->checksum != NULL)
888 : 24 : fprintf(mandigests, "%s:%s:%ld:%ld:%ld:%s\n", cur_dig->origin,
889 : 12 : cur_dig->digest, cur_dig->manifest_pos, cur_dig->files_pos,
890 : 12 : cur_dig->manifest_length, cur_dig->checksum);
891 : : else
892 : 0 : fprintf(mandigests, "%s:%s:%ld:%ld:%ld\n", cur_dig->origin,
893 : 0 : cur_dig->digest, cur_dig->manifest_pos, cur_dig->files_pos,
894 : 0 : cur_dig->manifest_length);
895 : :
896 : 12 : free(cur_dig->digest);
897 : 12 : free(cur_dig->origin);
898 : 12 : free(cur_dig);
899 : 12 : }
900 : 8 : }
901 : :
902 : 8 : if (meta->version == 1 && mandigests != NULL)
903 : 8 : fclose(mandigests);
904 : 277 : pkg_repo_meta_free(meta);
905 : :
906 : 277 : return (retcode);
907 : 277 : }
908 : :
909 : : static int
910 : 16 : pkg_repo_sign(char *path, char **argv, int argc, char **sig, size_t *siglen,
911 : : char **cert)
912 : : {
913 : : FILE *fp;
914 : : char *sha256;
915 : 16 : xstring *cmd = NULL;
916 : 16 : xstring *buf = NULL;
917 : 16 : xstring *sigstr = NULL;
918 : 16 : xstring *certstr = NULL;
919 : 16 : char *line = NULL;
920 : 16 : size_t linecap = 0;
921 : : ssize_t linelen;
922 : 16 : int i, ret = EPKG_OK;
923 : :
924 : 16 : sha256 = pkg_checksum_file(path, PKG_HASH_TYPE_SHA256_HEX);
925 [ - + ]: 16 : if (!sha256)
926 : 0 : return (EPKG_FATAL);
927 : :
928 : 16 : cmd = xstring_new();
929 : :
930 [ + + ]: 48 : for (i = 0; i < argc; i++) {
931 [ - + ]: 32 : if (strspn(argv[i], " \t\n") > 0)
932 : 0 : fprintf(cmd->fp, " \"%s\" ", argv[i]);
933 : : else
934 : 32 : fprintf(cmd->fp, " %s ", argv[i]);
935 : 32 : }
936 : :
937 : 16 : fflush(cmd->fp);
938 [ - + ]: 16 : if ((fp = popen(cmd->buf, "r+")) == NULL) {
939 : 0 : ret = EPKG_FATAL;
940 : 0 : goto done;
941 : : }
942 : :
943 : 16 : fprintf(fp, "%s\n", sha256);
944 : :
945 : 16 : sigstr = xstring_new();
946 : 16 : certstr = xstring_new();
947 : :
948 : 224 : while ((linelen = getline(&line, &linecap, fp)) > 0 ) {
949 [ + + ]: 224 : if (strcmp(line, "SIGNATURE\n") == 0) {
950 : 16 : buf = sigstr;
951 : 16 : continue;
952 [ + + ]: 208 : } else if (strcmp(line, "CERT\n") == 0) {
953 : 16 : buf = certstr;
954 : 16 : continue;
955 [ + + ]: 192 : } else if (strcmp(line, "END\n") == 0) {
956 : 16 : break;
957 : : }
958 : 176 : if (buf != NULL) {
959 : 176 : fwrite(line, linelen, 1, buf->fp);
960 : 176 : }
961 : : }
962 : :
963 : 16 : *cert = xstring_get(certstr);
964 : 16 : fclose(sigstr->fp);
965 : 16 : sigstr->size--;
966 : 16 : *siglen = sigstr->size;
967 : 16 : *sig = sigstr->buf;
968 : 16 : free(sigstr);
969 : :
970 : : /* remove the latest \n */
971 : :
972 [ - + ]: 16 : if (pclose(fp) != 0) {
973 : 0 : ret = EPKG_FATAL;
974 : 0 : goto done;
975 : : }
976 : :
977 : : done:
978 : 16 : free(sha256);
979 : 16 : xstring_free(cmd);
980 : :
981 : 16 : return (ret);
982 : 16 : }
983 : :
984 : : static int
985 : 562 : pkg_repo_pack_db(const char *name, const char *archive, char *path,
986 : : struct pkg_key *keyinfo, struct pkg_repo_meta *meta,
987 : : char **argv, int argc)
988 : : {
989 : : struct packing *pack;
990 : 562 : unsigned char *sigret = NULL;
991 : 562 : unsigned int siglen = 0;
992 : 562 : size_t signature_len = 0;
993 : : char fname[MAXPATHLEN];
994 : : char *sig, *pub;
995 : 562 : int ret = EPKG_OK;
996 : :
997 : 562 : sig = NULL;
998 : 562 : pub = NULL;
999 : :
1000 [ - + ]: 562 : if (packing_init(&pack, archive, meta->packing_format, 0, (time_t)-1, true, true) != EPKG_OK)
1001 : 0 : return (EPKG_FATAL);
1002 : :
1003 [ + + ]: 562 : if (keyinfo != NULL) {
1004 [ - + ]: 16 : if (rsa_sign(path, keyinfo, &sigret, &siglen) != EPKG_OK) {
1005 : 0 : ret = EPKG_FATAL;
1006 : 0 : goto out;
1007 : : }
1008 : :
1009 [ - + ]: 16 : if (packing_append_buffer(pack, sigret, "signature", siglen + 1) != EPKG_OK) {
1010 : 0 : ret = EPKG_FATAL;
1011 : 0 : goto out;
1012 : : }
1013 : 562 : } else if (argc >= 1) {
1014 [ - + ]: 16 : if (pkg_repo_sign(path, argv, argc, &sig, &signature_len, &pub) != EPKG_OK) {
1015 : 0 : ret = EPKG_FATAL;
1016 : 0 : goto out;
1017 : : }
1018 : :
1019 : 16 : snprintf(fname, sizeof(fname), "%s.sig", name);
1020 [ - + ]: 16 : if (packing_append_buffer(pack, sig, fname, signature_len) != EPKG_OK) {
1021 : 0 : ret = EPKG_FATAL;
1022 : 0 : goto out;
1023 : : }
1024 : :
1025 : 16 : snprintf(fname, sizeof(fname), "%s.pub", name);
1026 [ - + ]: 16 : if (packing_append_buffer(pack, pub, fname, strlen(pub)) != EPKG_OK) {
1027 : 0 : ret = EPKG_FATAL;
1028 : 0 : goto out;
1029 : : }
1030 : :
1031 : 16 : }
1032 : 562 : packing_append_file_attr(pack, path, name, "root", "wheel", 0644, 0);
1033 : :
1034 : : out:
1035 : 562 : packing_finish(pack);
1036 : 562 : unlink(path);
1037 : 562 : free(sigret);
1038 : 562 : free(sig);
1039 : 562 : free(pub);
1040 : :
1041 : 562 : return (ret);
1042 : 562 : }
1043 : :
1044 : : int
1045 : 277 : pkg_finish_repo(const char *output_dir, pkg_password_cb *password_cb,
1046 : : char **argv, int argc, bool filelist)
1047 : : {
1048 : : char repo_path[MAXPATHLEN];
1049 : : char repo_archive[MAXPATHLEN];
1050 : : char *key_file;
1051 : : const char *key_type;
1052 : 277 : struct pkg_key *keyinfo = NULL;
1053 : : struct pkg_repo_meta *meta;
1054 : : struct stat st;
1055 : 277 : int ret = EPKG_OK, nfile = 0, fd;
1056 : 277 : const int files_to_pack = 4;
1057 : :
1058 [ - + ]: 277 : if (!is_dir(output_dir)) {
1059 : 0 : pkg_emit_error("%s is not a directory", output_dir);
1060 : 0 : return (EPKG_FATAL);
1061 : : }
1062 : :
1063 : 277 : if (argc == 1) {
1064 : 8 : key_type = key_file = argv[0];
1065 [ + + ]: 8 : if (strncmp(key_file, "rsa:", 4) == 0) {
1066 : 4 : key_file += 4;
1067 : 4 : *(key_file - 1) = '\0';
1068 : 4 : } else {
1069 : 4 : key_type = "rsa";
1070 : : }
1071 : :
1072 : 8 : pkg_debug(1, "Loading %s key from '%s' for signing", key_type, key_file);
1073 : 8 : rsa_new(&keyinfo, password_cb, key_file);
1074 : 8 : }
1075 : :
1076 : 8 : if (argc > 1 && strcmp(argv[0], "signing_command:") != 0)
1077 : 0 : return (EPKG_FATAL);
1078 : :
1079 : 8 : if (argc > 1) {
1080 : 8 : argc--;
1081 : 8 : argv++;
1082 : 8 : }
1083 : :
1084 : 277 : pkg_emit_progress_start("Packing files for repository");
1085 : 277 : pkg_emit_progress_tick(nfile++, files_to_pack);
1086 : :
1087 : 277 : snprintf(repo_path, sizeof(repo_path), "%s/%s", output_dir,
1088 : : repo_meta_file);
1089 [ + - ]: 277 : if ((fd = open(repo_path, O_RDONLY)) != -1) {
1090 [ - + ]: 277 : if (pkg_repo_meta_load(fd, &meta) != EPKG_OK) {
1091 : 0 : pkg_emit_error("meta loading error while trying %s", repo_path);
1092 : 0 : rsa_free(keyinfo);
1093 : 0 : close(fd);
1094 : 0 : return (EPKG_FATAL);
1095 : : }
1096 [ - + - + : 831 : if (pkg_repo_pack_db(repo_meta_file, repo_path, repo_path, keyinfo,
- + ]
1097 : 554 : meta, argv, argc) != EPKG_OK) {
1098 : 0 : ret = EPKG_FATAL;
1099 : 0 : goto cleanup;
1100 : : }
1101 : 277 : }
1102 : : else {
1103 : 0 : meta = pkg_repo_meta_default();
1104 : : }
1105 : :
1106 : 554 : snprintf(repo_path, sizeof(repo_path), "%s/%s", output_dir,
1107 : 277 : meta->manifests);
1108 : 554 : snprintf(repo_archive, sizeof(repo_archive), "%s/%s", output_dir,
1109 : 277 : meta->manifests_archive);
1110 [ - + - + : 831 : if (pkg_repo_pack_db(meta->manifests, repo_archive, repo_path, keyinfo,
- + ]
1111 : 554 : meta, argv, argc) != EPKG_OK) {
1112 : 0 : ret = EPKG_FATAL;
1113 : 0 : goto cleanup;
1114 : : }
1115 : :
1116 : 277 : pkg_emit_progress_tick(nfile++, files_to_pack);
1117 : :
1118 : 277 : if (filelist) {
1119 : 0 : snprintf(repo_path, sizeof(repo_path), "%s/%s", output_dir,
1120 : 0 : meta->filesite);
1121 : 0 : snprintf(repo_archive, sizeof(repo_archive), "%s/%s",
1122 : 0 : output_dir, meta->filesite_archive);
1123 [ # # # # : 0 : if (pkg_repo_pack_db(meta->filesite, repo_archive, repo_path, keyinfo,
# # ]
1124 : 0 : meta, argv, argc) != EPKG_OK) {
1125 : 0 : ret = EPKG_FATAL;
1126 : 0 : goto cleanup;
1127 : : }
1128 : 0 : }
1129 : :
1130 : 8 : pkg_emit_progress_tick(nfile++, files_to_pack);
1131 : :
1132 : 8 : if (meta->version == 1) {
1133 : 16 : snprintf(repo_path, sizeof(repo_path), "%s/%s", output_dir,
1134 : 8 : meta->digests);
1135 : 16 : snprintf(repo_archive, sizeof(repo_archive), "%s/%s", output_dir,
1136 : 8 : meta->digests_archive);
1137 [ - + - + : 24 : if (pkg_repo_pack_db(meta->digests, repo_archive, repo_path, keyinfo,
- + ]
1138 : 16 : meta, argv, argc) != EPKG_OK) {
1139 : 0 : ret = EPKG_FATAL;
1140 : 0 : goto cleanup;
1141 : : }
1142 : 8 : }
1143 : :
1144 : 277 : pkg_emit_progress_tick(nfile++, files_to_pack);
1145 : :
1146 : : #if 0
1147 : : snprintf(repo_path, sizeof(repo_path), "%s/%s", output_dir,
1148 : : meta->conflicts);
1149 : : snprintf(repo_archive, sizeof(repo_archive), "%s/%s", output_dir,
1150 : : meta->conflicts_archive);
1151 : : if (pkg_repo_pack_db(meta->conflicts, repo_archive, repo_path, keyinfo,
1152 : : meta, argv, argc) != EPKG_OK) {
1153 : : ret = EPKG_FATAL;
1154 : : goto cleanup;
1155 : : }
1156 : : #endif
1157 : :
1158 : : /* Now we need to set the equal mtime for all archives in the repo */
1159 : 554 : snprintf(repo_archive, sizeof(repo_archive), "%s/%s.pkg",
1160 : 277 : output_dir, repo_meta_file);
1161 : 554 : if (stat(repo_archive, &st) == 0) {
1162 : 554 : struct timeval ftimes[2] = {
1163 : 554 : {
1164 : 277 : .tv_sec = st.st_mtime,
1165 : : .tv_usec = 0
1166 : : },
1167 : 554 : {
1168 : 277 : .tv_sec = st.st_mtime,
1169 : : .tv_usec = 0
1170 : : }
1171 : : };
1172 : 554 : snprintf(repo_archive, sizeof(repo_archive), "%s/%s.pkg",
1173 : 277 : output_dir, meta->manifests_archive);
1174 : 277 : utimes(repo_archive, ftimes);
1175 : 277 : if (meta->version == 1) {
1176 : 16 : snprintf(repo_archive, sizeof(repo_archive), "%s/%s.pkg",
1177 : 8 : output_dir, meta->digests_archive);
1178 : 8 : utimes(repo_archive, ftimes);
1179 : 8 : }
1180 : 16 : if (filelist) {
1181 : 0 : snprintf(repo_archive, sizeof(repo_archive),
1182 : 0 : "%s/%s.pkg", output_dir, meta->filesite_archive);
1183 : 0 : utimes(repo_archive, ftimes);
1184 : 0 : }
1185 : 554 : snprintf(repo_archive, sizeof(repo_archive),
1186 : 277 : "%s/%s.pkg", output_dir, repo_meta_file);
1187 : 277 : utimes(repo_archive, ftimes);
1188 : 277 : }
1189 : :
1190 : : cleanup:
1191 : 277 : pkg_emit_progress_tick(files_to_pack, files_to_pack);
1192 : 277 : pkg_repo_meta_free(meta);
1193 : :
1194 : 277 : rsa_free(keyinfo);
1195 : :
1196 : 277 : return (ret);
1197 : 277 : }
|