/* find the given segment and return 0 if found. * Leave the file pointer positioned at the start of the segment. * Return -1 if segment is not found, and leave pointer at the end */ int aff_find_seg(AFFILE *af,const char *segname, uint32_t *arg, size_t *datasize, size_t *segsize) { char next_segment_name[AF_MAX_NAME_LEN]; size_t next_segsize = 0; size_t next_datasize = 0; uint32_t next_arg; /* Try to use the TOC to find the segment in question */ struct aff_toc_mem *adm = aff_toc(af,segname); if(adm){ if(datasize==0 && segsize==0 && arg==0){ /* User was just probing to see if it was present. And it is! */ return 0; } fseeko(af->aseg,adm->offset,SEEK_SET); } else { af_rewind_seg(af); } while(af_probe_next_seg(af,next_segment_name,sizeof(next_segment_name), &next_arg,&next_datasize,&next_segsize,1)==0){ if(strcmp(next_segment_name,segname)==0){ // found the segment! if(datasize) *datasize = next_datasize; if(segsize) *segsize = next_segsize; if(arg) *arg = next_arg; return 0; // return the info } fseeko(af->aseg,next_segsize,SEEK_CUR); // skip the segment } return -1; // couldn't find segment }
static int evd_rewind_seg(AFFILE *af) { struct evd_private *ep = EVD_PRIVATE(af); ep->cur_file = 0; if(ep->num_evfs>0){ return af_rewind_seg(ep->evfs[0]); } return 0; // no files, so nothing to rewind }
/* Rewind all of the segments */ static int afd_rewind_seg(AFFILE *af) { struct afd_private *ap = AFD_PRIVATE(af); ap->cur_file = 0; for(int i=0;i<ap->num_afs;i++){ af_rewind_seg(ap->afs[i]); } return 0; }
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'); }
static PyObject *affile_get_seg_names(affile *self) { PyObject *headers, *tmp; char segname[AF_MAX_NAME_LEN]; af_rewind_seg(self->af); headers = PyList_New(0); while(af_get_next_seg(self->af, segname, sizeof(segname), 0, 0, 0) == 0){ tmp = PyString_FromString(segname); PyList_Append(headers, tmp); Py_DECREF(tmp); } return headers; }
static int afd_get_next_seg(AFFILE *af,char *segname,size_t segname_len,unsigned long *arg, unsigned char *data,size_t *datalen_) { /* See if there are any more in the current segment */ struct afd_private *ap = AFD_PRIVATE(af); while (ap->cur_file < ap->num_afs) { int r = af_get_next_seg(ap->afs[ap->cur_file],segname,segname_len,arg,data,datalen_); if(r!=AF_ERROR_EOF){ // if it is not EOF return r; } ap->cur_file++; // advance to the next file if(ap->cur_file < ap->num_afs){ // rewind it to the beginning af_rewind_seg(ap->afs[ap->cur_file]); } } while(ap->cur_file < ap->num_afs); return AF_ERROR_EOF; // really made it to the end }
/* 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 evd_get_next_seg(AFFILE *af,char *segname,size_t segname_len,unsigned long *arg, unsigned char *data,size_t *datalen_) { /* See if there are any more in the current segment */ struct evd_private *ep = EVD_PRIVATE(af); if(ep->num_evfs==0) return AF_ERROR_EOF; // no files, so we are at the end do { int r = af_get_next_seg(ep->evfs[ep->cur_file],segname,segname_len,arg,data,datalen_); if(r!=AF_ERROR_EOF){ // if it is not EOF return r; } if(ep->cur_file < ep->num_evfs-1){ ep->cur_file++; // go to the next file if there is one if(ep->cur_file < ep->num_evfs){ af_rewind_seg(ep->evfs[ep->cur_file]); // and rewind that file } } } while(ep->cur_file < ep->num_evfs-1); return AF_ERROR_EOF; // really made it to the end }
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; }
/* afm_rewind_seg: * Rewind both the AFF file and the split_raw file(s) */ static int afm_rewind_seg(AFFILE *af) { struct afm_private *ap = AFM_PRIVATE(af); if ( af_rewind_seg(ap->aff) ) return -1; // that's bad return af_rewind_seg(ap->sr); // and rewind the splitraw }
static int aff_update_seg(AFFILE *af, const char *name, uint32_t arg,const u_char *value,uint32_t vallen) { char next_segment_name[AF_MAX_NAME_LEN]; size_t next_segsize = 0; size_t next_datasize = 0; /* if we are updating with a different size, * remember the location and size of the AF_IGNORE segment that * has the smallest size that is >= strlen(name)+vallen */ size_t size_needed = vallen+aff_segment_overhead(name); size_t size_closest = 0; uint64_t loc_closest = 0; struct aff_toc_mem *adm = aff_toc(af,name); if(af_trace) fprintf(af_trace,"aff_update_seg(name=%s,arg=%"PRIu32",vallen=%u)\n",name,arg,vallen); if(adm){ /* Segment is in the TOC; seek to it */ fseeko(af->aseg,adm->offset,SEEK_SET); } else { /* Otherwise, go to the beginning of the file and try to find a suitable hole * TK: This could be made significantly faster by just scanning the TOC for a hole. */ af_rewind_seg(af); // start at the beginning } while(af_probe_next_seg(af,next_segment_name,sizeof(next_segment_name),0,&next_datasize,&next_segsize,1)==0){ /* Remember this information */ uint64_t next_segment_loc = ftello(af->aseg); #ifdef DEBUG2 fprintf(stderr," next_segment_name=%s next_datasize=%d next_segsize=%d next_segment_loc=%qd\n", next_segment_name, next_datasize, next_segsize,next_segment_loc); #endif if(strcmp(next_segment_name,name)==0){ // found the segment if(next_datasize == vallen){ // Does it exactly fit? int r = aff_write_seg(af,name,arg,value,vallen); // Yes, just write in place! return r; } //printf("** Segment '%s' doesn't fit at %qd; invalidating.\n",name,ftello(af->aseg)); aff_write_ignore(af,next_datasize+strlen(name)); /* If we are in random mode, jump back to the beginning of the file. * This does a good job filling in the holes. */ if(af->random_access){ af_rewind_seg(af); continue; } /* Otherwise just go to the end. Experience has shown that sequential access * tends not to generate holes. */ fseeko(af->aseg,(uint64_t)0,SEEK_END); // go to the end of the file break; // and exit this loop } if((next_segment_name[0]==0) && (next_datasize>=size_needed)){ //printf(" >> %d byte blank\n",next_datasize); } /* If this is an AF_IGNORE, see if it is a close match */ if((next_segment_name[0]==AF_IGNORE[0]) && (next_datasize>=size_needed) && ((next_datasize<size_closest || size_closest==0)) && ((next_datasize<1024 && size_needed<1024) || (next_datasize>=1024 && size_needed>=1024))){ size_closest = next_datasize; loc_closest = next_segment_loc; } fseeko(af->aseg,next_segsize,SEEK_CUR); // skip this segment } /* Ready to write */ if(size_closest>0){ /* Yes. Put it here and put a new AF_IGNORE in the space left-over * TODO: If the following space is also an AF_IGNORE, then combine the two. */ //printf("*** Squeezing it in at %qd. name=%s. vallen=%d size_closest=%d\n",loc_closest,name,vallen,size_closest); fseeko(af->aseg,loc_closest,SEEK_SET); // move to the location aff_write_seg(af,name,arg,value,vallen); // write the new segment size_t newsize = size_closest - vallen - aff_segment_overhead(0) - strlen(name); aff_write_ignore(af,newsize); // write the smaller ignore return 0; } /* If we reach here we are positioned at the end of the file. */ /* If the last segment is an ignore, truncate the file before writing */ while(af_truncate_blank(af)==0){ /* Keep truncating until there is nothing left */ } //printf("*** appending '%s' bytes=%d to the end\n",name,vallen); fseeko(af->aseg,0L,SEEK_END); // move back to the end of the file return aff_write_seg(af,name,arg,value,vallen); // just write at the end }