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; }