📄 vnode_split_raw.cpp
字号:
vni->imagesize = af->image_size; vni->pagesize = af->image_pagesize; vni->supports_compression = 0; vni->supports_metadata = 0; vni->changable_pagesize = 1; // change it at any time vni->changable_sectorsize = 1; // change it at any time return 0;}static int split_raw_read(AFFILE *af, unsigned char *buf, uint64 pos,size_t count){ struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af); off_t c3; int ret = 0; // how many bytes read if ((af->image_size - pos) < (unsigned)count){ count = (off_t)(af->image_size - pos); } while (count > 0) { int filenum = -1; off_t file_offset = 0; if (af->maxsize) { // if we do file segments filenum = (int)(pos / af->maxsize); file_offset = (off_t)(pos % af->maxsize); } else { filenum = 0; file_offset = (off_t)pos; } if (file_offset != (off_t) srp->pos[filenum]) { off_t c2 = lseek (srp->fds[filenum], file_offset, SEEK_SET); if (file_offset != c2) { // seek failed; return work to date if (ret) return ret; // some bytes were read; return that else return -1; // no bytes read; return error } srp->pos[filenum] = c2; // this file starts here } if (af->maxsize && ((af->maxsize - file_offset) < (unsigned) count)) c3 = (off_t)(af->maxsize - file_offset); else c3 = count; off_t c4 = read (srp->fds[filenum], buf, c3); if (c4 <= 0) { // got an error if (ret) return ret; // return how many bytes we read else return -1; // otherwise, return -1 } buf += c4; count -= c4; ret += c4; pos += c4; srp->pos[filenum] += c4; // position of this file pointer if (c3 != c4) return ret; // incomplete? } return ret;}/* * split_raw_write_internal2: * If buf==0, assume we are writing zeros to the end of the file, * and just seek to the last character and write a single NUL. */int split_raw_write_internal2(AFFILE *af, unsigned char *buf, uint64 pos,size_t count){ struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af); off_t c1, c3; int i; int ret = 0; struct affcallback_info acbi; /* Setup the callback structure */ memset(&acbi,0,sizeof(acbi)); acbi.info_version = 1; acbi.af = af->parent ? af->parent : af; acbi.pagenum = af->image_pagesize ? pos / af->image_pagesize : 0; acbi.bytes_to_write = count; while (count > 0) { if (af->maxsize) { // do we need to possibly split into multiple file writes? /* Figure out which file number we will need to write to... */ if (pos >= (af->maxsize * srp->num_raw_files)) { int fd = open(srp->next_raw_fname, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0666); if (fd < 0) { (*af->error_reporter)("split_raw_write: open(%s): ",af->fname); if (ret) return ret; else return -1; } srp_add_fd(af,fd); if (increment_fname (srp->next_raw_fname) != 0) { (*af->error_reporter)("split_raw_write: too many files\n"); if (ret) return ret; else return -1; } } i = (int)(pos / af->maxsize); c1 = (off_t)(pos % af->maxsize); } else { i = 0; c1 = (off_t)pos; } if (c1 != (off_t)srp->pos[i]) { // do we need to seek this file? off_t c2 = lseek (srp->fds[i], c1, SEEK_SET); // try to seek if (c1 != c2) { // hm. Ended up in the wrong place. That's an error if (ret>0) { // return how many bytes we got return ret; } else { return -1; } } srp->pos[i] = c2; } if (af->maxsize && ((af->maxsize - c1) < (unsigned)count)) c3 = (off_t)(af->maxsize - c1); else c3 = count; if(af->w_callback) {acbi.phase = 3;(*af->w_callback)(&acbi);} /* WRITE THE DATA! */ off_t c4 = 0; if(buf){ c4 = write (srp->fds[i], buf, c3); } else { /* Extend with lseek() and write a single byte */ char z = 0; lseek(srp->fds[i],c3-1,SEEK_CUR); write(srp->fds[i],&z,1); c4 = c3; } /* DONE! */ acbi.bytes_written = c4; if(af->w_callback) {acbi.phase = 4;(*af->w_callback)(&acbi);} if (c4 <= 0) { // some error writing? if (ret) return ret; else return -1; } buf += c4; count -= c4; ret += c4; pos += c4; srp->pos[i] += c4; if (af->image_size < pos) af->image_size = pos; // image was extended if (c3 != c4){ // amount written doesn't equal request; return return ret; } } return ret;}int split_raw_write(AFFILE *af, unsigned char *buf, uint64 pos,size_t count){ /* If we are being asked to start writing beyond the end of the file * pad out the file (and possibly create one or more new image files.) */ if (af->maxsize) { if (pos > af->image_size) { // writing beyond the end... while(pos > af->image_size){ /* repeat until file is as big as where we should be writing */ int64 bytes_left = pos - af->image_size; int bytes_to_write = (int)(af->maxsize - (af->image_size % af->maxsize)); if(bytes_to_write > bytes_left) bytes_to_write = (int)bytes_left; int bytes_written = split_raw_write_internal2(af,0,af->image_size,bytes_to_write); if(bytes_to_write != bytes_written){ return -1; // some kind of internal error } } } } return split_raw_write_internal2 (af, buf, pos,count);}/* Get a segment; if a data page is being asked for, then fake it. * Otherwise, return an error. */static int split_raw_get_seg(AFFILE *af,const char *name,unsigned long *arg,unsigned char *data, size_t *datalen){ int64 page_num = af_segname_page_number(name); if(page_num<0){ errno = ENOTSUP; // sorry! We don't store metadata return -1; } uint64 pos = page_num * af->image_pagesize; // where we are to start reading uint64 bytes_left = af->image_size - pos; // how many bytes left in the file unsigned int bytes_to_read = af->image_pagesize; // copy this many bytes, unless if(bytes_to_read > bytes_left) bytes_to_read = (unsigned int)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){ unsigned bytes_read = split_raw_read(af,data,pos,bytes_to_read); if(bytes_read==bytes_to_read){ if(datalen) *datalen = bytes_read; return 0; } return -1; // some kind of EOF? } return 0; // no problems!}/* * split_raw_get_next_seg: * Try get_next_seg on the AFF file first. If that fails, * create the next virtual segment */static int split_raw_get_next_seg(AFFILE *af,char *segname,size_t segname_len,unsigned long *arg, unsigned char *data,size_t *datalen_){ struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af); int64 total_pages = (af->image_size + af->image_pagesize - 1) / af->image_pagesize; if(srp->cur_page >= total_pages) return -1; // that's all there are /* Make the segment name */ char pagename[AF_MAX_NAME_LEN]; memset(pagename,0,sizeof(pagename)); snprintf(pagename,sizeof(pagename),AF_PAGE,srp->cur_page++); /* Get the segment, if we can */ int r = split_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}/* Rewind all of the segments */static int split_raw_rewind_seg(AFFILE *af){ struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af); srp->cur_page = 0; return 0;}static int split_raw_update_seg(AFFILE *af, const char *name, unsigned long arg,const void *value,unsigned int vallen) { int64 page_num = af_segname_page_number(name); if(page_num<0){ errno = ENOTSUP; // sorry! We don't store metadata return -1; } uint64 pos = page_num * af->image_pagesize; // where we are to start reading return split_raw_write(af, (unsigned char *)value, pos,vallen);}struct af_vnode vnode_split_raw = { AF_IDENTIFY_SPLIT_RAW, AF_VNODE_TYPE_COMPOUND|AF_VNODE_TYPE_RELIABLE|AF_VNODE_MAXSIZE_MULTIPLE, "Split Raw", split_raw_identify_file, split_raw_open, split_raw_close, split_raw_vstat, split_raw_get_seg, // get seg split_raw_get_next_seg, // get_next_seg split_raw_rewind_seg, // rewind_seg split_raw_update_seg, // update_seg 0, // del_seg split_raw_read, // read split_raw_write // write};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -