static int aff_vstat(AFFILE *af,struct af_vnode_info *vni) { memset(vni,0,sizeof(*vni)); // clear it vni->imagesize = af->image_size; // we can just return this vni->pagesize = af->image_pagesize; vni->supports_compression = 1; vni->has_pages = 1; vni->supports_metadata = 1; vni->cannot_decrypt = af_cannot_decrypt(af) ? 1 : 0; /* Check for an encrypted page */ if(af->toc){ for(int i=0;i<af->toc_count;i++){ if(af->toc[i].name){ bool is_page = false; vni->segment_count_total++; if(af_segname_page_number(af->toc[i].name)>=0){ vni->page_count_total++; is_page = true; } if(af_is_encrypted_segment(af->toc[i].name)){ vni->segment_count_encrypted++; if(is_page) vni->page_count_encrypted++; } if(af_is_signature_segment(af->toc[i].name)){ vni->segment_count_signed++; } } } } return 0; }
/* * afm_get_seg: * If it is a page segment, satisfy it from the splitraw, * otherwise from the aff file. */ static int afm_get_seg(AFFILE *af,const char *name,uint32_t *arg,unsigned char *data,size_t *datalen) { struct afm_private *ap = AFM_PRIVATE(af); int64_t page_num = af_segname_page_number(name); if(page_num>=0) return af_get_seg(ap->sr,name,arg,data,datalen); return af_get_seg(ap->aff,name,arg,data,datalen); }
/* * afm_del_seg: * If it is a page segment, generate an error. * otherwise from the aff file. */ static int afm_del_seg(AFFILE *af,const char *segname) { struct afm_private *ap = AFM_PRIVATE(af); int64_t page_num = af_segname_page_number(segname); if(page_num>=0){ errno = ENOTSUP; return -1; } return af_del_seg(ap->aff,segname); }
/* For afm_update_seg, hand off page updates to the split_raw implementation * and metadata updates to the AFF implementation. */ static int afm_update_seg(AFFILE *af, const char *name, uint32_t arg,const u_char *value,uint32_t vallen) { struct afm_private *ap = AFM_PRIVATE(af); int64_t page_num = af_segname_page_number(name); // <0 means update metadata if(page_num<0){ return af_update_seg(ap->aff,name,arg,value,vallen); } return af_update_seg(ap->sr,name,arg,value,vallen); }
int64_t af_segname_hash_page_number(const char *name,char *hash,int hashlen) { const char *cc = strchr((char *)name,'_'); if(!cc) return -1; // not possibly correct char *copy = strdup(name); // get a local copy char *dd = strchr(copy,'_'); if(!dd){free(copy);return -1;} // really weird; shouldn't happen *dd++ = '\000'; // terminate at _ if(strcmp(dd,"md5")!=0){free(copy);return -1;} // not a valid hash int64_t page = af_segname_page_number(copy); if(page<0){free(copy);return -1;} // wasn't what we wanted strlcpy(hash,dd,hashlen); return page; }
void affstats(const char *fname) { AFFILE *af = af_open(fname,O_RDONLY,0); if(!af) af_err(1,"af_open(%s)",fname); printf("%s\t",fname); uint32_t segsize=0; int64_t imagesize=0; int64_t blanksectors=0; int64_t badsectors=0; af_get_segq(af,AF_IMAGESIZE,&imagesize); if(af_get_seg(af,AF_PAGESIZE,&segsize,0,0)){ af_get_seg(af,AF_SEGSIZE_D,&segsize,0,0); // check for oldstype } af_get_segq(af,AF_BADSECTORS,&badsectors); af_get_segq(af,AF_BLANKSECTORS,&blanksectors); print_size(imagesize); printf("\t"); fflush(stdout); int64_t compressed_bytes = 0; int64_t uncompressed_bytes = 0; /* Now read through all of the segments and count the number of * data segments. We know the uncompressed size... */ af_rewind_seg(af); char segname[AF_MAX_NAME_LEN+1]; size_t datalen; while(af_get_next_seg(af,segname,sizeof(segname),0,0,&datalen)==0){ int64_t page_num = af_segname_page_number(segname); if(page_num>=0){ compressed_bytes += datalen; uncompressed_bytes += segsize; } } if(uncompressed_bytes > imagesize) uncompressed_bytes = imagesize; print_size(compressed_bytes); printf("\t"); print_size(uncompressed_bytes); printf(" %" I64d " %" I64d,blanksectors,badsectors); putchar('\n'); }
int64_t af_segname_hash_page_number(const char *name,char *hash,int hashlen) { char copy[AF_MAX_NAME_LEN]; const char *cc = strchr((char *)name,'_'); if(!cc) return -1; // not possibly correct strlcpy(copy,name,sizeof(copy)); char *dd = strchr(copy,'_'); if(!dd) return -1; // really weird; shouldn't happen *dd++ = '\000'; // terminate at _ if(strcmp(dd,"md5")!=0) return -1; // not a valid hash int64_t page = af_segname_page_number(copy); if(page<0) return -1; // wasn't what we wanted strlcpy(hash,dd,hashlen); return page; }
int raw_update_seg(AFFILE *af, const char *name, unsigned long arg,const void *value,unsigned int vallen,int append) { struct raw_private *rp = RAW_PRIVATE(af); /* Simple implementation; only updates data segments */ int64 pagenum = af_segname_page_number(name); if(pagenum<0){ errno = ENOTSUP; return -1; // not a segment number } int64 pos = pagenum * af->image_pagesize; // where we are to start reading fseeko(rp->raw,pos,SEEK_SET); if(fwrite(value,vallen,1,rp->raw)==1){ return 0; } return -1; // some kind of error... }
/* af_read_sizes: * Get the page sizes if they are set in the file. */ void af_read_sizes(AFFILE *af) { af_get_seg(af,AF_SECTORSIZE,&af->image_sectorsize,0,0); if(af->image_sectorsize==0) af->image_sectorsize = 512; // reasonable default if(af_get_seg(af,AF_PAGESIZE,&af->image_pagesize,0,0)){ af_get_seg(af,AF_SEGSIZE_D,&af->image_pagesize,0,0); // try old name } /* Read the badflag if it is present */ size_t sectorsize = af->image_sectorsize; if(af->badflag==0) af->badflag = (unsigned char *)malloc(sectorsize); if(af_get_seg(af,AF_BADFLAG,0,af->badflag,(size_t *)§orsize)==0){ af->badflag_set = 1; } /* Read the image file segment if it is present. * If it isn't, scan through the disk image to figure out the size of the disk image. */ if(af_get_segq(af,AF_IMAGESIZE,(int64_t *)&af->image_size)){ /* Calculate the imagesize by scanning all of the pages that are in * the disk image and finding the highest page number. * Then read that page to find the last allocated byte. */ char segname[AF_MAX_NAME_LEN]; size_t datalen = 0; af_rewind_seg(af); // start at the beginning int64_t highest_page_number = 0; while(af_get_next_seg(af,segname,sizeof(segname),0,0,&datalen)==0){ if(segname[0]==0) continue; // ignore sector int64_t pagenum = af_segname_page_number(segname); if(pagenum > highest_page_number) highest_page_number = pagenum; } size_t highest_page_len = 0; if(af_get_page(af,highest_page_number,0,&highest_page_len)==0){ af->image_size = af->image_pagesize * highest_page_number + highest_page_len; } } af->image_size_in_file = af->image_size; }
static int raw_get_seg(AFFILE *af,const char *name, unsigned long *arg,unsigned char *data,size_t *datalen) { struct raw_private *rp = RAW_PRIVATE(af); /* Right now, this only supports page segments */ int64 segnum = af_segname_page_number(name); if(segnum<0) return -1; // unknown segment number fflush(rp->raw); // make sure that any buffers are flushed int64 pos = (int64)segnum * af->image_pagesize; // where we are to start reading int64 bytes_left = af->image_size - pos; // how many bytes left in the file int bytes_to_read = af->image_pagesize; // copy this many bytes, unless if(bytes_to_read > bytes_left) bytes_to_read = bytes_left; // only this much is left if(arg) *arg = 0; // arg is always 0 if(datalen){ if(*datalen==0 && data==0){ // asked for 0 bytes, so give the actual size *datalen = bytes_to_read; return 0; } if(*datalen < (unsigned)bytes_to_read){ *datalen = bytes_to_read; return AF_ERROR_DATASMALL; } } if(data){ fseeko(rp->raw,pos,SEEK_SET); int bytes_read = fread(data,1,bytes_to_read,rp->raw); if(bytes_read==bytes_to_read){ if(datalen) *datalen = bytes_read; return 0; } return -1; // some kind of EOF? } return 0; // no problems! }
static int raw_get_seg(AFFILE *af,const char *name, uint32_t *arg,unsigned char *data,size_t *datalen) { struct raw_private *rp = RAW_PRIVATE(af); int64_t segnum = af_segname_page_number(name); if(segnum<0){ /* See if PAGESIZE or IMAGESIZE is being requested; we can fake those */ if(strcmp(name,AF_PAGESIZE)==0){ if(arg) *arg = af->image_pagesize; if(datalen) *datalen = 0; return 0; } if(strcmp(name,AF_IMAGESIZE)==0){ struct aff_quad q; if(data && *datalen>=8){ q.low = htonl((uint32_t)(af->image_size & 0xffffffff)); q.high = htonl((uint32_t)(af->image_size >> 32)); memcpy(data,&q,8); *datalen = 8; } return 0; } if(strcmp(name,AF_SECTORSIZE)==0){ if(arg) *arg = af->image_sectorsize; if(datalen) *datalen = 0; return 0; } if(strcmp(name,AF_DEVICE_SECTORS)==0){ int64_t devicesectors = af->image_size / af->image_sectorsize; struct aff_quad q; if(data && *datalen>=8){ q.low = htonl((uint32_t)(devicesectors & 0xffffffff)); q.high = htonl((uint32_t)(devicesectors >> 32)); memcpy(data,&q,8); *datalen = 8; }
Attributes AffNode::_attributes() { Attributes vmap; struct af_vnode_info vni; unsigned long total_segs = 0; unsigned long total_pages = 0; unsigned long total_hashes = 0; unsigned long total_signatures =0; unsigned long total_nulls = 0; vmap["orignal path"] = new Variant(this->originalPath); AFFILE* affile = af_open(this->originalPath.c_str(), O_RDONLY, 0); if (affile) { vmap["dump type"] = new Variant(std::string(af_identify_file_name(this->originalPath.c_str(), 1))); if (af_vstat(affile, &vni) == 0) { if (vni.segment_count_encrypted > 0 || vni.segment_count_signed > 0) { vmap["encrypted segments"] = new Variant(vni.segment_count_encrypted); vmap["signed segments"] = new Variant(vni.segment_count_signed); } vector <string> segments; char segname[AF_MAX_NAME_LEN]; af_rewind_seg(affile); int64_t total_datalen = 0; size_t total_segname_len = 0; size_t datalen = 0; int aes_segs=0; while(af_get_next_seg(affile, segname, sizeof(segname), 0, 0, &datalen)==0) { total_segs++; total_datalen += datalen; total_segname_len += strlen(segname); if(segname[0]==0) total_nulls++; char hash[64]; int64_t page_num = af_segname_page_number(segname); int64_t hash_num = af_segname_hash_page_number(segname,hash,sizeof(hash)); if(page_num>=0) total_pages++; if(hash_num>=0) total_hashes++; if(strstr(segname,AF_SIG256_SUFFIX)) total_signatures++; if(strstr(segname,AF_AES256_SUFFIX)) aes_segs++; if((page_num>=0||hash_num>=0)) continue; if(af_is_encrypted_segment(segname)) continue; this->addSegmentAttribute(&vmap, affile, segname); } vmap["Total segments"] = new Variant((uint64_t)total_segs); vmap["Total segments real"] = new Variant((uint64_t)(total_segs - total_nulls)); if (aes_segs) vmap["Encrypted segments"] = new Variant(aes_segs); vmap["Page segments"] = new Variant((uint64_t)total_pages); vmap["Hash segments"] = new Variant((uint64_t)total_hashes); vmap["Signature segments"] = new Variant((uint64_t)total_signatures); vmap["Null segments"] = new Variant((uint64_t)total_nulls); vmap["Total data bytes"] = new Variant((uint64_t)total_datalen); } } af_close(affile); return vmap; }