LCOV - code coverage report
Current view: top level - lib/dpkg - compress.c (source / functions) Hit Total Coverage
Test: dpkg 1.21.11 C code coverage Lines: 204 370 55.1 %
Date: 2022-12-03 00:40:01 Functions: 26 34 76.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 62 190 32.6 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * libdpkg - Debian packaging suite library routines
       3                 :            :  * compress.c - compression support functions
       4                 :            :  *
       5                 :            :  * Copyright © 2000 Wichert Akkerman <wakkerma@debian.org>
       6                 :            :  * Copyright © 2004 Scott James Remnant <scott@netsplit.com>
       7                 :            :  * Copyright © 2006-2015 Guillem Jover <guillem@debian.org>
       8                 :            :  *
       9                 :            :  * This is free software; you can redistribute it and/or modify
      10                 :            :  * it under the terms of the GNU General Public License as published by
      11                 :            :  * the Free Software Foundation; either version 2 of the License, or
      12                 :            :  * (at your option) any later version.
      13                 :            :  *
      14                 :            :  * This is distributed in the hope that it will be useful,
      15                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17                 :            :  * GNU General Public License for more details.
      18                 :            :  *
      19                 :            :  * You should have received a copy of the GNU General Public License
      20                 :            :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21                 :            :  */
      22                 :            : 
      23                 :            : #include <config.h>
      24                 :            : #include <compat.h>
      25                 :            : 
      26                 :            : #include <errno.h>
      27                 :            : #include <string.h>
      28                 :            : #include <unistd.h>
      29                 :            : #include <stdbool.h>
      30                 :            : #include <stdlib.h>
      31                 :            : 
      32                 :            : #if USE_LIBZ_IMPL != USE_LIBZ_IMPL_NONE
      33                 :            : #include <compat-zlib.h>
      34                 :            : #endif
      35                 :            : #ifdef WITH_LIBLZMA
      36                 :            : #include <lzma.h>
      37                 :            : #endif
      38                 :            : #ifdef WITH_LIBBZ2
      39                 :            : #include <bzlib.h>
      40                 :            : #endif
      41                 :            : 
      42                 :            : #include <dpkg/i18n.h>
      43                 :            : #include <dpkg/dpkg.h>
      44                 :            : #include <dpkg/error.h>
      45                 :            : #include <dpkg/varbuf.h>
      46                 :            : #include <dpkg/fdio.h>
      47                 :            : #include <dpkg/buffer.h>
      48                 :            : #include <dpkg/meminfo.h>
      49                 :            : #include <dpkg/command.h>
      50                 :            : #include <dpkg/compress.h>
      51                 :            : #if USE_LIBZ_IMPL == USE_LIBZ_IMPL_NONE || \
      52                 :            :     !defined(WITH_LIBLZMA) || \
      53                 :            :     !defined(WITH_LIBBZ2)
      54                 :            : #include <dpkg/subproc.h>
      55                 :            : 
      56                 :            : static void
      57                 :            : fd_fd_filter(struct command *cmd, int fd_in, int fd_out, const char *delenv[])
      58                 :            : {
      59                 :            :         pid_t pid;
      60                 :            :         int i;
      61                 :            : 
      62                 :            :         pid = subproc_fork();
      63                 :            :         if (pid == 0) {
      64                 :            :                 if (fd_in != 0) {
      65                 :            :                         m_dup2(fd_in, 0);
      66                 :            :                         close(fd_in);
      67                 :            :                 }
      68                 :            :                 if (fd_out != 1) {
      69                 :            :                         m_dup2(fd_out, 1);
      70                 :            :                         close(fd_out);
      71                 :            :                 }
      72                 :            : 
      73                 :            :                 for (i = 0; delenv[i]; i++)
      74                 :            :                         unsetenv(delenv[i]);
      75                 :            : 
      76                 :            :                 command_exec(cmd);
      77                 :            :         }
      78                 :            :         subproc_reap(pid, cmd->name, 0);
      79                 :            : }
      80                 :            : 
      81                 :            : static void
      82                 :            : command_compress_init(struct command *cmd, const char *name, const char *desc,
      83                 :            :                       int level)
      84                 :            : {
      85                 :            :         static char combuf[6];
      86                 :            : 
      87                 :            :         command_init(cmd, name, desc);
      88                 :            :         command_add_arg(cmd, name);
      89                 :            : 
      90                 :            :         snprintf(combuf, sizeof(combuf), "-c%d", level);
      91                 :            :         command_add_arg(cmd, combuf);
      92                 :            : }
      93                 :            : 
      94                 :            : static void
      95                 :            : command_decompress_init(struct command *cmd, const char *name, const char *desc)
      96                 :            : {
      97                 :            :         command_init(cmd, name, desc);
      98                 :            :         command_add_arg(cmd, name);
      99                 :            :         command_add_arg(cmd, "-dc");
     100                 :            : }
     101                 :            : #endif
     102                 :            : 
     103                 :            : struct compressor {
     104                 :            :         const char *name;
     105                 :            :         const char *extension;
     106                 :            :         int default_level;
     107                 :            :         void (*fixup_params)(struct compress_params *params);
     108                 :            :         void (*compress)(struct compress_params *params,
     109                 :            :                          int fd_in, int fd_out, const char *desc);
     110                 :            :         void (*decompress)(struct compress_params *params,
     111                 :            :                            int fd_in, int fd_out, const char *desc);
     112                 :            : };
     113                 :            : 
     114                 :            : /*
     115                 :            :  * No compressor (pass-through).
     116                 :            :  */
     117                 :            : 
     118                 :            : static void
     119                 :         58 : fixup_none_params(struct compress_params *params)
     120                 :            : {
     121                 :         58 : }
     122                 :            : 
     123                 :            : static void
     124                 :          7 : decompress_none(struct compress_params *params, int fd_in, int fd_out,
     125                 :            :                 const char *desc)
     126                 :            : {
     127                 :            :         struct dpkg_error err;
     128                 :            : 
     129         [ -  + ]:          7 :         if (fd_fd_copy(fd_in, fd_out, -1, &err) < 0)
     130                 :          0 :                 ohshit(_("%s: pass-through copy error: %s"), desc, err.str);
     131                 :          7 : }
     132                 :            : 
     133                 :            : static void
     134                 :          4 : compress_none(struct compress_params *params, int fd_in, int fd_out,
     135                 :            :               const char *desc)
     136                 :            : {
     137                 :            :         struct dpkg_error err;
     138                 :            : 
     139         [ -  + ]:          4 :         if (fd_fd_copy(fd_in, fd_out, -1, &err) < 0)
     140                 :          0 :                 ohshit(_("%s: pass-through copy error: %s"), desc, err.str);
     141                 :          4 : }
     142                 :            : 
     143                 :            : static const struct compressor compressor_none = {
     144                 :            :         .name = "none",
     145                 :            :         .extension = "",
     146                 :            :         .default_level = 0,
     147                 :            :         .fixup_params = fixup_none_params,
     148                 :            :         .compress = compress_none,
     149                 :            :         .decompress = decompress_none,
     150                 :            : };
     151                 :            : 
     152                 :            : /*
     153                 :            :  * Gzip compressor.
     154                 :            :  */
     155                 :            : 
     156                 :            : #define GZIP            "gzip"
     157                 :            : 
     158                 :            : static void
     159                 :          1 : fixup_gzip_params(struct compress_params *params)
     160                 :            : {
     161                 :            :         /* Normalize compression level. */
     162         [ -  + ]:          1 :         if (params->level == 0)
     163                 :          0 :                 params->type = COMPRESSOR_TYPE_NONE;
     164                 :          1 : }
     165                 :            : 
     166                 :            : #if USE_LIBZ_IMPL != USE_LIBZ_IMPL_NONE
     167                 :            : static void
     168                 :         11 : decompress_gzip(struct compress_params *params, int fd_in, int fd_out,
     169                 :            :                 const char *desc)
     170                 :            : {
     171                 :            :         char *buffer;
     172                 :         11 :         size_t bufsize = DPKG_BUFFER_SIZE;
     173                 :            :         int z_errnum;
     174                 :         11 :         gzFile gzfile = gzdopen(fd_in, "r");
     175                 :            : 
     176         [ -  + ]:         11 :         if (gzfile == NULL)
     177                 :          0 :                 ohshit(_("%s: error binding input to gzip stream"), desc);
     178                 :            : 
     179                 :         11 :         buffer = m_malloc(bufsize);
     180                 :            : 
     181                 :         11 :         for (;;) {
     182                 :            :                 int actualread, actualwrite;
     183                 :            : 
     184                 :         22 :                 actualread = gzread(gzfile, buffer, bufsize);
     185         [ -  + ]:         22 :                 if (actualread < 0) {
     186                 :          0 :                         const char *errmsg = gzerror(gzfile, &z_errnum);
     187                 :            : 
     188         [ #  # ]:          0 :                         if (z_errnum == Z_ERRNO)
     189                 :          0 :                                 errmsg = strerror(errno);
     190                 :          0 :                         ohshit(_("%s: internal gzip read error: '%s'"), desc,
     191                 :            :                                errmsg);
     192                 :            :                 }
     193         [ +  + ]:         22 :                 if (actualread == 0) /* EOF. */
     194                 :         11 :                         break;
     195                 :            : 
     196                 :         11 :                 actualwrite = fd_write(fd_out, buffer, actualread);
     197         [ -  + ]:         11 :                 if (actualwrite != actualread)
     198                 :          0 :                         ohshite(_("%s: internal gzip write error"), desc);
     199                 :            :         }
     200                 :            : 
     201                 :         11 :         free(buffer);
     202                 :            : 
     203                 :         11 :         z_errnum = gzclose(gzfile);
     204         [ -  + ]:         11 :         if (z_errnum) {
     205                 :            :                 const char *errmsg;
     206                 :            : 
     207         [ #  # ]:          0 :                 if (z_errnum == Z_ERRNO)
     208                 :          0 :                         errmsg = strerror(errno);
     209                 :            :                 else
     210                 :          0 :                         errmsg = zError(z_errnum);
     211                 :          0 :                 ohshit(_("%s: internal gzip read error: %s"), desc, errmsg);
     212                 :            :         }
     213                 :            : 
     214         [ -  + ]:         11 :         if (close(fd_out))
     215                 :          0 :                 ohshite(_("%s: internal gzip write error"), desc);
     216                 :         11 : }
     217                 :            : 
     218                 :            : static void
     219                 :          2 : compress_gzip(struct compress_params *params, int fd_in, int fd_out,
     220                 :            :               const char *desc)
     221                 :            : {
     222                 :            :         char *buffer;
     223                 :            :         char combuf[6];
     224                 :          2 :         size_t bufsize = DPKG_BUFFER_SIZE;
     225                 :            :         int strategy;
     226                 :            :         int z_errnum;
     227                 :            :         gzFile gzfile;
     228                 :            : 
     229         [ -  + ]:          2 :         if (params->strategy == COMPRESSOR_STRATEGY_FILTERED)
     230                 :          0 :                 strategy = 'f';
     231         [ -  + ]:          2 :         else if (params->strategy == COMPRESSOR_STRATEGY_HUFFMAN)
     232                 :          0 :                 strategy = 'h';
     233         [ -  + ]:          2 :         else if (params->strategy == COMPRESSOR_STRATEGY_RLE)
     234                 :          0 :                 strategy = 'R';
     235         [ -  + ]:          2 :         else if (params->strategy == COMPRESSOR_STRATEGY_FIXED)
     236                 :          0 :                 strategy = 'F';
     237                 :            :         else
     238                 :          2 :                 strategy = ' ';
     239                 :            : 
     240                 :          2 :         snprintf(combuf, sizeof(combuf), "w%d%c", params->level, strategy);
     241                 :          2 :         gzfile = gzdopen(fd_out, combuf);
     242         [ -  + ]:          2 :         if (gzfile == NULL)
     243                 :          0 :                 ohshit(_("%s: error binding output to gzip stream"), desc);
     244                 :            : 
     245                 :          2 :         buffer = m_malloc(bufsize);
     246                 :            : 
     247                 :          2 :         for (;;) {
     248                 :            :                 int actualread, actualwrite;
     249                 :            : 
     250                 :          4 :                 actualread = fd_read(fd_in, buffer, bufsize);
     251         [ -  + ]:          4 :                 if (actualread < 0)
     252                 :          0 :                         ohshite(_("%s: internal gzip read error"), desc);
     253         [ +  + ]:          4 :                 if (actualread == 0) /* EOF. */
     254                 :          2 :                         break;
     255                 :            : 
     256                 :          2 :                 actualwrite = gzwrite(gzfile, buffer, actualread);
     257         [ -  + ]:          2 :                 if (actualwrite != actualread) {
     258                 :          0 :                         const char *errmsg = gzerror(gzfile, &z_errnum);
     259                 :            : 
     260         [ #  # ]:          0 :                         if (z_errnum == Z_ERRNO)
     261                 :          0 :                                 errmsg = strerror(errno);
     262                 :          0 :                         ohshit(_("%s: internal gzip write error: '%s'"), desc,
     263                 :            :                                errmsg);
     264                 :            :                 }
     265                 :            :         }
     266                 :            : 
     267                 :          2 :         free(buffer);
     268                 :            : 
     269                 :          2 :         z_errnum = gzclose(gzfile);
     270         [ -  + ]:          2 :         if (z_errnum) {
     271                 :            :                 const char *errmsg;
     272                 :            : 
     273         [ #  # ]:          0 :                 if (z_errnum == Z_ERRNO)
     274                 :          0 :                         errmsg = strerror(errno);
     275                 :            :                 else
     276                 :          0 :                         errmsg = zError(z_errnum);
     277                 :          0 :                 ohshit(_("%s: internal gzip write error: %s"), desc, errmsg);
     278                 :            :         }
     279                 :          2 : }
     280                 :            : #else
     281                 :            : static const char *env_gzip[] = { "GZIP", NULL };
     282                 :            : 
     283                 :            : static void
     284                 :            : decompress_gzip(struct compress_params *params, int fd_in, int fd_out,
     285                 :            :                 const char *desc)
     286                 :            : {
     287                 :            :         struct command cmd;
     288                 :            : 
     289                 :            :         command_decompress_init(&cmd, GZIP, desc);
     290                 :            : 
     291                 :            :         fd_fd_filter(&cmd, fd_in, fd_out, env_gzip);
     292                 :            : 
     293                 :            :         command_destroy(&cmd);
     294                 :            : }
     295                 :            : 
     296                 :            : static void
     297                 :            : compress_gzip(struct compress_params *params, int fd_in, int fd_out,
     298                 :            :               const char *desc)
     299                 :            : {
     300                 :            :         struct command cmd;
     301                 :            : 
     302                 :            :         command_compress_init(&cmd, GZIP, desc, params->level);
     303                 :            :         command_add_arg(&cmd, "-n");
     304                 :            : 
     305                 :            :         fd_fd_filter(&cmd, fd_in, fd_out, env_gzip);
     306                 :            : 
     307                 :            :         command_destroy(&cmd);
     308                 :            : }
     309                 :            : #endif
     310                 :            : 
     311                 :            : static const struct compressor compressor_gzip = {
     312                 :            :         .name = "gzip",
     313                 :            :         .extension = ".gz",
     314                 :            :         .default_level = 9,
     315                 :            :         .fixup_params = fixup_gzip_params,
     316                 :            :         .compress = compress_gzip,
     317                 :            :         .decompress = decompress_gzip,
     318                 :            : };
     319                 :            : 
     320                 :            : /*
     321                 :            :  * Bzip2 compressor.
     322                 :            :  */
     323                 :            : 
     324                 :            : #define BZIP2           "bzip2"
     325                 :            : 
     326                 :            : static void
     327                 :          0 : fixup_bzip2_params(struct compress_params *params)
     328                 :            : {
     329                 :            :         /* Normalize compression level. */
     330         [ #  # ]:          0 :         if (params->level == 0)
     331                 :          0 :                 params->level = 1;
     332                 :          0 : }
     333                 :            : 
     334                 :            : #ifdef WITH_LIBBZ2
     335                 :            : static void
     336                 :          1 : decompress_bzip2(struct compress_params *params, int fd_in, int fd_out,
     337                 :            :                  const char *desc)
     338                 :            : {
     339                 :            :         char *buffer;
     340                 :          1 :         size_t bufsize = DPKG_BUFFER_SIZE;
     341                 :          1 :         BZFILE *bzfile = BZ2_bzdopen(fd_in, "r");
     342                 :            : 
     343         [ -  + ]:          1 :         if (bzfile == NULL)
     344                 :          0 :                 ohshit(_("%s: error binding input to bzip2 stream"), desc);
     345                 :            : 
     346                 :          1 :         buffer = m_malloc(bufsize);
     347                 :            : 
     348                 :          1 :         for (;;) {
     349                 :            :                 int actualread, actualwrite;
     350                 :            : 
     351                 :          2 :                 actualread = BZ2_bzread(bzfile, buffer, bufsize);
     352         [ -  + ]:          2 :                 if (actualread < 0) {
     353                 :          0 :                         int bz_errnum = 0;
     354                 :          0 :                         const char *errmsg = BZ2_bzerror(bzfile, &bz_errnum);
     355                 :            : 
     356         [ #  # ]:          0 :                         if (bz_errnum == BZ_IO_ERROR)
     357                 :          0 :                                 errmsg = strerror(errno);
     358                 :          0 :                         ohshit(_("%s: internal bzip2 read error: '%s'"), desc,
     359                 :            :                                errmsg);
     360                 :            :                 }
     361         [ +  + ]:          2 :                 if (actualread == 0) /* EOF. */
     362                 :          1 :                         break;
     363                 :            : 
     364                 :          1 :                 actualwrite = fd_write(fd_out, buffer, actualread);
     365         [ -  + ]:          1 :                 if (actualwrite != actualread)
     366                 :          0 :                         ohshite(_("%s: internal bzip2 write error"), desc);
     367                 :            :         }
     368                 :            : 
     369                 :          1 :         free(buffer);
     370                 :            : 
     371                 :          1 :         BZ2_bzclose(bzfile);
     372                 :            : 
     373         [ -  + ]:          1 :         if (close(fd_out))
     374                 :          0 :                 ohshite(_("%s: internal bzip2 write error"), desc);
     375                 :          1 : }
     376                 :            : 
     377                 :            : static void
     378                 :          0 : compress_bzip2(struct compress_params *params, int fd_in, int fd_out,
     379                 :            :                const char *desc)
     380                 :            : {
     381                 :            :         char *buffer;
     382                 :            :         char combuf[6];
     383                 :          0 :         size_t bufsize = DPKG_BUFFER_SIZE;
     384                 :            :         int bz_errnum;
     385                 :            :         BZFILE *bzfile;
     386                 :            : 
     387                 :          0 :         snprintf(combuf, sizeof(combuf), "w%d", params->level);
     388                 :          0 :         bzfile = BZ2_bzdopen(fd_out, combuf);
     389         [ #  # ]:          0 :         if (bzfile == NULL)
     390                 :          0 :                 ohshit(_("%s: error binding output to bzip2 stream"), desc);
     391                 :            : 
     392                 :          0 :         buffer = m_malloc(bufsize);
     393                 :            : 
     394                 :          0 :         for (;;) {
     395                 :            :                 int actualread, actualwrite;
     396                 :            : 
     397                 :          0 :                 actualread = fd_read(fd_in, buffer, bufsize);
     398         [ #  # ]:          0 :                 if (actualread < 0)
     399                 :          0 :                         ohshite(_("%s: internal bzip2 read error"), desc);
     400         [ #  # ]:          0 :                 if (actualread == 0) /* EOF. */
     401                 :          0 :                         break;
     402                 :            : 
     403                 :          0 :                 actualwrite = BZ2_bzwrite(bzfile, buffer, actualread);
     404         [ #  # ]:          0 :                 if (actualwrite != actualread) {
     405                 :          0 :                         const char *errmsg = BZ2_bzerror(bzfile, &bz_errnum);
     406                 :            : 
     407         [ #  # ]:          0 :                         if (bz_errnum == BZ_IO_ERROR)
     408                 :          0 :                                 errmsg = strerror(errno);
     409                 :          0 :                         ohshit(_("%s: internal bzip2 write error: '%s'"), desc,
     410                 :            :                                errmsg);
     411                 :            :                 }
     412                 :            :         }
     413                 :            : 
     414                 :          0 :         free(buffer);
     415                 :            : 
     416                 :          0 :         BZ2_bzWriteClose(&bz_errnum, bzfile, 0, NULL, NULL);
     417         [ #  # ]:          0 :         if (bz_errnum != BZ_OK) {
     418                 :          0 :                 const char *errmsg = _("unexpected bzip2 error");
     419                 :            : 
     420         [ #  # ]:          0 :                 if (bz_errnum == BZ_IO_ERROR)
     421                 :          0 :                         errmsg = strerror(errno);
     422                 :          0 :                 ohshit(_("%s: internal bzip2 write error: '%s'"), desc,
     423                 :            :                        errmsg);
     424                 :            :         }
     425                 :            : 
     426                 :            :         /* Because BZ2_bzWriteClose has done a fflush on the file handle,
     427                 :            :          * doing a close on the file descriptor associated with it should
     428                 :            :          * be safe™. */
     429         [ #  # ]:          0 :         if (close(fd_out))
     430                 :          0 :                 ohshite(_("%s: internal bzip2 write error"), desc);
     431                 :          0 : }
     432                 :            : #else
     433                 :            : static const char *env_bzip2[] = { "BZIP", "BZIP2", NULL };
     434                 :            : 
     435                 :            : static void
     436                 :            : decompress_bzip2(struct compress_params *params, int fd_in, int fd_out,
     437                 :            :                  const char *desc)
     438                 :            : {
     439                 :            :         struct command cmd;
     440                 :            : 
     441                 :            :         command_decompress_init(&cmd, BZIP2, desc);
     442                 :            : 
     443                 :            :         fd_fd_filter(&cmd, fd_in, fd_out, env_bzip2);
     444                 :            : 
     445                 :            :         command_destroy(&cmd);
     446                 :            : }
     447                 :            : 
     448                 :            : static void
     449                 :            : compress_bzip2(struct compress_params *params, int fd_in, int fd_out,
     450                 :            :                const char *desc)
     451                 :            : {
     452                 :            :         struct command cmd;
     453                 :            : 
     454                 :            :         command_compress_init(&cmd, BZIP2, desc, params->level);
     455                 :            : 
     456                 :            :         fd_fd_filter(&cmd, fd_in, fd_out, env_bzip2);
     457                 :            : 
     458                 :            :         command_destroy(&cmd);
     459                 :            : }
     460                 :            : #endif
     461                 :            : 
     462                 :            : static const struct compressor compressor_bzip2 = {
     463                 :            :         .name = "bzip2",
     464                 :            :         .extension = ".bz2",
     465                 :            :         .default_level = 9,
     466                 :            :         .fixup_params = fixup_bzip2_params,
     467                 :            :         .compress = compress_bzip2,
     468                 :            :         .decompress = decompress_bzip2,
     469                 :            : };
     470                 :            : 
     471                 :            : /*
     472                 :            :  * Xz compressor.
     473                 :            :  */
     474                 :            : 
     475                 :            : #define XZ              "xz"
     476                 :            : 
     477                 :            : #ifdef WITH_LIBLZMA
     478                 :            : enum dpkg_stream_status {
     479                 :            :         DPKG_STREAM_INIT        = DPKG_BIT(1),
     480                 :            :         DPKG_STREAM_RUN         = DPKG_BIT(2),
     481                 :            :         DPKG_STREAM_COMPRESS    = DPKG_BIT(3),
     482                 :            :         DPKG_STREAM_DECOMPRESS  = DPKG_BIT(4),
     483                 :            :         DPKG_STREAM_FILTER      = DPKG_STREAM_COMPRESS | DPKG_STREAM_DECOMPRESS,
     484                 :            : };
     485                 :            : 
     486                 :            : /* XXX: liblzma does not expose error messages. */
     487                 :            : static const char *
     488                 :          0 : dpkg_lzma_strerror(lzma_ret code, enum dpkg_stream_status status)
     489                 :            : {
     490                 :          0 :         const char *const impossible = _("internal error (bug)");
     491                 :            : 
     492   [ #  #  #  #  :          0 :         switch (code) {
             #  #  #  # ]
     493                 :          0 :         case LZMA_MEM_ERROR:
     494                 :          0 :                 return strerror(ENOMEM);
     495                 :          0 :         case LZMA_MEMLIMIT_ERROR:
     496         [ #  # ]:          0 :                 if (status & DPKG_STREAM_RUN)
     497                 :          0 :                         return _("memory usage limit reached");
     498                 :          0 :                 return impossible;
     499                 :          0 :         case LZMA_OPTIONS_ERROR:
     500         [ #  # ]:          0 :                 if (status == (DPKG_STREAM_INIT | DPKG_STREAM_COMPRESS))
     501                 :          0 :                         return _("unsupported compression preset");
     502         [ #  # ]:          0 :                 if (status == (DPKG_STREAM_RUN | DPKG_STREAM_DECOMPRESS))
     503                 :          0 :                         return _("unsupported options in file header");
     504                 :          0 :                 return impossible;
     505                 :          0 :         case LZMA_DATA_ERROR:
     506         [ #  # ]:          0 :                 if (status & DPKG_STREAM_RUN)
     507                 :          0 :                         return _("compressed data is corrupt");
     508                 :          0 :                 return impossible;
     509                 :          0 :         case LZMA_BUF_ERROR:
     510         [ #  # ]:          0 :                 if (status & DPKG_STREAM_RUN)
     511                 :          0 :                         return _("unexpected end of input");
     512                 :          0 :                 return impossible;
     513                 :          0 :         case LZMA_FORMAT_ERROR:
     514         [ #  # ]:          0 :                 if (status == (DPKG_STREAM_RUN | DPKG_STREAM_DECOMPRESS))
     515                 :          0 :                         return _("file format not recognized");
     516                 :          0 :                 return impossible;
     517                 :          0 :         case LZMA_UNSUPPORTED_CHECK:
     518         [ #  # ]:          0 :                 if (status == (DPKG_STREAM_INIT | DPKG_STREAM_COMPRESS))
     519                 :          0 :                         return _("unsupported type of integrity check");
     520                 :          0 :                 return impossible;
     521                 :          0 :         default:
     522                 :          0 :                 return impossible;
     523                 :            :         }
     524                 :            : }
     525                 :            : 
     526                 :            : struct io_lzma {
     527                 :            :         const char *desc;
     528                 :            : 
     529                 :            :         struct compress_params *params;
     530                 :            :         enum dpkg_stream_status status;
     531                 :            :         lzma_action action;
     532                 :            : 
     533                 :            :         void (*init)(struct io_lzma *io, lzma_stream *s);
     534                 :            :         int (*code)(struct io_lzma *io, lzma_stream *s);
     535                 :            :         void (*done)(struct io_lzma *io, lzma_stream *s);
     536                 :            : };
     537                 :            : 
     538                 :            : static void
     539                 :         21 : filter_lzma(struct io_lzma *io, int fd_in, int fd_out)
     540                 :            : {
     541                 :            :         uint8_t *buf_in;
     542                 :            :         uint8_t *buf_out;
     543                 :         21 :         size_t buf_size = DPKG_BUFFER_SIZE;
     544                 :         21 :         lzma_stream s = LZMA_STREAM_INIT;
     545                 :            :         lzma_ret ret;
     546                 :            : 
     547                 :         21 :         buf_in = m_malloc(buf_size);
     548                 :         21 :         buf_out = m_malloc(buf_size);
     549                 :            : 
     550                 :         21 :         s.next_out = buf_out;
     551                 :         21 :         s.avail_out = buf_size;
     552                 :            : 
     553                 :         21 :         io->action = LZMA_RUN;
     554                 :         21 :         io->status = DPKG_STREAM_INIT;
     555                 :         21 :         io->init(io, &s);
     556                 :         21 :         io->status = (io->status & DPKG_STREAM_FILTER) | DPKG_STREAM_RUN;
     557                 :            : 
     558                 :            :         do {
     559                 :            :                 ssize_t len;
     560                 :            : 
     561   [ +  -  +  - ]:         35 :                 if (s.avail_in == 0 && io->action != LZMA_FINISH) {
     562                 :         35 :                         len = fd_read(fd_in, buf_in, buf_size);
     563         [ -  + ]:         35 :                         if (len < 0)
     564                 :          0 :                                 ohshite(_("%s: lzma read error"), io->desc);
     565         [ +  + ]:         35 :                         if (len == 0)
     566                 :         14 :                                 io->action = LZMA_FINISH;
     567                 :         35 :                         s.next_in = buf_in;
     568                 :         35 :                         s.avail_in = len;
     569                 :            :                 }
     570                 :            : 
     571                 :         35 :                 ret = io->code(io, &s);
     572                 :            : 
     573   [ +  -  +  + ]:         35 :                 if (s.avail_out == 0 || ret == LZMA_STREAM_END) {
     574                 :         21 :                         len = fd_write(fd_out, buf_out, s.next_out - buf_out);
     575         [ -  + ]:         21 :                         if (len < 0)
     576                 :          0 :                                 ohshite(_("%s: lzma write error"), io->desc);
     577                 :         21 :                         s.next_out = buf_out;
     578                 :         21 :                         s.avail_out = buf_size;
     579                 :            :                 }
     580         [ +  + ]:         35 :         } while (ret != LZMA_STREAM_END);
     581                 :            : 
     582                 :         21 :         io->done(io, &s);
     583                 :            : 
     584                 :         21 :         free(buf_in);
     585                 :         21 :         free(buf_out);
     586                 :            : 
     587         [ -  + ]:         21 :         if (close(fd_out))
     588                 :          0 :                 ohshite(_("%s: lzma close error"), io->desc);
     589                 :         21 : }
     590                 :            : 
     591                 :            : static void DPKG_ATTR_NORET
     592                 :          0 : filter_lzma_error(struct io_lzma *io, lzma_ret ret)
     593                 :            : {
     594                 :          0 :         ohshit(_("%s: lzma error: %s"), io->desc,
     595                 :            :                dpkg_lzma_strerror(ret, io->status));
     596                 :            : }
     597                 :            : 
     598                 :            : #ifdef HAVE_LZMA_MT_ENCODER
     599                 :            : static uint64_t
     600                 :         14 : filter_xz_get_memlimit(void)
     601                 :            : {
     602                 :            :         uint64_t mt_memlimit;
     603                 :            : 
     604                 :            :         /* Ask the kernel what is currently available for us. If this fails
     605                 :            :          * initialize the memory limit to half the physical RAM, or to 128 MiB
     606                 :            :          * if we cannot infer the number. */
     607         [ -  + ]:         14 :         if (meminfo_get_available(&mt_memlimit) < 0) {
     608                 :          0 :                 mt_memlimit = lzma_physmem() / 2;
     609         [ #  # ]:          0 :                 if (mt_memlimit == 0)
     610                 :          0 :                         mt_memlimit = 128 * 1024 * 1024;
     611                 :            :         }
     612                 :            :         /* Clamp the multi-threaded memory limit to half the addressable
     613                 :            :          * memory on this architecture. */
     614         [ -  + ]:         14 :         if (mt_memlimit > INTPTR_MAX)
     615                 :          0 :                 mt_memlimit = INTPTR_MAX;
     616                 :            : 
     617                 :         14 :         return mt_memlimit;
     618                 :            : }
     619                 :            : 
     620                 :            : static uint32_t
     621                 :         14 : filter_xz_get_cputhreads(struct compress_params *params)
     622                 :            : {
     623                 :            :         long threads_max;
     624                 :            : 
     625                 :         14 :         threads_max = lzma_cputhreads();
     626         [ -  + ]:         14 :         if (threads_max == 0)
     627                 :          0 :                 threads_max = 1;
     628                 :            : 
     629         [ -  + ]:         14 :         if (params->threads_max >= 0)
     630         [ #  # ]:          0 :                 return clamp(params->threads_max, 1, threads_max);
     631                 :            : 
     632                 :         14 :         return threads_max;
     633                 :            : }
     634                 :            : #endif
     635                 :            : 
     636                 :            : static void
     637                 :          6 : filter_unxz_init(struct io_lzma *io, lzma_stream *s)
     638                 :            : {
     639                 :          6 :         uint64_t memlimit = UINT64_MAX;
     640                 :            :         lzma_ret ret;
     641                 :            : 
     642                 :          6 :         io->status |= DPKG_STREAM_DECOMPRESS;
     643                 :            : 
     644                 :          6 :         ret = lzma_stream_decoder(s, memlimit, 0);
     645         [ -  + ]:          6 :         if (ret != LZMA_OK)
     646                 :          0 :                 filter_lzma_error(io, ret);
     647                 :          6 : }
     648                 :            : 
     649                 :            : static void
     650                 :         14 : filter_xz_init(struct io_lzma *io, lzma_stream *s)
     651                 :            : {
     652                 :            :         uint32_t preset;
     653                 :         14 :         lzma_check check = LZMA_CHECK_CRC64;
     654                 :            : #ifdef HAVE_LZMA_MT_ENCODER
     655                 :            :         uint64_t mt_memlimit;
     656                 :         14 :         lzma_mt mt_options = {
     657                 :            :                 .flags = 0,
     658                 :            :                 .block_size = 0,
     659                 :            :                 .timeout = 0,
     660                 :            :                 .filters = NULL,
     661                 :            :                 .check = check,
     662                 :            :         };
     663                 :            : #endif
     664                 :            :         lzma_ret ret;
     665                 :            : 
     666                 :         14 :         io->status |= DPKG_STREAM_COMPRESS;
     667                 :            : 
     668                 :         14 :         preset = io->params->level;
     669         [ -  + ]:         14 :         if (io->params->strategy == COMPRESSOR_STRATEGY_EXTREME)
     670                 :          0 :                 preset |= LZMA_PRESET_EXTREME;
     671                 :            : 
     672                 :            : #ifdef HAVE_LZMA_MT_ENCODER
     673                 :         14 :         mt_options.preset = preset;
     674                 :         14 :         mt_memlimit = filter_xz_get_memlimit();
     675                 :         14 :         mt_options.threads = filter_xz_get_cputhreads(io->params);
     676                 :            : 
     677                 :            :         /* Guess whether we have enough RAM to use the multi-threaded encoder,
     678                 :            :          * and decrease them up to single-threaded to reduce memory usage. */
     679         [ +  - ]:         14 :         for (; mt_options.threads > 1; mt_options.threads--) {
     680                 :            :                 uint64_t mt_memusage;
     681                 :            : 
     682                 :         14 :                 mt_memusage = lzma_stream_encoder_mt_memusage(&mt_options);
     683         [ +  - ]:         14 :                 if (mt_memusage < mt_memlimit)
     684                 :         14 :                         break;
     685                 :            :         }
     686                 :            : 
     687                 :         14 :         ret = lzma_stream_encoder_mt(s, &mt_options);
     688                 :            : #else
     689                 :            :         ret = lzma_easy_encoder(s, preset, check);
     690                 :            : #endif
     691                 :            : 
     692         [ -  + ]:         14 :         if (ret != LZMA_OK)
     693                 :          0 :                 filter_lzma_error(io, ret);
     694                 :         14 : }
     695                 :            : 
     696                 :            : static int
     697                 :         35 : filter_lzma_code(struct io_lzma *io, lzma_stream *s)
     698                 :            : {
     699                 :            :         lzma_ret ret;
     700                 :            : 
     701                 :         35 :         ret = lzma_code(s, io->action);
     702   [ +  +  -  + ]:         35 :         if (ret != LZMA_OK && ret != LZMA_STREAM_END)
     703                 :          0 :                 filter_lzma_error(io, ret);
     704                 :            : 
     705                 :         35 :         return ret;
     706                 :            : }
     707                 :            : 
     708                 :            : static void
     709                 :         21 : filter_lzma_done(struct io_lzma *io, lzma_stream *s)
     710                 :            : {
     711                 :         21 :         lzma_end(s);
     712                 :         21 : }
     713                 :            : 
     714                 :            : static void
     715                 :          6 : decompress_xz(struct compress_params *params, int fd_in, int fd_out,
     716                 :            :               const char *desc)
     717                 :            : {
     718                 :            :         struct io_lzma io;
     719                 :            : 
     720                 :          6 :         io.init = filter_unxz_init;
     721                 :          6 :         io.code = filter_lzma_code;
     722                 :          6 :         io.done = filter_lzma_done;
     723                 :          6 :         io.desc = desc;
     724                 :          6 :         io.params = params;
     725                 :            : 
     726                 :          6 :         filter_lzma(&io, fd_in, fd_out);
     727                 :          6 : }
     728                 :            : 
     729                 :            : static void
     730                 :         14 : compress_xz(struct compress_params *params, int fd_in, int fd_out,
     731                 :            :             const char *desc)
     732                 :            : {
     733                 :            :         struct io_lzma io;
     734                 :            : 
     735                 :         14 :         io.init = filter_xz_init;
     736                 :         14 :         io.code = filter_lzma_code;
     737                 :         14 :         io.done = filter_lzma_done;
     738                 :         14 :         io.desc = desc;
     739                 :         14 :         io.params = params;
     740                 :            : 
     741                 :         14 :         filter_lzma(&io, fd_in, fd_out);
     742                 :         14 : }
     743                 :            : #else
     744                 :            : static const char *env_xz[] = { "XZ_DEFAULTS", "XZ_OPT", NULL };
     745                 :            : 
     746                 :            : static void
     747                 :            : decompress_xz(struct compress_params *params, int fd_in, int fd_out,
     748                 :            :               const char *desc)
     749                 :            : {
     750                 :            :         struct command cmd;
     751                 :            : 
     752                 :            :         command_decompress_init(&cmd, XZ, desc);
     753                 :            : 
     754                 :            :         fd_fd_filter(&cmd, fd_in, fd_out, env_xz);
     755                 :            : 
     756                 :            :         command_destroy(&cmd);
     757                 :            : }
     758                 :            : 
     759                 :            : static void
     760                 :            : compress_xz(struct compress_params *params, int fd_in, int fd_out,
     761                 :            :             const char *desc)
     762                 :            : {
     763                 :            :         struct command cmd;
     764                 :            :         char *threads_opt = NULL;
     765                 :            : 
     766                 :            :         command_compress_init(&cmd, XZ, desc, params->level);
     767                 :            : 
     768                 :            :         if (params->strategy == COMPRESSOR_STRATEGY_EXTREME)
     769                 :            :                 command_add_arg(&cmd, "-e");
     770                 :            : 
     771                 :            :         if (params->threads_max > 0) {
     772                 :            :                 threads_opt = str_fmt("-T%d", params->threads_max);
     773                 :            :                 command_add_arg(&cmd, threads_opt);
     774                 :            :         }
     775                 :            : 
     776                 :            :         fd_fd_filter(&cmd, fd_in, fd_out, env_xz);
     777                 :            : 
     778                 :            :         command_destroy(&cmd);
     779                 :            :         free(threads_opt);
     780                 :            : }
     781                 :            : #endif
     782                 :            : 
     783                 :            : static const struct compressor compressor_xz = {
     784                 :            :         .name = "xz",
     785                 :            :         .extension = ".xz",
     786                 :            :         .default_level = 6,
     787                 :            :         .fixup_params = fixup_none_params,
     788                 :            :         .compress = compress_xz,
     789                 :            :         .decompress = decompress_xz,
     790                 :            : };
     791                 :            : 
     792                 :            : /*
     793                 :            :  * Lzma compressor.
     794                 :            :  */
     795                 :            : 
     796                 :            : #ifdef WITH_LIBLZMA
     797                 :            : static void
     798                 :          1 : filter_unlzma_init(struct io_lzma *io, lzma_stream *s)
     799                 :            : {
     800                 :          1 :         uint64_t memlimit = UINT64_MAX;
     801                 :            :         lzma_ret ret;
     802                 :            : 
     803                 :          1 :         io->status |= DPKG_STREAM_DECOMPRESS;
     804                 :            : 
     805                 :          1 :         ret = lzma_alone_decoder(s, memlimit);
     806         [ -  + ]:          1 :         if (ret != LZMA_OK)
     807                 :          0 :                 filter_lzma_error(io, ret);
     808                 :          1 : }
     809                 :            : 
     810                 :            : static void
     811                 :          0 : filter_lzma_init(struct io_lzma *io, lzma_stream *s)
     812                 :            : {
     813                 :            :         uint32_t preset;
     814                 :            :         lzma_options_lzma options;
     815                 :            :         lzma_ret ret;
     816                 :            : 
     817                 :          0 :         io->status |= DPKG_STREAM_COMPRESS;
     818                 :            : 
     819                 :          0 :         preset = io->params->level;
     820         [ #  # ]:          0 :         if (io->params->strategy == COMPRESSOR_STRATEGY_EXTREME)
     821                 :          0 :                 preset |= LZMA_PRESET_EXTREME;
     822         [ #  # ]:          0 :         if (lzma_lzma_preset(&options, preset))
     823                 :          0 :                 filter_lzma_error(io, LZMA_OPTIONS_ERROR);
     824                 :            : 
     825                 :          0 :         ret = lzma_alone_encoder(s, &options);
     826         [ #  # ]:          0 :         if (ret != LZMA_OK)
     827                 :          0 :                 filter_lzma_error(io, ret);
     828                 :          0 : }
     829                 :            : 
     830                 :            : static void
     831                 :          1 : decompress_lzma(struct compress_params *params, int fd_in, int fd_out,
     832                 :            :                 const char *desc)
     833                 :            : {
     834                 :            :         struct io_lzma io;
     835                 :            : 
     836                 :          1 :         io.init = filter_unlzma_init;
     837                 :          1 :         io.code = filter_lzma_code;
     838                 :          1 :         io.done = filter_lzma_done;
     839                 :          1 :         io.desc = desc;
     840                 :          1 :         io.params = params;
     841                 :            : 
     842                 :          1 :         filter_lzma(&io, fd_in, fd_out);
     843                 :          1 : }
     844                 :            : 
     845                 :            : static void
     846                 :          0 : compress_lzma(struct compress_params *params, int fd_in, int fd_out,
     847                 :            :               const char *desc)
     848                 :            : {
     849                 :            :         struct io_lzma io;
     850                 :            : 
     851                 :          0 :         io.init = filter_lzma_init;
     852                 :          0 :         io.code = filter_lzma_code;
     853                 :          0 :         io.done = filter_lzma_done;
     854                 :          0 :         io.desc = desc;
     855                 :          0 :         io.params = params;
     856                 :            : 
     857                 :          0 :         filter_lzma(&io, fd_in, fd_out);
     858                 :          0 : }
     859                 :            : #else
     860                 :            : static void
     861                 :            : decompress_lzma(struct compress_params *params, int fd_in, int fd_out,
     862                 :            :                 const char *desc)
     863                 :            : {
     864                 :            :         struct command cmd;
     865                 :            : 
     866                 :            :         command_decompress_init(&cmd, XZ, desc);
     867                 :            :         command_add_arg(&cmd, "--format=lzma");
     868                 :            : 
     869                 :            :         fd_fd_filter(&cmd, fd_in, fd_out, env_xz);
     870                 :            : 
     871                 :            :         command_destroy(&cmd);
     872                 :            : }
     873                 :            : 
     874                 :            : static void
     875                 :            : compress_lzma(struct compress_params *params, int fd_in, int fd_out,
     876                 :            :               const char *desc)
     877                 :            : {
     878                 :            :         struct command cmd;
     879                 :            : 
     880                 :            :         command_compress_init(&cmd, XZ, desc, params->level);
     881                 :            :         command_add_arg(&cmd, "--format=lzma");
     882                 :            : 
     883                 :            :         fd_fd_filter(&cmd, fd_in, fd_out, env_xz);
     884                 :            : 
     885                 :            :         command_destroy(&cmd);
     886                 :            : }
     887                 :            : #endif
     888                 :            : 
     889                 :            : static const struct compressor compressor_lzma = {
     890                 :            :         .name = "lzma",
     891                 :            :         .extension = ".lzma",
     892                 :            :         .default_level = 6,
     893                 :            :         .fixup_params = fixup_none_params,
     894                 :            :         .compress = compress_lzma,
     895                 :            :         .decompress = decompress_lzma,
     896                 :            : };
     897                 :            : 
     898                 :            : /*
     899                 :            :  * Generic compressor filter.
     900                 :            :  */
     901                 :            : 
     902                 :            : static const struct compressor *compressor_array[] = {
     903                 :            :         [COMPRESSOR_TYPE_NONE] = &compressor_none,
     904                 :            :         [COMPRESSOR_TYPE_GZIP] = &compressor_gzip,
     905                 :            :         [COMPRESSOR_TYPE_XZ] = &compressor_xz,
     906                 :            :         [COMPRESSOR_TYPE_BZIP2] = &compressor_bzip2,
     907                 :            :         [COMPRESSOR_TYPE_LZMA] = &compressor_lzma,
     908                 :            : };
     909                 :            : 
     910                 :            : static const struct compressor *
     911                 :        181 : compressor(enum compressor_type type)
     912                 :            : {
     913                 :        181 :         const enum compressor_type max_type = array_count(compressor_array);
     914                 :            : 
     915   [ +  -  -  + ]:        181 :         if (type < 0 || type >= max_type)
     916                 :          0 :                 internerr("compressor_type %d is out of range", type);
     917                 :            : 
     918                 :        181 :         return compressor_array[type];
     919                 :            : }
     920                 :            : 
     921                 :            : const char *
     922                 :          0 : compressor_get_name(enum compressor_type type)
     923                 :            : {
     924                 :          0 :         return compressor(type)->name;
     925                 :            : }
     926                 :            : 
     927                 :            : const char *
     928                 :         17 : compressor_get_extension(enum compressor_type type)
     929                 :            : {
     930                 :         17 :         return compressor(type)->extension;
     931                 :            : }
     932                 :            : 
     933                 :            : enum compressor_type
     934                 :          3 : compressor_find_by_name(const char *name)
     935                 :            : {
     936                 :            :         size_t i;
     937                 :            : 
     938         [ +  - ]:          4 :         for (i = 0; i < array_count(compressor_array); i++)
     939         [ +  + ]:          4 :                 if (strcmp(compressor_array[i]->name, name) == 0)
     940                 :          3 :                         return i;
     941                 :            : 
     942                 :          0 :         return COMPRESSOR_TYPE_UNKNOWN;
     943                 :            : }
     944                 :            : 
     945                 :            : enum compressor_type
     946                 :         30 : compressor_find_by_extension(const char *extension)
     947                 :            : {
     948                 :            :         size_t i;
     949                 :            : 
     950         [ +  + ]:         66 :         for (i = 0; i < array_count(compressor_array); i++)
     951         [ +  + ]:         65 :                 if (strcmp(compressor_array[i]->extension, extension) == 0)
     952                 :         29 :                         return i;
     953                 :            : 
     954                 :          1 :         return COMPRESSOR_TYPE_UNKNOWN;
     955                 :            : }
     956                 :            : 
     957                 :            : enum compressor_strategy
     958                 :          0 : compressor_get_strategy(const char *name)
     959                 :            : {
     960         [ #  # ]:          0 :         if (strcmp(name, "none") == 0)
     961                 :          0 :                 return COMPRESSOR_STRATEGY_NONE;
     962         [ #  # ]:          0 :         if (strcmp(name, "filtered") == 0)
     963                 :          0 :                 return COMPRESSOR_STRATEGY_FILTERED;
     964         [ #  # ]:          0 :         if (strcmp(name, "huffman") == 0)
     965                 :          0 :                 return COMPRESSOR_STRATEGY_HUFFMAN;
     966         [ #  # ]:          0 :         if (strcmp(name, "rle") == 0)
     967                 :          0 :                 return COMPRESSOR_STRATEGY_RLE;
     968         [ #  # ]:          0 :         if (strcmp(name, "fixed") == 0)
     969                 :          0 :                 return COMPRESSOR_STRATEGY_FIXED;
     970         [ #  # ]:          0 :         if (strcmp(name, "extreme") == 0)
     971                 :          0 :                 return COMPRESSOR_STRATEGY_EXTREME;
     972                 :            : 
     973                 :          0 :         return COMPRESSOR_STRATEGY_UNKNOWN;
     974                 :            : }
     975                 :            : 
     976                 :            : static void
     977                 :         59 : compressor_fixup_params(struct compress_params *params)
     978                 :            : {
     979                 :         59 :         compressor(params->type)->fixup_params(params);
     980                 :            : 
     981         [ +  - ]:         59 :         if (params->level < 0)
     982                 :         59 :                 params->level = compressor(params->type)->default_level;
     983                 :         59 : }
     984                 :            : 
     985                 :            : bool
     986                 :         59 : compressor_check_params(struct compress_params *params, struct dpkg_error *err)
     987                 :            : {
     988                 :         59 :         compressor_fixup_params(params);
     989                 :            : 
     990         [ +  - ]:         59 :         if (params->strategy == COMPRESSOR_STRATEGY_NONE)
     991                 :         59 :                 return true;
     992                 :            : 
     993         [ #  # ]:          0 :         if (params->type == COMPRESSOR_TYPE_GZIP &&
     994         [ #  # ]:          0 :             (params->strategy == COMPRESSOR_STRATEGY_FILTERED ||
     995         [ #  # ]:          0 :              params->strategy == COMPRESSOR_STRATEGY_HUFFMAN ||
     996         [ #  # ]:          0 :              params->strategy == COMPRESSOR_STRATEGY_RLE ||
     997         [ #  # ]:          0 :              params->strategy == COMPRESSOR_STRATEGY_FIXED))
     998                 :          0 :                 return true;
     999                 :            : 
    1000         [ #  # ]:          0 :         if (params->type == COMPRESSOR_TYPE_XZ &&
    1001         [ #  # ]:          0 :             params->strategy == COMPRESSOR_STRATEGY_EXTREME)
    1002                 :          0 :                 return true;
    1003                 :            : 
    1004                 :          0 :         dpkg_put_error(err, _("unknown compression strategy"));
    1005                 :          0 :         return false;
    1006                 :            : }
    1007                 :            : 
    1008                 :            : void
    1009                 :         26 : decompress_filter(struct compress_params *params, int fd_in, int fd_out,
    1010                 :            :                   const char *desc_fmt, ...)
    1011                 :            : {
    1012                 :            :         va_list args;
    1013                 :         26 :         struct varbuf desc = VARBUF_INIT;
    1014                 :            : 
    1015                 :         26 :         va_start(args, desc_fmt);
    1016                 :         26 :         varbuf_vprintf(&desc, desc_fmt, args);
    1017                 :         26 :         va_end(args);
    1018                 :            : 
    1019                 :         26 :         compressor(params->type)->decompress(params, fd_in, fd_out, desc.buf);
    1020                 :            : 
    1021                 :         26 :         varbuf_destroy(&desc);
    1022                 :         26 : }
    1023                 :            : 
    1024                 :            : void
    1025                 :         20 : compress_filter(struct compress_params *params, int fd_in, int fd_out,
    1026                 :            :                 const char *desc_fmt, ...)
    1027                 :            : {
    1028                 :            :         va_list args;
    1029                 :         20 :         struct varbuf desc = VARBUF_INIT;
    1030                 :            : 
    1031                 :         20 :         va_start(args, desc_fmt);
    1032                 :         20 :         varbuf_vprintf(&desc, desc_fmt, args);
    1033                 :         20 :         va_end(args);
    1034                 :            : 
    1035                 :         20 :         compressor(params->type)->compress(params, fd_in, fd_out, desc.buf);
    1036                 :            : 
    1037                 :         20 :         varbuf_destroy(&desc);
    1038                 :         20 : }

Generated by: LCOV version 1.16