Beispiel #1
0
static void
g_zlib_decompressor_set_gzheader (GZlibDecompressor *decompressor)
{
  /* On win32, these functions were not exported before 1.2.4 */
#if !defined (G_OS_WIN32) || ZLIB_VERNUM >= 0x1240
  if (decompressor->format != G_ZLIB_COMPRESSOR_FORMAT_GZIP)
    return;

  if (decompressor->header_data != NULL)
    {
      if (decompressor->header_data->file_info)
        g_object_unref (decompressor->header_data->file_info);

      memset (decompressor->header_data, 0, sizeof (HeaderData));
    }
  else
    {
      decompressor->header_data = g_new0 (HeaderData, 1);
    }

  decompressor->header_data->gzheader.name = (Bytef*) &decompressor->header_data->filename;
  /* We keep one byte to guarantee the string is 0-terminated */
  decompressor->header_data->gzheader.name_max = 256;

  if (inflateGetHeader (&decompressor->zstream, &decompressor->header_data->gzheader) != Z_OK)
    g_warning ("unexpected zlib error: %s\n", decompressor->zstream.msg);
#endif /* !G_OS_WIN32 || ZLIB >= 1.2.4 */
}
Beispiel #2
0
/* generic inflate() run, where hex is the hexadecimal input data, what is the
   text to include in an error message, step is how much input data to feed
   inflate() on each call, or zero to feed it all, win is the window bits
   parameter to inflateInit2(), len is the size of the output buffer, and err
   is the error code expected from the first inflate() call (the second
   inflate() call is expected to return Z_STREAM_END).  If win is 47, then
   header information is collected with inflateGetHeader().  If a zlib stream
   is looking for a dictionary, then an empty dictionary is provided.
   inflate() is run until all of the input data is consumed. */
local void inf(char *hex, char *what, unsigned step, int win, unsigned len,
               int err)
{
    int ret;
    unsigned have;
    unsigned char *in, *out;
    z_stream strm, copy;
    gz_header head;

    mem_setup(&strm);
    strm.avail_in = 0;
    strm.next_in = Z_NULL;
    ret = inflateInit2(&strm, win);
    if (ret != Z_OK) {
        mem_done(&strm, what);
        return;
    }
    out = malloc(len);                          assert(out != NULL);
    if (win == 47) {
        head.extra = out;
        head.extra_max = len;
        head.name = out;
        head.name_max = len;
        head.comment = out;
        head.comm_max = len;
        ret = inflateGetHeader(&strm, &head);   assert(ret == Z_OK);
    }
    in = h2b(hex, &have);                       assert(in != NULL);
    if (step == 0 || step > have)
        step = have;
    strm.avail_in = step;
    have -= step;
    strm.next_in = in;
    do {
        strm.avail_out = len;
        strm.next_out = out;
        ret = inflate(&strm, Z_NO_FLUSH);       assert(err == 9 || ret == err);
        if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_NEED_DICT)
            break;
        if (ret == Z_NEED_DICT) {
            ret = inflateSetDictionary(&strm, in, 1);
                                                assert(ret == Z_DATA_ERROR);
            mem_limit(&strm, 1);
            ret = inflateSetDictionary(&strm, out, 0);
                                                assert(ret == Z_MEM_ERROR);
            mem_limit(&strm, 0);
            ((struct inflate_state *)strm.state)->mode = DICT;
            ret = inflateSetDictionary(&strm, out, 0);
                                                assert(ret == Z_OK);
            ret = inflate(&strm, Z_NO_FLUSH);   assert(ret == Z_BUF_ERROR);
        }
        ret = inflateCopy(&copy, &strm);        assert(ret == Z_OK);
        ret = inflateEnd(&copy);                assert(ret == Z_OK);
        err = 9;                        /* don't care next time around */
        have += strm.avail_in;
        strm.avail_in = step > have ? have : step;
        have -= strm.avail_in;
    } while (strm.avail_in);
    free(in);
    free(out);
    ret = inflateReset2(&strm, -8);             assert(ret == Z_OK);
    ret = inflateEnd(&strm);                    assert(ret == Z_OK);
    mem_done(&strm, what);
}
Beispiel #3
0
void *rd_gz_decompress (void *compressed, int compressed_len,
			uint64_t *decompressed_lenp) {
	int pass = 1;
	char *decompressed = NULL;

	/* First pass (1): calculate decompressed size.
	 *                 (pass-1 is skipped if *decompressed_lenp is
	 *                  non-zero).
	 * Second pass (2): perform actual decompression.
	 */

	if (*decompressed_lenp != 0LLU)
		pass++;

	for (; pass <= 2 ; pass++) {
		z_stream strm = {};
		gz_header hdr;
		char buf[512];
		char *p;
		int len;
		int r;
		
		if ((r = inflateInit2(&strm, 15+32)) != Z_OK)
			goto fail;

		strm.next_in = compressed;
		strm.avail_in = compressed_len;

		if ((r = inflateGetHeader(&strm, &hdr)) != Z_OK) {
			inflateEnd(&strm);
			goto fail;
		}

		if (pass == 1) {
			/* Use dummy output buffer */
			p = buf;
			len = sizeof(buf);
		} else {
			/* Use real output buffer */
			p = decompressed;
			len = *decompressed_lenp;
		}

		do {
			strm.next_out = (unsigned char *)p;
			strm.avail_out = len;

			r = inflate(&strm, Z_NO_FLUSH);
			switch  (r) {
			case Z_STREAM_ERROR:
			case Z_NEED_DICT:
			case Z_DATA_ERROR:
			case Z_MEM_ERROR:
				inflateEnd(&strm);
				goto fail;
			}

			p += len - strm.avail_out;
			len -= len - strm.avail_out;

		} while (strm.avail_out == 0 && r != Z_STREAM_END);


		if (pass == 1) {
			*decompressed_lenp = strm.total_out;
			if (!(decompressed = malloc(*decompressed_lenp+1))) {
				inflateEnd(&strm);
				return NULL;
			}
			/* For convenience of the caller we nul-terminate
			 * the buffer. If it happens to be a string there
			 * is no need for extra copies. */
			decompressed[*decompressed_lenp] = '\0';
		}

		inflateEnd(&strm);
	}

	return decompressed;

fail:
	if (decompressed)
		free(decompressed);
	return NULL;
}
Beispiel #4
0
/**
 * FIXME Verbose mode missing yet.
 */
static int do_list_contents(FILE *fp, char *out_f, int list_contents)
{
	int rc;
	struct stat st;
	uint32_t d, crc32, size, compressed_size;
	float ratio = 0.0;
	z_stream strm;
	uint8_t in[4096];
	uint8_t out[4096];
	gz_header head;
	uint8_t extra[64 * 1024];
	uint8_t comment[1024];
	uint8_t name[1024];
	int window_bits = 31;	/* GZIP */
	const char *mon[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
			      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };

	rc = fstat(fileno(fp), &st);
	if (rc != 0)
		return rc;

	memset(&strm, 0, sizeof(strm));
	strm.avail_in = 0;
	strm.next_in = Z_NULL;
	rc = inflateInit2(&strm, window_bits);
	if (Z_OK != rc)
		return rc;

	strm.next_out = out;
	strm.avail_out = sizeof(out);
	strm.next_in = in;
	strm.avail_in = fread(in, 1, sizeof(in), fp);
	if (ferror(fp))
		return Z_ERRNO;

	head.extra = extra;
	head.extra_len = 0;
	head.extra_max = sizeof(extra);

	head.comment = comment;
	head.comm_max = sizeof(comment);

	head.name = name;
	head.name_max = sizeof(name);

	rc = inflateGetHeader(&strm, &head);
	if (Z_OK != rc) {
		fprintf(stderr, "err: Cannot read gz header! rc=%d\n", rc);
		return rc;
	}

	rc = inflate(&strm, Z_BLOCK);
	if (Z_OK != rc) {
		fprintf(stderr, "err: inflate(Z_BLOCK) failed rc=%d\n", rc);
		return rc;
	}

	if (head.done == 0) {
		fprintf(stderr, "err: gzip header not entirely decoded! "
			"total_in=%ld total_out=%ld head.done=%d\n",
			strm.total_in, strm.total_out, head.done);
		return Z_DATA_ERROR;
	}

	rc = fseek(fp, st.st_size - 2 * sizeof(uint32_t), SEEK_SET);
	if (rc != 0)
		return rc;

	rc = fread(&d, sizeof(d), 1, fp);
	if (rc != 1)
		return -1;
	crc32 = __le32_to_cpu(d);

	rc = fread(&d, sizeof(d), 1, fp);
	if (rc != 1)
		return -1;
	size = __le32_to_cpu(d);

	/* Compressed size is total file size reduced by gzip header
	   size and 8 bytes for the gzip trailer. */
	compressed_size = st.st_size - strm.total_in - 8;
	if (size)
		ratio = 100 - (float)compressed_size * 100 / size;

	if (!verbose) {
		fprintf(stderr,
			"         compressed        uncompressed  ratio "
			"uncompressed_name\n"
			"%19lld %19d  %2.2f%% %s\n",
			(long long)st.st_size, size, ratio,
			out_f);
	} else {
		time_t t = time(NULL);
		struct tm *tm = localtime(&t);
		/* (const time_t *)&head.time */

		fprintf(stderr, "method  crc     date  time           "
			"compressed        uncompressed  ratio "
			"uncompressed_name\n"
			"%s %x %s %2d %d:%d %19lld %19d  %2.2f%% %s\n",
			"defla", crc32,
			mon[tm->tm_mon], tm->tm_mday, tm->tm_hour, tm->tm_min,
			(long long)st.st_size, size, ratio,
			out_f);
	}

	if (list_contents > 1)
		do_print_gzip_hdr(&head, stderr);

	return 0;
}