LCOV - code coverage report
Current view: top level - common - compr.c (source / functions) Hit Total Coverage
Test: a simple test Lines: 33 98 33.7 %
Date: 2024-06-05 20:10:43 Functions: 4 7 57.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2008 Nokia Corporation.
       3             :  * Copyright (C) 2008 University of Szeged, Hungary
       4             :  *
       5             :  * This program is free software; you can redistribute it and/or modify it
       6             :  * under the terms of the GNU General Public License version 2 as published by
       7             :  * the Free Software Foundation.
       8             :  *
       9             :  * This program is distributed in the hope that it will be useful, but WITHOUT
      10             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      11             :  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      12             :  * more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License along with
      15             :  * this program; if not, write to the Free Software Foundation, Inc., 51
      16             :  * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      17             :  *
      18             :  * Authors: Artem Bityutskiy
      19             :  *          Adrian Hunter
      20             :  *          Zoltan Sogor
      21             :  */
      22             : 
      23             : #include <stdlib.h>
      24             : #include <stdio.h>
      25             : #include <stdint.h>
      26             : #include <string.h>
      27             : #ifdef WITH_LZO
      28             : #include <lzo/lzo1x.h>
      29             : #endif
      30             : #include <linux/types.h>
      31             : #ifdef WITH_ZSTD
      32             : #include <zstd.h>
      33             : #endif
      34             : 
      35             : #ifdef WITH_ZLIB
      36             : #define crc32 __zlib_crc32
      37             : #include <zlib.h>
      38             : #undef crc32
      39             : #endif
      40             : 
      41             : #include "compr.h"
      42             : #include "ubifs.h"
      43             : 
      44             : static void *lzo_mem;
      45             : static unsigned long long errcnt = 0;
      46             : #ifdef WITH_LZO
      47             : extern struct ubifs_info info_;
      48             : static struct ubifs_info *c = &info_;
      49             : #endif
      50             : 
      51             : #ifdef WITH_ZLIB
      52             : #define DEFLATE_DEF_LEVEL     Z_DEFAULT_COMPRESSION
      53             : #define DEFLATE_DEF_WINBITS   11
      54             : #define DEFLATE_DEF_MEMLEVEL  8
      55             : 
      56           0 : static int zlib_deflate(void *in_buf, size_t in_len, void *out_buf,
      57             :                         size_t *out_len)
      58             : {
      59             :         z_stream strm;
      60             : 
      61           0 :         strm.zalloc = NULL;
      62           0 :         strm.zfree = NULL;
      63             : 
      64             :         /*
      65             :          * Match exactly the zlib parameters used by the Linux kernel crypto
      66             :          * API.
      67             :          */
      68           0 :         if (deflateInit2(&strm, DEFLATE_DEF_LEVEL, Z_DEFLATED,
      69             :                          -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
      70             :                          Z_DEFAULT_STRATEGY)) {
      71           0 :                 errcnt += 1;
      72           0 :                 return -1;
      73             :         }
      74             : 
      75           0 :         strm.next_in = in_buf;
      76           0 :         strm.avail_in = in_len;
      77           0 :         strm.total_in = 0;
      78             : 
      79           0 :         strm.next_out = out_buf;
      80           0 :         strm.avail_out = *out_len;
      81           0 :         strm.total_out = 0;
      82             : 
      83           0 :         if (deflate(&strm, Z_FINISH) != Z_STREAM_END) {
      84           0 :                 deflateEnd(&strm);
      85           0 :                 errcnt += 1;
      86           0 :                 return -1;
      87             :         }
      88             : 
      89           0 :         if (deflateEnd(&strm) != Z_OK) {
      90           0 :                 errcnt += 1;
      91           0 :                 return -1;
      92             :         }
      93             : 
      94           0 :         *out_len = strm.total_out;
      95             : 
      96           0 :         return 0;
      97             : }
      98             : #endif
      99             : 
     100             : #ifdef WITH_LZO
     101      592320 : static int lzo_compress(void *in_buf, size_t in_len, void *out_buf,
     102             :                         size_t *out_len)
     103             : {
     104             :         lzo_uint len;
     105             :         int ret;
     106             : 
     107      592320 :         len = *out_len;
     108      592320 :         ret = lzo1x_999_compress(in_buf, in_len, out_buf, &len, lzo_mem);
     109      592320 :         *out_len = len;
     110             : 
     111      592320 :         if (ret != LZO_E_OK) {
     112           0 :                 errcnt += 1;
     113           0 :                 return -1;
     114             :         }
     115             : 
     116             :         return 0;
     117             : }
     118             : #endif
     119             : 
     120             : #ifdef WITH_ZSTD
     121             : static ZSTD_CCtx *zctx;
     122             : 
     123           0 : static int zstd_compress(void *in_buf, size_t in_len, void *out_buf,
     124             :                          size_t *out_len)
     125             : {
     126             :         size_t ret;
     127             : 
     128           0 :         ret = ZSTD_compressCCtx(zctx, out_buf, *out_len, in_buf, in_len, 0);
     129           0 :         if (ZSTD_isError(ret)) {
     130           0 :                 errcnt += 1;
     131           0 :                 return -1;
     132             :         }
     133           0 :         *out_len = ret;
     134           0 :         return 0;
     135             : }
     136             : #endif
     137             : 
     138             : static int no_compress(void *in_buf, size_t in_len, void *out_buf,
     139             :                        size_t *out_len)
     140             : {
     141      592960 :         memcpy(out_buf, in_buf, in_len);
     142      592960 :         *out_len = in_len;
     143             :         return 0;
     144             : }
     145             : 
     146             : static char *zlib_buf;
     147             : 
     148             : #if defined(WITH_LZO) && defined(WITH_ZLIB)
     149           0 : static int favor_lzo_compress(void *in_buf, size_t in_len, void *out_buf,
     150             :                                size_t *out_len, int *type)
     151             : {
     152             :         int lzo_ret, zlib_ret;
     153             :         size_t lzo_len, zlib_len;
     154             : 
     155           0 :         lzo_len = zlib_len = *out_len;
     156           0 :         lzo_ret = lzo_compress(in_buf, in_len, out_buf, &lzo_len);
     157           0 :         zlib_ret = zlib_deflate(in_buf, in_len, zlib_buf, &zlib_len);
     158             : 
     159           0 :         if (lzo_ret && zlib_ret)
     160             :                 /* Both compressors failed */
     161             :                 return -1;
     162             : 
     163           0 :         if (!lzo_ret && !zlib_ret) {
     164             :                 double percent;
     165             : 
     166             :                 /* Both compressors succeeded */
     167           0 :                 if (lzo_len <= zlib_len )
     168             :                         goto select_lzo;
     169             : 
     170           0 :                 percent = (double)zlib_len / (double)lzo_len;
     171           0 :                 percent *= 100;
     172           0 :                 if (percent > 100 - c->favor_percent)
     173             :                         goto select_lzo;
     174             :                 goto select_zlib;
     175             :         }
     176             : 
     177           0 :         if (lzo_ret)
     178             :                 /* Only zlib compressor succeeded */
     179             :                 goto select_zlib;
     180             : 
     181             :         /* Only LZO compressor succeeded */
     182             : 
     183           0 : select_lzo:
     184           0 :         *out_len = lzo_len;
     185           0 :         *type = UBIFS_COMPR_LZO;
     186           0 :         return 0;
     187             : 
     188           0 : select_zlib:
     189           0 :         *out_len = zlib_len;
     190           0 :         *type = UBIFS_COMPR_ZLIB;
     191           0 :         memcpy(out_buf, zlib_buf, zlib_len);
     192           0 :         return 0;
     193             : }
     194             : #endif
     195             : 
     196     1185280 : int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len,
     197             :                   int type)
     198             : {
     199             :         int ret;
     200             : 
     201     1185280 :         if (in_len < UBIFS_MIN_COMPR_LEN) {
     202         640 :                 no_compress(in_buf, in_len, out_buf, out_len);
     203         640 :                 return UBIFS_COMPR_NONE;
     204             :         }
     205             : 
     206             : #if defined(WITH_LZO) && defined(WITH_ZLIB)
     207     1184640 :         if (c->favor_lzo)
     208           0 :                 ret = favor_lzo_compress(in_buf, in_len, out_buf, out_len, &type);
     209             :         else {
     210             : #else
     211             :         {
     212             : #endif
     213     1184640 :                 switch (type) {
     214             : #ifdef WITH_LZO
     215      592320 :                 case UBIFS_COMPR_LZO:
     216      592320 :                         ret = lzo_compress(in_buf, in_len, out_buf, out_len);
     217      592320 :                         break;
     218             : #endif
     219             : #ifdef WITH_ZLIB
     220           0 :                 case UBIFS_COMPR_ZLIB:
     221           0 :                         ret = zlib_deflate(in_buf, in_len, out_buf, out_len);
     222           0 :                         break;
     223             : #endif
     224             : #ifdef WITH_ZSTD
     225           0 :                 case UBIFS_COMPR_ZSTD:
     226           0 :                         ret = zstd_compress(in_buf, in_len, out_buf, out_len);
     227           0 :                         break;
     228             : #endif
     229             :                 case UBIFS_COMPR_NONE:
     230             :                         ret = 1;
     231             :                         break;
     232           0 :                 default:
     233           0 :                         errcnt += 1;
     234           0 :                         ret = 1;
     235             :                         break;
     236             :                 }
     237             :         }
     238      592320 :         if (ret || *out_len >= in_len) {
     239      592320 :                 no_compress(in_buf, in_len, out_buf, out_len);
     240      592320 :                 return UBIFS_COMPR_NONE;
     241             :         }
     242      592320 :         return type;
     243             : }
     244             : 
     245         640 : int init_compression(void)
     246             : {
     247             : #ifndef WITH_LZO
     248             :         lzo_mem = NULL;
     249             : #else
     250         640 :         lzo_mem = malloc(LZO1X_999_MEM_COMPRESS);
     251         640 :         if (!lzo_mem)
     252             :                 return -1;
     253             : #endif
     254             : 
     255             : #ifndef WITH_ZLIB
     256             :         zlib_buf = NULL;
     257             : #else
     258         640 :         zlib_buf = malloc(UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR);
     259         640 :         if (!zlib_buf)
     260             :                 goto err;
     261             : #endif
     262             : 
     263             : #ifdef WITH_ZSTD
     264         640 :         zctx = ZSTD_createCCtx();
     265         640 :         if (!zctx)
     266             :                 goto err;
     267             : #endif
     268             : 
     269             :         return 0;
     270           0 : err:
     271           0 :         free(zlib_buf);
     272           0 :         free(lzo_mem);
     273           0 :         return -1;
     274             : }
     275             : 
     276         640 : void destroy_compression(void)
     277             : {
     278         640 :         free(zlib_buf);
     279         640 :         free(lzo_mem);
     280             : #ifdef WITH_ZSTD
     281         640 :         ZSTD_freeCCtx(zctx);
     282             : #endif
     283         640 :         if (errcnt)
     284           0 :                 fprintf(stderr, "%llu compression errors occurred\n", errcnt);
     285         640 : }

Generated by: LCOV version 1.13