/***********************************************************************1* *2* This software is part of the zlib package *3* Copyright (c) 1995-2009 Jean-loup Gailly and Mark Adler *4* *5* This software is provided 'as-is', without any express or implied *6* warranty. In no event will the authors be held liable for any *7* damages arising from the use of this software. *8* *9* Permission is granted to anyone to use this software for any *10* purpose, including commercial applications, and to alter it and *11* redistribute it freely, subject to the following restrictions: *12* *13* 1. The origin of this software must not be misrepresented; *14* you must not claim that you wrote the original software. If *15* you use this software in a product, an acknowledgment in the *16* product documentation would be appreciated but is not *17* required. *18* *19* 2. Altered source versions must be plainly marked as such, *20* and must not be misrepresented as being the original *21* software. *22* *23* 3. This notice may not be removed or altered from any source *24* distribution. *25* *26* This software is provided "as-is", without any express or implied *27* warranty. In no event will the authors be held liable for any damages*28* arising from the use of this software. *29* *30* Permission is granted to anyone to use this software for any purpose,*31* including commercial applications, and to alter it and redistribute i*32* freely, subject to the following restrictions: *33* *34* 1. The origin of this software must not be misrepresented; you must n*35* claim that you wrote the original software. If you use this softwa*36* in a product, an acknowledgment in the product documentation would*37* be appreciated but is not required. *38* *39* 2. Altered source versions must be plainly marked as such, and must n*40* be misrepresented as being the original software. *41* *42* 3. This notice may not be removed or altered from any source *43* distribution. *44* *45* Jean-loup Gailly *46* Mark Adler *47* *48***********************************************************************/49#pragma prototyped5051/*52* sfio gzip discipline53*54* handles { gzip compress vczip } on input55* handles { gzip compress } on output56*/5758#include <sfio_t.h>59#include <ast.h>60#include <zlib.h>61#include <sfdcgzip.h>6263#ifdef z_off64_t64#undef z_off_t65#define z_off_t z_off64_t66#undef gzsync67#define gzsync gzsync6468#endif6970typedef struct71{72Sfdisc_t disc; /* sfio discipline */73gzFile* gz; /* gz handle */74Sfio_t* op; /* original stream */75} Sfgzip_t;7677/*78* gzip exception handler79* free on close80*/8182static int83sfgzexcept(Sfio_t* sp, int op, void* val, Sfdisc_t* dp)84{85register Sfgzip_t* gz = (Sfgzip_t*)dp;86int f;87int r;8889NoP(sp);90#if 091{92static char aha[] = "AHA sfdcgzip event 0\n";93static int init;9495if (!init)96init = getenv("SFGZ_DEBUG") ? 1 : -1;97if (init > 0)98{99aha[sizeof(aha) - 3] = '0' + op;100write(2, aha, sizeof(aha) - 1);101}102}103#endif104switch (op)105{106case SF_ATEXIT:107sfdisc(sp, SF_POPDISC);108return 0;109case SF_CLOSING:110case SF_DPOP:111case SF_FINAL:112if (gz->gz)113{114SFDCNEXT(sp, f);115if (r = gzclose(gz->gz) ? -1 : 0)116sp->_flags |= SF_ERROR;117gz->gz = 0;118SFDCPREV(sp, f);119}120else121r = 0;122if (gz->op)123{124sfclose(gz->op);125gz->op = 0;126}127if (op != SF_CLOSING)128free(dp);129return r;130case SF_DBUFFER:131return 1;132case SF_SYNC:133if (!val && gzsync(gz->gz, (z_off_t)(-1)) < 0)134sp->_flags |= SF_ERROR;135return 0;136case SFGZ_HANDLE:137return (*((gzFile**)val) = gz->gz) ? 1 : -1;138case SFGZ_GETPOS:139return (*((Sfoff_t*)val) = gzsync(gz->gz, (z_off_t)(-1))) < 0 ? -1 : 0;140case SFGZ_SETPOS:141return gzsync(gz->gz, (z_off_t)(*((Sfoff_t*)val))) < 0 ? -1 : 0;142}143return 0;144}145146/*147* sfio gzip discipline seek148*/149150static Sfoff_t151sfgzseek(Sfio_t* fp, Sfoff_t off, int op, Sfdisc_t* dp)152{153return sfsk(fp, off, op, dp);154}155156/*157* sfio gzip discipline read158*/159160static ssize_t161sfgzread(Sfio_t* fp, Void_t* buf, size_t size, Sfdisc_t* dp)162{163register Sfgzip_t* gz = (Sfgzip_t*)dp;164165return gzread(gz->gz, buf, size);166}167168/*169* sfio gzip discipline write170*/171172static ssize_t173sfgzwrite(Sfio_t* fp, const Void_t* buf, size_t size, Sfdisc_t* dp)174{175register Sfgzip_t* gz = (Sfgzip_t*)dp;176177return gzwrite(gz->gz, (void*)buf, size);178}179180/*181* create and push the sfio gzip discipline182*183* (flags&SFGZ_VERIFY) return184* >0 is a { g:gzip c:compress v:vczip } file185* 0 not a { gzip compress vczip } file186* <0 error187* otherwise return188* >0 discipline pushed { g:gzip c:compress v:vczip }189* 0 discipline not needed190* <0 error191*/192193#undef PRIVATE194#define PRIVATE 0195196int197sfdcgzip(Sfio_t* sp, int flags)198{199char* m;200Sfgzip_t* gz;201int fd;202int rd;203size_t z;204char mode[10];205206rd = sfset(sp, 0, 0) & SF_READ;207if (rd)208{209register unsigned char* s;210register int n;211register int r;212213/*214* peek the first 4 bytes to verify the magic215*216* 0x1f8b.... sfdcgzip gzip217* 0x1f9d.... sfdclzw compress218* 0xd6c3c4d8 sfpopen vcunzip219*/220221#if PRIVATE222if (!(n = sfset(sp, 0, 0) & SF_SHARE))223sfset(sp, SF_SHARE, 1);224#endif225s = (unsigned char*)sfreserve(sp, 4, SF_LOCKR);226#if PRIVATE227if (!n)228sfset(sp, SF_SHARE, 0);229#endif230if (!s)231return -1;232n = 0;233if (s[0] == 0x1f)234{235if (s[1] == 0x8b)236n = 'g';237else if (s[1] == 0x9d)238n = 'c';239}240else if (s[0] == 0xd6 && s[1] == 0xc3 && s[2] == 0xc4 && s[3] == 0xd8)241n = 'v';242sfread(sp, s, 0);243if (!n)244return 0;245if (flags & SFGZ_VERIFY)246return n != 0;247switch (n)248{249case 'c':250return (r = sfdclzw(sp, flags)) > 0 ? 'c' : r;251case 'v':252r = 0;253n = dup(0);254close(0);255if (dup(sffileno(sp)) || !sfpopen(sp, "vcunzip", "r"))256r = -1;257close(0);258if (n > 0 && dup(n))259r = -1;260close(n);261return r > 0 ? 'v' : r;262}263}264else if (flags & SFGZ_VERIFY)265return -1;266if (!(gz = newof(0, Sfgzip_t, 1, 0)))267return -1;268gz->disc.exceptf = sfgzexcept;269if (rd)270gz->disc.readf = sfgzread;271else272gz->disc.writef = sfgzwrite;273gz->disc.seekf = sfgzseek;274m = mode;275*m++ = rd ? 'r' : 'w';276*m++ = 'b';277if (flags & SFGZ_NOCRC)278*m++ = 'n';279*m++ = 'o';280if ((flags &= 0xf) > 0 && flags <= 9)281*m++ = '0' + flags;282*m = 0;283#if PRIVATE284sfset(sp, SF_SHARE|SF_PUBLIC, 0);285#endif286if (!rd)287{288m = 0;289z = 0;290}291else if (!(z = sfreserve(sp, 0, -1) ? (size_t)sfvalue(sp) : 0))292m = 0;293else if (m = sfreserve(sp, z, 0))294z = (size_t)sfvalue(sp);295else296z = 0;297fd = sffileno(sp);298if (rd && (gz->op = sfopen(NiL, "/dev/null", "r")))299sfswap(sp, gz->op);300if (!(gz->gz = gzbopen(fd, mode, m, z)) || sfdisc(sp, &gz->disc) != &gz->disc)301{302free(gz);303return -1;304}305#if PRIVATE306#if 0307{308char* v;309long n;310311if ((v = getenv("SFGZ_sfdcgzip_bufsize")) || (v = getenv("SFGZ_bufsize")))312{313if ((n = strtol(v, NiL, 0)) > 0)314sfsetbuf(sp, NiL, n);315}316else317sfsetbuf(sp, NiL, SF_BUFSIZE);318}319#else320sfsetbuf(sp, NiL, SF_BUFSIZE);321#endif322#endif323if (!rd)324sfset(sp, SF_IOCHECK, 1);325return 'g';326}327328#if __OBSOLETE__ < 19990717329330#if defined(__EXPORT__)331#define extern __EXPORT__332#endif333334extern int335sfgzip(Sfio_t* sp)336{337return sfdcgzip(sp, 0);338}339340#undef extern341342#endif343344345