LCOV - code coverage report
Current view: top level - common/stream - gz_stream.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 71 112 63.4 %
Date: 2021-10-13 02:24:04 Functions: 9 15 60.0 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : /* streams working on a lzma/xz-compressed disk file */
      10             : 
      11             : #include "monetdb_config.h"
      12             : #include "stream.h"
      13             : #include "stream_internal.h"
      14             : #include "pump.h"
      15             : 
      16             : 
      17             : #ifdef HAVE_LIBZ
      18             : 
      19             : struct inner_state {
      20             :         z_stream strm;
      21             :         int (*indeflate)(z_streamp strm, int flush);
      22             :         int (*indeflateEnd)(z_streamp strm);
      23             :         void (*reset)(inner_state_t *inner_state);
      24             :         Bytef buf[64*1024];
      25             :         bool prev_was_stream_end;
      26             : };
      27             : 
      28             : static pump_buffer
      29        3114 : get_src_win(inner_state_t *inner_state)
      30             : {
      31        3114 :         return (pump_buffer) {
      32        3118 :                 .start = (void*) inner_state->strm.next_in,
      33        3118 :                 .count = inner_state->strm.avail_in,
      34             :         };
      35             : }
      36             : 
      37             : static void
      38         751 : set_src_win(inner_state_t *inner_state, pump_buffer buf)
      39             : {
      40         751 :         assert(buf.count < UINT_MAX);
      41         751 :         inner_state->strm.next_in = (Bytef*)buf.start;
      42         751 :         inner_state->strm.avail_in = (uInt)buf.count;
      43         751 : }
      44             : 
      45             : static pump_buffer
      46        2152 : get_dst_win(inner_state_t *inner_state)
      47             : {
      48        2152 :         return (pump_buffer) {
      49        2156 :                 .start = (char*)inner_state->strm.next_out,
      50        2156 :                 .count = inner_state->strm.avail_out,
      51             :         };
      52             : }
      53             : 
      54             : static void
      55         138 : set_dst_win(inner_state_t *inner_state, pump_buffer buf)
      56             : {
      57         138 :         assert(buf.count < UINT_MAX);
      58         138 :         inner_state->strm.next_out = (Bytef*)buf.start;
      59         138 :         inner_state->strm.avail_out = (uInt)buf.count;
      60         138 : }
      61             : 
      62             : static pump_buffer
      63         840 : get_buffer(inner_state_t *inner_state)
      64             : {
      65         840 :         return (pump_buffer) {
      66         840 :                 .start = (char*)inner_state->buf,
      67             :                 .count = sizeof(inner_state->buf),
      68             :         };
      69             : }
      70             : 
      71             : static pump_result
      72        1062 : work(inner_state_t *inner_state, pump_action action)
      73             : {
      74             :         int a;
      75             :         switch (action) {
      76             :         case PUMP_NO_FLUSH:
      77             :                 a = Z_NO_FLUSH;
      78             :                 break;
      79             :         case PUMP_FLUSH_DATA:
      80             :                 a = Z_SYNC_FLUSH;
      81             :                 break;
      82             :         case PUMP_FLUSH_ALL:
      83             :                 a = Z_FULL_FLUSH;
      84             :                 break;
      85             :         case PUMP_FINISH:
      86             :                 a = Z_FINISH;
      87             :                 break;
      88             :         default:
      89           0 :                 assert(0 /* unknown action */);
      90             :                 return PUMP_ERROR;
      91             :         }
      92             : 
      93        1062 :         if (inner_state->strm.next_in == NULL && inner_state->prev_was_stream_end) {
      94             :                 // on the previous Z_STREAM_END we attempted to continue in case there
      95             :                 // was a concatenated additional zstream but that is not the case.
      96             :                 return PUMP_END;
      97             :         }
      98             : 
      99        1054 :         int ret = inner_state->indeflate(&inner_state->strm, a);
     100             : 
     101        1054 :         inner_state->prev_was_stream_end = false;
     102        1054 :         switch (ret) {
     103             :                 case Z_OK:
     104             :                         return PUMP_OK;
     105           5 :                 case Z_STREAM_END:
     106           5 :                         inner_state->prev_was_stream_end = true;
     107           5 :                         if (action == PUMP_NO_FLUSH && inner_state->reset != NULL) {
     108             :                                 // zlib returns end, but maybe the input consists of multiple
     109             :                                 // gzipped files.
     110           4 :                                 inner_state->reset(inner_state);
     111           4 :                                 return PUMP_OK;
     112             :                         } else {
     113             :                                 // no more incoming data
     114             :                                 return PUMP_END;
     115             :                         }
     116         190 :                 default:
     117         190 :                         return PUMP_ERROR;
     118             :         }
     119             : }
     120             : 
     121             : static void
     122           5 : finalizer(inner_state_t *inner_state)
     123             : {
     124           5 :         inner_state->indeflateEnd(&inner_state->strm);
     125           5 :         free(inner_state);
     126           5 : }
     127             : 
     128             : 
     129             : static const char*
     130           0 : get_error(inner_state_t *inner_state)
     131             : {
     132           0 :         return inner_state->strm.msg;
     133             : }
     134             : 
     135             : static void
     136           4 : inflate_reset(inner_state_t *inner_state)
     137             : {
     138             :         pump_buffer src = get_src_win(inner_state);
     139             :         pump_buffer dst = get_dst_win(inner_state);
     140           4 :         inflateReset(&inner_state->strm);
     141           4 :         set_src_win(inner_state, src);
     142           4 :         set_dst_win(inner_state, dst);
     143           4 : }
     144             : 
     145             : stream *
     146           5 : gz_stream(stream *inner, int level)
     147             : {
     148           5 :         inner_state_t *gz = calloc(1, sizeof(inner_state_t));
     149           5 :         pump_state *state = calloc(1, sizeof(pump_state));
     150           5 :         if (gz == NULL || state == NULL) {
     151           0 :                 free(gz);
     152           0 :                 free(state);
     153           0 :                 mnstr_set_open_error(inner->name, errno, "couldn't initialize gz stream");
     154           0 :                 return NULL;
     155             :         }
     156             : 
     157           5 :         state->inner_state = gz;
     158           5 :         state->get_src_win = get_src_win;
     159           5 :         state->set_src_win = set_src_win;
     160           5 :         state->get_dst_win = get_dst_win;
     161           5 :         state->set_dst_win = set_dst_win;
     162           5 :         state->get_buffer = get_buffer;
     163           5 :         state->worker = work;
     164           5 :         state->get_error = get_error;
     165           5 :         state->finalizer = finalizer;
     166             : 
     167             :         int ret;
     168           5 :         if (inner->readonly) {
     169           4 :                 gz->indeflate = inflate;
     170           4 :                 gz->indeflateEnd = inflateEnd;
     171           4 :                 gz->reset = inflate_reset;
     172             :                 gz->strm.next_in = gz->buf;
     173           4 :                 gz->strm.avail_in = 0;
     174           4 :                 gz->strm.next_in = NULL;
     175             :                 gz->strm.avail_in = 0;
     176           4 :                 ret = inflateInit2(&gz->strm, 15 | 32); // 15 = allow all window sizes, 32 = accept gzip and zlib headers
     177             :         } else {
     178           1 :                 gz->indeflate = deflate;
     179           1 :                 gz->indeflateEnd = deflateEnd;
     180           1 :                 gz->strm.next_out = gz->buf;
     181           1 :                 gz->strm.avail_out = sizeof(gz->buf);
     182           1 :                 if (level == 0)
     183             :                         level = 6;
     184           1 :                 ret = deflateInit2(&gz->strm, level, Z_DEFLATED, 15 | 16, 8, Z_DEFAULT_STRATEGY);
     185             :         }
     186             : 
     187           5 :         if (ret != Z_OK) {
     188           0 :                 free(gz);
     189           0 :                 free(state);
     190           0 :                 mnstr_set_open_error(inner->name, 0, "failed to initialize gz stream: code %d", (int)ret);
     191           0 :                 return NULL;
     192             :         }
     193             : 
     194           5 :         stream *s = pump_stream(inner, state);
     195             : 
     196           5 :         if (s == NULL) {
     197           0 :                 gz->indeflateEnd(&gz->strm);
     198           0 :                 free(gz);
     199           0 :                 free(state);
     200           0 :                 return NULL;
     201             :         }
     202             : 
     203             :         return s;
     204             : }
     205             : 
     206             : static stream *
     207           0 : open_gzstream(const char *restrict filename, const char *restrict flags)
     208             : {
     209             :         stream *inner;
     210             : 
     211           0 :         inner = open_stream(filename, flags);
     212           0 :         if (inner == NULL)
     213             :                 return NULL;
     214             : 
     215           0 :         return gz_stream(inner, 0);
     216             : }
     217             : 
     218             : stream *
     219           0 : open_gzrstream(const char *filename)
     220             : {
     221           0 :         stream *s = open_gzstream(filename, "rb");
     222           0 :         if (s == NULL)
     223             :                 return NULL;
     224             : 
     225           0 :         assert(s->readonly == true);
     226           0 :         assert(s->binary == true);
     227             :         return s;
     228             : }
     229             : 
     230             : stream *
     231           0 : open_gzwstream(const char *restrict filename, const char *restrict mode)
     232             : {
     233           0 :         stream *s = open_gzstream(filename, mode);
     234           0 :         if (s == NULL)
     235             :                 return NULL;
     236             : 
     237           0 :         assert(s->readonly == false);
     238           0 :         assert(s->binary == true);
     239             :         return s;
     240             : }
     241             : 
     242             : stream *
     243           0 : open_gzrastream(const char *filename)
     244             : {
     245           0 :         stream *s = open_gzstream(filename, "r");
     246           0 :         s = create_text_stream(s);
     247           0 :         if (s == NULL)
     248             :                 return NULL;
     249             : 
     250           0 :         assert(s->readonly == true);
     251           0 :         assert(s->binary == false);
     252             :         return s;
     253             : }
     254             : 
     255             : stream *
     256           0 : open_gzwastream(const char *restrict filename, const char *restrict mode)
     257             : {
     258           0 :         stream *s = open_gzstream(filename, mode);
     259           0 :         s = create_text_stream(s);
     260           0 :         if (s == NULL)
     261             :                 return NULL;
     262           0 :         assert(s->readonly == false);
     263           0 :         assert(s->binary == false);
     264             :         return s;
     265             : }
     266             : #else
     267             : 
     268             : stream *
     269             : gz_stream(stream *inner, int preset)
     270             : {
     271             :         (void) inner;
     272             :         (void) preset;
     273             :         mnstr_set_open_error(inner->name, 0, "GZ support has been left out of this MonetDB");
     274             :         return NULL;
     275             : }
     276             : stream *
     277             : open_gzrstream(const char *filename)
     278             : {
     279             :         mnstr_set_open_error(filename, 0, "GZ support has been left out of this MonetDB");
     280             :         return NULL;
     281             : }
     282             : 
     283             : stream *
     284             : open_gzwstream(const char *restrict filename, const char *restrict mode)
     285             : {
     286             :         (void) mode;
     287             :         mnstr_set_open_error(filename, 0, "GZ support has been left out of this MonetDB");
     288             :         return NULL;
     289             : }
     290             : 
     291             : stream *
     292             : open_gzrastream(const char *filename)
     293             : {
     294             :         mnstr_set_open_error(filename, 0, "GZ support has been left out of this MonetDB");
     295             :         return NULL;
     296             : }
     297             : 
     298             : stream *
     299             : open_gzwastream(const char *restrict filename, const char *restrict mode)
     300             : {
     301             :         (void) mode;
     302             :         mnstr_set_open_error(filename, 0, "GZ support has been left out of this MonetDB");
     303             :         return NULL;
     304             : }
     305             : 
     306             : #endif

Generated by: LCOV version 1.14