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; }
/* Add a file to the AFF system. * if fname==0, create a new one and copy over the relevant metadata... */ static int afd_add_file(AFFILE *af,const char *fname_) { struct afd_private *ap = AFD_PRIVATE(af); const char *segs_to_copy[] = {AF_BADFLAG, AF_CASE_NUM, AF_IMAGE_GID, AF_ACQUISITION_ISO_COUNTRY, AF_ACQUISITION_COMMAND_LINE, AF_ACQUISITION_DATE, AF_ACQUISITION_NOTES, AF_ACQUISITION_DEVICE, AF_ACQUISITION_TECHNICIAN, AF_DEVICE_MANUFACTURER, AF_DEVICE_MODEL, AF_DEVICE_SN, AF_DEVICE_FIRMWARE, AF_DEVICE_SOURCE, AF_CYLINDERS, AF_HEADS, AF_SECTORS_PER_TRACK, AF_LBA_SIZE, AF_HPA_PRESENT, AF_DCO_PRESENT, AF_LOCATION_IN_COMPUTER, AF_DEVICE_CAPABILITIES, 0}; char fname[MAXPATHLEN+1]; memset(fname,0,sizeof(fname)); if(fname_){ strlcpy(fname,fname_,sizeof(fname)); } else { aff_filename(af,fname,sizeof(fname),ap->num_afs); } int new_file = access(fname,F_OK)!=0; // Is this a new file? AFFILE *af2 = af_open(fname,af->openflags|AF_NO_CRYPTO,af->openmode); if(af2==0){ (*af->error_reporter)("open(%s,%d,%d) failed: %s\n", fname,af->openflags,af->openmode,strerror(errno)); return -1; // this is bad } ap->num_afs += 1; ap->afs = (AFFILE **)realloc(ap->afs,sizeof(AFFILE *) * ap->num_afs); ap->afs[ap->num_afs-1] = af2; if(new_file){ /* Copy over configuration from AFD vnode*/ af_enable_compression(af2,af->compression_type,af->compression_level); af_set_pagesize(af2,af->image_pagesize); // af_set_sectorsize(af2,af->image_sectorsize); af_update_seg(af,AF_AFF_FILE_TYPE,0,(const u_char *)"AFD",3); /* If this is the second file, copy over additional metadata from first... */ if(ap->num_afs>1){ AFFILE *af0 = ap->afs[0]; memcpy(af2->badflag,af0->badflag,af->image_sectorsize); af2->bytes_memcpy += af->image_sectorsize; for(const char **segname=segs_to_copy;*segname;segname++){ unsigned char data[65536]; // big enough for most metadata size_t datalen = sizeof(data); unsigned long arg=0; if(af_get_seg(af0,*segname,&arg,data,&datalen)==0){ int r = af_update_seg(af2,*segname,arg,data,datalen); if(r!=0){ (*af->error_reporter)("afd_add_file: could not update %s in %s (r=%d)", *segname,af_filename(af2),r); } } } } } 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_t 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_t *)&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 the AFF image_size has been set */ if (ap->aff->image_size && 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 */ uint32_t 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; }