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 + -
显示快捷键?