LCOV - code coverage report
Current view: top level - libpkg - pkg_repo_create.c (source / functions) Hit Total Coverage
Test: cov.info Lines: 341 589 57.9 %
Date: 2015-08-15 Functions: 9 12 75.0 %

          Line data    Source code
       1             : /*-
       2             :  * Copyright (c) 2011-2013 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/sysctl.h>
      36             : #include <sys/wait.h>
      37             : #include <sys/socket.h>
      38             : #include <sys/file.h>
      39             : #include <sys/time.h>
      40             : 
      41             : #include <archive_entry.h>
      42             : #include <assert.h>
      43             : #include <fts.h>
      44             : #include <libgen.h>
      45             : #include <sqlite3.h>
      46             : #include <string.h>
      47             : #define _WITH_GETLINE
      48             : #include <stdio.h>
      49             : #include <stdbool.h>
      50             : #include <sysexits.h>
      51             : #include <unistd.h>
      52             : #include <errno.h>
      53             : #include <fcntl.h>
      54             : #include <math.h>
      55             : #include <poll.h>
      56             : #include <sys/uio.h>
      57             : 
      58             : #include "pkg.h"
      59             : #include "private/event.h"
      60             : #include "private/utils.h"
      61             : #include "private/pkg.h"
      62             : #include "private/pkgdb.h"
      63             : 
      64             : 
      65             : struct digest_list_entry {
      66             :         char *origin;
      67             :         char *digest;
      68             :         long manifest_pos;
      69             :         long files_pos;
      70             :         long manifest_length;
      71             :         char *checksum;
      72             :         struct digest_list_entry *prev, *next;
      73             : };
      74             : 
      75             : struct pkg_conflict_bulk {
      76             :         struct pkg_conflict *conflicts;
      77             :         char *file;
      78             :         UT_hash_handle hh;
      79             : };
      80             : 
      81             : static int
      82          31 : pkg_digest_sort_compare_func(struct digest_list_entry *d1,
      83             :                 struct digest_list_entry *d2)
      84             : {
      85          31 :         return strcmp(d1->origin, d2->origin);
      86             : }
      87             : 
      88             : static void
      89           0 : pkg_repo_new_conflict(const char *uniqueid, struct pkg_conflict_bulk *bulk)
      90             : {
      91             :         struct pkg_conflict *new;
      92             : 
      93           0 :         pkg_conflict_new(&new);
      94           0 :         new->uid = strdup(uniqueid);
      95             : 
      96           0 :         HASH_ADD_KEYPTR(hh, bulk->conflicts, new->uid, strlen(new->uid), new);
      97           0 : }
      98             : 
      99             : static void
     100           0 : pkg_repo_write_conflicts (struct pkg_conflict_bulk *bulk, FILE *out)
     101             : {
     102           0 :         struct pkg_conflict_bulk        *pkg_bulk = NULL, *cur, *tmp, *s;
     103             :         struct pkg_conflict     *c1, *c1tmp, *c2, *c2tmp, *ctmp;
     104             : 
     105             :         /*
     106             :          * Here we reorder bulk hash from hash by file
     107             :          * to hash indexed by a package, so we iterate over the
     108             :          * original hash and create a new hash indexed by package name
     109             :          */
     110             : 
     111           0 :         HASH_ITER (hh, bulk, cur, tmp) {
     112           0 :                 HASH_ITER (hh, cur->conflicts, c1, c1tmp) {
     113           0 :                         HASH_FIND_STR(pkg_bulk, c1->uid, s);
     114           0 :                         if (s == NULL) {
     115             :                                 /* New entry required */
     116           0 :                                 s = malloc(sizeof(struct pkg_conflict_bulk));
     117           0 :                                 if (s == NULL) {
     118           0 :                                         pkg_emit_errno("malloc", "struct pkg_conflict_bulk");
     119           0 :                                         goto out;
     120             :                                 }
     121           0 :                                 memset(s, 0, sizeof(struct pkg_conflict_bulk));
     122           0 :                                 s->file = c1->uid;
     123           0 :                                 HASH_ADD_KEYPTR(hh, pkg_bulk, s->file, strlen(s->file), s);
     124             :                         }
     125             :                         /* Now add all new entries from this file to this conflict structure */
     126           0 :                         HASH_ITER (hh, cur->conflicts, c2, c2tmp) {
     127           0 :                                 if (strcmp(c1->uid, c2->uid) == 0)
     128           0 :                                         continue;
     129             : 
     130           0 :                                 HASH_FIND_STR(s->conflicts, c2->uid, ctmp);
     131           0 :                                 if (ctmp == NULL)
     132           0 :                                         pkg_repo_new_conflict(c2->uid, s);
     133             :                         }
     134             :                 }
     135             :         }
     136             : 
     137           0 :         HASH_ITER (hh, pkg_bulk, cur, tmp) {
     138           0 :                 fprintf(out, "%s:", cur->file);
     139           0 :                 HASH_ITER (hh, cur->conflicts, c1, c1tmp) {
     140           0 :                         if (c1->hh.next != NULL)
     141           0 :                                 fprintf(out, "%s,", c1->uid);
     142             :                         else
     143           0 :                                 fprintf(out, "%s\n", c1->uid);
     144             :                 }
     145             :         }
     146             : out:
     147           0 :         HASH_ITER (hh, pkg_bulk, cur, tmp) {
     148           0 :                 HASH_ITER (hh, cur->conflicts, c1, c1tmp) {
     149           0 :                         HASH_DEL(cur->conflicts, c1);
     150           0 :                         free(c1->uid);
     151           0 :                         free(c1);
     152             :                 }
     153           0 :                 HASH_DEL(pkg_bulk, cur);
     154           0 :                 free(cur);
     155             :         }
     156           0 :         return;
     157             : }
     158             : 
     159             : struct pkg_fts_item {
     160             :         char *fts_accpath;
     161             :         char *pkg_path;
     162             :         char *fts_name;
     163             :         off_t fts_size;
     164             :         int fts_info;
     165             :         struct pkg_fts_item *next;
     166             : };
     167             : 
     168             : static struct pkg_fts_item*
     169          91 : pkg_create_repo_fts_new(FTSENT *fts, const char *root_path)
     170             : {
     171             :         struct pkg_fts_item *item;
     172             :         char *pkg_path;
     173             : 
     174          91 :         item = malloc(sizeof(*item));
     175          91 :         if (item != NULL) {
     176          91 :                 item->fts_accpath = strdup(fts->fts_accpath);
     177          91 :                 item->fts_name = strdup(fts->fts_name);
     178          91 :                 item->fts_size = fts->fts_statp->st_size;
     179          91 :                 item->fts_info = fts->fts_info;
     180             : 
     181          91 :                 pkg_path = fts->fts_path;
     182          91 :                 pkg_path += strlen(root_path);
     183         273 :                 while (pkg_path[0] == '/')
     184          91 :                         pkg_path++;
     185             : 
     186          91 :                 item->pkg_path = strdup(pkg_path);
     187             :         }
     188             :         else {
     189           0 :                 pkg_emit_errno("malloc", "struct pkg_fts_item");
     190             :         }
     191             : 
     192          91 :         return (item);
     193             : }
     194             : 
     195             : static void
     196          31 : pkg_create_repo_fts_free(struct pkg_fts_item *item)
     197             : {
     198          31 :         free(item->fts_accpath);
     199          31 :         free(item->pkg_path);
     200          31 :         free(item->fts_name);
     201          31 :         free(item);
     202          31 : }
     203             : 
     204             : static int
     205          31 : pkg_create_repo_read_fts(struct pkg_fts_item **items, FTS *fts,
     206             :         const char *repopath, size_t *plen, struct pkg_repo_meta *meta)
     207             : {
     208             :         FTSENT *fts_ent;
     209             :         struct pkg_fts_item *fts_cur;
     210             :         char *ext;
     211             : 
     212          31 :         errno = 0;
     213             : 
     214         613 :         while ((fts_ent = fts_read(fts)) != NULL) {
     215             :                 /*
     216             :                  * Skip directories starting with '.' to avoid Poudriere
     217             :                  * symlinks.
     218             :                  */
     219        1040 :                 if ((fts_ent->fts_info == FTS_D ||
     220         613 :                     fts_ent->fts_info == FTS_DP) &&
     221         192 :                     fts_ent->fts_namelen > 2 &&
     222          68 :                     fts_ent->fts_name[0] == '.') {
     223           0 :                         fts_set(fts, fts_ent, FTS_SKIP);
     224           0 :                         continue;
     225             :                 }
     226             :                 /*
     227             :                  * Ignore 'Latest' directory as it is just symlinks back to
     228             :                  * already-processed packages.
     229             :                  */
     230        1040 :                 if ((fts_ent->fts_info == FTS_D ||
     231         916 :                     fts_ent->fts_info == FTS_DP ||
     232         557 :                     fts_ent->fts_info == FTS_SL) &&
     233         130 :                     strcmp(fts_ent->fts_name, "Latest") == 0) {
     234           6 :                         fts_set(fts, fts_ent, FTS_SKIP);
     235           6 :                         continue;
     236             :                 }
     237             :                 /* Follow symlinks. */
     238         545 :                 if (fts_ent->fts_info == FTS_SL) {
     239           6 :                         fts_set(fts, fts_ent, FTS_FOLLOW);
     240             :                         /* Restart. Next entry will be the resolved file. */
     241           6 :                         continue;
     242             :                 }
     243             :                 /* Skip everything that is not a file */
     244         539 :                 if (fts_ent->fts_info != FTS_F)
     245         118 :                         continue;
     246             : 
     247         421 :                 ext = strrchr(fts_ent->fts_name, '.');
     248             : 
     249         421 :                 if (ext == NULL)
     250         115 :                         continue;
     251             : 
     252         306 :                 if (strcmp(ext + 1, packing_format_to_string(meta->packing_format)) != 0)
     253         197 :                         continue;
     254             : 
     255         109 :                 *ext = '\0';
     256             : 
     257         212 :                 if (strcmp(fts_ent->fts_name, "meta") == 0 ||
     258         103 :                                 pkg_repo_meta_is_special_file(fts_ent->fts_name, meta)) {
     259          18 :                         *ext = '.';
     260          18 :                         continue;
     261             :                 }
     262             : 
     263          91 :                 *ext = '.';
     264          91 :                 fts_cur = pkg_create_repo_fts_new(fts_ent, repopath);
     265          91 :                 if (fts_cur == NULL)
     266           0 :                         return (EPKG_FATAL);
     267             : 
     268          91 :                 LL_PREPEND(*items, fts_cur);
     269          91 :                 (*plen) ++;
     270             :         }
     271             : 
     272          31 :         if (errno != 0) {
     273           0 :                 pkg_emit_errno("fts_read", "pkg_create_repo_read_fts");
     274           0 :                 return (EPKG_FATAL);
     275             :         }
     276             : 
     277          31 :         return (EPKG_OK);
     278             : }
     279             : 
     280             : static int
     281          49 : pkg_create_repo_worker(struct pkg_fts_item *start, size_t nelts,
     282             :         const char *mlfile, const char *flfile, int pip,
     283             :         struct pkg_repo_meta *meta)
     284             : {
     285             :         pid_t pid;
     286          49 :         int mfd, ffd = -1;
     287          49 :         bool read_files = (flfile != NULL);
     288          49 :         bool legacy = (meta == NULL);
     289          49 :         int flags, ret = EPKG_OK;
     290          49 :         size_t cur_job = 0;
     291             :         struct pkg_fts_item *cur;
     292          49 :         struct pkg *pkg = NULL;
     293          49 :         struct pkg_manifest_key *keys = NULL;
     294          49 :         char *mdigest = NULL;
     295             :         char digestbuf[1024];
     296             :         struct iovec iov[2];
     297             :         struct msghdr msg;
     298             : 
     299          49 :         struct sbuf *b = sbuf_new_auto();
     300             : 
     301          49 :         mfd = open(mlfile, O_APPEND|O_CREAT|O_WRONLY, 00644);
     302          49 :         if (mfd == -1) {
     303           0 :                 pkg_emit_errno("pkg_create_repo_worker", "open");
     304           0 :                 return (EPKG_FATAL);
     305             :         }
     306             : 
     307          49 :         if (read_files) {
     308           0 :                 ffd = open(flfile, O_APPEND|O_CREAT|O_WRONLY, 00644);
     309           0 :                 if (ffd == -1) {
     310           0 :                         close(mfd);
     311           0 :                         pkg_emit_errno("pkg_create_repo_worker", "open");
     312           0 :                         return (EPKG_FATAL);
     313             :                 }
     314             :         }
     315             : 
     316          49 :         pid = fork();
     317          49 :         switch(pid) {
     318             :         case -1:
     319           0 :                 pkg_emit_errno("pkg_create_repo_worker", "fork");
     320           0 :                 close(mfd);
     321           0 :                 if (read_files)
     322           0 :                         close(ffd);
     323           0 :                 return (EPKG_FATAL);
     324             :                 break;
     325             :         case 0:
     326          20 :                 break;
     327             :         default:
     328             :                 /* Parent */
     329          29 :                 close(mfd);
     330          29 :                 if (read_files)
     331           0 :                         close(ffd);
     332             : 
     333          29 :                 return (EPKG_OK);
     334             :                 break;
     335             :         }
     336             : 
     337          20 :         pkg_manifest_keys_new(&keys);
     338          20 :         pkg_debug(1, "start worker to parse %d packages", nelts);
     339             : 
     340          20 :         if (read_files)
     341           0 :                 flags = PKG_OPEN_MANIFEST_ONLY;
     342             :         else
     343          20 :                 flags = PKG_OPEN_MANIFEST_ONLY | PKG_OPEN_MANIFEST_COMPACT;
     344             : 
     345          20 :         if (read(pip, digestbuf, 1) == -1) {
     346           0 :                 pkg_emit_errno("pkg_create_repo_worker", "read");
     347           0 :                 goto cleanup;
     348             :         }
     349             : 
     350          51 :         LL_FOREACH(start, cur) {
     351          40 :                 if (cur_job >= nelts)
     352           9 :                         break;
     353             : 
     354          31 :                 if (pkg_open(&pkg, cur->fts_accpath, keys, flags) == EPKG_OK) {
     355             :                         int r;
     356          31 :                         off_t mpos, fpos = 0;
     357             :                         size_t mlen;
     358             : 
     359          31 :                         pkg->sum = pkg_checksum_file(cur->fts_accpath,
     360             :                             PKG_HASH_TYPE_SHA256_HEX);
     361          31 :                         pkg->pkgsize = cur->fts_size;
     362          31 :                         pkg->repopath = strdup(cur->pkg_path);
     363             : 
     364             :                         /*
     365             :                          * TODO: use pkg_checksum for new manifests
     366             :                          */
     367          31 :                         sbuf_clear(b);
     368          31 :                         if (legacy)
     369           0 :                                 pkg_emit_manifest_sbuf(pkg, b, PKG_MANIFEST_EMIT_COMPACT, &mdigest);
     370             :                         else {
     371          31 :                                 mdigest = malloc(pkg_checksum_type_size(meta->digest_format));
     372             : 
     373          31 :                                 pkg_emit_manifest_sbuf(pkg, b, PKG_MANIFEST_EMIT_COMPACT, NULL);
     374          31 :                                 if (pkg_checksum_generate(pkg, mdigest,
     375             :                                      pkg_checksum_type_size(meta->digest_format),
     376             :                                      meta->digest_format) != EPKG_OK) {
     377           0 :                                         pkg_emit_error("Cannot generate digest for a package");
     378           0 :                                         ret = EPKG_FATAL;
     379             : 
     380           0 :                                         goto cleanup;
     381             :                                 }
     382             :                         }
     383          31 :                         mlen = sbuf_len(b);
     384          31 :                         sbuf_finish(b);
     385             : 
     386          31 :                         if (flock(mfd, LOCK_EX) == -1) {
     387           0 :                                 pkg_emit_errno("pkg_create_repo_worker", "flock");
     388           0 :                                 ret = EPKG_FATAL;
     389           0 :                                 goto cleanup;
     390             :                         }
     391             : 
     392          31 :                         mpos = lseek(mfd, 0, SEEK_END);
     393             : 
     394          31 :                         iov[0].iov_base = sbuf_data(b);
     395          31 :                         iov[0].iov_len = sbuf_len(b);
     396          31 :                         iov[1].iov_base = (void *)"\n";
     397          31 :                         iov[1].iov_len = 1;
     398             : 
     399          31 :                         if (writev(mfd, iov, 2) == -1) {
     400           0 :                                 pkg_emit_errno("pkg_create_repo_worker", "write");
     401           0 :                                 ret = EPKG_FATAL;
     402           0 :                                 flock(mfd, LOCK_UN);
     403           0 :                                 goto cleanup;
     404             :                         }
     405             : 
     406          31 :                         flock(mfd, LOCK_UN);
     407             : 
     408          31 :                         if (read_files) {
     409             :                                 FILE *fl;
     410             : 
     411           0 :                                 if (flock(ffd, LOCK_EX) == -1) {
     412           0 :                                         pkg_emit_errno("pkg_create_repo_worker", "flock");
     413           0 :                                         ret = EPKG_FATAL;
     414           0 :                                         goto cleanup;
     415             :                                 }
     416           0 :                                 fpos = lseek(ffd, 0, SEEK_END);
     417           0 :                                 fl = fdopen(dup(ffd), "a");
     418           0 :                                 pkg_emit_filelist(pkg, fl);
     419           0 :                                 fclose(fl);
     420             : 
     421           0 :                                 flock(ffd, LOCK_UN);
     422             :                         }
     423             : 
     424          62 :                         r = snprintf(digestbuf, sizeof(digestbuf), "%s:%s:%ld:%ld:%ld:%s\n",
     425          31 :                                 pkg->origin,
     426             :                                 mdigest,
     427             :                                 (long)mpos,
     428             :                                 (long)fpos,
     429             :                                 (long)mlen,
     430          31 :                                 pkg->sum);
     431             : 
     432          31 :                         free(mdigest);
     433          31 :                         mdigest = NULL;
     434          31 :                         iov[0].iov_base = digestbuf;
     435          31 :                         iov[0].iov_len = r;
     436          31 :                         memset(&msg, 0, sizeof(msg));
     437          31 :                         msg.msg_iov = iov;
     438          31 :                         msg.msg_iovlen = 1;
     439          31 :                         sendmsg(pip, &msg, MSG_EOR);
     440             :                 }
     441          31 :                 cur_job ++;
     442             :         }
     443             : 
     444             : cleanup:
     445          20 :         pkg_manifest_keys_free(keys);
     446             : 
     447          20 :         write(pip, ".\n", 2);
     448          20 :         close(pip);
     449          20 :         close(mfd);
     450          20 :         if (read_files)
     451           0 :                 close(ffd);
     452          20 :         free(mdigest);
     453             : 
     454          20 :         pkg_debug(1, "worker done");
     455          20 :         exit(ret);
     456             : }
     457             : 
     458             : static int
     459          35 : pkg_create_repo_read_pipe(int fd, struct digest_list_entry **dlist)
     460             : {
     461          35 :         struct digest_list_entry *dig = NULL;
     462             :         char buf[1024];
     463             :         int r, i, start;
     464             :         enum {
     465             :                 s_set_origin = 0,
     466             :                 s_set_digest,
     467             :                 s_set_mpos,
     468             :                 s_set_fpos,
     469             :                 s_set_mlen,
     470             :                 s_set_checksum
     471          35 :         } state = 0;
     472             : 
     473             :         for (;;) {
     474          66 :                 r = read(fd, buf, sizeof(buf));
     475             : 
     476          66 :                 if (r == -1) {
     477          15 :                         if (errno == EINTR)
     478           0 :                                 continue;
     479          15 :                         else if (errno == ECONNRESET) {
     480             :                                 /* Treat it as the end of a connection */
     481           0 :                                 return (EPKG_END);
     482             :                         }
     483          15 :                         else if (errno == EAGAIN || errno == EWOULDBLOCK)
     484          15 :                                 return (EPKG_OK);
     485             : 
     486           0 :                         pkg_emit_errno("pkg_create_repo_read_pipe", "read");
     487           0 :                         return (EPKG_FATAL);
     488             :                 }
     489          51 :                 else if (r == 0)
     490           0 :                         return (EPKG_END);
     491             : 
     492             :                 /*
     493             :                  * XXX: can parse merely full lines
     494             :                  */
     495          51 :                 start = 0;
     496        4461 :                 for (i = 0; i < r; i ++) {
     497        4461 :                         if (buf[i] == ':') {
     498         155 :                                 switch(state) {
     499             :                                 case s_set_origin:
     500          31 :                                         dig = calloc(1, sizeof(*dig));
     501          31 :                                         dig->origin = malloc(i - start + 1);
     502          31 :                                         strlcpy(dig->origin, &buf[start], i - start + 1);
     503          31 :                                         state = s_set_digest;
     504          31 :                                         break;
     505             :                                 case s_set_digest:
     506          31 :                                         dig->digest = malloc(i - start + 1);
     507          31 :                                         strlcpy(dig->digest, &buf[start], i - start + 1);
     508          31 :                                         state = s_set_mpos;
     509          31 :                                         break;
     510             :                                 case s_set_mpos:
     511          31 :                                         dig->manifest_pos = strtol(&buf[start], NULL, 10);
     512          31 :                                         state = s_set_fpos;
     513          31 :                                         break;
     514             :                                 case s_set_fpos:
     515          31 :                                         dig->files_pos = strtol(&buf[start], NULL, 10);
     516          31 :                                         state = s_set_mlen;
     517          31 :                                         break;
     518             :                                 case s_set_mlen:
     519          31 :                                         dig->manifest_length = strtol(&buf[start], NULL, 10);
     520          31 :                                         state = s_set_checksum;
     521          31 :                                         break;
     522             :                                 case s_set_checksum:
     523           0 :                                         dig->checksum =  malloc(i - start + 1);
     524           0 :                                         strlcpy(dig->digest, &buf[start], i - start + 1);
     525           0 :                                         state = s_set_origin;
     526           0 :                                         break;
     527             :                                 }
     528         155 :                                 start = i + 1;
     529             :                         }
     530        4306 :                         else if (buf[i] == '\n') {
     531          31 :                                 if (state == s_set_mlen) {
     532           0 :                                         dig->manifest_length = strtol(&buf[start], NULL, 10);
     533             :                                 }
     534          31 :                                 else if (state == s_set_checksum) {
     535          31 :                                         dig->checksum =  malloc(i - start + 1);
     536          31 :                                         strlcpy(dig->checksum, &buf[start], i - start + 1);
     537             :                                 }
     538          31 :                                 assert(dig->origin != NULL);
     539          31 :                                 assert(dig->digest != NULL);
     540          31 :                                 DL_APPEND(*dlist, dig);
     541          31 :                                 state = s_set_origin;
     542          31 :                                 start = i + 1;
     543          31 :                                 break;
     544             :                         }
     545        4275 :                         else if (buf[i] == '.' && buf[i + 1] == '\n') {
     546          20 :                                 return (EPKG_END);
     547             :                         }
     548             :                 }
     549          31 :         }
     550             : 
     551             :         /*
     552             :          * Never reached
     553             :          */
     554             :         return (EPKG_OK);
     555             : }
     556             : 
     557             : int
     558          31 : pkg_create_repo(char *path, const char *output_dir, bool filelist,
     559             :         const char *metafile, bool legacy)
     560             : {
     561          31 :         FTS *fts = NULL;
     562          31 :         struct pkg_fts_item *fts_items = NULL, *fts_cur, *fts_start;
     563             : 
     564             :         struct pkg_conflict *c, *ctmp;
     565          31 :         struct pkg_conflict_bulk *conflicts = NULL, *curcb, *tmpcb;
     566             :         int num_workers, i, remaining_workers, remain, cur_jobs, remain_jobs, nworker;
     567             :         size_t len, tasks_per_worker, ntask;
     568          31 :         struct digest_list_entry *dlist = NULL, *cur_dig, *dtmp;
     569          31 :         struct pollfd *pfd = NULL;
     570             :         int cur_pipe[2], fd;
     571          31 :         struct pkg_repo_meta *meta = NULL;
     572          31 :         int retcode = EPKG_OK;
     573             : 
     574             :         char *repopath[2];
     575             :         char packagesite[MAXPATHLEN],
     576             :                  filesite[MAXPATHLEN],
     577             :                  repodb[MAXPATHLEN];
     578          31 :         FILE *mandigests = NULL;
     579             : 
     580          31 :         if (!is_dir(path)) {
     581           0 :                 pkg_emit_error("%s is not a directory", path);
     582           0 :                 return (EPKG_FATAL);
     583             :         }
     584             : 
     585          31 :         errno = 0;
     586          31 :         if (!is_dir(output_dir)) {
     587             :                 /* Try to create dir */
     588           0 :                 if (errno == ENOENT) {
     589           0 :                         if (mkdir(output_dir, 00755) == -1) {
     590           0 :                                 pkg_emit_error("cannot create output directory %s: %s",
     591           0 :                                         output_dir, strerror(errno));
     592           0 :                                 return (EPKG_FATAL);
     593             :                         }
     594             :                 }
     595             :                 else {
     596           0 :                         pkg_emit_error("%s is not a directory", output_dir);
     597           0 :                         return (EPKG_FATAL);
     598             :                 }
     599             :         }
     600             : 
     601          31 :         if (metafile != NULL) {
     602           0 :                 if (pkg_repo_meta_load(metafile, &meta) != EPKG_OK) {
     603           0 :                         pkg_emit_error("meta loading error while trying %s", metafile);
     604           0 :                         return (EPKG_FATAL);
     605             :                 }
     606             :         }
     607             :         else {
     608          31 :                 meta = pkg_repo_meta_default();
     609             :         }
     610             : 
     611          31 :         repopath[0] = path;
     612          31 :         repopath[1] = NULL;
     613             : 
     614          31 :         num_workers = pkg_object_int(pkg_config_get("WORKERS_COUNT"));
     615          31 :         if (num_workers <= 0) {
     616          31 :                 len = sizeof(num_workers);
     617             : #ifdef HAVE_SYSCTLBYNAME
     618          31 :                 if (sysctlbyname("hw.ncpu", &num_workers, &len, NULL, 0) == -1)
     619           0 :                         num_workers = 6;
     620             : #else
     621             :                 num_workers = 6;
     622             : #endif
     623             :         }
     624             : 
     625          31 :         if ((fts = fts_open(repopath, FTS_PHYSICAL|FTS_NOCHDIR, NULL)) == NULL) {
     626           0 :                 pkg_emit_errno("fts_open", path);
     627           0 :                 retcode = EPKG_FATAL;
     628           0 :                 goto cleanup;
     629             :         }
     630             : 
     631          31 :         snprintf(packagesite, sizeof(packagesite), "%s/%s", output_dir,
     632          31 :             meta->manifests);
     633          31 :         if ((fd = open(packagesite, O_CREAT|O_TRUNC|O_WRONLY, 00644)) == -1) {
     634           0 :                 retcode = EPKG_FATAL;
     635           0 :                 goto cleanup;
     636             :         }
     637          31 :         close(fd);
     638          31 :         if (filelist) {
     639           0 :                 snprintf(filesite, sizeof(filesite), "%s/%s", output_dir,
     640           0 :                     meta->filesite);
     641           0 :                 if ((fd = open(filesite, O_CREAT|O_TRUNC|O_WRONLY, 00644)) == -1) {
     642           0 :                         retcode = EPKG_FATAL;
     643           0 :                         goto cleanup;
     644             :                 }
     645           0 :                 close(fd);
     646             :         }
     647          31 :         snprintf(repodb, sizeof(repodb), "%s/%s", output_dir,
     648          31 :             meta->digests);
     649          31 :         if ((mandigests = fopen(repodb, "w")) == NULL) {
     650           0 :                 retcode = EPKG_FATAL;
     651           0 :                 goto cleanup;
     652             :         }
     653             : 
     654          31 :         len = 0;
     655             : 
     656          31 :         pkg_create_repo_read_fts(&fts_items, fts, path, &len, meta);
     657             : 
     658          31 :         if (len == 0) {
     659             :                 /* Nothing to do */
     660           0 :                 pkg_emit_error("No package files have been found");
     661           0 :                 retcode = EPKG_FATAL;
     662           0 :                 goto cleanup;
     663             :         }
     664             : 
     665             :         /* Split items over all workers */
     666          31 :         num_workers = MIN(num_workers, len);
     667          31 :         tasks_per_worker = len / num_workers;
     668             :         /* How much extra tasks should be distributed over the workers */
     669          31 :         remain = len % num_workers;
     670          31 :         assert(tasks_per_worker > 0);
     671             : 
     672             :         /* Launch workers */
     673          31 :         pkg_emit_progress_start("Creating repository in %s", output_dir);
     674             : 
     675          31 :         pfd = calloc(num_workers, sizeof(struct pollfd));
     676          31 :         ntask = 0;
     677          31 :         cur_jobs = (remain > 0) ? tasks_per_worker + 1 : tasks_per_worker;
     678          31 :         remain_jobs = cur_jobs;
     679          31 :         fts_start = fts_items;
     680          31 :         nworker = 0;
     681             : 
     682          89 :         LL_FOREACH(fts_items, fts_cur) {
     683          78 :                 if (--remain_jobs == 0) {
     684             :                         /* Create new worker */
     685             :                         int ofl;
     686          49 :                         int st = SOCK_DGRAM;
     687             : 
     688             : #ifdef HAVE_SEQPACKET
     689          49 :                         st = SOCK_SEQPACKET;
     690             : #endif
     691          49 :                         if (socketpair(AF_UNIX, st, 0, cur_pipe) == -1) {
     692           0 :                                 pkg_emit_errno("pkg_create_repo", "pipe");
     693           0 :                                 retcode = EPKG_FATAL;
     694           0 :                                 goto cleanup;
     695             :                         }
     696             : 
     697          49 :                         if (pkg_create_repo_worker(fts_start, cur_jobs,
     698             :                                         packagesite, (filelist ? filesite : NULL), cur_pipe[1],
     699             :                                         (legacy ? NULL : meta)) == EPKG_FATAL) {
     700           0 :                                 close(cur_pipe[0]);
     701           0 :                                 close(cur_pipe[1]);
     702           0 :                                 retcode = EPKG_FATAL;
     703           0 :                                 goto cleanup;
     704             :                         }
     705             : 
     706          29 :                         pfd[nworker].fd = cur_pipe[0];
     707          29 :                         pfd[nworker].events = POLLIN;
     708          29 :                         close(cur_pipe[1]);
     709             :                         /* Make our end of the pipe non-blocking */
     710          29 :                         ofl = fcntl(cur_pipe[0], F_GETFL, 0);
     711          29 :                         fcntl(cur_pipe[0], F_SETFL, ofl | O_NONBLOCK);
     712             : 
     713          29 :                         if (--remain > 0)
     714           0 :                                 cur_jobs = tasks_per_worker + 1;
     715             :                         else
     716          29 :                                 cur_jobs = tasks_per_worker;
     717             : 
     718          29 :                         remain_jobs = cur_jobs;
     719          29 :                         fts_start = fts_cur->next;
     720          29 :                         nworker ++;
     721             :                 }
     722          58 :                 ntask ++;
     723             :         }
     724             : 
     725             :         /* Send start marker to all workers */
     726          31 :         for (i = 0; i < num_workers; i ++) {
     727          20 :                 if (write(pfd[i].fd, ".", 1) == -1)
     728           0 :                         pkg_emit_errno("pkg_create_repo", "write");
     729             :         }
     730             : 
     731          11 :         ntask = 0;
     732          11 :         remaining_workers = num_workers;
     733          56 :         while(remaining_workers > 0) {
     734             :                 int st;
     735             : 
     736          34 :                 pkg_debug(1, "checking for %d workers", remaining_workers);
     737          34 :                 retcode = poll(pfd, num_workers, -1);
     738          34 :                 if (retcode == -1) {
     739           0 :                         if (errno == EINTR) {
     740           0 :                                 continue;
     741             :                         }
     742             :                         else {
     743           0 :                                 retcode = EPKG_FATAL;
     744           0 :                                 goto cleanup;
     745             :                         }
     746             :                 }
     747          34 :                 else if (retcode > 0) {
     748         100 :                         for (i = 0; i < num_workers; i ++) {
     749         123 :                                 if (pfd[i].fd != -1 &&
     750          57 :                                                                 (pfd[i].revents & (POLLIN|POLLHUP|POLLERR))) {
     751          35 :                                         if (pkg_create_repo_read_pipe(pfd[i].fd, &dlist) != EPKG_OK) {
     752             :                                                 /*
     753             :                                                  * Wait for the worker finished
     754             :                                                  */
     755             : 
     756          40 :                                                 while (wait(&st) == -1) {
     757           0 :                                                         if (errno == EINTR)
     758           0 :                                                                 continue;
     759             : 
     760           0 :                                                         pkg_emit_errno("pkg_create_repo", "wait");
     761           0 :                                                         break;
     762             :                                                 }
     763             : 
     764          20 :                                                 remaining_workers --;
     765          20 :                                                 pkg_debug(1, "finished worker, %d remaining",
     766             :                                                         remaining_workers);
     767          20 :                                                 pfd[i].events = 0;
     768          20 :                                                 pfd[i].revents = 0;
     769          20 :                                                 close(pfd[i].fd);
     770          20 :                                                 pfd[i].fd = -1;
     771             :                                         }
     772             :                                         else {
     773          15 :                                                 pkg_emit_progress_tick(ntask++, len);
     774             :                                         }
     775             :                                 }
     776             :                         }
     777             :                 }
     778             :         }
     779             : 
     780          11 :         pkg_emit_progress_tick(len, len);
     781          11 :         retcode = EPKG_OK;
     782             : 
     783             :         /* Now sort all digests */
     784          11 :         DL_SORT(dlist, pkg_digest_sort_compare_func);
     785             : 
     786             :         /*
     787             :          * XXX: it is not used actually
     788             :          */
     789             : #if 0
     790             :         pkg_repo_write_conflicts(conflicts, fconflicts);
     791             : #endif
     792             : 
     793             :         /* Write metafile */
     794          11 :         if (!legacy) {
     795             :                 ucl_object_t *meta_dump;
     796             :                 FILE *mfile;
     797             : 
     798          11 :                 snprintf(repodb, sizeof(repodb), "%s/%s", output_dir,
     799             :                         "meta");
     800          11 :                 if ((mfile = fopen(repodb, "w")) != NULL) {
     801          11 :                         meta_dump = pkg_repo_meta_to_ucl(meta);
     802          11 :                         ucl_object_emit_file(meta_dump, UCL_EMIT_CONFIG, mfile);
     803          11 :                         ucl_object_unref(meta_dump);
     804          11 :                         fclose(mfile);
     805             :                 }
     806             :                 else {
     807           0 :                         pkg_emit_notice("cannot create metafile at %s", repodb);
     808             :                 }
     809             :         }
     810             : cleanup:
     811          11 :         HASH_ITER (hh, conflicts, curcb, tmpcb) {
     812           0 :                 HASH_ITER (hh, curcb->conflicts, c, ctmp) {
     813           0 :                         free(c->uid);
     814           0 :                         HASH_DEL(curcb->conflicts, c);
     815           0 :                         free(c);
     816             :                 }
     817           0 :                 HASH_DEL(conflicts, curcb);
     818           0 :                 free(curcb);
     819             :         }
     820             : 
     821          11 :         if (pfd != NULL)
     822          11 :                 free(pfd);
     823          11 :         if (fts != NULL)
     824          11 :                 fts_close(fts);
     825             : 
     826          11 :         LL_FREE(fts_items, pkg_create_repo_fts_free);
     827          42 :         LL_FOREACH_SAFE(dlist, cur_dig, dtmp) {
     828          31 :                 if (cur_dig->checksum != NULL)
     829          31 :                         fprintf(mandigests, "%s:%s:%ld:%ld:%ld:%s\n", cur_dig->origin,
     830             :                                 cur_dig->digest, cur_dig->manifest_pos, cur_dig->files_pos,
     831             :                                 cur_dig->manifest_length, cur_dig->checksum);
     832             :                 else
     833           0 :                         fprintf(mandigests, "%s:%s:%ld:%ld:%ld\n", cur_dig->origin,
     834             :                                 cur_dig->digest, cur_dig->manifest_pos, cur_dig->files_pos,
     835             :                                 cur_dig->manifest_length);
     836             : 
     837          31 :                 free(cur_dig->digest);
     838          31 :                 free(cur_dig->origin);
     839          31 :                 free(cur_dig);
     840             :         }
     841             : 
     842          11 :         pkg_repo_meta_free(meta);
     843             : 
     844          11 :         if (mandigests != NULL)
     845          11 :                 fclose(mandigests);
     846             : 
     847          11 :         return (retcode);
     848             : }
     849             : 
     850             : 
     851             : static int
     852           0 : pkg_repo_sign(char *path, char **argv, int argc, struct sbuf **sig, struct sbuf **cert)
     853             : {
     854             :         FILE *fp;
     855             :         char *sha256;
     856           0 :         struct sbuf *cmd = NULL;
     857           0 :         struct sbuf *buf = NULL;
     858           0 :         char *line = NULL;
     859           0 :         size_t linecap = 0;
     860             :         ssize_t linelen;
     861           0 :         int i, ret = EPKG_OK;
     862             : 
     863           0 :         sha256 = pkg_checksum_file(path, PKG_HASH_TYPE_SHA256_HEX);
     864           0 :         if (!sha256)
     865           0 :                 return (EPKG_FATAL);
     866             : 
     867           0 :         cmd = sbuf_new_auto();
     868             : 
     869           0 :         for (i = 0; i < argc; i++) {
     870           0 :                 if (strspn(argv[i], " \t\n") > 0)
     871           0 :                         sbuf_printf(cmd, " \"%s\" ", argv[i]);
     872             :                 else
     873           0 :                         sbuf_printf(cmd, " %s ", argv[i]);
     874             :         }
     875           0 :         sbuf_finish(cmd);
     876             : 
     877           0 :         if ((fp = popen(sbuf_data(cmd), "r+")) == NULL) {
     878           0 :                 ret = EPKG_FATAL;
     879           0 :                 goto done;
     880             :         }
     881             : 
     882           0 :         fprintf(fp, "%s\n", sha256);
     883             : 
     884           0 :         if (*sig == NULL)
     885           0 :                 *sig = sbuf_new_auto();
     886           0 :         if (*cert == NULL)
     887           0 :                 *cert = sbuf_new_auto();
     888             : 
     889           0 :         while ((linelen = getline(&line, &linecap, fp)) > 0 ) {
     890           0 :                 if (strcmp(line, "SIGNATURE\n") == 0) {
     891           0 :                         buf = *sig;
     892           0 :                         continue;
     893           0 :                 } else if (strcmp(line, "CERT\n") == 0) {
     894           0 :                         buf = *cert;
     895           0 :                         continue;
     896           0 :                 } else if (strcmp(line, "END\n") == 0) {
     897           0 :                         break;
     898             :                 }
     899           0 :                 if (buf != NULL)
     900           0 :                         sbuf_bcat(buf, line, linelen);
     901             :         }
     902             : 
     903           0 :         if (pclose(fp) != 0) {
     904           0 :                 ret = EPKG_FATAL;
     905           0 :                 goto done;
     906             :         }
     907             : 
     908           0 :         if (sbuf_data(*sig)[sbuf_len(*sig) -1 ] == '\n')
     909           0 :                 sbuf_setpos(*sig, sbuf_len(*sig) -1);
     910             : 
     911           0 :         sbuf_finish(*sig);
     912           0 :         sbuf_finish(*cert);
     913             : done:
     914           0 :         free(sha256);
     915           0 :         if (cmd)
     916           0 :                 sbuf_delete(cmd);
     917             : 
     918           0 :         return (ret);
     919             : }
     920             : 
     921             : static int
     922          33 : pkg_repo_pack_db(const char *name, const char *archive, char *path,
     923             :                 struct rsa_key *rsa, struct pkg_repo_meta *meta,
     924             :                 char **argv, int argc)
     925             : {
     926             :         struct packing *pack;
     927          33 :         unsigned char *sigret = NULL;
     928          33 :         unsigned int siglen = 0;
     929             :         char fname[MAXPATHLEN];
     930             :         struct sbuf *sig, *pub;
     931             : 
     932          33 :         sig = NULL;
     933          33 :         pub = NULL;
     934             : 
     935          33 :         if (packing_init(&pack, archive, meta->packing_format, false) != EPKG_OK)
     936           0 :                 return (EPKG_FATAL);
     937             : 
     938          33 :         if (rsa != NULL) {
     939           0 :                 if (rsa_sign(path, rsa, &sigret, &siglen) != EPKG_OK) {
     940           0 :                         packing_finish(pack);
     941           0 :                         unlink(path);
     942           0 :                         return (EPKG_FATAL);
     943             :                 }
     944             : 
     945           0 :                 if (packing_append_buffer(pack, sigret, "signature", siglen + 1) != EPKG_OK) {
     946           0 :                         free(sigret);
     947           0 :                         free(pack);
     948           0 :                         unlink(path);
     949           0 :                         return (EPKG_FATAL);
     950             :                 }
     951             : 
     952           0 :                 free(sigret);
     953          33 :         } else if (argc >= 1) {
     954           0 :                 if (pkg_repo_sign(path, argv, argc, &sig, &pub) != EPKG_OK) {
     955           0 :                         packing_finish(pack);
     956           0 :                         unlink(path);
     957           0 :                         return (EPKG_FATAL);
     958             :                 }
     959             : 
     960           0 :                 snprintf(fname, sizeof(fname), "%s.sig", name);
     961           0 :                 if (packing_append_buffer(pack, sbuf_data(sig), fname, sbuf_len(sig)) != EPKG_OK) {
     962           0 :                         packing_finish(pack);
     963           0 :                         sbuf_delete(sig);
     964           0 :                         sbuf_delete(pub);
     965           0 :                         unlink(path);
     966           0 :                         return (EPKG_FATAL);
     967             :                 }
     968             : 
     969           0 :                 snprintf(fname, sizeof(fname), "%s.pub", name);
     970           0 :                 if (packing_append_buffer(pack, sbuf_data(pub), fname, sbuf_len(pub)) != EPKG_OK) {
     971           0 :                         packing_finish(pack);
     972           0 :                         unlink(path);
     973           0 :                         sbuf_delete(sig);
     974           0 :                         sbuf_delete(pub);
     975           0 :                         return (EPKG_FATAL);
     976             :                 }
     977             : 
     978             :         }
     979          33 :         packing_append_file_attr(pack, path, name, "root", "wheel", 0644, 0);
     980             : 
     981          33 :         packing_finish(pack);
     982          33 :         unlink(path);
     983          33 :         if (sig != NULL)
     984           0 :                 sbuf_delete(sig);
     985          33 :         if (pub != NULL)
     986           0 :                 sbuf_delete(pub);
     987             : 
     988          33 :         return (EPKG_OK);
     989             : }
     990             : 
     991             : int
     992          11 : pkg_finish_repo(const char *output_dir, pem_password_cb *password_cb,
     993             :     char **argv, int argc, bool filelist)
     994             : {
     995             :         char repo_path[MAXPATHLEN];
     996             :         char repo_archive[MAXPATHLEN];
     997          11 :         struct rsa_key *rsa = NULL;
     998             :         struct pkg_repo_meta *meta;
     999             :         struct stat st;
    1000          11 :         int ret = EPKG_OK, nfile = 0;
    1001          11 :         const int files_to_pack = 4;
    1002          11 :         bool legacy = false;
    1003             : 
    1004          11 :         if (!is_dir(output_dir)) {
    1005           0 :                 pkg_emit_error("%s is not a directory", output_dir);
    1006           0 :                 return (EPKG_FATAL);
    1007             :         }
    1008             : 
    1009          11 :         if (argc == 1) {
    1010           0 :                 rsa_new(&rsa, password_cb, argv[0]);
    1011             :         }
    1012             : 
    1013          11 :         if (argc > 1 && strcmp(argv[0], "signing_command:") != 0)
    1014           0 :                 return (EPKG_FATAL);
    1015             : 
    1016          11 :         if (argc > 1) {
    1017           0 :                 argc--;
    1018           0 :                 argv++;
    1019             :         }
    1020             : 
    1021          11 :         pkg_emit_progress_start("Packing files for repository");
    1022          11 :         pkg_emit_progress_tick(nfile++, files_to_pack);
    1023             : 
    1024          11 :         snprintf(repo_path, sizeof(repo_path), "%s/%s", output_dir,
    1025             :                 repo_meta_file);
    1026             :         /*
    1027             :          * If no meta is defined, then it is a legacy repo
    1028             :          */
    1029          11 :         if (access(repo_path, R_OK) != -1) {
    1030          11 :                 if (pkg_repo_meta_load(repo_path, &meta) != EPKG_OK) {
    1031           0 :                         pkg_emit_error("meta loading error while trying %s", repo_path);
    1032           0 :                         rsa_free(rsa);
    1033           0 :                         return (EPKG_FATAL);
    1034             :                 }
    1035             :                 else {
    1036          11 :                         meta = pkg_repo_meta_default();
    1037             :                 }
    1038          11 :                 if (pkg_repo_pack_db(repo_meta_file, repo_path, repo_path, rsa, meta,
    1039             :                         argv, argc) != EPKG_OK) {
    1040           0 :                         ret = EPKG_FATAL;
    1041           0 :                         goto cleanup;
    1042             :                 }
    1043             :         }
    1044             :         else {
    1045           0 :                 legacy = true;
    1046           0 :                 meta = pkg_repo_meta_default();
    1047             :         }
    1048             : 
    1049          11 :         snprintf(repo_path, sizeof(repo_path), "%s/%s", output_dir,
    1050          11 :             meta->manifests);
    1051          11 :         snprintf(repo_archive, sizeof(repo_archive), "%s/%s", output_dir,
    1052          11 :                 meta->manifests_archive);
    1053          11 :         if (pkg_repo_pack_db(meta->manifests, repo_archive, repo_path, rsa, meta,
    1054             :                 argv, argc) != EPKG_OK) {
    1055           0 :                 ret = EPKG_FATAL;
    1056           0 :                 goto cleanup;
    1057             :         }
    1058             : 
    1059          11 :         pkg_emit_progress_tick(nfile++, files_to_pack);
    1060             : 
    1061          11 :         if (filelist) {
    1062           0 :                 snprintf(repo_path, sizeof(repo_path), "%s/%s", output_dir,
    1063           0 :                     meta->filesite);
    1064           0 :                 snprintf(repo_archive, sizeof(repo_archive), "%s/%s",
    1065           0 :                     output_dir, meta->filesite_archive);
    1066           0 :                 if (pkg_repo_pack_db(meta->filesite, repo_archive, repo_path, rsa, meta,
    1067             :                         argv, argc) != EPKG_OK) {
    1068           0 :                         ret = EPKG_FATAL;
    1069           0 :                         goto cleanup;
    1070             :                 }
    1071             :         }
    1072             : 
    1073          11 :         pkg_emit_progress_tick(nfile++, files_to_pack);
    1074             : 
    1075          11 :         snprintf(repo_path, sizeof(repo_path), "%s/%s", output_dir,
    1076          11 :             meta->digests);
    1077          11 :         snprintf(repo_archive, sizeof(repo_archive), "%s/%s", output_dir,
    1078          11 :             meta->digests_archive);
    1079          11 :         if (pkg_repo_pack_db(meta->digests, repo_archive, repo_path, rsa, meta,
    1080             :                 argv, argc) != EPKG_OK) {
    1081           0 :                 ret = EPKG_FATAL;
    1082           0 :                 goto cleanup;
    1083             :         }
    1084             : 
    1085          11 :         pkg_emit_progress_tick(nfile++, files_to_pack);
    1086             : 
    1087             : #if 0
    1088             :         snprintf(repo_path, sizeof(repo_path), "%s/%s", output_dir,
    1089             :                 meta->conflicts);
    1090             :         snprintf(repo_archive, sizeof(repo_archive), "%s/%s", output_dir,
    1091             :                 meta->conflicts_archive);
    1092             :         if (pkg_repo_pack_db(meta->conflicts, repo_archive, repo_path, rsa, meta,
    1093             :                 argv, argc) != EPKG_OK) {
    1094             :                 ret = EPKG_FATAL;
    1095             :                 goto cleanup;
    1096             :         }
    1097             : #endif
    1098             : 
    1099             :         /* Now we need to set the equal mtime for all archives in the repo */
    1100          11 :         snprintf(repo_archive, sizeof(repo_archive), "%s/%s.txz",
    1101             :             output_dir, repo_meta_file);
    1102          11 :         if (stat(repo_archive, &st) == 0) {
    1103          22 :                 struct timeval ftimes[2] = {
    1104             :                         {
    1105          11 :                         .tv_sec = st.st_mtime,
    1106             :                         .tv_usec = 0
    1107             :                         },
    1108             :                         {
    1109          11 :                         .tv_sec = st.st_mtime,
    1110             :                         .tv_usec = 0
    1111             :                         }
    1112             :                 };
    1113          11 :                 snprintf(repo_archive, sizeof(repo_archive), "%s/%s.txz",
    1114          11 :                     output_dir, meta->manifests_archive);
    1115          11 :                 utimes(repo_archive, ftimes);
    1116          11 :                 snprintf(repo_archive, sizeof(repo_archive), "%s/%s.txz",
    1117          11 :                     output_dir, meta->digests_archive);
    1118          11 :                 utimes(repo_archive, ftimes);
    1119          11 :                 if (filelist) {
    1120           0 :                         snprintf(repo_archive, sizeof(repo_archive),
    1121           0 :                             "%s/%s.txz", output_dir, meta->filesite_archive);
    1122           0 :                         utimes(repo_archive, ftimes);
    1123             :                 }
    1124          11 :                 if (!legacy) {
    1125          11 :                         snprintf(repo_archive, sizeof(repo_archive),
    1126             :                                 "%s/%s.txz", output_dir, repo_meta_file);
    1127          11 :                         utimes(repo_archive, ftimes);
    1128             :                 }
    1129             :         }
    1130             : 
    1131             : cleanup:
    1132          11 :         pkg_emit_progress_tick(files_to_pack, files_to_pack);
    1133          11 :         pkg_repo_meta_free(meta);
    1134             : 
    1135          11 :         rsa_free(rsa);
    1136             : 
    1137          11 :         return (ret);
    1138             : }

Generated by: LCOV version 1.10