Git Product home page Git Product logo

Comments (2)

watfordjc avatar watfordjc commented on June 14, 2024

Data Redesign

The LTO-Encryption-SPTI application at the moment is mostly a load of constants and structs and manual parsing. Part of the reason for that is that the data is received unformatted.

Having decided to P/Invoke CreateFile() directly in LTO-Encryption-Manager rather than creating a wrapper function in a C library, I am now considering the feasibility of doing things mostly in C# rather than using a C library. The SPTI sample is C-based, and LTO-Encryption-SPTI is written in C, but almost everything is converting to structs and parsing. Sometimes the parsing is on fields of a structure that can't be converted to a struct.

In order to enable encryption, the following are needed via P/Invoke and SPTI at a minimum:

  • A HANDLE to the drive.
  • The WWN/LUN for the drive (Device Identifiers page).
  • Whether or not the drive's encryption is supported (Supported Security Protocol, Data Encryption Management Capabilities, Data Encryption Capabilities, and Supported Key Formats pages).
  • Current encryption status (Data Encryption Status page).
  • Drive's public key for key wrapping (Device Server Key Wrapping Public Key page).
  • Tape barcode, whether the tape is formatted LTFS, whether the tape is encrypted (MAM attributes).
  • First block encryption status KAD (Next Block Encryption Status KAD).

The first item, a HANDLE to the drive, is obtained by getting the drive path via CIM or an alternative method, and then (if necessary) appending a hash/octothorpe and the GUID for a tape drive (GUID_DEVINTERFACE_TAPE): #{53F5630B-B6BF-11D0-94F2-00A0C91EFB8B}, and using that full path with CreateFile().

Step one of obtaining the WWN/LUN (or anything else) requires calling DeviceIoControl() 4 times to check we can communicate with the drive, although the only thing I'm checking is that SrbType is of the newer/extended SCSI block variety STORAGE_REQUEST_BLOCK:

  1. Obtain a STORAGE_DESCRIPTOR_HEADER (parsed for the size of a STORAGE_ADAPTER_DESCRIPTOR).
  2. Obtain a STORAGE_ADAPTER_DESCRIPTOR (parsed for the AlignmentMask and SrbType values).
  3. Obtain a STORAGE_DESCRIPTOR_HEADER (parsed for the size of a STORAGE_DEVICE_DESCRIPTOR).
  4. Obtain a STORAGE_DEVICE_DESCRIPTOR (parsed for the BusType and SerialNumber).

Next, the process of sending/getting data to/from the drive is similar for most pages. SPTI wraps the SRB and sends it to the drive. Let's look at the C code:

if (srbType == SRB_TYPE_STORAGE_REQUEST_BLOCK)
{
	int pageCode;

	/*
	* CDB: Inquiry, Device Identifiers VPD page
	*/
	length = ResetSrbIn(psptwb_ex, SCSIOP_INQUIRY);
	if (length == 0) { goto Cleanup; }
	psptwb_ex->spt.Cdb[1] = CDB_INQUIRY_EVPD;
	psptwb_ex->spt.Cdb[2] = VPD_DEVICE_IDENTIFIERS;
	status = SendSrb(fileHandle, psptwb_ex, length, &returned);

	if (CheckStatus(fileHandle, psptwb_ex, status, returned, length))
	{
		pageCode = psptwb_ex->ucDataBuf[1];
		if (pageCode == VPD_DEVICE_IDENTIFIERS)
		{
			ParseDeviceIdentifiers((PVPD_IDENTIFICATION_PAGE)psptwb_ex->ucDataBuf, &logicalUnitIdentifierLength, &logicalUnitIdentifier);
		}
	}
...
}

I'm going to need one of those psptwb_ex variables. That would be a PSCSI_PASS_THROUGH_WITH_BUFFERS_EX. I'm going to need to convert some C structs to C#. After spending way to long trying to marshal between C# and C and back, and ending up with a 9 byte offset issue, I have decided I am going to do it all in C# with CsWin32 and (where not covered) Win32 P/Invoke.

Let's compare what I've currently got in terms of C# code for the Device Identifiers VPD page:

public static void GetTapeDriveIdentifiers(TapeDrive tapeDrive)
{
    IntPtr psptwb_ex = Marshal.AllocHGlobal(Marshal.SizeOf<SCSI_PASS_THROUGH_WITH_BUFFERS_EX>());
    SCSI_PASS_THROUGH_WITH_BUFFERS_EX sptwb_ex = new();
    Marshal.StructureToPtr(sptwb_ex, psptwb_ex, true);
    uint length = ResetSrbIn(psptwb_ex, Constants.SCSIOP_INQUIRY);
    sptwb_ex = Marshal.PtrToStructure<SCSI_PASS_THROUGH_WITH_BUFFERS_EX>(psptwb_ex);
    Windows.Win32.InlineArrayIndexerExtensions.ItemRef(ref sptwb_ex.spt.Cdb, 1) = Constants.CDB_INQUIRY_EVPD;
    Windows.Win32.InlineArrayIndexerExtensions.ItemRef(ref sptwb_ex.spt.Cdb, 2) = Constants.VPD_DEVICE_IDENTIFIERS;
    Marshal.StructureToPtr(sptwb_ex, psptwb_ex, true);

    uint returnedData = 0;
    Windows.Win32.System.IO.OVERLAPPED overlapped;
    bool ok;
    unsafe
    {
        ok = Windows.Win32.PInvoke.DeviceIoControl(tapeDrive.Handle,
            Windows.Win32.PInvoke.IOCTL_SCSI_PASS_THROUGH_EX,
            (void*)psptwb_ex,
            (uint)Marshal.SizeOf(sptwb_ex),
            (void*)psptwb_ex,
            length,
            &returnedData,
            &overlapped);
    }
    if (ok)
    {
        sptwb_ex = Marshal.PtrToStructure<SCSI_PASS_THROUGH_WITH_BUFFERS_EX>(psptwb_ex);
        Trace.WriteLine(Convert.ToHexString(sptwb_ex.ucDataBuf, 0, (int)sptwb_ex.spt.DataInTransferLength));
    }
    Marshal.FreeHGlobal(psptwb_ex);
}

ResetSrbIn() pretty much does what its name suggests: it resets an SRB for usage in the in/read direction. Having found the InlineArrayIndexerExtensions method (it doesn't even have any Google results) after hunting through IntelliSense for a way to access the 2nd byte of a 1 byte variable sized array (UCHAR[ANYSIZE_ARRAY] in Win32 C), I migrated ResetSrbIn() to C#.

There is one issue with migrating to C#: many constants and structs, such as the VPD page struct, do not appear to be available via CsWin32. C# also doesn't really do bit fields in structs. Piping the Trace.WriteLine(Convert.ToHexString(...)) output through xxd and hexdump, though, I can see the LUN (and HP_____Ultrium 6-SCSI__[SerialNumber], where _ is a space) in the bytes.

I need to parse the pages though, and with CsWin32 appearing to not have the page structs, I am going to have to implement all of them myself, including working out how to handle bit fields. This is one of the problems with manual parsing: having to reimplement the same thing again.

I am considering defining the pages using ASN.1+ECN, although there might not be a library or tool that can convert those definitions to C#.

The Compaq/HP OID 1.3.6.1.4.1.232.5.5.4.1 (iso.identified-organization.dod.internet.private.enterprise.compaq.cpqScsi.cpqSasComponent.cpqSasTapeDrv.cpqSasTapeDrvTable.cpqSasTapeDrvEntry) is a table entry for a SAS tape drive used with tape libraries that do SNMP and it has some MIB objects defined such as 1.3.6.1.4.1.232.5.5.4.1.1.8 (cpqSasTapeDrvSerialNumber):

cpqSasTapeDrvSerialNumber OBJECT-TYPE
	SYNTAX  DisplayString (SIZE (0..40))
	ACCESS  read-only
	STATUS  mandatory
	DESCRIPTION
		"SAS Tape Drive Serial Number.

		This is the serial number assigned to the tape drive."
::= { cpqSasTapeDrvEntry 8 }

Such objects/modules may have a use if SNMP support were desired, however getting the pages from the drive and parsing them so that such an object can be populated is something for a tape library to implement. As far as I can see, those tables in the LTO manuals are the only definitions the LTO publish.

Let's take the VPD struct from scsi.h (with comments removed), and a non-ECN translation in bullet list form:

typedef struct _VPD_IDENTIFICATION_PAGE {
    UCHAR DeviceType : 5;
    UCHAR DeviceTypeQualifier : 3;
    UCHAR PageCode;
    UCHAR Reserved;
    UCHAR PageLength;
    UCHAR Descriptors[0];
#endif
} VPD_IDENTIFICATION_PAGE, *PVPD_IDENTIFICATION_PAGE;
  • The first byte contains two options: a 5 bit peripheral device type in the lower bits, and a 3 bit peripheral qualifier in the upper bits. The values of these fields are from an enum/list (e.g. DeviceType = 0x05 means CD Device).
  • The page code, defining what the rest of the data is. For VPD_IDENTIFICATION_PAGE that would be 0x83.
  • A reserved/padding byte.
  • The page length (total length minus this byte and the 3 bytes above).
  • The page (variable length sequence of Descriptors).

Using the ASN.1 example RLC-RADIO-HANDOVER-COMPLETE (from ETSI TS 101 761-2 V1.3.1, AKA the Hiperlan specification) as a template (the specification has ASN.1 throughout and transfer syntax tables in Annex A), the ASN.1 for VPD-Identification-Page arguments would be something like this:

Device-Identification-Page-Arg ::= SEQUENCE {
	device-type 				Device-Type
	device-type-qualifier			Device-Type-Qualifier
	page-code				Page-Code
	page-length				Page-Length
	device-identification-descriptor-list	Device-Identification-Descriptor-List
}

Adding in the reserved/padding, the initial encoding structure would be something like this:

#Device-Identification-Page-Arg-struct ::= #CONCATENATION {
	device-type 				#Device-Type
	device-type-qualifier			#Device-Type-Qualifier
	page-code				#Page-Code
	aux-reserved-1				#PAD
	page-length				#Page-Length
	device-identification-descriptor-list	#Device-Identification-Descriptor-List
}

[TODO...]


I can't seem to get SPIN working. Keep getting Medium not present errors.

from lto-encryption-manager.

watfordjc avatar watfordjc commented on June 14, 2024

Ubuntu

This is a side-note on installing tape and LTFS software in Ubuntu, because testing transfer rates when reading/writing from/to LTFS volumes in Windows revealed abysmal speeds. Using two operating systems isn't ideal, however enabling LTO encryption on a drive can leave that key installed on the drive through multiple reboots (i.e. not setting the CKOD bit to 1).

This is a fresh (non-live desktop) install of Ubuntu 20.04.4 on a 64 GB flash drive, installed by clicking on install from within a live session of Ubuntu 20.04.4 on a different USB flash drive, installed using rufus in Windows 10.

This is an 8 core/16 thread machine, so I use 12 threads -j 12 when I call make during installation of ltfs.

A note on formatting in this comment, given markdown's limitations:

typed command at a $ bash prompt in gnome-terminal

output from the command

Existing Software Information

Kernal and Operating System Versions

uname -a

Linux john-desktop 5.13.0-39-generic #44~20.04.1-Ubuntu SMP Thu Mar 24 16:43:35 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

lsb_release -a

No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 20.04.4 LTS
Release:	20.04
Codename:	focal

Installed Packages/Software

comm -23 <(apt-mark showmanual | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort -u)

git
google-chrome-stable
gparted
grub2-common
keepass2
nvidia-driver-510
uuid
veracrypt

Installation

Cloning the ltfs Repository

cd /opt
sudo mkdir ltfs
sudo chown john:john ltfs
git clone 'https://github.com/LinearTapeFileSystem/ltfs.git'
cd ltfs
git log -n1 --oneline

98e8854 (HEAD -> master, origin/master, origin/HEAD) Fix filehandle corruption on LP64 (#345)

Installing ltfs Dependencies

sudo apt install automake icu-devtools libfuse-dev libsnmp-dev libtool libxml2-dev mt-st python3-pyxattr uuid-dev

There is one more thing needed: /usr/bin/icu-config

stat /usr/bin/icu-config

stat: cannot stat '/usr/bin/icu-config': No such file or directory

sudo cp .github/workflows/icu-config /usr/bin/icu-config
sudo chmod +x /usr/bin/icu-config

Building and Installing ltfs

cd /opt/ltfs
./autogen.sh
./configure
make -j12
sudo ldconfig
sudo make install
sudo ldconfig


Testing ltfs Drive Detection

sudo mkdir /mnt/ltfs
sudo chown john:john /mnt/ltfs
sudo ltfs -o device_list

98df LTFS14000I LTFS starting, LTFS version 2.5.0.0 (Prelim), log level 2.
98df LTFS14058I LTFS Format Specification version 2.4.0.
98df LTFS14104I Launched by "ltfs -o device_list".
98df LTFS14105I This binary is built for Linux (x86_64).
98df LTFS14106I GCC version is 9.4.0.
98df LTFS17087I Kernel version: Linux version 5.13.0-39-generic (buildd@lcy02-amd64-080) (gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0, GNU ld (GNU Binutils for Ubuntu) 2.34) #44~20.04.1-Ubuntu SMP Thu Mar 24 16:43:35 UTC 2022 i386.
98df LTFS17089I Distribution: DISTRIB_ID=Ubuntu.
98df LTFS17089I Distribution: NAME="Ubuntu".
98df LTFS17085I Plugin: Loading "sg" tape backend.
Tape Device list:.
Device Name = /dev/sg0 (11.0.0.0), Vendor ID = HP      , Product ID = Ultrium 6-SCSI  , Serial Number = [REDACTED], Product Name =[Ultrium 6-SCSI].

sudo ltfs /mnt/ltfs/ -o devname=/dev/sg0 -o sync_type=unmount

98e7 LTFS14000I LTFS starting, LTFS version 2.5.0.0 (Prelim), log level 2.
98e7 LTFS14058I LTFS Format Specification version 2.4.0.
98e7 LTFS14104I Launched by "ltfs /mnt/ltfs/ -o devname=/dev/sg0 -o sync_type=unmount".
98e7 LTFS14105I This binary is built for Linux (x86_64).
98e7 LTFS14106I GCC version is 9.4.0.
98e7 LTFS17087I Kernel version: Linux version 5.13.0-39-generic (buildd@lcy02-amd64-080) (gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0, GNU ld (GNU Binutils for Ubuntu) 2.34) #44~20.04.1-Ubuntu SMP Thu Mar 24 16:43:35 UTC 2022 i386.
98e7 LTFS17089I Distribution: DISTRIB_ID=Ubuntu.
98e7 LTFS17089I Distribution: NAME="Ubuntu".
98e7 LTFS14064I Sync type is "unmount".
98e7 LTFS17085I Plugin: Loading "sg" tape backend.
98e7 LTFS17085I Plugin: Loading "unified" iosched backend.
98e7 LTFS14095I Set the tape device write-anywhere mode to avoid cartridge ejection.
98e7 LTFS30209I Opening a device through sg-ibmtape driver (/dev/sg0).
98e7 LTFS30250I Opened the SCSI tape device 11.0.0.0 (/dev/sg0).
98e7 LTFS30207I Vendor ID is HP      .
98e7 LTFS30208I Product ID is Ultrium 6-SCSI  .
98e7 LTFS30214I Firmware revision is 35GD.
98e7 LTFS30215I Drive serial is [REDACTED].
98e7 LTFS30285I The reserved buffer size of /dev/sg0 is 1048576.
98e7 LTFS30294I Setting up timeout values from RSOC.
98e7 LTFS17160I Maximum device block size is 1048576.
98e7 LTFS11330I Loading cartridge.
98e7 LTFS11332I Load successful.
98e7 LTFS17157I Changing the drive setting to write-anywhere mode.
98e7 LTFS11005I Mounting the volume from device.
98e7 LTFS17192W Cannot read: medium is encrypted.
98e7 LTFS12049E Cannot read: backend call failed (-21600).
98e7 LTFS11174E Cannot read ANSI label: read failed (-21600).
98e7 LTFS11170E Failed to read label (-21600) from partition 0.
98e7 LTFS11009E Cannot read volume: failed to read partition labels.
98e7 LTFS14013E Cannot mount the volume from device.
98e7 LTFS30205I MODESELECT (0x55) returns -20500.
98e7 LTFS30263I MODESELECT returns Invalid Field in Parameter List (-20500) /dev/sg0.

Reading MAM/CM Attributes

Other than some things displayed by HPE Tape Tools in Windows, the only thing I have used for reading MAM attributes has been LTO-Encryption-SPTI.

Cloning the lto-info Repository

cd /opt
sudo mkdir lto-info
sudo chown john:john lto-info
git clone 'https://github.com/speed47/lto-info'

Installing lto-info Dependencies

sudo snap install go --classic

Building and Installing lto-info

cd /opt/lto-info
make
sudo ln -s /opt/lto-info/lto-info /usr/local/bin/lto-info

Testing lto-info

sudo lto-info

Drive information:
   Vendor  : HP
   Model   : Ultrium 6-SCSI
   Firmware: 35GD
Medium information:
  Cartridge Type: 0x00 - Data cartridge
  Medium format : 0x5a - LTO-6
  Formatted as  : 0x5a - LTO-6
  MAM Capacity  : 16384 bytes
Format specs:
   Capacity  :  2500 GB native   -  6250 GB compressed with a 2.5:1 ratio
   R/W Speed :   160 MB/s native -   400 MB/s compressed
   Partitions:     4 max partitions supported
   Phy. specs: 4 bands/tape, 34 wraps/band, 16 tracks/wrap, 2176 total tracks
   Duration  : 4h20 to fill tape with 136 end-to-end passes (115 seconds/pass)
Usage information:
Previous sessions:

Cloning the mam-info Repository

cd /opt
sudo mkdir lto-info
sudo chown john:john lto-info
git clone 'https://github.com/arogge/maminfo.git'

Installing mam-info Dependencies

sudo apt install libsgutils2-dev

Building and Installing mam-info

cd maminfo
make
sudo ln -s /opt/maminfo/mam-info /usr/local/bin/mam-info

Testing mam-info

sudo mam-info -f /dev/sg0

ERROR : Problem reading attribute 0400
ERROR : Read failed (try verbose opt)

The Problem

Looking at the source code for mam-info.c, it seems apparent that these tools make assumptions about what attributes to ask for.

LTO-Encryption-SPTI, on the other hand, does the following for the MAM/CM attribute parsing section:

  1. Ask the drive for the Volume List.
  2. Ask the drive for the Partition List.
  3. Ask the drive for the Supported Attributes.
  4. Ask the drive for the MAM Attribute List, and then parse and display that list.
  5. Ask the drive for the MAM Attribute List for each partition in the Partition List, and then parse and display that list.
  6. Ask the drive for the MAM default locale IDs (ASCII, binary, etc.) for each partition.
  7. Ask the drive for the MAM Attribute Values for each partition in the Partition List, and then parse and display those values, using the default locale ID (or the locale ID for a attribute) to display the string/hex raw value of unknown attributes (or known attributes with an unexpected locale ID).

The Solution

sg_read_attr can be used in combination with reference to some of the constants defined in spti.h in LTO-Encryption-SPTI:

/* Read Attribute Extensions to scsi.h */
#define READ_ATTRIBUTE_SERVICE_ATTRIBUTE_VALUES 0x00
#define READ_ATTRIBUTE_SERVICE_ATTRIBUTE_LIST 0x01
#define READ_ATTRIBUTE_SERVICE_VOLUME_LIST 0x02
#define READ_ATTRIBUTE_SERVICE_PARTITION_LIST 0x03
#define READ_ATTRIBUTE_SERVICE_SUPPORTED_ATTRIBUTES 0x05

A rather simple dash/bash script should do, although this is something I put together rather quickly and is not well tested:

#!/bin/sh

if [ ! "$(id -u)" = "0" ]; then
  echo "Run with sudo" >&1
  exit 1
elif [ ! -c "$1" ]; then
  echo "Usage: $0 /dev/sg0"
  return 0
fi

DRIVE="$1"

echo "-----"
echo "Tape Attributes follow"
echo "---"
sudo sg_read_attr --cache --sa=0x00 "$1"
echo "-----"


VOLUME_LIST_RAW=$(sudo sg_read_attr --cache --sa=0x02 -H "$DRIVE" | sed 's/  */ /g;s/^ //g;s/ $//g' | cut -d' ' -f2-)
if [ ! $(echo "$VOLUME_LIST_RAW" | head -n1 | awk '{print $1 $2}' | sed 's/^0*//') = 2 ]; then
	echo "Volume List data is unexpected length" >&1
	exit 1
else
	VOLUME_COUNT=$(echo "$VOLUME_LIST_RAW" | head -n1 | awk '{print $3 $4}' | sed 's/^0*//')
	echo "Number of volumes: $VOLUME_COUNT"
	if [ "$VOLUME_COUNT" = "" ]; then
		echo "No volumes?" >&1
		exit 1
	elif [ $VOLUME_COUNT -ne 1 ]; then
		echo "Error: LTO only allows 1 volume. Is $DRIVE an LTO tape drive?" >&1
		exit 1
	fi
fi

PARTITION_LIST_RAW=$(sudo sg_read_attr --cache --sa=0x03 -H "$DRIVE" | sed 's/  */ /g;s/^ //g;s/ $//g' | cut -d' ' -f2-)
if [ ! $(echo "$PARTITION_LIST_RAW" | head -n1 | awk '{print $1 $2}' | sed 's/^0*//') = 2 ]; then
	echo "Partition List data is unexpected length" >&1
	exit 1
else
	PARTITION_COUNT=$(echo "$PARTITION_LIST_RAW" | head -n1 | awk '{print $3 $4}' | sed 's/^0*//')
	echo "Number of partitions: $PARTITION_COUNT"
fi

if [ "$PARTITION_COUNT" = "" ]; then
	echo "No partitions?" >&1
	exit 0
fi

MAXIMUM_PARTITION=$(expr $PARTITION_COUNT - 1)
for CURRENT_PARTITION in $(seq 0 $MAXIMUM_PARTITION); do
	echo "-----"
	echo "Partition $CURRENT_PARTITION Attributes follow"
	echo "---"
	sudo sg_read_attr --cache --sa=0x00 -p $CURRENT_PARTITION "$1"
done

Similarly, getting the full barcode of a tape could be done with a bash script (again, not thoroughly tested, and it assumes the textual output of the commands won't change format):

#!/bin/sh

if [ ! "$(id -u)" = "0" ]; then
  echo "Run with sudo" >&1
  exit 1
elif [ ! -c "$1" ]; then
  echo "Usage: $0 /dev/sg0"
  return 0
fi

DRIVE="$1"
MAM_BARCODE="0x0806"
MAM_MEDIUM_DENSITY_CODE="0x0405"
MAM_MEDIUM_TYPE="0x0408"

sg_read_attr --sa=0x00 "$DRIVE" >/dev/null
BARCODE=$(sg_read_attr --cache --sa=0x00 --filter="$MAM_BARCODE" "$DRIVE" | cut -d':' -f2 | sed 's/^ *//g;s/ *$//g')
MEDIUM_DENSITY_CODE=$(sg_read_attr --cache --sa=0x00 --filter="$MAM_MEDIUM_DENSITY_CODE" "$DRIVE" | cut -d':' -f2 | sed 's/^ *//g;s/ *$//g')
MEDIUM_TYPE=$(sg_read_attr --cache --sa=0x00 --filter="$MAM_MEDIUM_TYPE" "$DRIVE" | cut -d':' -f2 | sed 's/^ *//g;s/ *$//g')

if [ "$BARCODE" = "" ]; then
	echo "No barcode" >&1
	exit 0
fi

#echo "Barcode: $BARCODE"
#echo "Medium Density Code: $MEDIUM_DENSITY_CODE"
#echo "Medium Type: $MEDIUM_TYPE"

LTO_GENERATION=""

case "$MEDIUM_DENSITY_CODE" in

	"0x40")
		LTO_GENERATION="1"
	;;
	"0x42")
		LTO_GENERATION="2"
	;;
	"0x44")
		LTO_GENERATION="3"
	;;
	"0x46")
		LTO_GENERATION="4"
	;;
	"0x58")
		LTO_GENERATION="5"
	;;
	"0x5a")
		LTO_GENERATION="6"
	;;
	"0x5c")
		LTO_GENERATION="7"
	;;
	"0x5d")
		LTO_GENERATION="M8"
	;;
	"0x5e")
		LTO_GENERATION="8"
	;;
	"0x60")
		LTO_GENERATION="9"
	;;
	*)
		echo "Unhandled Medium Density Code: $MEDIUM_DENSITY_CODE" >&1
		exit 1
	;;
esac

MEDIUM_TYPE_DATA="0X0"
MEDIUM_TYPE_CLEAN="0X1"
MEDIUM_TYPE_WORM="0X80"

BARCODE_SUFFIX_CHAR1=""

BARCODE_SUFFIX=""

case "$MEDIUM_TYPE" in

	"0x0")
		if [ ! "$LTO_GENERATION" = "M8" ]; then
			BARCODE_SUFFIX="L$LTO_GENERATION"
		else
			BARCODE_SUFFIX="M8"
		fi
	;;
	"0x1")
		if [ ! "$LTO_GENERATION" = "M8" ]; then
			BARCODE_SUFFIX="L$LTO_GENERATION"
		else
			BARCODE_SUFFIX="M8"
		fi
	;;
	"0x80")
		case "LTO_GENERATION" in

			"3")
				BARCODE_SUFFIX="LT"
			;;
			"4")
				BARCODE_SUFFIX="LU"
			;;
			"5")
				BARCODE_SUFFIX="LV"
			;;
			"6")
				BARCODE_SUFFIX="LW"
			;;
			"7")
				BARCODE_SUFFIX="LX"
			;;
			"8")
				BARCODE_SUFFIX="LY"
			;;
			"9")
				BARCODE_SUFFIX="LZ"
			;;
		esac
	;;
	*)
		echo "Unhandle Medium Type: $MEDIUM_TYPE" >&1
		exit 1
	;;
esac

#echo "Full barcode: $BARCODE$BARCODE_SUFFIX"
echo "$BARCODE$BARCODE_SUFFIX"

Writing a C program that uses the libsgutils2-dev library, rather than parsing the output of the sg_read_attr command, could remove the issue of things breaking if the text output format changes, but dash/bash scripting is my usual scripting option on Linux/WSL2.


from lto-encryption-manager.

Related Issues (4)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.