mirror of
https://github.com/moibenko/mtx.git
synced 2026-01-11 06:00:13 +00:00
Compare commits
15 Commits
rpm1.3.12-
...
absolute_a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cfc1a886e5 | ||
|
|
60a1e55727 | ||
|
|
b338d5f9a0 | ||
|
|
71e237e6e8 | ||
|
|
8767727b15 | ||
|
|
7b8da461e5 | ||
|
|
963faa172c | ||
|
|
a13704f62f | ||
|
|
2c95a251e4 | ||
|
|
4bf05d31c5 | ||
|
|
5e4d13d026 | ||
|
|
05c81f6d17 | ||
|
|
3718d257b2 | ||
|
|
efde4187b4 | ||
|
|
4edb12f775 |
2
README.md
Normal file
2
README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# mtx
|
||||
The MTX program controls the robotic mechanism in autoloaders and tape libraries. Taken from Souceforge, patches from centOS were applied, plus my changes to allow to use mtx over library calls.
|
||||
BIN
mtx-1.3.12.tgz
Normal file
BIN
mtx-1.3.12.tgz
Normal file
Binary file not shown.
@@ -3,16 +3,17 @@
|
||||
# USE GMAKE, NOT REGULAR BSD MAKE!)
|
||||
#
|
||||
# Valid targets:
|
||||
# linux86 freebsd86 solarissparc sgi dec vms
|
||||
# linux86 freebsd86 solarissparc sgi dec vms
|
||||
#
|
||||
# Makefile changes by Lars Kellogg-Stedman for better integration with
|
||||
# GNU Autoconf.
|
||||
# GNU Autoconf.
|
||||
|
||||
# Version # for 'make dist'...
|
||||
VERSION=1.3.12
|
||||
|
||||
BINS = mtx@EXEEXT@ tapeinfo@EXEEXT@ loaderinfo@EXEEXT@ scsitape@EXEEXT@ scsieject@EXEEXT@
|
||||
EXTRA_BINS = nsmhack@EXEEXT@
|
||||
LIB=libmtx.a
|
||||
DBGS := $(BINS:%@EXEEXT@=%.dbg)
|
||||
MAN = mtx.1 tapeinfo.1 loaderinfo.1 scsitape.1 scsieject.1
|
||||
MAN_HTML := $(MAN:%.1=%.html)
|
||||
@@ -33,6 +34,7 @@ INSTALL_DOC = $(INSTALL) -m 644
|
||||
INSTALL_BIN = $(INSTALL) -m 755
|
||||
INSTALL_DIR = $(INSTALL) -m 755 -d
|
||||
|
||||
DESTDIR =
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
sbindir = @sbindir@
|
||||
@@ -45,7 +47,7 @@ VPATH = $(srcdir)
|
||||
# Linux on x86...
|
||||
#
|
||||
ifeq ($(TARGET),linux)
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wall -fpic -O3
|
||||
CPPFLAGS += -DLONG_PRINT_REQUEST_SENSE=1
|
||||
endif
|
||||
|
||||
@@ -63,7 +65,7 @@ LIBS += -lcam
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),hpux)
|
||||
CFLAGS += -O -D_HPUX_SOURCE -D __hpux__
|
||||
CFLAGS += -O -D_HPUX_SOURCE -D __hpux__
|
||||
endif
|
||||
|
||||
#
|
||||
@@ -104,18 +106,18 @@ else
|
||||
strip $< -o $@
|
||||
endif
|
||||
|
||||
all: $(BINS)
|
||||
all: $(BINS) $(LIB)
|
||||
|
||||
dbgs: $(DBGS)
|
||||
|
||||
install: $(BINS)
|
||||
$(INSTALL_DIR) $(sbindir)
|
||||
$(INSTALL_DIR) $(DESTDIR)$(sbindir)
|
||||
for file in $(BINS); do \
|
||||
$(INSTALL_BIN) "$$file" $(sbindir) ; \
|
||||
done
|
||||
$(INSTALL_DIR) $(mandir) $(mandir)/man1
|
||||
$(INSTALL_BIN) "$$file" $(DESTDIR)$(sbindir) ; \
|
||||
done
|
||||
$(INSTALL_DIR) $(DESTDIR)$(mandir) $(DESTDIR)$(mandir)/man1
|
||||
for file in mtx.1 tapeinfo.1 scsitape.1 scsieject.1 loaderinfo.1 ; do \
|
||||
$(INSTALL_DOC) "$$file" $(mandir)/man1 ; \
|
||||
$(INSTALL_DOC) "$$file" $(DESTDIR)$(mandir)/man1 ; \
|
||||
done
|
||||
|
||||
clean:
|
||||
@@ -131,7 +133,7 @@ distclean: clean
|
||||
rm -f Makefile config.h config.log config.cache config.status
|
||||
|
||||
dist: distclean
|
||||
./makedist $(VERSION)
|
||||
./makedist $(VERSION)
|
||||
|
||||
loaderinfo@EXEEXT@: loaderinfo.o mtxl.o mtxl.h mtx.h $(EXTRA)
|
||||
$(CC) $(LDFLAGS) -o loaderinfo@EXEEXT@ loaderinfo.o mtxl.o $(EXTRA) $(LIBS)
|
||||
@@ -142,7 +144,7 @@ nsmhack@EXEEXT@: nsmhack.o mtxl.o $(EXTRA)
|
||||
mtx@EXEEXT@: mtx.o mtxl.o mtxl.h mtx.h $(EXTRA)
|
||||
$(CC) $(LDFLAGS) -o mtx@EXEEXT@ mtx.o mtxl.o $(EXTRA) $(LIBS)
|
||||
|
||||
mam2debug@EXEEXT@: mtxl.o mam2debug.o mtx.h $(EXTRA)
|
||||
mam2debug@EXEEXT@: mtxl.o mam2debug.o mtx.h $(EXTRA)
|
||||
$(CC) $(LDFLAGS) -o mam2debug@EXEEXT@ mtxl.o mam2debug.o $(EXTRA) $(LIBS)
|
||||
|
||||
tapeinfo@EXEEXT@: tapeinfo.o mtxl.o mtx.h mtxl.h $(EXTRA)
|
||||
@@ -159,6 +161,9 @@ scsitape.o: scsitape.c mtx.h mtxl.h
|
||||
scsieject@EXEEXT@: scsieject.o mtxl.o mtxl.h mtx.h $(EXTRA)
|
||||
$(CC) $(LDFLAGS) -o scsieject@EXEEXT@ scsieject.o mtxl.o $(EXTRA) $(LIBS)
|
||||
|
||||
$(LIB): mtx.o mtxl.o
|
||||
ar qvs contrib/$(LIB) mtx.o mtxl.o
|
||||
$(CC) $(LDFLAGS) -shared -o contrib/libmtx.so mtx.o mtxl.o
|
||||
scsieject.o: scsieject.c mtx.h mtxl.h
|
||||
|
||||
loaderinfo.o: loaderinfo.c mtx.h mtxl.h
|
||||
|
||||
@@ -488,7 +488,6 @@ int main(int argc, char **argv)
|
||||
argv0=argv[0];
|
||||
if (argc != 3)
|
||||
{
|
||||
fprintf(stderr,"argc=%d",argc);
|
||||
usage();
|
||||
}
|
||||
|
||||
|
||||
@@ -131,13 +131,16 @@ may need to eject the tape using your OS's tape control commands
|
||||
first). Note that this command may not be what you want on large
|
||||
tape libraries -- e.g. on Exabyte 220, the first slot is usually a
|
||||
cleaning tape. If <drivenum> is omitted, defaults to first drive.
|
||||
|
||||
.TP 10
|
||||
.B last [<drivenum>]
|
||||
Loads drive <drivenum> from the last slot in the media changer. Unloads
|
||||
the drive if there is already a tape in it. (Note: you may need to eject
|
||||
the tape using your OS's tape control commands first).
|
||||
.TP 10
|
||||
.B previous [<drivenum>]
|
||||
Unloads the drive and loads the previous tape in sequence. If the drive
|
||||
was empty, loads the first tape into the drive.
|
||||
.TP 10
|
||||
.B next [<drivenum>]
|
||||
Unloads the drive and loads the next tape in sequence. If the drive was
|
||||
empty, loads the first tape into the drive.
|
||||
@@ -145,6 +148,9 @@ empty, loads the first tape into the drive.
|
||||
.B position <slotnum>
|
||||
Positions the robot at a specific slot. Needed by some changers to
|
||||
move to and open the import/export, or mailbox, slot.
|
||||
.TP 10
|
||||
.B eject
|
||||
Eject the tape currently in the drive.
|
||||
|
||||
.SH AUTHORS
|
||||
The original 'mtx' program was written by Leonard Zubkoff and extensively
|
||||
|
||||
103
mtx-1.3.12/mtx.c
103
mtx-1.3.12/mtx.c
@@ -31,7 +31,7 @@
|
||||
Near complete re-write Feb 2000 Eric Lee Green <eric@badtux.org> to add support for
|
||||
multi-drive tape changers, extract out library stuff into mtxl.c,
|
||||
and otherwise bring things up to date for dealing with LARGE tape jukeboxes
|
||||
and other such enterprise-class storage subsystems.
|
||||
and other such enterprise-class storage subsystems.
|
||||
*/
|
||||
|
||||
char *argv0;
|
||||
@@ -39,7 +39,7 @@ char *argv0;
|
||||
#include "mtx.h" /* various defines for bit order etc. */
|
||||
#include "mtxl.h"
|
||||
|
||||
/* A table for printing out the peripheral device type as ASCII. */
|
||||
/* A table for printing out the peripheral device type as ASCII. */
|
||||
static char *PeripheralDeviceType[32] =
|
||||
{
|
||||
"Disk Drive", /* 0 */
|
||||
@@ -49,10 +49,10 @@ static char *PeripheralDeviceType[32] =
|
||||
"Write-once", /* 4 */
|
||||
"CD-ROM", /* 5 */
|
||||
"Scanner", /* 6 */
|
||||
"Optical", /* 7 */
|
||||
"Optical", /* 7 */
|
||||
"Medium Changer", /* 8 */
|
||||
"Communications", /* 9 */
|
||||
"ASC IT8", /* a */
|
||||
"ASC IT8", /* a */
|
||||
"ASC IT8", /* b */
|
||||
"RAID Array", /* c */
|
||||
"Enclosure Services", /* d */
|
||||
@@ -79,7 +79,8 @@ static char *PeripheralDeviceType[32] =
|
||||
static int argc;
|
||||
static char **argv;
|
||||
|
||||
static char *device=NULL; /* the device name passed as argument */
|
||||
char *device=NULL; /* the device name passed as argument */
|
||||
int absolute_addressing=1; /* if not 0 - use absolute adresses of storage and tranport elements as known to the robot */
|
||||
|
||||
/* Unfortunately this must be true for SGI, because SGI does not
|
||||
use an int :-(.
|
||||
@@ -112,7 +113,7 @@ static void Transfer(void);
|
||||
static void Eepos(void);
|
||||
static void NoAttach(void);
|
||||
static void Version(void);
|
||||
static void do_Inventory(void);
|
||||
static void do_Inventory(void);
|
||||
static void do_Unload(void);
|
||||
static void do_Erase(void);
|
||||
static void NoBarCode(void);
|
||||
@@ -149,7 +150,7 @@ command_table[] =
|
||||
{ 0, "erase", do_Erase, 1, 0},
|
||||
{ 0, "nobarcode", NoBarCode, 0,0},
|
||||
{ 1, "position", do_Position, 1, 1},
|
||||
{ 0, "invert2", Invert2, 0, 0},
|
||||
{ 0, "invert2", Invert2, 0, 0},
|
||||
{ 3, "exchange", Exchange, 1, 1 },
|
||||
{ 0, "altres", AltReadElementStatus, 0,0},
|
||||
{ 0, NULL, NULL }
|
||||
@@ -184,7 +185,7 @@ static void Usage()
|
||||
static void Version(void)
|
||||
{
|
||||
fprintf(stderr, "mtx version %s\n\n", VERSION);
|
||||
Usage();
|
||||
Usage();
|
||||
}
|
||||
|
||||
|
||||
@@ -258,7 +259,7 @@ static void First(void)
|
||||
arg1 = ElementStatus->DataTransferElementSourceStorageElementNumber[driveno] + 1;
|
||||
if (arg1 == 1)
|
||||
{
|
||||
printf("loading...done.\n"); /* it already has tape #1 in it! */
|
||||
printf("loading...done.\n"); /* it already has tape #1 in it! */
|
||||
return;
|
||||
}
|
||||
arg2 = driveno;
|
||||
@@ -292,7 +293,7 @@ static void Last(void)
|
||||
arg1 = ElementStatus->DataTransferElementSourceStorageElementNumber[driveno] + 1;
|
||||
if (arg1 >= (ElementStatus->StorageElementCount - ElementStatus->ImportExportCount))
|
||||
{
|
||||
printf("loading...done.\n"); /* it already has last tape in it! */
|
||||
printf("loading...done.\n"); /* it already has last tape in it! */
|
||||
return;
|
||||
}
|
||||
arg2 = driveno;
|
||||
@@ -392,7 +393,7 @@ static void Next(void)
|
||||
FatalError("No More Media\n"); /* last slot */
|
||||
}
|
||||
|
||||
static void do_Inventory(void)
|
||||
static void do_Inventory(void)
|
||||
{
|
||||
if (Inventory(MediumChangerFD) < 0)
|
||||
{
|
||||
@@ -420,7 +421,7 @@ static void do_Erase(void)
|
||||
exit(1); /* exit with an error status. */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This should eject a tape or magazine, depending upon the device sent
|
||||
* to.
|
||||
@@ -441,12 +442,12 @@ static void ReportInquiry(void)
|
||||
int i;
|
||||
|
||||
Inquiry = RequestInquiry(MediumChangerFD,&RequestSense);
|
||||
if (Inquiry == NULL)
|
||||
if (Inquiry == NULL)
|
||||
{
|
||||
PrintRequestSense(&RequestSense);
|
||||
FatalError("INQUIRY Command Failed\n");
|
||||
}
|
||||
|
||||
|
||||
printf("Product Type: %s\n", PeripheralDeviceType[Inquiry->PeripheralDeviceType]);
|
||||
printf("Vendor ID: '");
|
||||
for (i = 0; i < sizeof(Inquiry->VendorIdentification); i++)
|
||||
@@ -484,6 +485,7 @@ static void Status(void)
|
||||
{
|
||||
int StorageElementNumber;
|
||||
int TransferElementNumber;
|
||||
PhysicalLocation_T *phys_loc;
|
||||
|
||||
printf( " Storage Changer %s:%d Drives, %d Slots ( %d Import/Export )\n",
|
||||
device,
|
||||
@@ -492,18 +494,34 @@ static void Status(void)
|
||||
ElementStatus->ImportExportCount);
|
||||
|
||||
|
||||
for (TransferElementNumber = 0;
|
||||
for (TransferElementNumber = 0;
|
||||
TransferElementNumber < ElementStatus->DataTransferElementCount;
|
||||
TransferElementNumber++)
|
||||
{
|
||||
|
||||
if (absolute_addressing==0) {
|
||||
printf("Data Transfer Element %d:", TransferElementNumber);
|
||||
}
|
||||
else {
|
||||
printf("Data Transfer Element %d ", ElementStatus->DataTransferElementAddress[TransferElementNumber]);
|
||||
phys_loc = (PhysicalLocation_T *) &ElementStatus->DataTransferElementPhysicalLocation[TransferElementNumber];
|
||||
printf("Phys Loc F%u,C%u,R%u,Z%u SN%s ID %s:",
|
||||
phys_loc->frame, phys_loc->column, phys_loc->row, phys_loc->zone,
|
||||
ElementStatus->DataTransferElementSerialNumber[TransferElementNumber],
|
||||
ElementStatus->DataTransferElementProductId[TransferElementNumber]
|
||||
);
|
||||
}
|
||||
if (ElementStatus->DataTransferElementFull[TransferElementNumber])
|
||||
{
|
||||
if (ElementStatus->DataTransferElementSourceStorageElementNumber[TransferElementNumber] > -1)
|
||||
{
|
||||
printf("Full (Storage Element %d Loaded)",
|
||||
ElementStatus->DataTransferElementSourceStorageElementNumber[TransferElementNumber]+1);
|
||||
if (absolute_addressing==0) {
|
||||
printf("Full (Storage Element %d Loaded)",
|
||||
ElementStatus->DataTransferElementSourceStorageElementNumber[TransferElementNumber]+1);
|
||||
}
|
||||
else {
|
||||
printf("Full (Storage Element %d Loaded)",
|
||||
ElementStatus->StorageElementAddress[TransferElementNumber]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -517,7 +535,7 @@ static void Status(void)
|
||||
|
||||
if (ElementStatus->DataTransferAlternateVolumeTag[TransferElementNumber][0])
|
||||
{
|
||||
printf(":AlternateVolumeTag = %s", ElementStatus->DataTransferAlternateVolumeTag[TransferElementNumber]);
|
||||
printf(":AlternateVolumeTag = %s", ElementStatus->DataTransferAlternateVolumeTag[TransferElementNumber]);
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
@@ -531,9 +549,17 @@ static void Status(void)
|
||||
StorageElementNumber < ElementStatus->StorageElementCount;
|
||||
StorageElementNumber++)
|
||||
{
|
||||
if (absolute_addressing==0) {
|
||||
printf( " Storage Element %d%s:%s", StorageElementNumber + 1,
|
||||
(ElementStatus->StorageElementIsImportExport[StorageElementNumber]) ? " IMPORT/EXPORT" : "",
|
||||
(ElementStatus->StorageElementFull[StorageElementNumber] ? "Full " : "Empty"));
|
||||
}
|
||||
else {
|
||||
printf( " Storage Element %d Phys Loc %s %s:%s ", ElementStatus->StorageElementAddress[StorageElementNumber],
|
||||
ElementStatus->StorageElementPhysicalLocation[StorageElementNumber],
|
||||
(ElementStatus->StorageElementIsImportExport[StorageElementNumber]) ? " IMPORT/EXPORT" : "",
|
||||
(ElementStatus->StorageElementFull[StorageElementNumber] ? "Full " : "Empty"));
|
||||
}
|
||||
|
||||
if (ElementStatus->PrimaryVolumeTag[StorageElementNumber][0])
|
||||
{
|
||||
@@ -562,7 +588,7 @@ void Position(int dest)
|
||||
|
||||
void Move(int src, int dest) {
|
||||
RequestSense_T *result; /* from MoveMedium */
|
||||
|
||||
|
||||
result = MoveMedium(MediumChangerFD, src, dest, ElementStatus, inquiry_info, &SCSI_Flags);
|
||||
if (result)
|
||||
{
|
||||
@@ -620,7 +646,7 @@ static void Load(void)
|
||||
if (!device_opened)
|
||||
{
|
||||
FatalError("No Media Changer Device Specified\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (arg1 < 0 || arg1 >= ElementStatus->StorageElementCount)
|
||||
{
|
||||
@@ -724,7 +750,7 @@ static void Exchange(void)
|
||||
src = ElementStatus->StorageElementAddress[arg1 - 1];
|
||||
dest = ElementStatus->StorageElementAddress[arg2 - 1];
|
||||
dest2 = ElementStatus->StorageElementAddress[arg3 - 1];
|
||||
|
||||
|
||||
result = ExchangeMedium(MediumChangerFD, src, dest, dest2, ElementStatus, &SCSI_Flags);
|
||||
if (result)
|
||||
{
|
||||
@@ -783,7 +809,7 @@ static void Unload(void)
|
||||
if (!device_opened)
|
||||
{
|
||||
FatalError("No Media Changer Device Specified\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* okay, we should be there: */
|
||||
if (arg1 < 0)
|
||||
@@ -840,7 +866,7 @@ static void Unload(void)
|
||||
}
|
||||
|
||||
fprintf(stdout, "Unloading drive %d into Storage Element %d...", arg2, arg1 + 1);
|
||||
fflush(stdout); /* make it real-time :-( */
|
||||
fflush(stdout); /* make it real-time :-( */
|
||||
|
||||
Move(src,dest);
|
||||
|
||||
@@ -852,7 +878,7 @@ static void Unload(void)
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
** ARGUMENT PARSING SUBROUTINES: Parse arguments, dispatch.
|
||||
** ARGUMENT PARSING SUBROUTINES: Parse arguments, dispatch.
|
||||
*****************************************************************/
|
||||
|
||||
/* ***
|
||||
@@ -860,9 +886,9 @@ static void Unload(void)
|
||||
*
|
||||
* If we have an actual argument at the index position indicated (i.e. we
|
||||
* have not gone off the edge of the world), we return
|
||||
* its number. If we don't, or it's not a numeric argument,
|
||||
* we return -1. Note that 'get_arg' is kind of misleading, we only accept
|
||||
* numeric arguments, not any other kind.
|
||||
* its number. If we don't, or it's not a numeric argument,
|
||||
* we return -1. Note that 'get_arg' is kind of misleading, we only accept
|
||||
* numeric arguments, not any other kind.
|
||||
*/
|
||||
int get_arg(int idx)
|
||||
{
|
||||
@@ -898,12 +924,11 @@ void open_device(void)
|
||||
|
||||
|
||||
/* we see if we've got a file open. If not, we open one :-(. Then
|
||||
* we execute the actual command. Or not :-(.
|
||||
*/
|
||||
* we execute the actual command. Or not :-(.
|
||||
*/
|
||||
void execute_command(struct command_table_struct *command)
|
||||
{
|
||||
RequestSense_T RequestSense;
|
||||
|
||||
if (device == NULL && command->need_device)
|
||||
{
|
||||
/* try to get it from TAPE environment variable... */
|
||||
@@ -918,7 +943,11 @@ void execute_command(struct command_table_struct *command)
|
||||
}
|
||||
open_device();
|
||||
}
|
||||
|
||||
if (command->need_status && absolute_addressing)
|
||||
{
|
||||
FreeElementData(ElementStatus);
|
||||
ElementStatus = NULL;
|
||||
}
|
||||
if (!ElementStatus && command->need_status)
|
||||
{
|
||||
inquiry_info = RequestInquiry(MediumChangerFD,&RequestSense);
|
||||
@@ -932,7 +961,7 @@ void execute_command(struct command_table_struct *command)
|
||||
if (!ElementStatus)
|
||||
{
|
||||
PrintRequestSense(&RequestSense);
|
||||
FatalError("READ ELEMENT STATUS Command Failed\n");
|
||||
FatalError("READ ELEMENT STATUS Command Failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -946,8 +975,8 @@ void execute_command(struct command_table_struct *command)
|
||||
* load in another tape into drive 0, and we execute these commands one
|
||||
* at a time as we come to them. If we don't have a -f at the start, we
|
||||
* barf. If we leave out a drive #, we default to drive 0 (the first drive
|
||||
* in the cabinet).
|
||||
*/
|
||||
* in the cabinet).
|
||||
*/
|
||||
|
||||
int parse_args(void)
|
||||
{
|
||||
@@ -1008,7 +1037,7 @@ int parse_args(void)
|
||||
|
||||
if (command->num_args>=2 && arg1 != -1)
|
||||
{
|
||||
arg2 = get_arg(i);
|
||||
arg2 = get_arg(i);
|
||||
if (arg2 != -1)
|
||||
{
|
||||
i++;
|
||||
@@ -1064,7 +1093,7 @@ int main(int ArgCount, char *ArgVector[])
|
||||
if (!ElementStatus)
|
||||
{
|
||||
PrintRequestSense(&RequestSense);
|
||||
FatalError("READ ELEMENT STATUS Command Failed\n");
|
||||
FatalError("READ ELEMENT STATUS Command Failed\n");
|
||||
}
|
||||
VMS_DefineStatusSymbols();
|
||||
SCSI_CloseDevice(device, MediumChangerFD);
|
||||
|
||||
@@ -209,6 +209,7 @@ typedef struct SCSI_Flags_Struct
|
||||
int has_barcodes;
|
||||
int querytype; //MTX_ELEMENTSTATUS
|
||||
unsigned char invert2; /* used for EXCHANGE command, sigh. */
|
||||
int absolute_addressing; /* indicates that asolute addresses are required */
|
||||
} SCSI_Flags_T;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@@ -306,6 +307,16 @@ typedef struct Inquiry
|
||||
}
|
||||
Inquiry_T;
|
||||
|
||||
typedef struct InquiryShort
|
||||
{
|
||||
unsigned char pad[2];
|
||||
unsigned char VendorIdentification[8]; /* Bytes 8-15 */
|
||||
unsigned char ProductIdentification[16]; /* Bytes 16-31 */
|
||||
unsigned char SerialNumber[12]; /* Bytes 32-43 */
|
||||
|
||||
}
|
||||
InquiryShort_T;
|
||||
|
||||
/* Hockey Pux may define these. If so, *UN*define them. */
|
||||
#ifdef ILI
|
||||
#undef ILI
|
||||
@@ -499,6 +510,15 @@ typedef struct TransportElementDescriptorShort
|
||||
}
|
||||
TransportElementDescriptorShort_T;
|
||||
|
||||
typedef struct PhysicalLocation
|
||||
{
|
||||
unsigned char zone :1;
|
||||
unsigned char : 3;
|
||||
unsigned char row: 4;
|
||||
unsigned char column :3;
|
||||
unsigned char frame :5;
|
||||
} PhysicalLocation_T;
|
||||
|
||||
|
||||
typedef struct TransportElementDescriptor
|
||||
{
|
||||
@@ -545,6 +565,7 @@ TransportElementDescriptor_T;
|
||||
/* Now for element status data; */
|
||||
|
||||
typedef unsigned char barcode[37];
|
||||
typedef unsigned char serialnumber[13];
|
||||
|
||||
typedef struct ElementStatus {
|
||||
|
||||
@@ -553,6 +574,10 @@ typedef struct ElementStatus {
|
||||
int DataTransferElementCount;
|
||||
int *DataTransferElementAddress; /* array. */
|
||||
int *DataTransferElementSourceStorageElementNumber; /* array */
|
||||
int *DataTransferElementPhysicalLocation; /*array */
|
||||
serialnumber *DataTransferElementProductId; /*array */
|
||||
serialnumber *DataTransferElementSerialNumber; /*array */
|
||||
barcode *StorageElementPhysicalLocation; /*array */
|
||||
barcode *DataTransferPrimaryVolumeTag; /* array. */
|
||||
barcode *DataTransferAlternateVolumeTag; /* array. */
|
||||
barcode *PrimaryVolumeTag; /* array */
|
||||
|
||||
@@ -1,100 +1,225 @@
|
||||
Name: mtx
|
||||
Version: 1.3.12
|
||||
Release: 1%{?dist}
|
||||
Release: 15fnal%{?dist}
|
||||
Summary: SCSI media changer control program
|
||||
License: GPL
|
||||
Group: Utilities/System
|
||||
Source0: ftp://ftp.opensource-sw.net/pub/mtx/stable/%{name}-%{version}.tar.gz
|
||||
Url: http://%{name}.sourceforge.net
|
||||
BuildRoot: /var/tmp/%{name}-%{version}
|
||||
License: GPLv2
|
||||
Group: Applications/System
|
||||
Source0: mtx-1.3.12.tgz
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
|
||||
|
||||
%description
|
||||
The MTX program controls the robotic mechanism in autoloaders and tape
|
||||
libraries such as the HP SureStore DAT 40x6, Exabyte EZ-17, and
|
||||
Exabyte 220. This program is also reported to work with a variety of other tape
|
||||
libraries and autochangers from Tandberg/Overland, Breece Hill, HP, and
|
||||
Seagate.
|
||||
Exabyte 220. This program is also reported to work with a variety of
|
||||
other tape libraries and autochangers from ADIC, Tandberg/Overland,
|
||||
Breece Hill, HP, and Seagate.
|
||||
|
||||
If you have a backup tape device capable of handling more than one
|
||||
tape at a time, you should install MTX.
|
||||
|
||||
This is FNAL version of mtx rpm with mtx library.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
# remove exec permission
|
||||
chmod a-x contrib/config_sgen_solaris.sh contrib/mtx-changer
|
||||
|
||||
|
||||
%build
|
||||
export CFLAGS="$RPM_OPT_FLAGS"
|
||||
%configure
|
||||
make
|
||||
make %{?_smp_mflags}
|
||||
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/sbin
|
||||
install mtx $RPM_BUILD_ROOT/sbin/mtx
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/sbin
|
||||
install loaderinfo $RPM_BUILD_ROOT/usr/sbin/loaderinfo
|
||||
install scsieject $RPM_BUILD_ROOT/usr/sbin/scsieject
|
||||
install scsitape $RPM_BUILD_ROOT/usr/sbin/scsitape
|
||||
install tapeinfo $RPM_BUILD_ROOT/usr/sbin/tapeinfo
|
||||
mkdir -p $RPM_BUILD_ROOT/%{_mandir}/man1
|
||||
install mtx.1 $RPM_BUILD_ROOT/%{_mandir}/man1/mtx.1
|
||||
install loaderinfo.1 $RPM_BUILD_ROOT/%{_mandir}/man1/loaderinfo.1
|
||||
install scsieject.1 $RPM_BUILD_ROOT/%{_mandir}/man1/scsieject.1
|
||||
install scsitape.1 $RPM_BUILD_ROOT/%{_mandir}/man1/scsitape.1
|
||||
install tapeinfo.1 $RPM_BUILD_ROOT/%{_mandir}/man1/tapeinfo.1
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
make install DESTDIR=$RPM_BUILD_ROOT
|
||||
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%doc mtx.doc CHANGES README mtxl.README.html
|
||||
%doc COMPATABILITY FAQ LICENSE* TODO contrib
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%doc CHANGES COMPATABILITY contrib FAQ LICENSE
|
||||
%doc mtx.doc mtxl.README.html README TODO
|
||||
%{_mandir}/man1/*
|
||||
/sbin/mtx
|
||||
/usr/sbin/*
|
||||
%{_sbindir}/*
|
||||
|
||||
|
||||
%changelog
|
||||
* Fri Sep 27 2002 Eric Green <eric@badtux.org>
|
||||
- 1.3.0rel
|
||||
- move changelog to end.
|
||||
- change source directory to ftp.badtux.net.
|
||||
- use * for files to catch new files.
|
||||
* Wed Jan 23 2019 Alexander Moibenko <moibenko@fnal.gov> - 1.3.12-15fnal
|
||||
- For absolute_addressing refresh elements data when status command is executed. This is needed to update tape library infortion in the calling program.
|
||||
- Changes to allow to use mtx as library and show absolute transfer and storage elements as output of status call
|
||||
* Wed Aug 1 2018 Alexander Moibenko <moibenko@fnal.gov> - 1.3.12-14fnal
|
||||
- All patches applied to code and new source mtx.tgz created to build rpm
|
||||
- Changes to allow to use mtx as library and show absolute transfer and storage elements as output of status call
|
||||
* Tue Jul 31 2018 Alexander Moibenko <moibenko@fnal.gov> - 1.3.12-14fnal_p
|
||||
- Changes to allow to use mtx as library and show absolute transfer and storage elements as output of status call
|
||||
* Wed Mar 16 2016 David Sommerseth <davids@redhat.com> - 1.3.12-14
|
||||
- Update scsitape --help screen to show the erase command and improved mtx.1 man page (#948459)
|
||||
|
||||
* Wed Apr 18 2001 Kenneth Porter <shiva@well.com>
|
||||
- 1.2.12pre1
|
||||
- Need to create usr/sbin for install
|
||||
* Wed Mar 16 2016 David Sommerseth <davids@redhat.com> - 1.3.12-13
|
||||
- Fix resource leak during processing of import/export information
|
||||
|
||||
* Fri Mar 02 2001 Eric Green <eric@estinc.com>
|
||||
- 1.2.11pre6
|
||||
- Move tapeinfo,loaderinfo, scsitape to /usr/sbin rather than /sbin
|
||||
* Fri Mar 11 2016 David Sommerseth <davids@redhat.com> - 1.3.12-12
|
||||
- Fix fail with too high slot count (#1298647)
|
||||
|
||||
* Wed Feb 28 2001 Kenneth Porter <shiva@well.com>
|
||||
- 1.2.11pre5
|
||||
- Remove commented-out patch.
|
||||
- Use mandir FHS macro and configure macro.
|
||||
- Install more stuff.
|
||||
- Use build policy for stripping.
|
||||
* Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 1.3.12-11
|
||||
- Mass rebuild 2014-01-24
|
||||
|
||||
* Wed Jan 17 2001 Eric Green <eric@estinc.com>
|
||||
- 1.2.11pre3
|
||||
- Removed patch, now use ./configure.
|
||||
* Fri Dec 27 2013 Daniel Mach <dmach@redhat.com> - 1.3.12-10
|
||||
- Mass rebuild 2013-12-27
|
||||
|
||||
* Mon Nov 27 2000 Eric Green <eric@estinc.com>
|
||||
* Thu Feb 14 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.3.12-9
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
|
||||
|
||||
* Fri Jul 20 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.3.12-8
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
|
||||
|
||||
* Fri Jan 13 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.3.12-7
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
|
||||
|
||||
* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.3.12-6
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
|
||||
|
||||
* Thu Nov 19 2009 Dan Horák <dan[at]danny.cz> 1.3.12-5
|
||||
- dropped debug output when tools are called with wrong number of arguments (#538403)
|
||||
- added patch to support DESTDIR for installing
|
||||
|
||||
* Sat Jul 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.3.12-4
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
|
||||
|
||||
* Wed Feb 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.3.12-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
|
||||
|
||||
* Sun Dec 21 2008 Dan Horák <dan[at]danny.cz> 1.3.12-2
|
||||
- spec file cleanup for better compliance with the guidelines
|
||||
|
||||
* Mon Aug 25 2008 Dan Horák <dan[at]danny.cz> 1.3.12-1
|
||||
- update to mtx-1.3.12
|
||||
|
||||
* Tue Feb 19 2008 Fedora Release Engineering <rel-eng@fedoraproject.org> - 1.3.11-3
|
||||
- Autorebuild for GCC 4.3
|
||||
|
||||
* Thu Aug 23 2007 Jindrich Novy <jnovy@redhat.com> 1.3.11-2
|
||||
- update License
|
||||
- rebuild for BuildID
|
||||
|
||||
* Wed Mar 28 2007 Jindrich Novy <jnovy@redhat.com> 1.3.11-1
|
||||
- update to 1.3.11 (adds new scsieject utility, bugfixes)
|
||||
- sync nostrip patch
|
||||
|
||||
* Tue Feb 06 2007 Jindrich Novy <jnovy@redhat.com> 1.3.10-1
|
||||
- update to mtx-1.3.10
|
||||
- update URL, Source0
|
||||
- don't strip debuginfo
|
||||
|
||||
* Tue Dec 12 2006 Jindrich Novy <jnovy@redhat.com> 1.2.18-9
|
||||
- spec cleanup
|
||||
|
||||
* Wed Jul 12 2006 Jesse Keating <jkeating@redhat.com> - 1.2.18-8.2.2
|
||||
- rebuild
|
||||
|
||||
* Fri Feb 10 2006 Jesse Keating <jkeating@redhat.com> - 1.2.18-8.2.1
|
||||
- bump again for double-long bug on ppc(64)
|
||||
|
||||
* Tue Feb 07 2006 Jesse Keating <jkeating@redhat.com> - 1.2.18-8.2
|
||||
- rebuilt for new gcc4.1 snapshot and glibc changes
|
||||
|
||||
* Fri Dec 09 2005 Jesse Keating <jkeating@redhat.com>
|
||||
- rebuilt
|
||||
|
||||
* Mon Mar 7 2005 Jindrich Novy <jnovy@redhat.com> 1.2.18-8
|
||||
- fix type confusion in SCSI_writet(), SCSI_readt(), slow_memcopy()
|
||||
and slow_bzero()
|
||||
- rebuilt with gcc4
|
||||
|
||||
* Thu Feb 10 2005 Jindrich Novy <jnovy@redhat.com> 1.2.18-7
|
||||
- remove -D_FORTIFY_SOURCE=2 from CFLAGS, present in RPM_OPT_FLAGS
|
||||
|
||||
* Wed Feb 9 2005 Jindrich Novy <jnovy@redhat.com> 1.2.18-6
|
||||
- rebuilt with -D_FORTIFY_SOURCE=2
|
||||
|
||||
* Wed Aug 11 2004 Jindrich Novy <jnovy@redhat.com> 1.2.18-5
|
||||
- dead code elimination
|
||||
- updated spec link to recent source
|
||||
- removed spec link to obsolete URL
|
||||
- rebuilt
|
||||
|
||||
* Tue Jun 15 2004 Elliot Lee <sopwith@redhat.com>
|
||||
- rebuilt
|
||||
|
||||
* Fri Feb 13 2004 Elliot Lee <sopwith@redhat.com>
|
||||
- rebuilt
|
||||
|
||||
* Tue Jan 13 2004 Than Ngo <than@redhat.com> 1.2.18-2
|
||||
- rebuild
|
||||
|
||||
* Fri Sep 26 2003 Harald Hoyer <harald@redhat.de> 1.2.18-1
|
||||
- 1.2.18
|
||||
|
||||
* Wed Jun 04 2003 Elliot Lee <sopwith@redhat.com>
|
||||
- rebuilt
|
||||
|
||||
* Wed Jan 22 2003 Tim Powers <timp@redhat.com>
|
||||
- rebuilt
|
||||
|
||||
* Wed Dec 11 2002 Tim Powers <timp@redhat.com> 1.2.16-6
|
||||
- rebuild on all arches
|
||||
|
||||
* Fri Jun 21 2002 Tim Powers <timp@redhat.com>
|
||||
- automated rebuild
|
||||
|
||||
* Wed Jun 19 2002 Than Ngo <than@redhat.com> 1.2.16-4
|
||||
- don't forcibly strip binaries
|
||||
|
||||
* Thu May 23 2002 Tim Powers <timp@redhat.com>
|
||||
- automated rebuild
|
||||
|
||||
* Tue Feb 26 2002 Than Ngo <than@redhat.com> 1.2.16-2
|
||||
- rebuild
|
||||
|
||||
* Tue Feb 19 2002 Bernhard Rosenkraenzer <bero@redhat.com> 1.2.16-1
|
||||
- 1.2.16
|
||||
|
||||
* Wed Jan 09 2002 Tim Powers <timp@redhat.com>
|
||||
- automated rebuild
|
||||
|
||||
* Fri Dec 14 2001 Than Ngo <than@redhat.com> 1.2.15-1
|
||||
- update to 1.2.15
|
||||
|
||||
* Mon Aug 13 2001 Preston Brown <pbrown@redhat.com> 1.2.13-1
|
||||
- 1.2.13 fixes "+ Too many Data Transfer Elements Reported" problem (#49258)
|
||||
|
||||
* Mon Jun 25 2001 Preston Brown <pbrown@redhat.com>
|
||||
- 1.2.12
|
||||
- moved binaries to /usr/sbin from /sbin
|
||||
|
||||
* Wed Feb 14 2001 Michael Stefaniuc <mstefani@redhat.com>
|
||||
- 1.2.10
|
||||
- Fixed patching to use the portable.patch.
|
||||
- updated %%doc
|
||||
|
||||
* Tue Jul 25 2000 Eric Green <eric@estinc.com>
|
||||
- 1.2.8
|
||||
- Added portability patch to mtx.spec so should compile on Red Hat Alpha etc.
|
||||
* Mon Dec 11 2000 Preston Brown <pbrown@redhat.com>
|
||||
- 1.2.9
|
||||
|
||||
* Thu Jun 6 2000 Eric Green <eric@estinc.com>
|
||||
* Wed Jul 12 2000 Prospector <bugzilla@redhat.com>
|
||||
- automatic rebuild
|
||||
|
||||
* Thu Jun 15 2000 Preston Brown <pbrown@redhat.com>
|
||||
- 1.2.7
|
||||
- Fixed single-drive Exabyte 220 special case.
|
||||
- Fixed ADIC DAT Autochanger special case.
|
||||
- Fixed mtx.spec to move the binaries to /sbin since we need root access
|
||||
|
||||
* Tue May 23 2000 Preston Brown <pbrown@redhat.com>
|
||||
- adopted for Winston
|
||||
|
||||
* Fri May 12 2000 Kenneth Porter <shiva@well.com>
|
||||
- 1.2.6
|
||||
- Fixed 'eepos' stuff to use | rather than || (whoops!)
|
||||
- Accept a 4-byte element descriptor for the robot arm for certain older
|
||||
- autochangers.
|
||||
- autochangers.
|
||||
|
||||
* Mon May 8 2000 Kenneth Porter <shiva@well.com>
|
||||
- Spell sourceforge right so the link at rpmfind.net will work.
|
||||
|
||||
@@ -23,22 +23,25 @@
|
||||
|
||||
/*
|
||||
* FatalError: changed Feb. 2000 elg@badtux.org to eliminate a buffer
|
||||
* overflow :-(. That could be important if mtxl is SUID for some reason.
|
||||
* overflow :-(. That could be important if mtxl is SUID for some reason.
|
||||
*/
|
||||
|
||||
#include "mtx.h"
|
||||
#include "mtxl.h"
|
||||
|
||||
/* #define DEBUG_NSM 1 */
|
||||
|
||||
/* #define DEBUG_BARCODE */
|
||||
/* #define DEBUG_MODE_SENSE 1 */
|
||||
/* #define DEBUG */
|
||||
/* #define DEBUG_SCSI */
|
||||
#define __WEIRD_CHAR_SUPPRESS 1
|
||||
#define __WEIRD_CHAR_SUPPRESS 1
|
||||
|
||||
/* zap the following define when we finally add real import/export support */
|
||||
#define IMPORT_EXPORT_HACK 1 /* for the moment, import/export == storage */
|
||||
|
||||
/* only so many element per SCSI Read Element Status */
|
||||
#define SCSI_RES_ELEMENTS 5000
|
||||
|
||||
/* First, do some SCSI routines: */
|
||||
|
||||
/* the camlib is used on FreeBSD. */
|
||||
@@ -97,7 +100,7 @@ Inquiry_T *RequestInquiry(DEVICE_TYPE fd, RequestSense_T *RequestSense)
|
||||
Inquiry_T *Inquiry;
|
||||
CDB_T CDB;
|
||||
|
||||
Inquiry = (Inquiry_T *) xmalloc(sizeof(Inquiry_T));
|
||||
Inquiry = (Inquiry_T *) xmalloc(sizeof(Inquiry_T));
|
||||
|
||||
CDB[0] = 0x12; /* INQUIRY */
|
||||
CDB[1] = 0; /* EVPD = 0 */
|
||||
@@ -228,7 +231,8 @@ void FatalError(char *ErrorMessage, ...)
|
||||
va_end(ArgumentPointer);
|
||||
|
||||
#ifndef VMS
|
||||
exit(1);
|
||||
//exit(1);
|
||||
return; /* if used as library routine it can not exit, because this would terminate the caller */
|
||||
#else
|
||||
sys$exit(VMS_ExitCode);
|
||||
#endif
|
||||
@@ -277,10 +281,10 @@ int max(int x, int y)
|
||||
|
||||
|
||||
/* Okay, this is a hack for the NSM modular jukebox series, which
|
||||
* uses the "SEND DIAGNOSTIC" command to do shit.
|
||||
* uses the "SEND DIAGNOSTIC" command to do shit.
|
||||
*/
|
||||
|
||||
int SendNSMHack(DEVICE_TYPE MediumChangerFD, NSM_Param_T *nsm_command,
|
||||
int SendNSMHack(DEVICE_TYPE MediumChangerFD, NSM_Param_T *nsm_command,
|
||||
int param_len, int timeout)
|
||||
{
|
||||
CDB_T CDB;
|
||||
@@ -359,7 +363,7 @@ NSM_Result_T *RecNSMHack( DEVICE_TYPE MediumChangerFD,
|
||||
|
||||
/* Routine to inventory the library. Needed by, e.g., some Breece Hill
|
||||
* loaders. Sends an INITIALIZE_ELEMENT_STATUS command. This command
|
||||
* has no parameters, such as a range to scan :-(.
|
||||
* has no parameters, such as a range to scan :-(.
|
||||
*/
|
||||
|
||||
int Inventory(DEVICE_TYPE MediumChangerFD)
|
||||
@@ -367,7 +371,7 @@ int Inventory(DEVICE_TYPE MediumChangerFD)
|
||||
CDB_T CDB;
|
||||
|
||||
/* okay, now for the command: */
|
||||
CDB[0] = 0x07;
|
||||
CDB[0] = 0x07;
|
||||
CDB[1] = CDB[2] = CDB[3] = CDB[4] = CDB[5] = 0;
|
||||
|
||||
/* set us a very long timeout, sigh... */
|
||||
@@ -391,8 +395,8 @@ int Inventory(DEVICE_TYPE MediumChangerFD)
|
||||
/* Routine to read the Mode Sense Element Address Assignment Page */
|
||||
/* We try to read the page. If we can't read the page, we return NULL.
|
||||
* Our caller really isn't too worried about why we could not read the
|
||||
* page, it will simply default to some kind of default values.
|
||||
*/
|
||||
* page, it will simply default to some kind of default values.
|
||||
*/
|
||||
ElementModeSense_T *ReadAssignmentPage(DEVICE_TYPE MediumChangerFD)
|
||||
{
|
||||
CDB_T CDB;
|
||||
@@ -402,7 +406,7 @@ ElementModeSense_T *ReadAssignmentPage(DEVICE_TYPE MediumChangerFD)
|
||||
|
||||
/* okay, now for the command: */
|
||||
CDB[0] = 0x1A; /* Mode Sense(6) */
|
||||
CDB[1] = 0x08;
|
||||
CDB[1] = 0x08;
|
||||
CDB[2] = 0x1D; /* Mode Sense Element Address Assignment Page */
|
||||
CDB[3] = 0;
|
||||
CDB[4] = 136; /* allocation_length... */
|
||||
@@ -479,7 +483,7 @@ ElementModeSense_T *ReadAssignmentPage(DEVICE_TYPE MediumChangerFD)
|
||||
((int)sense_page->NumStorageHi << 8) + sense_page->NumStorageLo;
|
||||
|
||||
retval->ImportExportStart =
|
||||
((int)sense_page->ImportExportStartHi << 8) + sense_page->ImportExportStartLo;
|
||||
((int)sense_page->ImportExportStartHi << 8) + sense_page->ImportExportStartLo;
|
||||
|
||||
retval->NumImportExport =
|
||||
((int)sense_page->NumImportExportHi << 8) + sense_page->NumImportExportLo;
|
||||
@@ -491,7 +495,7 @@ ElementModeSense_T *ReadAssignmentPage(DEVICE_TYPE MediumChangerFD)
|
||||
((int)sense_page->NumDataTransferHi << 8) + sense_page->NumDataTransferLo;
|
||||
|
||||
/* allocate a couple spares 'cause some HP autochangers and maybe others
|
||||
* don't properly report the robotics arm(s) count here...
|
||||
* don't properly report the robotics arm(s) count here...
|
||||
*/
|
||||
retval->NumElements =
|
||||
retval->NumStorage+retval->NumImportExport +
|
||||
@@ -519,10 +523,18 @@ ElementModeSense_T *ReadAssignmentPage(DEVICE_TYPE MediumChangerFD)
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void FreeElementData(ElementStatus_T *data)
|
||||
void FreeElementData(ElementStatus_T *data)
|
||||
{
|
||||
if (!data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
free(data->DataTransferElementAddress);
|
||||
free(data->DataTransferElementSourceStorageElementNumber);
|
||||
free(data->DataTransferElementPhysicalLocation);
|
||||
free(data->DataTransferElementProductId);
|
||||
free(data->DataTransferElementSerialNumber);
|
||||
free(data->StorageElementPhysicalLocation);
|
||||
free(data->DataTransferPrimaryVolumeTag);
|
||||
free(data->DataTransferAlternateVolumeTag);
|
||||
free(data->PrimaryVolumeTag);
|
||||
@@ -546,8 +558,16 @@ static ElementStatus_T *AllocateElementData(ElementModeSense_T *mode_sense)
|
||||
|
||||
retval->DataTransferElementAddress =
|
||||
(int *)xzmalloc(sizeof(int) * (mode_sense->NumDataTransfer + 1));
|
||||
retval->DataTransferElementSourceStorageElementNumber =
|
||||
retval->DataTransferElementSourceStorageElementNumber =
|
||||
(int *)xzmalloc(sizeof(int) * (mode_sense->NumDataTransfer + 1));
|
||||
retval->DataTransferElementPhysicalLocation =
|
||||
(int *)xzmalloc(sizeof(int) * (mode_sense->NumDataTransfer + 1));
|
||||
retval->DataTransferElementProductId =
|
||||
(serialnumber *)xzmalloc(sizeof(serialnumber) * (mode_sense->NumDataTransfer + 1));
|
||||
retval->DataTransferElementSerialNumber =
|
||||
(serialnumber *)xzmalloc(sizeof(serialnumber) * (mode_sense->NumDataTransfer + 1));
|
||||
retval->StorageElementPhysicalLocation =
|
||||
(barcode *)xzmalloc(sizeof(barcode) * (mode_sense->NumStorage + 1));
|
||||
retval->DataTransferPrimaryVolumeTag =
|
||||
(barcode *)xzmalloc(sizeof(barcode) * (mode_sense->NumDataTransfer + 1));
|
||||
retval->DataTransferAlternateVolumeTag =
|
||||
@@ -584,14 +604,42 @@ void copy_barcode(unsigned char *src, unsigned char *dest)
|
||||
|
||||
dest++;
|
||||
}
|
||||
*dest = 0; /* null-terminate */
|
||||
*dest = 0; /* null-terminate */
|
||||
}
|
||||
|
||||
void copy_physical_location(unsigned char *src, unsigned char *dest)
|
||||
{
|
||||
while ((*src< 32) || (*src > 127)) {
|
||||
src++;
|
||||
}
|
||||
strcpy((char *)dest, (char *)src);
|
||||
}
|
||||
|
||||
void copy_char_buffer(unsigned char *src, unsigned char *dest, int num)
|
||||
{
|
||||
int i;
|
||||
while ((*src< 32) || (*src > 127)) {
|
||||
src++;
|
||||
}
|
||||
for (i=0; i < num; i++)
|
||||
{
|
||||
*dest = *src++;
|
||||
|
||||
if ((*dest < 32) || (*dest > 127))
|
||||
{
|
||||
*dest = 0;
|
||||
break;
|
||||
}
|
||||
dest++;
|
||||
}
|
||||
*dest = 0;
|
||||
}
|
||||
|
||||
/* This #%!@# routine has more parameters than I can count! */
|
||||
static unsigned char *SendElementStatusRequestActual(
|
||||
DEVICE_TYPE MediumChangerFD,
|
||||
RequestSense_T *RequestSense,
|
||||
Inquiry_T *inquiry_info,
|
||||
Inquiry_T *inquiry_info,
|
||||
SCSI_Flags_T *flags,
|
||||
int ElementStart,
|
||||
int NumElements,
|
||||
@@ -606,7 +654,7 @@ static unsigned char *SendElementStatusRequestActual(
|
||||
#ifdef HAVE_GET_ID_LUN
|
||||
scsi_id_t *scsi_id;
|
||||
#endif
|
||||
if (inquiry_info->MChngr &&
|
||||
if (inquiry_info->MChngr &&
|
||||
inquiry_info->PeripheralDeviceType != MEDIUM_CHANGER_TYPE)
|
||||
{
|
||||
is_attached = true;
|
||||
@@ -614,7 +662,7 @@ static unsigned char *SendElementStatusRequestActual(
|
||||
|
||||
if (flags->no_attached)
|
||||
{
|
||||
/* override, sigh */
|
||||
/* override, sigh */
|
||||
is_attached = false;
|
||||
}
|
||||
|
||||
@@ -630,11 +678,11 @@ static unsigned char *SendElementStatusRequestActual(
|
||||
|
||||
if (is_attached)
|
||||
{
|
||||
CDB[0] = 0xB4; /* whoops, READ_ELEMENT_STATUS_ATTACHED! */
|
||||
CDB[0] = 0xB4; /* whoops, READ_ELEMENT_STATUS_ATTACHED! */
|
||||
}
|
||||
|
||||
#ifdef HAVE_GET_ID_LUN
|
||||
CDB[1] = (scsi_id->lun << 5) | ((flags->no_barcodes) ?
|
||||
CDB[1] = (scsi_id->lun << 5) | ((flags->no_barcodes) ?
|
||||
0 : 0x10) | flags->elementtype; /* Lun + VolTag + Type code */
|
||||
free(scsi_id);
|
||||
#else
|
||||
@@ -650,6 +698,9 @@ static unsigned char *SendElementStatusRequestActual(
|
||||
CDB[5]= (unsigned char)NumElements;
|
||||
|
||||
CDB[6] = 0; /* Reserved */
|
||||
if (((flags->elementtype == DataTransferElement || flags->elementtype == StorageElement)) && (flags->absolute_addressing == 1)) {
|
||||
CDB[6] = 0x01; /* set DVCID to read physical location */
|
||||
}
|
||||
|
||||
/* allocation length */
|
||||
CDB[7]= (unsigned char)(NumBytes >> 16);
|
||||
@@ -674,7 +725,7 @@ static unsigned char *SendElementStatusRequestActual(
|
||||
|
||||
/*
|
||||
First see if we have sense key of 'illegal request',
|
||||
additional sense code of '24', additional sense qualfier of
|
||||
additional sense code of '24', additional sense qualfier of
|
||||
'0', and field in error of '4'. This means that we issued a request
|
||||
w/bar code reader and did not have one, thus must re-issue the request
|
||||
w/out barcode :-(.
|
||||
@@ -718,15 +769,15 @@ static unsigned char *SendElementStatusRequestActual(
|
||||
/* print a bunch of extra debug data :-(. */
|
||||
PrintRequestSense(RequestSense); /* see what it sez :-(. */
|
||||
fprintf(stderr,"Data:\n");
|
||||
PrintHex(2, DataBuffer, 40);
|
||||
#endif
|
||||
PrintHex(2, DataBuffer, 100);
|
||||
#endif
|
||||
return DataBuffer; /* we succeeded! */
|
||||
}
|
||||
|
||||
|
||||
unsigned char *SendElementStatusRequest(DEVICE_TYPE MediumChangerFD,
|
||||
RequestSense_T *RequestSense,
|
||||
Inquiry_T *inquiry_info,
|
||||
Inquiry_T *inquiry_info,
|
||||
SCSI_Flags_T *flags,
|
||||
int ElementStart,
|
||||
int NumElements,
|
||||
@@ -747,7 +798,7 @@ unsigned char *SendElementStatusRequest(DEVICE_TYPE MediumChangerFD,
|
||||
/*
|
||||
One weird loader wants either 8 or BYTE_COUNT_OF_REPORT
|
||||
values for the ALLOCATION_LENGTH. Give it what it wants
|
||||
if we get an Sense Key of 05 Illegal Request with a
|
||||
if we get an Sense Key of 05 Illegal Request with a
|
||||
CDB position of 7 as the field in error.
|
||||
*/
|
||||
|
||||
@@ -802,12 +853,13 @@ unsigned char *SendElementStatusRequest(DEVICE_TYPE MediumChangerFD,
|
||||
*/
|
||||
|
||||
static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
int *EmptyStorageElementCount,
|
||||
unsigned char *DataBuffer,
|
||||
ElementStatus_T *ElementStatus,
|
||||
ElementModeSense_T *mode_sense,
|
||||
int *pNextElement
|
||||
)
|
||||
int *EmptyStorageElementCount,
|
||||
unsigned char *DataBuffer,
|
||||
ElementStatus_T *ElementStatus,
|
||||
ElementModeSense_T *mode_sense,
|
||||
int *pNextElement,
|
||||
boolean absolute_address
|
||||
)
|
||||
{
|
||||
unsigned char *DataPointer = DataBuffer;
|
||||
TransportElementDescriptor_T TEBuf;
|
||||
@@ -879,7 +931,7 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
{
|
||||
/* TransportElementDescriptor =
|
||||
(TransportElementDescriptor_T *) DataPointer; */
|
||||
memcpy(&TEBuf, DataPointer,
|
||||
memcpy(&TEBuf, DataPointer,
|
||||
(TransportElementDescriptorLength <= sizeof(TEBuf)) ?
|
||||
TransportElementDescriptorLength :
|
||||
sizeof(TEBuf));
|
||||
@@ -906,7 +958,7 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
case MediumTransportElement:
|
||||
ElementStatus->TransportElementAddress = BigEndian16(TransportElementDescriptor->ElementAddress);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"TransportElementAddress=%d\n",ElementStatus->TransportElementAddress);
|
||||
fprintf(stderr,"TransportElementAddress=%d\n",ElementStatus->TransportElementAddress);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -933,7 +985,7 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
ElementStatus->StorageElementFull[ImportExportIndex] =
|
||||
TransportElementDescriptor->Full;
|
||||
|
||||
if ( (TransportElementDescriptorLength > 11) &&
|
||||
if ( (TransportElementDescriptorLength > 11) &&
|
||||
(ElementStatusPage->VolBits & E2_AVOLTAG))
|
||||
{
|
||||
copy_barcode(TransportElementDescriptor->AlternateVolumeTag,
|
||||
@@ -942,8 +994,8 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
else
|
||||
{
|
||||
ElementStatus->AlternateVolumeTag[ImportExportIndex][0] = 0; /* null string. */;
|
||||
}
|
||||
if ((TransportElementDescriptorLength > 11) &&
|
||||
}
|
||||
if ((TransportElementDescriptorLength > 11) &&
|
||||
(ElementStatusPage->VolBits & E2_PVOLTAG))
|
||||
{
|
||||
copy_barcode(TransportElementDescriptor->PrimaryVolumeTag,
|
||||
@@ -964,8 +1016,8 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
fprintf(stderr,"StorageElementCount=%d ElementAddress = %d ",ElementStatus->StorageElementCount,BigEndian16(TransportElementDescriptor->ElementAddress));
|
||||
#endif
|
||||
/* ATL/Exabyte kludge -- skip slots that aren't installed :-( */
|
||||
if (TransportElementDescriptor->AdditionalSenseCode==0x83 &&
|
||||
TransportElementDescriptor->AdditionalSenseCodeQualifier==0x02)
|
||||
if (TransportElementDescriptor->AdditionalSenseCode==0x83 &&
|
||||
TransportElementDescriptor->AdditionalSenseCodeQualifier==0x02)
|
||||
continue;
|
||||
|
||||
ElementStatus->StorageElementAddress[ElementStatus->StorageElementCount] =
|
||||
@@ -983,17 +1035,11 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
ElementStatus->StorageElementCount; /* slot idx. */
|
||||
/* ElementStatus->StorageElementAddress[ElementStatus->StorageElementCount]; */
|
||||
}
|
||||
if ((TransportElementDescriptorLength > 11) &&
|
||||
(ElementStatusPage->VolBits & E2_AVOLTAG))
|
||||
{
|
||||
copy_barcode(TransportElementDescriptor->AlternateVolumeTag,
|
||||
ElementStatus->AlternateVolumeTag[ElementStatus->StorageElementCount]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ElementStatus->AlternateVolumeTag[ElementStatus->StorageElementCount][0]=0; /* null string. */;
|
||||
}
|
||||
if ((TransportElementDescriptorLength > 11) &&
|
||||
}
|
||||
if ((TransportElementDescriptorLength > 11) &&
|
||||
(ElementStatusPage->VolBits & E2_PVOLTAG))
|
||||
{
|
||||
copy_barcode(TransportElementDescriptor->PrimaryVolumeTag,
|
||||
@@ -1003,12 +1049,16 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
{
|
||||
ElementStatus->PrimaryVolumeTag[ElementStatus->StorageElementCount][0]=0; /* null string. */
|
||||
}
|
||||
|
||||
|
||||
if (absolute_address){
|
||||
copy_physical_location(TransportElementDescriptor->AlternateVolumeTag, ElementStatus->StorageElementPhysicalLocation[ElementStatus->StorageElementCount]);
|
||||
}
|
||||
|
||||
ElementStatus->StorageElementCount++;
|
||||
/*
|
||||
Note that the original mtx had no check here for
|
||||
Note that the original mtx had no check here for
|
||||
buffer overflow, though some drives might mistakingly
|
||||
do one...
|
||||
do one...
|
||||
*/
|
||||
|
||||
if (ElementStatus->StorageElementCount > mode_sense->NumStorage)
|
||||
@@ -1030,37 +1080,47 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
report that they have a 2nd tape drive when they don't. We
|
||||
could generalize this in an ideal world, but my attempt to
|
||||
do so failed with dual-drive Exabyte tape libraries that
|
||||
*DID* have the second drive. Sigh.
|
||||
*DID* have the second drive. Sigh.
|
||||
*/
|
||||
if (TransportElementDescriptor->AdditionalSenseCode==0x83 &&
|
||||
if (TransportElementDescriptor->AdditionalSenseCode==0x83 &&
|
||||
TransportElementDescriptor->AdditionalSenseCodeQualifier==0x04)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* generalize it. Does it work? Let's try it! */
|
||||
/*
|
||||
/*
|
||||
No, dammit, following does not work on dual-drive Exabyte
|
||||
'cause if a tape is in the drive, it sets the AdditionalSense
|
||||
code to something (sigh).
|
||||
*/
|
||||
/* if (TransportElementDescriptor->AdditionalSenseCode!=0)
|
||||
continue;
|
||||
*/
|
||||
*/
|
||||
|
||||
if (absolute_address){
|
||||
ElementStatus->DataTransferElementPhysicalLocation[ElementStatus->DataTransferElementCount] =
|
||||
BigEndian16(TransportElementDescriptor->SourceStorageElementAddress);
|
||||
InquiryShort_T *inqs;
|
||||
inqs = (InquiryShort_T *) TransportElementDescriptor->PrimaryVolumeTag;
|
||||
copy_char_buffer(inqs->SerialNumber, ElementStatus->DataTransferElementSerialNumber[ElementStatus->DataTransferElementCount], 12);
|
||||
copy_char_buffer(inqs->ProductIdentification+2, ElementStatus->DataTransferElementProductId[ElementStatus->DataTransferElementCount], 12);
|
||||
ElementStatus->DataTransferElementCount++;
|
||||
break;
|
||||
}
|
||||
ElementStatus->DataTransferElementAddress[ElementStatus->DataTransferElementCount] =
|
||||
BigEndian16(TransportElementDescriptor->ElementAddress);
|
||||
ElementStatus->DataTransferElementFull[ElementStatus->DataTransferElementCount] =
|
||||
ElementStatus->DataTransferElementFull[ElementStatus->DataTransferElementCount] =
|
||||
TransportElementDescriptor->Full;
|
||||
ElementStatus->DataTransferElementSourceStorageElementNumber[ElementStatus->DataTransferElementCount] =
|
||||
BigEndian16(TransportElementDescriptor->SourceStorageElementAddress);
|
||||
BigEndian16(TransportElementDescriptor->SourceStorageElementAddress);
|
||||
|
||||
#if DEBUG
|
||||
fprintf(stderr, "%d: ElementAddress = %d, Full = %d, SourceElement = %d\n",
|
||||
ElementStatus->DataTransferElementCount,
|
||||
ElementStatus->DataTransferElementAddress[ElementStatus->DataTransferElementCount],
|
||||
ElementStatus->DataTransferElementFull[ElementStatus->DataTransferElementCount],
|
||||
ElementStatus->DataTransferElementSourceStorageElementNumber[ElementStatus->DataTransferElementCount]);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "%d: ElementAddress = %d, Full = %d, SourceElement = %d\n",
|
||||
ElementStatus->DataTransferElementCount,
|
||||
ElementStatus->DataTransferElementAddress[ElementStatus->DataTransferElementCount],
|
||||
ElementStatus->DataTransferElementFull[ElementStatus->DataTransferElementCount],
|
||||
ElementStatus->DataTransferElementSourceStorageElementNumber[ElementStatus->DataTransferElementCount]);
|
||||
#endif
|
||||
if (ElementStatus->DataTransferElementCount >= mode_sense->NumDataTransfer)
|
||||
{
|
||||
@@ -1115,17 +1175,17 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
/*
|
||||
* We no longer do the funky trick to figure out ALLOCATION_LENGTH.
|
||||
* Instead, we use the SCSI Generic command rather than SEND_SCSI_COMMAND
|
||||
* under Linux, which gets around the @#%@ 4k buffer size in Linux.
|
||||
* under Linux, which gets around the @#%@ 4k buffer size in Linux.
|
||||
* We still have the restriction that Linux cuts off the last two
|
||||
* bytes of the SENSE DATA (Q#@$%@#$^ Linux!). Which means that the
|
||||
* verbose widget won't work :-(.
|
||||
|
||||
* verbose widget won't work :-(.
|
||||
|
||||
* We now look for that "attached" bit in the inquiry_info to see whether
|
||||
* to use READ_ELEMENT_ATTACHED or plain old READ_ELEMENT. In addition, we
|
||||
* look at the device type in the inquiry_info to see whether it is a media
|
||||
* changer or tape device, and if it's a media changer device, we ignore the
|
||||
* attached bit (one beta tester found an old 4-tape DAT changer that set
|
||||
* the attached bit for both the tape device AND the media changer device).
|
||||
* the attached bit for both the tape device AND the media changer device).
|
||||
|
||||
*/
|
||||
|
||||
@@ -1141,6 +1201,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
int empty_idx = 0;
|
||||
boolean is_attached = false;
|
||||
int i,j;
|
||||
int FirstElem, NumElements, NumThisRES;
|
||||
|
||||
ElementModeSense_T *mode_sense = NULL;
|
||||
|
||||
@@ -1151,7 +1212,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
|
||||
if (flags->no_attached)
|
||||
{
|
||||
/* override, sigh */
|
||||
/* override, sigh */
|
||||
is_attached = false;
|
||||
}
|
||||
|
||||
@@ -1181,7 +1242,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
ElementStatus->DataTransferElementCount = 0;
|
||||
|
||||
/* first, allocate some empty storage stuff: Note that we pass this
|
||||
* down to ParseElementStatus (sigh!)
|
||||
* down to ParseElementStatus (sigh!)
|
||||
*/
|
||||
|
||||
EmptyStorageElementAddress = (int *)xzmalloc((mode_sense->NumStorage+1)*sizeof(int));
|
||||
@@ -1198,43 +1259,56 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
for (i = 0; i < mode_sense->NumDataTransfer; i++)
|
||||
{
|
||||
/* initialize them to an illegal # so that we can fix later... */
|
||||
ElementStatus->DataTransferElementSourceStorageElementNumber[i] = -1;
|
||||
ElementStatus->DataTransferElementSourceStorageElementNumber[i] = -1;
|
||||
}
|
||||
|
||||
if (flags->querytype == MTX_ELEMENTSTATUS_ORIGINAL)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"Using original element status polling method (storage, import/export, drivers etc independantly)\n");
|
||||
fprintf(stderr,"Storage start %d, Num %d, max %d\n", mode_sense->StorageStart, mode_sense->NumStorage - mode_sense->NumImportExport, mode_sense->MaxReadElementStatusData);
|
||||
#endif
|
||||
flags->elementtype = StorageElement; /* sigh! */
|
||||
DataBuffer = SendElementStatusRequest( MediumChangerFD, RequestSense,
|
||||
inquiry_info, flags,
|
||||
mode_sense->StorageStart,
|
||||
/* adjust for import/export. */
|
||||
mode_sense->NumStorage - mode_sense->NumImportExport,
|
||||
mode_sense->MaxReadElementStatusData);
|
||||
flags->absolute_addressing = 1;
|
||||
|
||||
if (!DataBuffer)
|
||||
NumElements = mode_sense->NumStorage - mode_sense->NumImportExport;
|
||||
FirstElem = mode_sense->StorageStart;
|
||||
|
||||
do
|
||||
{
|
||||
NumThisRES = (NumElements > SCSI_RES_ELEMENTS ? SCSI_RES_ELEMENTS : NumElements);
|
||||
DataBuffer = SendElementStatusRequest( MediumChangerFD, RequestSense,
|
||||
inquiry_info, flags,
|
||||
FirstElem,
|
||||
/* adjust for import/export. */
|
||||
NumThisRES,
|
||||
SCSI_RES_ELEMENTS * 52 +120);
|
||||
|
||||
if (!DataBuffer)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"Had no elements!\n");
|
||||
fprintf(stderr,"Had no elements!\n");
|
||||
#endif
|
||||
/* darn. Free up stuff and return. */
|
||||
/* darn. Free up stuff and return. */
|
||||
#ifdef DEBUG_MODE_SENSE
|
||||
PrintRequestSense(RequestSense);
|
||||
PrintRequestSense(RequestSense);
|
||||
#endif
|
||||
FreeElementData(ElementStatus);
|
||||
return NULL;
|
||||
}
|
||||
FreeElementData(ElementStatus);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Parsing storage elements\n");
|
||||
fprintf(stderr, "Parsing storage elements\n");
|
||||
#endif
|
||||
ParseElementStatus(EmptyStorageElementAddress, &EmptyStorageElementCount,
|
||||
DataBuffer,ElementStatus,mode_sense,NULL);
|
||||
|
||||
free(DataBuffer); /* sigh! */
|
||||
ParseElementStatus(EmptyStorageElementAddress, &EmptyStorageElementCount,
|
||||
DataBuffer,ElementStatus,mode_sense,NULL, true);
|
||||
|
||||
free(DataBuffer); /* sigh! */
|
||||
FirstElem += SCSI_RES_ELEMENTS;
|
||||
NumElements -= SCSI_RES_ELEMENTS;
|
||||
} while ( NumElements > 0 );
|
||||
|
||||
flags->absolute_addressing = 0;
|
||||
/* --------------IMPORT/EXPORT--------------- */
|
||||
/* Next let's see if we need to do Import/Export: */
|
||||
if (mode_sense->NumImportExport > 0)
|
||||
@@ -1247,8 +1321,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
inquiry_info, flags,
|
||||
mode_sense->ImportExportStart,
|
||||
mode_sense->NumImportExport,
|
||||
mode_sense->MaxReadElementStatusData);
|
||||
|
||||
SCSI_RES_ELEMENTS * 52 +120);
|
||||
if (!DataBuffer)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -1268,8 +1341,8 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
dump_data(DataBuffer, 100); /* dump some data :-(. */
|
||||
#endif
|
||||
ParseElementStatus( EmptyStorageElementAddress, &EmptyStorageElementCount,
|
||||
DataBuffer, ElementStatus, mode_sense, NULL);
|
||||
|
||||
DataBuffer, ElementStatus, mode_sense, NULL, false);
|
||||
free(DataBuffer);
|
||||
ElementStatus->StorageElementCount += ElementStatus->ImportExportCount;
|
||||
}
|
||||
|
||||
@@ -1279,11 +1352,12 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
fprintf(stderr,"Sending request for data transfer element (drive) status\n");
|
||||
#endif
|
||||
flags->elementtype = DataTransferElement; /* sigh! */
|
||||
flags->absolute_addressing = 0;
|
||||
DataBuffer = SendElementStatusRequest( MediumChangerFD, RequestSense,
|
||||
inquiry_info, flags,
|
||||
mode_sense->DataTransferStart,
|
||||
mode_sense->NumDataTransfer,
|
||||
mode_sense->MaxReadElementStatusData);
|
||||
SCSI_RES_ELEMENTS * 52 +120);
|
||||
if (!DataBuffer)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -1294,14 +1368,38 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
PrintRequestSense(RequestSense);
|
||||
#endif
|
||||
FreeElementData(ElementStatus);
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"Parsing data for data transfer element (drive) status\n");
|
||||
#endif
|
||||
ParseElementStatus( EmptyStorageElementAddress, &EmptyStorageElementCount,
|
||||
DataBuffer,ElementStatus, mode_sense, NULL);
|
||||
DataBuffer,ElementStatus, mode_sense, NULL, false);
|
||||
|
||||
free(DataBuffer); /* sigh! */
|
||||
|
||||
flags->absolute_addressing = 1;
|
||||
DataBuffer = SendElementStatusRequest( MediumChangerFD, RequestSense,
|
||||
inquiry_info, flags,
|
||||
mode_sense->DataTransferStart,
|
||||
mode_sense->NumDataTransfer,
|
||||
SCSI_RES_ELEMENTS * 52 +120);
|
||||
if (!DataBuffer)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"No data transfer element status.");
|
||||
#endif
|
||||
/* darn. Free up stuff and return. */
|
||||
#ifdef DEBUG_MODE_SENSE
|
||||
PrintRequestSense(RequestSense);
|
||||
#endif
|
||||
FreeElementData(ElementStatus);
|
||||
return NULL;
|
||||
}
|
||||
ElementStatus->DataTransferElementCount = 0;
|
||||
ParseElementStatus( EmptyStorageElementAddress, &EmptyStorageElementCount,
|
||||
DataBuffer,ElementStatus, mode_sense, NULL, true);
|
||||
|
||||
free(DataBuffer); /* sigh! */
|
||||
|
||||
@@ -1309,7 +1407,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
|
||||
/* grr, damned brain dead HP doesn't report that it has any! */
|
||||
if (!mode_sense->NumMediumTransport)
|
||||
{
|
||||
{
|
||||
ElementStatus->TransportElementAddress = 0; /* default it sensibly :-(. */
|
||||
}
|
||||
else
|
||||
@@ -1322,7 +1420,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
inquiry_info, flags,
|
||||
mode_sense->MediumTransportStart,
|
||||
1, /* only get 1, sigh. */
|
||||
mode_sense->MaxReadElementStatusData);
|
||||
SCSI_RES_ELEMENTS * 52 +120);
|
||||
if (!DataBuffer)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -1333,16 +1431,17 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
PrintRequestSense(RequestSense);
|
||||
#endif
|
||||
FreeElementData(ElementStatus);
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"Parsing robot arm data\n");
|
||||
#endif
|
||||
ParseElementStatus( EmptyStorageElementAddress, &EmptyStorageElementCount,
|
||||
DataBuffer, ElementStatus, mode_sense, NULL);
|
||||
DataBuffer, ElementStatus, mode_sense, NULL, false);
|
||||
|
||||
free(DataBuffer);
|
||||
}
|
||||
flags->absolute_addressing = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1352,8 +1451,8 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
fprintf(stderr,"Using alternative element status polling method (all elements)\n");
|
||||
#endif
|
||||
/* ----------------- ALL Elements ---------------------- */
|
||||
/* Just keep asking for elements till no more are returned
|
||||
- increment our starting address as we go acording to the
|
||||
/* Just keep asking for elements till no more are returned
|
||||
- increment our starting address as we go acording to the
|
||||
number of elements returned from the last call
|
||||
*/
|
||||
|
||||
@@ -1370,7 +1469,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
mode_sense->MaxReadElementStatusData);
|
||||
if (!DataBuffer)
|
||||
{
|
||||
if (RequestSense->AdditionalSenseCode == 0x21 &&
|
||||
if (RequestSense->AdditionalSenseCode == 0x21 &&
|
||||
RequestSense->AdditionalSenseCodeQualifier == 0x01)
|
||||
{
|
||||
/* Error is invalid element address, we've probably just hit the end */
|
||||
@@ -1379,13 +1478,13 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
|
||||
/* darn. Free up stuff and return. */
|
||||
FreeElementData(ElementStatus);
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nLastEl = nNextEl;
|
||||
|
||||
ParseElementStatus( EmptyStorageElementAddress, &EmptyStorageElementCount,
|
||||
DataBuffer, ElementStatus, mode_sense, &nNextEl);
|
||||
DataBuffer, ElementStatus, mode_sense, &nNextEl, false);
|
||||
|
||||
free(DataBuffer); /* sigh! */
|
||||
}
|
||||
@@ -1409,7 +1508,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
*
|
||||
* Pass1:
|
||||
* Translate from raw element # to our translated # (if possible).
|
||||
* First, check the SourceStorageElementNumbers against the list of
|
||||
* First, check the SourceStorageElementNumbers against the list of
|
||||
* filled slots. If the slots indicated are empty, we accept that list as
|
||||
* valid. Otherwise decide the SourceStorageElementNumbers are invalid.
|
||||
*
|
||||
@@ -1418,7 +1517,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
* then we must search for free slots, and assign SourceStorageElementNumbers
|
||||
* to those free slots. We happen to already built a list of free
|
||||
* slots as part of the process of reading the storage element numbers
|
||||
* from the tape. So that's easy enough to do!
|
||||
* from the tape. So that's easy enough to do!
|
||||
*/
|
||||
|
||||
#ifdef DEBUG_TAPELIST
|
||||
@@ -1434,7 +1533,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
|
||||
/*
|
||||
* Now we re-assign origin slots if the "real" origin slot
|
||||
* is obviously defective:
|
||||
* is obviously defective:
|
||||
*/
|
||||
/* pass one: */
|
||||
for (i = 0; i < ElementStatus->DataTransferElementCount; i++)
|
||||
@@ -1472,12 +1571,12 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
* drives will be assigned a -1 (see the initialization loop for
|
||||
* EmptyStorageElementAddress above), which will be reported as "slot 0"
|
||||
* by the user interface. This is an invalid value, but more useful for us
|
||||
* to have than just crapping out here :-(.
|
||||
* to have than just crapping out here :-(.
|
||||
*/
|
||||
empty_idx=0;
|
||||
for (i = 0; i < ElementStatus->DataTransferElementCount; i++)
|
||||
{
|
||||
if (ElementStatus->DataTransferElementFull[i] &&
|
||||
if (ElementStatus->DataTransferElementFull[i] &&
|
||||
ElementStatus->DataTransferElementSourceStorageElementNumber[i] < 0)
|
||||
{
|
||||
#ifdef DEBUG_TAPELIST
|
||||
@@ -1529,7 +1628,7 @@ RequestSense_T *PositionElement(DEVICE_TYPE MediumChangerFD,
|
||||
|
||||
/* Now the actual media movement routine! */
|
||||
RequestSense_T *MoveMedium( DEVICE_TYPE MediumChangerFD, int SourceAddress,
|
||||
int DestinationAddress,
|
||||
int DestinationAddress,
|
||||
ElementStatus_T *ElementStatus,
|
||||
Inquiry_T *inquiry_info, SCSI_Flags_T *flags)
|
||||
{
|
||||
@@ -1632,7 +1731,7 @@ RequestSense_T *ExchangeMedium( DEVICE_TYPE MediumChangerFD, int SourceAddress,
|
||||
|
||||
#ifdef DEBUG_EXCHANGE
|
||||
dump_cdb(&CDB,12);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (SCSI_ExecuteCommand(MediumChangerFD, Output, &CDB, 12,
|
||||
NULL, 0, RequestSense) != 0)
|
||||
@@ -1676,8 +1775,8 @@ RequestSense_T *Erase(DEVICE_TYPE MediumChangerFD)
|
||||
return NULL; /* Success! */
|
||||
}
|
||||
|
||||
/* Routine to send an LOAD/UNLOAD from the MMC/SSC spec to a device.
|
||||
* For tapes and changers this can be used either to eject a tape
|
||||
/* Routine to send an LOAD/UNLOAD from the MMC/SSC spec to a device.
|
||||
* For tapes and changers this can be used either to eject a tape
|
||||
* or to eject a magazine (on some Seagate changers, when sent to LUN 1 ).
|
||||
* For CD/DVDs this is used to Load or Unload a disc which is required by
|
||||
* some media changers.
|
||||
@@ -1707,8 +1806,8 @@ int LoadUnload(DEVICE_TYPE fd, int bLoad)
|
||||
return 0; /* did do! */
|
||||
}
|
||||
|
||||
/* Routine to send an START/STOP from the MMC/SSC spec to a device.
|
||||
* For tape drives this may be required prior to using the changer
|
||||
/* Routine to send an START/STOP from the MMC/SSC spec to a device.
|
||||
* For tape drives this may be required prior to using the changer
|
||||
* Load or Unload commands.
|
||||
* For CD/DVD drives this is used to Load or Unload a disc which may be
|
||||
* required by some media changers.
|
||||
@@ -1732,9 +1831,9 @@ int StartStop(DEVICE_TYPE fd, int bStart)
|
||||
return 0; /* did do! */
|
||||
}
|
||||
|
||||
/* Routine to send a LOCK/UNLOCK from the SSC/MMC spec to a device.
|
||||
/* Routine to send a LOCK/UNLOCK from the SSC/MMC spec to a device.
|
||||
* This can be used to prevent or allow the Tape or CD/DVD from being
|
||||
* removed.
|
||||
* removed.
|
||||
*/
|
||||
|
||||
int LockUnlock(DEVICE_TYPE fd, int bLock)
|
||||
@@ -1862,7 +1961,7 @@ void PrintRequestSense(RequestSense_T *RequestSense)
|
||||
fprintf(stderr, "mtx: Request Sense: Valid Residual=%s\n", RequestSense->Valid ? Yes : No);
|
||||
|
||||
if (RequestSense->ErrorCode == 0x70)
|
||||
{
|
||||
{
|
||||
msg = "Current" ;
|
||||
}
|
||||
else if (RequestSense->ErrorCode == 0x71)
|
||||
|
||||
@@ -60,6 +60,7 @@ ElementStatus_T *ReadElementStatus( DEVICE_TYPE MediumChangerFD,
|
||||
RequestSense_T *RequestSense,
|
||||
Inquiry_T *inquiry_info,
|
||||
SCSI_Flags_T *flags);
|
||||
void FreeElementData(ElementStatus_T *data);
|
||||
|
||||
Inquiry_T *RequestInquiry( DEVICE_TYPE fd,
|
||||
RequestSense_T *RequestSense);
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
diff --git a/mtxl.c b/mtxl.c
|
||||
index 3ae77a6..12ea157 100644
|
||||
--- a/mtxl.c
|
||||
+++ b/mtxl.c
|
||||
@@ -39,6 +39,9 @@
|
||||
/* zap the following define when we finally add real import/export support */
|
||||
#define IMPORT_EXPORT_HACK 1 /* for the moment, import/export == storage */
|
||||
|
||||
+/* only so many element per SCSI Read Element Status */
|
||||
+#define SCSI_RES_ELEMENTS 5000
|
||||
+
|
||||
/* First, do some SCSI routines: */
|
||||
|
||||
/* the camlib is used on FreeBSD. */
|
||||
@@ -1055,7 +1058,7 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
ElementStatus->DataTransferElementSourceStorageElementNumber[ElementStatus->DataTransferElementCount] =
|
||||
BigEndian16(TransportElementDescriptor->SourceStorageElementAddress);
|
||||
|
||||
-#if DEBUG
|
||||
+#ifdef DEBUG
|
||||
fprintf(stderr, "%d: ElementAddress = %d, Full = %d, SourceElement = %d\n",
|
||||
ElementStatus->DataTransferElementCount,
|
||||
ElementStatus->DataTransferElementAddress[ElementStatus->DataTransferElementCount],
|
||||
@@ -1141,6 +1144,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
int empty_idx = 0;
|
||||
boolean is_attached = false;
|
||||
int i,j;
|
||||
+ int FirstElem, NumElements, NumThisRES;
|
||||
|
||||
ElementModeSense_T *mode_sense = NULL;
|
||||
|
||||
@@ -1205,35 +1209,46 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"Using original element status polling method (storage, import/export, drivers etc independantly)\n");
|
||||
+ fprintf(stderr,"Storage start %d, Num %d, max %d\n", mode_sense->StorageStart, mode_sense->NumStorage - mode_sense->NumImportExport, mode_sense->MaxReadElementStatusData);
|
||||
#endif
|
||||
flags->elementtype = StorageElement; /* sigh! */
|
||||
- DataBuffer = SendElementStatusRequest( MediumChangerFD, RequestSense,
|
||||
+
|
||||
+ NumElements = mode_sense->NumStorage - mode_sense->NumImportExport;
|
||||
+ FirstElem = mode_sense->StorageStart;
|
||||
+
|
||||
+ do
|
||||
+ {
|
||||
+ NumThisRES = (NumElements > SCSI_RES_ELEMENTS ? SCSI_RES_ELEMENTS : NumElements);
|
||||
+ DataBuffer = SendElementStatusRequest( MediumChangerFD, RequestSense,
|
||||
inquiry_info, flags,
|
||||
- mode_sense->StorageStart,
|
||||
+ FirstElem,
|
||||
/* adjust for import/export. */
|
||||
- mode_sense->NumStorage - mode_sense->NumImportExport,
|
||||
- mode_sense->MaxReadElementStatusData);
|
||||
+ NumThisRES,
|
||||
+ SCSI_RES_ELEMENTS * 52 +120);
|
||||
|
||||
- if (!DataBuffer)
|
||||
- {
|
||||
+ if (!DataBuffer)
|
||||
+ {
|
||||
#ifdef DEBUG
|
||||
- fprintf(stderr,"Had no elements!\n");
|
||||
+ fprintf(stderr,"Had no elements!\n");
|
||||
#endif
|
||||
- /* darn. Free up stuff and return. */
|
||||
+ /* darn. Free up stuff and return. */
|
||||
#ifdef DEBUG_MODE_SENSE
|
||||
- PrintRequestSense(RequestSense);
|
||||
+ PrintRequestSense(RequestSense);
|
||||
#endif
|
||||
- FreeElementData(ElementStatus);
|
||||
- return NULL;
|
||||
- }
|
||||
+ FreeElementData(ElementStatus);
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
#ifdef DEBUG
|
||||
- fprintf(stderr, "Parsing storage elements\n");
|
||||
+ fprintf(stderr, "Parsing storage elements\n");
|
||||
#endif
|
||||
- ParseElementStatus(EmptyStorageElementAddress, &EmptyStorageElementCount,
|
||||
- DataBuffer,ElementStatus,mode_sense,NULL);
|
||||
+ ParseElementStatus(EmptyStorageElementAddress, &EmptyStorageElementCount,
|
||||
+ DataBuffer,ElementStatus,mode_sense,NULL);
|
||||
|
||||
- free(DataBuffer); /* sigh! */
|
||||
+ free(DataBuffer); /* sigh! */
|
||||
+ FirstElem += SCSI_RES_ELEMENTS;
|
||||
+ NumElements -= SCSI_RES_ELEMENTS;
|
||||
+ } while ( NumElements > 0 );
|
||||
|
||||
/* --------------IMPORT/EXPORT--------------- */
|
||||
/* Next let's see if we need to do Import/Export: */
|
||||
@@ -1247,8 +1262,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
inquiry_info, flags,
|
||||
mode_sense->ImportExportStart,
|
||||
mode_sense->NumImportExport,
|
||||
- mode_sense->MaxReadElementStatusData);
|
||||
-
|
||||
+ SCSI_RES_ELEMENTS * 52 +120);
|
||||
if (!DataBuffer)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -1283,7 +1297,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
inquiry_info, flags,
|
||||
mode_sense->DataTransferStart,
|
||||
mode_sense->NumDataTransfer,
|
||||
- mode_sense->MaxReadElementStatusData);
|
||||
+ SCSI_RES_ELEMENTS * 52 +120);
|
||||
if (!DataBuffer)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -1322,7 +1336,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
inquiry_info, flags,
|
||||
mode_sense->MediumTransportStart,
|
||||
1, /* only get 1, sigh. */
|
||||
- mode_sense->MaxReadElementStatusData);
|
||||
+ SCSI_RES_ELEMENTS * 52 +120);
|
||||
if (!DataBuffer)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
|
||||
45
mtx-1.3.12/patches/mtx-1.3.12-argc.patch
Normal file
45
mtx-1.3.12/patches/mtx-1.3.12-argc.patch
Normal file
@@ -0,0 +1,45 @@
|
||||
From f8e0af006f6a85243f0882ed08d31016032531b1 Mon Sep 17 00:00:00 2001
|
||||
From: =?utf-8?q?Dan=20Hor=C3=A1k?= <dan@danny.cz>
|
||||
Date: Thu, 19 Nov 2009 15:45:54 +0100
|
||||
Subject: [PATCH 2/2] remove the weird debugging-like info
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The loaderinfo and tapeinfo utilities print a debugging-like information
|
||||
about the number of arguments on command line when started with wrong number
|
||||
of arguments.
|
||||
|
||||
Signed-off-by: Dan Horák <dan@danny.cz>
|
||||
---
|
||||
mtx/loaderinfo.c | 1 -
|
||||
mtx/tapeinfo.c | 1 -
|
||||
2 files changed, 0 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/mtx/loaderinfo.c b/mtx/loaderinfo.c
|
||||
index 534666f..27d22d9 100644
|
||||
--- a/mtx/loaderinfo.c
|
||||
+++ b/mtx/loaderinfo.c
|
||||
@@ -488,7 +488,6 @@ int main(int argc, char **argv)
|
||||
argv0=argv[0];
|
||||
if (argc != 3)
|
||||
{
|
||||
- fprintf(stderr,"argc=%d",argc);
|
||||
usage();
|
||||
}
|
||||
|
||||
diff --git a/mtx/tapeinfo.c b/mtx/tapeinfo.c
|
||||
index 4d9c283..67547a6 100644
|
||||
--- a/mtx/tapeinfo.c
|
||||
+++ b/mtx/tapeinfo.c
|
||||
@@ -933,7 +933,6 @@ int main(int argc, char **argv)
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
- fprintf(stderr,"argc=%d",argc);
|
||||
usage();
|
||||
}
|
||||
|
||||
--
|
||||
1.6.3.3
|
||||
|
||||
47
mtx-1.3.12/patches/mtx-1.3.12-destdir.patch
Normal file
47
mtx-1.3.12/patches/mtx-1.3.12-destdir.patch
Normal file
@@ -0,0 +1,47 @@
|
||||
From a5d4d1c2fbdad8b24c2938b00406bccb037e5ab4 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Horak <dan@danny.cz>
|
||||
Date: Sat, 24 Jan 2009 18:06:43 +0100
|
||||
Subject: [PATCH 1/2] add support for DESTDIR
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
|
||||
Signed-off-by: Dan Horák <dan@danny.cz>
|
||||
---
|
||||
mtx/Makefile.in | 9 +++++----
|
||||
1 files changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/mtx/Makefile.in b/mtx/Makefile.in
|
||||
index 6b967cf..05894d2 100644
|
||||
--- a/mtx/Makefile.in
|
||||
+++ b/mtx/Makefile.in
|
||||
@@ -33,6 +33,7 @@ INSTALL_DOC = $(INSTALL) -m 644
|
||||
INSTALL_BIN = $(INSTALL) -m 755
|
||||
INSTALL_DIR = $(INSTALL) -m 755 -d
|
||||
|
||||
+DESTDIR =
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
sbindir = @sbindir@
|
||||
@@ -109,13 +110,13 @@ all: $(BINS)
|
||||
dbgs: $(DBGS)
|
||||
|
||||
install: $(BINS)
|
||||
- $(INSTALL_DIR) $(sbindir)
|
||||
+ $(INSTALL_DIR) $(DESTDIR)$(sbindir)
|
||||
for file in $(BINS); do \
|
||||
- $(INSTALL_BIN) "$$file" $(sbindir) ; \
|
||||
+ $(INSTALL_BIN) "$$file" $(DESTDIR)$(sbindir) ; \
|
||||
done
|
||||
- $(INSTALL_DIR) $(mandir) $(mandir)/man1
|
||||
+ $(INSTALL_DIR) $(DESTDIR)$(mandir) $(DESTDIR)$(mandir)/man1
|
||||
for file in mtx.1 tapeinfo.1 scsitape.1 scsieject.1 loaderinfo.1 ; do \
|
||||
- $(INSTALL_DOC) "$$file" $(mandir)/man1 ; \
|
||||
+ $(INSTALL_DOC) "$$file" $(DESTDIR)$(mandir)/man1 ; \
|
||||
done
|
||||
|
||||
clean:
|
||||
--
|
||||
1.6.3.3
|
||||
|
||||
11
mtx-1.3.12/patches/mtx-1.3.12-fix-resource-leak.patch
Normal file
11
mtx-1.3.12/patches/mtx-1.3.12-fix-resource-leak.patch
Normal file
@@ -0,0 +1,11 @@
|
||||
--- a/mtxl.c 2016-03-16 18:53:48.947779146 +0100
|
||||
+++ b/mtxl.c 2016-03-16 18:55:15.592873800 +0100
|
||||
@@ -1283,7 +1283,7 @@
|
||||
#endif
|
||||
ParseElementStatus( EmptyStorageElementAddress, &EmptyStorageElementCount,
|
||||
DataBuffer, ElementStatus, mode_sense, NULL);
|
||||
-
|
||||
+ free(DataBuffer);
|
||||
ElementStatus->StorageElementCount += ElementStatus->ImportExportCount;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
From 26bf6f6794a8a35f69dc2a8a01e69bf50200800f Mon Sep 17 00:00:00 2001
|
||||
From: David Sommerseth <davids@redhat.com>
|
||||
Date: Fri, 6 May 2016 21:00:58 +0200
|
||||
Subject: [PATCH] man: Document mtx eject and previous operations
|
||||
|
||||
---
|
||||
mtx.1 | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/mtx.1 b/mtx.1
|
||||
index a5e6cc6..108836e 100644
|
||||
--- a/mtx.1
|
||||
+++ b/mtx.1
|
||||
@@ -131,13 +131,16 @@ may need to eject the tape using your OS's tape control commands
|
||||
first). Note that this command may not be what you want on large
|
||||
tape libraries -- e.g. on Exabyte 220, the first slot is usually a
|
||||
cleaning tape. If <drivenum> is omitted, defaults to first drive.
|
||||
-
|
||||
.TP 10
|
||||
.B last [<drivenum>]
|
||||
Loads drive <drivenum> from the last slot in the media changer. Unloads
|
||||
the drive if there is already a tape in it. (Note: you may need to eject
|
||||
the tape using your OS's tape control commands first).
|
||||
.TP 10
|
||||
+.B previous [<drivenum>]
|
||||
+Unloads the drive and loads the previous tape in sequence. If the drive
|
||||
+was empty, loads the first tape into the drive.
|
||||
+.TP 10
|
||||
.B next [<drivenum>]
|
||||
Unloads the drive and loads the next tape in sequence. If the drive was
|
||||
empty, loads the first tape into the drive.
|
||||
@@ -145,6 +148,9 @@ empty, loads the first tape into the drive.
|
||||
.B position <slotnum>
|
||||
Positions the robot at a specific slot. Needed by some changers to
|
||||
move to and open the import/export, or mailbox, slot.
|
||||
+.TP 10
|
||||
+.B eject
|
||||
+Eject the tape currently in the drive.
|
||||
|
||||
.SH AUTHORS
|
||||
The original 'mtx' program was written by Leonard Zubkoff and extensively
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
691
mtx-1.3.12/patches/mtx-1.3.12-mtx-library.patch
Normal file
691
mtx-1.3.12/patches/mtx-1.3.12-mtx-library.patch
Normal file
@@ -0,0 +1,691 @@
|
||||
diff --git a/mtx-1.3.12/Makefile.in b/mtx-1.3.12/Makefile.in
|
||||
index 05894d2..18fc35b 100644
|
||||
--- a/mtx-1.3.12/Makefile.in
|
||||
+++ b/mtx-1.3.12/Makefile.in
|
||||
@@ -3,16 +3,17 @@
|
||||
# USE GMAKE, NOT REGULAR BSD MAKE!)
|
||||
#
|
||||
# Valid targets:
|
||||
-# linux86 freebsd86 solarissparc sgi dec vms
|
||||
+# linux86 freebsd86 solarissparc sgi dec vms
|
||||
#
|
||||
# Makefile changes by Lars Kellogg-Stedman for better integration with
|
||||
-# GNU Autoconf.
|
||||
+# GNU Autoconf.
|
||||
|
||||
# Version # for 'make dist'...
|
||||
VERSION=1.3.12
|
||||
|
||||
BINS = mtx@EXEEXT@ tapeinfo@EXEEXT@ loaderinfo@EXEEXT@ scsitape@EXEEXT@ scsieject@EXEEXT@
|
||||
EXTRA_BINS = nsmhack@EXEEXT@
|
||||
+LIB=libmtx.a
|
||||
DBGS := $(BINS:%@EXEEXT@=%.dbg)
|
||||
MAN = mtx.1 tapeinfo.1 loaderinfo.1 scsitape.1 scsieject.1
|
||||
MAN_HTML := $(MAN:%.1=%.html)
|
||||
@@ -46,7 +47,7 @@ VPATH = $(srcdir)
|
||||
# Linux on x86...
|
||||
#
|
||||
ifeq ($(TARGET),linux)
|
||||
-CFLAGS += -Wall
|
||||
+CFLAGS += -Wall -fpic -O3
|
||||
CPPFLAGS += -DLONG_PRINT_REQUEST_SENSE=1
|
||||
endif
|
||||
|
||||
@@ -64,7 +65,7 @@ LIBS += -lcam
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),hpux)
|
||||
-CFLAGS += -O -D_HPUX_SOURCE -D __hpux__
|
||||
+CFLAGS += -O -D_HPUX_SOURCE -D __hpux__
|
||||
endif
|
||||
|
||||
#
|
||||
@@ -105,7 +106,7 @@ else
|
||||
strip $< -o $@
|
||||
endif
|
||||
|
||||
-all: $(BINS)
|
||||
+all: $(BINS) $(LIB)
|
||||
|
||||
dbgs: $(DBGS)
|
||||
|
||||
@@ -113,7 +114,7 @@ install: $(BINS)
|
||||
$(INSTALL_DIR) $(DESTDIR)$(sbindir)
|
||||
for file in $(BINS); do \
|
||||
$(INSTALL_BIN) "$$file" $(DESTDIR)$(sbindir) ; \
|
||||
- done
|
||||
+ done
|
||||
$(INSTALL_DIR) $(DESTDIR)$(mandir) $(DESTDIR)$(mandir)/man1
|
||||
for file in mtx.1 tapeinfo.1 scsitape.1 scsieject.1 loaderinfo.1 ; do \
|
||||
$(INSTALL_DOC) "$$file" $(DESTDIR)$(mandir)/man1 ; \
|
||||
@@ -132,7 +133,7 @@ distclean: clean
|
||||
rm -f Makefile config.h config.log config.cache config.status
|
||||
|
||||
dist: distclean
|
||||
- ./makedist $(VERSION)
|
||||
+ ./makedist $(VERSION)
|
||||
|
||||
loaderinfo@EXEEXT@: loaderinfo.o mtxl.o mtxl.h mtx.h $(EXTRA)
|
||||
$(CC) $(LDFLAGS) -o loaderinfo@EXEEXT@ loaderinfo.o mtxl.o $(EXTRA) $(LIBS)
|
||||
@@ -143,7 +144,7 @@ nsmhack@EXEEXT@: nsmhack.o mtxl.o $(EXTRA)
|
||||
mtx@EXEEXT@: mtx.o mtxl.o mtxl.h mtx.h $(EXTRA)
|
||||
$(CC) $(LDFLAGS) -o mtx@EXEEXT@ mtx.o mtxl.o $(EXTRA) $(LIBS)
|
||||
|
||||
-mam2debug@EXEEXT@: mtxl.o mam2debug.o mtx.h $(EXTRA)
|
||||
+mam2debug@EXEEXT@: mtxl.o mam2debug.o mtx.h $(EXTRA)
|
||||
$(CC) $(LDFLAGS) -o mam2debug@EXEEXT@ mtxl.o mam2debug.o $(EXTRA) $(LIBS)
|
||||
|
||||
tapeinfo@EXEEXT@: tapeinfo.o mtxl.o mtx.h mtxl.h $(EXTRA)
|
||||
@@ -160,6 +161,9 @@ scsitape.o: scsitape.c mtx.h mtxl.h
|
||||
scsieject@EXEEXT@: scsieject.o mtxl.o mtxl.h mtx.h $(EXTRA)
|
||||
$(CC) $(LDFLAGS) -o scsieject@EXEEXT@ scsieject.o mtxl.o $(EXTRA) $(LIBS)
|
||||
|
||||
+$(LIB): mtx.o mtxl.o
|
||||
+ ar qvs contrib/$(LIB) mtx.o mtxl.o
|
||||
+ $(CC) $(LDFLAGS) -shared -o contrib/libmtx.so mtx.o mtxl.o
|
||||
scsieject.o: scsieject.c mtx.h mtxl.h
|
||||
|
||||
loaderinfo.o: loaderinfo.c mtx.h mtxl.h
|
||||
diff --git a/mtx-1.3.12/mtx.c b/mtx-1.3.12/mtx.c
|
||||
index fab11bb..e09d161 100644
|
||||
--- a/mtx-1.3.12/mtx.c
|
||||
+++ b/mtx-1.3.12/mtx.c
|
||||
@@ -79,7 +79,8 @@ static char *PeripheralDeviceType[32] =
|
||||
static int argc;
|
||||
static char **argv;
|
||||
|
||||
-static char *device=NULL; /* the device name passed as argument */
|
||||
+char *device=NULL; /* the device name passed as argument */
|
||||
+int absolute_addressing=0; /* if not 0 - use absolute adresses of storage and tranport elements as known to the robot */
|
||||
|
||||
/* Unfortunately this must be true for SGI, because SGI does not
|
||||
use an int :-(.
|
||||
@@ -496,14 +497,24 @@ static void Status(void)
|
||||
TransferElementNumber < ElementStatus->DataTransferElementCount;
|
||||
TransferElementNumber++)
|
||||
{
|
||||
-
|
||||
+ if (absolute_addressing==0) {
|
||||
printf("Data Transfer Element %d:", TransferElementNumber);
|
||||
+ }
|
||||
+ else {
|
||||
+ printf("Data Transfer Element %d :", ElementStatus->DataTransferElementAddress[TransferElementNumber]);
|
||||
+ }
|
||||
if (ElementStatus->DataTransferElementFull[TransferElementNumber])
|
||||
{
|
||||
if (ElementStatus->DataTransferElementSourceStorageElementNumber[TransferElementNumber] > -1)
|
||||
{
|
||||
- printf("Full (Storage Element %d Loaded)",
|
||||
- ElementStatus->DataTransferElementSourceStorageElementNumber[TransferElementNumber]+1);
|
||||
+ if (absolute_addressing==0) {
|
||||
+ printf("Full (Storage Element %d Loaded)",
|
||||
+ ElementStatus->DataTransferElementSourceStorageElementNumber[TransferElementNumber]+1);
|
||||
+ }
|
||||
+ else {
|
||||
+ printf("Full (Storage Element %d Loaded)",
|
||||
+ ElementStatus->StorageElementAddress[TransferElementNumber]);
|
||||
+ }
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -531,9 +542,16 @@ static void Status(void)
|
||||
StorageElementNumber < ElementStatus->StorageElementCount;
|
||||
StorageElementNumber++)
|
||||
{
|
||||
+ if (absolute_addressing==0) {
|
||||
printf( " Storage Element %d%s:%s", StorageElementNumber + 1,
|
||||
(ElementStatus->StorageElementIsImportExport[StorageElementNumber]) ? " IMPORT/EXPORT" : "",
|
||||
(ElementStatus->StorageElementFull[StorageElementNumber] ? "Full " : "Empty"));
|
||||
+ }
|
||||
+ else {
|
||||
+ printf( " Storage Element %d%s:%s", ElementStatus->StorageElementAddress[StorageElementNumber],
|
||||
+ (ElementStatus->StorageElementIsImportExport[StorageElementNumber]) ? " IMPORT/EXPORT" : "",
|
||||
+ (ElementStatus->StorageElementFull[StorageElementNumber] ? "Full " : "Empty"));
|
||||
+ }
|
||||
|
||||
if (ElementStatus->PrimaryVolumeTag[StorageElementNumber][0])
|
||||
{
|
||||
@@ -918,7 +936,6 @@ void execute_command(struct command_table_struct *command)
|
||||
}
|
||||
open_device();
|
||||
}
|
||||
-
|
||||
if (!ElementStatus && command->need_status)
|
||||
{
|
||||
inquiry_info = RequestInquiry(MediumChangerFD,&RequestSense);
|
||||
diff --git a/mtx-1.3.12/mtxl.c b/mtx-1.3.12/mtxl.c
|
||||
index c468f88..5e3b921 100644
|
||||
--- a/mtx-1.3.12/mtxl.c
|
||||
+++ b/mtx-1.3.12/mtxl.c
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* FatalError: changed Feb. 2000 elg@badtux.org to eliminate a buffer
|
||||
- * overflow :-(. That could be important if mtxl is SUID for some reason.
|
||||
+ * overflow :-(. That could be important if mtxl is SUID for some reason.
|
||||
*/
|
||||
|
||||
#include "mtx.h"
|
||||
@@ -34,7 +34,7 @@
|
||||
/* #define DEBUG_MODE_SENSE 1 */
|
||||
/* #define DEBUG */
|
||||
/* #define DEBUG_SCSI */
|
||||
-#define __WEIRD_CHAR_SUPPRESS 1
|
||||
+#define __WEIRD_CHAR_SUPPRESS 1
|
||||
|
||||
/* zap the following define when we finally add real import/export support */
|
||||
#define IMPORT_EXPORT_HACK 1 /* for the moment, import/export == storage */
|
||||
@@ -100,7 +100,7 @@ Inquiry_T *RequestInquiry(DEVICE_TYPE fd, RequestSense_T *RequestSense)
|
||||
Inquiry_T *Inquiry;
|
||||
CDB_T CDB;
|
||||
|
||||
- Inquiry = (Inquiry_T *) xmalloc(sizeof(Inquiry_T));
|
||||
+ Inquiry = (Inquiry_T *) xmalloc(sizeof(Inquiry_T));
|
||||
|
||||
CDB[0] = 0x12; /* INQUIRY */
|
||||
CDB[1] = 0; /* EVPD = 0 */
|
||||
@@ -231,7 +231,8 @@ void FatalError(char *ErrorMessage, ...)
|
||||
va_end(ArgumentPointer);
|
||||
|
||||
#ifndef VMS
|
||||
- exit(1);
|
||||
+ //exit(1);
|
||||
+ return; /* if used as library routine it can not exit, because this would terminate the caller */
|
||||
#else
|
||||
sys$exit(VMS_ExitCode);
|
||||
#endif
|
||||
@@ -280,10 +281,10 @@ int max(int x, int y)
|
||||
|
||||
|
||||
/* Okay, this is a hack for the NSM modular jukebox series, which
|
||||
- * uses the "SEND DIAGNOSTIC" command to do shit.
|
||||
+ * uses the "SEND DIAGNOSTIC" command to do shit.
|
||||
*/
|
||||
|
||||
-int SendNSMHack(DEVICE_TYPE MediumChangerFD, NSM_Param_T *nsm_command,
|
||||
+int SendNSMHack(DEVICE_TYPE MediumChangerFD, NSM_Param_T *nsm_command,
|
||||
int param_len, int timeout)
|
||||
{
|
||||
CDB_T CDB;
|
||||
@@ -362,7 +363,7 @@ NSM_Result_T *RecNSMHack( DEVICE_TYPE MediumChangerFD,
|
||||
|
||||
/* Routine to inventory the library. Needed by, e.g., some Breece Hill
|
||||
* loaders. Sends an INITIALIZE_ELEMENT_STATUS command. This command
|
||||
- * has no parameters, such as a range to scan :-(.
|
||||
+ * has no parameters, such as a range to scan :-(.
|
||||
*/
|
||||
|
||||
int Inventory(DEVICE_TYPE MediumChangerFD)
|
||||
@@ -370,7 +371,7 @@ int Inventory(DEVICE_TYPE MediumChangerFD)
|
||||
CDB_T CDB;
|
||||
|
||||
/* okay, now for the command: */
|
||||
- CDB[0] = 0x07;
|
||||
+ CDB[0] = 0x07;
|
||||
CDB[1] = CDB[2] = CDB[3] = CDB[4] = CDB[5] = 0;
|
||||
|
||||
/* set us a very long timeout, sigh... */
|
||||
@@ -394,8 +395,8 @@ int Inventory(DEVICE_TYPE MediumChangerFD)
|
||||
/* Routine to read the Mode Sense Element Address Assignment Page */
|
||||
/* We try to read the page. If we can't read the page, we return NULL.
|
||||
* Our caller really isn't too worried about why we could not read the
|
||||
- * page, it will simply default to some kind of default values.
|
||||
- */
|
||||
+ * page, it will simply default to some kind of default values.
|
||||
+ */
|
||||
ElementModeSense_T *ReadAssignmentPage(DEVICE_TYPE MediumChangerFD)
|
||||
{
|
||||
CDB_T CDB;
|
||||
@@ -405,7 +406,7 @@ ElementModeSense_T *ReadAssignmentPage(DEVICE_TYPE MediumChangerFD)
|
||||
|
||||
/* okay, now for the command: */
|
||||
CDB[0] = 0x1A; /* Mode Sense(6) */
|
||||
- CDB[1] = 0x08;
|
||||
+ CDB[1] = 0x08;
|
||||
CDB[2] = 0x1D; /* Mode Sense Element Address Assignment Page */
|
||||
CDB[3] = 0;
|
||||
CDB[4] = 136; /* allocation_length... */
|
||||
@@ -482,7 +483,7 @@ ElementModeSense_T *ReadAssignmentPage(DEVICE_TYPE MediumChangerFD)
|
||||
((int)sense_page->NumStorageHi << 8) + sense_page->NumStorageLo;
|
||||
|
||||
retval->ImportExportStart =
|
||||
- ((int)sense_page->ImportExportStartHi << 8) + sense_page->ImportExportStartLo;
|
||||
+ ((int)sense_page->ImportExportStartHi << 8) + sense_page->ImportExportStartLo;
|
||||
|
||||
retval->NumImportExport =
|
||||
((int)sense_page->NumImportExportHi << 8) + sense_page->NumImportExportLo;
|
||||
@@ -494,7 +495,7 @@ ElementModeSense_T *ReadAssignmentPage(DEVICE_TYPE MediumChangerFD)
|
||||
((int)sense_page->NumDataTransferHi << 8) + sense_page->NumDataTransferLo;
|
||||
|
||||
/* allocate a couple spares 'cause some HP autochangers and maybe others
|
||||
- * don't properly report the robotics arm(s) count here...
|
||||
+ * don't properly report the robotics arm(s) count here...
|
||||
*/
|
||||
retval->NumElements =
|
||||
retval->NumStorage+retval->NumImportExport +
|
||||
@@ -549,7 +550,7 @@ static ElementStatus_T *AllocateElementData(ElementModeSense_T *mode_sense)
|
||||
|
||||
retval->DataTransferElementAddress =
|
||||
(int *)xzmalloc(sizeof(int) * (mode_sense->NumDataTransfer + 1));
|
||||
- retval->DataTransferElementSourceStorageElementNumber =
|
||||
+ retval->DataTransferElementSourceStorageElementNumber =
|
||||
(int *)xzmalloc(sizeof(int) * (mode_sense->NumDataTransfer + 1));
|
||||
retval->DataTransferPrimaryVolumeTag =
|
||||
(barcode *)xzmalloc(sizeof(barcode) * (mode_sense->NumDataTransfer + 1));
|
||||
@@ -587,14 +588,14 @@ void copy_barcode(unsigned char *src, unsigned char *dest)
|
||||
|
||||
dest++;
|
||||
}
|
||||
- *dest = 0; /* null-terminate */
|
||||
+ *dest = 0; /* null-terminate */
|
||||
}
|
||||
|
||||
/* This #%!@# routine has more parameters than I can count! */
|
||||
static unsigned char *SendElementStatusRequestActual(
|
||||
DEVICE_TYPE MediumChangerFD,
|
||||
RequestSense_T *RequestSense,
|
||||
- Inquiry_T *inquiry_info,
|
||||
+ Inquiry_T *inquiry_info,
|
||||
SCSI_Flags_T *flags,
|
||||
int ElementStart,
|
||||
int NumElements,
|
||||
@@ -609,7 +610,7 @@ static unsigned char *SendElementStatusRequestActual(
|
||||
#ifdef HAVE_GET_ID_LUN
|
||||
scsi_id_t *scsi_id;
|
||||
#endif
|
||||
- if (inquiry_info->MChngr &&
|
||||
+ if (inquiry_info->MChngr &&
|
||||
inquiry_info->PeripheralDeviceType != MEDIUM_CHANGER_TYPE)
|
||||
{
|
||||
is_attached = true;
|
||||
@@ -617,7 +618,7 @@ static unsigned char *SendElementStatusRequestActual(
|
||||
|
||||
if (flags->no_attached)
|
||||
{
|
||||
- /* override, sigh */
|
||||
+ /* override, sigh */
|
||||
is_attached = false;
|
||||
}
|
||||
|
||||
@@ -633,11 +634,11 @@ static unsigned char *SendElementStatusRequestActual(
|
||||
|
||||
if (is_attached)
|
||||
{
|
||||
- CDB[0] = 0xB4; /* whoops, READ_ELEMENT_STATUS_ATTACHED! */
|
||||
+ CDB[0] = 0xB4; /* whoops, READ_ELEMENT_STATUS_ATTACHED! */
|
||||
}
|
||||
|
||||
#ifdef HAVE_GET_ID_LUN
|
||||
- CDB[1] = (scsi_id->lun << 5) | ((flags->no_barcodes) ?
|
||||
+ CDB[1] = (scsi_id->lun << 5) | ((flags->no_barcodes) ?
|
||||
0 : 0x10) | flags->elementtype; /* Lun + VolTag + Type code */
|
||||
free(scsi_id);
|
||||
#else
|
||||
@@ -677,7 +678,7 @@ static unsigned char *SendElementStatusRequestActual(
|
||||
|
||||
/*
|
||||
First see if we have sense key of 'illegal request',
|
||||
- additional sense code of '24', additional sense qualfier of
|
||||
+ additional sense code of '24', additional sense qualfier of
|
||||
'0', and field in error of '4'. This means that we issued a request
|
||||
w/bar code reader and did not have one, thus must re-issue the request
|
||||
w/out barcode :-(.
|
||||
@@ -722,14 +723,14 @@ static unsigned char *SendElementStatusRequestActual(
|
||||
PrintRequestSense(RequestSense); /* see what it sez :-(. */
|
||||
fprintf(stderr,"Data:\n");
|
||||
PrintHex(2, DataBuffer, 40);
|
||||
-#endif
|
||||
+#endif
|
||||
return DataBuffer; /* we succeeded! */
|
||||
}
|
||||
|
||||
|
||||
unsigned char *SendElementStatusRequest(DEVICE_TYPE MediumChangerFD,
|
||||
RequestSense_T *RequestSense,
|
||||
- Inquiry_T *inquiry_info,
|
||||
+ Inquiry_T *inquiry_info,
|
||||
SCSI_Flags_T *flags,
|
||||
int ElementStart,
|
||||
int NumElements,
|
||||
@@ -750,7 +751,7 @@ unsigned char *SendElementStatusRequest(DEVICE_TYPE MediumChangerFD,
|
||||
/*
|
||||
One weird loader wants either 8 or BYTE_COUNT_OF_REPORT
|
||||
values for the ALLOCATION_LENGTH. Give it what it wants
|
||||
- if we get an Sense Key of 05 Illegal Request with a
|
||||
+ if we get an Sense Key of 05 Illegal Request with a
|
||||
CDB position of 7 as the field in error.
|
||||
*/
|
||||
|
||||
@@ -882,7 +883,7 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
{
|
||||
/* TransportElementDescriptor =
|
||||
(TransportElementDescriptor_T *) DataPointer; */
|
||||
- memcpy(&TEBuf, DataPointer,
|
||||
+ memcpy(&TEBuf, DataPointer,
|
||||
(TransportElementDescriptorLength <= sizeof(TEBuf)) ?
|
||||
TransportElementDescriptorLength :
|
||||
sizeof(TEBuf));
|
||||
@@ -909,7 +910,7 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
case MediumTransportElement:
|
||||
ElementStatus->TransportElementAddress = BigEndian16(TransportElementDescriptor->ElementAddress);
|
||||
#ifdef DEBUG
|
||||
- fprintf(stderr,"TransportElementAddress=%d\n",ElementStatus->TransportElementAddress);
|
||||
+ fprintf(stderr,"TransportElementAddress=%d\n",ElementStatus->TransportElementAddress);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -936,7 +937,7 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
ElementStatus->StorageElementFull[ImportExportIndex] =
|
||||
TransportElementDescriptor->Full;
|
||||
|
||||
- if ( (TransportElementDescriptorLength > 11) &&
|
||||
+ if ( (TransportElementDescriptorLength > 11) &&
|
||||
(ElementStatusPage->VolBits & E2_AVOLTAG))
|
||||
{
|
||||
copy_barcode(TransportElementDescriptor->AlternateVolumeTag,
|
||||
@@ -945,8 +946,8 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
else
|
||||
{
|
||||
ElementStatus->AlternateVolumeTag[ImportExportIndex][0] = 0; /* null string. */;
|
||||
- }
|
||||
- if ((TransportElementDescriptorLength > 11) &&
|
||||
+ }
|
||||
+ if ((TransportElementDescriptorLength > 11) &&
|
||||
(ElementStatusPage->VolBits & E2_PVOLTAG))
|
||||
{
|
||||
copy_barcode(TransportElementDescriptor->PrimaryVolumeTag,
|
||||
@@ -967,8 +968,8 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
fprintf(stderr,"StorageElementCount=%d ElementAddress = %d ",ElementStatus->StorageElementCount,BigEndian16(TransportElementDescriptor->ElementAddress));
|
||||
#endif
|
||||
/* ATL/Exabyte kludge -- skip slots that aren't installed :-( */
|
||||
- if (TransportElementDescriptor->AdditionalSenseCode==0x83 &&
|
||||
- TransportElementDescriptor->AdditionalSenseCodeQualifier==0x02)
|
||||
+ if (TransportElementDescriptor->AdditionalSenseCode==0x83 &&
|
||||
+ TransportElementDescriptor->AdditionalSenseCodeQualifier==0x02)
|
||||
continue;
|
||||
|
||||
ElementStatus->StorageElementAddress[ElementStatus->StorageElementCount] =
|
||||
@@ -986,7 +987,7 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
ElementStatus->StorageElementCount; /* slot idx. */
|
||||
/* ElementStatus->StorageElementAddress[ElementStatus->StorageElementCount]; */
|
||||
}
|
||||
- if ((TransportElementDescriptorLength > 11) &&
|
||||
+ if ((TransportElementDescriptorLength > 11) &&
|
||||
(ElementStatusPage->VolBits & E2_AVOLTAG))
|
||||
{
|
||||
copy_barcode(TransportElementDescriptor->AlternateVolumeTag,
|
||||
@@ -995,8 +996,8 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
else
|
||||
{
|
||||
ElementStatus->AlternateVolumeTag[ElementStatus->StorageElementCount][0]=0; /* null string. */;
|
||||
- }
|
||||
- if ((TransportElementDescriptorLength > 11) &&
|
||||
+ }
|
||||
+ if ((TransportElementDescriptorLength > 11) &&
|
||||
(ElementStatusPage->VolBits & E2_PVOLTAG))
|
||||
{
|
||||
copy_barcode(TransportElementDescriptor->PrimaryVolumeTag,
|
||||
@@ -1009,9 +1010,9 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
|
||||
ElementStatus->StorageElementCount++;
|
||||
/*
|
||||
- Note that the original mtx had no check here for
|
||||
+ Note that the original mtx had no check here for
|
||||
buffer overflow, though some drives might mistakingly
|
||||
- do one...
|
||||
+ do one...
|
||||
*/
|
||||
|
||||
if (ElementStatus->StorageElementCount > mode_sense->NumStorage)
|
||||
@@ -1033,33 +1034,33 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
report that they have a 2nd tape drive when they don't. We
|
||||
could generalize this in an ideal world, but my attempt to
|
||||
do so failed with dual-drive Exabyte tape libraries that
|
||||
- *DID* have the second drive. Sigh.
|
||||
+ *DID* have the second drive. Sigh.
|
||||
*/
|
||||
- if (TransportElementDescriptor->AdditionalSenseCode==0x83 &&
|
||||
+ if (TransportElementDescriptor->AdditionalSenseCode==0x83 &&
|
||||
TransportElementDescriptor->AdditionalSenseCodeQualifier==0x04)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* generalize it. Does it work? Let's try it! */
|
||||
- /*
|
||||
+ /*
|
||||
No, dammit, following does not work on dual-drive Exabyte
|
||||
'cause if a tape is in the drive, it sets the AdditionalSense
|
||||
code to something (sigh).
|
||||
*/
|
||||
/* if (TransportElementDescriptor->AdditionalSenseCode!=0)
|
||||
continue;
|
||||
- */
|
||||
+ */
|
||||
|
||||
ElementStatus->DataTransferElementAddress[ElementStatus->DataTransferElementCount] =
|
||||
BigEndian16(TransportElementDescriptor->ElementAddress);
|
||||
- ElementStatus->DataTransferElementFull[ElementStatus->DataTransferElementCount] =
|
||||
+ ElementStatus->DataTransferElementFull[ElementStatus->DataTransferElementCount] =
|
||||
TransportElementDescriptor->Full;
|
||||
ElementStatus->DataTransferElementSourceStorageElementNumber[ElementStatus->DataTransferElementCount] =
|
||||
BigEndian16(TransportElementDescriptor->SourceStorageElementAddress);
|
||||
|
||||
#ifdef DEBUG
|
||||
- fprintf(stderr, "%d: ElementAddress = %d, Full = %d, SourceElement = %d\n",
|
||||
+ fprintf(stderr, "%d: ElementAddress = %d, Full = %d, SourceElement = %d\n",
|
||||
ElementStatus->DataTransferElementCount,
|
||||
ElementStatus->DataTransferElementAddress[ElementStatus->DataTransferElementCount],
|
||||
ElementStatus->DataTransferElementFull[ElementStatus->DataTransferElementCount],
|
||||
@@ -1118,17 +1119,17 @@ static void ParseElementStatus( int *EmptyStorageElementAddress,
|
||||
/*
|
||||
* We no longer do the funky trick to figure out ALLOCATION_LENGTH.
|
||||
* Instead, we use the SCSI Generic command rather than SEND_SCSI_COMMAND
|
||||
- * under Linux, which gets around the @#%@ 4k buffer size in Linux.
|
||||
+ * under Linux, which gets around the @#%@ 4k buffer size in Linux.
|
||||
* We still have the restriction that Linux cuts off the last two
|
||||
* bytes of the SENSE DATA (Q#@$%@#$^ Linux!). Which means that the
|
||||
- * verbose widget won't work :-(.
|
||||
-
|
||||
+ * verbose widget won't work :-(.
|
||||
+
|
||||
* We now look for that "attached" bit in the inquiry_info to see whether
|
||||
* to use READ_ELEMENT_ATTACHED or plain old READ_ELEMENT. In addition, we
|
||||
* look at the device type in the inquiry_info to see whether it is a media
|
||||
* changer or tape device, and if it's a media changer device, we ignore the
|
||||
* attached bit (one beta tester found an old 4-tape DAT changer that set
|
||||
- * the attached bit for both the tape device AND the media changer device).
|
||||
+ * the attached bit for both the tape device AND the media changer device).
|
||||
|
||||
*/
|
||||
|
||||
@@ -1155,7 +1156,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
|
||||
if (flags->no_attached)
|
||||
{
|
||||
- /* override, sigh */
|
||||
+ /* override, sigh */
|
||||
is_attached = false;
|
||||
}
|
||||
|
||||
@@ -1185,7 +1186,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
ElementStatus->DataTransferElementCount = 0;
|
||||
|
||||
/* first, allocate some empty storage stuff: Note that we pass this
|
||||
- * down to ParseElementStatus (sigh!)
|
||||
+ * down to ParseElementStatus (sigh!)
|
||||
*/
|
||||
|
||||
EmptyStorageElementAddress = (int *)xzmalloc((mode_sense->NumStorage+1)*sizeof(int));
|
||||
@@ -1202,7 +1203,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
for (i = 0; i < mode_sense->NumDataTransfer; i++)
|
||||
{
|
||||
/* initialize them to an illegal # so that we can fix later... */
|
||||
- ElementStatus->DataTransferElementSourceStorageElementNumber[i] = -1;
|
||||
+ ElementStatus->DataTransferElementSourceStorageElementNumber[i] = -1;
|
||||
}
|
||||
|
||||
if (flags->querytype == MTX_ELEMENTSTATUS_ORIGINAL)
|
||||
@@ -1308,7 +1309,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
PrintRequestSense(RequestSense);
|
||||
#endif
|
||||
FreeElementData(ElementStatus);
|
||||
- return NULL;
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -1323,7 +1324,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
|
||||
/* grr, damned brain dead HP doesn't report that it has any! */
|
||||
if (!mode_sense->NumMediumTransport)
|
||||
- {
|
||||
+ {
|
||||
ElementStatus->TransportElementAddress = 0; /* default it sensibly :-(. */
|
||||
}
|
||||
else
|
||||
@@ -1347,8 +1348,8 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
PrintRequestSense(RequestSense);
|
||||
#endif
|
||||
FreeElementData(ElementStatus);
|
||||
- return NULL;
|
||||
- }
|
||||
+ return NULL;
|
||||
+ }
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"Parsing robot arm data\n");
|
||||
#endif
|
||||
@@ -1366,8 +1367,8 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
fprintf(stderr,"Using alternative element status polling method (all elements)\n");
|
||||
#endif
|
||||
/* ----------------- ALL Elements ---------------------- */
|
||||
- /* Just keep asking for elements till no more are returned
|
||||
- - increment our starting address as we go acording to the
|
||||
+ /* Just keep asking for elements till no more are returned
|
||||
+ - increment our starting address as we go acording to the
|
||||
number of elements returned from the last call
|
||||
*/
|
||||
|
||||
@@ -1384,7 +1385,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
mode_sense->MaxReadElementStatusData);
|
||||
if (!DataBuffer)
|
||||
{
|
||||
- if (RequestSense->AdditionalSenseCode == 0x21 &&
|
||||
+ if (RequestSense->AdditionalSenseCode == 0x21 &&
|
||||
RequestSense->AdditionalSenseCodeQualifier == 0x01)
|
||||
{
|
||||
/* Error is invalid element address, we've probably just hit the end */
|
||||
@@ -1393,8 +1394,8 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
|
||||
/* darn. Free up stuff and return. */
|
||||
FreeElementData(ElementStatus);
|
||||
- return NULL;
|
||||
- }
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
nLastEl = nNextEl;
|
||||
|
||||
@@ -1423,7 +1424,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
*
|
||||
* Pass1:
|
||||
* Translate from raw element # to our translated # (if possible).
|
||||
- * First, check the SourceStorageElementNumbers against the list of
|
||||
+ * First, check the SourceStorageElementNumbers against the list of
|
||||
* filled slots. If the slots indicated are empty, we accept that list as
|
||||
* valid. Otherwise decide the SourceStorageElementNumbers are invalid.
|
||||
*
|
||||
@@ -1432,7 +1433,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
* then we must search for free slots, and assign SourceStorageElementNumbers
|
||||
* to those free slots. We happen to already built a list of free
|
||||
* slots as part of the process of reading the storage element numbers
|
||||
- * from the tape. So that's easy enough to do!
|
||||
+ * from the tape. So that's easy enough to do!
|
||||
*/
|
||||
|
||||
#ifdef DEBUG_TAPELIST
|
||||
@@ -1448,7 +1449,7 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
|
||||
/*
|
||||
* Now we re-assign origin slots if the "real" origin slot
|
||||
- * is obviously defective:
|
||||
+ * is obviously defective:
|
||||
*/
|
||||
/* pass one: */
|
||||
for (i = 0; i < ElementStatus->DataTransferElementCount; i++)
|
||||
@@ -1486,12 +1487,12 @@ ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *
|
||||
* drives will be assigned a -1 (see the initialization loop for
|
||||
* EmptyStorageElementAddress above), which will be reported as "slot 0"
|
||||
* by the user interface. This is an invalid value, but more useful for us
|
||||
- * to have than just crapping out here :-(.
|
||||
+ * to have than just crapping out here :-(.
|
||||
*/
|
||||
empty_idx=0;
|
||||
for (i = 0; i < ElementStatus->DataTransferElementCount; i++)
|
||||
{
|
||||
- if (ElementStatus->DataTransferElementFull[i] &&
|
||||
+ if (ElementStatus->DataTransferElementFull[i] &&
|
||||
ElementStatus->DataTransferElementSourceStorageElementNumber[i] < 0)
|
||||
{
|
||||
#ifdef DEBUG_TAPELIST
|
||||
@@ -1543,7 +1544,7 @@ RequestSense_T *PositionElement(DEVICE_TYPE MediumChangerFD,
|
||||
|
||||
/* Now the actual media movement routine! */
|
||||
RequestSense_T *MoveMedium( DEVICE_TYPE MediumChangerFD, int SourceAddress,
|
||||
- int DestinationAddress,
|
||||
+ int DestinationAddress,
|
||||
ElementStatus_T *ElementStatus,
|
||||
Inquiry_T *inquiry_info, SCSI_Flags_T *flags)
|
||||
{
|
||||
@@ -1646,7 +1647,7 @@ RequestSense_T *ExchangeMedium( DEVICE_TYPE MediumChangerFD, int SourceAddress,
|
||||
|
||||
#ifdef DEBUG_EXCHANGE
|
||||
dump_cdb(&CDB,12);
|
||||
-#endif
|
||||
+#endif
|
||||
|
||||
if (SCSI_ExecuteCommand(MediumChangerFD, Output, &CDB, 12,
|
||||
NULL, 0, RequestSense) != 0)
|
||||
@@ -1690,8 +1691,8 @@ RequestSense_T *Erase(DEVICE_TYPE MediumChangerFD)
|
||||
return NULL; /* Success! */
|
||||
}
|
||||
|
||||
-/* Routine to send an LOAD/UNLOAD from the MMC/SSC spec to a device.
|
||||
- * For tapes and changers this can be used either to eject a tape
|
||||
+/* Routine to send an LOAD/UNLOAD from the MMC/SSC spec to a device.
|
||||
+ * For tapes and changers this can be used either to eject a tape
|
||||
* or to eject a magazine (on some Seagate changers, when sent to LUN 1 ).
|
||||
* For CD/DVDs this is used to Load or Unload a disc which is required by
|
||||
* some media changers.
|
||||
@@ -1721,8 +1722,8 @@ int LoadUnload(DEVICE_TYPE fd, int bLoad)
|
||||
return 0; /* did do! */
|
||||
}
|
||||
|
||||
-/* Routine to send an START/STOP from the MMC/SSC spec to a device.
|
||||
- * For tape drives this may be required prior to using the changer
|
||||
+/* Routine to send an START/STOP from the MMC/SSC spec to a device.
|
||||
+ * For tape drives this may be required prior to using the changer
|
||||
* Load or Unload commands.
|
||||
* For CD/DVD drives this is used to Load or Unload a disc which may be
|
||||
* required by some media changers.
|
||||
@@ -1746,9 +1747,9 @@ int StartStop(DEVICE_TYPE fd, int bStart)
|
||||
return 0; /* did do! */
|
||||
}
|
||||
|
||||
-/* Routine to send a LOCK/UNLOCK from the SSC/MMC spec to a device.
|
||||
+/* Routine to send a LOCK/UNLOCK from the SSC/MMC spec to a device.
|
||||
* This can be used to prevent or allow the Tape or CD/DVD from being
|
||||
- * removed.
|
||||
+ * removed.
|
||||
*/
|
||||
|
||||
int LockUnlock(DEVICE_TYPE fd, int bLock)
|
||||
@@ -1876,7 +1877,7 @@ void PrintRequestSense(RequestSense_T *RequestSense)
|
||||
fprintf(stderr, "mtx: Request Sense: Valid Residual=%s\n", RequestSense->Valid ? Yes : No);
|
||||
|
||||
if (RequestSense->ErrorCode == 0x70)
|
||||
- {
|
||||
+ {
|
||||
msg = "Current" ;
|
||||
}
|
||||
else if (RequestSense->ErrorCode == 0x71)
|
||||
@@ -0,0 +1,13 @@
|
||||
diff --git a/scsitape.c b/scsitape.c
|
||||
index dd52dd5..63f4977 100644
|
||||
--- a/scsitape.c
|
||||
+++ b/scsitape.c
|
||||
@@ -63,7 +63,7 @@
|
||||
#endif
|
||||
|
||||
void Usage(void) {
|
||||
- FatalError("Usage: scsitape -f <generic-device> <command> where <command> is:\n setblk <n> | fsf <n> | bsf <n> | eod | rewind | eject | mark <n> |\n seek <n> | read [<blksize> [<numblocks]] | write [<blocksize>] \n");
|
||||
+ FatalError("Usage: scsitape -f <generic-device> <command> where <command> is:\n setblk <n> | fsf <n> | bsf <n> | eod | rewind | eject | erase |\n mark <n> | seek <n> | read [<blksize> [<numblocks]] |\n write [<blocksize>]\n");
|
||||
}
|
||||
|
||||
#define arg1 (arg[0]) /* for backward compatibility, sigh */
|
||||
@@ -63,7 +63,7 @@
|
||||
#endif
|
||||
|
||||
void Usage(void) {
|
||||
FatalError("Usage: scsitape -f <generic-device> <command> where <command> is:\n setblk <n> | fsf <n> | bsf <n> | eod | rewind | eject | mark <n> |\n seek <n> | read [<blksize> [<numblocks]] | write [<blocksize>] \n");
|
||||
FatalError("Usage: scsitape -f <generic-device> <command> where <command> is:\n setblk <n> | fsf <n> | bsf <n> | eod | rewind | eject | erase |\n mark <n> | seek <n> | read [<blksize> [<numblocks]] |\n write [<blocksize>]\n");
|
||||
}
|
||||
|
||||
#define arg1 (arg[0]) /* for backward compatibility, sigh */
|
||||
|
||||
@@ -933,7 +933,6 @@ int main(int argc, char **argv)
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
fprintf(stderr,"argc=%d",argc);
|
||||
usage();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user