LCOV - code coverage report
Current view: top level - libpkg - pkg_add.c (source / functions) Hit Total Coverage
Test: rapport Lines: 599 883 67.8 %
Date: 2021-12-10 16:22:55 Functions: 32 34 94.1 %
Branches: 337 614 54.9 %

           Branch data     Line data    Source code
       1                 :            : /*-
       2                 :            :  * Copyright (c) 2011-2020 Baptiste Daroussin <bapt@FreeBSD.org>
       3                 :            :  * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
       4                 :            :  * Copyright (c) 2016, Vsevolod Stakhov
       5                 :            :  *
       6                 :            :  * Redistribution and use in source and binary forms, with or without
       7                 :            :  * modification, are permitted provided that the following conditions
       8                 :            :  * are met:
       9                 :            :  * 1. Redistributions of source code must retain the above copyright
      10                 :            :  *    notice, this list of conditions and the following disclaimer
      11                 :            :  *    in this position and unchanged.
      12                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      13                 :            :  *    notice, this list of conditions and the following disclaimer in the
      14                 :            :  *    documentation and/or other materials provided with the distribution.
      15                 :            :  *
      16                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
      17                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      18                 :            :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      19                 :            :  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
      20                 :            :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      21                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      22                 :            :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      23                 :            :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      24                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      25                 :            :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      26                 :            :  */
      27                 :            : 
      28                 :            : #ifdef HAVE_CONFIG_H
      29                 :            : #include "pkg_config.h"
      30                 :            : #endif
      31                 :            : 
      32                 :            : #include <archive.h>
      33                 :            : #include <archive_entry.h>
      34                 :            : #include <assert.h>
      35                 :            : #include <libgen.h>
      36                 :            : #include <string.h>
      37                 :            : #include <errno.h>
      38                 :            : #include <fcntl.h>
      39                 :            : #include <glob.h>
      40                 :            : #include <pwd.h>
      41                 :            : #include <grp.h>
      42                 :            : #include <sys/time.h>
      43                 :            : #include <time.h>
      44                 :            : #include <xstring.h>
      45                 :            : 
      46                 :            : #include "pkg.h"
      47                 :            : #include "private/event.h"
      48                 :            : #include "private/utils.h"
      49                 :            : #include "private/pkg.h"
      50                 :            : #include "private/pkgdb.h"
      51                 :            : 
      52   [ +  -  +  +  :         92 : KHASH_MAP_INIT_INT(hls, char *);
          -  +  -  +  -  
          +  #  #  -  +  
          -  +  -  +  #  
          #  +  -  +  -  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  +  -  #  #  
          -  +  -  +  +  
          -  +  -  +  -  
          -  +  +  -  -  
          +  -  +  -  +  
          #  #  #  #  #  
             #  #  #  +  
                      - ]
      53                 :            : 
      54                 :            : #if defined(UF_NOUNLINK)
      55                 :            : #define NOCHANGESFLAGS  (UF_IMMUTABLE | UF_APPEND | UF_NOUNLINK | SF_IMMUTABLE | SF_APPEND | SF_NOUNLINK)
      56                 :            : #else
      57                 :            : #define NOCHANGESFLAGS  (UF_IMMUTABLE | UF_APPEND | SF_IMMUTABLE | SF_APPEND)
      58                 :            : #endif
      59                 :            : 
      60                 :            : static const unsigned char litchar[] =
      61                 :            : "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
      62                 :            : 
      63                 :            : static void
      64                 :        531 : pkg_add_file_random_suffix(char *buf, int buflen, int suflen)
      65                 :            : {
      66                 :        531 :         int nchars = strlen(buf);
      67                 :            :         char *pos;
      68                 :            :         int r;
      69                 :            : 
      70         [ +  - ]:        531 :         if (nchars + suflen > buflen - 1) {
      71                 :          0 :                 suflen = buflen - nchars - 1;
      72         [ #  # ]:          0 :                 if (suflen <= 0)
      73                 :          0 :                         return;
      74                 :          0 :         }
      75                 :            : 
      76                 :        531 :         buf[nchars++] = '.';
      77                 :        531 :         pos = buf + nchars;
      78                 :            : 
      79         [ +  + ]:       6903 :         while(suflen --) {
      80                 :            : #ifndef HAVE_ARC4RANDOM
      81                 :            :                 r = rand() % (sizeof(litchar) - 1);
      82                 :            : #else
      83                 :       6372 :                 r = arc4random_uniform(sizeof(litchar) - 1);
      84                 :            : #endif
      85                 :       6372 :                 *pos++ = litchar[r];
      86                 :            :         }
      87                 :            : 
      88                 :        531 :         *pos = '\0';
      89                 :        531 : }
      90                 :            : 
      91                 :            : static void
      92                 :        531 : pkg_hidden_tempfile(char *buf, int buflen, const char *path)
      93                 :            : {
      94                 :            :         const char *fname;
      95                 :            : 
      96                 :        531 :         fname = strrchr(path, '/');
      97         [ -  + ]:        531 :         if (fname != NULL)
      98                 :        531 :                 fname++;
      99                 :            : 
     100         [ -  + ]:        531 :         if (fname != NULL)
     101                 :        531 :                 snprintf(buf, buflen, "%.*s.pkgtemp.%s", (int)(fname - path), path, fname);
     102                 :            :         else
     103                 :          0 :                 snprintf(buf, buflen, ".pkgtemp.%s", path);
     104                 :            : 
     105                 :        531 :         pkg_add_file_random_suffix(buf, buflen, 12);
     106                 :        531 : }
     107                 :            : 
     108                 :            : static void
     109                 :         42 : attempt_to_merge(int rootfd, struct pkg_config_file *rcf, struct pkg *local,
     110                 :            :     bool merge)
     111                 :            : {
     112                 :         42 :         const struct pkg_file *lf = NULL;
     113                 :            :         struct stat st;
     114                 :            :         xstring *newconf;
     115                 :         42 :         struct pkg_config_file *lcf = NULL;
     116                 :            : 
     117                 :         42 :         char *localconf = NULL;
     118                 :            :         off_t sz;
     119                 :            :         char *localsum;
     120                 :            : 
     121         [ +  - ]:         42 :         if (rcf == NULL) {
     122                 :          0 :                 pkg_debug(3, "No remote config file");
     123                 :          0 :                 return;
     124                 :            :         }
     125                 :            : 
     126         [ +  + ]:         42 :         if (local == NULL) {
     127                 :         20 :                 pkg_debug(3, "No local package");
     128         [ +  + ]:         20 :                 if (fstatat(rootfd, RELATIVE_PATH(rcf->path), &st, 0) == 0) {
     129                 :          5 :                         rcf->status = MERGE_NOT_LOCAL;
     130                 :          5 :                 }
     131                 :         20 :                 return;
     132                 :            :         }
     133                 :            : 
     134         [ +  + ]:         22 :         if (!pkg_is_config_file(local, rcf->path, &lf, &lcf)) {
     135                 :         10 :                 pkg_debug(3, "No local package");
     136                 :         10 :                 rcf->status = MERGE_FAILED;
     137                 :         10 :                 return;
     138                 :            :         }
     139                 :            : 
     140         [ +  - ]:         12 :         if (lcf->content == NULL) {
     141                 :          0 :                 pkg_debug(3, "Empty configuration content for local package");
     142                 :          0 :                 return;
     143                 :            :         }
     144                 :            : 
     145                 :         12 :         pkg_debug(1, "Config file found %s", rcf->path);
     146         [ -  + ]:         12 :         if (file_to_bufferat(rootfd, RELATIVE_PATH(rcf->path), &localconf, &sz) != EPKG_OK)
     147                 :          0 :                 return;
     148                 :            : 
     149                 :         12 :         pkg_debug(2, "size: %jd vs %jd", (intmax_t)sz, (intmax_t)strlen(lcf->content));
     150                 :            : 
     151         [ +  - ]:         12 :         if (sz == strlen(lcf->content)) {
     152                 :          0 :                 pkg_debug(2, "Ancient vanilla and deployed conf are the same size testing checksum");
     153                 :          0 :                 localsum = pkg_checksum_data(localconf, sz,
     154                 :            :                     PKG_HASH_TYPE_SHA256_HEX);
     155   [ #  #  #  # ]:          0 :                 if (localsum && strcmp(localsum, lf->sum) == 0) {
     156                 :          0 :                         pkg_debug(2, "Checksum are the same %jd", (intmax_t)strlen(localconf));
     157                 :          0 :                         free(localconf);
     158                 :          0 :                         free(localsum);
     159                 :          0 :                         return;
     160                 :            :                 }
     161                 :          0 :                 free(localsum);
     162                 :          0 :                 pkg_debug(2, "Checksum are different %jd", (intmax_t)strlen(localconf));
     163                 :          0 :         }
     164                 :         12 :         rcf->status = MERGE_FAILED;
     165         [ +  - ]:         12 :         if (!merge) {
     166                 :          0 :                 free(localconf);
     167                 :          0 :                 return;
     168                 :            :         }
     169                 :            : 
     170                 :         12 :         pkg_debug(1, "Attempting to merge %s", rcf->path);
     171                 :         12 :         newconf = xstring_new();
     172         [ -  + ]:         12 :         if (merge_3way(lcf->content, localconf, rcf->content, newconf) != 0) {
     173                 :          0 :                 xstring_free(newconf);
     174                 :          0 :                 pkg_emit_error("Impossible to merge configuration file");
     175                 :          0 :         } else {
     176                 :         12 :                 char *conf = xstring_get(newconf);
     177                 :         12 :                 rcf->newcontent = conf;
     178                 :         12 :                 rcf->status = MERGE_SUCCESS;
     179                 :            :         }
     180                 :         12 :         free(localconf);
     181                 :         42 : }
     182                 :            : 
     183                 :            : static uid_t
     184                 :        512 : get_uid_from_archive(struct archive_entry *ae)
     185                 :            : {
     186                 :            :         static char user_buffer[1024];
     187                 :            :         const char *user;
     188                 :            :         static struct passwd pwent;
     189                 :            :         struct passwd *result;
     190                 :            :         int err;
     191                 :            : 
     192                 :        512 :         user = archive_entry_uname(ae);
     193   [ +  +  +  + ]:        512 :         if (pwent.pw_name != NULL && strcmp(user, pwent.pw_name) == 0)
     194                 :        152 :                 goto out;
     195                 :        360 :         pwent.pw_name = NULL;
     196                 :        360 :         err = getpwnam_r(user, &pwent, user_buffer, sizeof(user_buffer),
     197                 :            :             &result);
     198         [ -  + ]:        360 :         if (err != 0) {
     199                 :          0 :                 pkg_emit_errno("getpwnam_r", user );
     200                 :          0 :                 return (0);
     201                 :            :         }
     202         [ +  - ]:        360 :         if (result == NULL)
     203                 :          0 :                 return (0);
     204                 :            : out:
     205                 :        512 :         return (pwent.pw_uid);
     206                 :        512 : }
     207                 :            : 
     208                 :            : static gid_t
     209                 :        512 : get_gid_from_archive(struct archive_entry *ae)
     210                 :            : {
     211                 :            :         static char group_buffer[1024];
     212                 :            :         static struct group grent;
     213                 :            :         struct group *result;
     214                 :            :         const char *group;
     215                 :            :         int err;
     216                 :            : 
     217                 :        512 :         group = archive_entry_gname(ae);
     218   [ +  +  +  + ]:        512 :         if (grent.gr_name != NULL && strcmp(group, grent.gr_name) == 0)
     219                 :        156 :                 goto out;
     220                 :        356 :         grent.gr_name = NULL;
     221                 :        356 :         err = getgrnam_r(group, &grent, group_buffer, sizeof(group_buffer),
     222                 :            :             &result);
     223         [ -  + ]:        356 :         if (err != 0) {
     224                 :          0 :                 pkg_emit_errno("getgrnam_r", group );
     225                 :          0 :                 return (0);
     226                 :            :         }
     227         [ +  - ]:        356 :         if (result == NULL)
     228                 :          0 :                 return (0);
     229                 :            : out:
     230                 :        512 :         return (grent.gr_gid);
     231                 :        512 : }
     232                 :            : 
     233                 :            : int
     234                 :        528 : set_attrsat(int fd, const char *path, mode_t perm, uid_t uid, gid_t gid,
     235                 :            :     const struct timespec *ats, const struct timespec *mts)
     236                 :            : {
     237                 :            : 
     238                 :            :         struct timeval tv[2];
     239                 :            :         struct stat st;
     240                 :            :         int fdcwd;
     241                 :            : #ifdef HAVE_UTIMENSAT
     242                 :            :         struct timespec times[2];
     243                 :            : 
     244                 :        528 :         times[0] = *ats;
     245                 :        528 :         times[1] = *mts;
     246         [ #  # ]:        528 :         if (utimensat(fd, RELATIVE_PATH(path), times,
     247         [ -  + ]:        528 :             AT_SYMLINK_NOFOLLOW) == -1 && errno != EOPNOTSUPP){
     248                 :          0 :                 pkg_fatal_errno("Fail to set time on %s", path);
     249                 :          0 :         }
     250         [ +  - ]:        528 :         if (errno == EOPNOTSUPP) {
     251                 :            : #endif
     252                 :            : 
     253                 :          0 :         tv[0].tv_sec = ats->tv_sec;
     254                 :          0 :         tv[0].tv_usec = ats->tv_nsec / 1000;
     255                 :          0 :         tv[1].tv_sec = mts->tv_sec;
     256                 :          0 :         tv[1].tv_usec = mts->tv_nsec / 1000;
     257                 :            : 
     258         [ #  # ]:          0 :         if ((fdcwd = open(".", O_DIRECTORY|O_CLOEXEC)) == -1) {
     259                 :          0 :                 pkg_fatal_errno("Failed to open .%s", "");
     260                 :          0 :         }
     261                 :          0 :         fchdir(fd);
     262                 :            : 
     263         [ #  # ]:          0 :         if (lutimes(RELATIVE_PATH(path), tv) == -1) {
     264                 :            : 
     265         [ #  # ]:          0 :                 if (errno != ENOSYS) {
     266                 :          0 :                         close(fdcwd);
     267                 :          0 :                         pkg_fatal_errno("Fail to set time on %s", path);
     268                 :          0 :                 }
     269                 :            :                 else {
     270                 :            :                         /* Fallback to utimes */
     271         [ #  # ]:          0 :                         if (utimes(RELATIVE_PATH(path), tv) == -1) {
     272                 :          0 :                                 close(fdcwd);
     273                 :          0 :                                 pkg_fatal_errno("Fail to set time(fallback) on "
     274                 :            :                                     "%s", path);
     275                 :          0 :                         }
     276                 :            :                 }
     277                 :          0 :         }
     278                 :          0 :         fchdir(fdcwd);
     279                 :          0 :         close(fdcwd);
     280                 :            : #ifdef HAVE_UTIMENSAT
     281                 :          0 :         }
     282                 :            : #endif
     283                 :            : 
     284         [ +  + ]:        528 :         if (getenv("INSTALL_AS_USER") == NULL) {
     285   [ +  -  +  - ]:          8 :                 if (fchownat(fd, RELATIVE_PATH(path), uid, gid,
     286                 :          4 :                                 AT_SYMLINK_NOFOLLOW) == -1) {
     287         [ #  # ]:          0 :                         if (errno == ENOTSUP) {
     288         [ #  # ]:          0 :                                 if (fchownat(fd, RELATIVE_PATH(path), uid, gid, 0) == -1) {
     289                 :          0 :                                         pkg_fatal_errno("Fail to chown(fallback) %s", path);
     290                 :          0 :                                 }
     291                 :          0 :                         }
     292                 :            :                         else {
     293                 :          0 :                                 pkg_fatal_errno("Fail to chown %s", path);
     294                 :            :                         }
     295                 :          0 :                 }
     296                 :          4 :         }
     297                 :            : 
     298                 :            :         /* zfs drops the setuid on fchownat */
     299         [ +  - ]:        528 :         if (fchmodat(fd, RELATIVE_PATH(path), perm, AT_SYMLINK_NOFOLLOW) == -1) {
     300         [ #  # ]:          0 :                 if (errno == ENOTSUP) {
     301                 :            :                         /* 
     302                 :            :                          * Executing fchmodat on a symbolic link results in
     303                 :            :                          * ENOENT (file not found) on platforms that do not
     304                 :            :                          * support AT_SYMLINK_NOFOLLOW. The file mode of
     305                 :            :                          * symlinks cannot be modified via file descriptor
     306                 :            :                          * reference on these systems. The lchmod function is
     307                 :            :                          * also not an option because it is not a posix
     308                 :            :                          * standard, nor is implemented everywhere. Since
     309                 :            :                          * symlink permissions have never been evaluated and
     310                 :            :                          * thus cosmetic, just skip them on these systems.
     311                 :            :                          */
     312         [ #  # ]:          0 :                         if (fstatat(fd, RELATIVE_PATH(path), &st, AT_SYMLINK_NOFOLLOW) == -1) {
     313                 :          0 :                                 pkg_fatal_errno("Fail to get file status %s", path);
     314                 :          0 :                         }
     315         [ #  # ]:          0 :                         if (!S_ISLNK(st.st_mode)) {
     316         [ #  # ]:          0 :                                 if (fchmodat(fd, RELATIVE_PATH(path), perm, 0) == -1) {
     317                 :          0 :                                         pkg_fatal_errno("Fail to chmod(fallback) %s", path);
     318                 :          0 :                                 }
     319                 :          0 :                         }
     320                 :          0 :                 }
     321                 :            :                 else {
     322                 :          0 :                         pkg_fatal_errno("Fail to chmod %s", path);
     323                 :            :                 }
     324                 :          0 :         }
     325                 :            : 
     326                 :        528 :         return (EPKG_OK);
     327                 :        528 : }
     328                 :            : 
     329                 :            : static void
     330                 :        512 : fill_timespec_buf(const struct stat *aest, struct timespec tspec[2])
     331                 :            : {
     332                 :            : #ifdef HAVE_STRUCT_STAT_ST_MTIM
     333                 :        512 :         tspec[0].tv_sec = aest->st_atim.tv_sec;
     334                 :        512 :         tspec[0].tv_nsec = aest->st_atim.tv_nsec;
     335                 :        512 :         tspec[1].tv_sec = aest->st_mtim.tv_sec;
     336                 :        512 :         tspec[1].tv_nsec = aest->st_mtim.tv_nsec;
     337                 :            : #else
     338                 :            : # if defined(_DARWIN_C_SOURCE) || defined(__APPLE__)
     339                 :            :         tspec[0].tv_sec = aest->st_atimespec.tv_sec;
     340                 :            :         tspec[0].tv_nsec = aest->st_atimespec.tv_nsec;
     341                 :            :         tspec[1].tv_sec = aest->st_mtimespec.tv_sec;
     342                 :            :         tspec[1].tv_nsec = aest->st_mtimespec.tv_nsec;
     343                 :            : # else
     344                 :            :         /* Portable unix version */
     345                 :            :         tspec[0].tv_sec = aest->st_atime;
     346                 :            :         tspec[0].tv_nsec = 0;
     347                 :            :         tspec[1].tv_sec = aest->st_mtime;
     348                 :            :         tspec[1].tv_nsec = 0;
     349                 :            : # endif
     350                 :            : #endif
     351                 :        512 : }
     352                 :            : 
     353                 :            : static int
     354                 :         24 : create_dir(struct pkg *pkg, struct pkg_dir *d)
     355                 :            : {
     356                 :            :         struct stat st;
     357                 :            : 
     358         [ +  + ]:         24 :         if (mkdirat(pkg->rootfd, RELATIVE_PATH(d->path), 0755) == -1)
     359         [ +  - ]:         16 :                 if (!mkdirat_p(pkg->rootfd, RELATIVE_PATH(d->path)))
     360                 :          0 :                         return (EPKG_FATAL);
     361         [ +  + ]:         24 :         if (fstatat(pkg->rootfd, RELATIVE_PATH(d->path), &st, 0) == -1) {
     362         [ +  - ]:          4 :                 if (errno != ENOENT) {
     363                 :          0 :                         pkg_fatal_errno("Fail to stat directory %s", d->path);
     364                 :          0 :                 }
     365         [ +  - ]:          4 :                 if (fstatat(pkg->rootfd, RELATIVE_PATH(d->path), &st, AT_SYMLINK_NOFOLLOW) == 0) {
     366                 :          4 :                         unlinkat(pkg->rootfd, RELATIVE_PATH(d->path), 0);
     367                 :          4 :                 }
     368         [ -  + ]:          4 :                 if (mkdirat(pkg->rootfd, RELATIVE_PATH(d->path), 0755) == -1) {
     369                 :          0 :                         pkg_fatal_errno("Fail to create directory %s", d->path);
     370                 :          0 :                 }
     371                 :          4 :         }
     372                 :            : 
     373   [ +  +  +  -  :         24 :         if (st.st_uid == d->uid && st.st_gid == d->gid &&
                   -  + ]
     374                 :         12 :             (st.st_mode & ~S_IFMT) == (d->perm & ~S_IFMT)) {
     375                 :         12 :                 d->noattrs = true;
     376                 :         12 :         }
     377                 :            : 
     378                 :         24 :         return (EPKG_OK);
     379                 :         24 : }
     380                 :            : 
     381                 :            : /* In case of directories create the dir and extract the creds */
     382                 :            : static int
     383                 :         24 : do_extract_dir(struct pkg* pkg, struct archive *a __unused, struct archive_entry *ae,
     384                 :            :     const char *path, struct pkg *local __unused)
     385                 :            : {
     386                 :            :         struct pkg_dir *d;
     387                 :            :         const struct stat *aest;
     388                 :            :         unsigned long clear;
     389                 :            : 
     390                 :         24 :         d = pkg_get_dir(pkg, path);
     391         [ +  - ]:         24 :         if (d == NULL) {
     392                 :          0 :                 pkg_emit_error("Directory %s not specified in the manifest, skipping",
     393                 :          0 :                                 path);
     394                 :          0 :                 return (EPKG_OK);
     395                 :            :         }
     396                 :         24 :         aest = archive_entry_stat(ae);
     397                 :         24 :         d->perm = aest->st_mode;
     398                 :         24 :         d->uid = get_uid_from_archive(ae);
     399                 :         24 :         d->gid = get_gid_from_archive(ae);
     400                 :         24 :         fill_timespec_buf(aest, d->time);
     401                 :         24 :         archive_entry_fflags(ae, &d->fflags, &clear);
     402                 :            : 
     403         [ -  + ]:         24 :         if (create_dir(pkg, d) == EPKG_FATAL) {
     404                 :          0 :                 return (EPKG_FATAL);
     405                 :            :         }
     406                 :            : 
     407                 :         48 :         metalog_add(PKG_METALOG_DIR, RELATIVE_PATH(path),
     408                 :         24 :             archive_entry_uname(ae), archive_entry_gname(ae),
     409                 :         24 :             aest->st_mode & ~S_IFDIR, d->fflags, NULL);
     410                 :            : 
     411                 :         24 :         return (EPKG_OK);
     412                 :         24 : }
     413                 :            : 
     414                 :            : 
     415                 :            : static bool
     416                 :         96 : try_mkdir(int fd, const char *path)
     417                 :            : {
     418                 :         96 :         char *p = get_dirname(xstrdup(path));
     419                 :            : 
     420         [ -  + ]:         96 :         if (!mkdirat_p(fd, RELATIVE_PATH(p))) {
     421                 :          0 :                 free(p);
     422                 :          0 :                 return (false);
     423                 :            :         }
     424                 :         96 :         free(p);
     425                 :         96 :         return (true);
     426                 :         96 : }
     427                 :            : 
     428                 :            : static int
     429                 :         48 : create_symlinks(struct pkg *pkg, struct pkg_file *f, const char *target)
     430                 :            : {
     431                 :         48 :         bool tried_mkdir = false;
     432                 :            : 
     433                 :         48 :         pkg_hidden_tempfile(f->temppath, sizeof(f->temppath), f->path);
     434                 :            : retry:
     435         [ +  + ]:         56 :         if (symlinkat(target, pkg->rootfd, RELATIVE_PATH(f->temppath)) == -1) {
     436         [ +  - ]:          8 :                 if (!tried_mkdir) {
     437         [ +  - ]:          8 :                         if (!try_mkdir(pkg->rootfd, f->path))
     438                 :          0 :                                 return (EPKG_FATAL);
     439                 :          8 :                         tried_mkdir = true;
     440                 :          8 :                         goto retry;
     441                 :            :                 }
     442                 :            : 
     443                 :          0 :                 pkg_fatal_errno("Fail to create symlink: %s", f->temppath);
     444                 :          0 :         }
     445                 :            : 
     446   [ +  -  +  -  :        144 :         if (set_attrsat(pkg->rootfd, f->temppath, f->perm, f->uid, f->gid,
                   +  - ]
     447                 :         96 :             &f->time[0], &f->time[1]) != EPKG_OK) {
     448                 :          0 :                 return (EPKG_FATAL);
     449                 :            :         }
     450                 :         48 :         return (EPKG_OK);
     451                 :         48 : }
     452                 :            : 
     453                 :            : /* In case of a symlink create it directly with a random name */
     454                 :            : static int
     455                 :         36 : do_extract_symlink(struct pkg *pkg, struct archive *a __unused, struct archive_entry *ae,
     456                 :            :     const char *path, struct pkg *local __unused)
     457                 :            : {
     458                 :            :         struct pkg_file *f;
     459                 :            :         const struct stat *aest;
     460                 :            :         unsigned long clear;
     461                 :            : 
     462                 :         36 :         f = pkg_get_file(pkg, path);
     463         [ +  - ]:         36 :         if (f == NULL) {
     464                 :          0 :                 pkg_emit_error("Symlink %s not specified in the manifest", path);
     465                 :          0 :                 return (EPKG_FATAL);
     466                 :            :         }
     467                 :            : 
     468                 :         36 :         aest = archive_entry_stat(ae);
     469                 :         36 :         archive_entry_fflags(ae, &f->fflags, &clear);
     470                 :         36 :         f->uid = get_uid_from_archive(ae);
     471                 :         36 :         f->gid = get_gid_from_archive(ae);
     472                 :         36 :         f->perm = aest->st_mode;
     473                 :         36 :         fill_timespec_buf(aest, f->time);
     474                 :         36 :         archive_entry_fflags(ae, &f->fflags, &clear);
     475                 :            : 
     476         [ -  + ]:         36 :         if (create_symlinks(pkg, f, archive_entry_symlink(ae)) == EPKG_FATAL)
     477                 :          0 :                 return (EPKG_FATAL);
     478                 :            : 
     479                 :         72 :         metalog_add(PKG_METALOG_LINK, RELATIVE_PATH(path),
     480                 :         36 :             archive_entry_uname(ae), archive_entry_gname(ae),
     481                 :         36 :             aest->st_mode & ~S_IFLNK, f->fflags, archive_entry_symlink(ae));
     482                 :            : 
     483                 :         36 :         return (EPKG_OK);
     484                 :         36 : }
     485                 :            : 
     486                 :            : static int
     487                 :         19 : create_hardlink(struct pkg *pkg, struct pkg_file *f, const char *path)
     488                 :            : {
     489                 :         19 :         bool tried_mkdir = false;
     490                 :            :         struct pkg_file *fh;
     491                 :            : 
     492                 :         19 :         pkg_hidden_tempfile(f->temppath, sizeof(f->temppath), f->path);
     493                 :         19 :         fh = pkg_get_file(pkg, path);
     494         [ +  - ]:         19 :         if (fh == NULL) {
     495                 :          0 :                 pkg_emit_error("Can't find the file %s is supposed to be"
     496                 :          0 :                     " hardlinked to %s", f->path, path);
     497                 :          0 :                 return (EPKG_FATAL);
     498                 :            :         }
     499                 :            : 
     500                 :            : 
     501                 :            : retry:
     502   [ +  -  +  -  :         57 :         if (linkat(pkg->rootfd, RELATIVE_PATH(fh->temppath),
                   +  - ]
     503                 :         38 :             pkg->rootfd, RELATIVE_PATH(f->temppath), 0) == -1) {
     504         [ #  # ]:          0 :                 if (!tried_mkdir) {
     505         [ #  # ]:          0 :                         if (!try_mkdir(pkg->rootfd, f->path))
     506                 :          0 :                                 return (EPKG_FATAL);
     507                 :          0 :                         tried_mkdir = true;
     508                 :          0 :                         goto retry;
     509                 :            :                 }
     510                 :            : 
     511                 :          0 :                 pkg_fatal_errno("Fail to create hardlink: %s", f->temppath);
     512                 :          0 :         }
     513                 :            : 
     514                 :         19 :         return (EPKG_OK);
     515                 :         19 : }
     516                 :            : 
     517                 :            : static int
     518                 :         15 : do_extract_hardlink(struct pkg *pkg, struct archive *a __unused, struct archive_entry *ae,
     519                 :            :     const char *path, struct pkg *local __unused)
     520                 :            : {
     521                 :            :         struct pkg_file *f;
     522                 :            :         const struct stat *aest;
     523                 :            :         const char *lp;
     524                 :            : 
     525                 :         15 :         f = pkg_get_file(pkg, path);
     526         [ +  - ]:         15 :         if (f == NULL) {
     527                 :          0 :                 pkg_emit_error("Hardlink %s not specified in the manifest", path);
     528                 :          0 :                 return (EPKG_FATAL);
     529                 :            :         }
     530                 :         15 :         lp = archive_entry_hardlink(ae);
     531                 :         15 :         aest = archive_entry_stat(ae);
     532                 :            : 
     533         [ -  + ]:         15 :         if (create_hardlink(pkg, f, lp) == EPKG_FATAL)
     534                 :          0 :                 return (EPKG_FATAL);
     535                 :            : 
     536                 :         30 :         metalog_add(PKG_METALOG_FILE, RELATIVE_PATH(path),
     537                 :         15 :             archive_entry_uname(ae), archive_entry_gname(ae),
     538                 :         15 :             aest->st_mode & ~S_IFREG, 0, NULL);
     539                 :            : 
     540                 :         15 :         return (EPKG_OK);
     541                 :         15 : }
     542                 :            : 
     543                 :            : static int
     544                 :        464 : create_regfile(struct pkg *pkg, struct pkg_file *f, struct archive *a,
     545                 :            :     struct archive_entry *ae, int fromfd, struct pkg *local)
     546                 :            : {
     547                 :        464 :         int fd = -1;
     548                 :        464 :         bool tried_mkdir = false;
     549                 :            :         size_t len;
     550                 :            :         char buf[32768];
     551                 :            : 
     552                 :        464 :         pkg_hidden_tempfile(f->temppath, sizeof(f->temppath), f->path);
     553                 :            : 
     554                 :            : retry:
     555                 :            :         /* Create the new temp file */
     556                 :       1104 :         fd = openat(pkg->rootfd, RELATIVE_PATH(f->temppath),
     557                 :        552 :             O_CREAT|O_WRONLY|O_EXCL, f->perm);
     558         [ +  + ]:        552 :         if (fd == -1) {
     559         [ +  - ]:         88 :                 if (!tried_mkdir) {
     560         [ +  - ]:         88 :                         if (!try_mkdir(pkg->rootfd, f->path))
     561                 :          0 :                                 return (EPKG_FATAL);
     562                 :         88 :                         tried_mkdir = true;
     563                 :         88 :                         goto retry;
     564                 :            :                 }
     565                 :          0 :                 pkg_fatal_errno("Fail to create temporary file: %s",
     566                 :            :                     f->temppath);
     567                 :          0 :         }
     568                 :            : 
     569         [ +  + ]:        464 :         if (fromfd == -1) {
     570                 :            :                 /* check if this is a config file */
     571                 :        452 :                 f->config = pkghash_get_value(pkg->config_files_hash, f->path);
     572         [ +  + ]:        452 :                 if (f->config) {
     573                 :            :                         const char *cfdata;
     574                 :         42 :                         bool merge = pkg_object_bool(pkg_config_get("AUTOMERGE"));
     575                 :            : 
     576                 :         42 :                         pkg_debug(1, "Populating config_file %s", f->path);
     577                 :         42 :                         len = archive_entry_size(ae);
     578                 :         42 :                         f->config->content = xmalloc(len + 1);
     579                 :         42 :                         archive_read_data(a, f->config->content, len);
     580                 :         42 :                         f->config->content[len] = '\0';
     581                 :         42 :                         cfdata = f->config->content;
     582                 :         42 :                         attempt_to_merge(pkg->rootfd, f->config, local, merge);
     583         [ +  + ]:         42 :                         if (f->config->status == MERGE_SUCCESS)
     584                 :         12 :                                 cfdata = f->config->newcontent;
     585                 :         42 :                         dprintf(fd, "%s", cfdata);
     586         [ +  + ]:         42 :                         if (f->config->newcontent != NULL)
     587                 :         12 :                                 free(f->config->newcontent);
     588                 :         42 :                 } else {
     589         [ -  + ]:        410 :                         if (ftruncate(fd, archive_entry_size(ae)) == -1) {
     590                 :          0 :                                 pkg_errno("Fail to truncate file: %s", f->temppath);
     591                 :          0 :                         }
     592                 :            :                 }
     593                 :            : 
     594   [ +  +  +  - ]:        452 :                 if (!f->config && archive_read_data_into_fd(a, fd) != ARCHIVE_OK) {
     595                 :          0 :                         pkg_emit_error("Fail to extract %s from package: %s",
     596                 :          0 :                             f->path, archive_error_string(a));
     597                 :          0 :                         return (EPKG_FATAL);
     598                 :            :                 }
     599                 :        452 :         } else {
     600         [ +  + ]:         20 :                 while ((len = read(fromfd, buf, sizeof(buf))) > 0)
     601         [ +  - ]:          8 :                         if (write(fd, buf, len) == -1) {
     602                 :          0 :                                 pkg_errno("Fail to write file: %s", f->temppath);
     603                 :          0 :                         }
     604                 :            :         }
     605         [ -  + ]:        464 :         if (fd != -1) {
     606                 :        464 :                 close(fd);
     607                 :        464 :         }
     608                 :            : 
     609   [ -  +  -  +  :       1392 :         if (set_attrsat(pkg->rootfd, f->temppath, f->perm, f->uid, f->gid,
                   -  + ]
     610                 :        928 :             &f->time[0], &f->time[1]) != EPKG_OK)
     611                 :          0 :                         return (EPKG_FATAL);
     612                 :            : 
     613                 :        464 :         return (EPKG_OK);
     614                 :        464 : }
     615                 :            : 
     616                 :            : static int
     617                 :        452 : do_extract_regfile(struct pkg *pkg, struct archive *a, struct archive_entry *ae,
     618                 :            :     const char *path, struct pkg *local)
     619                 :            : {
     620                 :            :         struct pkg_file *f;
     621                 :            :         const struct stat *aest;
     622                 :            :         unsigned long clear;
     623                 :            : 
     624                 :        452 :         f = pkg_get_file(pkg, path);
     625         [ +  - ]:        452 :         if (f == NULL) {
     626                 :          0 :                 pkg_emit_error("File %s not specified in the manifest", path);
     627                 :          0 :                 return (EPKG_FATAL);
     628                 :            :         }
     629                 :            : 
     630                 :        452 :         aest = archive_entry_stat(ae);
     631                 :        452 :         archive_entry_fflags(ae, &f->fflags, &clear);
     632                 :        452 :         f->perm = aest->st_mode;
     633                 :        452 :         f->uid = get_uid_from_archive(ae);
     634                 :        452 :         f->gid = get_gid_from_archive(ae);
     635                 :        452 :         fill_timespec_buf(aest, f->time);
     636                 :        452 :         archive_entry_fflags(ae, &f->fflags, &clear);
     637                 :            : 
     638         [ -  + ]:        452 :         if (create_regfile(pkg, f, a, ae, -1, local) == EPKG_FATAL)
     639                 :          0 :                 return (EPKG_FATAL);
     640                 :            : 
     641                 :        904 :         metalog_add(PKG_METALOG_FILE, RELATIVE_PATH(path),
     642                 :        452 :             archive_entry_uname(ae), archive_entry_gname(ae),
     643                 :        452 :             aest->st_mode & ~S_IFREG, f->fflags, NULL);
     644                 :            : 
     645                 :        452 :         return (EPKG_OK);
     646                 :        452 : }
     647                 :            : 
     648                 :            : static int
     649                 :        440 : do_extract(struct archive *a, struct archive_entry *ae,
     650                 :            :     int nfiles, struct pkg *pkg, struct pkg *local)
     651                 :            : {
     652                 :        440 :         int     retcode = EPKG_OK;
     653                 :        440 :         int     ret = 0, cur_file = 0;
     654                 :            :         char    path[MAXPATHLEN];
     655                 :            :         int (*extract_cb)(struct pkg *pkg, struct archive *a,
     656                 :            :             struct archive_entry *ae, const char *path, struct pkg *local);
     657                 :            : 
     658                 :            : #ifndef HAVE_ARC4RANDOM
     659                 :            :         srand(time(NULL));
     660                 :            : #endif
     661                 :            : 
     662         [ +  - ]:        440 :         if (nfiles == 0)
     663                 :          0 :                 return (EPKG_OK);
     664                 :            : 
     665                 :        440 :         pkg_emit_extract_begin(pkg);
     666                 :        440 :         pkg_emit_progress_start(NULL);
     667                 :            : 
     668                 :        440 :         do {
     669                 :        527 :                 pkg_absolutepath(archive_entry_pathname(ae), path, sizeof(path), true);
     670   [ -  +  -  + ]:       1054 :                 if (match_ucl_lists(path,
     671                 :        527 :                     pkg_config_get("FILES_IGNORE_GLOB"),
     672                 :        527 :                     pkg_config_get("FILES_IGNORE_REGEX")))
     673                 :          0 :                         continue;
     674   [ +  +  +  +  :        527 :                 switch (archive_entry_filetype(ae)) {
          -  -  -  -  -  
                      - ]
     675                 :            :                 case AE_IFDIR:
     676                 :         24 :                         extract_cb = do_extract_dir;
     677                 :         24 :                         break;
     678                 :            :                 case AE_IFLNK:
     679                 :         36 :                         extract_cb = do_extract_symlink;
     680                 :         36 :                         break;
     681                 :            :                 case 0: /* HARDLINKS */
     682                 :         15 :                         extract_cb = do_extract_hardlink;
     683                 :         15 :                         break;
     684                 :            :                 case AE_IFREG:
     685                 :        452 :                         extract_cb = do_extract_regfile;
     686                 :        452 :                         break;
     687                 :            :                 case AE_IFMT:
     688                 :          0 :                         pkg_emit_error("Archive contains an unsupported filetype (AE_IFMT): %s", path);
     689                 :          0 :                         retcode = EPKG_FATAL;
     690                 :          0 :                         goto cleanup;
     691                 :            :                         break;
     692                 :            :                 case AE_IFSOCK:
     693                 :          0 :                         pkg_emit_error("Archive contains an unsupported filetype (AE_IFSOCK): %s", path);
     694                 :          0 :                         retcode = EPKG_FATAL;
     695                 :          0 :                         goto cleanup;
     696                 :            :                         break;
     697                 :            :                 case AE_IFCHR:
     698                 :          0 :                         pkg_emit_error("Archive contains an unsupported filetype (AE_IFCHR): %s", path);
     699                 :          0 :                         retcode = EPKG_FATAL;
     700                 :          0 :                         goto cleanup;
     701                 :            :                         break;
     702                 :            :                 case AE_IFIFO:
     703                 :          0 :                         pkg_emit_error("Archive contains an unsupported filetype (AE_IFIFO): %s", path);
     704                 :          0 :                         retcode = EPKG_FATAL;
     705                 :          0 :                         goto cleanup;
     706                 :            :                         break;
     707                 :            :                 case AE_IFBLK:
     708                 :          0 :                         pkg_emit_error("Archive contains an unsupported filetype (AE_IFBLK): %s", path);
     709                 :          0 :                         retcode = EPKG_FATAL;
     710                 :          0 :                         goto cleanup;
     711                 :            :                         break;
     712                 :            :                 default:
     713                 :          0 :                         pkg_emit_error("Archive contains an unsupported filetype (%d): %s", archive_entry_filetype(ae), path);
     714                 :          0 :                         retcode = EPKG_FATAL;
     715                 :          0 :                         goto cleanup;
     716                 :            :                         break;
     717                 :            :                 }
     718                 :            : 
     719         [ +  - ]:        527 :                 if (extract_cb(pkg, a, ae, path, local) != EPKG_OK) {
     720                 :          0 :                         retcode = EPKG_FATAL;
     721                 :          0 :                         goto cleanup;
     722                 :            :                 }
     723         [ +  + ]:        527 :                 if (archive_entry_filetype(ae) != AE_IFDIR) {
     724                 :        503 :                         pkg_emit_progress_tick(cur_file++, nfiles);
     725                 :        503 :                 }
     726         [ +  + ]:        527 :         } while ((ret = archive_read_next_header(a, &ae)) == ARCHIVE_OK);
     727                 :        440 :         pkg_emit_progress_tick(cur_file++, nfiles);
     728                 :            : 
     729         [ +  - ]:        440 :         if (ret != ARCHIVE_EOF) {
     730                 :          0 :                 pkg_emit_error("archive_read_next_header(): %s",
     731                 :          0 :                     archive_error_string(a));
     732                 :          0 :                 retcode = EPKG_FATAL;
     733                 :          0 :         }
     734                 :            : 
     735                 :            : cleanup:
     736                 :        440 :         pkg_emit_progress_tick(nfiles, nfiles);
     737                 :        440 :         pkg_emit_extract_finished(pkg);
     738                 :            : 
     739                 :        440 :         return (retcode);
     740                 :        440 : }
     741                 :            : 
     742                 :            : static int
     743                 :        711 : pkg_extract_finalize(struct pkg *pkg)
     744                 :            : {
     745                 :            :         struct stat st;
     746                 :        711 :         struct pkg_file *f = NULL;
     747                 :        711 :         struct pkg_dir *d = NULL;
     748                 :            :         char path[MAXPATHLEN + 8];
     749                 :            :         const char *fto;
     750                 :            : #ifdef HAVE_CHFLAGSAT
     751                 :            :         bool install_as_user;
     752                 :            : 
     753                 :        711 :         install_as_user = (getenv("INSTALL_AS_USER") != NULL);
     754                 :            : #endif
     755                 :            : 
     756         [ +  + ]:       1242 :         while (pkg_files(pkg, &f) == EPKG_OK) {
     757                 :            : 
     758   [ -  +  -  + ]:       1062 :                 if (match_ucl_lists(f->path,
     759                 :        531 :                     pkg_config_get("FILES_IGNORE_GLOB"),
     760                 :        531 :                     pkg_config_get("FILES_IGNORE_REGEX")))
     761                 :          0 :                         continue;
     762                 :        531 :                 append_touched_file(f->path);
     763         [ +  - ]:        531 :                 if (*f->temppath == '\0')
     764                 :          0 :                         continue;
     765                 :        531 :                 fto = f->path;
     766   [ +  +  +  +  :        531 :                 if (f->config && f->config->status == MERGE_FAILED &&
                   +  + ]
     767                 :         10 :                     f->previous != PKG_FILE_NONE) {
     768                 :          5 :                         snprintf(path, sizeof(path), "%s.pkgnew", f->path);
     769                 :          5 :                         fto = path;
     770                 :          5 :                 }
     771                 :            : 
     772   [ +  +  +  + ]:        531 :                 if (f->config && f->config->status == MERGE_NOT_LOCAL) {
     773                 :          5 :                         snprintf(path, sizeof(path), "%s.pkgsave", f->path);
     774   [ +  -  +  -  :         15 :                         if (renameat(pkg->rootfd, RELATIVE_PATH(fto),
                   +  - ]
     775                 :         10 :                             pkg->rootfd, RELATIVE_PATH(path)) == -1) {
     776                 :          0 :                                 pkg_fatal_errno("Fail to rename %s -> %s",
     777                 :            :                                   fto, path);
     778                 :          0 :                         }
     779                 :          5 :                 }
     780                 :            : 
     781                 :            :                 /*
     782                 :            :                  * enforce an unlink of the file to workaround a bug that
     783                 :            :                  * results in renameat returning 0 of the from file is hardlink
     784                 :            :                  * on the to file, but the to file is not removed
     785                 :            :                  */
     786   [ +  +  +  + ]:        531 :                 if (f->previous != PKG_FILE_NONE &&
     787                 :        280 :                     fstatat(pkg->rootfd, RELATIVE_PATH(fto), &st,
     788                 :        280 :                     AT_SYMLINK_NOFOLLOW) != -1) {
     789                 :            : #ifdef HAVE_CHFLAGSAT
     790   [ -  +  #  # ]:        270 :                         if (!install_as_user && st.st_flags & NOCHANGESFLAGS) {
     791                 :          0 :                                 chflagsat(pkg->rootfd, RELATIVE_PATH(fto), 0,
     792                 :            :                                     AT_SYMLINK_NOFOLLOW);
     793                 :          0 :                         }
     794                 :            : #endif
     795                 :            :                         /* if the files does not belong to any package, we do save it */
     796         [ +  + ]:        270 :                         if (f->previous == PKG_FILE_SAVE) {
     797                 :        228 :                                 snprintf(path, sizeof(path), "%s.pkgsave", f->path);
     798                 :        456 :                                 renameat(pkg->rootfd, RELATIVE_PATH(fto),
     799                 :        228 :                                     pkg->rootfd, RELATIVE_PATH(path));
     800                 :        228 :                         }
     801                 :        270 :                         unlinkat(pkg->rootfd, RELATIVE_PATH(fto), 0);
     802                 :        270 :                 }
     803   [ +  -  +  -  :       1593 :                 if (renameat(pkg->rootfd, RELATIVE_PATH(f->temppath),
                   +  - ]
     804                 :       1062 :                     pkg->rootfd, RELATIVE_PATH(fto)) == -1) {
     805                 :          0 :                         pkg_fatal_errno("Fail to rename %s -> %s",
     806                 :            :                             f->temppath, fto);
     807                 :          0 :                 }
     808                 :            : 
     809                 :            : #ifdef HAVE_CHFLAGSAT
     810   [ -  +  #  # ]:        531 :                 if (!install_as_user && f->fflags != 0) {
     811   [ #  #  #  #  :          0 :                         if (chflagsat(pkg->rootfd, RELATIVE_PATH(fto),
                   #  # ]
     812                 :          0 :                             f->fflags, AT_SYMLINK_NOFOLLOW) == -1) {
     813                 :          0 :                                 pkg_fatal_errno("Fail to chflags %s", fto);
     814                 :          0 :                         }
     815                 :          0 :                 }
     816                 :            : #endif
     817                 :            :         }
     818                 :            : 
     819         [ +  + ]:        735 :         while (pkg_dirs(pkg, &d) == EPKG_OK) {
     820         [ +  + ]:         24 :                 if (d->noattrs)
     821                 :         12 :                         continue;
     822   [ +  -  +  -  :         36 :                 if (set_attrsat(pkg->rootfd, d->path, d->perm,
                   +  - ]
     823                 :         24 :                     d->uid, d->gid, &d->time[0], &d->time[1]) != EPKG_OK)
     824                 :          0 :                         return (EPKG_FATAL);
     825                 :            :         }
     826                 :            : 
     827                 :        711 :         return (EPKG_OK);
     828                 :        711 : }
     829                 :            : 
     830                 :            : static char *
     831                 :         78 : pkg_globmatch(char *pattern, const char *name)
     832                 :            : {
     833                 :            :         glob_t g;
     834                 :            :         int i;
     835                 :            :         char *buf, *buf2;
     836                 :         78 :         char *path = NULL;
     837                 :            : 
     838         [ +  + ]:         78 :         if (glob(pattern, 0, NULL, &g) == GLOB_NOMATCH) {
     839                 :         39 :                 globfree(&g);
     840                 :            : 
     841                 :         39 :                 return (NULL);
     842                 :            :         }
     843                 :            : 
     844         [ +  + ]:         78 :         for (i = 0; i < g.gl_pathc; i++) {
     845                 :            :                 /* the version starts here */
     846                 :         39 :                 buf = strrchr(g.gl_pathv[i], '-');
     847         [ +  - ]:         39 :                 if (buf == NULL)
     848                 :          0 :                         continue;
     849                 :         39 :                 buf2 = strrchr(g.gl_pathv[i], '/');
     850         [ +  - ]:         39 :                 if (buf2 == NULL)
     851                 :          0 :                         buf2 = g.gl_pathv[i];
     852                 :            :                 else
     853                 :         39 :                         buf2++;
     854                 :            :                 /* ensure we have match the proper name */
     855         [ -  + ]:         39 :                 if (strncmp(buf2, name, buf - buf2) != 0)
     856                 :          0 :                         continue;
     857         [ -  + ]:         39 :                 if (path == NULL) {
     858                 :         39 :                         path = g.gl_pathv[i];
     859                 :         39 :                         continue;
     860                 :            :                 }
     861         [ #  # ]:          0 :                 if (pkg_version_cmp(path, g.gl_pathv[i]) == 1)
     862                 :          0 :                         path = g.gl_pathv[i];
     863                 :          0 :         }
     864         [ +  - ]:         39 :         if (path)
     865                 :         39 :                 path = xstrdup(path);
     866                 :         39 :         globfree(&g);
     867                 :            : 
     868                 :         39 :         return (path);
     869                 :         78 : }
     870                 :            : 
     871                 :            : static int
     872                 :        203 : pkg_add_check_pkg_archive(struct pkgdb *db, struct pkg *pkg,
     873                 :            :         const char *path, int flags,
     874                 :            :         struct pkg_manifest_key *keys, const char *location)
     875                 :            : {
     876                 :            :         const char      *arch;
     877                 :            :         int     ret, retcode;
     878                 :        203 :         struct pkg_dep  *dep = NULL;
     879                 :        203 :         char    bd[MAXPATHLEN], *basedir = NULL;
     880                 :            :         char    dpath[MAXPATHLEN], *ppath;
     881                 :        203 :         const char      *ext = NULL;
     882                 :        203 :         struct pkg      *pkg_inst = NULL;
     883                 :            :         bool    fromstdin;
     884                 :            : 
     885         [ -  + ]:        203 :         arch = pkg->abi != NULL ? pkg->abi : pkg->arch;
     886                 :            : 
     887   [ -  +  #  # ]:        203 :         if (!is_valid_abi(arch, true) && (flags & PKG_ADD_FORCE) == 0) {
     888                 :          0 :                 return (EPKG_FATAL);
     889                 :            :         }
     890                 :            : 
     891   [ -  +  #  # ]:        203 :         if (!is_valid_os_version(pkg) && (flags & PKG_ADD_FORCE) == 0) {
     892                 :          0 :                 return (EPKG_FATAL);
     893                 :            :         }
     894                 :            : 
     895                 :            :         /* XX check */
     896                 :        203 :         ret = pkg_try_installed(db, pkg->name, &pkg_inst, PKG_LOAD_BASIC);
     897         [ +  - ]:        203 :         if (ret == EPKG_OK) {
     898         [ #  # ]:          0 :                 if ((flags & PKG_ADD_FORCE) == 0) {
     899                 :          0 :                         pkg_emit_already_installed(pkg_inst);
     900                 :          0 :                         pkg_free(pkg_inst);
     901                 :          0 :                         pkg_inst = NULL;
     902                 :          0 :                         return (EPKG_INSTALLED);
     903                 :            :                 }
     904         [ #  # ]:          0 :                 if (pkg_inst->locked) {
     905                 :          0 :                         pkg_emit_locked(pkg_inst);
     906                 :          0 :                         pkg_free(pkg_inst);
     907                 :          0 :                         pkg_inst = NULL;
     908                 :          0 :                         return (EPKG_LOCKED);
     909                 :            :                 }
     910                 :          0 :                 pkg_emit_notice("package %s is already installed, forced "
     911                 :          0 :                     "install", pkg->name);
     912                 :          0 :                 pkg_free(pkg_inst);
     913                 :          0 :                 pkg_inst = NULL;
     914         [ -  + ]:        203 :         } else if (ret != EPKG_END) {
     915                 :          0 :                 return (ret);
     916                 :            :         }
     917                 :            : 
     918                 :            :         /*
     919                 :            :          * Check for dependencies by searching the same directory as
     920                 :            :          * the package archive we're reading.  Of course, if we're
     921                 :            :          * reading from a file descriptor or a unix domain socket or
     922                 :            :          * whatever, there's no valid directory to search.
     923                 :            :          */
     924                 :        203 :         fromstdin = (strcmp(path, "-") == 0);
     925                 :        203 :         strlcpy(bd, path, sizeof(bd));
     926         [ +  + ]:        203 :         if (!fromstdin) {
     927                 :        164 :                 basedir = get_dirname(bd);
     928                 :        164 :                 strlcpy(bd, basedir, sizeof(bd));
     929         [ +  - ]:        164 :                 if ((ext = strrchr(path, '.')) == NULL) {
     930                 :          0 :                         pkg_emit_error("%s has no extension", path);
     931                 :          0 :                         return (EPKG_FATAL);
     932                 :            :                 }
     933                 :        164 :         }
     934                 :            : 
     935                 :        203 :         retcode = EPKG_FATAL;
     936                 :        203 :         pkg_emit_add_deps_begin(pkg);
     937                 :            : 
     938         [ +  + ]:        272 :         while (pkg_deps(pkg, &dep) == EPKG_OK) {
     939                 :        108 :                 dpath[0] = '\0';
     940                 :            : 
     941         [ +  - ]:        108 :                 if (pkg_is_installed(db, dep->name) == EPKG_OK)
     942                 :          0 :                         continue;
     943                 :            : 
     944         [ +  + ]:        108 :                 if (fromstdin) {
     945                 :         26 :                         pkg_emit_missing_dep(pkg, dep);
     946         [ +  + ]:         26 :                         if ((flags & PKG_ADD_FORCE_MISSING) == 0)
     947                 :         13 :                                 goto cleanup;
     948                 :         13 :                         continue;
     949                 :            :                 }
     950                 :            : 
     951   [ +  +  -  + ]:         82 :                 if (dep->version != NULL && dep->version[0] != '\0') {
     952                 :         86 :                         snprintf(dpath, sizeof(dpath), "%s/%s-%s%s", bd,
     953                 :         43 :                                 dep->name, dep->version, ext);
     954                 :         43 :                 }
     955                 :            : 
     956   [ +  +  +  + ]:         82 :                 if (strlen(dpath) == 0 || access(dpath, F_OK) != 0) {
     957                 :        156 :                         snprintf(dpath, sizeof(dpath), "%s/%s-*%s", bd,
     958                 :         78 :                             dep->name, ext);
     959                 :         78 :                         ppath = pkg_globmatch(dpath, dep->name);
     960         [ +  + ]:         78 :                         if (ppath == NULL) {
     961                 :         39 :                                 pkg_emit_missing_dep(pkg, dep);
     962         [ +  + ]:         39 :                                 if ((flags & PKG_ADD_FORCE_MISSING) == 0)
     963                 :         26 :                                         goto cleanup;
     964                 :         13 :                                 continue;
     965                 :            :                         }
     966                 :         39 :                         strlcpy(dpath, ppath, sizeof(dpath));
     967                 :         39 :                         free(ppath);
     968                 :         39 :                 }
     969                 :            : 
     970   [ +  -  -  + ]:         43 :                 if ((flags & PKG_ADD_UPGRADE) == 0 &&
     971                 :         43 :                                 access(dpath, F_OK) == 0) {
     972                 :         86 :                         ret = pkg_add(db, dpath, PKG_ADD_AUTOMATIC,
     973                 :         43 :                                         keys, location);
     974                 :            : 
     975         [ +  - ]:         43 :                         if (ret != EPKG_OK)
     976                 :          0 :                                 goto cleanup;
     977                 :         43 :                 } else {
     978                 :          0 :                         pkg_emit_missing_dep(pkg, dep);
     979         [ #  # ]:          0 :                         if ((flags & PKG_ADD_FORCE_MISSING) == 0)
     980                 :          0 :                                 goto cleanup;
     981                 :            :                 }
     982                 :            :         }
     983                 :            : 
     984                 :        164 :         retcode = EPKG_OK;
     985                 :            : cleanup:
     986                 :        203 :         pkg_emit_add_deps_finished(pkg);
     987                 :            : 
     988                 :        203 :         return (retcode);
     989                 :        203 : }
     990                 :            : 
     991                 :            : static int
     992                 :        132 : pkg_add_cleanup_old(struct pkgdb *db, struct pkg *old, struct pkg *new, int flags)
     993                 :            : {
     994                 :            :         struct pkg_file *f;
     995                 :        132 :         int ret = EPKG_OK;
     996                 :            : 
     997                 :        132 :         pkg_start_stop_rc_scripts(old, PKG_RC_STOP);
     998                 :            : 
     999                 :            :         /*
    1000                 :            :          * Execute pre deinstall scripts
    1001                 :            :          */
    1002         [ -  + ]:        132 :         if ((flags & PKG_ADD_NOSCRIPT) == 0) {
    1003                 :        132 :                 ret = pkg_lua_script_run(old, PKG_LUA_PRE_DEINSTALL, (old != NULL));
    1004   [ -  +  #  # ]:        132 :                 if (ret != EPKG_OK && ctx.developer_mode) {
    1005                 :          0 :                         return (ret);
    1006                 :            :                 } else {
    1007                 :        132 :                         ret = pkg_script_run(old, PKG_SCRIPT_PRE_DEINSTALL, (old != NULL));
    1008   [ -  +  #  # ]:        132 :                         if (ret != EPKG_OK && ctx.developer_mode) {
    1009                 :          0 :                                 return (ret);
    1010                 :            :                         } else {
    1011                 :        132 :                                 ret = EPKG_OK;
    1012                 :            :                         }
    1013                 :            :                 }
    1014                 :        132 :         }
    1015                 :            : 
    1016                 :            :         /* Now remove files that no longer exist in the new package */
    1017         [ +  - ]:        132 :         if (new != NULL) {
    1018                 :        132 :                 f = NULL;
    1019         [ +  + ]:        188 :                 while (pkg_files(old, &f) == EPKG_OK) {
    1020   [ +  +  -  +  :         56 :                         if (!pkg_has_file(new, f->path) || match_ucl_lists(f->path,
                   -  + ]
    1021                 :         48 :                             pkg_config_get("FILES_IGNORE_GLOB"),
    1022                 :         48 :                             pkg_config_get("FILES_IGNORE_REGEX"))) {
    1023                 :          8 :                                 pkg_debug(2, "File %s is not in the new package", f->path);
    1024         [ -  + ]:          8 :                                 if (ctx.backup_libraries) {
    1025                 :            :                                         const char *libname;
    1026                 :          8 :                                         libname = strrchr(f->path, '/');
    1027   [ +  -  -  + ]:          8 :                                         if (libname != NULL &&
    1028                 :          8 :                                             pkghash_get(old->shlibs_provided, libname+1) != NULL) {
    1029                 :          8 :                                                 backup_library(db, old, f->path);
    1030                 :          8 :                                         }
    1031                 :          8 :                                 }
    1032                 :          8 :                                 pkg_delete_file(old, f, flags & PKG_DELETE_FORCE ? 1 : 0);
    1033                 :          8 :                         }
    1034                 :            :                 }
    1035                 :            : 
    1036                 :        132 :                 pkg_delete_dirs(db, old, new);
    1037                 :        132 :         }
    1038                 :            : 
    1039                 :        132 :         return (ret);
    1040                 :        132 : }
    1041                 :            : 
    1042                 :            : void
    1043                 :          0 : pkg_rollback_pkg(struct pkg *p)
    1044                 :            : {
    1045                 :          0 :         struct pkg_file *f = NULL;
    1046                 :            : 
    1047         [ #  # ]:          0 :         while (pkg_files(p, &f) == EPKG_OK) {
    1048   [ #  #  #  # ]:          0 :                 if (match_ucl_lists(f->path,
    1049                 :          0 :                     pkg_config_get("FILES_IGNORE_GLOB"),
    1050                 :          0 :                     pkg_config_get("FILES_IGNORE_REGEX")))
    1051                 :          0 :                         continue;
    1052         [ #  # ]:          0 :                 if (*f->temppath != '\0') {
    1053                 :          0 :                         unlinkat(p->rootfd, f->temppath, 0);
    1054                 :          0 :                 }
    1055                 :            :         }
    1056                 :          0 : }
    1057                 :            : 
    1058                 :            : void
    1059                 :          0 : pkg_rollback_cb(void *data)
    1060                 :            : {
    1061                 :          0 :         pkg_rollback_pkg((struct pkg *)data);
    1062                 :          0 : }
    1063                 :            : 
    1064                 :            : int
    1065                 :        160 : pkg_add_triggers(void)
    1066                 :            : {
    1067                 :        160 :         return (triggers_execute(NULL));
    1068                 :            : }
    1069                 :            : 
    1070                 :            : static int
    1071                 :        742 : pkg_add_common(struct pkgdb *db, const char *path, unsigned flags,
    1072                 :            :     struct pkg_manifest_key *keys, const char *reloc, struct pkg *remote,
    1073                 :            :     struct pkg *local)
    1074                 :            : {
    1075                 :            :         struct archive          *a;
    1076                 :            :         struct archive_entry    *ae;
    1077                 :        742 :         struct pkg              *pkg = NULL;
    1078                 :        742 :         xstring                 *message = NULL;
    1079                 :            :         struct pkg_message      *msg;
    1080                 :            :         struct pkg_file         *f;
    1081                 :            :         const char              *msgstr;
    1082                 :        742 :         bool                     extract = true;
    1083                 :        742 :         int                      retcode = EPKG_OK;
    1084                 :            :         int                      ret;
    1085                 :            :         int                      nfiles;
    1086                 :            : 
    1087         [ +  - ]:        742 :         assert(path != NULL);
    1088                 :            : 
    1089         [ +  + ]:        742 :         if (local != NULL)
    1090                 :        132 :                 flags |= PKG_ADD_UPGRADE;
    1091                 :            : 
    1092                 :            :         /*
    1093                 :            :          * Open the package archive file, read all the meta files and set the
    1094                 :            :          * current archive_entry to the first non-meta file.
    1095                 :            :          * If there is no non-meta files, EPKG_END is returned.
    1096                 :            :          */
    1097                 :        742 :         ret = pkg_open2(&pkg, &a, &ae, path, keys, 0, -1);
    1098         [ +  + ]:        742 :         if (ret == EPKG_END)
    1099                 :        276 :                 extract = false;
    1100         [ -  + ]:        466 :         else if (ret != EPKG_OK) {
    1101                 :          0 :                 retcode = ret;
    1102                 :          0 :                 goto cleanup;
    1103                 :            :         }
    1104         [ +  + ]:        742 :         if ((flags & PKG_ADD_SPLITTED_UPGRADE) != PKG_ADD_SPLITTED_UPGRADE)
    1105                 :        734 :                 pkg_emit_new_action();
    1106         [ +  + ]:        742 :         if ((flags & PKG_ADD_UPGRADE) == 0)
    1107                 :        203 :                 pkg_emit_install_begin(pkg);
    1108                 :            :         else {
    1109         [ +  + ]:        539 :                 if (local != NULL)
    1110                 :        132 :                         pkg_emit_upgrade_begin(pkg, local);
    1111                 :            :                 else
    1112                 :        407 :                         pkg_emit_install_begin(pkg);
    1113                 :            :         }
    1114                 :            : 
    1115         [ -  + ]:        742 :         if (pkg_is_valid(pkg) != EPKG_OK) {
    1116                 :          0 :                 pkg_emit_error("the package is not valid");
    1117                 :          0 :                 return (EPKG_FATAL);
    1118                 :            :         }
    1119                 :            : 
    1120         [ +  + ]:        742 :         if (flags & PKG_ADD_AUTOMATIC)
    1121                 :        164 :                 pkg->automatic = true;
    1122                 :            : 
    1123                 :            :         /*
    1124                 :            :          * Additional checks for non-remote package
    1125                 :            :          */
    1126         [ +  + ]:        742 :         if (remote == NULL) {
    1127                 :        406 :                 ret = pkg_add_check_pkg_archive(db, pkg, path, flags, keys,
    1128                 :        203 :                     reloc);
    1129         [ +  + ]:        203 :                 if (ret != EPKG_OK) {
    1130                 :            :                         /* Do not return error on installed package */
    1131         [ -  + ]:         39 :                         retcode = (ret == EPKG_INSTALLED ? EPKG_OK : ret);
    1132                 :         39 :                         goto cleanup;
    1133                 :            :                 }
    1134                 :        164 :         }
    1135                 :            :         else {
    1136         [ +  + ]:        539 :                 if (remote->repo != NULL) {
    1137                 :            :                         /* Save reponame */
    1138                 :        327 :                         pkg_kv_add(&pkg->annotations, "repository", remote->repo->name, "annotation");
    1139                 :        327 :                         pkg_kv_add(&pkg->annotations, "repo_type", remote->repo->ops->type, "annotation");
    1140                 :        327 :                 }
    1141                 :            : 
    1142                 :        539 :                 free(pkg->digest);
    1143                 :        539 :                 pkg->digest = xstrdup(remote->digest);
    1144                 :            :                 /* only preserve flags if -A has not been passed */
    1145         [ +  + ]:        539 :                 if ((flags & PKG_ADD_AUTOMATIC) == 0)
    1146                 :        431 :                         pkg->automatic = remote->automatic;
    1147                 :            :         }
    1148                 :            : 
    1149         [ -  + ]:        703 :         if (reloc != NULL)
    1150                 :          0 :                 pkg_kv_add(&pkg->annotations, "relocated", reloc, "annotation");
    1151                 :            : 
    1152                 :        703 :         pkg_open_root_fd(pkg);
    1153                 :            :         /* analyse previous files */
    1154                 :        703 :         f = NULL;
    1155         [ +  + ]:       1206 :         while (pkg_files(pkg, &f) == EPKG_OK) {
    1156   [ -  +  -  + ]:       1006 :                 if (match_ucl_lists(f->path,
    1157                 :        503 :                     pkg_config_get("FILES_IGNORE_GLOB"),
    1158                 :        503 :                     pkg_config_get("FILES_IGNORE_REGEX"))) {
    1159                 :          0 :                         continue;
    1160                 :            :                 }
    1161         [ +  + ]:        503 :                 if (faccessat(pkg->rootfd, RELATIVE_PATH(f->path), F_OK, 0) == 0) {
    1162                 :        280 :                         f->previous = PKG_FILE_EXIST;
    1163         [ +  + ]:        280 :                         if (!pkgdb_file_exists(db, f->path)) {
    1164                 :        233 :                                 f->previous = PKG_FILE_SAVE;
    1165                 :        233 :                         }
    1166                 :        280 :                 }
    1167                 :            :         }
    1168                 :            : 
    1169                 :            :         /* register the package before installing it in case there are
    1170                 :            :          * problems that could be caught here. */
    1171                 :        703 :         retcode = pkgdb_register_pkg(db, pkg, flags & PKG_ADD_FORCE, NULL);
    1172                 :            : 
    1173         [ -  + ]:        703 :         if (retcode != EPKG_OK)
    1174                 :          0 :                 goto cleanup;
    1175                 :            : 
    1176                 :            :         /*
    1177                 :            :          * Execute pre-install scripts
    1178                 :            :          */
    1179         [ +  + ]:        703 :         if ((flags & PKG_ADD_NOSCRIPT) == 0) {
    1180         [ -  + ]:        690 :                 if ((retcode = pkg_lua_script_run(pkg, PKG_LUA_PRE_INSTALL, (local != NULL))) != EPKG_OK)
    1181                 :          0 :                         goto cleanup;
    1182         [ +  + ]:        690 :                 if ((retcode = pkg_script_run(pkg, PKG_SCRIPT_PRE_INSTALL, (local != NULL))) != EPKG_OK)
    1183                 :          4 :                         goto cleanup;
    1184                 :        686 :         }
    1185                 :            : 
    1186                 :            : 
    1187                 :            :         /* add the user and group if necessary */
    1188                 :            : 
    1189                 :        699 :         nfiles = pkghash_count(pkg->filehash) + pkghash_count(pkg->dirhash);
    1190                 :            :         /*
    1191                 :            :          * Extract the files on disk.
    1192                 :            :          */
    1193         [ +  + ]:        699 :         if (extract) {
    1194                 :        440 :                 pkg_register_cleanup_callback(pkg_rollback_cb, pkg);
    1195                 :        440 :                 retcode = do_extract(a, ae, nfiles, pkg, local);
    1196                 :        440 :                 pkg_unregister_cleanup_callback(pkg_rollback_cb, pkg);
    1197         [ -  + ]:        440 :                 if (retcode != EPKG_OK) {
    1198                 :            :                         /* If the add failed, clean up (silently) */
    1199                 :            : 
    1200                 :          0 :                         pkg_rollback_pkg(pkg);
    1201                 :          0 :                         pkg_delete_dirs(db, pkg, NULL);
    1202                 :          0 :                         pkgdb_register_finale(db, retcode, NULL);
    1203                 :          0 :                         goto cleanup;
    1204                 :            :                 }
    1205                 :        440 :         }
    1206                 :            : 
    1207         [ +  + ]:        699 :         if (local != NULL) {
    1208                 :        132 :                 pkg_open_root_fd(local);
    1209                 :        132 :                 pkg_debug(1, "Cleaning up old version");
    1210         [ -  + ]:        132 :                 if (pkg_add_cleanup_old(db, local, pkg, flags) != EPKG_OK) {
    1211                 :          0 :                         retcode = EPKG_FATAL;
    1212                 :          0 :                         goto cleanup;
    1213                 :            :                 }
    1214                 :        132 :         }
    1215                 :            : 
    1216                 :            : 
    1217                 :            :         /* Update configuration file content with db with newer versions */
    1218                 :        699 :         pkgdb_update_config_file_content(pkg, db->sqlite);
    1219                 :            : 
    1220                 :        699 :         retcode = pkg_extract_finalize(pkg);
    1221                 :            : 
    1222                 :        699 :         pkgdb_register_finale(db, retcode, NULL);
    1223                 :            :         /*
    1224                 :            :          * Execute post install scripts
    1225                 :            :          */
    1226                 :            : 
    1227         [ -  + ]:        699 :         if (retcode != EPKG_OK)
    1228                 :          0 :                 goto cleanup;
    1229         [ +  + ]:        699 :         if ((flags & PKG_ADD_NOSCRIPT) == 0) {
    1230                 :        686 :                 pkg_lua_script_run(pkg, PKG_LUA_POST_INSTALL, (local != NULL));
    1231                 :        686 :                 pkg_script_run(pkg, PKG_SCRIPT_POST_INSTALL, (local != NULL));
    1232                 :        686 :         }
    1233                 :            : 
    1234                 :            :         /*
    1235                 :            :          * start the different related services if the users do want that
    1236                 :            :          * and that the service is running
    1237                 :            :          */
    1238                 :            : 
    1239                 :        699 :         pkg_start_stop_rc_scripts(pkg, PKG_RC_START);
    1240                 :            : 
    1241         [ +  + ]:        699 :         if ((flags & PKG_ADD_UPGRADE) == 0)
    1242                 :        164 :                 pkg_emit_install_finished(pkg, local);
    1243                 :            :         else {
    1244         [ +  + ]:        535 :                 if (local != NULL)
    1245                 :        132 :                         pkg_emit_upgrade_finished(pkg, local);
    1246                 :            :                 else
    1247                 :        403 :                         pkg_emit_install_finished(pkg, local);
    1248                 :            :         }
    1249                 :            : 
    1250         [ +  + ]:        783 :         LL_FOREACH(pkg->message, msg) {
    1251                 :         84 :                 msgstr = NULL;
    1252         [ +  + ]:         84 :                 if (msg->type == PKG_MESSAGE_ALWAYS) {
    1253                 :         12 :                         msgstr = msg->str;
    1254   [ +  -  +  + ]:         84 :                 } else if (local != NULL &&
    1255                 :         72 :                      msg->type == PKG_MESSAGE_UPGRADE) {
    1256   [ +  +  +  + ]:         48 :                         if (msg->maximum_version == NULL &&
    1257                 :         24 :                             msg->minimum_version == NULL) {
    1258                 :         12 :                                 msgstr = msg->str;
    1259         [ +  + ]:         48 :                         } else if (msg->maximum_version == NULL) {
    1260         [ +  + ]:         12 :                                 if (pkg_version_cmp(local->version, msg->minimum_version) == 1) {
    1261                 :          8 :                                         msgstr = msg->str;
    1262                 :          8 :                                 }
    1263         [ +  + ]:         36 :                         } else if (msg->minimum_version == NULL) {
    1264         [ +  + ]:         12 :                                 if (pkg_version_cmp(local->version, msg->maximum_version) == -1) {
    1265                 :          4 :                                         msgstr = msg->str;
    1266                 :          4 :                                 }
    1267   [ +  +  +  + ]:         24 :                         } else if (pkg_version_cmp(local->version, msg->maximum_version) == -1 &&
    1268                 :          8 :                                     pkg_version_cmp(local->version, msg->minimum_version) == 1) {
    1269                 :          4 :                                 msgstr = msg->str;
    1270                 :          4 :                         }
    1271   [ -  +  #  # ]:         72 :                 } else if (local == NULL &&
    1272                 :          0 :                     msg->type == PKG_MESSAGE_INSTALL) {
    1273                 :          0 :                         msgstr = msg->str;
    1274                 :          0 :                 }
    1275         [ +  + ]:         84 :                 if (msgstr != NULL) {
    1276         [ +  + ]:         40 :                         if (message == NULL) {
    1277                 :         12 :                                 message = xstring_new();
    1278                 :         24 :                                 pkg_fprintf(message->fp, "=====\nMessage from "
    1279                 :         12 :                                     "%n-%v:\n\n", pkg, pkg);
    1280                 :         12 :                         }
    1281                 :         40 :                         fprintf(message->fp, "--\n%s\n", msgstr);
    1282                 :         40 :                 }
    1283                 :         84 :         }
    1284   [ +  +  +  - ]:        711 :         if (pkg->message != NULL && message != NULL) {
    1285                 :         12 :                 fflush(message->fp);
    1286                 :         12 :                 pkg_emit_message(message->buf);
    1287                 :         12 :                 xstring_free(message);
    1288                 :         12 :         }
    1289                 :            : 
    1290                 :            : cleanup:
    1291         [ +  - ]:        742 :         if (a != NULL) {
    1292                 :        742 :                 archive_read_close(a);
    1293                 :        742 :                 archive_read_free(a);
    1294                 :        742 :         }
    1295                 :            : 
    1296                 :        742 :         pkg_free(pkg);
    1297                 :            : 
    1298                 :        742 :         return (retcode);
    1299                 :        742 : }
    1300                 :            : 
    1301                 :            : int
    1302                 :        203 : pkg_add(struct pkgdb *db, const char *path, unsigned flags,
    1303                 :            :     struct pkg_manifest_key *keys, const char *location)
    1304                 :            : {
    1305                 :        203 :         return pkg_add_common(db, path, flags, keys, location, NULL, NULL);
    1306                 :            : }
    1307                 :            : 
    1308                 :            : int
    1309                 :        407 : pkg_add_from_remote(struct pkgdb *db, const char *path, unsigned flags,
    1310                 :            :     struct pkg_manifest_key *keys, const char *location, struct pkg *rp)
    1311                 :            : {
    1312                 :        407 :         return pkg_add_common(db, path, flags, keys, location, rp, NULL);
    1313                 :            : }
    1314                 :            : 
    1315                 :            : int
    1316                 :        132 : pkg_add_upgrade(struct pkgdb *db, const char *path, unsigned flags,
    1317                 :            :     struct pkg_manifest_key *keys, const char *location,
    1318                 :            :     struct pkg *rp, struct pkg *lp)
    1319                 :            : {
    1320   [ -  +  -  + ]:        264 :         if (pkgdb_ensure_loaded(db, lp,
    1321                 :        132 :             PKG_LOAD_FILES|PKG_LOAD_SCRIPTS|PKG_LOAD_DIRS|PKG_LOAD_LUA_SCRIPTS) != EPKG_OK)
    1322                 :          0 :                 return (EPKG_FATAL);
    1323                 :            : 
    1324                 :        132 :         return pkg_add_common(db, path, flags, keys, location, rp, lp);
    1325                 :        132 : }
    1326                 :            : 
    1327                 :            : int
    1328                 :         12 : pkg_add_fromdir(struct pkg *pkg, const char *src)
    1329                 :            : {
    1330                 :            :         struct stat st;
    1331                 :         12 :         struct pkg_dir *d = NULL;
    1332                 :         12 :         struct pkg_file *f = NULL;
    1333                 :            :         char target[MAXPATHLEN];
    1334                 :            :         struct passwd *pw, pwent;
    1335                 :            :         struct group *gr, grent;
    1336                 :            :         int err, fd, fromfd;
    1337                 :            :         int retcode;
    1338                 :         12 :         kh_hls_t *hardlinks = NULL;;
    1339                 :            :         const char *path;
    1340                 :            :         char buffer[1024];
    1341                 :            :         size_t link_len;
    1342                 :            :         bool install_as_user;
    1343                 :            : 
    1344                 :         12 :         install_as_user = (getenv("INSTALL_AS_USER") != NULL);
    1345                 :            : 
    1346                 :         12 :         fromfd = open(src, O_DIRECTORY);
    1347         [ +  - ]:         12 :         if (fromfd == -1) {
    1348                 :          0 :                 pkg_fatal_errno("Unable to open source directory '%s'", src);
    1349                 :          0 :         }
    1350                 :         12 :         pkg_open_root_fd(pkg);
    1351                 :            : 
    1352         [ -  + ]:         12 :         while (pkg_dirs(pkg, &d) == EPKG_OK) {
    1353         [ #  # ]:          0 :                 if (fstatat(fromfd, RELATIVE_PATH(d->path), &st, 0) == -1) {
    1354                 :          0 :                         close(fromfd);
    1355                 :          0 :                         pkg_fatal_errno("%s%s", src, d->path);
    1356                 :          0 :                 }
    1357         [ #  # ]:          0 :                 if (d->perm == 0)
    1358                 :          0 :                         d->perm = st.st_mode & ~S_IFMT;
    1359         [ #  # ]:          0 :                 if (d->uname[0] != '\0') {
    1360                 :          0 :                         err = getpwnam_r(d->uname, &pwent, buffer,
    1361                 :            :                             sizeof(buffer), &pw);
    1362         [ #  # ]:          0 :                         if (err != 0) {
    1363                 :          0 :                                 pkg_emit_errno("getpwnam_r", d->uname);
    1364                 :          0 :                                 retcode = EPKG_FATAL;
    1365                 :          0 :                                 goto cleanup;
    1366                 :            :                         }
    1367                 :          0 :                         d->uid = pwent.pw_uid;
    1368                 :          0 :                 } else {
    1369         [ #  # ]:          0 :                         d->uid = install_as_user ? st.st_uid : 0;
    1370                 :            :                 }
    1371         [ #  # ]:          0 :                 if (d->gname[0] != '\0') {
    1372                 :          0 :                         err = getgrnam_r(d->gname, &grent, buffer,
    1373                 :            :                             sizeof(buffer), &gr);
    1374         [ #  # ]:          0 :                         if (err != 0) {
    1375                 :          0 :                                 pkg_emit_errno("getgrnam_r", d->gname);
    1376                 :          0 :                                 retcode = EPKG_FATAL;
    1377                 :          0 :                                 goto cleanup;
    1378                 :            :                         }
    1379                 :          0 :                         d->gid = grent.gr_gid;
    1380                 :          0 :                 } else {
    1381                 :          0 :                         d->gid = st.st_gid;
    1382                 :            :                 }
    1383                 :            : #ifdef HAVE_STRUCT_STAT_ST_MTIM
    1384                 :          0 :                 d->time[0] = st.st_atim;
    1385                 :          0 :                 d->time[1] = st.st_mtim;
    1386                 :            : #else
    1387                 :            : #if defined(_DARWIN_C_SOURCE) || defined(__APPLE__)
    1388                 :            :                 d->time[0] = st.st_atimespec;
    1389                 :            :                 d->time[1] = st.st_mtimespec;
    1390                 :            : #else
    1391                 :            :                 d->time[0].tv_sec = st.st_atime;
    1392                 :            :                 d->time[0].tv_nsec = 0;
    1393                 :            :                 d->time[1].tv_sec = st.st_mtime;
    1394                 :            :                 d->time[1].tv_nsec = 0;
    1395                 :            : #endif
    1396                 :            : #endif
    1397                 :            : 
    1398         [ #  # ]:          0 :                 if (create_dir(pkg, d) == EPKG_FATAL) {
    1399                 :          0 :                         retcode = EPKG_FATAL;
    1400                 :          0 :                         goto cleanup;
    1401                 :            :                 }
    1402                 :            :         }
    1403                 :            : 
    1404                 :         12 :         hardlinks = kh_init_hls();
    1405         [ +  + ]:         40 :         while (pkg_files(pkg, &f) == EPKG_OK) {
    1406   [ -  +  -  + ]:         56 :                 if (match_ucl_lists(f->path,
    1407                 :         28 :                     pkg_config_get("FILES_IGNORE_GLOB"),
    1408                 :         28 :                     pkg_config_get("FILES_IGNORE_REGEX")))
    1409                 :          0 :                         continue;
    1410   [ +  -  +  - ]:         56 :                 if (fstatat(fromfd, RELATIVE_PATH(f->path), &st,
    1411                 :         28 :                     AT_SYMLINK_NOFOLLOW) == -1) {
    1412                 :          0 :                         kh_destroy_hls(hardlinks);
    1413                 :          0 :                         close(fromfd);
    1414                 :          0 :                         pkg_fatal_errno("%s%s", src, f->path);
    1415                 :          0 :                 }
    1416         [ +  + ]:         28 :                 if (f->uname[0] != '\0') {
    1417                 :         24 :                         err = getpwnam_r(f->uname, &pwent, buffer,
    1418                 :            :                             sizeof(buffer), &pw);
    1419         [ +  - ]:         24 :                         if (err != 0) {
    1420                 :          0 :                                 pkg_emit_errno("getpwnam_r", f->uname);
    1421                 :          0 :                                 retcode = EPKG_FATAL;
    1422                 :          0 :                                 goto cleanup;
    1423                 :            :                         }
    1424                 :         24 :                         f->uid = pwent.pw_uid;
    1425                 :         24 :                 } else {
    1426         [ +  - ]:          4 :                         f->uid = install_as_user ? st.st_uid : 0;
    1427                 :            :                 }
    1428                 :            : 
    1429         [ +  + ]:         28 :                 if (f->gname[0] != '\0') {
    1430                 :         24 :                         err = getgrnam_r(f->gname, &grent, buffer,
    1431                 :            :                             sizeof(buffer), &gr);
    1432         [ +  - ]:         24 :                         if (err != 0) {
    1433                 :          0 :                                 pkg_emit_errno("getgrnam_r", f->gname);
    1434                 :          0 :                                 retcode = EPKG_FATAL;
    1435                 :          0 :                                 goto cleanup;
    1436                 :            :                         }
    1437                 :         24 :                         f->gid = grent.gr_gid;
    1438                 :         24 :                 } else {
    1439                 :          4 :                         f->gid = st.st_gid;
    1440                 :            :                 }
    1441                 :            : 
    1442         [ -  + ]:         28 :                 if (f->perm == 0)
    1443                 :         28 :                         f->perm = st.st_mode & ~S_IFMT;
    1444   [ +  +  -  + ]:         28 :                 if (f->uid == 0 && install_as_user)
    1445                 :         24 :                         f->uid = st.st_uid;
    1446                 :            : #ifdef HAVE_STRUCT_STAT_ST_MTIM
    1447                 :         28 :                 f->time[0] = st.st_atim;
    1448                 :         28 :                 f->time[1] = st.st_mtim;
    1449                 :            : #else
    1450                 :            : #if defined(_DARWIN_C_SOURCE) || defined(__APPLE__)
    1451                 :            :                 f->time[0] = st.st_atimespec;
    1452                 :            :                 f->time[1] = st.st_mtimespec;
    1453                 :            : #else
    1454                 :            :                 f->time[0].tv_sec = st.st_atime;
    1455                 :            :                 f->time[0].tv_nsec = 0;
    1456                 :            :                 f->time[1].tv_sec = st.st_mtime;
    1457                 :            :                 f->time[1].tv_nsec = 0;
    1458                 :            : #endif
    1459                 :            : #endif
    1460                 :            : 
    1461         [ +  + ]:         28 :                 if (S_ISLNK(st.st_mode)) {
    1462   [ +  -  +  -  :         36 :                         if ((link_len = readlinkat(fromfd,
                   +  - ]
    1463                 :         12 :                             RELATIVE_PATH(f->path), target,
    1464                 :         12 :                             sizeof(target))) == -1) {
    1465                 :          0 :                                 kh_destroy_hls(hardlinks);
    1466                 :          0 :                                 close(fromfd);
    1467                 :          0 :                                 pkg_fatal_errno("Impossible to read symlinks "
    1468                 :            :                                     "'%s'", f->path);
    1469                 :          0 :                         }
    1470                 :         12 :                         target[link_len] = '\0';
    1471         [ +  - ]:         12 :                         if (create_symlinks(pkg, f, target) == EPKG_FATAL) {
    1472                 :          0 :                                 retcode = EPKG_FATAL;
    1473                 :          0 :                                 goto cleanup;
    1474                 :            :                         }
    1475         [ +  - ]:         28 :                 } else if (S_ISREG(st.st_mode)) {
    1476   [ +  -  +  - ]:         32 :                         if ((fd = openat(fromfd, RELATIVE_PATH(f->path),
    1477                 :         16 :                             O_RDONLY)) == -1) {
    1478                 :          0 :                                 kh_destroy_hls(hardlinks);
    1479                 :          0 :                                 close(fromfd);
    1480                 :          0 :                                 pkg_fatal_errno("Impossible to open source file"
    1481                 :            :                                     " '%s'", RELATIVE_PATH(f->path));
    1482                 :          0 :                         }
    1483   [ -  +  +  + ]:         16 :                         kh_find(hls, hardlinks, st.st_ino, path);
    1484         [ +  + ]:         16 :                         if (path != NULL) {
    1485         [ +  - ]:          4 :                                 if (create_hardlink(pkg, f, path) == EPKG_FATAL) {
    1486                 :          0 :                                         close(fd);
    1487                 :          0 :                                         retcode = EPKG_FATAL;
    1488                 :          0 :                                         goto cleanup;
    1489                 :            :                                 }
    1490                 :          4 :                         } else {
    1491         [ +  - ]:         12 :                                 if (create_regfile(pkg, f, NULL, NULL, fd, NULL) == EPKG_FATAL) {
    1492                 :          0 :                                         close(fd);
    1493                 :          0 :                                         retcode = EPKG_FATAL;
    1494                 :          0 :                                         goto cleanup;
    1495                 :            :                                 }
    1496   [ +  -  -  + ]:         12 :                                 kh_safe_add(hls, hardlinks, f->path, st.st_ino);
    1497                 :            :                         }
    1498                 :         16 :                         close(fd);
    1499                 :         16 :                 } else {
    1500                 :          0 :                         pkg_emit_error("Invalid file type");
    1501                 :          0 :                         retcode = EPKG_FATAL;
    1502                 :          0 :                         goto cleanup;
    1503                 :            :                 }
    1504                 :            :         }
    1505                 :            : 
    1506                 :         12 :         retcode = pkg_extract_finalize(pkg);
    1507                 :            : 
    1508                 :            : cleanup:
    1509                 :         12 :         kh_destroy_hls(hardlinks);
    1510                 :         12 :         close(fromfd);
    1511                 :         12 :         return (retcode);
    1512                 :         12 : }
    1513                 :            : 

Generated by: LCOV version 1.15