LCOV - code coverage report
Current view: top level - import - import-compress.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 0 257 0.0 %
Date: 2019-08-22 15:41:25 Functions: 0 9 0.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include "import-compress.h"
       4             : #include "string-table.h"
       5             : #include "util.h"
       6             : 
       7           0 : void import_compress_free(ImportCompress *c) {
       8           0 :         assert(c);
       9             : 
      10           0 :         if (c->type == IMPORT_COMPRESS_XZ)
      11           0 :                 lzma_end(&c->xz);
      12           0 :         else if (c->type == IMPORT_COMPRESS_GZIP) {
      13           0 :                 if (c->encoding)
      14           0 :                         deflateEnd(&c->gzip);
      15             :                 else
      16           0 :                         inflateEnd(&c->gzip);
      17             : #if HAVE_BZIP2
      18           0 :         } else if (c->type == IMPORT_COMPRESS_BZIP2) {
      19           0 :                 if (c->encoding)
      20           0 :                         BZ2_bzCompressEnd(&c->bzip2);
      21             :                 else
      22           0 :                         BZ2_bzDecompressEnd(&c->bzip2);
      23             : #endif
      24             :         }
      25             : 
      26           0 :         c->type = IMPORT_COMPRESS_UNKNOWN;
      27           0 : }
      28             : 
      29           0 : int import_uncompress_detect(ImportCompress *c, const void *data, size_t size) {
      30             :         static const uint8_t xz_signature[] = {
      31             :                 0xfd, '7', 'z', 'X', 'Z', 0x00
      32             :         };
      33             :         static const uint8_t gzip_signature[] = {
      34             :                 0x1f, 0x8b
      35             :         };
      36             :         static const uint8_t bzip2_signature[] = {
      37             :                 'B', 'Z', 'h'
      38             :         };
      39             : 
      40             :         int r;
      41             : 
      42           0 :         assert(c);
      43             : 
      44           0 :         if (c->type != IMPORT_COMPRESS_UNKNOWN)
      45           0 :                 return 1;
      46             : 
      47           0 :         if (size < MAX3(sizeof(xz_signature),
      48             :                         sizeof(gzip_signature),
      49             :                         sizeof(bzip2_signature)))
      50           0 :                 return 0;
      51             : 
      52           0 :         assert(data);
      53             : 
      54           0 :         if (memcmp(data, xz_signature, sizeof(xz_signature)) == 0) {
      55             :                 lzma_ret xzr;
      56             : 
      57           0 :                 xzr = lzma_stream_decoder(&c->xz, UINT64_MAX, LZMA_TELL_UNSUPPORTED_CHECK | LZMA_CONCATENATED);
      58           0 :                 if (xzr != LZMA_OK)
      59           0 :                         return -EIO;
      60             : 
      61           0 :                 c->type = IMPORT_COMPRESS_XZ;
      62             : 
      63           0 :         } else if (memcmp(data, gzip_signature, sizeof(gzip_signature)) == 0) {
      64           0 :                 r = inflateInit2(&c->gzip, 15+16);
      65           0 :                 if (r != Z_OK)
      66           0 :                         return -EIO;
      67             : 
      68           0 :                 c->type = IMPORT_COMPRESS_GZIP;
      69             : 
      70             : #if HAVE_BZIP2
      71           0 :         } else if (memcmp(data, bzip2_signature, sizeof(bzip2_signature)) == 0) {
      72           0 :                 r = BZ2_bzDecompressInit(&c->bzip2, 0, 0);
      73           0 :                 if (r != BZ_OK)
      74           0 :                         return -EIO;
      75             : 
      76           0 :                 c->type = IMPORT_COMPRESS_BZIP2;
      77             : #endif
      78             :         } else
      79           0 :                 c->type = IMPORT_COMPRESS_UNCOMPRESSED;
      80             : 
      81           0 :         c->encoding = false;
      82             : 
      83           0 :         return 1;
      84             : }
      85             : 
      86           0 : int import_uncompress(ImportCompress *c, const void *data, size_t size, ImportCompressCallback callback, void *userdata) {
      87             :         int r;
      88             : 
      89           0 :         assert(c);
      90           0 :         assert(callback);
      91             : 
      92           0 :         r = import_uncompress_detect(c, data, size);
      93           0 :         if (r <= 0)
      94           0 :                 return r;
      95             : 
      96           0 :         if (c->encoding)
      97           0 :                 return -EINVAL;
      98             : 
      99           0 :         if (size <= 0)
     100           0 :                 return 1;
     101             : 
     102           0 :         assert(data);
     103             : 
     104           0 :         switch (c->type) {
     105             : 
     106           0 :         case IMPORT_COMPRESS_UNCOMPRESSED:
     107           0 :                 r = callback(data, size, userdata);
     108           0 :                 if (r < 0)
     109           0 :                         return r;
     110             : 
     111           0 :                 break;
     112             : 
     113           0 :         case IMPORT_COMPRESS_XZ:
     114           0 :                 c->xz.next_in = data;
     115           0 :                 c->xz.avail_in = size;
     116             : 
     117           0 :                 while (c->xz.avail_in > 0) {
     118             :                         uint8_t buffer[16 * 1024];
     119             :                         lzma_ret lzr;
     120             : 
     121           0 :                         c->xz.next_out = buffer;
     122           0 :                         c->xz.avail_out = sizeof(buffer);
     123             : 
     124           0 :                         lzr = lzma_code(&c->xz, LZMA_RUN);
     125           0 :                         if (!IN_SET(lzr, LZMA_OK, LZMA_STREAM_END))
     126           0 :                                 return -EIO;
     127             : 
     128           0 :                         r = callback(buffer, sizeof(buffer) - c->xz.avail_out, userdata);
     129           0 :                         if (r < 0)
     130           0 :                                 return r;
     131             :                 }
     132             : 
     133           0 :                 break;
     134             : 
     135           0 :         case IMPORT_COMPRESS_GZIP:
     136           0 :                 c->gzip.next_in = (void*) data;
     137           0 :                 c->gzip.avail_in = size;
     138             : 
     139           0 :                 while (c->gzip.avail_in > 0) {
     140             :                         uint8_t buffer[16 * 1024];
     141             : 
     142           0 :                         c->gzip.next_out = buffer;
     143           0 :                         c->gzip.avail_out = sizeof(buffer);
     144             : 
     145           0 :                         r = inflate(&c->gzip, Z_NO_FLUSH);
     146           0 :                         if (!IN_SET(r, Z_OK, Z_STREAM_END))
     147           0 :                                 return -EIO;
     148             : 
     149           0 :                         r = callback(buffer, sizeof(buffer) - c->gzip.avail_out, userdata);
     150           0 :                         if (r < 0)
     151           0 :                                 return r;
     152             :                 }
     153             : 
     154           0 :                 break;
     155             : 
     156             : #if HAVE_BZIP2
     157           0 :         case IMPORT_COMPRESS_BZIP2:
     158           0 :                 c->bzip2.next_in = (void*) data;
     159           0 :                 c->bzip2.avail_in = size;
     160             : 
     161           0 :                 while (c->bzip2.avail_in > 0) {
     162             :                         uint8_t buffer[16 * 1024];
     163             : 
     164           0 :                         c->bzip2.next_out = (char*) buffer;
     165           0 :                         c->bzip2.avail_out = sizeof(buffer);
     166             : 
     167           0 :                         r = BZ2_bzDecompress(&c->bzip2);
     168           0 :                         if (!IN_SET(r, BZ_OK, BZ_STREAM_END))
     169           0 :                                 return -EIO;
     170             : 
     171           0 :                         r = callback(buffer, sizeof(buffer) - c->bzip2.avail_out, userdata);
     172           0 :                         if (r < 0)
     173           0 :                                 return r;
     174             :                 }
     175             : 
     176           0 :                 break;
     177             : #endif
     178             : 
     179           0 :         default:
     180           0 :                 assert_not_reached("Unknown compression");
     181             :         }
     182             : 
     183           0 :         return 1;
     184             : }
     185             : 
     186           0 : int import_compress_init(ImportCompress *c, ImportCompressType t) {
     187             :         int r;
     188             : 
     189           0 :         assert(c);
     190             : 
     191           0 :         switch (t) {
     192             : 
     193           0 :         case IMPORT_COMPRESS_XZ: {
     194             :                 lzma_ret xzr;
     195             : 
     196           0 :                 xzr = lzma_easy_encoder(&c->xz, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC64);
     197           0 :                 if (xzr != LZMA_OK)
     198           0 :                         return -EIO;
     199             : 
     200           0 :                 c->type = IMPORT_COMPRESS_XZ;
     201           0 :                 break;
     202             :         }
     203             : 
     204           0 :         case IMPORT_COMPRESS_GZIP:
     205           0 :                 r = deflateInit2(&c->gzip, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
     206           0 :                 if (r != Z_OK)
     207           0 :                         return -EIO;
     208             : 
     209           0 :                 c->type = IMPORT_COMPRESS_GZIP;
     210           0 :                 break;
     211             : 
     212             : #if HAVE_BZIP2
     213           0 :         case IMPORT_COMPRESS_BZIP2:
     214           0 :                 r = BZ2_bzCompressInit(&c->bzip2, 9, 0, 0);
     215           0 :                 if (r != BZ_OK)
     216           0 :                         return -EIO;
     217             : 
     218           0 :                 c->type = IMPORT_COMPRESS_BZIP2;
     219           0 :                 break;
     220             : #endif
     221             : 
     222           0 :         case IMPORT_COMPRESS_UNCOMPRESSED:
     223           0 :                 c->type = IMPORT_COMPRESS_UNCOMPRESSED;
     224           0 :                 break;
     225             : 
     226           0 :         default:
     227           0 :                 return -EOPNOTSUPP;
     228             :         }
     229             : 
     230           0 :         c->encoding = true;
     231           0 :         return 0;
     232             : }
     233             : 
     234           0 : static int enlarge_buffer(void **buffer, size_t *buffer_size, size_t *buffer_allocated) {
     235             :         size_t l;
     236             :         void *p;
     237             : 
     238           0 :         if (*buffer_allocated > *buffer_size)
     239           0 :                 return 0;
     240             : 
     241           0 :         l = MAX(16*1024U, (*buffer_size * 2));
     242           0 :         p = realloc(*buffer, l);
     243           0 :         if (!p)
     244           0 :                 return -ENOMEM;
     245             : 
     246           0 :         *buffer = p;
     247           0 :         *buffer_allocated = l;
     248             : 
     249           0 :         return 1;
     250             : }
     251             : 
     252           0 : int import_compress(ImportCompress *c, const void *data, size_t size, void **buffer, size_t *buffer_size, size_t *buffer_allocated) {
     253             :         int r;
     254             : 
     255           0 :         assert(c);
     256           0 :         assert(buffer);
     257           0 :         assert(buffer_size);
     258           0 :         assert(buffer_allocated);
     259             : 
     260           0 :         if (!c->encoding)
     261           0 :                 return -EINVAL;
     262             : 
     263           0 :         if (size <= 0)
     264           0 :                 return 0;
     265             : 
     266           0 :         assert(data);
     267             : 
     268           0 :         *buffer_size = 0;
     269             : 
     270           0 :         switch (c->type) {
     271             : 
     272           0 :         case IMPORT_COMPRESS_XZ:
     273             : 
     274           0 :                 c->xz.next_in = data;
     275           0 :                 c->xz.avail_in = size;
     276             : 
     277           0 :                 while (c->xz.avail_in > 0) {
     278             :                         lzma_ret lzr;
     279             : 
     280           0 :                         r = enlarge_buffer(buffer, buffer_size, buffer_allocated);
     281           0 :                         if (r < 0)
     282           0 :                                 return r;
     283             : 
     284           0 :                         c->xz.next_out = (uint8_t*) *buffer + *buffer_size;
     285           0 :                         c->xz.avail_out = *buffer_allocated - *buffer_size;
     286             : 
     287           0 :                         lzr = lzma_code(&c->xz, LZMA_RUN);
     288           0 :                         if (lzr != LZMA_OK)
     289           0 :                                 return -EIO;
     290             : 
     291           0 :                         *buffer_size += (*buffer_allocated - *buffer_size) - c->xz.avail_out;
     292             :                 }
     293             : 
     294           0 :                 break;
     295             : 
     296           0 :         case IMPORT_COMPRESS_GZIP:
     297             : 
     298           0 :                 c->gzip.next_in = (void*) data;
     299           0 :                 c->gzip.avail_in = size;
     300             : 
     301           0 :                 while (c->gzip.avail_in > 0) {
     302           0 :                         r = enlarge_buffer(buffer, buffer_size, buffer_allocated);
     303           0 :                         if (r < 0)
     304           0 :                                 return r;
     305             : 
     306           0 :                         c->gzip.next_out = (uint8_t*) *buffer + *buffer_size;
     307           0 :                         c->gzip.avail_out = *buffer_allocated - *buffer_size;
     308             : 
     309           0 :                         r = deflate(&c->gzip, Z_NO_FLUSH);
     310           0 :                         if (r != Z_OK)
     311           0 :                                 return -EIO;
     312             : 
     313           0 :                         *buffer_size += (*buffer_allocated - *buffer_size) - c->gzip.avail_out;
     314             :                 }
     315             : 
     316           0 :                 break;
     317             : 
     318             : #if HAVE_BZIP2
     319           0 :         case IMPORT_COMPRESS_BZIP2:
     320             : 
     321           0 :                 c->bzip2.next_in = (void*) data;
     322           0 :                 c->bzip2.avail_in = size;
     323             : 
     324           0 :                 while (c->bzip2.avail_in > 0) {
     325           0 :                         r = enlarge_buffer(buffer, buffer_size, buffer_allocated);
     326           0 :                         if (r < 0)
     327           0 :                                 return r;
     328             : 
     329           0 :                         c->bzip2.next_out = (void*) ((uint8_t*) *buffer + *buffer_size);
     330           0 :                         c->bzip2.avail_out = *buffer_allocated - *buffer_size;
     331             : 
     332           0 :                         r = BZ2_bzCompress(&c->bzip2, BZ_RUN);
     333           0 :                         if (r != BZ_RUN_OK)
     334           0 :                                 return -EIO;
     335             : 
     336           0 :                         *buffer_size += (*buffer_allocated - *buffer_size) - c->bzip2.avail_out;
     337             :                 }
     338             : 
     339           0 :                 break;
     340             : #endif
     341             : 
     342           0 :         case IMPORT_COMPRESS_UNCOMPRESSED:
     343             : 
     344           0 :                 if (*buffer_allocated < size) {
     345             :                         void *p;
     346             : 
     347           0 :                         p = realloc(*buffer, size);
     348           0 :                         if (!p)
     349           0 :                                 return -ENOMEM;
     350             : 
     351           0 :                         *buffer = p;
     352           0 :                         *buffer_allocated = size;
     353             :                 }
     354             : 
     355           0 :                 memcpy(*buffer, data, size);
     356           0 :                 *buffer_size = size;
     357           0 :                 break;
     358             : 
     359           0 :         default:
     360           0 :                 return -EOPNOTSUPP;
     361             :         }
     362             : 
     363           0 :         return 0;
     364             : }
     365             : 
     366           0 : int import_compress_finish(ImportCompress *c, void **buffer, size_t *buffer_size, size_t *buffer_allocated) {
     367             :         int r;
     368             : 
     369           0 :         assert(c);
     370           0 :         assert(buffer);
     371           0 :         assert(buffer_size);
     372           0 :         assert(buffer_allocated);
     373             : 
     374           0 :         if (!c->encoding)
     375           0 :                 return -EINVAL;
     376             : 
     377           0 :         *buffer_size = 0;
     378             : 
     379           0 :         switch (c->type) {
     380             : 
     381           0 :         case IMPORT_COMPRESS_XZ: {
     382             :                 lzma_ret lzr;
     383             : 
     384           0 :                 c->xz.avail_in = 0;
     385             : 
     386             :                 do {
     387           0 :                         r = enlarge_buffer(buffer, buffer_size, buffer_allocated);
     388           0 :                         if (r < 0)
     389           0 :                                 return r;
     390             : 
     391           0 :                         c->xz.next_out = (uint8_t*) *buffer + *buffer_size;
     392           0 :                         c->xz.avail_out = *buffer_allocated - *buffer_size;
     393             : 
     394           0 :                         lzr = lzma_code(&c->xz, LZMA_FINISH);
     395           0 :                         if (!IN_SET(lzr, LZMA_OK, LZMA_STREAM_END))
     396           0 :                                 return -EIO;
     397             : 
     398           0 :                         *buffer_size += (*buffer_allocated - *buffer_size) - c->xz.avail_out;
     399           0 :                 } while (lzr != LZMA_STREAM_END);
     400             : 
     401           0 :                 break;
     402             :         }
     403             : 
     404           0 :         case IMPORT_COMPRESS_GZIP:
     405           0 :                 c->gzip.avail_in = 0;
     406             : 
     407             :                 do {
     408           0 :                         r = enlarge_buffer(buffer, buffer_size, buffer_allocated);
     409           0 :                         if (r < 0)
     410           0 :                                 return r;
     411             : 
     412           0 :                         c->gzip.next_out = (uint8_t*) *buffer + *buffer_size;
     413           0 :                         c->gzip.avail_out = *buffer_allocated - *buffer_size;
     414             : 
     415           0 :                         r = deflate(&c->gzip, Z_FINISH);
     416           0 :                         if (!IN_SET(r, Z_OK, Z_STREAM_END))
     417           0 :                                 return -EIO;
     418             : 
     419           0 :                         *buffer_size += (*buffer_allocated - *buffer_size) - c->gzip.avail_out;
     420           0 :                 } while (r != Z_STREAM_END);
     421             : 
     422           0 :                 break;
     423             : 
     424             : #if HAVE_BZIP2
     425           0 :         case IMPORT_COMPRESS_BZIP2:
     426           0 :                 c->bzip2.avail_in = 0;
     427             : 
     428             :                 do {
     429           0 :                         r = enlarge_buffer(buffer, buffer_size, buffer_allocated);
     430           0 :                         if (r < 0)
     431           0 :                                 return r;
     432             : 
     433           0 :                         c->bzip2.next_out = (void*) ((uint8_t*) *buffer + *buffer_size);
     434           0 :                         c->bzip2.avail_out = *buffer_allocated - *buffer_size;
     435             : 
     436           0 :                         r = BZ2_bzCompress(&c->bzip2, BZ_FINISH);
     437           0 :                         if (!IN_SET(r, BZ_FINISH_OK, BZ_STREAM_END))
     438           0 :                                 return -EIO;
     439             : 
     440           0 :                         *buffer_size += (*buffer_allocated - *buffer_size) - c->bzip2.avail_out;
     441           0 :                 } while (r != BZ_STREAM_END);
     442             : 
     443           0 :                 break;
     444             : #endif
     445             : 
     446           0 :         case IMPORT_COMPRESS_UNCOMPRESSED:
     447           0 :                 break;
     448             : 
     449           0 :         default:
     450           0 :                 return -EOPNOTSUPP;
     451             :         }
     452             : 
     453           0 :         return 0;
     454             : }
     455             : 
     456             : static const char* const import_compress_type_table[_IMPORT_COMPRESS_TYPE_MAX] = {
     457             :         [IMPORT_COMPRESS_UNKNOWN] = "unknown",
     458             :         [IMPORT_COMPRESS_UNCOMPRESSED] = "uncompressed",
     459             :         [IMPORT_COMPRESS_XZ] = "xz",
     460             :         [IMPORT_COMPRESS_GZIP] = "gzip",
     461             : #if HAVE_BZIP2
     462             :         [IMPORT_COMPRESS_BZIP2] = "bzip2",
     463             : #endif
     464             : };
     465             : 
     466           0 : DEFINE_STRING_TABLE_LOOKUP(import_compress_type, ImportCompressType);

Generated by: LCOV version 1.14