⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vnode_aff.cpp

📁 sleuthit-2.09 一个磁盘的工具集
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * vnode_aff.cpp: *  * Functions for the manipulation of AFF files... */#include "config.h"#include "afflib.h"#include "afflib_i.h"#include "vnode_aff.h"#include "aff_db.h"#define xstr(s) str(s)#define str(s) #s/* Low-level functions for putting * af_put_segv --- put a segment with an argument (also useful for putting numbers) * af_put_segq --- put a quadword, useful for putting 8-byte values. */static int	aff_ignore_overhead();	static int      aff_write_ignore(AFFILE *af,unsigned long bytes);static int	aff_write_seg(AFFILE *af,const char *name,unsigned long arg, const void *value,unsigned int vallen); static int	af_make_badflag(AFFILE *af);	// creates a badflag and puts itstatic int	aff_get_seg(AFFILE *af,const char *name,unsigned long *arg,unsigned char *data,size_t *datalen);static int	aff_get_next_seg(AFFILE *af,char *segname,size_t segname_len,				 unsigned long *arg, unsigned char *data, size_t *datalen);/* af_write_ignore: * write an AF_IGNORE structure of a given size. */static int aff_ignore_overhead(){    return sizeof(struct af_segment_head)+sizeof(struct af_segment_tail);}static int aff_write_ignore(AFFILE *af,unsigned long bytes){    unsigned char *invalidate_data = (unsigned char *)calloc(bytes,1);    aff_write_seg(af,AF_IGNORE,0,invalidate_data,bytes); // overwrite with NULLs    free(invalidate_data);    return(0);}/* aff_write_seg: * put the given named segment at the current position in the file. * Return 0 for success, -1 for failure (probably disk full?) * This is the only place where a segment actually gets written */int aff_write_seg(AFFILE *af, const char *segname,unsigned long arg,const void *data,unsigned int datalen){    //printf("aff_write_seg(%s) af->aseg=%p\n",segname,af->aseg);    struct af_segment_head segh;    struct af_segment_tail segt;    if(af->debug){      (*af->error_reporter)("aff_write_seg(" POINTER_FMT ",'%s',%lu,data=" POINTER_FMT ",datalen=%u)",			    af,segname,arg,data,datalen);    }    assert(sizeof(segh)==16);    assert(sizeof(segt)==8);    /* If the last command was not a probe (so we know where we are), and     * we are not at the end of the file, something is very wrong.     */    unsigned int segname_len = strlen(segname);    strcpy(segh.magic,AF_SEGHEAD);    segh.name_len = htonl(segname_len);    segh.data_len = htonl(datalen);    segh.flag      = htonl(arg);    strcpy(segt.magic,AF_SEGTAIL);    segt.segment_len = htonl(sizeof(segh)+segname_len + datalen + sizeof(segt));        int64 offset = ftello(af->aseg);        af_toc_insert(af,segname,offset);#ifdef DEBUG       {	fprintf(stderr,"aff_write_segv: putting segment %s (datalen=%d) offset=%qd\n",		segname,datalen,o);    }#endif    if(fwrite(&segh,sizeof(segh),1,af->aseg)!=1) return -10;    if(fwrite(segname,1,segname_len,af->aseg)!=segname_len) return -11;    if(fwrite(data,1,datalen,af->aseg)!=datalen) return -12;    if(fwrite(&segt,sizeof(segt),1,af->aseg)!=1) return -13;    fflush(af->aseg);			// make sure it is on the disk    return 0;}/**************************************************************** *** low-level routines for reading  ****************************************************************//* aff_get_segment: * Get the named segment, using the toc cache. * If there is no cache,  *  -  If the requested segment is the next segment, just get it. *  -  Otherwise go to the beginning and scan for it. */static int aff_get_seg(AFFILE *af,const char *name,		       unsigned long *arg,unsigned char *data,size_t *datalen){    char next[AF_MAX_NAME_LEN];    int first = 1;    size_t segsize = 0;    /* If the segment is in the directory, then seek the file to that location.     * Otherwise, we'll probe the next segment, and if it is not there,     * we will rewind to the beginning and go to the end.     */    struct af_toc_mem *adm = af_toc(af,name);    if(adm){	fseeko(af->aseg,adm->offset,SEEK_SET);	int ret = af_get_next_seg(af,next,sizeof(next),arg,data,datalen);	assert(strcmp(next,name)==0);	// hopefully this is what they asked for	return ret;    }    /* 2007-05-30: slg - if it is not in the TOC and we are using the TOC,     * then it is not in the file. Just return.     */    if(af->disable_toc==0) return -1;    /* This code searches through the file.     * This is what you have to do if there is no ToC.     * It's slow.*/    do {	int r = af_probe_next_seg(af,next,sizeof(next),0,0,&segsize,1);	if(r==0 && strcmp(next,name)==0){	// found the segment!	    int ret = af_get_next_seg(af,next,sizeof(next),arg,data,datalen);	    assert(strcmp(next,name)==0);	// hopefully it's still the same!	    return ret;	}	if(first){			// okay, should we try to rewind?	    af_rewind_seg(af);	    first = 0;			// no longer the first time through	    continue;	}	if(r!=0){			// did we encounter an error reading?	    break;			// yes	}	fseeko(af->aseg,segsize,SEEK_CUR); // seek to next segment    } while(1);    return -1;				// couldn't find segment}/**************************************************************** *** Get the next segment. *** data must not be freed. *** *datalen_ is size of data; *datalen_ is modified to amount of segment *** if no data is specified, then just seek past it... *** Returns 0 on success,  *** -1 on end of file. (AF_ERROR_EOF) *** -2 if *data is not large enough to hold the segment (AF_ERROR_DATASMALL) *** -3 af file is corrupt; no tail (AF_ERROR_CORRUPT) ****************************************************************/static int aff_get_next_seg(AFFILE *af,char *segname,size_t segname_len,unsigned long *arg,			unsigned char *data,size_t *datalen_){    if(!af->aseg){	snprintf(af->error_str,sizeof(af->error_str),"af_get_next_segv only works with aff files");	return AF_ERROR_INVALID_ARG;    }    int64 start = ftello(af->aseg);    size_t data_len;    int r = af_probe_next_seg(af,segname,segname_len,arg,&data_len,0,0);    if(r<0) return r;			// propigate error code    if(data){				/* Read the data? */	if(datalen_ == 0){	    snprintf(af->error_str,sizeof(af->error_str),"af_get_next_seg: data provided but datalen is NULL");	    return AF_ERROR_INVALID_ARG;	}	size_t read_size = data_len<=*datalen_ ? data_len : *datalen_;	if(fread(data,1,read_size,af->aseg)!=read_size){	    snprintf(af->error_str,sizeof(af->error_str),"af_get_next_segv: EOF on reading segment? File is corrupt.");	    return AF_ERROR_SEGH;	}	if(data_len > *datalen_){	    /* Read was incomplete;	     * go back to the beginning of the segment and return	     * the incomplete code.	     */	    fseeko(af->aseg,start,SEEK_SET);	// go back	    return AF_ERROR_DATASMALL;	}    } else {	fseeko(af->aseg,data_len,SEEK_CUR); // skip past the data    }    if(datalen_) *datalen_ = data_len;    /* Now read the tail */    struct af_segment_tail segt;    if(fread(&segt,sizeof(segt),1,af->aseg)!=1){	snprintf(af->error_str,sizeof(af->error_str),"af_get_next_segv: end of file reading segment tail...");	return AF_ERROR_TAIL;    }    /* Validate tail */    unsigned long stl = ntohl(segt.segment_len);    unsigned long calculated_segment_len =	sizeof(struct af_segment_head)	+ strlen(segname)	+ data_len + sizeof(struct af_segment_tail);    if(strcmp(segt.magic,AF_SEGTAIL)!=0){	snprintf(af->error_str,sizeof(af->error_str),"af_get_next_segv: AF file corrupt. No tail!");	return AF_ERROR_TAIL;    }    if(stl != calculated_segment_len){	snprintf(af->error_str,sizeof(af->error_str),"af_get_next_segv: AF file corrupt (%lu!=%lu)!",		 stl,calculated_segment_len);	return AF_ERROR_TAIL;    }    return 0;}static int aff_rewind_seg(AFFILE *af){    fseeko(af->aseg,sizeof(struct af_head),SEEK_SET); // go to the beginning    return 0;}/**************************************************************** *** Update functions ****************************************************************//* * af_update_seg: * Update the given named segment with the new value. * if "append" is false, don't append if it can't be found.  * if "append" is true and the named segment can't be found, append it. */int aff_update_seg(AFFILE *af, const char *name,		    unsigned long arg,const void *value,unsigned int 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 = strlen(name)+vallen+aff_ignore_overhead();    size_t size_closest = 0;    uint64         loc_closest = 0;    struct af_toc_mem *adm = af_toc(af,name);       #ifdef DEBUG    fprintf(stderr,"aff_update_seg(name=%s,arg=%lu,vallen=%u)\n",name,arg,vallen);#endif    /* Is the last segment an ignore? */    if(adm){	fseeko(af->aseg,adm->offset,SEEK_SET);    }    else {	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){	uint64 next_segment_loc = ftello(af->aseg);#ifdef DEBUG	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!	    /* Okay. Is there room to fit it here? */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -