Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 30 additions & 29 deletions src/libltfs/tape.c
Original file line number Diff line number Diff line change
Expand Up @@ -1674,7 +1674,7 @@ int tape_get_volume_change_reference(struct device_data *dev, uint64_t *volume_c
sizeof(vcr_data));

if (ret == 0) {
*volume_change_ref = (uint64_t)ltfs_betou32(vcr_data + 5);
*volume_change_ref = (uint64_t)ltfs_betou32(vcr_data + TC_MAM_PAGE_HEADER_SIZE);
if (*volume_change_ref == UINT32_MAX)
*volume_change_ref = UINT64_MAX; /* maintain "unusable VCR" state correctly */
} else {
Expand Down Expand Up @@ -1705,9 +1705,9 @@ int tape_get_cart_coherency(struct device_data *dev, const tape_partition_t part
sizeof(coh_data));

if (ret == 0) {
uint16_t id = ltfs_betou16(coh_data);
uint16_t len = ltfs_betou16(coh_data + 3);
uint8_t vcr_size = coh_data[5];
uint16_t id = ltfs_betou16(coh_data + TC_MAM_ATTR_ID_OFFSET);
uint16_t len = ltfs_betou16(coh_data + TC_MAM_ATTR_LENGTH_OFFSET);
uint8_t vcr_size = coh_data[TC_MAM_COH_VCR_SIZE_OFFSET];

if (id != TC_MAM_PAGE_COHERENCY) {
ltfsmsg(LTFS_WARN, 12058W, id);
Expand All @@ -1723,35 +1723,37 @@ int tape_get_cart_coherency(struct device_data *dev, const tape_partition_t part
coh->set_id = 0;

switch (vcr_size) {
case 8:
coh->volume_change_ref = ltfs_betou64(coh_data + 6);
case TC_MAM_COH_VCR_LENGTH:
coh->volume_change_ref = ltfs_betou64(coh_data + TC_MAM_COH_VCR_OFFSET);
break;
default:
ltfsmsg(LTFS_WARN, 12060W, vcr_size);
return -LTFS_UNEXPECTED_VALUE;
}

coh->count = ltfs_betou64(coh_data + 14);
coh->set_id = ltfs_betou64(coh_data + 22);
coh->count = ltfs_betou64(coh_data + TC_MAM_COH_COUNT_OFFSET);
coh->set_id = ltfs_betou64(coh_data + TC_MAM_COH_SETID_OFFSET);

/* Allow ap_clent_specific_len is 42 and 43 to keep backward compatibility.
* It should be 43 but in LTFS 1.0 and 1.0.1, it was set 42 as a code bug...
*/
uint16_t ap_clent_specific_len = ltfs_betou16(coh_data + 30);
if (ap_clent_specific_len != 42 && ap_clent_specific_len != 43) {
uint16_t ap_clent_specific_len = ltfs_betou16(coh_data + TC_MAM_COH_APPINFO_LEN_OFFSET);
if (ap_clent_specific_len != TC_MAM_COH_APPINFO_LENGTH_LEGACY &&
ap_clent_specific_len != TC_MAM_COH_APPINFO_LENGTH) {
ltfsmsg(LTFS_WARN, 12061W, ap_clent_specific_len);
return -LTFS_UNEXPECTED_VALUE;
} else if (strncmp((char *)coh_data + 32, "LTFS", sizeof("LTFS")) != 0) {
} else if (strncmp((char *)coh_data + TC_MAM_COH_SIGNATURE_OFFSET, TC_MAM_COHERENCY_SIGNATURE,
sizeof(TC_MAM_COHERENCY_SIGNATURE)) != 0) {
ltfsmsg(LTFS_WARN, 12062W);
return -LTFS_UNEXPECTED_VALUE;
}

memcpy(coh->uuid, coh_data + 37, 37);
memcpy(coh->uuid, coh_data + TC_MAM_COH_UUID_OFFSET, sizeof(coh->uuid));

/* Don't need to check the version field because the values parsed above are guaranteed
* to be supported in every version of the LTFS MAM parameters.
*/
coh->version = coh_data[74];
coh->version = coh_data[TC_MAM_COH_VERSION_OFFSET];
} else
ltfsmsg(LTFS_WARN, 12057W, ret);

Expand All @@ -1772,25 +1774,24 @@ int tape_set_cart_coherency(struct device_data *dev, const tape_partition_t part
CHECK_ARG_NULL(dev, -LTFS_NULL_ARG);
CHECK_ARG_NULL(dev->backend, -LTFS_NULL_ARG);

ltfs_u16tobe(coh_data, TC_MAM_PAGE_COHERENCY);
coh_data[2] = 0;
ltfs_u16tobe(coh_data + 3, TC_MAM_PAGE_COHERENCY_SIZE);
coh_data[5] = 0x08; /* Size of Volume Change Reference Value (VCR)*/
ltfs_u64tobe(coh_data + 6, coh->volume_change_ref);
ltfs_u64tobe(coh_data + 14, coh->count); /* VOLUME COHERENCY COUNT */
ltfs_u64tobe(coh_data + 22, coh->set_id); /* VOLUME COHERENCY SET IDENTIFIER */
/* APPLICATION CLIENT SPECIFIC INFORMATION LENGTH */
coh_data[30] = 0; /* Size of APPLICATION CLIENT SPECIFIC INFORMATION (Byte 1) */
coh_data[31] = 43; /* Size of APPLICATION CLIENT SPECIFIC INFORMATION (Byte 0) */
/* Size of the buffer to insert 'LTFS' needs to be size of 5 for the 4 letters and the null terminator*/
arch_strncpy((char *)coh_data + 32,"LTFS", 5, 4);
memcpy(coh_data + 37, coh->uuid, 37);
ltfs_u16tobe(coh_data + TC_MAM_ATTR_ID_OFFSET, TC_MAM_PAGE_COHERENCY);
coh_data[TC_MAM_ATTR_FORMAT_OFFSET] = 0;
ltfs_u16tobe(coh_data + TC_MAM_ATTR_LENGTH_OFFSET, TC_MAM_PAGE_COHERENCY_SIZE);
coh_data[TC_MAM_COH_VCR_SIZE_OFFSET] = TC_MAM_COH_VCR_LENGTH; /* Size of Volume Change Reference (VCR) */
ltfs_u64tobe(coh_data + TC_MAM_COH_VCR_OFFSET, coh->volume_change_ref);
ltfs_u64tobe(coh_data + TC_MAM_COH_COUNT_OFFSET, coh->count); /* VOLUME COHERENCY COUNT */
ltfs_u64tobe(coh_data + TC_MAM_COH_SETID_OFFSET, coh->set_id); /* VOLUME COHERENCY SET IDENTIFIER */
/* APPLICATION CLIENT SPECIFIC INFORMATION LENGTH: signature + UUID + version */
ltfs_u16tobe(coh_data + TC_MAM_COH_APPINFO_LEN_OFFSET, TC_MAM_COH_APPINFO_LENGTH);
/* memcpy instead of arch_strncpy to deterministically copy all bytes of the coherency signature including NULL terminator */
memcpy(coh_data + TC_MAM_COH_SIGNATURE_OFFSET, TC_MAM_COHERENCY_SIGNATURE, sizeof(TC_MAM_COHERENCY_SIGNATURE));
memcpy(coh_data + TC_MAM_COH_UUID_OFFSET, coh->uuid, sizeof(coh->uuid));
/*
Version field
0: GA and PGA1
1: From PGA2
*/
coh_data[74] = coh->version; /* version field should be specified before calling this function */
coh_data[TC_MAM_COH_VERSION_OFFSET] = coh->version; /* version field should be specified before calling this function */

ret = dev->backend->write_attribute(dev->backend_data, part, coh_data, sizeof(coh_data));
if (ret < 0)
Expand All @@ -1813,8 +1814,8 @@ int tape_get_cart_volume_lock_status(struct device_data *dev, int *status)
sizeof(attr_data));

if (ret == 0) {
uint16_t id = ltfs_betou16(attr_data);
uint16_t len = ltfs_betou16(attr_data + 3);
uint16_t id = ltfs_betou16(attr_data + TC_MAM_ATTR_ID_OFFSET);
uint16_t len = ltfs_betou16(attr_data + TC_MAM_ATTR_LENGTH_OFFSET);

if (id != TC_MAM_LOCKED_MAM) {
ltfsmsg(LTFS_WARN, 17196W, id);
Expand Down
21 changes: 21 additions & 0 deletions src/libltfs/tape_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,27 @@ typedef enum {
#define TC_MAM_PAGE_VCR_SIZE (0x4) /* Size of Volume Change Reference */
#define TC_MAM_PAGE_COHERENCY (0x080C)
#define TC_MAM_PAGE_COHERENCY_SIZE (0x46)
#define TC_MAM_COHERENCY_SIGNATURE "LTFS" /* Volume coherency signature; 4 chars + NUL, reader compares all 5 */

/* Byte offsets of the common MAM attribute header fields. The attribute value
* begins at TC_MAM_PAGE_HEADER_SIZE. */
#define TC_MAM_ATTR_ID_OFFSET (0) /* 2-byte attribute identifier */
#define TC_MAM_ATTR_FORMAT_OFFSET (2) /* 1-byte format byte */
#define TC_MAM_ATTR_LENGTH_OFFSET (3) /* 2-byte attribute length */

/* Byte offsets of the fields within the volume coherency attribute
* (TC_MAM_PAGE_COHERENCY), measured from the start of the attribute. */
#define TC_MAM_COH_VCR_SIZE_OFFSET (5) /* 1-byte length of the VCR field */
#define TC_MAM_COH_VCR_OFFSET (6) /* 8-byte volume change reference */
#define TC_MAM_COH_COUNT_OFFSET (14) /* 8-byte coherency count */
#define TC_MAM_COH_SETID_OFFSET (22) /* 8-byte coherency set identifier */
#define TC_MAM_COH_APPINFO_LEN_OFFSET (30) /* 2-byte app client specific info length */
#define TC_MAM_COH_SIGNATURE_OFFSET (32) /* 5-byte "LTFS\0" signature */
#define TC_MAM_COH_UUID_OFFSET (37) /* volume UUID (sizeof tc_coherency.uuid) */
#define TC_MAM_COH_VERSION_OFFSET (74) /* 1-byte format version */
#define TC_MAM_COH_VCR_LENGTH (8) /* value stored at the VCR size field */
#define TC_MAM_COH_APPINFO_LENGTH (43) /* signature + UUID + version byte count */
#define TC_MAM_COH_APPINFO_LENGTH_LEGACY (42) /* LTFS 1.0/1.0.1 wrote 42 (off-by-one) */

#define TC_MAM_APP_VENDER (0x0800)
#define TC_MAM_APP_VENDER_SIZE (0x8)
Expand Down
Loading