📄 vnode_raw.cpp
字号:
#include "config.h"#include "afflib.h"#include "afflib_i.h"#include "vnode_raw.h"/* the RAW_PAGESIZE is visible outside the module, but it's kind of irrevellant */#define RAW_PAGESIZE 16*1024*1024 /* raw file implementation */struct raw_private { /* For Raw files */ FILE *raw; // if it is a raw file int raw_popen; // opened with popen};static inline struct raw_private *RAW_PRIVATE(AFFILE *af){ assert(af->v == &vnode_raw); return (struct raw_private *)(af->vnodeprivate);}/* Return 1 if a file is a raw file... */static int raw_identify_file(const char *filename,int exists){ if(exists && access(filename,R_OK)!=0) return 0; // needs to exist and it doesn't return access(filename,R_OK)==0; // if we can read it, it's raw...}/* Return the size of the raw file */static int64 raw_filesize(AFFILE *af){ struct raw_private *rp = RAW_PRIVATE(af); struct stat sb; if(fstat(fileno(rp->raw),&sb)){ (*af->error_reporter)("raw_open: stat(%s): ",af->fname); return -1; // kind of odd... } return sb.st_size;}static int raw_open(AFFILE *af){ /* Raw is the passthrough system. * Right now, it is read only... */ af->vnodeprivate = (void *)calloc(1,sizeof(struct raw_private)); struct raw_private *rp = RAW_PRIVATE(af); if(af->fname) rp->raw=fopen(af->fname,"rb"); af->image_size = raw_filesize(af); af->image_pagesize = RAW_PAGESIZE; af->cur_page = 0; return 0;}int raw_freopen(AFFILE *af,FILE *file){ af->fname = 0; af->vnodeprivate = (void *)calloc(1,sizeof(struct raw_private)); struct raw_private *rp = RAW_PRIVATE(af); rp->raw = file; af->image_size = raw_filesize(af); af->image_pagesize = RAW_PAGESIZE; af->cur_page = 0; return 0;}int raw_popen(AFFILE *af,const char *command,const char *type){ if(strcmp(type,"r")!=0){ (*af->error_reporter)("af_popen: only type 'r' supported"); return -1; } /* If shell metacharacters exist in command, don't open it */ if(af_hasmeta(command)){ (*af->error_reporter)("raw_popen: invalid shell metacharacters in command '%s'", command); return -1; } af->fname = 0; af->vnodeprivate = (void *)calloc(1,sizeof(struct raw_private)); struct raw_private *rp = RAW_PRIVATE(af); rp->raw = popen(command,"r"); rp->raw_popen = 1; return 0;}static int raw_close(AFFILE *af){ struct raw_private *rp = RAW_PRIVATE(af); if(rp->raw_popen){#ifdef UNIX pclose(rp->raw);#endif } else { fclose(rp->raw); } memset(rp,0,sizeof(*rp)); // clean object reuse free(rp); // won't need it again return 0;}static int raw_get_seg(AFFILE *af,const char *name, unsigned long *arg,unsigned char *data,size_t *datalen){ struct raw_private *rp = RAW_PRIVATE(af); int64 segnum = af_segname_page_number(name); if(segnum<0){ /* See if PAGESIZE or IMAGESIZE is being requested; we can fake those */ if(strcmp(name,AF_PAGESIZE)==0 && arg){*arg = af->image_pagesize;return 0;} if(strcmp(name,AF_IMAGESIZE)==0 && data && *datalen>=8){ struct aff_quad q; q.low = htonl((unsigned long)(af->image_size & 0xffffffff)); q.high = htonl((unsigned long)(af->image_size >> 32)); memcpy(data,&q,8); return 0; } return -1; // don't know how to fake this } fflush(rp->raw); // make sure that any buffers are flushed int64 pos = (int64)segnum * af->image_pagesize; // where we are to start reading int64 bytes_left = af->image_size - pos; // how many bytes left in the file int bytes_to_read = af->image_pagesize; // copy this many bytes, unless if(bytes_to_read > bytes_left) bytes_to_read = bytes_left; // only this much is left if(arg) *arg = 0; // arg is always 0 if(datalen){ if(*datalen==0 && data==0){ // asked for 0 bytes, so give the actual size *datalen = bytes_to_read; return 0; } if(*datalen < (unsigned)bytes_to_read){ *datalen = bytes_to_read; return AF_ERROR_DATASMALL; } } if(data){ fseeko(rp->raw,pos,SEEK_SET); int bytes_read = fread(data,1,bytes_to_read,rp->raw); if(bytes_read==bytes_to_read){ if(datalen) *datalen = bytes_read; return 0; } return -1; // some kind of EOF? } return 0; // no problems!}int raw_update_seg(AFFILE *af, const char *name, unsigned long arg,const void *value,unsigned int vallen){ struct raw_private *rp = RAW_PRIVATE(af); /* Simple implementation; only updates data segments */ int64 pagenum = af_segname_page_number(name); if(pagenum<0){ errno = ENOTSUP; return -1; // not a segment number } int64 pos = pagenum * af->image_pagesize; // where we are to start reading fseeko(rp->raw,pos,SEEK_SET); if(fwrite(value,vallen,1,rp->raw)==1){ return 0; } return -1; // some kind of error...}static int raw_vstat(AFFILE *af,struct af_vnode_info *vni){ struct raw_private *rp = RAW_PRIVATE(af); vni->imagesize = -1; vni->pagesize = RAW_PAGESIZE; // decent page size vni->supports_metadata = 0; vni->changable_pagesize = 1; // change it at any time vni->changable_sectorsize = 1; // change it at any time /* If we can stat the file, use that. */ fflush(rp->raw); struct stat sb; if(fstat(fileno(rp->raw),&sb)==0){ if(sb.st_mode & S_IFREG){ // only do this for regular files vni->imagesize = sb.st_size; } } if(vni->imagesize==-1){ /* See if this is a device that we can figure */ struct af_figure_media_buf afb; if(af_figure_media(fileno(rp->raw),&afb)==0){ if(afb.total_sectors>0 && afb.sector_size>0){ vni->imagesize = afb.total_sectors * afb.sector_size; } } } vni->supports_compression = 0; vni->has_pages = 1; if(rp->raw_popen){ /* popen files require special handling */ vni->has_pages = 0; vni->use_eof = 1; vni->at_eof = feof(rp->raw); // are we there yet? } return 0;}static int raw_rewind_seg(AFFILE *af){ af->cur_page = 0; return 0;}static int raw_get_next_seg(AFFILE *af,char *segname,size_t segname_len,unsigned long *arg, unsigned char *data,size_t *datalen){ /* See if we are at the end of the "virtual" segment list */ if(af->cur_page * af->image_pagesize >= af->image_size) return -1; /* Make the segment name */ char pagename[AF_MAX_NAME_LEN]; // memset(pagename,0,sizeof(pagename)); snprintf(pagename,sizeof(pagename),AF_PAGE,af->cur_page++); /* Get the segment, if we can */ int r = raw_get_seg(af,pagename,arg,data,datalen); /* If r==0 and there is room for copying in the segment name, return it */ if(r==0){ if(strlen(pagename)+1 < segname_len){ strcpy(segname,pagename); return 0; } /* segname wasn't big enough */ return -2; } return r; // some other error}static int raw_read(AFFILE *af, unsigned char *buf, uint64 pos,size_t count){ struct raw_private *rp = RAW_PRIVATE(af); fseek(rp->raw,pos,SEEK_SET); return fread(buf,1,count,rp->raw);}static int raw_write(AFFILE *af, unsigned char *buf, uint64 pos,size_t count){ struct raw_private *rp = RAW_PRIVATE(af); fseek(rp->raw,pos,SEEK_SET); return fwrite(buf,1,count,rp->raw);}struct af_vnode vnode_raw = { AF_IDENTIFY_RAW, AF_VNODE_TYPE_PRIMITIVE|AF_VNODE_TYPE_RELIABLE, "Raw", raw_identify_file, raw_open, raw_close, raw_vstat, raw_get_seg, // get seg raw_get_next_seg, // get_next_seg raw_rewind_seg, // rewind_seg raw_update_seg, // update_seg 0, // del_seg raw_read, // read raw_write // write};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -