LCOV - code coverage report
Current view: top level - libpkg - pkg_add.c (source / functions) Hit Total Coverage
Test: plop Lines: 721 1123 64.2 %
Date: 2024-12-28 18:40:32 Functions: 31 36 86.1 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 416 752 55.3 %

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

Generated by: LCOV version 1.15