static int skip_to_next_header(uint8_t *sam_stat) { MHVTL_DBG(1, "skip_to_next_header"); if (raw_pos.hdr.blk_type == B_EOD) { sam_blank_check(E_END_OF_DATA, sam_stat); MHVTL_DBG(1, "End of data detected while forward SPACEing!!"); return -1; } if (raw_pos.next_blk != lseek64(datafile, raw_pos.next_blk, SEEK_SET)) { sam_medium_error(E_SEQUENTIAL_POSITION_ERR, sam_stat); MHVTL_DBG(1, "Unable to seek to next block header"); return -1; } if (read_header(&raw_pos, sam_stat)) { sam_medium_error(E_SEQUENTIAL_POSITION_ERR, sam_stat); MHVTL_DBG(1, "Unable to read next block header"); return -1; } /* Position to start of header (rewind over header) */ if (raw_pos.curr_blk != position_to_curr_header(sam_stat)) { sam_medium_error(E_SEQUENTIAL_POSITION_ERR, sam_stat); MHVTL_DBG(1, "Error position in datafile. Offset: %" PRId64, raw_pos.curr_blk); return -1; } return 0; }
static int read_header(uint32_t blk_number, uint8_t *sam_stat) { loff_t nread; if (blk_number > eod_blk_number) { MHVTL_ERR("Attempt to seek [%d] beyond EOD [%d]", blk_number, eod_blk_number); } else if (blk_number == eod_blk_number) mkEODHeader(eod_blk_number, eod_data_offset); else { nread = pread(indxfile, &raw_pos, sizeof(raw_pos), blk_number * sizeof(raw_pos)); if (nread < 0) { MHVTL_ERR("Medium format corrupt"); sam_medium_error(E_MEDIUM_FMT_CORRUPT, sam_stat); return -1; } else if (nread != sizeof(raw_pos)) { MHVTL_ERR("Failed to read next header"); sam_medium_error(E_END_OF_DATA, sam_stat); return -1; } } MHVTL_DBG(3, "Reading header %d at offset %ld, type: %s, size: %d", raw_pos.hdr.blk_number, (unsigned long)raw_pos.data_offset, mhvtl_block_type_desc(raw_pos.hdr.blk_type), raw_pos.hdr.blk_size); return 0; }
/* * Rewind to beginning of data file and the position to first data header. * * Return 0 -> Not loaded. * 1 -> Load OK * 2 -> format corrupt. */ int rewind_tape(uint8_t *sam_stat) { MHVTL_DBG(1, "rewind_tape"); if (rawRewind(sam_stat)) { sam_medium_error(E_MEDIUM_FMT_CORRUPT, sam_stat); return 2; } if (raw_pos.hdr.blk_type != B_BOT) { sam_medium_error(E_MEDIUM_FMT_CORRUPT, sam_stat); return 2; } if (skip_to_next_header(sam_stat)) return 2; switch (MediumType) { case MEDIA_TYPE_CLEAN: OK_to_write = 0; break; case MEDIA_TYPE_WORM: /* Special condition... * If we * - rewind, * - write filemark * - EOD * We set this as writable media as the tape is blank. */ if (raw_pos.hdr.blk_type != B_EOD) OK_to_write = 0; /* Check that this header is a filemark and the next header * is End of Data. If it is, we are OK to write */ if (raw_pos.hdr.blk_type == B_FILEMARK) { skip_to_next_header(sam_stat); if (raw_pos.hdr.blk_type == B_EOD) OK_to_write = 1; } /* Now we have to go thru thru the rewind again.. */ if (rawRewind(sam_stat)) { sam_medium_error(E_MEDIUM_FMT_CORRUPT, sam_stat); return 2; } /* No need to do all previous error checking... */ skip_to_next_header(sam_stat); break; case MEDIA_TYPE_DATA: OK_to_write = 1; /* Reset flag to OK. */ break; } MHVTL_DBG(1, "Media is %s", (OK_to_write) ? "writable" : "not writable"); return 1; }
static int check_for_overwrite(uint8_t *sam_stat) { MHVTL_DBG(1, "check_for_overwrite"); #if NOTDEF uint32_t blk_number; uint64_t data_offset; int i; if (raw_pos.hdr.blk_type == B_EOD) return 0; MHVTL_DBG(2, "At block %ld", (unsigned long)raw_pos.hdr.blk_number); /* We aren't at EOD so we are performing a rewrite. Truncate * the data and index files back to the current length. */ blk_number = raw_pos.hdr.blk_number; data_offset = raw_pos.data_offset; if (ftruncate(indxfile, blk_number * sizeof(raw_pos))) { sam_medium_error(E_WRITE_ERROR, sam_stat); MHVTL_LOG("Index file ftruncate failure, pos: " "%" PRId64 ": %s", (uint64_t)blk_number * sizeof(raw_pos), strerror(errno)); return -1; } if (ftruncate(datafile, data_offset)) { sam_medium_error(E_WRITE_ERROR, sam_stat); MHVTL_LOG("Data file ftruncate failure, pos: " "%" PRId64 ": %s", data_offset, strerror(errno)); return -1; } /* Update the filemark map removing any filemarks which will be * overwritten. Rewrite the filemark map so that the on-disk image * of the map is consistent with the new sizes of the other two files. */ for (i = 0; i < meta.filemark_count; i++) { MHVTL_DBG(2, "filemarks[%d] %d", i, filemarks[i]); if (filemarks[i] >= blk_number) { MHVTL_DBG(2, "Setting filemark_count from %d to %d", meta.filemark_count, i); meta.filemark_count = i; return rewrite_meta_file(); } } #endif return 0; }
static int read_header(struct raw_header *h, uint8_t *sam_stat) { MHVTL_DBG(1, "read_header"); loff_t nread; nread = read(datafile, h, sizeof(*h)); if (nread < 0) { sam_medium_error(E_MEDIUM_FMT_CORRUPT, sam_stat); return -1; } else if (nread != sizeof(*h)) { sam_medium_error(E_END_OF_DATA, sam_stat); return -1; } return 0; }
int write_tape_block(const uint8_t *buf, uint32_t blk_size, uint32_t comp_size, const struct encryption *cp, uint8_t *sam_stat) { loff_t nwrite; uint32_t iosize; MHVTL_DBG(1, "write_tape_block"); if (!tape_loaded(sam_stat)) return -1; /* If comp_size is non-zero then the data is compressed, so use comp_size for the I/O size. If comp_size is zero, the data is non-compressed, so use the blk_size as the I/O size. */ iosize = comp_size ? comp_size : blk_size; if (mkNewHeader(B_DATA, blk_size, comp_size, cp, sam_stat)) { MHVTL_DBG(1, "Failed to write header"); sam_medium_error(E_WRITE_ERROR, sam_stat); return -1; } /* now write the block of data.. */ nwrite = write(datafile, buf, iosize); if (nwrite <= 0) { MHVTL_DBG(1, "failed to write %d bytes, %s", iosize, strerror(errno)); sam_medium_error(E_WRITE_ERROR, sam_stat); return -1; } else if (nwrite != iosize) { MHVTL_DBG(1, "Did not write all data"); sam_medium_error(E_WRITE_ERROR, sam_stat); return -1; } /* Write END-OF-DATA marker */ if (mkEODHeader(sam_stat)) { MHVTL_DBG(1, "Did not write EOD"); sam_medium_error(E_WRITE_ERROR, sam_stat); return -1; } return 0; }
static int skip_to_prev_header(uint8_t *sam_stat) { MHVTL_DBG(1, "skip_to_prev_header"); /* Position to previous header */ MHVTL_DBG(3, "Positioning to raw_pos.prev_blk: %" PRId64, raw_pos.prev_blk); if (raw_pos.prev_blk != lseek64(datafile, raw_pos.prev_blk, SEEK_SET)) { sam_medium_error(E_MEDIUM_FMT_CORRUPT, sam_stat); MHVTL_DBG(1, "Error position in datafile !!"); return -1; } /* Read in header */ MHVTL_DBG(3, "Reading in header: %d bytes", (int)sizeof(raw_pos)); if (read_header(&raw_pos, sam_stat)) { MHVTL_DBG(1, "Error reading datafile while reverse SPACEing"); return -1; } if (raw_pos.hdr.blk_type == B_BOT) { MHVTL_DBG(3, "Found Beginning Of Tape, " "Skipping to next header.."); skip_to_next_header(sam_stat); sam_medium_error(E_BOM, sam_stat); MHVTL_DBG(3, "Found BOT!!"); return -1; } /* Position to start of header (rewind over header) */ if (raw_pos.curr_blk != position_to_curr_header(sam_stat)) { sam_medium_error(E_SEQUENTIAL_POSITION_ERR, sam_stat); MHVTL_DBG(1, "Error position in datafile !!"); return -1; } MHVTL_DBG(3, "Rewinding over header just read in: " "curr_position: %" PRId64, raw_pos.curr_blk); return 0; }
/* * Writes data in struct MAM back to beginning of datafile.. * Returns 0 if nothing written or -1 on error */ int rewriteMAM(uint8_t *sam_stat) { loff_t nwrite = 0; MHVTL_DBG(1, "rewriteMAM"); /* Rewrite MAM data */ nwrite = pwrite(datafile, &mam, sizeof(mam), sizeof(struct blk_header)); if (nwrite != sizeof(mam)) { sam_medium_error(E_MEDIUM_FMT_CORRUPT, sam_stat); return -1; } MediumType = mam.MediumType; return 0; }
int rewriteMAM(uint8_t *sam_stat) { loff_t nwrite = 0; if (!tape_loaded(sam_stat)) return -1; /* Rewrite MAM data */ nwrite = pwrite(metafile, &mam, sizeof(mam), 0); if (nwrite != sizeof(mam)) { sam_medium_error(E_MEDIUM_FMT_CORRUPT, sam_stat); return -1; } return nwrite; }
static int mkEODHeader(uint8_t *sam_stat) { MHVTL_DBG(1, "mkEODHeader"); if (mkNewHeader(B_EOD, 0, 0, NULL, sam_stat)) return -1; if (MediumType == MEDIA_TYPE_WORM) OK_to_write = 1; /* If we have just written a END OF DATA marker, * rewind to just before it. */ /* Position to start of header (rewind over header) */ if (raw_pos.curr_blk != position_to_curr_header(sam_stat)) { sam_medium_error(E_SEQUENTIAL_POSITION_ERR, sam_stat); MHVTL_DBG(1, "Failed to write EOD header"); return -1; } return 0; }
int load_tape(const char *pcl, uint8_t *sam_stat) { char pcl_data[1024], pcl_indx[1024], pcl_meta[1024]; struct stat data_stat, indx_stat, meta_stat; uint64_t exp_size; size_t io_size; loff_t nread; int rc = 0; int null_media_type; char touch_file[128]; uint8_t error_check; snprintf(touch_file, 127, "%s/bypass_error_check", MHVTL_HOME_PATH); error_check = (stat(touch_file, &data_stat) == -1) ? FALSE : TRUE; if (error_check) { MHVTL_LOG("WARNING - touch file %s found - bypassing sanity checks on open", touch_file); } /* KFRDEBUG - sam_stat needs updates in lots of places here. */ /* If some other PCL is already open, return. */ if (datafile >= 0) return 1; /* Open all three files and stat them to get their current sizes. */ if (strlen(home_directory)) snprintf(currentPCL, ARRAY_SIZE(currentPCL), "%s/%s", home_directory, pcl); else snprintf(currentPCL, ARRAY_SIZE(currentPCL), "%s/%s", MHVTL_HOME_PATH, pcl); snprintf(pcl_data, ARRAY_SIZE(pcl_data), "%s/data", currentPCL); snprintf(pcl_indx, ARRAY_SIZE(pcl_indx), "%s/indx", currentPCL); snprintf(pcl_meta, ARRAY_SIZE(pcl_meta), "%s/meta", currentPCL); MHVTL_DBG(2, "Opening media: %s", pcl); if (stat(pcl_data, &data_stat) == -1) { MHVTL_DBG(2, "Couldn't find %s, trying previous default: %s/%s", pcl_data, MHVTL_HOME_PATH, pcl); snprintf(currentPCL, ARRAY_SIZE(currentPCL), "%s/%s", MHVTL_HOME_PATH, pcl); snprintf(pcl_data, ARRAY_SIZE(pcl_data), "%s/data", currentPCL); snprintf(pcl_indx, ARRAY_SIZE(pcl_indx), "%s/indx", currentPCL); snprintf(pcl_meta, ARRAY_SIZE(pcl_meta), "%s/meta", currentPCL); } datafile = open(pcl_data, O_RDWR|O_LARGEFILE); if (datafile == -1) { MHVTL_ERR("open of pcl %s file %s failed, %s", pcl, pcl_data, strerror(errno)); rc = 3; goto failed; } indxfile = open(pcl_indx, O_RDWR|O_LARGEFILE); if (indxfile == -1) { MHVTL_ERR("open of pcl %s file %s failed, %s", pcl, pcl_indx, strerror(errno)); rc = 3; goto failed; } metafile = open(pcl_meta, O_RDWR|O_LARGEFILE); if (metafile == -1) { MHVTL_ERR("open of pcl %s file %s failed, %s", pcl, pcl_meta, strerror(errno)); rc = 3; goto failed; } if (fstat(datafile, &data_stat) < 0) { MHVTL_ERR("stat of pcl %s file %s failed: %s", pcl, pcl_data, strerror(errno)); rc = 3; goto failed; } if (fstat(indxfile, &indx_stat) < 0) { MHVTL_ERR("stat of pcl %s file %s failed: %s", pcl, pcl_indx, strerror(errno)); rc = 3; goto failed; } if (fstat(metafile, &meta_stat) < 0) { MHVTL_ERR("stat of pcl %s file %s failed: %s", pcl, pcl_meta, strerror(errno)); rc = 3; goto failed; } /* Verify that the metafile size is at least reasonable. */ exp_size = sizeof(mam) + sizeof(meta); if ((uint32_t)meta_stat.st_size < exp_size) { MHVTL_ERR("sizeof(mam) + sizeof(meta) - " "pcl %s file %s is not the correct length, " "expected at least %" PRId64 ", actual %" PRId64, pcl, pcl_meta, exp_size, meta_stat.st_size); if (error_check) { rc = 2; goto failed; } } /* Read in the MAM and sanity-check it. */ nread = read(metafile, &mam, sizeof(mam)); if (nread < 0) { MHVTL_ERR("Error reading pcl %s MAM from metafile: %s", pcl, strerror(errno)); if (error_check) { rc = 2; goto failed; } } else if (nread != sizeof(mam)) { MHVTL_ERR("Error reading pcl %s MAM from metafile: " "unexpected read length", pcl); if (error_check) { rc = 2; goto failed; } } null_media_type = mam.MediumType == MEDIA_TYPE_NULL ? 1 : 0; if (mam.tape_fmt_version != TAPE_FMT_VERSION) { MHVTL_ERR("pcl %s MAM contains incorrect media format", pcl); sam_medium_error(E_MEDIUM_FMT_CORRUPT, sam_stat); if (error_check) { rc = 2; goto failed; } } /* Read in the meta_header structure and sanity-check it. */ nread = read(metafile, &meta, sizeof(meta)); if (nread < 0) { MHVTL_ERR("Error reading pcl %s meta_header from " "metafile: %s", pcl, strerror(errno)); rc = 2; goto failed; } else if (nread != sizeof(meta)) { MHVTL_ERR("Error reading pcl %s meta header from " "metafile: unexpected read length", pcl); rc = 2; goto failed; } /* Now recompute the correct size of the meta file. */ exp_size = sizeof(mam) + sizeof(meta) + (meta.filemark_count * sizeof(*filemarks)); if ((uint32_t)meta_stat.st_size != exp_size) { MHVTL_ERR("sizeof(mam) + sizeof(meta) + sizeof(*filemarks) - " "pcl %s file %s is not the correct length, " "expected %" PRId64 ", actual %" PRId64, pcl, pcl_meta, exp_size, meta_stat.st_size); if (error_check) { rc = 2; goto failed; } } /* See if we have allocated enough space for the actual number of filemarks on the tape. If not, realloc now. */ if (check_filemarks_alloc(meta.filemark_count)) { if (error_check) { rc = 3; goto failed; } } /* Now read in the filemark map. */ io_size = meta.filemark_count * sizeof(*filemarks); if (io_size) { nread = read(metafile, filemarks, io_size); if (nread < 0) { MHVTL_ERR("Error reading pcl %s filemark map from " "metafile: %s", pcl, strerror(errno)); rc = 2; goto failed; } else if ((size_t)nread != io_size) { MHVTL_ERR("Error reading pcl %s filemark map from " "metafile: unexpected read length", pcl); if (error_check) { rc = 2; goto failed; } } } /* Use the size of the indx file to work out where the virtual B_EOD block resides. */ if ((indx_stat.st_size % sizeof(struct raw_header)) != 0) { MHVTL_ERR("pcl %s indx file has improper length, indicating " "possible file corruption", pcl); rc = 2; goto failed; } eod_blk_number = indx_stat.st_size / sizeof(struct raw_header); /* Make sure that the filemark map is consistent with the size of the indx file. */ if (meta.filemark_count && eod_blk_number && filemarks[meta.filemark_count - 1] >= eod_blk_number) { MHVTL_ERR("pcl %s indx file has improper length as compared " "to the meta file, indicating possible file corruption", pcl); MHVTL_ERR("Filemark count: %d eod_blk_number: %d", meta.filemark_count, eod_blk_number); rc = 2; goto failed; } /* Read in the last raw_header struct from the indx file and use that to validate the correct size of the data file. */ if (eod_blk_number == 0) eod_data_offset = 0; else { if (read_header(eod_blk_number - 1, sam_stat)) { rc = 3; goto failed; } eod_data_offset = raw_pos.data_offset + raw_pos.hdr.disk_blk_size; } if (null_media_type) { MHVTL_LOG("Loaded NULL media type"); /* Skip check */ } else if ((uint64_t)data_stat.st_size != eod_data_offset) { MHVTL_ERR("st_size != eod_data_offset - " "pcl %s file %s is not the correct length, " "expected %" PRId64 ", actual %" PRId64, pcl, pcl_data, eod_data_offset, data_stat.st_size); if (error_check) { rc = 2; goto failed; } } /* Give a hint to the kernel that data, once written, tends not to be accessed again immediately. */ posix_fadvise(indxfile, 0, 0, POSIX_FADV_DONTNEED); posix_fadvise(datafile, 0, 0, POSIX_FADV_DONTNEED); /* Now initialize raw_pos by reading in the first header, if any. */ if (read_header(0, sam_stat)) { rc = 3; goto failed; } return 0; failed: if (datafile >= 0) { close(datafile); datafile = -1; } if (indxfile >= 0) { close(indxfile); indxfile = -1; } if (metafile >= 0) { close(metafile); metafile = -1; } return rc; }
int write_tape_block(const uint8_t *buffer, uint32_t blk_size, uint32_t comp_size, const struct encryption *encryptp, uint8_t comp_type, uint8_t null_media_type, uint8_t *sam_stat) { uint32_t blk_number, disk_blk_size; uint32_t max_blk_number; uint64_t data_offset; ssize_t nwrite; /* Medium format limits to unsigned 32bit blks */ max_blk_number = 0xfffffff0; if (!tape_loaded(sam_stat)) return -1; if (check_for_overwrite(sam_stat)) return -1; /* Preserve existing raw_pos data we need, then clear out raw_pos and fill it in with new data. */ blk_number = raw_pos.hdr.blk_number; data_offset = raw_pos.data_offset; if (blk_number > max_blk_number) { MHVTL_ERR("Too many tape blocks - 32byte overflow"); return -1; } memset(&raw_pos, 0, sizeof(raw_pos)); raw_pos.data_offset = data_offset; raw_pos.hdr.blk_type = B_DATA; /* Header type */ raw_pos.hdr.blk_flags = 0; raw_pos.hdr.blk_number = blk_number; raw_pos.hdr.blk_size = blk_size; /* Size of uncompressed data */ if (comp_size) { if (comp_type == LZO) raw_pos.hdr.blk_flags |= BLKHDR_FLG_LZO_COMPRESSED; else raw_pos.hdr.blk_flags |= BLKHDR_FLG_ZLIB_COMPRESSED; raw_pos.hdr.disk_blk_size = disk_blk_size = comp_size; } else raw_pos.hdr.disk_blk_size = disk_blk_size = blk_size; if (encryptp != NULL) { unsigned int i; raw_pos.hdr.blk_flags |= BLKHDR_FLG_ENCRYPTED; raw_pos.hdr.encryption.ukad_length = encryptp->ukad_length; for (i = 0; i < encryptp->ukad_length; ++i) raw_pos.hdr.encryption.ukad[i] = encryptp->ukad[i]; raw_pos.hdr.encryption.akad_length = encryptp->akad_length; for (i = 0; i < encryptp->akad_length; ++i) raw_pos.hdr.encryption.akad[i] = encryptp->akad[i]; raw_pos.hdr.encryption.key_length = encryptp->key_length; for (i = 0; i < encryptp->key_length; ++i) raw_pos.hdr.encryption.key[i] = encryptp->key[i]; } /* Now write out both the data and the header. */ if (null_media_type) { nwrite = disk_blk_size; } else nwrite = pwrite(datafile, buffer, disk_blk_size, data_offset); if (nwrite != disk_blk_size) { sam_medium_error(E_WRITE_ERROR, sam_stat); MHVTL_ERR("Data file write failure, pos: %" PRId64 ": %s", data_offset, strerror(errno)); /* Truncate last partital write */ MHVTL_DBG(1, "Truncating data file size: %"PRId64, data_offset); if (ftruncate(datafile, data_offset) < 0) { MHVTL_ERR("Error truncating data: %s", strerror(errno)); } mkEODHeader(blk_number, data_offset); return -1; } nwrite = pwrite(indxfile, &raw_pos, sizeof(raw_pos), blk_number * sizeof(raw_pos)); if (nwrite != sizeof(raw_pos)) { long indxsz = (blk_number - 1) * sizeof(raw_pos); sam_medium_error(E_WRITE_ERROR, sam_stat); MHVTL_ERR("Index file write failure, pos: %" PRId64 ": %s", (uint64_t)blk_number * sizeof(raw_pos), strerror(errno)); MHVTL_DBG(1, "Truncating index file size to: %ld", indxsz); if (ftruncate(indxfile, indxsz) < 0) { MHVTL_ERR("Error truncating indx: %s", strerror(errno)); } if (!null_media_type) { MHVTL_DBG(1, "Truncating data file size: %"PRId64, data_offset); if (ftruncate(datafile, data_offset) < 0) { MHVTL_ERR("Error truncating data: %s", strerror(errno)); } } mkEODHeader(blk_number, data_offset); return -1; } MHVTL_DBG(3, "Successfully wrote block: %u", blk_number); return mkEODHeader(blk_number + 1, data_offset + disk_blk_size); }
int write_filemarks(uint32_t count, uint8_t *sam_stat) { uint32_t blk_number; uint64_t data_offset; ssize_t nwrite; if (!tape_loaded(sam_stat)) return -1; /* Applications assume that writing a filemark (even writing zero filemarks) will force-flush any data buffered in the drive to media so that after the write-filemarks call returns there is no possibility that any data previously written could be lost due to a power hit. Provide a similar guarantee here. */ if (count == 0) { MHVTL_DBG(2, "Flushing data - 0 filemarks written"); fsync(datafile); fsync(indxfile); fsync(metafile); return 0; } if (check_for_overwrite(sam_stat)) return -1; /* Preserve existing raw_pos data we need, then clear raw_pos and fill it in with new data. */ blk_number = raw_pos.hdr.blk_number; data_offset = raw_pos.data_offset; memset(&raw_pos, 0, sizeof(raw_pos)); raw_pos.data_offset = data_offset; raw_pos.hdr.blk_type = B_FILEMARK; /* Header type */ raw_pos.hdr.blk_flags = 0; raw_pos.hdr.blk_number = blk_number; raw_pos.hdr.blk_size = 0; raw_pos.hdr.disk_blk_size = 0; /* Now write out one header per filemark. */ for ( ; count > 0; count--, blk_number++) { raw_pos.hdr.blk_number = blk_number; MHVTL_DBG(3, "Writing filemark: block %d", blk_number); nwrite = pwrite(indxfile, &raw_pos, sizeof(raw_pos), blk_number * sizeof(raw_pos)); if (nwrite != sizeof(raw_pos)) { sam_medium_error(E_WRITE_ERROR, sam_stat); MHVTL_ERR("Index file write failure," " pos: %" PRId64 ": %s", (uint64_t)blk_number * sizeof(raw_pos), strerror(errno)); return -1; } add_filemark(blk_number); } /* Provide the force-flush guarantee. */ fsync(datafile); fsync(indxfile); fsync(metafile); return mkEODHeader(blk_number, data_offset); }
int load_tape(const char *pcl, uint8_t *sam_stat) { loff_t nread; uint32_t version = 0; MHVTL_DBG(1, "load_tape"); /* KFRDEBUG - sam_stat needs updates in lots of places here. */ #if NOTDEF if (datafile == -1) /* return 1; */ /* don't return 1 here */ return 0; #endif sprintf(currentMedia, "%s/%s", MHVTL_HOME_PATH, pcl); /* MHVTL_DBG(2, "Opening file/media %s", currentMedia); */ MHVTL_LOG("Opening file/media %s", currentMedia); datafile = open(currentMedia, O_RDWR|O_LARGEFILE); if (datafile == -1) { MHVTL_DBG(1, "%s: open file/media failed, %s", currentMedia, strerror(errno)); return 3; /* Unsuccessful load */ } /* Now read in header information from just opened datafile */ nread = read(datafile, &raw_pos, sizeof(raw_pos)); if (nread < 0) { MHVTL_LOG("%s: %s", "Error reading header in datafile, load failed", strerror(errno)); close(datafile); datafile = -1; return 4; /* Unsuccessful load */ } else if (nread < sizeof(raw_pos)) { /* Did not read anything... */ MHVTL_LOG("%s: %s", "Error: Not a tape format, load failed", strerror(errno)); close(datafile); datafile = -1; return 5; } if (raw_pos.hdr.blk_type != B_BOT) { MHVTL_LOG("Header type: %d not valid, load failed", raw_pos.hdr.blk_type); close(datafile); datafile = -1; return 6; } /* FIXME: Need better validation checking here !! */ if (raw_pos.next_blk != (sizeof(raw_pos) + sizeof(mam))) { MHVTL_LOG("MAM size incorrect, load failed" " - Expected size: %d, size found: %" PRId64, (int)(sizeof(raw_pos) + sizeof(mam)), raw_pos.next_blk); close(datafile); datafile = -1; return 7; /* Unsuccessful load */ } nread = read(datafile, &mam, sizeof(mam)); if (nread < 0) { MHVTL_LOG("Can not read MAM from mounted media, %s", strerror(errno)); close(datafile); datafile = -1; return 8; /* Unsuccessful load */ } if (nread != sizeof(mam)) { MHVTL_LOG("Can not read MAM from mounted media, " "insufficient data"); close(datafile); datafile = -1; return 9; /* Unsuccessful load */ } version = mam.tape_fmt_version; if (version != TAPE_FMT_VERSION) { MHVTL_LOG("Incorrect media format %lu", version); sam_medium_error(E_MEDIUM_FMT_CORRUPT, sam_stat); close(datafile); datafile = -1; return 10; } MediumType = mam.MediumType; c_pos = &raw_pos.hdr; return 0; }
static int mkNewHeader(uint32_t type, int blk_size, int comp_size, const struct encryption *cp, uint8_t *sam_stat) { struct raw_header h; MHVTL_DBG(1, "mkNewHeader"); memset(&h, 0, sizeof(h)); h.hdr.blk_type = type; /* Header type */ h.hdr.blk_flags = 0; h.hdr.blk_number = raw_pos.hdr.blk_number; if (type != B_DATA) { h.hdr.blk_size = 0; h.hdr.disk_blk_size = 0; } else { h.hdr.blk_size = blk_size; /* Size of uncompressed data */ if (comp_size) { h.hdr.blk_flags |= BLKHDR_FLG_COMPRESSED; h.hdr.disk_blk_size = comp_size; } else { h.hdr.disk_blk_size = blk_size; } if (cp != NULL) { int i; h.hdr.blk_flags |= BLKHDR_FLG_ENCRYPTED; h.hdr.encryption.ukad_length = cp->ukad_length; for (i = 0; i < cp->ukad_length; ++i) h.hdr.encryption.ukad[i] = cp->ukad[i]; h.hdr.encryption.akad_length = cp->akad_length; for (i = 0; i < cp->akad_length; ++i) h.hdr.encryption.akad[i] = cp->akad[i]; h.hdr.encryption.key_length = cp->key_length; for (i = 0; i < cp->key_length; ++i) h.hdr.encryption.key[i] = cp->key[i]; } } /* Update current position */ h.curr_blk = lseek64(datafile, 0, SEEK_CUR); /* If we are writing a new EOD marker, * - then set next pointer to itself * else * - Set pointer to next header (header size + size of data) */ if (type == B_EOD) h.next_blk = h.curr_blk; else h.next_blk = h.curr_blk + h.hdr.disk_blk_size + sizeof(h); if (h.curr_blk == raw_pos.curr_blk) { /* If current pos == last header read in we are about to overwrite the * current header block */ h.prev_blk = raw_pos.prev_blk; h.hdr.blk_number = raw_pos.hdr.blk_number; } else if (h.curr_blk == raw_pos.next_blk) { /* New header block at end of data file.. */ h.prev_blk = raw_pos.curr_blk; h.hdr.blk_number = raw_pos.hdr.blk_number + 1; } else { MHVTL_DBG(1, "Position error blk No: %d, Pos: %" PRId64 ", Exp: %" PRId64, h.hdr.blk_number, h.curr_blk, raw_pos.curr_blk); sam_medium_error(E_SEQUENTIAL_POSITION_ERR, sam_stat); return -1; } if (write(datafile, &h, sizeof(h)) != sizeof(h)) { sam_medium_error(E_WRITE_ERROR, sam_stat); MHVTL_DBG(1, "Write failure, pos: %" PRId64 ": %s", h.curr_blk, strerror(errno)); return -1; } /* * Write was successful, update raw_pos with this header block. */ memcpy(&raw_pos, &h, sizeof(h)); /* Update where we think we are.. */ return 0; }