示例#1
0
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;
}
示例#2
0
文件: vtlcart.c 项目: fishky/mhvtl
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;
}
示例#3
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;
}
示例#4
0
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;
}
示例#5
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;
}
示例#6
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;
}
示例#7
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;
}
示例#8
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;
}
示例#9
0
文件: vtlcart.c 项目: fishky/mhvtl
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;
}
示例#10
0
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;
}
示例#11
0
文件: vtlcart.c 项目: fishky/mhvtl
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;
}
示例#12
0
文件: vtlcart.c 项目: fishky/mhvtl
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);
}
示例#13
0
文件: vtlcart.c 项目: fishky/mhvtl
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);
}
示例#14
0
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;
}
示例#15
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;
}