Exemple #1
0
void lzma_test()
{
#if defined(__FreeBSD__) && !defined(__APPLE__)
    _malloc_options = "XARV";
#endif
    //char *fn = "/usr/share/dict/web2";
    const char *fn = "/etc/motd";

    printf("starting up\n");
    FILE *f = fopen(fn,"r");
    if(!f) err(1,"%s",fn);
    
    struct stat st;
    if(fstat(fileno(f),&st)) err(1,"stat");

    /* Allocate memory */
    size_t buflen = st.st_size;
    printf("size=%qd\n",(long long)buflen);
    unsigned char *buf = (unsigned char *)malloc(buflen);
    if(buf==0) errx(1,"malloc");
    if(fread(buf,1,st.st_size,f)!=(size_t)st.st_size) err(1,"read");

    /* Allocate memory for the compressed buffer */
    size_t cbufsize = (int)(buflen*1.05);
    size_t cbuf_actual=0;
    unsigned char *cbuf = (unsigned char *)malloc(cbufsize);

#ifdef USE_LZMA
    lzma_compress(cbuf,&cbufsize,buf,st.st_size,9);
#endif
    printf("cbuf_actual=%d\n",(int)cbuf_actual);

    /* Now try to decompress */
    size_t outbuf_size = buflen*2;
    unsigned char *outbuf = (unsigned char *)malloc(outbuf_size);

#ifdef USE_LZMA
    lzma_uncompress(outbuf,&outbuf_size,cbuf,cbufsize);
#endif
    printf("cbuf[0]=%d\n",cbuf[0]);

    if(memcmp(buf,outbuf,outbuf_size)==0){
	printf("Decompression works!\n");
    }
}
int af_get_page(AFFILE *af,int64_t pagenum,unsigned char *data,size_t *bytes)
{
    unsigned long arg=0;
    size_t page_len=0;

    if (af_trace){
	fprintf(af_trace,"af_get_page(%p,pagenum=%"I64d",buf=%p,bytes=%zu)\n",af,pagenum,data,*bytes);
    }

    /* Find out the size of the segment and if it is compressed or not.
     * If we can't find it with new nomenclature, try the old one...
     */
    int r = af_get_page_raw(af,pagenum,&arg,0,&page_len);
    if(r){
	/* Segment doesn't exist.
	 * If we have been provided with a buffer,
	 * fill buffer with the 'bad segment' flag and return.
	 */
	if (data && (af->openmode&AF_BADBLOCK_FILL)) {
	    for(size_t i = 0;i <= af->image_pagesize - af->image_sectorsize;
		i+= af->image_sectorsize){
		memcpy(data+i,af->badflag,af->image_sectorsize);
		af->bytes_memcpy += af->image_sectorsize;
	    }
	}
	return r;		// segment doesn't exist
    }
       
    /* If no data buffer was provided, just return */
    if(data==0) return 0;

    /* If the segment isn't compressed, just get it*/
    unsigned long pageflag = 0;
    if((arg & AF_PAGE_COMPRESSED)==0){
	int ret = af_get_page_raw(af,pagenum,&pageflag,data,bytes);
	if(*bytes > page_len) *bytes = page_len; // we only read this much
	if(ret!=0) return ret;		// some error happened?
    }
    else {
	/* Allocate memory to hold the compressed segment */
	unsigned char *compressed_data = (unsigned char *)malloc(page_len);
	size_t compressed_data_len = page_len;
	if(compressed_data==0){
	    return -2;			// memory error
	}

	/* Get the data */
	if(af_get_page_raw(af,pagenum,&pageflag,compressed_data,&compressed_data_len)){
	    free(compressed_data);
	    return -3;			// read error
	}

	/* Now uncompress directly into the buffer provided by the caller. */
	int res = -1;			// 0 is success

	switch((pageflag & AF_PAGE_COMP_ALG_MASK)){
	case AF_PAGE_COMP_ALG_ZERO:
	    if(compressed_data_len != 4){
		(*af->error_reporter)("ALG_ZERO compressed data is %d bytes, expected 4.",compressed_data_len);
		break;
	    }
	    memset(data,0,af->image_pagesize);
	    *bytes = ntohl(*(long *)compressed_data);
	    res = 0;			// not very hard to decompress with the ZERO compressor.
	    break;

	case AF_PAGE_COMP_ALG_ZLIB:
	    res = uncompress(data,(uLongf *)bytes,compressed_data,compressed_data_len);
	    switch(res){
	    case Z_OK:
		break;
	    case Z_ERRNO:
		(*af->error_reporter)("Z_ERRNOR decompressing segment %"I64d,pagenum);
	    case Z_STREAM_ERROR:
		(*af->error_reporter)("Z_STREAM_ERROR decompressing segment %"I64d,pagenum);
	    case Z_DATA_ERROR:
		(*af->error_reporter)("Z_DATA_ERROR decompressing segment %"I64d,pagenum);
	    case Z_MEM_ERROR:
		(*af->error_reporter)("Z_MEM_ERROR decompressing segment %"I64d,pagenum);
	    case Z_BUF_ERROR:
		(*af->error_reporter)("Z_BUF_ERROR decompressing segment %"I64d,pagenum);
	    case Z_VERSION_ERROR:
		(*af->error_reporter)("Z_VERSION_ERROR decompressing segment %"I64d,pagenum);
	    default:
		(*af->error_reporter)("uncompress returned an invalid value in get_segment");
	    }
	    break;

#ifdef USE_LZMA
	case AF_PAGE_COMP_ALG_LZMA:
	    res = lzma_uncompress(data,bytes,compressed_data,compressed_data_len);
	    if (af_trace) fprintf(af_trace,"   LZMA decompressed page %"I64d". %zd bytes => %zd bytes\n",
				  pagenum,compressed_data_len,*bytes);
	    switch(res){
	    case 0:break;		// OK
	    case 1:(*af->error_reporter)("LZMA header error decompressing segment %"I64d"\n",pagenum);
		break;
	    case 2:(*af->error_reporter)("LZMA memory error decompressing segment %"I64d"\n",pagenum);
		break;
	    }
	    break;
#endif
	    
	default:
	    (*af->error_reporter)("Unknown compression algorithm 0x%d",
				  pageflag & AF_PAGE_COMP_ALG_MASK);
	    break;
	}

	free(compressed_data);		// don't need this one anymore
	af->pages_decompressed++;
	if(res!=Z_OK) return -1;
    }

    /* If the page size is larger than the sector_size,
     * make sure that the rest of the sector is zeroed, and that the
     * rest after that has the 'bad block' notation.
     */
    if(af->image_pagesize > af->image_sectorsize){
	const int SECTOR_SIZE = af->image_sectorsize;	// for ease of typing
	size_t bytes_left_in_sector = (SECTOR_SIZE - (*bytes % SECTOR_SIZE)) % SECTOR_SIZE;
	for(size_t i=0;i<bytes_left_in_sector;i++){
	    data[*bytes + i] = 0;
	}
	size_t end_of_data = *bytes + bytes_left_in_sector;
	
	/* Now fill to the end of the page... */
	for(size_t i = end_of_data; i <= af->image_pagesize-SECTOR_SIZE; i+=SECTOR_SIZE){
	    memcpy(data+i,af->badflag,SECTOR_SIZE);
	    af->bytes_memcpy += SECTOR_SIZE;
	}
    }
    return 0;
}