1/* zran.c -- example of deflate stream indexing and random access 2 * Copyright (C) 2005, 2012, 2018, 2023 Mark Adler 3 * For conditions of distribution and use, see copyright notice in zlib.h 4 * Version 1.4 13 Apr 2023 Mark Adler */ 5 6/* Version History: 7 1.0 29 May 2005 First version 8 1.1 29 Sep 2012 Fix memory reallocation error 9 1.2 14 Oct 2018 Handle gzip streams with multiple members 10 Add a header file to facilitate usage in applications 11 1.3 18 Feb 2023 Permit raw deflate streams as well as zlib and gzip 12 Permit crossing gzip member boundaries when extracting 13 Support a size_t size when extracting (was an int) 14 Do a binary search over the index for an access point 15 Expose the access point type to enable save and load 16 1.4 13 Apr 2023 Add a NOPRIME define to not use inflatePrime() 17 */ 18 19// Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary() 20// for random access of a compressed file. A file containing a raw deflate 21// stream is provided on the command line. The compressed stream is decoded in 22// its entirety, and an index built with access points about every SPAN bytes 23// in the uncompressed output. The compressed file is left open, and can then 24// be read randomly, having to decompress on the average SPAN/2 uncompressed 25// bytes before getting to the desired block of data. 26// 27// An access point can be created at the start of any deflate block, by saving 28// the starting file offset and bit of that block, and the 32K bytes of 29// uncompressed data that precede that block. Also the uncompressed offset of 30// that block is saved to provide a reference for locating a desired starting 31// point in the uncompressed stream. deflate_index_build() decompresses the 32// input raw deflate stream a block at a time, and at the end of each block 33// decides if enough uncompressed data has gone by to justify the creation of a 34// new access point. If so, that point is saved in a data structure that grows 35// as needed to accommodate the points. 36// 37// To use the index, an offset in the uncompressed data is provided, for which 38// the latest access point at or preceding that offset is located in the index. 39// The input file is positioned to the specified location in the index, and if 40// necessary the first few bits of the compressed data is read from the file. 41// inflate is initialized with those bits and the 32K of uncompressed data, and 42// decompression then proceeds until the desired offset in the file is reached. 43// Then decompression continues to read the requested uncompressed data from 44// the file. 45// 46// There is some fair bit of overhead to starting inflation for the random 47// access, mainly copying the 32K byte dictionary. If small pieces of the file 48// are being accessed, it would make sense to implement a cache to hold some 49// lookahead to avoid many calls to deflate_index_extract() for small lengths. 50// 51// Another way to build an index would be to use inflateCopy(). That would not 52// be constrained to have access points at block boundaries, but would require 53// more memory per access point, and could not be saved to a file due to the 54// use of pointers in the state. The approach here allows for storage of the 55// index in a file. 56 57#include <stdio.h> 58#include <stdlib.h> 59#include <string.h> 60#include <limits.h> 61#include "zlib.h" 62#include "zran.h" 63 64#define WINSIZE 32768U // sliding window size 65#define CHUNK 16384 // file input buffer size 66 67// See comments in zran.h. 68void deflate_index_free(struct deflate_index *index) 69{ 70 if (index != NULL) { 71 free(index->list); 72 free(index); 73 } 74} 75 76// Add an access point to the list. If out of memory, deallocate the existing 77// list and return NULL. index->mode is temporarily the allocated number of 78// access points, until it is time for deflate_index_build() to return. Then 79// index->mode is set to the mode of inflation. 80static struct deflate_index *add_point(struct deflate_index *index, int bits, 81 off_t in, off_t out, unsigned left, 82 unsigned char *window) 83{ 84 if (index == NULL) { 85 // The list is empty. Create it, starting with eight access points. 86 index = malloc(sizeof(struct deflate_index)); 87 if (index == NULL) 88 return NULL; 89 index->have = 0; 90 index->mode = 8; 91 index->list = malloc(sizeof(point_t) * index->mode); 92 if (index->list == NULL) { 93 free(index); 94 return NULL; 95 } 96 } 97 98 else if (index->have == index->mode) { 99 // The list is full. Make it bigger. 100 index->mode <<= 1; 101 point_t *next = realloc(index->list, sizeof(point_t) * index->mode); 102 if (next == NULL) { 103 deflate_index_free(index); 104 return NULL; 105 } 106 index->list = next; 107 } 108 109 // Fill in the access point and increment how many we have. 110 point_t *next = (point_t *)(index->list) + index->have++; 111 if (index->have < 0) { 112 // Overflowed the int! 113 deflate_index_free(index); 114 return NULL; 115 } 116 next->out = out; 117 next->in = in; 118 next->bits = bits; 119 if (left) 120 memcpy(next->window, window + WINSIZE - left, left); 121 if (left < WINSIZE) 122 memcpy(next->window + left, window, WINSIZE - left); 123 124 // Return the index, which may have been newly allocated or destroyed. 125 return index; 126} 127 128// Decompression modes. These are the inflateInit2() windowBits parameter. 129#define RAW -15 130#define ZLIB 15 131#define GZIP 31 132 133// See comments in zran.h. 134int deflate_index_build(FILE *in, off_t span, struct deflate_index **built) 135{ 136 // Set up inflation state. 137 z_stream strm = {0}; // inflate engine (gets fired up later) 138 unsigned char buf[CHUNK]; // input buffer 139 unsigned char win[WINSIZE] = {0}; // output sliding window 140 off_t totin = 0; // total bytes read from input 141 off_t totout = 0; // total bytes uncompressed 142 int mode = 0; // mode: RAW, ZLIB, or GZIP (0 => not set yet) 143 144 // Decompress from in, generating access points along the way. 145 int ret; // the return value from zlib, or Z_ERRNO 146 off_t last; // last access point uncompressed offset 147 struct deflate_index *index = NULL; // list of access points 148 do { 149 // Assure available input, at least until reaching EOF. 150 if (strm.avail_in == 0) { 151 strm.avail_in = fread(buf, 1, sizeof(buf), in); 152 totin += strm.avail_in; 153 strm.next_in = buf; 154 if (strm.avail_in < sizeof(buf) && ferror(in)) { 155 ret = Z_ERRNO; 156 break; 157 } 158 159 if (mode == 0) { 160 // At the start of the input -- determine the type. Assume raw 161 // if it is neither zlib nor gzip. This could in theory result 162 // in a false positive for zlib, but in practice the fill bits 163 // after a stored block are always zeros, so a raw stream won't 164 // start with an 8 in the low nybble. 165 mode = strm.avail_in == 0 ? RAW : // empty -- will fail 166 (strm.next_in[0] & 0xf) == 8 ? ZLIB : 167 strm.next_in[0] == 0x1f ? GZIP : 168 /* else */ RAW; 169 ret = inflateInit2(&strm, mode); 170 if (ret != Z_OK) 171 break; 172 } 173 } 174 175 // Assure available output. This rotates the output through, for use as 176 // a sliding window on the uncompressed data. 177 if (strm.avail_out == 0) { 178 strm.avail_out = sizeof(win); 179 strm.next_out = win; 180 } 181 182 if (mode == RAW && index == NULL) 183 // We skip the inflate() call at the start of raw deflate data in 184 // order generate an access point there. Set data_type to imitate 185 // the end of a header. 186 strm.data_type = 0x80; 187 else { 188 // Inflate and update the number of uncompressed bytes. 189 unsigned before = strm.avail_out; 190 ret = inflate(&strm, Z_BLOCK); 191 totout += before - strm.avail_out; 192 } 193 194 if ((strm.data_type & 0xc0) == 0x80 && 195 (index == NULL || totout - last >= span)) { 196 // We are at the end of a header or a non-last deflate block, so we 197 // can add an access point here. Furthermore, we are either at the 198 // very start for the first access point, or there has been span or 199 // more uncompressed bytes since the last access point, so we want 200 // to add an access point here. 201 index = add_point(index, strm.data_type & 7, totin - strm.avail_in, 202 totout, strm.avail_out, win); 203 if (index == NULL) { 204 ret = Z_MEM_ERROR; 205 break; 206 } 207 last = totout; 208 } 209 210 if (ret == Z_STREAM_END && mode == GZIP && 211 (strm.avail_in || ungetc(getc(in), in) != EOF)) 212 // There is more input after the end of a gzip member. Reset the 213 // inflate state to read another gzip member. On success, this will 214 // set ret to Z_OK to continue decompressing. 215 ret = inflateReset2(&strm, GZIP); 216 217 // Keep going until Z_STREAM_END or error. If the compressed data ends 218 // prematurely without a file read error, Z_BUF_ERROR is returned. 219 } while (ret == Z_OK); 220 inflateEnd(&strm); 221 222 if (ret != Z_STREAM_END) { 223 // An error was encountered. Discard the index and return a negative 224 // error code. 225 deflate_index_free(index); 226 return ret == Z_NEED_DICT ? Z_DATA_ERROR : ret; 227 } 228 229 // Shrink the index to only the occupied access points and return it. 230 index->mode = mode; 231 index->length = totout; 232 point_t *list = realloc(index->list, sizeof(point_t) * index->have); 233 if (list == NULL) { 234 // Seems like a realloc() to make something smaller should always work, 235 // but just in case. 236 deflate_index_free(index); 237 return Z_MEM_ERROR; 238 } 239 index->list = list; 240 *built = index; 241 return index->have; 242} 243 244#ifdef NOPRIME 245// Support zlib versions before 1.2.3 (July 2005), or incomplete zlib clones 246// that do not have inflatePrime(). 247 248# define INFLATEPRIME inflatePreface 249 250// Append the low bits bits of value to in[] at bit position *have, updating 251// *have. value must be zero above its low bits bits. bits must be positive. 252// This assumes that any bits above the *have bits in the last byte are zeros. 253// That assumption is preserved on return, as any bits above *have + bits in 254// the last byte written will be set to zeros. 255static inline void append_bits(unsigned value, int bits, 256 unsigned char *in, int *have) { 257 in += *have >> 3; // where the first bits from value will go 258 int k = *have & 7; // the number of bits already there 259 *have += bits; 260 if (k) 261 *in |= value << k; // write value above the low k bits 262 else 263 *in = value; 264 k = 8 - k; // the number of bits just appended 265 while (bits > k) { 266 value >>= k; // drop the bits appended 267 bits -= k; 268 k = 8; // now at a byte boundary 269 *++in = value; 270 } 271} 272 273// Insert enough bits in the form of empty deflate blocks in front of the 274// low bits bits of value, in order to bring the sequence to a byte boundary. 275// Then feed that to inflate(). This does what inflatePrime() does, except that 276// a negative value of bits is not supported. bits must be in 0..16. If the 277// arguments are invalid, Z_STREAM_ERROR is returned. Otherwise the return 278// value from inflate() is returned. 279static int inflatePreface(z_stream *strm, int bits, int value) 280{ 281 // Check input. 282 if (strm == Z_NULL || bits < 0 || bits > 16) 283 return Z_STREAM_ERROR; 284 if (bits == 0) 285 return Z_OK; 286 value &= (2 << (bits - 1)) - 1; 287 288 // An empty dynamic block with an odd number of bits (95). The high bit of 289 // the last byte is unused. 290 static const unsigned char dyn[] = { 291 4, 0xe0, 0x81, 8, 0, 0, 0, 0, 0x20, 0xa8, 0xab, 0x1f 292 }; 293 const int dynlen = 95; // number of bits in the block 294 295 // Build an input buffer for inflate that is a multiple of eight bits in 296 // length, and that ends with the low bits bits of value. 297 unsigned char in[(dynlen + 3 * 10 + 16 + 7) / 8]; 298 int have = 0; 299 if (bits & 1) { 300 // Insert an empty dynamic block to get to an odd number of bits, so 301 // when bits bits from value are appended, we are at an even number of 302 // bits. 303 memcpy(in, dyn, sizeof(dyn)); 304 have = dynlen; 305 } 306 while ((have + bits) & 7) 307 // Insert empty fixed blocks until appending bits bits would put us on 308 // a byte boundary. This will insert at most three fixed blocks. 309 append_bits(2, 10, in, &have); 310 311 // Append the bits bits from value, which takes us to a byte boundary. 312 append_bits(value, bits, in, &have); 313 314 // Deliver the input to inflate(). There is no output space provided, but 315 // inflate() can't get stuck waiting on output not ingesting all of the 316 // provided input. The reason is that there will be at most 16 bits of 317 // input from value after the empty deflate blocks (which themselves 318 // generate no output). At least ten bits are needed to generate the first 319 // output byte from a fixed block. The last two bytes of the buffer have to 320 // be ingested in order to get ten bits, which is the most that value can 321 // occupy. 322 strm->avail_in = have >> 3; 323 strm->next_in = in; 324 strm->avail_out = 0; 325 strm->next_out = in; // not used, but can't be NULL 326 return inflate(strm, Z_NO_FLUSH); 327} 328 329#else 330# define INFLATEPRIME inflatePrime 331#endif 332 333// See comments in zran.h. 334ptrdiff_t deflate_index_extract(FILE *in, struct deflate_index *index, 335 off_t offset, unsigned char *buf, size_t len) 336{ 337 // Do a quick sanity check on the index. 338 if (index == NULL || index->have < 1 || index->list[0].out != 0) 339 return Z_STREAM_ERROR; 340 341 // If nothing to extract, return zero bytes extracted. 342 if (len == 0 || offset < 0 || offset >= index->length) 343 return 0; 344 345 // Find the access point closest to but not after offset. 346 int lo = -1, hi = index->have; 347 point_t *point = index->list; 348 while (hi - lo > 1) { 349 int mid = (lo + hi) >> 1; 350 if (offset < point[mid].out) 351 hi = mid; 352 else 353 lo = mid; 354 } 355 point += lo; 356 357 // Initialize the input file and prime the inflate engine to start there. 358 int ret = fseeko(in, point->in - (point->bits ? 1 : 0), SEEK_SET); 359 if (ret == -1) 360 return Z_ERRNO; 361 int ch = 0; 362 if (point->bits && (ch = getc(in)) == EOF) 363 return ferror(in) ? Z_ERRNO : Z_BUF_ERROR; 364 z_stream strm = {0}; 365 ret = inflateInit2(&strm, RAW); 366 if (ret != Z_OK) 367 return ret; 368 if (point->bits) 369 INFLATEPRIME(&strm, point->bits, ch >> (8 - point->bits)); 370 inflateSetDictionary(&strm, point->window, WINSIZE); 371 372 // Skip uncompressed bytes until offset reached, then satisfy request. 373 unsigned char input[CHUNK]; 374 unsigned char discard[WINSIZE]; 375 offset -= point->out; // number of bytes to skip to get to offset 376 size_t left = len; // number of bytes left to read after offset 377 do { 378 if (offset) { 379 // Discard up to offset uncompressed bytes. 380 strm.avail_out = offset < WINSIZE ? (unsigned)offset : WINSIZE; 381 strm.next_out = discard; 382 } 383 else { 384 // Uncompress up to left bytes into buf. 385 strm.avail_out = left < UINT_MAX ? (unsigned)left : UINT_MAX; 386 strm.next_out = buf + len - left; 387 } 388 389 // Uncompress, setting got to the number of bytes uncompressed. 390 if (strm.avail_in == 0) { 391 // Assure available input. 392 strm.avail_in = fread(input, 1, CHUNK, in); 393 if (strm.avail_in < CHUNK && ferror(in)) { 394 ret = Z_ERRNO; 395 break; 396 } 397 strm.next_in = input; 398 } 399 unsigned got = strm.avail_out; 400 ret = inflate(&strm, Z_NO_FLUSH); 401 got -= strm.avail_out; 402 403 // Update the appropriate count. 404 if (offset) 405 offset -= got; 406 else 407 left -= got; 408 409 // If we're at the end of a gzip member and there's more to read, 410 // continue to the next gzip member. 411 if (ret == Z_STREAM_END && index->mode == GZIP) { 412 // Discard the gzip trailer. 413 unsigned drop = 8; // length of gzip trailer 414 if (strm.avail_in >= drop) { 415 strm.avail_in -= drop; 416 strm.next_in += drop; 417 } 418 else { 419 // Read and discard the remainder of the gzip trailer. 420 drop -= strm.avail_in; 421 strm.avail_in = 0; 422 do { 423 if (getc(in) == EOF) 424 // The input does not have a complete trailer. 425 return ferror(in) ? Z_ERRNO : Z_BUF_ERROR; 426 } while (--drop); 427 } 428 429 if (strm.avail_in || ungetc(getc(in), in) != EOF) { 430 // There's more after the gzip trailer. Use inflate to skip the 431 // gzip header and resume the raw inflate there. 432 inflateReset2(&strm, GZIP); 433 do { 434 if (strm.avail_in == 0) { 435 strm.avail_in = fread(input, 1, CHUNK, in); 436 if (strm.avail_in < CHUNK && ferror(in)) { 437 ret = Z_ERRNO; 438 break; 439 } 440 strm.next_in = input; 441 } 442 strm.avail_out = WINSIZE; 443 strm.next_out = discard; 444 ret = inflate(&strm, Z_BLOCK); // stop at end of header 445 } while (ret == Z_OK && (strm.data_type & 0x80) == 0); 446 if (ret != Z_OK) 447 break; 448 inflateReset2(&strm, RAW); 449 } 450 } 451 452 // Continue until we have the requested data, the deflate data has 453 // ended, or an error is encountered. 454 } while (ret == Z_OK && left); 455 inflateEnd(&strm); 456 457 // Return the number of uncompressed bytes read into buf, or the error. 458 return ret == Z_OK || ret == Z_STREAM_END ? len - left : ret; 459} 460 461#ifdef TEST 462 463#define SPAN 1048576L // desired distance between access points 464#define LEN 16384 // number of bytes to extract 465 466// Demonstrate the use of deflate_index_build() and deflate_index_extract() by 467// processing the file provided on the command line, and extracting LEN bytes 468// from 2/3rds of the way through the uncompressed output, writing that to 469// stdout. An offset can be provided as the second argument, in which case the 470// data is extracted from there instead. 471int main(int argc, char **argv) 472{ 473 // Open the input file. 474 if (argc < 2 || argc > 3) { 475 fprintf(stderr, "usage: zran file.raw [offset]\n"); 476 return 1; 477 } 478 FILE *in = fopen(argv[1], "rb"); 479 if (in == NULL) { 480 fprintf(stderr, "zran: could not open %s for reading\n", argv[1]); 481 return 1; 482 } 483 484 // Get optional offset. 485 off_t offset = -1; 486 if (argc == 3) { 487 char *end; 488 offset = strtoll(argv[2], &end, 10); 489 if (*end || offset < 0) { 490 fprintf(stderr, "zran: %s is not a valid offset\n", argv[2]); 491 return 1; 492 } 493 } 494 495 // Build index. 496 struct deflate_index *index = NULL; 497 int len = deflate_index_build(in, SPAN, &index); 498 if (len < 0) { 499 fclose(in); 500 switch (len) { 501 case Z_MEM_ERROR: 502 fprintf(stderr, "zran: out of memory\n"); 503 break; 504 case Z_BUF_ERROR: 505 fprintf(stderr, "zran: %s ended prematurely\n", argv[1]); 506 break; 507 case Z_DATA_ERROR: 508 fprintf(stderr, "zran: compressed data error in %s\n", argv[1]); 509 break; 510 case Z_ERRNO: 511 fprintf(stderr, "zran: read error on %s\n", argv[1]); 512 break; 513 default: 514 fprintf(stderr, "zran: error %d while building index\n", len); 515 } 516 return 1; 517 } 518 fprintf(stderr, "zran: built index with %d access points\n", len); 519 520 // Use index by reading some bytes from an arbitrary offset. 521 unsigned char buf[LEN]; 522 if (offset == -1) 523 offset = ((index->length + 1) << 1) / 3; 524 ptrdiff_t got = deflate_index_extract(in, index, offset, buf, LEN); 525 if (got < 0) 526 fprintf(stderr, "zran: extraction failed: %s error\n", 527 got == Z_MEM_ERROR ? "out of memory" : "input corrupted"); 528 else { 529 fwrite(buf, 1, got, stdout); 530 fprintf(stderr, "zran: extracted %ld bytes at %lld\n", got, offset); 531 } 532 533 // Clean up and exit. 534 deflate_index_free(index); 535 fclose(in); 536 return 0; 537} 538 539#endif 540