📄 vnode_aff.cpp
字号:
if(next_datasize == vallen){ /* We can just write in place! */ int r = aff_write_seg(af,name,arg,value,vallen); return r; } /* Invalidate this segment and continue scanning */ uint64 loc_invalidated = next_segment_loc; // remember where this is aff_write_ignore(af,next_datasize+strlen(name)); uint64 loc_before_seek = ftello(af->aseg); // before the seek fseeko(af->aseg,(uint64)0,SEEK_END); // go to the end of the file uint64 pos_eof = ftello(af->aseg); if(pos_eof == loc_before_seek){ /* Apparently I didn't move at all with the seek. * If the segment being written is larger than the segment being replaced, * we can just backspace. */ if(next_segsize < vallen){ //fprintf(stderr," *** seeking to %qd\n",loc_invalidated); fseeko(af->aseg,loc_invalidated,SEEK_SET); } } break; // and exit this loop } /* If this is an AF_IGNORE, see if it is a close match */ if(next_segment_name[0]==AF_IGNORE[0]){ if(next_datasize>=size_needed && ((next_datasize<size_closest || size_closest==0))){ size_closest = next_datasize; loc_closest = next_segment_loc; } } fseeko(af->aseg,next_segsize,SEEK_CUR); // skip this segment } /* Ready to write */ //fprintf(stderr,"size_closest=%d\n",size_closest); 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. */#ifdef DEBUG fprintf(stderr,"size_closest=%d\n",size_closest); fprintf(stderr,"loc_closest=%qd\n",loc_closest); fprintf(stderr,"*** Squeezing it in at %qd. name=%s. vallen=%d\n",loc_closest,name,vallen);#endif fseeko(af->aseg,loc_closest,SEEK_SET); // move to the location aff_write_seg(af,name,arg,value,vallen); // write the new segment int newsize = size_closest - vallen - aff_ignore_overhead() - strlen(name); aff_write_ignore(af,newsize); // write the smaller ignore return 0; } /* Just write to the end of the file */ return aff_write_seg(af,name,arg,value,vallen); // just write at the end}/* Delete the first occurance of the named segment. * Special case code: See if the segment being deleted * is the last segment. If it is, truncate the file... * This handles the case of AF_DIRECTORY and possibly other cases * as well... */static int aff_del_seg(AFFILE *af,const char *segname){ af_toc_del(af,segname); // remove it from the directory /* Find out if the last segment is the one we are deleting; * If so, we can just truncate the file. * Note: we can't do this on Windows because _chsize(), * the equivillent of ftruncate(), takes a 32-bit argument. */#ifndef WIN32 char last_segname[AF_MAX_NAME_LEN]; int64 last_pos; af_last_seg(af,last_segname,sizeof(last_segname),&last_pos); if(strcmp(segname,last_segname)==0){ fflush(af->aseg); // flush any ouput ftruncate(fileno(af->aseg),last_pos); // make the file shorter return 0; }#endif size_t datasize=0,segsize=0; if(aff_find_seg(af,segname,0,&datasize,&segsize)!=0){ return -1; // nothing to delete? } /* Now wipe it out */ size_t ignore_size = datasize+strlen(segname); aff_write_ignore(af,ignore_size); return 0;}#ifdef HAVE_OPENSSL_RAND_H#include <openssl/rand.h>#endif/* * af_make_badflag: * Create a randomized bag flag and * leave an empty segment of how many badsectors there are * in the image... */int af_make_badflag(AFFILE *af){#ifdef HAVE_OPENSSL_RAND_H RAND_pseudo_bytes(af->badflag,af->image_sectorsize); strcpy((char *)af->badflag,"BAD SECTOR");#else for(int i=0;i<af->image_sectorsize;i++){ af->badflag[i] = rand() & 0xff; }#endif af->badflag_set = 1; if(af_update_seg(af,AF_BADFLAG,0,af->badflag,af->image_sectorsize)){ return -1; } if(af_update_segq(af,AF_BADSECTORS,0)){ return -1; } return 0;}/* aff_create: * af is an empty file that is being set up. */static int aff_create(AFFILE *af){ fwrite(AF_HEADER,1,8,af->aseg); // writes the header af_toc_build(af); // build the toc (will be pretty small) af_make_badflag(af); // writes the flag for bad blocks char *version = xstr(PACKAGE_VERSION); af_update_seg(af,AF_AFFLIB_VERSION,0,version,strlen(version)); #ifdef HAVE_GETPROGNAME const char *progname = getprogname(); if(af_update_seg(af,AF_CREATOR,0,progname,strlen(progname))) return -1;#endif if(af_update_seg(af,AF_AFF_FILE_TYPE,0,"AFF",3)) return -1; return 0;}/**************************************************************** *** User-visible functions. ****************************************************************/static int aff_open(AFFILE *af){ int fd = open(af->fname,af->openflags | O_BINARY,af->openmode); if(fd<0){ // couldn't open return -1; } af->compression_type = AF_COMPRESSION_ALG_ZLIB; // default af->compression_level = Z_DEFAULT_COMPRESSION; /* Open the FILE for the AFFILE */ char strflag[8]; strcpy(strflag,"rb"); // we have to be able to read if(af->openflags & O_RDWR) strcpy(strflag,"w+b"); af->aseg = fdopen(fd,strflag); if(!af->aseg){ (*af->error_reporter)("fdopen(%d,%s)",fd,strflag); return -1; } /* Get file size */ struct stat sb; if(fstat(fd,&sb)){ (*af->error_reporter)("aff_open: fstat(%s): ",af->fname); // this should not happen return -1; } /* If file is empty, then put out an AFF header, badflag, and AFF version */ if(sb.st_size==0){ return aff_create(af); } /* We are opening an existing file. Verify once more than it is an AFF file * and skip past the header... */ char buf[8]; if(fread(buf,sizeof(buf),1,af->aseg)!=1){ /* Hm. End of file. That shouldn't happen here. */ (*af->error_reporter)("aff_open: couldn't read AFF header on existing file?"); return -1; // should not happen } if(strcmp(buf,AF_HEADER)!=0){ buf[7] = 0; (*af->error_reporter)("aff_open: %s is not an AFF file (header=%s)\n", af->fname,buf); return -1; } /* File has been validated */ if(af_toc_build(af)) return -1; // build the TOC return 0; // everything must be okay.}static bool last4_is_aff(const char *filename){ if(strlen(filename)>4){ const char *last4 = filename+strlen(filename)-4; if(strcasecmp(last4,".aff")==0) return 1; } return 0;}/* Return 1 if a file is an AFF file */static int aff_identify_file(const char *filename,int exists){ if(exists && access(filename,R_OK)!=0) return 0; // needs to exist and it doesn't int fd = open(filename,O_RDONLY | O_BINARY); if(fd>0){ int len = strlen(AF_HEADER)+1; char buf[64]; int r = read(fd,buf,len); close(fd); if(r==len){ // if I could read the header if(strcmp(buf,AF_HEADER)==0) return 1; // must be an AFF file return 0; // not an AFF file } /* If it is a zero-length file and the file extension ends AFF, * then let it be an AFF file... */ if(r==0 && last4_is_aff(filename)) return 1; return 0; // must not be an aff file } /* File doesn't exist. Is this an AFF name? */ if(af_ext_is(filename,"aff")) return 1; return 0;}/* * aff_close: * If the imagesize changed, write out a new value. */static int aff_close(AFFILE *af){ fclose(af->aseg); return 0;}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; return 0;}struct af_vnode vnode_aff = { AF_IDENTIFY_AFF, AF_VNODE_TYPE_PRIMITIVE|AF_VNODE_TYPE_RELIABLE, "AFF", aff_identify_file, aff_open, aff_close, aff_vstat, aff_get_seg, aff_get_next_seg, aff_rewind_seg, aff_update_seg, aff_del_seg, 0, // read; keep 0 0 // write};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -