Esempio n. 1
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;
}
Esempio n. 2
0
static void init_3592_inquiry(struct lu_phy_attr *lu)
{
	int pg;
	uint8_t worm;
	uint8_t local_TapeAlert[8] =
			{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

	worm = ((struct priv_lu_ssc *)lu->lu_private)->pm->drive_supports_WORM;
	lu->inquiry[2] =
		((struct priv_lu_ssc *)lu->lu_private)->pm->drive_ANSI_VERSION;

	/* Sequential Access device capabilities - Ref: 8.4.2 */
	pg = PCODE_OFFSET(0xb0);
	lu->lu_vpd[pg] = alloc_vpd(VPD_B0_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_ERR("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_b0(lu, &worm);

	/* Manufacture-assigned serial number - Ref: 8.4.3 */
	pg = PCODE_OFFSET(0xb1);
	lu->lu_vpd[pg] = alloc_vpd(VPD_B1_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_ERR("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_b1(lu, lu->lu_serial_no);

	/* TapeAlert supported flags - Ref: 8.4.4 */
	pg = PCODE_OFFSET(0xb2);
	lu->lu_vpd[pg] = alloc_vpd(VPD_B2_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_ERR("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_b2(lu, &local_TapeAlert);

	/* VPD page 0xC0 */
	pg = PCODE_OFFSET(0xc0);
	lu->lu_vpd[pg] = alloc_vpd(VPD_C0_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_ERR("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_c0(lu, "10-03-2008 19:38:00");

	/* VPD page 0xC1 */
	pg = PCODE_OFFSET(0xc1);
	lu->lu_vpd[pg] = alloc_vpd(strlen("Security"));
	if (!lu->lu_vpd[pg]) {
		MHVTL_ERR("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_c1(lu, "Security");
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
static int
rewrite_meta_file(void)
{
	ssize_t io_size, nwrite;
	size_t io_offset;

	io_size = sizeof(meta);
	io_offset = sizeof(struct MAM);
	nwrite = pwrite(metafile, &meta, io_size, io_offset);
	if (nwrite < 0) {
		MHVTL_ERR("Error writing meta_header to metafile: %s",
					strerror(errno));
		return -1;
	}
	if (nwrite != io_size) {
		MHVTL_ERR("Error writing meta_header map to metafile."
				" Expected to write %d bytes", (int)io_size);
		return -1;
	}

	io_size = meta.filemark_count * sizeof(*filemarks);
	io_offset = sizeof(struct MAM) + sizeof(meta);

	if (io_size) {
		nwrite = pwrite(metafile, filemarks, io_size, io_offset);
		if (nwrite < 0) {
			MHVTL_ERR("Error writing filemark map to metafile: %s",
					strerror(errno));
			return -1;
		}
		if (nwrite != io_size) {
			MHVTL_ERR("Error writing filemark map to metafile."
				" Expected to write %d bytes", (int)io_size);
			return -1;
		}
	}

	/* If filemarks were overwritten, the meta file may need to be shorter
	   than before.
	*/

	if (ftruncate(metafile, io_offset + io_size) < 0) {
		MHVTL_ERR("Error truncating metafile: %s", strerror(errno));
		return -1;
	}

	return 0;
}
Esempio n. 5
0
static void update_scalar_vpd_83(struct  lu_phy_attr *lu)
{
	struct vpd *lu_vpd;
	struct smc_priv *smc_p;
	uint8_t *d;

	lu_vpd = lu->lu_vpd[PCODE_OFFSET(0x83)];
	smc_p = lu->lu_private;

	/* Unit Serial Number */
	if (lu_vpd)	/* Free any earlier allocation */
		dealloc_vpd(lu_vpd);

	lu_vpd = alloc_vpd(36);
	if (lu_vpd) {
		d = lu_vpd->data;
		d[0] = 0xf2;
		d[1] = 0x01;
		d[3] = 0x20;
		snprintf((char *)&d[4], 9, "%-8s", lu->vendor_id);
		snprintf((char *)&d[12], 25, "%-24s", lu->lu_serial_no);

	} else {
		MHVTL_ERR("Could not malloc(36) bytes, line %d", __LINE__);
	}
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
/* DLT7000 & DLT8000 */
static void init_dlt_inquiry(struct lu_phy_attr *lu)
{
	int pg;
	char b[32];
	int x, y, z;

	lu->inquiry[2] =
		((struct priv_lu_ssc *)lu->lu_private)->pm->drive_ANSI_VERSION;

	lu->inquiry[36] = get_product_family(lu);

	sprintf(b, "%s", MHVTL_VERSION);
	sscanf(b, "%d.%d.%d", &x, &y, &z);
	if (x) {
		lu->inquiry[37] = x;
		lu->inquiry[38] = y;
	} else {
		lu->inquiry[37] = y;
		lu->inquiry[38] = z;
	}

	/* VPD page 0xC0 */
	pg = PCODE_OFFSET(0xc0);
	lu->lu_vpd[pg] = alloc_vpd(44);
	if (!lu->lu_vpd[pg]) {
		MHVTL_ERR("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_dlt_c0(lu);

	/* VPD page 0xC1 */
	pg = PCODE_OFFSET(0xc1);
	lu->lu_vpd[pg] = alloc_vpd(44);
	if (!lu->lu_vpd[pg]) {
		MHVTL_ERR("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_dlt_c1(lu, lu->lu_serial_no);
}
Esempio n. 8
0
/*
 * Used by mode sense/mode select struct.
 *
 * Allocate 'size' bytes & init to 0
 * set first 2 bytes:
 *  byte[0] = pcode
 *  byte[1] = size - sizeof(byte[0])
 *
 * Return pointer to mode structure being init. or NULL if alloc failed
 */
struct mode *alloc_mode_page(struct list_head *m,
				uint8_t pcode, uint8_t subpcode, int size)
{
	struct mode *mp;

	MHVTL_DBG(3, "Allocating %d bytes for (%02x/%02x)",
					size, pcode, subpcode);

	mp = lookup_pcode(m, pcode, subpcode);
	if (!mp) {	/* Create a new entry */
		mp = (struct mode *)malloc(sizeof(struct mode));
	}
	if (mp) {
		mp->pcodePointer = (uint8_t *)malloc(size);
		if (mp->pcodePointer) {	/* If ! null, set size of data */
			memset(mp->pcodePointer, 0, size);
			mp->pcode = pcode;
			mp->subpcode = subpcode;
			mp->pcodeSize = size;

			/* Allocate a 'changeable bitmap' mode page info */
			mp->pcodePointerBitMap = malloc(size);
			if (!mp->pcodePointerBitMap) {
				free(mp);
				MHVTL_ERR("Unable to malloc(%d)", size);
				return NULL;
			}
			memset(mp->pcodePointerBitMap, 0, size);

			list_add_tail(&mp->siblings, m);
			return mp;
		} else {
			MHVTL_ERR("Unable to malloc(%d)", size);
			free(mp);
		}
	}
	return NULL;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
static void update_eml_vpd_80(struct lu_phy_attr *lu)
{
	struct vpd **lu_vpd = lu->lu_vpd;
	uint8_t *d;
	int pg;

	/* Unit Serial Number */
	pg = PCODE_OFFSET(0x80);
	if (lu_vpd[pg])		/* Free any earlier allocation */
		dealloc_vpd(lu_vpd[pg]);
	lu_vpd[pg] = alloc_vpd(0x12);
	if (lu_vpd[pg]) {
		d = lu_vpd[pg]->data;
		snprintf((char *)&d[0], 11, "%-10.10s", lu->lu_serial_no);
		/* Unique Logical Library Identifier */
	} else {
		MHVTL_ERR("Could not malloc(0x12) bytes, line %d", __LINE__);
	}
}
Esempio n. 11
0
static void update_stk_l_vpd_80(struct lu_phy_attr *lu)
{
	struct vpd *lu_vpd;
	uint8_t *d;

	lu_vpd = lu->lu_vpd[PCODE_OFFSET(0x80)];

	/* Unit Serial Number */
	if (lu_vpd)	/* Free any earlier allocation */
		dealloc_vpd(lu_vpd);

	lu_vpd = alloc_vpd(0x12);
	if (lu_vpd) {
		d = lu_vpd->data;
		/* d[4 - 15] Serial number of device */
		snprintf((char *)&d[0], 13, "%-12s", lu->lu_serial_no);
		/* Unique Logical Library Identifier */
	} else {
		MHVTL_ERR("Could not malloc(0x12) bytes, line %d", __LINE__);
	}
}
Esempio n. 12
0
static int check_filemarks_alloc(uint32_t count)
{
	uint32_t new_size;

	/* See if we have enough space allocated to hold 'count' filemarks.
	   If not, realloc now.
	*/

	if (count > (uint32_t)filemark_alloc) {
		new_size = ((count + FM_DELTA - 1) / FM_DELTA) * FM_DELTA;

		filemarks = (uint32_t *)realloc(filemarks,
						new_size * sizeof(*filemarks));
		if (filemarks == NULL) {
			MHVTL_ERR("filemark map realloc failed, %s",
				strerror(errno));
			return -1;
		}
		filemark_alloc = new_size;
	}
	return 0;
}
Esempio n. 13
0
static void update_scalar_vpd_80(struct  lu_phy_attr *lu)
{
	struct vpd *lu_vpd;
	struct smc_priv *smc_p;
	uint8_t *d;

	lu_vpd = lu->lu_vpd[PCODE_OFFSET(0x80)];
	smc_p = lu->lu_private;

	/* Unit Serial Number */
	if (lu_vpd)	/* Free any earlier allocation */
		dealloc_vpd(lu_vpd);

	lu_vpd = alloc_vpd(24);
	if (lu_vpd) {
		d = lu_vpd->data;
		/* d[4 - 27] Serial number prefixed by Vendor ID */
		snprintf((char *)&d[0], 25, "%-s%-17s", lu->vendor_id, lu->lu_serial_no);
	} else {
		MHVTL_ERR("Could not malloc(24) bytes, line %d", __LINE__);
	}
}
Esempio n. 14
0
static void init_9840_inquiry(struct lu_phy_attr *lu)
{
	int pg;
	uint8_t worm;

	worm = ((struct priv_lu_ssc *)lu->lu_private)->pm->drive_supports_WORM;
	lu->inquiry[2] =
		((struct priv_lu_ssc *)lu->lu_private)->pm->drive_ANSI_VERSION;

	lu->inquiry[3] = 0x42;
	lu->inquiry[4] = INQUIRY_LEN - 5;	/* Additional Length */
	lu->inquiry[54] = 0x04;	/* Key Management */
	lu->inquiry[55] = 0x12;	/* Support Encryption & Compression */

	/* Sequential Access device capabilities - Ref: 8.4.2 */
	pg = PCODE_OFFSET(0xb0);
	lu->lu_vpd[pg] = alloc_vpd(VPD_B0_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_ERR("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_b0(lu, &worm);
}
Esempio n. 15
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;
}
Esempio n. 16
0
int create_tape(const char *pcl, const struct MAM *mamp, uint8_t *sam_stat)
{
	struct stat data_stat;
	char newMedia[1024];
	char newMedia_data[1024];
	char newMedia_indx[1024];
	char newMedia_meta[1024];
	struct passwd *pw;
	int rc = 0;

	/* Attempt to create the new PCL.  This will fail if the PCL's directory
	   or any of the PCL's three files already exist, leaving any existing
	   files as they were.
	*/

	pw = getpwnam(USR);	/* Find UID for user 'vtl' */
	if (!pw) {
		MHVTL_ERR("Failed to get UID for user '%s': %s", USR,
			strerror(errno));
		return 1;
	}

	snprintf(newMedia, ARRAY_SIZE(newMedia), "%s/%s", home_directory, pcl);

	snprintf(newMedia_data, ARRAY_SIZE(newMedia_data), "%s/data", newMedia);
	snprintf(newMedia_indx, ARRAY_SIZE(newMedia_indx), "%s/indx", newMedia);
	snprintf(newMedia_meta, ARRAY_SIZE(newMedia_meta), "%s/meta", newMedia);

	/* Check if data file already exists, nothing to create */
	if (stat(newMedia_data, &data_stat) != -1)
		return 0;

	umask(0007);
	rc = mkdir(newMedia, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_ISGID);
	if (rc) {
		/* No need to fail just because the parent dir exists */
		if (errno != EEXIST) {
			MHVTL_ERR("Failed to create directory %s: %s",
					newMedia, strerror(errno));
			return 2;
		}
	}

	/* Don't really care if chown() fails or not..
	 * But lets try anyway
	 */
	chown(newMedia, pw->pw_uid, pw->pw_gid);

	datafile = creat(newMedia_data, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
	if (datafile == -1) {
		MHVTL_ERR("Failed to create file %s: %s", newMedia_data,
			strerror(errno));
		return 2;
	}
	indxfile = creat(newMedia_indx, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
	if (indxfile == -1) {
		MHVTL_ERR("Failed to create file %s: %s", newMedia_indx,
			strerror(errno));
		unlink(newMedia_data);
		rc = 2;
		goto cleanup;
	}
	metafile = creat(newMedia_meta, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
	if (metafile == -1) {
		MHVTL_ERR("Failed to create file %s: %s", newMedia_meta,
			strerror(errno));
		unlink(newMedia_data);
		unlink(newMedia_indx);
		rc = 2;
		goto cleanup;
	}
	chown(newMedia_data, pw->pw_uid, pw->pw_gid);
	chown(newMedia_indx, pw->pw_uid, pw->pw_gid);
	chown(newMedia_meta, pw->pw_uid, pw->pw_gid);

	MHVTL_LOG("%s files created", newMedia);

	/* Write the meta file consisting of the MAM and the meta_header
	   structure with the filemark count initialized to zero.
	*/
	mam = *mamp;

	memset(&meta, 0, sizeof(meta));
	meta.filemark_count = 0;

	if (write(metafile, &mam, sizeof(mam)) != sizeof(mam) ||
		    write(metafile, &meta, sizeof(meta)) != sizeof(meta)) {
		MHVTL_ERR("Failed to initialize file %s: %s", newMedia_meta,
			strerror(errno));
		unlink(newMedia_data);
		unlink(newMedia_indx);
		unlink(newMedia_meta);
		rc = 1;
	}

cleanup:
	if (datafile >= 0) {
		close(datafile);
		datafile = -1;
	}
	if (indxfile >= 0) {
		close(indxfile);
		indxfile = -1;
	}
	if (metafile >= 0) {
		close(metafile);
		metafile = -1;
	}

	return rc;
}
Esempio n. 17
0
/* SuperDLT range */
static void init_sdlt_inquiry(struct lu_phy_attr *lu)
{
	int pg;
	uint8_t worm;
	uint8_t ta[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
	char b[32];
	int x, y, z;

	worm = ((struct priv_lu_ssc *)lu->lu_private)->pm->drive_supports_WORM;
	lu->inquiry[2] =
		((struct priv_lu_ssc *)lu->lu_private)->pm->drive_ANSI_VERSION;


	lu->inquiry[36] = get_product_family(lu);

	sprintf(b, "%s", MHVTL_VERSION);
	sscanf(b, "%d.%d.%d", &x, &y, &z);
	if (x) {
		lu->inquiry[37] = x;
		lu->inquiry[38] = y;
	} else {
		lu->inquiry[37] = y;
		lu->inquiry[38] = z;
	}

	/* Sequential Access device capabilities - Ref: 8.4.2 */
	pg = PCODE_OFFSET(0xb0);
	lu->lu_vpd[pg] = alloc_vpd(VPD_B0_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_ERR("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_b0(lu, &worm);

	/* Manufacture-assigned serial number - Ref: 8.4.3 */
	pg = PCODE_OFFSET(0xb1);
	lu->lu_vpd[pg] = alloc_vpd(VPD_B1_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_ERR("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_b1(lu, lu->lu_serial_no);

	/* TapeAlert supported flags - Ref: 8.4.4 */
	pg = PCODE_OFFSET(0xb2);
	lu->lu_vpd[pg] = alloc_vpd(VPD_B2_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_ERR("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_b2(lu, &ta);

	/* VPD page 0xC0 */
	pg = PCODE_OFFSET(0xc0);
	lu->lu_vpd[pg] = alloc_vpd(44);
	if (!lu->lu_vpd[pg]) {
		MHVTL_ERR("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_dlt_c0(lu);

	/* VPD page 0xC1 */
	pg = PCODE_OFFSET(0xc1);
	lu->lu_vpd[pg] = alloc_vpd(44);
	if (!lu->lu_vpd[pg]) {
		MHVTL_ERR("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_dlt_c1(lu, lu->lu_serial_no);
}
Esempio n. 18
0
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);
}
Esempio n. 19
0
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);
}
Esempio n. 20
0
static void update_eml_vpd_83(struct lu_phy_attr *lu)
{
	struct vpd **lu_vpd = lu->lu_vpd;
	uint8_t *d;
	int num;
	char *ptr;
	int pg;
	int len, j;

	num = VENDOR_ID_LEN + PRODUCT_ID_LEN + 10;

	pg = PCODE_OFFSET(0x83);
	if (lu_vpd[pg])		/* Free any earlier allocation */
		dealloc_vpd(lu_vpd[pg]);
	lu_vpd[pg] = alloc_vpd(num + 12);
	if (!lu_vpd[pg]) {
		MHVTL_ERR("Can't malloc() to setup for vpd_83");
		return;
	}

	d = lu_vpd[pg]->data;

	d[0] = 2;
	d[1] = 1;
	d[2] = 0;
	d[3] = num;

	memcpy(&d[4], &lu->vendor_id, VENDOR_ID_LEN);
	memcpy(&d[12], &lu->product_id, PRODUCT_ID_LEN);
	memcpy(&d[28], &lu->lu_serial_no, 10);
	len = (int)strlen(lu->lu_serial_no);
	ptr = &lu->lu_serial_no[len];

	num += 4;
	/* NAA IEEE registered identifier (faked) */
	d[num] = 0x1;	/* Binary */
	d[num + 1] = 0x3;
	d[num + 2] = 0x0;
	d[num + 3] = 0x8;
	d[num + 4] = 0x51;
	d[num + 5] = 0x23;
	d[num + 6] = 0x45;
	d[num + 7] = 0x60;
	d[num + 8] = 0x3;
	d[num + 9] = 0x3;
	d[num + 10] = 0x3;
	d[num + 11] = 0x3;

	if (lu->naa) { /* If defined in config file */
		sscanf((const char *)lu->naa,
			"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
			&d[num + 4],
			&d[num + 5],
			&d[num + 6],
			&d[num + 7],
			&d[num + 8],
			&d[num + 9],
			&d[num + 10],
			&d[num + 11]);
	} else { /* Else munge the serial number */
		ptr--;
		for (j = 11; j > 3; ptr--, j--)
			d[num + j] = *ptr;
	}
	d[num + 4] &= 0x0f;
	d[num + 4] |= 0x50;
}
Esempio n. 21
0
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);
}
Esempio n. 22
0
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;
}