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

📄 vnode_afd.cpp

📁 sleuthit-2.09 一个磁盘的工具集
💻 CPP
字号:
/* * vnode_aff.cpp: *  * Functions for the manipulation of AFF files... */#include "config.h"#include "afflib.h"#include "afflib_i.h"#include "vnode_afd.h"#include "aff_db.h"#ifndef F_OK#define F_OK 00#endif#ifndef R_OK#define R_OK 04#endif#ifdef WIN32/**************************************************************** *** Windows emulation of opendir()/readdir() *** From php ****************************************************************//* struct dirent - same as Unix */struct dirent {	long d_ino;					/* inode (always 1 in WIN32) */	off_t d_off;				/* offset to this dirent */	int d_reclen;		/* length of d_name; was unsigned short */	char d_name[_MAX_FNAME + 1];	/* filename (null terminated) */};/* typedef DIR - not the same as Unix */typedef struct {	long handle;				/* _findfirst/_findnext handle */	short offset;				/* offset into directory */	short finished;				/* 1 if there are not more files */	struct _finddata_t fileinfo;	/* from _findfirst/_findnext */	char *dir;					/* the dir we are reading */	struct dirent dent;			/* the dirent to return */} DIR;/* Function prototypes */DIR *opendir(const char *);struct dirent *readdir(DIR *);int readdir_r(DIR *, struct dirent *, struct dirent **);int closedir(DIR *);int rewinddir(DIR *);/********************************************************************** * Implement dirent-style opendir/readdir/rewinddir/closedir on Win32 * * Functions defined are opendir(), readdir(), rewinddir() and * closedir() with the same prototypes as the normal dirent.h * implementation. * * Does not implement telldir(), seekdir(), or scandir().  The dirent * struct is compatible with Unix, except that d_ino is always 1 and * d_off is made up as we go along. * * The DIR typedef is not compatible with Unix. **********************************************************************/static DIR *opendir(const char *dir){	DIR *dp;	char *filespec;	long handle;	int index;	filespec = (char *)malloc(strlen(dir) + 2 + 1);	strcpy(filespec, dir);	index = strlen(filespec) - 1;	if (index >= 0 && (filespec[index] == '/' || 	   (filespec[index] == '\\' && !IsDBCSLeadByte(filespec[index-1]))))		filespec[index] = '\0';	strcat(filespec, "/*");	dp = (DIR *) malloc(sizeof(DIR));	dp->offset = 0;	dp->finished = 0;	if ((handle = _findfirst(filespec, &(dp->fileinfo))) < 0) {		if (errno == ENOENT) {			dp->finished = 1;		} else {			free(dp);			free(filespec);			return NULL;		}	}	dp->dir = strdup(dir);	dp->handle = handle;	free(filespec);	return dp;}static struct dirent *readdir(DIR *dp){	if (!dp || dp->finished)		return NULL;	if (dp->offset != 0) {		if (_findnext(dp->handle, &(dp->fileinfo)) < 0) {			dp->finished = 1;			return NULL;		}	}	dp->offset++;	strlcpy(dp->dent.d_name, dp->fileinfo.name, _MAX_FNAME+1);	dp->dent.d_ino = 1;	dp->dent.d_reclen = strlen(dp->dent.d_name);	dp->dent.d_off = dp->offset;	return &(dp->dent);}static int readdir_r(DIR *dp, struct dirent *entry, struct dirent **result){	if (!dp || dp->finished) {		*result = NULL;		return 0;	}	if (dp->offset != 0) {		if (_findnext(dp->handle, &(dp->fileinfo)) < 0) {			dp->finished = 1;			*result = NULL;			return 0;		}	}	dp->offset++;	strlcpy(dp->dent.d_name, dp->fileinfo.name, _MAX_FNAME+1);	dp->dent.d_ino = 1;	dp->dent.d_reclen = strlen(dp->dent.d_name);	dp->dent.d_off = dp->offset;	memcpy(entry, &dp->dent, sizeof(*entry));	*result = &dp->dent;	return 0;}static int closedir(DIR *dp){	if (!dp)		return 0;	_findclose(dp->handle);	if (dp->dir)		free(dp->dir);	if (dp)		free(dp);	return 0;}static int rewinddir(DIR *dp){	/* Re-set to the beginning */	char *filespec;	long handle;	int index;	_findclose(dp->handle);	dp->offset = 0;	dp->finished = 0;	filespec = (char *)malloc(strlen(dp->dir) + 2 + 1);	strcpy(filespec, dp->dir);	index = strlen(filespec) - 1;	if (index >= 0 && (filespec[index] == '/' || filespec[index] == '\\'))		filespec[index] = '\0';	strcat(filespec, "/*");	if ((handle = _findfirst(filespec, &(dp->fileinfo))) < 0) {		if (errno == ENOENT)			dp->finished = 1;		}	dp->handle = handle;	free(filespec);	return 0;}#endif/**************************************************************** *** Service routines ****************************************************************/struct afd_private {    AFFILE **afs;			// list of AFFILEs...    int num_afs;			// number of them    int cur_file;			// current segment number...};static inline struct afd_private *AFD_PRIVATE(AFFILE *af){    assert(af->v == &vnode_afd);    return (struct afd_private *)(af->vnodeprivate);}static bool last4_is_afd(const char *filename){    return af_ext_is(filename,"afd");}static bool last4_is_aff(const char *filename){    return af_ext_is(filename,"aff");}/* afd_file_with_seg: * Returns the AFFILE for a given segment, or 0 if it isn't found. */static AFFILE *afd_file_with_seg(AFFILE *af,const char *name){    struct afd_private *ap = AFD_PRIVATE(af);    for(int i=0;i<ap->num_afs;i++){	if(af_get_seg(ap->afs[i],name,0,0,0)==0){	    return ap->afs[i];	}    }    errno = ENOTDIR;			// get ready for error return    return 0;}static void aff_filename(AFFILE *afd,char *buf,int buflen,int num){    snprintf(buf,buflen,"%s/file_%03d.aff",afd->fname,num);}/* Return 1 if a file is an AFF file */static int afd_identify_file(const char *filename,int exists){    if(filename==0 || strlen(filename)==0) return 0;	// zero-length filenames aren't welcome    if(exists && access(filename,R_OK)!=0) return 0;	// needs to exist and it doesn't    /* If it ends with a '/', remove it */    char *fn = (char *)alloca(strlen(filename)+1);    strcpy(fn,filename);    char *lastc = fn + strlen(fn) - 1;    if(*lastc=='/') *lastc = '\000';    /* If filename exists and it is a dir, it needs to end afd */    struct stat sb;    if(stat(fn,&sb)==0){	if((sb.st_mode & S_IFMT)==S_IFDIR){	    if(last4_is_afd(fn)) return 1;	}	return 0;			//    }    /* Doesn't exist. Does it end .afd ? */    if(last4_is_afd(fn)) return 1;    return 0;}/* Add a file to the AFF system. * if fname==0, create a new one and copy over the relevant metadata... */static int afd_add_file(AFFILE *af,const char *fname_){    struct afd_private *ap = AFD_PRIVATE(af);    const char *segs_to_copy[] = {AF_BADFLAG,				  AF_CASE_NUM,				  AF_IMAGE_GID,				  AF_ACQUISITION_ISO_COUNTRY,				  AF_ACQUISITION_COMMAND_LINE,				  AF_ACQUISITION_DATE,				  AF_ACQUISITION_NOTES,				  AF_ACQUISITION_DEVICE,				  AF_ACQUISITION_TECHNICIAN,				  AF_DEVICE_MANUFACTURER,				  AF_DEVICE_MODEL,				  AF_DEVICE_SN,				  AF_DEVICE_FIRMWARE,				  AF_DEVICE_SOURCE,				  AF_CYLINDERS,				  AF_HEADS,				  AF_SECTORS_PER_TRACK,				  AF_LBA_SIZE,				  AF_HPA_PRESENT,				  AF_DCO_PRESENT,				  AF_LOCATION_IN_COMPUTER,				  AF_DEVICE_CAPABILITIES,				  0};    char fname[MAXPATHLEN+1];    memset(fname,0,sizeof(fname));    if(fname_){	strlcpy(fname,fname_,sizeof(fname));    }    else {	aff_filename(af,fname,sizeof(fname),ap->num_afs);    }    int new_file = access(fname,F_OK)!=0;	// Is this a new file?    AFFILE *af2 = af_open(fname,af->openflags,af->openmode);     if(af2==0){	(*af->error_reporter)("open(%s,%d,%d) failed: %s\n",			      fname,af->openflags,af->openmode,strerror(errno));	return -1;			// this is bad    }    ap->num_afs += 1;    ap->afs = (AFFILE **)realloc(ap->afs,sizeof(AFFILE *) * ap->num_afs);    ap->afs[ap->num_afs-1] = af2;    if(new_file){	if(af->writing==0){	    (af->error_reporter)("afd_add_file: created new file and not writing?\n");	    return -1;	}	/* Copy over configuration from AFD vnode*/	af_enable_writing(af2,af->writing);	af_enable_compression(af2,af->compression_type,af->compression_level);	af_set_pagesize(af2,af->image_pagesize);		//	af_set_sectorsize(af2,af->image_sectorsize);	af_update_seg(af,AF_AFF_FILE_TYPE,0,"AFD",3);		/* If this is the second file, copy over additional metadata from first... */	if(ap->num_afs>0){	    AFFILE *af0 = ap->afs[0];	    memcpy(af2->badflag,af0->badflag,af->image_sectorsize);	    af2->bytes_memcpy += af->image_sectorsize;	    	    for(const char **segname=segs_to_copy;*segname;segname++){		unsigned char data[65536];	// big enough for most metadata		size_t datalen = sizeof(data);		unsigned long arg=0;				if(af_get_seg(af0,*segname,&arg,data,&datalen)==0){		    int r = af_update_seg(af2,*segname,arg,data,datalen);		    if(r!=0){			(*af->error_reporter)("afd_add_file: could not update %s in %s (r=%d)",					      *segname,af_filename(af2),r);		    }		}	    }	}    }        return 0;}    		    /**************************************************************** *** User-visible functions. ****************************************************************/static int afd_open(AFFILE *af){    if(af->fname==0 || strlen(af->fname)==0) return -1;	// zero-length filenames aren't welcome    /* If the name ends with a '/', remove it */    char *lastc = af->fname + strlen(af->fname) - 1;    if(*lastc=='/') *lastc = '\000';        /* If the directory doesn't exist, make it (if we are O_CREAT) */    struct stat sb;    if(stat(af->fname,&sb)!=0){	if((af->openflags & O_CREAT) == 0){ // flag not set	    errno = ENOTDIR;	    return -1;	}	mode_t omask = umask(0);	// reset umask for now...	mkdir(af->fname,af->openmode|0111); // make the directory	umask(omask);			// put back the old mask    }    af->maxsize = AFD_DEFAULT_MAXSIZE;    af->vnodeprivate = (void *)calloc(1,sizeof(struct afd_private));    struct afd_private *ap = AFD_PRIVATE(af);    ap->afs = (AFFILE **)malloc(sizeof(AFFILE *));    /* Open the directory and read all of the AFF files */    DIR *dirp = opendir(af->fname);    if(!dirp){	return -1;			// something is wrong...    }    struct dirent *dp;    while ((dp = readdir(dirp)) != NULL){	if (last4_is_aff(dp->d_name)){	    char path[MAXPATHLEN+1];	    strlcpy(path,af->fname,sizeof(path));	    strlcat(path,"/",sizeof(path));	    strlcat(path,dp->d_name,sizeof(path));	    if(afd_add_file(af,path)){		return -1;	    }	}    }    closedir(dirp);    return 0;				// "we were successful"}static int afd_close(AFFILE *af){    struct afd_private *ap = AFD_PRIVATE(af);    uint64 image_size = af_get_imagesize(af); // get the largest imagesize    /* Close all of the subfiles, then free the memory, then close this file */    for(int i=0;i<ap->num_afs;i++){	ap->afs[i]->image_size = image_size; // set each to have current imagesize	af_close(ap->afs[i]);		// and close each file    }    free(ap->afs);    memset(ap,0,sizeof(*ap));		// clean object reuse    free(ap);				// won't need it again    return 0;}#ifndef WIN32static uint64 max(uint64 a,uint64 b){    return a > b ? a : b;}#endifstatic int afd_vstat(AFFILE *af,struct af_vnode_info *vni){    struct afd_private *ap = AFD_PRIVATE(af);    memset(vni,0,sizeof(*vni));		// clear it    /* See if there is some device that knows how big the disk is */    if(ap->num_afs>0){	af_vstat(ap->afs[0],vni);	// get disk free bytes    }    /* Get the file with the largest imagesize from either the     * AFD or any of the sub AFDs...     */    vni->imagesize = af->image_size;    for(int i=0;i<ap->num_afs;i++){	vni->imagesize = max(vni->imagesize,ap->afs[i]->image_size);    }    vni->has_pages = 1;    vni->supports_metadata = 1;    return 0;}static int afd_get_seg(AFFILE *af,const char *name,unsigned long *arg,unsigned char *data,		       size_t *datalen){    AFFILE *af2 = afd_file_with_seg(af,name);    if(af2){	return af_get_seg(af2,name,arg,data,datalen); // use this one    }    return -1;				// not found}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}/* 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;		}/* Update: * If this segment is in any of the existing files, update it there. * Otherwise, if the last file isn't too big, add it there. * Otherwise, ada a new file. */static int afd_update_seg(AFFILE *af, const char *name,		    unsigned long arg,const void *value,unsigned int vallen)    {    struct afd_private *ap = AFD_PRIVATE(af);    AFFILE *af2 = afd_file_with_seg(af,name);    if(af2){	return af_update_seg(af2,name,arg,value,vallen); // update where it was found    }    /* Segment doesn't exist anywhere... */    /* Append to the last file if there is space and a space limitation... */    if(ap->num_afs>0){	AFFILE *af3 = ap->afs[ap->num_afs-1];	FILE *aseg = af3->aseg;	uint64 offset = ftello(aseg);	fseeko(aseg,0,SEEK_END);	uint64 len = ftello(aseg);	fseeko(aseg,offset,SEEK_SET);	if((len + vallen + 1024 < af->maxsize) && (af->maxsize!=0)){	    /* It should fit with room left over! */	    return af_update_seg(af3,name,arg,value,vallen);	}    }    /* Add a new segment and update that one */    if(afd_add_file(af,0)) return -1;    AFFILE *af4 = ap->afs[ap->num_afs-1]; // this is the one just added    return af_update_seg(af4,name,arg,value,vallen);}int afd_del_seg(AFFILE *af,const char *segname){    AFFILE *af2 = afd_file_with_seg(af,segname);    if(af2){	return af_del_seg(af2,segname);    }    return -1;				// not found}struct af_vnode vnode_afd = {    AF_IDENTIFY_AFD,		//     AF_VNODE_TYPE_COMPOUND|AF_VNODE_TYPE_RELIABLE,		//     "AFF Directory",    afd_identify_file,    afd_open,			// open    afd_close,			// close    afd_vstat,			// vstat    afd_get_seg,		// get_seg    afd_get_next_seg,		// get_next_seg    afd_rewind_seg,		// rewind_seg    afd_update_seg,		// update_seg    afd_del_seg,		// del_seg    0,				// read    0				// write};

⌨️ 快捷键说明

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