The on-disk MAM structure was stored in endian machines so the ssc image file has no compatibility among big and little endian architecutres. This patch makes the on-disk MAM structure big endian. Signed-off-by: FUJITA Tomonori <fujita.tomonori@xxxxxxxxxxxxx> --- usr/Makefile | 13 ++++- usr/bs_ssc.c | 7 ++- usr/bs_ssc.h | 60 ++++++++++++++++++ usr/dump_tape.c | 11 ++- usr/libssc.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ usr/libssc.h | 7 ++ usr/mktape.c | 51 +++++++++------- usr/ssc.h | 11 +--- 8 files changed, 301 insertions(+), 39 deletions(-) create mode 100644 usr/libssc.c create mode 100644 usr/libssc.h diff --git a/usr/Makefile b/usr/Makefile index 1174f7e..b0f3b20 100644 --- a/usr/Makefile +++ b/usr/Makefile @@ -57,7 +57,8 @@ LIBS += -lpthread PROGRAMS += tgtd tgtadm mktape dump_tape SCRIPTS += ../scripts/tgt-setup-lun ../scripts/tgt-admin TGTD_OBJS += tgtd.o mgmt.o target.o scsi.o log.o driver.o util.o work.o \ - parser.o spc.o sbc.o mmc.o osd.o scc.o smc.o ssc.o bs_ssc.o \ + parser.o spc.o sbc.o mmc.o osd.o scc.o smc.o \ + ssc.o bs_ssc.o libssc.o \ bs_null.o bs.o libcrc32c.o MANPAGES = ../doc/manpages/tgtadm.8 ../doc/manpages/tgt-admin.8 \ ../doc/manpages/tgt-setup-lun.8 @@ -77,6 +78,16 @@ tgtadm: tgtadm.o -include tgtadm.d +mktape: mktape.o libssc.o + $(CC) $^ -o $@ + +-include mktape.d libssc.d + +dump_tape: dump_tape.o libssc.o + $(CC) $^ -o $@ + +-include dump_tape.d libssc.d + %.o: %.c $(CC) -c $(CFLAGS) $*.c -o $*.o @$(CC) -MM $(CFLAGS) -MF $*.d -MT $*.o $*.c diff --git a/usr/bs_ssc.c b/usr/bs_ssc.c index 4919082..d9f7036 100644 --- a/usr/bs_ssc.c +++ b/usr/bs_ssc.c @@ -38,6 +38,7 @@ #include "media.h" #include "bs_ssc.h" #include "ssc.h" +#include "libssc.h" static void ssc_sense_data_build(struct scsi_cmd *cmd, uint8_t key, uint16_t asc, uint8_t *info, int info_len) @@ -604,6 +605,7 @@ static int bs_tape_open(struct scsi_lu *lu, char *path, int *fd, uint64_t *size) struct ssc_info *ssc; char *cart = NULL; ssize_t rd; + int ret; ssc = dtype_priv(lu); @@ -634,11 +636,12 @@ static int bs_tape_open(struct scsi_lu *lu, char *path, int *fd, uint64_t *size) goto read_failed; } - rd = pread(*fd, &ssc->mam, sizeof(struct MAM), rd); - if (rd < sizeof(struct MAM)) { + ret = ssc_read_mam_info(*fd, &ssc->mam); + if (ret) { eprintf("Failed to read MAM: %d %m\n", (int)rd); goto read_failed; } + rd = pread(*fd, ssc->c_blk, sizeof(struct blk_header), ssc->c_blk->next); if (rd < sizeof(struct blk_header)) { diff --git a/usr/bs_ssc.h b/usr/bs_ssc.h index 7e9a7d9..85cf25f 100644 --- a/usr/bs_ssc.h +++ b/usr/bs_ssc.h @@ -1,3 +1,6 @@ +#ifndef __BS_SSC_H +#define __BS_SSC_H + /* * structure of a 'poor mans double linked list' on disk. */ @@ -38,3 +41,60 @@ struct blk_header { uint8_t z; }; +/* + * MAM (media access memory) structure based from IBM Ultrium SCSI + * Reference WB1109-02 + */ +struct MAM { + uint32_t tape_fmt_version; + uint32_t __pad1; + + uint64_t remaining_capacity; + uint64_t max_capacity; + uint64_t TapeAlert; + uint64_t load_count; + uint64_t MAM_space_remaining; + + uint8_t assigning_organization_1[8]; + uint8_t formatted_density_code; + uint8_t __pad2[5]; + uint8_t initialization_count[2]; + uint8_t dev_make_serial_last_load[4][40]; + + uint64_t written_in_medium_life; + uint64_t read_in_medium_life; + uint64_t written_in_last_load; + uint64_t read_in_last_load; + + uint8_t medium_manufacturer[8]; + uint8_t medium_serial_number[32]; + uint32_t medium_length; + uint32_t medium_width; + uint8_t assigning_organization_2[8]; + uint8_t medium_density_code; + uint8_t __pad3[7]; + uint8_t medium_manufacture_date[8]; + uint64_t MAM_capacity; + uint8_t medium_type; + uint8_t __pad4; + uint16_t medium_type_information; + uint8_t __pad5[4]; + + uint8_t application_vendor[8]; + uint8_t application_name[32]; + uint8_t application_version[8]; + uint8_t user_medium_text_label[160]; + uint8_t date_time_last_written[12]; + uint8_t __pad6[3]; + uint8_t localization_identifier; + uint8_t barcode[32]; + uint8_t owning_host_textual_name[80]; + uint8_t media_pool[160]; + + uint8_t vendor_unique[256]; + + uint8_t dirty; + uint8_t __reserved[7]; +}; + +#endif diff --git a/usr/dump_tape.c b/usr/dump_tape.c index ef6b6c3..ff2124d 100644 --- a/usr/dump_tape.c +++ b/usr/dump_tape.c @@ -33,6 +33,7 @@ #include "media.h" #include "ssc.h" #include "bs_ssc.h" +#include "libssc.h" void print_current_header(struct blk_header *pos) { @@ -104,7 +105,7 @@ int main(int argc, char *argv[]) char *progname; char datafile[1024] = ""; loff_t nread; - struct MAM mam; + struct MAM_info mam; struct blk_header current_position; time_t t; int a; @@ -151,13 +152,15 @@ int main(int argc, char *argv[]) perror("Could not read blk header"); exit(1); } - nread = read(ofp, &mam, sizeof(struct MAM)); - if (nread < (sizeof(struct MAM))) { + + nread = ssc_read_mam_info(ofp, &mam); + if (nread) { perror("Could not read MAM"); exit(1); } if (mam.tape_fmt_version != TGT_TAPE_VERSION) { - printf("Unknown media format version\n"); + printf("Unknown media format version %x\n", + mam.tape_fmt_version); exit(1); } diff --git a/usr/libssc.c b/usr/libssc.c new file mode 100644 index 0000000..297867e --- /dev/null +++ b/usr/libssc.c @@ -0,0 +1,180 @@ +/* + * helpers for assessing to ssc on-disk structures + * + * Copyright (C) 2008 FUJITA Tomonori <tomof@xxxxxxx> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include "bs_ssc.h" +#include "ssc.h" +#include "be_byteshift.h" + +#define SSC_1ST_HDR_OFFSET (sizeof(struct MAM) + sizeof(struct blk_header)) + +#define SSC_GET_MAM_INFO_VAL(member, bits)\ +{\ + (i)->member = get_unaligned_be##bits(&((m)->member));\ +} + +#define SSC_GET_MAM_INFO_ARRAY(member)\ +{\ + memcpy((i)->member, (m)->member, sizeof((m)->member));\ +} + +static inline uint8_t get_unaligned_be8(const uint8_t *p) +{ + return p[0]; +} + +int ssc_read_mam_info(int fd, struct MAM_info *i) +{ + struct MAM mam, *m; + int ret; + + m = &mam; + + ret = pread(fd, m, sizeof(struct MAM), sizeof(struct blk_header)); + if (ret != sizeof(struct MAM)) + return 1; + + if (lseek64(fd, SSC_1ST_HDR_OFFSET, SEEK_SET) != SSC_1ST_HDR_OFFSET) + return 1; + + SSC_GET_MAM_INFO_VAL(tape_fmt_version, 32); + + SSC_GET_MAM_INFO_VAL(remaining_capacity, 64); + SSC_GET_MAM_INFO_VAL(max_capacity, 64); + SSC_GET_MAM_INFO_VAL(TapeAlert, 64); + SSC_GET_MAM_INFO_VAL(load_count, 64); + SSC_GET_MAM_INFO_VAL(MAM_space_remaining, 64); + + SSC_GET_MAM_INFO_ARRAY(assigning_organization_1); + SSC_GET_MAM_INFO_VAL(formatted_density_code, 8); + SSC_GET_MAM_INFO_ARRAY(initialization_count); + SSC_GET_MAM_INFO_ARRAY(dev_make_serial_last_load); + + SSC_GET_MAM_INFO_VAL(written_in_medium_life, 64); + SSC_GET_MAM_INFO_VAL(read_in_medium_life, 64); + SSC_GET_MAM_INFO_VAL(written_in_last_load, 64); + SSC_GET_MAM_INFO_VAL(read_in_last_load, 64); + + SSC_GET_MAM_INFO_ARRAY(medium_manufacturer); + SSC_GET_MAM_INFO_ARRAY(medium_serial_number); + SSC_GET_MAM_INFO_VAL(medium_length, 32); + SSC_GET_MAM_INFO_VAL(medium_width, 32); + SSC_GET_MAM_INFO_ARRAY(assigning_organization_2); + SSC_GET_MAM_INFO_VAL(medium_density_code, 8); + SSC_GET_MAM_INFO_ARRAY(medium_manufacture_date); + SSC_GET_MAM_INFO_VAL(MAM_capacity, 64); + SSC_GET_MAM_INFO_VAL(medium_type, 8); + SSC_GET_MAM_INFO_VAL(medium_type_information, 16); + + SSC_GET_MAM_INFO_ARRAY(application_vendor); + SSC_GET_MAM_INFO_ARRAY(application_name); + SSC_GET_MAM_INFO_ARRAY(application_version); + SSC_GET_MAM_INFO_ARRAY(user_medium_text_label); + SSC_GET_MAM_INFO_ARRAY(date_time_last_written); + SSC_GET_MAM_INFO_VAL(localization_identifier, 8); + SSC_GET_MAM_INFO_ARRAY(barcode); + SSC_GET_MAM_INFO_ARRAY(owning_host_textual_name); + SSC_GET_MAM_INFO_ARRAY(media_pool); + + SSC_GET_MAM_INFO_ARRAY(vendor_unique); + + SSC_GET_MAM_INFO_VAL(dirty, 8); + + return 0; +} + +#define SSC_PUT_MAM_INFO_VAL(member, bits)\ +{\ + put_unaligned_be##bits((i)->member, &((m)->member));\ +} + +#define SSC_PUT_MAM_INFO_ARRAY(member)\ +{\ + memcpy((m)->member, (i)->member, sizeof((m)->member));\ +} + +static inline void put_unaligned_be8(uint8_t val, uint8_t *p) +{ + *p = val; +} + +int ssc_write_mam_info(int fd, struct MAM_info *i) +{ + struct MAM mam, *m; + int ret; + + m = &mam; + memset(m, 0, sizeof(struct MAM)); + + SSC_PUT_MAM_INFO_VAL(tape_fmt_version, 32); + + SSC_PUT_MAM_INFO_VAL(remaining_capacity, 64); + SSC_PUT_MAM_INFO_VAL(max_capacity, 64); + SSC_PUT_MAM_INFO_VAL(TapeAlert, 64); + SSC_PUT_MAM_INFO_VAL(load_count, 64); + SSC_PUT_MAM_INFO_VAL(MAM_space_remaining, 64); + + SSC_PUT_MAM_INFO_ARRAY(assigning_organization_1); + SSC_PUT_MAM_INFO_VAL(formatted_density_code, 8); + SSC_PUT_MAM_INFO_ARRAY(initialization_count); + SSC_PUT_MAM_INFO_ARRAY(dev_make_serial_last_load); + + SSC_PUT_MAM_INFO_VAL(written_in_medium_life, 64); + SSC_PUT_MAM_INFO_VAL(read_in_medium_life, 64); + SSC_PUT_MAM_INFO_VAL(written_in_last_load, 64); + SSC_PUT_MAM_INFO_VAL(read_in_last_load, 64); + + SSC_PUT_MAM_INFO_ARRAY(medium_manufacturer); + SSC_PUT_MAM_INFO_ARRAY(medium_serial_number); + SSC_PUT_MAM_INFO_VAL(medium_length, 32); + SSC_PUT_MAM_INFO_VAL(medium_width, 32); + SSC_PUT_MAM_INFO_ARRAY(assigning_organization_2); + SSC_PUT_MAM_INFO_VAL(medium_density_code, 8); + SSC_PUT_MAM_INFO_ARRAY(medium_manufacture_date); + SSC_PUT_MAM_INFO_VAL(MAM_capacity, 64); + SSC_PUT_MAM_INFO_VAL(medium_type, 8); + SSC_PUT_MAM_INFO_VAL(medium_type_information, 16); + + SSC_PUT_MAM_INFO_ARRAY(application_vendor); + SSC_PUT_MAM_INFO_ARRAY(application_name); + SSC_PUT_MAM_INFO_ARRAY(application_version); + SSC_PUT_MAM_INFO_ARRAY(user_medium_text_label); + SSC_PUT_MAM_INFO_ARRAY(date_time_last_written); + SSC_PUT_MAM_INFO_VAL(localization_identifier, 8); + SSC_PUT_MAM_INFO_ARRAY(barcode); + SSC_PUT_MAM_INFO_ARRAY(owning_host_textual_name); + SSC_PUT_MAM_INFO_ARRAY(media_pool); + + SSC_PUT_MAM_INFO_ARRAY(vendor_unique); + + SSC_PUT_MAM_INFO_VAL(dirty, 8); + + ret = pwrite(fd, m, sizeof(struct MAM), sizeof(struct blk_header)); + if (ret != sizeof(struct MAM)) + return 1; + + if (lseek64(fd, SSC_1ST_HDR_OFFSET, SEEK_SET) != SSC_1ST_HDR_OFFSET) + return 1; + + return 0; +} diff --git a/usr/libssc.h b/usr/libssc.h new file mode 100644 index 0000000..891bb30 --- /dev/null +++ b/usr/libssc.h @@ -0,0 +1,7 @@ +#ifndef __LIBSSC_H +#define __LIBSSC_H + +extern int ssc_read_mam_info(int fd, struct MAM_info *i); +extern int ssc_write_mam_info(int fd, struct MAM_info *i); + +#endif diff --git a/usr/mktape.c b/usr/mktape.c index 1abf948..8278317 100644 --- a/usr/mktape.c +++ b/usr/mktape.c @@ -33,6 +33,7 @@ #include "media.h" #include "bs_ssc.h" #include "ssc.h" +#include "libssc.h" const char *mktape_version = "0.01"; @@ -49,7 +50,7 @@ int main(int argc, char *argv[]) { int file; struct blk_header h; - struct MAM mam; + struct MAM_info mi; uint8_t current_media[1024]; long nwrite; char *progname = argv[0]; @@ -57,6 +58,7 @@ int main(int argc, char *argv[]) char *media_type = NULL; char *media_capacity = NULL; uint32_t size; + int ret; if (argc < 2) { usage(progname); @@ -124,38 +126,40 @@ int main(int argc, char *argv[]) h.blk_sz = size; h.prev = 0; h.curr = 0; - h.next = sizeof(mam) + sizeof(h); + h.next = sizeof(struct MAM) + sizeof(h); printf("blk_sz: %d, next %" PRId64 ", %" PRId64 "\n", h.blk_sz, h.next, h.next); printf("Sizeof(mam): %" PRId64 ", sizeof(h): %" PRId64 "\n", - (uint64_t)sizeof(mam), (uint64_t)sizeof(h)); - memset((uint8_t *)&mam, 0, sizeof(mam)); - - mam.tape_fmt_version = 2; - mam.max_capacity = size * 1048576; - mam.remaining_capacity = size * 1048576; - mam.MAM_space_remaining = sizeof(mam.vendor_unique); - mam.medium_length = 384; /* 384 tracks */ - mam.medium_width = 127; /* 127 x tenths of mm (12.7 mm) */ - memcpy(&mam.medium_manufacturer, "Foo ", 8); - memcpy(&mam.application_vendor, "Bar ", 8); + (uint64_t)sizeof(struct MAM), (uint64_t)sizeof(h)); + + memset(&mi, 0, sizeof(mi)); + + mi.tape_fmt_version = TGT_TAPE_VERSION; + mi.max_capacity = size * 1048576; + mi.remaining_capacity = size * 1048576; + mi.MAM_space_remaining = sizeof(mi.vendor_unique); + mi.medium_length = 384; /* 384 tracks */ + mi.medium_width = 127; /* 127 x tenths of mm (12.7 mm) */ + memcpy(mi.medium_manufacturer, "Foo ", 8); + memcpy(mi.application_vendor, "Bar ", 8); if (!strncmp("clean", media_type, 5)) { - mam.medium_type = CART_CLEAN; - mam.medium_type_information = 20; /* Max cleaning loads */ + mi.medium_type = CART_CLEAN; + mi.medium_type_information = 20; /* Max cleaning loads */ } else if (!strncmp("WORM", media_type, 4)) { - mam.medium_type = CART_WORM; + mi.medium_type = CART_WORM; } else { - mam.medium_type = CART_DATA; + mi.medium_type = CART_DATA; } - sprintf((char *)mam.medium_serial_number, "%s_%d", - barcode, (int)time(NULL)); - sprintf((char *)mam.barcode, "%-31s", barcode); - + sprintf((char *)mi.medium_serial_number, "%s_%d", barcode, + (int)time(NULL)); + sprintf((char *)mi.barcode, "%-31s", barcode); sprintf((char *)current_media, "%s", barcode); + syslog(LOG_DAEMON|LOG_INFO, "%s being created", current_media); + file = creat((char *)current_media, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); if (file == -1) { perror("Failed creating file"); @@ -166,8 +170,9 @@ int main(int argc, char *argv[]) perror("Unable to write header"); exit(1); } - nwrite = write(file, &mam, sizeof(mam)); - if (nwrite <= 0) { + + ret = ssc_write_mam_info(file, &mi); + if (ret) { perror("Unable to write MAM"); exit(1); } diff --git a/usr/ssc.h b/usr/ssc.h index 308c8e5..dcd1337 100644 --- a/usr/ssc.h +++ b/usr/ssc.h @@ -8,9 +8,8 @@ /* * MAM structure based from IBM Ultrium SCSI Reference WB1109-02 */ -struct MAM { +struct MAM_info { uint32_t tape_fmt_version; - uint32_t __pad1; uint64_t remaining_capacity; uint64_t max_capacity; @@ -20,7 +19,6 @@ struct MAM { uint8_t assigning_organization_1[8]; uint8_t formatted_density_code; - uint8_t __pad2[5]; uint8_t initialization_count[2]; uint8_t dev_make_serial_last_load[4][40]; @@ -35,20 +33,16 @@ struct MAM { uint32_t medium_width; uint8_t assigning_organization_2[8]; uint8_t medium_density_code; - uint8_t __pad3[7]; uint8_t medium_manufacture_date[8]; uint64_t MAM_capacity; uint8_t medium_type; - uint8_t __pad4; uint16_t medium_type_information; - uint8_t __pad5[4]; uint8_t application_vendor[8]; uint8_t application_name[32]; uint8_t application_version[8]; uint8_t user_medium_text_label[160]; uint8_t date_time_last_written[12]; - uint8_t __pad6[3]; uint8_t localization_identifier; uint8_t barcode[32]; uint8_t owning_host_textual_name[80]; @@ -57,14 +51,13 @@ struct MAM { uint8_t vendor_unique[256]; uint8_t dirty; - uint8_t __reserved[7]; }; struct ssc_info { uint64_t bytes_read; /* Bytes read this load */ uint64_t bytes_written; /* Bytes written this load */ - struct MAM mam; + struct MAM_info mam; struct blk_header *c_blk; /* Current block header */ }; -- 1.5.6.5 -- To unsubscribe from this list: send the line "unsubscribe stgt" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html