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

📄 afflib_stream.cpp

📁 sleuthit-2.09 一个磁盘的工具集
💻 CPP
字号:
/* * The AFFLIB data stream interface. * Supports the page->segment name translation, and the actual file pointer. *//* * Copyright (c) 2005, 2006 *	Simson L. Garfinkel and Basis Technology, Inc.  *      All rights reserved. * * This code is derrived from software contributed by * Simson L. Garfinkel * * 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 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 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 GARFINKEL, BAIS 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.   */#include "config.h"#include "afflib.h"#include "afflib_i.h"/**************************************************************** *** Internal Functions. ****************************************************************//* * af_set_maxsize * Sets the maxsize. Fails with -1 if imagesize >= 0 unless this is a raw or split_raw file */int af_set_maxsize(AFFILE *af,int64 maxsize){    if(af_get_imagesize(af)>0){	(*af->error_reporter)("Cannot set maxsize as imagesize is %"I64d,af_get_imagesize(af));	return -1;	// now allowed to set if imagesize is bigger than 0    }    if((af->image_sectorsize==0) || (maxsize % af->image_sectorsize != 0)){	(*af->error_reporter)("Cannot set maxsize to %"I64d" (sectorsize=%d)\n",			      maxsize,af->image_sectorsize);	return -1;    }    if((af->image_pagesize!=0)       && (af->v->type & AF_VNODE_MAXSIZE_MULTIPLE)       && (maxsize % af->image_pagesize != 0)){	(*af->error_reporter)("Cannot set maxsize to %"I64d" --- not multiple of pagesize=%d\n",			      maxsize,af->image_pagesize);	return -1;    }    af->maxsize = maxsize;    return 0;}const unsigned char *af_badflag(AFFILE *af){    return af->badflag;}/**************************************************************** *** Stream-level interface ****************************************************************//* Throw out the current segment */int af_purge(AFFILE *af){    if (af_trace) fprintf(af_trace,"af_purge(%p)\n",af);    int ret = af_cache_flush(af);	// flush the cache    af->pb = 0;				// no longer have a current page    return ret;}int af_read(AFFILE *af,unsigned char *buf,size_t count){    if (af_trace) fprintf(af_trace,"af_read(%p,%p,%d) (pos=%"I64d")\n",af,buf,count,af->pos);    if (af->v->read){			// bypass	int r = (af->v->read)(af, buf, af->pos, count);	if(r>0) af->pos += r;	return r;    }    uint64 image_size = af_get_imagesize(af); // get the imagesize     if(image_size==0) return 0;		// no data in file    uint64 offset = af->pos;		/* where to start */    /* Make sure we have a pagebuf if none was defined */    if(af->image_pagesize==0){		// page size not defined	errno = EFAULT;	return -1;    }    int total = 0;    while(count>0){	/* If the correct segment is not loaded, purge the segment */	int64 new_page = offset / af->image_pagesize;	if(af->pb==0 || new_page != af->pb->pagenum){	    af_cache_flush(af);	    af->pb = 0;	}	/* If no segment is loaded in cache, load the current segment */	if(af->pb==0){	    int64 pagenum = offset / af->image_pagesize;	    af->pb = af_cache_alloc(af,pagenum);	    if(af->pb->pagebuf_valid==0){ 		/* page buffer isn't valid; need to get it */		af->pb->pagebuf_bytes = af->image_pagesize;		// we can hold this much		if(af_get_page(af,af->pb->pagenum,af->pb->pagebuf, &af->pb->pagebuf_bytes)){		    break;			// no more to get		}		af->pb->pagebuf_valid = 1;	// contents of the page buffer are valid	    }	}	// Compute how many bytes can be copied...	// where we were reading from	unsigned int page_offset   = (uint)(offset - af->pb->pagenum * af->image_pagesize); 	unsigned int page_left     = af->pb->pagebuf_bytes - page_offset; // number we can get out	unsigned int bytes_to_read = count;	if(bytes_to_read > page_left)           bytes_to_read = page_left;	if(bytes_to_read > image_size - offset) bytes_to_read = (uint)(image_size - offset);	assert(bytes_to_read >= 0);	// 	if(bytes_to_read==0) break; // that's all we could get	/* Copy out the bytes for the user */	memcpy(buf,af->pb->pagebuf+page_offset,bytes_to_read); // copy out	af->bytes_memcpy += bytes_to_read;	buf     += bytes_to_read;	offset  += bytes_to_read;	count   -= bytes_to_read;	total   += bytes_to_read;	af->pos += bytes_to_read;    }    /* We have copied all of the user's requested data, so return */    return total;}/* * Handle writing to the file... * af_write() --- returns the number of bytes written * */int af_write(AFFILE *af,unsigned char *buf,size_t count){    if (!af->writing){	errno = EPERM;			// operation not permitted	return -1;			// not opened for writing    }    if (af_trace){	fprintf(af_trace,"af_write(af=%p,buf=%p,count=%d) pos=%"I64d"\n",			  af,buf,count,af->pos);    }    /* vnode write bypass:     * If a write function is defined, use it and avoid the page and cache business.      */    if (af->v->write){			int r = (af->v->write)(af, buf, af->pos, count);	if(r>0){	    af->pos += r;	    af->bytes_written += r;	}	if(af->pos >= af->image_size) af->image_size = af->pos;	return r;    }    uint64 offset = af->pos;		// where to start    /* If the correct segment is not loaded, purge the current segment */    int64 write_page = offset / af->image_pagesize;    if(af->pb && af->pb->pagenum!=write_page){	af_cache_flush(af);	af->pb = 0;    }    int write_page_offset = (int)(offset % af->image_pagesize);    /* Page Write Bypass:     * If no data has been written into the current page buffer,     * and if the position of the stream is byte-aligned on the page buffer,     * and if an entire page is being written,     * just write it out and update the pointers, then return.     */    if(af->pb==0 && af->image_pagesize==(unsigned)count && write_page_offset == 0){	af_cache_writethrough(af,write_page,buf,count);	// copy into cache if we have this page anywhere in our cache	int ret = af_update_page(af,write_page,buf,count);	if(ret==0){			// no error	    af->pos += count;	    if(af->pos > af->image_size) af->image_size = af->pos;	    return count;	}	return -1;			// error    }           /* Can't use high-speed optimization; write through the cache */    int total = 0;    while(count>0){	/* If no page is loaded, or the wrong page is loaded, load the correct page */	int64 pagenum = offset / af->image_pagesize;	// will be the segment we want	if(af->pb==0 || af->pb->pagenum != pagenum){	    af->pb = af_cache_alloc(af,pagenum);	    af->pb->pagebuf_bytes = af->image_pagesize;	    assert(af->pb->pagenum == pagenum);	    /* Now try to load the page. If we can't load it, then we are creating a new page. */	    if(af_get_page(af,af->pb->pagenum,af->pb->pagebuf, &af->pb->pagebuf_bytes)){		/* Creating a new page; note that we have no bytes in this page */		af->pb->pagebuf_bytes = 0;	    }	}	unsigned int seg_offset = (uint)(offset - af->pb->pagenum * af->image_pagesize); // where writing to	unsigned int seg_left   = af->image_pagesize - seg_offset; // number we can write into	unsigned int bytes_to_write = count;	if(bytes_to_write > seg_left) bytes_to_write = seg_left;	assert(bytes_to_write >= 0);	// 	if(bytes_to_write==0) break; // that's all we could get	/* Copy out the bytes for the user */	memcpy(af->pb->pagebuf+seg_offset,buf,bytes_to_write); // copy into the page cache	af->bytes_memcpy += bytes_to_write;	if(af->pb->pagebuf_bytes < seg_offset+bytes_to_write){	    af->pb->pagebuf_bytes = seg_offset+bytes_to_write; // it has been extended.	}	buf     += bytes_to_write;	offset  += bytes_to_write;	count   -= bytes_to_write;	total   += bytes_to_write;	af->pos += bytes_to_write;	af->pb->pagebuf_valid = 1;	af->pb->pagebuf_dirty = 1;	/* If we wrote out all of the bytes that were left in the segment,	 * then we are at the end of the segment, write it back...	 */	if(seg_left == bytes_to_write){		    if(af_cache_flush(af)) return -1;	}	/* If we have written more than the image size, update the image size */	if(offset > af->image_size) af->image_size = offset;    }    /* We have copied all of the user's requested data, so return */    return total;}int af_is_badsector(AFFILE *af,unsigned char *buf){    if(af->badflag_set==0) return 0;    if(af->badflag==0) return 0;    return memcmp(af->badflag,buf,af->image_sectorsize)==0;}

⌨️ 快捷键说明

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