gzio.c

来自「OTP是开放电信平台的简称」· C语言 代码 · 共 856 行 · 第 1/2 页

C
856
字号
	    s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));	    start = s->stream.next_out;	    if (getLong(s) != s->crc) {		s->z_err = Z_DATA_ERROR;	    } else {	        (void)getLong(s);                /* The uncompressed length returned by above getlong() may                 * be different from s->stream.total_out) in case of		 * concatenated .gz files. Check for such files:		 */		check_header(s);		if (s->z_err == Z_OK) {		    uLong total_in = s->stream.total_in;		    uLong total_out = s->stream.total_out;		    inflateReset(&(s->stream));		    s->stream.total_in = total_in;		    s->stream.total_out = total_out;		    s->crc = crc32(0L, Z_NULL, 0);		}	    }	}	if (s->z_err != Z_OK || s->z_eof) break;    }    s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));    s->position += (int)(len - s->stream.avail_out);    return (int)(len - s->stream.avail_out);}/* ===========================================================================     Writes the given number of uncompressed bytes into the compressed file.   gzwrite returns the number of bytes actually written (0 in case of error).*/interts_gzwrite(gzFile file, voidpc buf, unsigned len){    gz_stream *s = (gz_stream*)file;    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;    s->stream.next_in = buf;    s->stream.avail_in = len;    while (s->stream.avail_in != 0) {        if (s->stream.avail_out == 0) {            s->stream.next_out = s->outbuf;            if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {                s->z_err = Z_ERRNO;                break;            }            s->stream.avail_out = Z_BUFSIZE;        }        s->z_err = deflate(&(s->stream), Z_NO_FLUSH);        if (s->z_err != Z_OK) break;    }    s->crc = crc32(s->crc, buf, len);    s->position += (int)(len - s->stream.avail_in);    return (int)(len - s->stream.avail_in);}/* * For use by Erlang file driver. * * XXX Limitations: *  - SEEK_END is not allowed (length of file is not known). *  - When writing, only forward seek is supported. */interts_gzseek(gzFile file, int offset, int whence){    int pos;    gz_stream* s = (gz_stream *) file;    if (s == NULL) {	errno = EINVAL;	return -1;    }    if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) {	errno = EIO;	return -1;    }    switch (whence) {    case SEEK_SET: pos = offset; break;    case SEEK_CUR: pos = s->position+offset; break;    case SEEK_END:     default:      errno = EINVAL; return -1;    }    if (pos == s->position) {	return pos;    }    if (pos < s->position) {	if (s->mode == 'w') {	    errno = EINVAL;	    return -1;	}	gz_rewind(s);    }    while (s->position < pos) {	char buf[512];	int n;	n = pos - s->position;	if (n > sizeof(buf))	    n = sizeof(buf);	if (s->mode == 'r') {	    erts_gzread(file, buf, n);	} else {	    memset(buf, '\0', n);	    erts_gzwrite(file, buf, n);	}    }    return s->position;}/* ===========================================================================     Flushes all pending output into the compressed file. The parameter   flush is as in the deflate() function.     gzflush should be called only when strictly necessary because it can   degrade compression.*/interts_gzflush(gzFile file, int flush){    uInt len;    int done = 0;    gz_stream *s = (gz_stream*)file;    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;    s->stream.avail_in = 0; /* should be zero already anyway */    for (;;) {        len = Z_BUFSIZE - s->stream.avail_out;        if (len != 0) {            if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {                s->z_err = Z_ERRNO;                return Z_ERRNO;            }            s->stream.next_out = s->outbuf;            s->stream.avail_out = Z_BUFSIZE;        }        if (done) break;        s->z_err = deflate(&(s->stream), flush);        /* deflate has finished flushing only when it hasn't used up         * all the available space in the output buffer:          */        done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);         if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;    }    fflush(s->file);    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;}/* ===========================================================================   Outputs a long in LSB order to the given file*/local void putLong (file, x)    FILE *file;    uLong x;{    int n;    for (n = 0; n < 4; n++) {        fputc((int)(x & 0xff), file);        x >>= 8;    }}/* ===========================================================================   Reads a long in LSB order from the given gz_stream. Sets */local uLong getLong (s)    gz_stream *s;{    uLong x = (uLong)get_byte(s);    int c;    x += ((uLong)get_byte(s))<<8;    x += ((uLong)get_byte(s))<<16;    c = get_byte(s);    if (c == EOF) s->z_err = Z_DATA_ERROR;    x += ((uLong)c)<<24;    return x;}/* ===========================================================================     Flushes all pending output if necessary, closes the compressed file   and deallocates all the (de)compression state.*/interts_gzclose(gzFile file){    int err;    gz_stream *s = (gz_stream*)file;    if (s == NULL) return Z_STREAM_ERROR;    if (s->mode == 'w') {        err = erts_gzflush (file, Z_FINISH);        if (err != Z_OK) return s->destroy(file);        putLong (s->file, s->crc);        putLong (s->file, s->stream.total_in);    }    return s->destroy(file);}/* ===========================================================================   Uncompresses the buffer given and returns a pointer to a binary.   If the buffer was not compressed with gzip, the buffer contents   will be copied unchanged into the binary.   If a `gzip' header was found, but there were subsequent errors,   a NULL pointer is returned.*/ErlDrvBinary*erts_gzinflate_buffer(char* start, int size){    ErlDrvBinary* bin;    ErlDrvBinary* bin2;    gzFile fd;    int bytes_read = 0;    if ((fd = gzbufopen(start, size)) == NULL)	return NULL;    size *= 2;    if ((bin = driver_alloc_binary(size)) == NULL) {	return NULL;    }    for (;;) {	int n = erts_gzread(fd, bin->orig_bytes + bytes_read, size-bytes_read);	if (n == 0) {	    erts_gzclose(fd);	    if ((bin2 = driver_realloc_binary(bin, bytes_read)) == NULL) {		driver_free_binary(bin);	    }	    return bin2;	} else if (n == -1) {	    driver_free_binary(bin);	    erts_gzclose(fd);	    return NULL;	}	bytes_read += n;	size *= 2;	if ((bin2 = driver_realloc_binary(bin, size)) == NULL) {	    driver_free_binary(bin);	    erts_gzclose(fd);	    return NULL;	}	bin = bin2;    }}/* ===========================================================================   Compresses the buffer given and returns a pointer to a binary.   A NULL pointer is returned if any error occurs.   Writes a gzip header as well.*/#define GZIP_HD_SIZE 10#define GZIP_TL_SIZE 8#define GZIP_X_SIZE (GZIP_HD_SIZE+GZIP_TL_SIZE)ErlDrvBinary*erts_gzdeflate_buffer(char* start, int size){    z_stream c_stream; /* compression stream */    ErlDrvBinary* bin;    ErlDrvBinary* bin2;    uLong    crc;     /* crc32 of uncompressed data */    uLong    szIn;    Byte* ptr;    int comprLen = size + (size/1000) + 1 + 12; /* see zlib.h */    crc = crc32(0L, Z_NULL, 0);    c_stream.zalloc = (alloc_func)0;    c_stream.zfree = (free_func)0;    c_stream.opaque = (voidpf)0;    if (deflateInit2(&c_stream, Z_DEFAULT_COMPRESSION,		     Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0) != Z_OK)	return NULL;    if ((bin = driver_alloc_binary(comprLen+GZIP_X_SIZE)) == NULL)	return NULL;    sprintf(bin->orig_bytes, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],	    Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);    c_stream.next_out = ((Byte*) bin->orig_bytes)+GZIP_HD_SIZE;    c_stream.avail_out = (uInt) bin->orig_size - GZIP_HD_SIZE;    c_stream.next_in  = (Byte*) start;    c_stream.avail_in = (uInt) size;    if (deflate(&c_stream, Z_FINISH) != Z_STREAM_END) {	driver_free_binary(bin);	return NULL;	    }    crc = crc32(crc, (unsigned char*)start, size);    ptr = c_stream.next_out;    szIn = c_stream.total_in;    *ptr++ = (crc & 0xff); crc >>= 8;    *ptr++ = (crc & 0xff); crc >>= 8;    *ptr++ = (crc & 0xff); crc >>= 8;    *ptr++ = (crc & 0xff); crc >>= 8;    *ptr++ = (szIn & 0xff); szIn >>= 8;    *ptr++ = (szIn & 0xff); szIn >>= 8;    *ptr++ = (szIn & 0xff); szIn >>= 8;    *ptr++ = (szIn & 0xff); szIn >>= 8;    if (deflateEnd(&c_stream) != Z_OK) {	driver_free_binary(bin);	return NULL;	    }	    size = ptr - (Byte*)bin->orig_bytes;    if ((bin2 = driver_realloc_binary(bin, size)) == NULL)	driver_free_binary(bin);    return bin2;}/* ===========================================================================   Like gzopen(), but opens a RAM file on the given the buffer.*/gzFilegzbufopen(bytes, size)    char* bytes;		/* Start of buffer to read from. */    int size;			/* Size of buffer. */{    int err;    gz_stream *s;    s = (gz_stream *)ALLOC(sizeof(gz_stream));    if (!s)	return Z_NULL;    s->stream.zalloc = (alloc_func)0;    s->stream.zfree = (free_func)0;    s->stream.opaque = (voidpf)0;    s->stream.next_in = s->inbuf = (unsigned char*)bytes;    s->stream.next_out = s->outbuf = Z_NULL;    s->stream.avail_in = size;    s->stream.avail_out = 0;    s->file = NULL;    s->z_err = Z_OK;    s->z_eof = 0;    s->crc = crc32(0L, Z_NULL, 0);    s->msg = NULL;    s->transparent = 0;    s->position = 0;    s->path = (char*)ALLOC(1);    s->path[0] = '\0';    s->reader = mem_reader_dummy;    s->destroy = mem_destroy;    s->mode = 'r';        err = inflateInit2(&(s->stream), -MAX_WBITS);    if (err != Z_OK || s->inbuf == Z_NULL) {	return s->destroy(s), (gzFile)Z_NULL;    }    s->stream.avail_out = Z_BUFSIZE;    errno = 0;    s->file = NULL;    check_header(s);    return (gzFile)s;}local int mem_destroy(s)    gz_stream* s;{    int err = Z_OK;    if (!s) return Z_STREAM_ERROR;    TRYFREE(s->msg);    if (s->stream.state != NULL) {       if (s->mode == 'w') {           err = deflateEnd(&(s->stream));       } else if (s->mode == 'r') {           err = inflateEnd(&(s->stream));       }    }    if (s->z_err < 0)	err = s->z_err;    TRYFREE(s->path);    TRYFREE(s->outbuf);    TRYFREE(s);    return err;}local unsigned mem_reader_dummy(buf, size, items, fp)    void* buf;    unsigned size;    unsigned items;    FILE* fp;{    return 0;			/* Always end of file. */}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?