예제 #1
0
파일: ssc.c 프로젝트: aroundrobin/mhvtl
uint8_t ssc_report_density_support(struct scsi_cmd *cmd)
{
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;
	uint8_t media;

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;

	media = cmd->scb[1] & 0x01;
	cmd->dbuf_p->sz = 0;

	MHVTL_DBG(1, "Report %s Density Support (%ld) **",
					(media) ? "mounted Media" : "Drive",
					(long)cmd->dbuf_p->serialNo);

	if (cmd->scb[1] & 0x02) { /* Don't support Medium Type (yet) */
		MHVTL_DBG(1, "Medium Type - not currently supported");
		mkSenseBuf(ILLEGAL_REQUEST, E_INVALID_FIELD_IN_CDB, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}

	if (media == 1 && lu_priv->tapeLoaded != TAPE_LOADED) {
		MHVTL_DBG(1, "Media has to be mounted to return media density");
		mkSenseBuf(NOT_READY, E_MEDIUM_NOT_PRESENT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}

	cmd->dbuf_p->sz = get_unaligned_be16(&cmd->scb[7]);
	cmd->dbuf_p->sz = resp_report_density(lu_priv, media, cmd->dbuf_p);
	return SAM_STAT_GOOD;
}
예제 #2
0
파일: ssc.c 프로젝트: aroundrobin/mhvtl
uint8_t ssc_write_attributes(struct scsi_cmd *cmd)
{
	int sz;
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;

	MHVTL_DBG(1, "Write Attributes (%ld) **", (long)cmd->dbuf_p->serialNo);

	switch (lu_priv->tapeLoaded) {
	case TAPE_UNLOADED:
		mkSenseBuf(NOT_READY, E_MEDIUM_NOT_PRESENT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	case TAPE_LOADED:
		cmd->dbuf_p->sz = get_unaligned_be32(&cmd->scb[10]);
		sz = retrieve_CDB_data(cmd->cdev, cmd->dbuf_p);
		MHVTL_DBG(1, "  --> Expected to read %d bytes"
				", read %d", cmd->dbuf_p->sz, sz);
		if (resp_write_attribute(cmd) > 0)
			rewriteMAM(sam_stat);
		break;
	default:
		mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	}
	return SAM_STAT_GOOD;
}
예제 #3
0
파일: ssc.c 프로젝트: aroundrobin/mhvtl
uint8_t ssc_erase(struct scsi_cmd *cmd)
{
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;

	MHVTL_DBG(1, "Erasing (%ld) **", (long)cmd->dbuf_p->serialNo);

	current_state = MHVTL_STATE_ERASE;

	if (!lu_priv->pm->check_restrictions(cmd))
		return SAM_STAT_CHECK_CONDITION;

	if (c_pos->blk_number != 0) {
		MHVTL_LOG("Not at BOT.. Can't erase unless at BOT");
		mkSenseBuf(NOT_READY, E_INVALID_FIELD_IN_CDB, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}

	if (OK_to_write)
		format_tape(sam_stat);
	else {
		MHVTL_LOG("Attempt to erase Write-protected media");
		mkSenseBuf(NOT_READY, E_MEDIUM_OVERWRITE_ATTEMPTED, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}
	return SAM_STAT_GOOD;
}
예제 #4
0
파일: ssc.c 프로젝트: aroundrobin/mhvtl
uint8_t ssc_read_position(struct scsi_cmd *cmd)
{
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;
	int service_action;

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;

	MHVTL_DBG(1, "Read Position (%ld) **", (long)cmd->dbuf_p->serialNo);

	service_action = cmd->scb[1] & 0x1f;
	/* service_action == 0 or 1 -> Returns 20 bytes of data (short) */

	*sam_stat = SAM_STAT_GOOD;

	switch (lu_priv->tapeLoaded) {
	case TAPE_LOADED:
		if ((service_action == 0) || (service_action == 1))
			cmd->dbuf_p->sz = resp_read_position(c_pos->blk_number,
							cmd->dbuf_p->data,
							sam_stat);
		break;
	case TAPE_UNLOADED:
		mkSenseBuf(NOT_READY, E_MEDIUM_NOT_PRESENT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	default:
		mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	}
	return *sam_stat;
}
예제 #5
0
파일: ssc.c 프로젝트: aroundrobin/mhvtl
uint8_t ssc_read_media_sn(struct scsi_cmd *cmd)
{
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;

	MHVTL_DBG(1, "Read Medium Serial No. (%ld) **",
						(long)cmd->dbuf_p->serialNo);
	switch (lu_priv->tapeLoaded) {
	case TAPE_LOADED:
		cmd->dbuf_p->sz = resp_read_media_serial(lu_priv->mediaSerialNo,
							cmd->dbuf_p->data,
							sam_stat);
		break;
	case TAPE_UNLOADED:
		mkSenseBuf(NOT_READY, E_MEDIUM_NOT_PRESENT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	default:
		mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	}
	return *sam_stat;
}
예제 #6
0
파일: vtlcart.c 프로젝트: aroundrobin/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");
			mkSenseBuf(MEDIUM_ERROR,E_MEDIUM_FMT_CORRUPT, sam_stat);
			return -1;
		} else if (nread != sizeof(raw_pos)) {
			MHVTL_ERR("Failed to read next header");
			mkSenseBuf(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;
}
예제 #7
0
파일: ssc.c 프로젝트: aroundrobin/mhvtl
uint8_t ssc_rewind(struct scsi_cmd *cmd)
{
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;
	int retval;

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;

	MHVTL_DBG(1, "Rewinding (%ld) **", (long)cmd->dbuf_p->serialNo);

	current_state = MHVTL_STATE_REWIND;

	switch (lu_priv->tapeLoaded) {
	case TAPE_UNLOADED:
		mkSenseBuf(NOT_READY, E_MEDIUM_NOT_PRESENT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	case TAPE_LOADED:
		retval = rewind_tape(sam_stat);
		if (retval < 0) {
			mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat);
			return SAM_STAT_CHECK_CONDITION;
		}
		break;
	default:
		mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	}

	return SAM_STAT_GOOD;
}
예제 #8
0
파일: ssc.c 프로젝트: aroundrobin/mhvtl
uint8_t ssc_allow_overwrite(struct scsi_cmd *cmd)
{
	uint8_t *cdb = cmd->scb;
	uint8_t allow_overwrite = cdb[2] & 0x0f;
	uint8_t partition = cdb[3];
	uint8_t *sam_stat = &cmd->dbuf_p->sam_stat;
	uint8_t ret_stat = SAM_STAT_GOOD;
	uint64_t allow_overwrite_block;
	struct priv_lu_ssc *lu_ssc;

	lu_ssc = cmd->lu->lu_private;

	if (allow_overwrite > 2) /* Truncate bad values 3 to 15 -> '3' */
		allow_overwrite = 3;

	MHVTL_DBG(1, "ALLOW OVERWRITE (%ld) : %s **",
			(long)cmd->dbuf_p->serialNo,
			allow_overwrite_desc[allow_overwrite].desc);

	lu_ssc->allow_overwrite = FALSE;

	switch (allow_overwrite) {
	case 0:
		break;
	case 1:  /* current position */
		if (partition) { /* Paritions not supported at this stage */
			MHVTL_LOG("Partitions not implemented at this time");
			mkSenseBuf(ILLEGAL_REQUEST,
					E_INVALID_FIELD_IN_CDB,
					sam_stat);
			return SAM_STAT_CHECK_CONDITION;
		}
		allow_overwrite_block = get_unaligned_be64(&cdb[4]);
		MHVTL_DBG(1, "Allow overwrite block: %lld",
					(long long)allow_overwrite_block);
		if (allow_overwrite_block == current_tape_block()) {
			lu_ssc->allow_overwrite_block = allow_overwrite_block;
			lu_ssc->allow_overwrite = TRUE;
		} else {
			/* Set allow_overwrite position to an invalid number */
			lu_ssc->allow_overwrite_block = 0;
			lu_ssc->allow_overwrite_block--;
			mkSenseBuf(ILLEGAL_REQUEST,
					E_SEQUENTIAL_POSITIONING_ERROR,
					sam_stat);
			ret_stat = SAM_STAT_CHECK_CONDITION;
		}
		break;
	case 2:
		lu_ssc->allow_overwrite = 2;
		break;
	default:
		mkSenseBuf(ILLEGAL_REQUEST, E_INVALID_FIELD_IN_CDB, sam_stat);
		ret_stat = SAM_STAT_CHECK_CONDITION;
		break;
	}

	return ret_stat;
}
예제 #9
0
파일: vtlcart.c 프로젝트: aroundrobin/mhvtl
int
position_blocks_forw(uint32_t count, uint8_t *sam_stat)
{
	uint32_t residual;
	uint32_t blk_target;
	unsigned int i;

	if (!tape_loaded(sam_stat)) {
		return -1;
	}

	if (mam.MediumType == MEDIA_TYPE_WORM)
		OK_to_write = 0;

	blk_target = raw_pos.hdr.blk_number + count;

	/* Find the first filemark forward from our current position, if any. */

	for (i = 0; i < meta.filemark_count; i++) {
		MHVTL_DBG(3, "filemark at %ld", (unsigned long)filemarks[i]);
		if (filemarks[i] >= raw_pos.hdr.blk_number) {
			break;
		}
	}

	/* If there is one, see if it is between our current position and our
	   desired destination.
	*/

	if (i < meta.filemark_count) {
		if (filemarks[i] >= blk_target) {
			return position_to_block(blk_target, sam_stat);
		}

		residual = blk_target - raw_pos.hdr.blk_number + 1;
		if (read_header(filemarks[i] + 1, sam_stat)) {
			return -1;
		}
		MHVTL_DBG(1, "Filemark encountered: block %d", filemarks[i]);
		mkSenseBuf(NO_SENSE | SD_FILEMARK, E_MARK, sam_stat);
		put_unaligned_be32(residual, &sense[3]);
		return -1;
	}

	if (blk_target > eod_blk_number) {
		residual = blk_target - eod_blk_number;
		if (read_header(eod_blk_number, sam_stat)) {
			return -1;
		}
		MHVTL_DBG(1, "EOD encountered");
		mkSenseBuf(BLANK_CHECK, E_END_OF_DATA, sam_stat);
		put_unaligned_be32(residual, &sense[3]);
		return -1;
	}

	return position_to_block(blk_target, sam_stat);
}
예제 #10
0
파일: vtlcart.c 프로젝트: aroundrobin/mhvtl
static int
check_for_overwrite(uint8_t *sam_stat)
{
	uint32_t blk_number;
	uint64_t data_offset;
	unsigned 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))) {
		mkSenseBuf(MEDIUM_ERROR, E_WRITE_ERROR, sam_stat);
		MHVTL_ERR("Index file ftruncate failure, pos: "
			"%" PRId64 ": %s",
			(uint64_t)blk_number * sizeof(raw_pos),
			strerror(errno));
		return -1;
	}
	if (ftruncate(datafile, data_offset)) {
		mkSenseBuf(MEDIUM_ERROR, E_WRITE_ERROR, sam_stat);
		MHVTL_ERR("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();
		}
	}

	return 0;
}
예제 #11
0
파일: ssc.c 프로젝트: aroundrobin/mhvtl
uint8_t ssc_read_block_limits(struct scsi_cmd *cmd)
{
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;

	MHVTL_DBG(1, "Read block limits (%ld) **",
						(long)cmd->dbuf_p->serialNo);

	switch (lu_priv->tapeLoaded) {
	case TAPE_LOADED:
	case TAPE_UNLOADED:
		cmd->dbuf_p->sz = resp_read_block_limits(cmd->dbuf_p,
							lu_priv->bufsize);
		break;
	default:
		mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	}

	return SAM_STAT_GOOD;
}
예제 #12
0
파일: vtlcart.c 프로젝트: aroundrobin/mhvtl
int
position_filemarks_back(uint32_t count, uint8_t *sam_stat)
{
	uint32_t residual;
	int i;

	if (!tape_loaded(sam_stat)) {
		return -1;
	}

	if (mam.MediumType == MEDIA_TYPE_WORM)
		OK_to_write = 0;

	/* Find the block number of the first filemark less than our
	   current position.
	*/

	for (i = meta.filemark_count - 1; i >= 0; i--) {
		if (filemarks[i] < raw_pos.hdr.blk_number) {
			break;
		}
	}

	if (i + 1 >= count) {
		return position_to_block(filemarks[i - count + 1], sam_stat);
	} else {
		residual = count - i - 1;
		if (read_header(0, sam_stat)) {
			return -1;
		}
		mkSenseBuf(NO_SENSE | SD_EOM, E_BOM, sam_stat);
		put_unaligned_be32(residual, &sense[3]);
		return -1;
	}
}
예제 #13
0
파일: vtlcart.c 프로젝트: aroundrobin/mhvtl
int
position_filemarks_forw(uint32_t count, uint8_t *sam_stat)
{
	uint32_t residual;
	unsigned int i;

	if (!tape_loaded(sam_stat)) {
		return -1;
	}

	if (mam.MediumType == MEDIA_TYPE_WORM)
		OK_to_write = 0;

	/* Find the block number of the first filemark greater than our
	   current position.
	*/

	for (i = 0; i < meta.filemark_count; i++) {
		if (filemarks[i] >= raw_pos.hdr.blk_number) {
			break;
		}
	}

	if (i + count - 1 < meta.filemark_count) {
		return position_to_block(filemarks[i + count - 1] + 1, sam_stat);
	} else {
		residual = i + count - meta.filemark_count;
		if (read_header(eod_blk_number, sam_stat)) {
			return -1;
		}
		mkSenseBuf(BLANK_CHECK, E_END_OF_DATA, sam_stat);
		put_unaligned_be32(residual, &sense[3]);
		return -1;
	}
}
예제 #14
0
파일: vtlcart.c 프로젝트: aroundrobin/mhvtl
int position_to_block(uint32_t blk_number, uint8_t *sam_stat)
{
	if (!tape_loaded(sam_stat))
		return -1;

	MHVTL_DBG(2, "Position to block %d", blk_number);

	if (mam.MediumType == MEDIA_TYPE_WORM)
		OK_to_write = 0;

	if (blk_number > eod_blk_number) {
		mkSenseBuf(BLANK_CHECK, E_END_OF_DATA, sam_stat);
		MHVTL_DBG(1, "End of data detected while positioning");
		return position_to_eod(sam_stat);
	}

	/* Treat a position to block zero specially, as it has different
	   semantics than other blocks when the tape is WORM.
	*/

	if (blk_number == 0)
		return rewind_tape(sam_stat);
	else
		return read_header(blk_number, sam_stat);
}
예제 #15
0
파일: vtlcart.c 프로젝트: aroundrobin/mhvtl
static int
tape_loaded(uint8_t *sam_stat)
{
	if (datafile != -1) {
		return 1;
	}
	mkSenseBuf(NOT_READY, E_MEDIUM_NOT_PRESENT, sam_stat);
	return 0;
}
예제 #16
0
파일: ssc.c 프로젝트: aroundrobin/mhvtl
uint8_t ssc_load_unload(struct scsi_cmd *cmd)
{
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;
	int load;

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;

	load = cmd->scb[4] & 0x01;

	current_state = (load) ? MHVTL_STATE_LOADING : MHVTL_STATE_UNLOADING;

	if (cmd->scb[4] & 0x04) { /* EOT bit */
		MHVTL_ERR("EOT bit set on load. Not supported");
		mkSenseBuf(ILLEGAL_REQUEST, E_INVALID_FIELD_IN_CDB, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}

	MHVTL_DBG(1, "%s tape (%ld) **", (load) ? "Loading" : "Unloading",
						(long)cmd->dbuf_p->serialNo);

	switch (lu_priv->tapeLoaded) {
	case TAPE_UNLOADED:
		if (load)
			rewind_tape(sam_stat);
		else {
			mkSenseBuf(NOT_READY, E_MEDIUM_NOT_PRESENT, sam_stat);
			return SAM_STAT_CHECK_CONDITION;
		}
		break;

	case TAPE_LOADED:
		if (!load)
			unloadTape(sam_stat);
		break;

	default:
		mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	}
	return SAM_STAT_GOOD;
}
예제 #17
0
파일: ssc.c 프로젝트: aroundrobin/mhvtl
uint8_t valid_encryption_blk(struct scsi_cmd *cmd)
{
	uint8_t correct_key;
	int i;
	struct lu_phy_attr *lu = cmd->lu;
	struct priv_lu_ssc *lu_priv;
	struct encryption *encr;
	uint8_t *sam_stat = &cmd->dbuf_p->sam_stat;

	lu_priv = lu->lu_private;
	encr = lu_priv->encr;

	/* decryption logic */
	correct_key = TRUE;
	if (c_pos->blk_flags & BLKHDR_FLG_ENCRYPTED) {
		/* compare the keys */
		if (lu_priv->DECRYPT_MODE > 1) {
			if (c_pos->encryption.key_length != KEY_LENGTH) {
				mkSenseBuf(DATA_PROTECT, E_INCORRECT_KEY, sam_stat);
				correct_key = FALSE;
			}
			for (i = 0; i < c_pos->encryption.key_length; ++i) {
				if (c_pos->encryption.key[i] != KEY[i]) {
					mkSenseBuf(DATA_PROTECT,
							E_INCORRECT_KEY,
							sam_stat);
					correct_key = FALSE;
					return correct_key;
				}
			}
		} else {
			mkSenseBuf(DATA_PROTECT, E_UNABLE_TO_DECRYPT, sam_stat);
			correct_key = FALSE;
		}
	} else if (lu_priv->DECRYPT_MODE == 2) {
		mkSenseBuf(DATA_PROTECT, E_UNENCRYPTED_DATA, sam_stat);
		correct_key = FALSE;
	}
	return correct_key;
}
예제 #18
0
파일: ssc.c 프로젝트: aroundrobin/mhvtl
uint8_t ssc_read_attributes(struct scsi_cmd *cmd)
{
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;

	MHVTL_DBG(1, "Read Attribute (%ld) **",
						(long)cmd->dbuf_p->serialNo);

	switch (lu_priv->tapeLoaded) {
	case TAPE_UNLOADED:
		MHVTL_DBG(1, "Failed due to \"no media loaded\"");
		mkSenseBuf(NOT_READY, E_MEDIUM_NOT_PRESENT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	case TAPE_LOADED:
		break;
	default:
		MHVTL_DBG(1, "Failed due to \"media corrupt\"");
		mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	}

	/* Only support Service Action - Attribute Values */
	if (cmd->scb[1] > 1) {
		mkSenseBuf(ILLEGAL_REQUEST, E_INVALID_FIELD_IN_CDB, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}

	cmd->dbuf_p->sz = resp_read_attribute(cmd);

	return SAM_STAT_GOOD;
}
예제 #19
0
파일: vtlcart.c 프로젝트: aroundrobin/mhvtl
uint32_t
read_tape_block(uint8_t *buf, uint32_t buf_size, uint8_t *sam_stat)
{
	loff_t nread;
	uint32_t iosize;

	if (!tape_loaded(sam_stat))
		return -1;

	MHVTL_DBG(3, "Reading blk %ld, size: %d",
			(unsigned long)raw_pos.hdr.blk_number, buf_size);

	/* The caller should have already verified that this is a
	   B_DATA block before issuing this read, so we shouldn't have to
	   worry about B_EOD or B_FILEMARK here.
	*/

	if (raw_pos.hdr.blk_type == B_EOD) {
		mkSenseBuf(BLANK_CHECK, E_END_OF_DATA, sam_stat);
		MHVTL_ERR("End of data detected while reading");
		return -1;
	}

	iosize = raw_pos.hdr.disk_blk_size;
	if (iosize > buf_size)
		iosize = buf_size;

	nread = pread(datafile, buf, iosize, raw_pos.data_offset);
	if (nread != iosize) {
		MHVTL_ERR("Failed to read %d bytes", iosize);
		return -1;
	}

	// Now position to the following block.

	if (read_header(raw_pos.hdr.blk_number + 1, sam_stat)) {
		MHVTL_ERR("Failed to read block header %d",
				raw_pos.hdr.blk_number + 1);
		return -1;
	}

	return nread;
}
예제 #20
0
파일: vtlcart.c 프로젝트: aroundrobin/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)) {
		mkSenseBuf(MEDIUM_ERROR, E_MEDIUM_FMT_CORRUPT, sam_stat);
		return -1;
	}

	return nwrite;
}
예제 #21
0
파일: ssc.c 프로젝트: aroundrobin/mhvtl
uint8_t ssc_write_filemarks(struct scsi_cmd *cmd)
{
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;
	int count;

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;

	count = get_unaligned_be24(&cmd->scb[2]);

	MHVTL_DBG(1, "Write %d filemarks (%ld) **", count,
						(long)cmd->dbuf_p->serialNo);
	if (!lu_priv->pm->check_restrictions(cmd)) {
		/* If restrictions & WORM media at block 0.. OK
		 * Otherwise return CHECK_CONDITION.
		 *	check_restrictions()
		 *	was nice enough to set correct sense status for us.
		 */
		if ((mam.MediumType == MEDIA_TYPE_WORM) &&
					(c_pos->blk_number == 0)) {
			MHVTL_DBG(1, "Erasing WORM media");
		} else
			return SAM_STAT_CHECK_CONDITION;
	}

	write_filemarks(count, sam_stat);
	if (count) {
		if (current_tape_offset() >=
				get_unaligned_be64(&mam.max_capacity)) {
			mam.remaining_capacity = 0L;
			MHVTL_DBG(2, "Setting EOM flag");
			mkSenseBuf(NO_SENSE|SD_EOM, NO_ADDITIONAL_SENSE,
					sam_stat);
			return SAM_STAT_CHECK_CONDITION;
		}
	}

	return SAM_STAT_GOOD;
}
예제 #22
0
파일: ssc.c 프로젝트: aroundrobin/mhvtl
uint8_t ssc_format_media(struct scsi_cmd *cmd)
{
	struct lu_phy_attr *lu;
	struct priv_lu_ssc *lu_priv;

	lu = cmd->lu;
	lu_priv = lu->lu_private;

	MHVTL_DBG(1, "Format Medium (%ld) **", (long)cmd->dbuf_p->serialNo);

	if (!lu_priv->pm->check_restrictions(cmd))
		return SAM_STAT_CHECK_CONDITION;

	if (c_pos->blk_number != 0) {
		MHVTL_DBG(2, "Not at beginning **");
		mkSenseBuf(ILLEGAL_REQUEST, E_POSITION_PAST_BOM,
					&cmd->dbuf_p->sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}
	format_tape(&cmd->dbuf_p->sam_stat);

	return SAM_STAT_GOOD;
}
예제 #23
0
/*
 *
 * Process the SCSI command
 *
 * Called with:
 *	cdev          -> Char dev file handle,
 *	cdb           -> SCSI Command buffer pointer,
 *	struct vtl_ds -> general purpose data structure... Need better name
 *
 * Return:
 *	SAM status returned in struct vtl_ds.sam_stat
 */
static void processCommand(int cdev, uint8_t *cdb, struct vtl_ds *dbuf_p,
			useconds_t pollInterval)
{
	struct scsi_cmd _cmd;
	struct scsi_cmd *cmd;
	cmd = &_cmd;

	cmd->scb = cdb;
	cmd->scb_len = 16;	/* fixme */
	cmd->dbuf_p = dbuf_p;
	cmd->lu = &lunit;
	cmd->pollInterval = pollInterval;

	MHVTL_DBG_PRT_CDB(1, cmd);

	switch (cdb[0]) {
	case REPORT_LUNS:
	case REQUEST_SENSE:
	case MODE_SELECT:
	case INQUIRY:
		dbuf_p->sam_stat = SAM_STAT_GOOD;
		break;
	default:
		if (cmd->lu->online == 0) {
			mkSenseBuf(NOT_READY, E_OFFLINE, &dbuf_p->sam_stat);
			return;
		}
		if (check_reset(&dbuf_p->sam_stat))
			return;
	}

	if (cmd->lu->scsi_ops->ops[cdb[0]].pre_cmd_perform)
		cmd->lu->scsi_ops->ops[cdb[0]].pre_cmd_perform(cmd, NULL);

	dbuf_p->sam_stat = cmd->lu->scsi_ops->ops[cdb[0]].cmd_perform(cmd);
	return;
}
예제 #24
0
파일: ssc.c 프로젝트: aroundrobin/mhvtl
uint8_t valid_encryption_media(struct scsi_cmd *cmd)
{
	uint8_t *sam_stat = &cmd->dbuf_p->sam_stat;
	struct lu_phy_attr *lu;
	struct priv_lu_ssc *lu_priv;

	lu = cmd->lu;
	lu_priv = lu->lu_private;

	if (c_pos->blk_number == 0) {
		modeBlockDescriptor[0] = lu_priv->pm->native_drive_density->density;
		mam.MediumDensityCode = modeBlockDescriptor[0];
		mam.FormattedDensityCode = modeBlockDescriptor[0];
		rewriteMAM(sam_stat);
	} else {
		if (mam.MediumDensityCode !=
				lu_priv->pm->native_drive_density->density) {
			mkSenseBuf(DATA_PROTECT, E_WRITE_PROTECT, sam_stat);
			return SAM_STAT_CHECK_CONDITION;
		}
	}

	return SAM_STAT_GOOD;
}
예제 #25
0
파일: ssc.c 프로젝트: aroundrobin/mhvtl
uint8_t ssc_tur(struct scsi_cmd *cmd)
{
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;
	char str[64];

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;
	*sam_stat = SAM_STAT_GOOD;

	sprintf(str, "Test Unit Ready (%ld) ** : ",
				(long)cmd->dbuf_p->serialNo);

	switch (lu_priv->tapeLoaded) {
	case TAPE_UNLOADED:
		strcat(str, "No, No tape loaded");
		mkSenseBuf(NOT_READY, E_MEDIUM_NOT_PRESENT, sam_stat);
		*sam_stat = SAM_STAT_CHECK_CONDITION;
		break;
	case TAPE_LOADED:
		if (mam.MediumType == MEDIA_TYPE_CLEAN) {
			int state;

			strcat(str, "No, Cleaning cart loaded");

			if (lu_priv->cleaning_media_state)
				state = *lu_priv->cleaning_media_state;
			else
				state = 0;

			switch (state) {
			case CLEAN_MOUNT_STAGE1:
				mkSenseBuf(NOT_READY, E_CLEANING_CART_INSTALLED,
								sam_stat);
				break;
			case CLEAN_MOUNT_STAGE2:
				mkSenseBuf(NOT_READY, E_CAUSE_NOT_REPORTABLE,
								sam_stat);
				break;
			case CLEAN_MOUNT_STAGE3:
				mkSenseBuf(NOT_READY, E_INITIALIZING_REQUIRED,
								sam_stat);
				break;
			default:
				MHVTL_ERR("Unknown cleaning media mount state");
				mkSenseBuf(NOT_READY, E_CLEANING_CART_INSTALLED,
								sam_stat);
				break;
			}

			*sam_stat = SAM_STAT_CHECK_CONDITION;
		} else
			strcat(str, "Yes");
		break;
	default:
		strcat(str, "No, Media format corrupt");
		mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat);
		*sam_stat = SAM_STAT_CHECK_CONDITION;
		break;
	}

	MHVTL_DBG(1, "%s", str);

	return *sam_stat;
}
예제 #26
0
파일: vtlcart.c 프로젝트: aroundrobin/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;

/* 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);
	}

	if ((datafile = open(pcl_data, O_RDWR|O_LARGEFILE)) == -1) {
		MHVTL_ERR("open of pcl %s file %s failed, %s", pcl,
			pcl_data, strerror(errno));
		rc = 3;
		goto failed;
	}
	if ((indxfile = open(pcl_indx, O_RDWR|O_LARGEFILE)) == -1) {
		MHVTL_ERR("open of pcl %s file %s failed, %s", pcl,
			pcl_indx, strerror(errno));
		rc = 3;
		goto failed;
	}
	if ((metafile = open(pcl_meta, O_RDWR|O_LARGEFILE)) == -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("pcl %s file %s is not the correct length, "
			"expected at least %" PRId64 ", actual %" PRId64,
			pcl, pcl_meta, exp_size, meta_stat.st_size);
		rc = 2;
		goto failed;
	}

	/* Read in the MAM and sanity-check it. */

	if ((nread = read(metafile, &mam, sizeof(mam))) < 0) {
		MHVTL_ERR("Error reading pcl %s MAM from metafile: %s",
			pcl, strerror(errno));
		rc = 2;
		goto failed;
	} else if (nread != sizeof(mam)) {
		MHVTL_ERR("Error reading pcl %s MAM from metafile: "
			"unexpected read length", pcl);
		rc = 2;
		goto failed;
	}

	if (mam.tape_fmt_version != TAPE_FMT_VERSION) {
		MHVTL_ERR("pcl %s MAM contains incorrect media format", pcl);
		mkSenseBuf(MEDIUM_ERROR, E_MEDIUM_FMT_CORRUPT, sam_stat);
		rc = 2;
		goto failed;
	}

	/* Read in the meta_header structure and sanity-check it. */

	if ((nread = read(metafile, &meta, sizeof(meta))) < 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("pcl %s file %s is not the correct length, "
			"expected %" PRId64 ", actual %" PRId64, pcl,
			pcl_meta, exp_size, meta_stat.st_size);
		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)) {
		rc = 3;
		goto failed;
	}

	/* Now read in the filemark map. */

	io_size = meta.filemark_count * sizeof(*filemarks);
	if (io_size == 0) {
		/* do nothing */
	} else if ((nread = read(metafile, filemarks, io_size)) < 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);
		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 > 0 &&
		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);
		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 ((uint64_t)data_stat.st_size != eod_data_offset) {
		MHVTL_ERR("pcl %s file %s is not the correct length, "
			"expected %" PRId64 ", actual %" PRId64, pcl,
			pcl_data, eod_data_offset, data_stat.st_size);
		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;
}
예제 #27
0
파일: ssc.c 프로젝트: aroundrobin/mhvtl
/*
 * Process the MODE_SELECT command
 */
uint8_t ssc_mode_select(struct scsi_cmd *cmd)
{
	uint8_t *sam_stat = &cmd->dbuf_p->sam_stat;
	uint8_t *buf = cmd->dbuf_p->data;
	int block_descriptor_sz;
	int page_len;
	uint8_t *bdb = NULL;
	int i;
	int long_lba = 0;
	int count;
	int save_page;

	save_page = cmd->scb[1] & 0x01;

	switch (cmd->scb[0]) {
	case MODE_SELECT:
		cmd->dbuf_p->sz = cmd->scb[4];
		break;
	case MODE_SELECT_10:
		cmd->dbuf_p->sz = get_unaligned_be16(&cmd->scb[7]);
		break;
	default:
		cmd->dbuf_p->sz = 0;
	}

	count = retrieve_CDB_data(cmd->cdev, cmd->dbuf_p);

	MHVTL_DBG(1, "MODE SELECT (%ld) **", (long)cmd->dbuf_p->serialNo);

	if (!(cmd->scb[1] & 0x10)) { /* Page Format: 1 - SPC, 0 - vendor uniq */
		mkSenseBuf(ILLEGAL_REQUEST, E_INVALID_FIELD_IN_CDB, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}

	switch (cmd->scb[0]) {
	case MODE_SELECT:
		block_descriptor_sz = buf[3];
		if (block_descriptor_sz)
			bdb = &buf[4];
		i = 4 + block_descriptor_sz;
		break;
	case MODE_SELECT_10:
		block_descriptor_sz = get_unaligned_be16(&buf[6]);
		long_lba = buf[4] & 1;
		if (block_descriptor_sz)
			bdb = &buf[8];
		i = 8 + block_descriptor_sz;
		break;
	default:
		mkSenseBuf(ILLEGAL_REQUEST, E_INVALID_OP_CODE, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}

	if (bdb) {
		if (long_lba) {
			mkSenseBuf(ILLEGAL_REQUEST, E_INVALID_FIELD_IN_CDB,
							sam_stat);
			MHVTL_DBG(1, "Warning can not "
				"handle long descriptor block (long_lba bit)");
			return SAM_STAT_CHECK_CONDITION;
		}
		memcpy(modeBlockDescriptor, bdb, block_descriptor_sz);
	}

	/* Ignore mode pages if 'save page' bit not set */
	if (!save_page) {
		MHVTL_DBG(1, "Save page bit not set. Ignoring page data");
		return SAM_STAT_GOOD;
	}

#ifdef MHVTL_DEBUG
	if (debug)
		hex_dump(buf, cmd->dbuf_p->sz);
#endif

	MHVTL_DBG(3, "count: %d, i: %d", count, i);
	if (i == 4) {
	MHVTL_DBG(3, "Offset 0: %02x %02x %02x %02x",
			buf[0], buf[1], buf[2], buf[3]);
	} else {
	MHVTL_DBG(3, "Offset 0: %02x %02x %02x %02x  %02x %02x %02x %02x",
			buf[0], buf[1], buf[2], buf[3],
			buf[4], buf[5], buf[6], buf[7]);
	}

	count -= i;
	while (i < count) {
		MHVTL_DBG(3, " %02d: %02x %02x %02x %02x  %02x %02x %02x %02x",
			i,
			buf[i+0], buf[i+1], buf[i+2], buf[i+3],
			buf[i+4], buf[i+5], buf[i+6], buf[i+7]);
		MHVTL_DBG(3, " %02d: %02x %02x %02x %02x  %02x %02x %02x %02x",
			i+8,
			buf[i+8], buf[i+9], buf[i+10], buf[i+11],
			buf[i+12], buf[i+13], buf[i+14], buf[i+15]);
		MHVTL_DBG(3, " %02d: %02x %02x %02x %02x  %02x %02x %02x %02x",
			i+16,
			buf[i+16], buf[i+17], buf[i+18], buf[i+19],
			buf[i+20], buf[i+21], buf[i+22], buf[i+23]);
		MHVTL_DBG(3, " %02d: %02x %02x %02x %02x  %02x %02x %02x %02x",
			i+24,
			buf[i+24], buf[i+25], buf[i+26], buf[i+27],
			buf[i+28], buf[i+29], buf[i+30], buf[i+31]);
		/* Default page len is, override if sub-pages */
		page_len = buf[i + 1];
		switch (buf[i]) {
		case MODE_DATA_COMPRESSION:
			set_mode_compression(cmd, &buf[i]);
			break;

		case MODE_DEVICE_CONFIGURATION:
			/* If this is '01' it's a subpage value
			 *     i.e. DEVICE CONFIGURATION EXTENSION
			 * If it's 0x0e, it indicates a page length
			 * for MODE DEVICE CONFIGURATION
			 */
			if (buf[i + 1] == 0x01) {
				if (set_device_configuration_extension(cmd,
								&buf[i]))
					return SAM_STAT_CHECK_CONDITION;
				/* Subpage 1 - override default page length */
				page_len = get_unaligned_be16(&buf[i + 2]);
			} else
				set_device_configuration(cmd, &buf[i]);
			break;

		default:
			MHVTL_DBG_PRT_CDB(1, cmd);
			MHVTL_DBG(1, "Mode page 0x%02x not handled", buf[i]);
			break;
		}
		if (page_len == 0) { /* Something wrong with data structure */
			page_len = cmd->dbuf_p->sz;
			MHVTL_LOG("Problem with mode select data structure");
		}
		i += page_len;	/* Next mode page */
	}

	return SAM_STAT_GOOD;
}
예제 #28
0
파일: vtlcart.c 프로젝트: aroundrobin/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)) {
			mkSenseBuf(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);
}
예제 #29
0
파일: vtlcart.c 프로젝트: aroundrobin/mhvtl
int
position_blocks_back(uint32_t count, uint8_t *sam_stat)
{
	uint32_t residual;
	uint32_t blk_target;
	int i = -1;
	unsigned int num_filemarks = meta.filemark_count;

	if (!tape_loaded(sam_stat))
		return -1;

	if (mam.MediumType == MEDIA_TYPE_WORM)
		OK_to_write = 0;

	MHVTL_DBG(2, "Position before movement: %d", raw_pos.hdr.blk_number);

	if (count < raw_pos.hdr.blk_number)
		blk_target = raw_pos.hdr.blk_number - count;
	else
		blk_target = 0;

	/* Find the first filemark prior to our current position, if any. */

	if (num_filemarks > 0) {
		for (i = num_filemarks - 1; i <= (int)num_filemarks; i--) {
			MHVTL_DBG(3, "filemark at %ld", (unsigned long)filemarks[i]);
			if (filemarks[i] < raw_pos.hdr.blk_number)
				break;
		}
	}

	/* If there is one, see if it is between our current position and our
	   desired destination.
	*/
	if (i >= 0) {
		if (filemarks[i] < blk_target)
			return position_to_block(blk_target, sam_stat);

		residual = raw_pos.hdr.blk_number - blk_target;
		if (read_header(filemarks[i], sam_stat))
			return -1;

		MHVTL_DBG(2, "Filemark encountered: block %d", filemarks[i]);
		mkSenseBuf(NO_SENSE | SD_FILEMARK, E_MARK, sam_stat);
		put_unaligned_be32(residual, &sense[3]);
		return -1;
	}

	if (count > raw_pos.hdr.blk_number) {
		residual = count - raw_pos.hdr.blk_number;
		if (read_header(0, sam_stat))
			return -1;

		MHVTL_DBG(1, "BOM encountered");
		mkSenseBuf(NO_SENSE | SD_EOM, E_BOM, sam_stat);
		put_unaligned_be32(residual, &sense[3]);
		return -1;
	}

	return position_to_block(blk_target, sam_stat);
}
예제 #30
0
파일: vtlcart.c 프로젝트: aroundrobin/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 *sam_stat)
{
	uint32_t blk_number, disk_blk_size;
	uint64_t data_offset;
	ssize_t nwrite;

	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;

	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 header and the data. */

	nwrite = pwrite(indxfile, &raw_pos, sizeof(raw_pos),
		blk_number * sizeof(raw_pos));
	if (nwrite != sizeof(raw_pos)) {
		mkSenseBuf(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;
	}

	nwrite = pwrite(datafile, buffer, disk_blk_size, data_offset);
	if (nwrite != disk_blk_size) {
		mkSenseBuf(MEDIUM_ERROR, E_WRITE_ERROR, sam_stat);
		MHVTL_ERR("Data file write failure, pos: %" PRId64 ": %s",
			data_offset, strerror(errno));
		return -1;
	}

	MHVTL_DBG(3, "Successfully wrote block: %u", blk_number);

	return mkEODHeader(blk_number + 1, data_offset + disk_blk_size);
}