📄 vnode_split_raw.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_split_raw.h"#ifdef HAVE_CTYPE_H#include <ctype.h>#endif#ifndef HAVE_ISDIGITstatic int isdigit(char ch){ return ch>='0' && ch<='9';}#endif/* split raw file implementation with optional metadata support */struct split_raw_private { uint num_raw_files; // number of raw files int *fds; // array of file descriptors for each open raw file uint64 *pos; // where we are in each file char *first_raw_fname; /* The filename of the first raw file. */ char *next_raw_fname; /* The filename of the next raw file, or 0 when one big file is used. */ int64 cur_page; // current page number, used for split_raw_get_next_seg};static inline struct split_raw_private *SPLIT_RAW_PRIVATE(AFFILE *af){ assert(af->v == &vnode_split_raw); return (struct split_raw_private *)(af->vnodeprivate);}static inline const char *last4(const char *filename){ if(strlen(filename)>4) { const char *l = filename+strlen(filename)-4; return l; } return "";}/* Return 1 if a file is a split raw file... */static int split_raw_identify_file(const char *filename,int exists){ if(exists && access(filename,R_OK)!=0) return 0; // needs to exist and it doesn't const char *l4 = last4 (filename); return (!strcmp (l4, ".000")) || (!strcmp (l4, ".001")) || (!strcasecmp (l4, ".aaa"));}/* split_raw_close: * Close each of the split files. */static int split_raw_close(AFFILE *af){ struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af); for (uint64 i = 0; i < srp->num_raw_files; i++){ close (srp->fds[i]); } if (srp->fds) free (srp->fds); if (srp->pos) free (srp->pos); if (srp->first_raw_fname) free (srp->first_raw_fname); if (srp->next_raw_fname) free (srp->next_raw_fname); free(srp); af->vnodeprivate = 0; return 0;}/* increment_fname(): * takes filesname.000 and turns it into filename.001 * takes filename.aaa and makes it filename.aab * fn must be at least 3 characters long. * Returns 0 if successful, or -1 if it runs out of namespace. */static int increment_fname (char *fn){ /* Scan to the end of the string, minus 3 */ while (fn[3]) fn++; if (fn[2] == '9') { fn[2] = '0'; if (fn[1] == '9') { fn[1] = '0'; if (fn[0] == '9') return -1; fn[0]++; } else { fn[1]++; } } else if (isdigit (fn[2])) { fn[2]++; } else if ((fn[2] == 'Z') || (fn[2] == 'z')) { fn[2] -= 25; fn[1]++; } else if ((fn[2] == 'L') || (fn[2] == 'l')) { /* We don't want to treat .afm as a valid raw file, since it is an * AFF metadata file. So if we would end up with .afm as the name of the * raw file, report being out of namespace instead. */ if ((fn[1] == 'F') || (fn[1] == 'f')) errno = EINVAL; return -1; fn[2]++; } else { fn[2]++; } return 0;}void srp_validate(AFFILE *af){ struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af); for(unsigned int i=0;i<srp->num_raw_files;i++){ assert(srp->fds[i]!=0); }} void srp_dump(AFFILE *af){ struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af); for(unsigned int i=0;i<srp->num_raw_files;i++){ fprintf(stderr," fds[%d]=%d pos[%d]=%"I64d"\n",i,srp->fds[i],i,srp->pos[i]); } srp_validate(af); fprintf(stderr,"===================\n");} static void srp_add_fd(AFFILE *af,int fd){ struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af); srp->num_raw_files++; srp->fds = (int *)realloc (srp->fds, sizeof (int) * (srp->num_raw_files)); srp->fds[srp->num_raw_files - 1] = fd; srp->pos = (uint64 *)realloc (srp->pos, sizeof (uint64) * (srp->num_raw_files)); srp->pos[srp->num_raw_files - 1] = 0;}static int split_raw_open_internal(AFFILE *af, uint64 *image_size){ struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af); int fd; struct stat sb; fd = open(srp->first_raw_fname, af->openflags|O_BINARY, 0666); if (fd < 0) { (*af->error_reporter)("split_raw_open_internal: open(%s): ",af->fname); return -1; } srp->num_raw_files = 1; srp->fds = (int *)malloc (sizeof (int)); srp->fds[0] = fd; srp->pos = (uint64 *)malloc (sizeof (uint64)); if (fstat (fd, &sb) != 0) { (*af->error_reporter)("split_raw_open_internal: fstat(%s): ",af->fname); close (fd); return -1; } af->maxsize = 0; /* If there's a next_raw_fname set by the caller of this function, we * have a split file; otherwise we have one big file. */ if (srp->next_raw_fname==0) { (*image_size) = sb.st_size; return 0; } /* This gets set to 1 the first time we find a file whose size doesn't match the size of the first file. If we successfully open a file when this flag is already 1, then our sanity checks fail. */ int current_file_must_be_last = 0; do { if (increment_fname (srp->next_raw_fname) != 0) { fprintf (stderr, "split_raw_open_internal: too many files\n"); errno = EINVAL; return -1; } fd = open(srp->next_raw_fname, af->openflags & O_RDWR ? (O_RDWR|O_BINARY) : (O_RDONLY|O_BINARY)); if (fd < 0) { if (errno != ENOENT) { (af->error_reporter)("split_raw_open_internal errno=%d",errno); return -1; } (*image_size) = sb.st_size + af->maxsize * (srp->num_raw_files - 1); errno = 0; // reset errno return 0; // end of files } srp_add_fd(af,fd); if (current_file_must_be_last) { fprintf(stderr, "split_raw_open_internal: %s exists, " "but previous file didn't match expected file size\n",af->fname); return -1; } /* Set af->maxsize to the size of the first file, but only if a second file exists. If no second file exists, then we want to use af->maxsize, which cannot be set until after af_open returns. */ if (!af->maxsize) af->maxsize = sb.st_size; if (fstat (fd, &sb) != 0) { (*af->error_reporter)("split_raw_open_internal: fstat(%s): ",af->fname); return -1; } if ((uint64)sb.st_size != af->maxsize){ current_file_must_be_last = 1; } } while (1); return -1;}static int split_raw_open(AFFILE *af){ int ret; af->vnodeprivate = (void *)calloc(sizeof(struct split_raw_private),1); struct split_raw_private *srp = SPLIT_RAW_PRIVATE(af); srp->first_raw_fname = strdup (af->fname); srp->next_raw_fname = strdup (af->fname); ret = split_raw_open_internal (af, &(af->image_size)); if (ret != 0) { split_raw_close (af); return ret; } /* Adaptively find the largest pagesize we can use that fits within maxsize */ af->image_pagesize = 512; while ((af->image_pagesize < (16 * 1024 * 1024)) && !(af->maxsize % (af->image_pagesize * 2))) af->image_pagesize *= 2; if ((ret == 0) && (af->maxsize % af->image_pagesize!=0)) { fprintf (stderr, "split_raw_open: %s: raw_file_size (%"I64d" not a multiple of pagesize %lu\n", af->fname, af->maxsize,af->image_pagesize); split_raw_close (af); return -1; } return 0;}static int split_raw_vstat(AFFILE *af,struct af_vnode_info *vni){ memset(vni,0,sizeof(*vni)); // clear it
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -