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

📄 vnode_afm.cpp

📁 sleuthit-2.09 一个磁盘的工具集
💻 CPP
字号:
/* * AFFLIB(tm) * * Copyright (c) 2005, 2006 *	Simson L. Garfinkel and Basis Technology Corp. *      All rights reserved. * * This code is derrived from software contributed by * Simson L. Garfinkel * * Support for split raw files and .afm files written by Joel N. Weber II * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *    This product includes software developed by Simson L. Garfinkel *    and Basis Technology Corp. * 4. Neither the name of Simson L. Garfinkel, Basis Technology, or other *    contributors to this program may be used to endorse or promote *    products derived from this software without specific prior written *    permission. * * THIS SOFTWARE IS PROVIDED BY SIMSON L. GARFINKEL, BASIS TECHNOLOGY, * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED.  IN NO EVENT SHALL SIMSON L. GARFINKEL, BASIS TECHNOLOGy, * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE.   * * AFF and AFFLIB is a trademark of Simson Garfinkel and Basis Technology Corp. */#include "config.h"#include "afflib.h"#include "afflib_i.h"#include "vnode_afm.h"#include "vnode_aff.h"#include "vnode_split_raw.h"/* * Notes on implementation: * AF_PAGES_PER_IMAGE_FILE is a segment read as a 64-bit number. * If its value is 0, then do not split the files. *//* afm raw file implementation with optional metadata support */struct afm_private {    AFFILE *aff;			// the AFFILE we use for the actual metadata    AFFILE *sr;				// the AFFILE we use for the splitraw    int sr_initialized;			// has the split-raw been setup from AFM?};static inline struct afm_private *AFM_PRIVATE(AFFILE *af){    assert(af->v == &vnode_afm);    return (struct afm_private *)(af->vnodeprivate);}/* Return 1 if a file has the AFF header or if the file doesn't * exist and its extension is .afm */static int afm_identify_file(const char *filename,int exists){    if(exists && access(filename,R_OK)!=0) return 0;	// needs to exist and it doesn't    return af_ext_is(filename,"afm");}static int afm_close(AFFILE *af){    struct afm_private *ap = AFM_PRIVATE(af);    if(ap){	if(ap->sr)  af_close(ap->sr);		// close the split files	if(ap->aff) af_close(ap->aff);		// and close the AFF file	memset(ap,0,sizeof(*ap));	free(ap);    }    return 0;}static int invalid_extension_char(const char *extension,int ext_len){    for(int i=0;i<ext_len;i++){	if(extension[1]=='\000') return 1;	if(extension[1]=='.') return 1;	if(extension[1]=='/') return 1;    }    return 0;}static int afm_create(AFFILE *af){    if (af_update_seg (af, AF_RAW_IMAGE_FILE_EXTENSION, 0, SPLITRAW_DEFAULT_EXTENSION, 		       strlen(SPLITRAW_DEFAULT_EXTENSION))) {	(*af->error_reporter)("split_raw_read_write_setup: %s: failed to write %s\n",			      af->fname, AF_RAW_IMAGE_FILE_EXTENSION);	afm_close(af);		// close the sub-file	return -1;			// we failed    }    af_set_pagesize(af,AFM_DEFAULT_PAGESIZE);    af_update_seg(af,AF_AFF_FILE_TYPE,0,"AFM",3);    return 0;}/* * The AFM is actually a shell that opens two * sub-implementations in their own files: an AFF file * and a split_raw file. */ static int afm_open(AFFILE *af){    af->vnodeprivate = (void *)calloc(sizeof(struct afm_private),1);    struct afm_private *ap = AFM_PRIVATE(af);    ap->aff = af_open_with(af_filename(af),af->openflags,af->openmode,&vnode_aff);    if(ap->aff==0){			// open failed?	afm_close(af);	return -1;    }    ap->aff->parent = af;    /* If this is a new file, write out the default split raw extension */    if(af->exists == 0){	if(afm_create(af)) return -1;    }    /* If this is an old file, read the image_pagesize */    if(af->exists){	af->image_pagesize = ap->aff->image_pagesize;    }    /* Read the split raw extension */    char raw_file_extension[4];    size_t  len=3;				// don't overwrite the NUL        memset(raw_file_extension,0,sizeof(raw_file_extension));    if (af_get_seg(ap->aff,AF_RAW_IMAGE_FILE_EXTENSION,0,(unsigned char *)raw_file_extension,&len)) {	(*af->error_reporter)("afm_open: %s: %s segment missing or too large\n",			      af_filename(af),AF_RAW_IMAGE_FILE_EXTENSION);	afm_close(af);	return -1;    }    if(invalid_extension_char(raw_file_extension,len)){	(*af->error_reporter)("afm_open: file extension contains invalid character\n",		 af->fname, AF_RAW_IMAGE_FILE_EXTENSION);	afm_close(af);	return -1;    }        /* Now open the splitraw file */    char *sr_filename = strdup(af_filename(af));    char *ext = strrchr(sr_filename,'.');    if(!ext){	(*af->error_reporter)("afm_open: cannot find extension in '%s'",sr_filename);	free(sr_filename);	afm_close(af);	return -1;    }    ext++;				// skip past '.'    if(strlen(ext) != strlen(raw_file_extension)){	(*af->error_reporter)("afm_open: file extension in '%s' too short",sr_filename);	free(sr_filename);	afm_close(af);	return -1;    }    strcpy(ext,raw_file_extension);    ap->sr  = af_open_with(sr_filename,af->openflags,af->openmode,&vnode_split_raw);    if(ap->sr==0){	(*af->error_reporter)("afm_open: could not open '%s'",sr_filename);	free(sr_filename);	afm_close(af);	return -1;    }    ap->sr->parent = af;    free(sr_filename);    /* Additional setup will happen first time a data read/write call is made     * by the function afm_read_write_setup().     * This allows a new file to be created with af_open() and then to have     * the parameters set with af_update_seg() calls, yet the split_raw     * implementation gets the proper settings     */    return 0;    }/*  afm_split_raw_setup: * Sets up the parameters of the split-raw by reading from the metadata file. * The advantage of doing it this way is that a new file can be opened, * the metadata parmeters set, and then an af_write() call made, and the values. * get copied. */static int afm_split_raw_setup(AFFILE *af){    struct afm_private *ap = AFM_PRIVATE(af);    if(ap->sr_initialized) return 0;		// already setup    /* The size of AF_PAGES_PER_RAW_IMAGE_FILE indicates whether the file is split.     * If it is not present, or if it is 0-length, assume that the file is not split.     */    uint64 pages_per_file = 0;    size_t len = 0;    if (af_get_seg(ap->aff,AF_PAGES_PER_RAW_IMAGE_FILE,0,0,&len)) {	/* Not in file; put it there based on maxsize and image_pagesize,	 * both of which better be set at this point	 */	if (af->image_pagesize < 1) {	    (*af->error_reporter)("afm_split_raw_setup: image_pagesize==0\n");	    return -1;	}	if (af->maxsize % af->image_pagesize) {	    (*af->error_reporter)("afm_split_raw_setup: maxsize (%"I64d") "				  "not a multiple of image_pagesize (%d)\n",				  af->maxsize,af->image_pagesize);	    return -1;	}	pages_per_file = af->maxsize / af->image_pagesize;	if (af_update_segq (af, AF_PAGES_PER_RAW_IMAGE_FILE, pages_per_file)) {	    (*af->error_reporter)("split_raw_read_write_setup: %s: failed to write %s\n",				  af_filename(af), AF_PAGES_PER_RAW_IMAGE_FILE);	    return -1;	}    }    /* Now, read the segment (which might have just been put there) and set up the split_raw file */    if(af_get_segq(af,AF_PAGES_PER_RAW_IMAGE_FILE,(int64 *)&pages_per_file)){	(*af->error_reporter)("split_raw_read_write_setup: %s: failed to write %s\n",			      af_filename(af), AF_PAGES_PER_RAW_IMAGE_FILE);	return -1;    }    /* Verify that splitraw's notion of the rawfilesize is the same as the     * metadata's notion.     */    if (ap->aff->image_size != ap->sr->image_size) {	(*af->error_reporter)("afm_split_raw_setup: internal error. "			      "AFF image_size %"I64d" != SR image_size %"I64d"\n",			      ap->aff->image_size,ap->sr->image_size);	return -1;    }    /* Uses pages_per_file to set the maxsize of the split_raw if it hasn't been set yet*/    if(ap->sr->maxsize==0){	ap->sr->maxsize = pages_per_file * af->image_pagesize;    }    /* Verify that the parameters make sense */    if (ap->sr->maxsize != (pages_per_file * af->image_pagesize) && pages_per_file>0) {	(*af->error_reporter)("afm_split_raw_setup: %s: per size indicated by metadata (%d * %d) "			      "doesn't match maxsize (%"I64d")\n",			      af_filename(af),pages_per_file,af->image_pagesize,ap->sr->maxsize);	return -1;    }    /* Push down the image_pagesize from the AFM to the split_raw */    unsigned long image_pagesize = af->image_pagesize; // default to what's in memory    af_get_seg(af,AF_PAGESIZE,&image_pagesize,0,0); // get from the AFF file if possible    ap->sr->image_pagesize = af->image_pagesize; // overwrite the default with what the AFM file         ap->sr_initialized = 1;    return 0;}/* * the stat of the afm is the stat of the metafile, * but we don't do compression. */static int afm_raw_vstat(AFFILE *af,struct af_vnode_info *vni){    memset(vni,0,sizeof(*vni));		// clear it    struct afm_private *ap = AFM_PRIVATE(af);    af_vstat(ap->aff,vni);    vni->supports_compression = 0;    vni->supports_metadata    = 1;    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,unsigned long *arg,unsigned char *data,size_t *datalen){    struct afm_private *ap = AFM_PRIVATE(af);    int64 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 page_num = af_segname_page_number(segname);    if(page_num>=0){	errno = ENOTSUP;	return -1;    }    return af_del_seg(ap->aff,segname);}/* * afm_get_next_seg: * Try get_next_seg on the AFF file first until it has none left. * Then call get_next_seg of the splitraw until it has noneleft. */static int afm_get_next_seg(AFFILE *af,char *segname,size_t segname_len,unsigned long *arg,			    unsigned char *data,size_t *datalen_){    struct afm_private *ap = AFM_PRIVATE(af);    int r = af_get_next_seg(ap->aff,segname,segname_len,arg,data,datalen_);    if(r==-1) return af_get_next_seg(ap->sr,segname,segname_len,arg,data,datalen_);    return r;}/* 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}/* 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,			  unsigned long arg,const void *value,unsigned int vallen)    {    struct afm_private *ap = AFM_PRIVATE(af);    int64 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);}static int afm_read(AFFILE *af, unsigned char *buf, uint64 pos,size_t count){    struct afm_private *ap = AFM_PRIVATE(af);    if(ap->sr_initialized==0 && afm_split_raw_setup(af)) return -1;    return (*ap->sr->v->read)(ap->sr,buf,pos,count);}static int afm_write(AFFILE *af, unsigned char *buf, uint64 pos,size_t count){    struct afm_private *ap = AFM_PRIVATE(af);    if(ap->sr_initialized==0 && afm_split_raw_setup(af)) return -1;    af_set_callback(ap->sr,af->w_callback);               // update the callback    int r = (*ap->sr->v->write)(ap->sr,buf,pos,count);  // call split_raw's write    if(ap->sr->image_size > af->image_size){	af->image_size      = ap->sr->image_size; // image was extended; note this in parent & AFF file	ap->aff->image_size = ap->sr->image_size; // copy over the image size    }    return r;}struct af_vnode vnode_afm = {    AF_IDENTIFY_AFM,    AF_VNODE_TYPE_COMPOUND|AF_VNODE_TYPE_RELIABLE|AF_VNODE_MAXSIZE_MULTIPLE,    "AFM (AFF metadata with split raw file)",    afm_identify_file,    afm_open,    afm_close,    afm_raw_vstat,			// nothing aff specific here.     afm_get_seg,			// get seg    afm_get_next_seg,			// get_next_seg    afm_rewind_seg,			// rewind_seg    afm_update_seg,			// update_seg    afm_del_seg,			// del_seg (afm_open fills in aff_del_seg)    afm_read,				// read    afm_write				// write};

⌨️ 快捷键说明

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