decompress.c revision c9431fa1e59a88c2f0abf611f25b97af964449e5
ae115bc77f6fcde83175c75b4206dc2e50747966mrj/*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * CDDL HEADER START
ae115bc77f6fcde83175c75b4206dc2e50747966mrj *
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * The contents of this file are subject to the terms of the
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * Common Development and Distribution License (the "License").
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * You may not use this file except in compliance with the License.
ae115bc77f6fcde83175c75b4206dc2e50747966mrj *
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * or http://www.opensolaris.org/os/licensing.
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * See the License for the specific language governing permissions
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * and limitations under the License.
ae115bc77f6fcde83175c75b4206dc2e50747966mrj *
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * When distributing Covered Code, include this CDDL HEADER in each
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * If applicable, add the following below this CDDL HEADER, with the
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * fields enclosed by brackets "[]" replaced with your own identifying
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * information: Portions Copyright [yyyy] [name of copyright owner]
ae115bc77f6fcde83175c75b4206dc2e50747966mrj *
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * CDDL HEADER END
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj/*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * Use is subject to license terms.
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#pragma ident "%Z%%M% %I% %E% SMI"
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj/*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * Decompression module for stand alone file systems.
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#include <sys/param.h>
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#include <sys/sysmacros.h>
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#include <sys/vnode.h>
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#include <sys/bootvfs.h>
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#include <sys/filep.h>
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#include <zmod/zlib.h>
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#ifdef _BOOT
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#include "../common/util.h"
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#else
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#include <sys/sunddi.h>
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#endif
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#define MAX_DECOMP_BUFS 8
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#define GZIP_ID_BYTE_1 0x1f
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#define GZIP_ID_BYTE_2 0x8b
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#define GZIP_CM_DEFLATE 0x08
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#define SEEKBUFSIZE 8192
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#ifdef _BOOT
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#define dprintf if (cf_debug) printf
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#else
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#define dprintf if (cf_debug) printf
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#endif
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrjextern int bootrd_debug;
ae115bc77f6fcde83175c75b4206dc2e50747966mrjextern void *bkmem_alloc(size_t);
ae115bc77f6fcde83175c75b4206dc2e50747966mrjextern void bkmem_free(void *, size_t);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrjcaddr_t scratch_bufs[MAX_DECOMP_BUFS]; /* array of free scratch mem bufs */
ae115bc77f6fcde83175c75b4206dc2e50747966mrjint decomp_bufcnt; /* total no, of allocated decomp bufs */
ae115bc77f6fcde83175c75b4206dc2e50747966mrjint free_dcomp_bufs; /* no. of free decomp bufs */
ae115bc77f6fcde83175c75b4206dc2e50747966mrjchar seek_scrbuf[SEEKBUFSIZE]; /* buffer for seeking */
ae115bc77f6fcde83175c75b4206dc2e50747966mrjint cf_debug; /* non-zero enables debug prints */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrjvoid *
ae115bc77f6fcde83175c75b4206dc2e50747966mrjcf_alloc(void *opaque, unsigned int items, unsigned int size)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj{
ae115bc77f6fcde83175c75b4206dc2e50747966mrj fileid_t *filep;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj unsigned int nbytes;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj caddr_t ptr;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep = (fileid_t *)opaque;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj nbytes = roundup(items * size, sizeof (long));
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if (nbytes > (DECOMP_BUFSIZE - filep->fi_dcscrused)) {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj ptr = bkmem_alloc(nbytes);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj } else {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj ptr = &filep->fi_dcscrbuf[filep->fi_dcscrused];
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_dcscrused += nbytes;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj }
ae115bc77f6fcde83175c75b4206dc2e50747966mrj bzero(ptr, nbytes);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj return (ptr);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj}
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj/*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * Decompression scratch memory free routine, does nothing since we free
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * the entire scratch area all at once on file close.
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj/* ARGSUSED */
ae115bc77f6fcde83175c75b4206dc2e50747966mrjvoid
ae115bc77f6fcde83175c75b4206dc2e50747966mrjcf_free(void *opaque, void *addr)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj{
ae115bc77f6fcde83175c75b4206dc2e50747966mrj}
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj/*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * Read the first block of the file described by filep and determine if
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * the file is gzip-compressed. If so, the compressed flag will be set
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * in the fileid_t struct pointed to by filep and it will be initialized
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * for doing decompression on reads to the file.
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrjint
ae115bc77f6fcde83175c75b4206dc2e50747966mrjcf_check_compressed(fileid_t *filep)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj{
ae115bc77f6fcde83175c75b4206dc2e50747966mrj unsigned char *filebytes;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj z_stream *zsp;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
9e6e15042fe8eed186bfa123fa6d79d7728f0adesmaybe /*
9e6e15042fe8eed186bfa123fa6d79d7728f0adesmaybe * If the file is not long enough to check for a decompression header
9e6e15042fe8eed186bfa123fa6d79d7728f0adesmaybe * then return not compressed.
9e6e15042fe8eed186bfa123fa6d79d7728f0adesmaybe */
9e6e15042fe8eed186bfa123fa6d79d7728f0adesmaybe if (filep->fi_inode->i_size < 3)
9e6e15042fe8eed186bfa123fa6d79d7728f0adesmaybe return (0);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_offset = 0;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if ((filep->fi_getblock)(filep) == -1)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj return (-1);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_offset = 0;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_count = 0;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_cfoff = 0;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filebytes = (unsigned char *)filep->fi_memp;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if (filebytes[0] != GZIP_ID_BYTE_1 || filebytes[1] != GZIP_ID_BYTE_2 ||
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filebytes[2] != GZIP_CM_DEFLATE)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj return (0); /* not compressed */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_flags |= FI_COMPRESSED;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dprintf("file %s is compressed\n", filep->fi_path);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj /*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * Allocate decompress scratch buffer
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if (free_dcomp_bufs) {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_dcscrbuf = scratch_bufs[--free_dcomp_bufs];
ae115bc77f6fcde83175c75b4206dc2e50747966mrj } else {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_dcscrbuf = bkmem_alloc(DECOMP_BUFSIZE);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj decomp_bufcnt++;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj }
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_dcscrused = 0;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp = bkmem_alloc(sizeof (*zsp));
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_dcstream = zsp;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj /*
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl * Initialize the decompression stream. Adding 16 to the window size
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl * indicates that zlib should expect a gzip header.
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj bzero(zsp, sizeof (*zsp));
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp->opaque = filep;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp->zalloc = cf_alloc;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp->zfree = cf_free;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp->avail_in = 0;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp->next_in = NULL;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp->avail_out = 0;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp->next_out = NULL;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl if (inflateInit2(zsp, MAX_WBITS + 16) != Z_OK) {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl dprintf("inflateInit2() failed\n");
ae115bc77f6fcde83175c75b4206dc2e50747966mrj return (-1);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
ae115bc77f6fcde83175c75b4206dc2e50747966mrj return (0);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj}
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj/*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * If the file described by fileid_t struct at *filep is compressed
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * free any resources associated with the decompression. (decompression
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * buffer, etc.).
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrjvoid
ae115bc77f6fcde83175c75b4206dc2e50747966mrjcf_close(fileid_t *filep)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj{
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if ((filep->fi_flags & FI_COMPRESSED) == 0)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj return;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dprintf("cf_close: %s\n", filep->fi_path);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj (void) inflateEnd(filep->fi_dcstream);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj bkmem_free(filep->fi_dcstream, sizeof (z_stream));
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if (free_dcomp_bufs == MAX_DECOMP_BUFS) {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj bkmem_free(filep->fi_dcscrbuf, DECOMP_BUFSIZE);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj } else {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj scratch_bufs[free_dcomp_bufs++] = filep->fi_dcscrbuf;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj }
ae115bc77f6fcde83175c75b4206dc2e50747966mrj}
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrjvoid
ae115bc77f6fcde83175c75b4206dc2e50747966mrjcf_rewind(fileid_t *filep)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj{
ae115bc77f6fcde83175c75b4206dc2e50747966mrj z_stream *zsp;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dprintf("cf_rewind: %s\n", filep->fi_path);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp = filep->fi_dcstream;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp->avail_in = 0;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp->next_in = NULL;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj (void) inflateReset(zsp);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_cfoff = 0;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj}
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#define FLG_FHCRC 0x02 /* crc field present */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#define FLG_FEXTRA 0x04 /* "extra" field present */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#define FLG_FNAME 0x08 /* file name field present */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj#define FLG_FCOMMENT 0x10 /* comment field present */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj/*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * Read at the current uncompressed offset from the compressed file described
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * by *filep. Will return decompressed data.
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrjint
ae115bc77f6fcde83175c75b4206dc2e50747966mrjcf_read(fileid_t *filep, caddr_t buf, size_t count)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj{
ae115bc77f6fcde83175c75b4206dc2e50747966mrj z_stream *zsp;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj struct inode *ip;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj int err = Z_OK;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl int infbytes;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj off_t soff;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj caddr_t smemp;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dprintf("cf_read: %s ", filep->fi_path);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dprintf("%lx bytes\n", count);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp = filep->fi_dcstream;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj ip = filep->fi_inode;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dprintf(" reading at offset %lx\n", zsp->total_out);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp->next_out = (unsigned char *)buf;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp->avail_out = count;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj while (zsp->avail_out != 0) {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if (zsp->avail_in == 0 && filep->fi_cfoff < ip->i_size) {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj /*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * read a block of the file to inflate
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj soff = filep->fi_offset;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj smemp = filep->fi_memp;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_memp = NULL;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_offset = filep->fi_cfoff;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_count = 0;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if ((*filep->fi_getblock)(filep) == -1)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj return (-1);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_offset = soff;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp->next_in = (unsigned char *)filep->fi_memp;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp->avail_in = filep->fi_count;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_memp = smemp;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_cfoff += filep->fi_count;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj }
ae115bc77f6fcde83175c75b4206dc2e50747966mrj infbytes = zsp->avail_out;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dprintf("attempting inflate of %x bytes to buf at: %lx\n",
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp->avail_out, (unsigned long)zsp->next_out);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj err = inflate(zsp, Z_NO_FLUSH);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj infbytes -= zsp->avail_out;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dprintf("inflated %x bytes, errcode=%d\n", infbytes, err);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj /*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * break out if we hit end of the compressed file
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * or the end of the compressed byte stream
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if (filep->fi_cfoff >= ip->i_size || err == Z_STREAM_END)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj break;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj }
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dprintf("cf_read: returned %lx bytes\n", count - zsp->avail_out);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj return (count - zsp->avail_out);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj}
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj/*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * Seek to the location specified by addr
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrjvoid
ae115bc77f6fcde83175c75b4206dc2e50747966mrjcf_seek(fileid_t *filep, off_t addr, int whence)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj{
ae115bc77f6fcde83175c75b4206dc2e50747966mrj z_stream *zsp;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj int readsz;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dprintf("cf_seek: %s ", filep->fi_path);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj dprintf("to %lx\n", addr);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj zsp = filep->fi_dcstream;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if (whence == SEEK_CUR)
ae115bc77f6fcde83175c75b4206dc2e50747966mrj addr += zsp->total_out;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj /*
ae115bc77f6fcde83175c75b4206dc2e50747966mrj * To seek backwards, must rewind and seek forwards
ae115bc77f6fcde83175c75b4206dc2e50747966mrj */
ae115bc77f6fcde83175c75b4206dc2e50747966mrj if (addr < zsp->total_out) {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj cf_rewind(filep);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj filep->fi_offset = 0;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj } else {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj addr -= zsp->total_out;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj }
ae115bc77f6fcde83175c75b4206dc2e50747966mrj while (addr > 0) {
ae115bc77f6fcde83175c75b4206dc2e50747966mrj readsz = MIN(addr, SEEKBUFSIZE);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj (void) cf_read(filep, seek_scrbuf, readsz);
ae115bc77f6fcde83175c75b4206dc2e50747966mrj addr -= readsz;
ae115bc77f6fcde83175c75b4206dc2e50747966mrj }
ae115bc77f6fcde83175c75b4206dc2e50747966mrj}