From be5a1fe4a8fe8e79214cb87a870d7e744ea9f200 Mon Sep 17 00:00:00 2001 From: Andreas Fankhauser (@tux-six) Date: Thu, 7 Jul 2022 02:26:29 +0200 Subject: Extract from existing sources I tried this to be a grafted history because MUST NOT include all the other, unrelated crap from the mess where I did extract this code from. But it seems a hard thing to do as all sorts of git commands (eg push, clone, ...) did not work as epxected. So I keep the commit metadata here where this got split-off. commit 196ff8beda7a23aee6e1e7388cfc24f6247a63c9 Author: Andreas Fankhauser (@tux-six) Date: 2022-06-10 02:52:11 +0200 (scriptlee) Fix bug in http --- src/main/c/deflate.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 src/main/c/deflate.c (limited to 'src/main/c/deflate.c') diff --git a/src/main/c/deflate.c b/src/main/c/deflate.c new file mode 100644 index 0000000..9043c10 --- /dev/null +++ b/src/main/c/deflate.c @@ -0,0 +1,204 @@ +/* + + See "./inflate.c" for bash helpers. + +*/ + +#include "commonbase.h" + +/* system */ +#include +#include +#include +#include + +/* libs */ +#include "zlib.h" + +/* project */ +#include "string-util.h" +#include "log.h" + + +typedef struct Deflate Deflate; + + +struct Deflate { + int level; + int useZlibHdr; +}; + + +static void printHelp( void ){ + printf("\n %s%s", strrchr(__FILE__,'/')+1, " @ " STR_QUOT(PROJECT_VERSION) "\n" + "\n" + "deflates stdin to stdout\n" + "\n" + "Options:\n" + "\n" + " --level\n" + " Compression level 0-9 (0 fastest, 9 smallest).\n" + "\n" + " --zlib\n" + " Prepend output with a zlib header.\n" + "\n"); +} + + +static int parseArgs( int argc, char**argv, Deflate*deflateCls ){ + deflateCls->level = Z_DEFAULT_COMPRESSION; + deflateCls->useZlibHdr = 0; + for( uint i=1 ; ilevel = strtol(arg, &end, 10); + if( arg == end ){ fprintf(stderr, "Failed to parse '%s'\n", arg); return -1; } + if( deflateCls->level < 0 || deflateCls->level > 9 ){ + fprintf(stderr, "OutOfRange: %s %s\n", argv[i-1], arg); return -1; + } + }else if( !strcmp(arg,"--zlib") ){ + deflateCls->useZlibHdr = !0; + }else{ + fprintf(stderr, "Unknown arg: %s\n", arg); + return -1; + } + } + return 0; +} + + +static int doDeflate( Deflate*deflateCls ){ + int err; + z_stream strm; + long tmpLong; + uchar innBuf[65536]; + const int innBuf_cap = sizeof innBuf; + int innBuf_len = 0, innBuf_off = 0; + uchar outBuf[65536]; + const int outBuf_cap = sizeof outBuf; + int outBuf_len = 0; + int zlibHdrWritten = deflateCls->useZlibHdr ? 2 : 0; + int inputIsEOF = 0; + int outputIsEOF = 0; + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.next_in = innBuf; + strm.avail_in = innBuf_len; + + err = deflateInit(&strm, deflateCls->level); + if( err != Z_OK ){ + LOG_ERROR("deflateInit(): (ret=%d): %s", err, strerror(errno)); + return -1; + } + + for(; !outputIsEOF ;){ + + /* input */ { + int space = innBuf_cap - innBuf_len; + /* look if we can shift */ + //LOG_DEBUG("space=%d\n", space); + if( space <= 0 && innBuf_off > 0 ){ + //LOG_DEBUG("do shifting\n"); + int wr = 0, rd = innBuf_off; + for(;;){ + err = rd - wr; /* chunk length to copy */ + if( rd + err > innBuf_cap) err = innBuf_cap - rd; + if( err <= 0 ) break; + memcpy(innBuf + wr, innBuf + rd, err); + rd += err; + wr += err; + } + innBuf_len -= innBuf_off; + innBuf_off = 0; + space = innBuf_cap - innBuf_len; + //LOG_DEBUG("space=%d (after shift)\n", space); + } + if( space > 0 && !inputIsEOF ){ + err = fread(innBuf + innBuf_len, 1, space, stdin); + if(unlikely( err <= 0 )){ + if( feof(stdin) ){ + inputIsEOF = !0; + }else{ + LOG_ERROR("fread(): %s", strerror(errno)); + return -1; + } + } + assert(err <= space); + innBuf_len += err; + } + assert(innBuf_len - innBuf_off >= 0); + } + + /* process */ { + strm.next_in = innBuf + innBuf_off; + strm.avail_in = innBuf_len - innBuf_off; + strm.next_out = outBuf; + strm.avail_out = outBuf_cap; + assert(strm.avail_out > 0); + //LOG_DEBUG("avail_in=%d, inputIsEOF=%d\n", strm.avail_in, inputIsEOF); + assert(strm.avail_in > 0 || inputIsEOF); + err = deflate(&strm, inputIsEOF ? Z_FINISH : Z_NO_FLUSH); + if(unlikely( err != Z_OK )){ + if( err == Z_STREAM_END ){ + outputIsEOF = !0; + }else{ + LOG_ERROR("deflate(): %s\n", strm.msg); + return -1; + } + } + innBuf_off = strm.next_in - innBuf; + outBuf_len = strm.next_out - outBuf; + } + + /* output */ { + int outBuf_off = 0; + if( zlibHdrWritten < 2 ){ + /* try to skip up to 2 bytes */ + err = 2 - zlibHdrWritten; + if( outBuf_len < err ){ err = outBuf_len; } + zlibHdrWritten += err; + outBuf_off += err; + } + err = fwrite(outBuf + outBuf_off, 1, outBuf_len - outBuf_off, stdout); + if(unlikely( err != outBuf_len - outBuf_off )){ + LOG_ERROR("fwrite(): %s\n", strerror(errno)); + return -1; + } + outBuf_len = 0; + } + } + + err = deflateEnd(&strm); + if( err != Z_OK ){ + LOG_WARN("deflateEnd() ret=%d: %s\n", err, strm.msg); + } + + return 0; +} + + +int deflate_main( int argc, char**argv ){ + int err; + Deflate deflateCls; + #define deflateCls (&deflateCls) + + err = parseArgs(argc, argv, deflateCls); + if( err < 0 ){ return err; } + + stdinModeBinary(); + stdoutModeBinary(); + + err = doDeflate(deflateCls); + if( err < 0 ){ return err; } + + return 0; + #undef deflate +} + -- cgit v1.1