Christoffer Hall-Frederiksen writes:
- I have a Exabyte EXB-480 gismo with 4 Exabyte Mammoth EXB-8900
- tapedrives in it. Now if I use Eric Lee Green's mtx (1.2.12) the
- whole thing works just great. I can load and unload tapes and get
- a nice status of the robot just fine. But in my test-setup of amanda
- (version 2.4.2) I get a rather strange error when I use chg-scsi.
- Amcheck tells me this:
Amanda 2.4.x doesn't have the complete support for the
Exabyte EXB-4x0 robots.. I posted a group of patches to amanda-hackers
a number of weeks/months ago (didn't I?) to allow it to work.
I'll attach those patches here as well. I've been using
Amanda with an EXB-480 since last September, quite successfully
(abit on a NetBSD/Alpha host) Also enclosed is a patch to keep
the server from leaking filedescriptors on large robots (like
the EXB-480.)
--
Eric Schnoebelen [EMAIL PROTECTED] http://www.cirr.com
There are two ways of constructing a software design: one way is to make
it so simple that there are obviously no deficiencies, and the other is
to make it so complicated there are no obvious deficiencies - CAR Hoare
$NetBSD$
# Commentary:
# The vast majority of the changes in this patch are to add support/fix
# for the Exabyte EXB8505 8MM tape drive, when attached to NetBSD, and
# within an EXB-4[48]0 robot.
# A smaller number of the changes are add support for the EXB-4[48]0
# SCSI robots.
# The remainder of the changes aer to improve the debugg-ability of
# the program, and the quality of the debug log
# A number of segmentation violations were also removed.
# SCSI_LoadUnload was recoded to use a private structure, to make
# sure the correct bitfields were set.
# Finally, a new function was added to set/clear (currently only used
# to clear) the Prevent/Allow Medium Removal flag.
#
--- changer-src/scsi-changer-driver.c.orig Tue Oct 24 19:21:15 2000
+++ changer-src/scsi-changer-driver.c Sat Feb 17 21:23:08 2001
@@ -92,6 +92,7 @@
int GenericFree();
int TapeStatus(); /* Is the tape loaded ? */
int DLT4000Eject(char *Device, int type);
+int EXB8505Eject(char *Device, int type);
int GenericEject(char *Device, int type);
int GenericClean(char *Device); /* Does the tape need a clean */
int GenericBarCode(int DeviceFD); /* Do we have Barcode reader support
*/
@@ -225,6 +226,30 @@
EXB120BarCode,
GenericSearch,
EXB120SenseHandler}},
+ {"EXB-440",
+ "Exabyte Robot [EXB-440]",
+ {GenericMove,
+ GenericElementStatus,
+ GenericResetStatus,
+ GenericFree,
+ GenericEject,
+ GenericClean,
+ GenericRewind,
+ EXB120BarCode,
+ GenericSearch,
+ EXB10eSenseHandler}},
+ {"EXB-480",
+ "Exabyte Robot [EXB-480]",
+ {GenericMove,
+ GenericElementStatus,
+ GenericResetStatus,
+ GenericFree,
+ GenericEject,
+ GenericClean,
+ GenericRewind,
+ EXB120BarCode,
+ GenericSearch,
+ EXB10eSenseHandler}},
{"EXB-85058HE-0000",
"Exabyte Tape [EXB-85058HE-0000]",
{DoNothing,
@@ -237,6 +262,19 @@
GenericBarCode,
GenericSearch,
EXB85058SenseHandler}},
+ {"EXB-85058SQANXR1",
+ "Exabyte Tape [EXB-85058SQANXR1]",
+ {DoNothing,
+ DoNothing,
+ DoNothing,
+ DoNothing,
+ /* DLT4000Eject, */
+ EXB8505Eject,
+ GenericClean,
+ GenericRewind,
+ GenericBarCode,
+ GenericSearch,
+ EXB85058SenseHandler}},
/* Tandberg Devices */
{"TDS 1420",
"Tandberg Robot (TDS 1420)",
@@ -364,9 +402,15 @@
{0x39,
"EXB-85058HE-0000",
EXB85058HEPage39},
+ {0x39,
+ "EXB-85058SQANXR1",
+ EXB85058HEPage39},
{0x3c,
"EXB-85058HE-0000",
EXB85058HEPage3c},
+ {0x3c,
+ "EXB-85058SQANXR1",
+ EXB85058HEPage3c},
{0, NULL, NULL}
};
@@ -512,13 +556,13 @@
int drive_loaded(int fd, int drivenum)
{
-
dbprintf(("###### START drive_loaded\n"));
dbprintf(("%-20s : fd %d drivenum %d \n", "drive_loaded", fd, drivenum));
if (pChangerDev == NULL)
{
dbprintf(("%-20s : pChangerCtl == NULL\n", "drive_loaded"));
+ dbprintf(("###### STOP drive_loaded: -1\n"));
return(-1);
}
@@ -526,12 +570,18 @@
{
if (pChangerDev->functions->function[CHG_STATUS](fd, 1) != 0)
{
+ dbprintf(("###### STOP drive_loaded: -1\n"));
return(-1);
}
}
if (pDTE[drivenum].status == 'E')
+ {
+ dbprintf(("###### STOP drive_loaded: 0\n"));
return(0);
+ }
+
+ dbprintf(("###### STOP drive_loaded: 1\n"));
return(1);
}
@@ -822,8 +872,10 @@
}
- GenericRewind(pwork->fd);
-
+ /*
+ * call the drive specific rewind function
+ */
+ pwork->functions->function[CHG_REWIND](pwork->fd);
while (true && cnt < wait)
{
@@ -1340,7 +1392,7 @@
dbprintf(("Ident = [%s], function = [%s]\n", pChangerDev->ident,
pChangerDev->functions->ident));
ret = pChangerDev->functions->function[CHG_ERROR](DeviceFD, flag, buffer);
- dbprintf(("#### STOP SenseHandler\n"));
+ dbprintf(("#### STOP SenseHandler (pChangerDev): %d\n", ret));
return(ret);
}
@@ -1349,20 +1401,20 @@
dbprintf(("Ident = [%s], function = [%s]\n", pTapeDev->ident,
pTapeDev->functions->ident));
ret = pTapeDev->functions->function[CHG_ERROR](DeviceFD, flag, buffer);
- dbprintf(("#### STOP SenseHandler\n"));
+ dbprintf(("#### STOP SenseHandler (pTapeDev): %d\n", ret));
return(ret);
}
if (pTapeDevCtl != NULL && pTapeDevCtl->fd == DeviceFD)
{
- dbprintf(("Ident = [%s], function = [%s]\n", pTapeDev->ident,
+ dbprintf(("Ident = [%s], function = [%s]\n", pTapeDevCtl->ident,
pTapeDevCtl->functions->ident));
ret = pTapeDevCtl->functions->function[CHG_ERROR](DeviceFD, flag, buffer);
- dbprintf(("#### STOP SenseHandler\n"));
+ dbprintf(("#### STOP SenseHandler (pTapeDevCtl): %d\n", ret));
return(ret);
}
- dbprintf(("#### STOP SenseHandler\n"));
+ dbprintf(("#### STOP SenseHandler: (SENSE_ABORT)\n"));
return(SENSE_ABORT);
}
@@ -1392,6 +1444,122 @@
return(0);
}
+int EXB8505Eject(char *Device, int type)
+{
+ RequestSense_T *pRequestSense;
+ ExtendedRequestSense_T *pExtendedRequestSense;
+ int ret;
+ int cnt = 0;
+ int true = 1;
+
+ dbprintf(("##### START EXB8505Eject (type=%d)\n", type));
+
+ if ((pRequestSense = malloc(sizeof(RequestSense_T))) == NULL)
+ {
+ dbprintf(("%-20s : malloc failed\n","EXB8505Eject"));
+ return(-1);
+ }
+
+ if ((pExtendedRequestSense = malloc(sizeof(ExtendedRequestSense_T))) == NULL)
+ {
+ dbprintf(("%-20s : malloc failed\n","EXB8505Eject"));
+ return(-1);
+ }
+
+ if (pTapeDevCtl != NULL && pTapeDevCtl->SCSI == 1)
+ LogSense(pTapeDevCtl->fd);
+
+ if ( type > 1)
+ {
+ dbprintf(("EXB8505Eject : use mtio ioctl for eject on %s (%s)\n",
+ ((pTapeDev != NULL) ? pTapeDev->dev : pTapeDevCtl->dev),
+ ((pTapeDev != NULL) ? pTapeDev->ident : pTapeDevCtl->ident)));
+ return(Tape_Eject(((pTapeDev != NULL) ? pTapeDev->fd : pTapeDevCtl->fd)));
+ }
+
+ if (pTapeDev != NULL &&
+ pTapeDevCtl != NULL &&
+ pTapeDev->fd != pTapeDevCtl->fd &&
+ pTapeDevCtl->SCSI == 1) {
+ dbprintf(("EXB8505Eject : Close %s \n", pTapeDev->dev));
+ close(pTapeDev->fd);
+ }
+
+
+ if (pTapeDevCtl->SCSI == 0)
+ {
+ dbprintf(("EXB8505Eject : Device %s not able to receive SCSI commands\n",
+pTapeDev->dev));
+ return(Tape_Eject((pTapeDev != NULL) ? pTapeDev->fd : pTapeDevCtl->fd));
+ }
+
+
+ dbprintf(("EXB8505Eject : SCSI eject on %s = %s\n",
+ pTapeDevCtl->dev, pTapeDevCtl->ident));
+
+ RequestSense(pTapeDevCtl->fd, pExtendedRequestSense, 0);
+ DecodeExtSense(pExtendedRequestSense, "EXB8505Eject : ", debug_file);
+ /*
+ * Tell the tape drive it _can_ actually eject the tape
+ */
+ ret = SCSI_MediumRemoval(pTapeDevCtl->fd, pRequestSense, 0);
+
+ RequestSense(pTapeDevCtl->fd, pExtendedRequestSense, 0);
+ DecodeExtSense(pExtendedRequestSense, "EXB8505Eject : ", debug_file);
+
+ /*
+ * Unload the tape, 0 == wait for success; 0 == unload
+ */
+ ret = SCSI_LoadUnload(pTapeDevCtl->fd, pRequestSense, 0, 0);
+
+ RequestSense(pTapeDevCtl->fd, pExtendedRequestSense, 0);
+ DecodeExtSense(pExtendedRequestSense, "EXB8505Eject : ", debug_file);
+
+ /* < 0 == fatal */
+ if (ret < 0)
+ return(-1);
+
+ if ( ret > 0)
+ {
+ }
+
+ true = 1;
+
+
+ /*
+ * the EXB8505 is never going to test UNIT_READY when there is no
+ * tape present. We need to loop, testing until we get
+ * pExtendedRequestSense.TNP == 1, at which point (we hope) the tape has
+ * been dismounted
+ */
+ while (true && cnt < 300)
+ {
+ /*
+ if (SCSI_TestUnitReady(pTapeDevCtl->fd, pRequestSense))
+ {
+ true = 0;
+ break;
+ }
+ */
+ RequestSense(pTapeDevCtl->fd, pExtendedRequestSense, 0);
+ DecodeExtSense(pExtendedRequestSense, "EXB8505Eject : ", debug_file);
+
+ if (pExtendedRequestSense->TNP == 1)
+ {
+ true=0;
+ break;
+ } else {
+ cnt++;
+ sleep(2);
+ }
+ }
+
+ free(pRequestSense);
+
+ dbprintf(("EXB8505Eject : Ready after %d sec, true = %d\n", cnt * 2, true));
+ return(0);
+
+}
+
int DLT4000Eject(char *Device, int type)
{
RequestSense_T *pRequestSense;
@@ -1404,30 +1572,32 @@
if ((pRequestSense = malloc(sizeof(RequestSense_T))) == NULL)
{
- dbprintf(("%-20s : malloc failed\n","GenericEject"));
+ dbprintf(("%-20s : malloc failed\n","DLT4000Eject"));
return(-1);
}
if ((pExtendedRequestSense = malloc(sizeof(ExtendedRequestSense_T))) == NULL)
{
- dbprintf(("%-20s : malloc failed\n","GenericEject"));
+ dbprintf(("%-20s : malloc failed\n","DLT4000Eject"));
return(-1);
}
- if (pTapeDevCtl != NULL && pTapeDevCtl->SCSI == 1 && pTapeDev != NULL)
- LogSense(pTapeDev->fd);
+ if (pTapeDevCtl != NULL && pTapeDevCtl->SCSI == 1)
+ LogSense(pTapeDevCtl->fd);
if ( type > 1)
{
- dbprintf(("GenericEject : use mtio ioctl for eject on %s\n", pTapeDev->dev));
- return(Tape_Eject(pTapeDev->fd));
+ dbprintf(("DLT4000Eject : use mtio ioctl for eject on %s (%s)\n",
+ ((pTapeDev != NULL) ? pTapeDev->dev : pTapeDevCtl->dev),
+ ((pTapeDev != NULL) ? pTapeDev->ident : pTapeDevCtl->ident)));
+ return(Tape_Eject(((pTapeDev != NULL) ? pTapeDev->fd : pTapeDevCtl->fd)));
}
if (pTapeDev != NULL &&
pTapeDevCtl != NULL &&
pTapeDev->fd != pTapeDevCtl->fd &&
pTapeDevCtl->SCSI == 1) {
- dbprintf(("GenericEject : Close %s \n", pTapeDev->dev));
+ dbprintf(("DLT4000Eject : Close %s \n", pTapeDev->dev));
close(pTapeDev->fd);
}
@@ -1493,7 +1663,7 @@
int cnt = 0;
int true = 1;
- dbprintf(("##### START GenericEject\n"));
+ dbprintf(("##### START GenericEject(%s,%d)\n", Device, type));
if ((pRequestSense = malloc(sizeof(RequestSense_T))) == NULL)
{
@@ -1501,13 +1671,15 @@
return(-1);
}
- if (pTapeDevCtl != NULL && pTapeDevCtl->SCSI == 1 && pTapeDev != NULL)
- LogSense(pTapeDev->fd);
+ if (pTapeDevCtl != NULL && pTapeDevCtl->SCSI == 1)
+ LogSense(pTapeDevCtl->fd);
if ( type > 1)
{
- dbprintf(("GenericEject : use mtio ioctl for eject on %s\n", pTapeDev->dev));
- return(Tape_Eject(pTapeDev->fd));
+ dbprintf(("GenericEject : use mtio ioctl for eject on %s (%s)\n",
+ ((pTapeDev != NULL) ? pTapeDev->dev : pTapeDevCtl->dev),
+ ((pTapeDev != NULL) ? pTapeDev->ident : pTapeDevCtl->ident)));
+ return(Tape_Eject(((pTapeDev != NULL) ? pTapeDev->fd : pTapeDevCtl->fd)));
}
if (pTapeDev != NULL &&
@@ -2096,8 +2268,11 @@
break;
}
break;
+ case SENSE_NULL:
+ ret = SENSE_NO;
+ break;
default:
- dbprintf(("EXB85058SenseHandler : Unknow %x ASC = %x ASCQ = %x\n",
+ dbprintf(("EXB85058SenseHandler : Unknown SenseKey = %x ASC = %x ASCQ =
+%x\n",
pRequestSense->SenseKey,
pRequestSense->AdditionalSenseCode,
pRequestSense->AdditionalSenseCodeQualifier));
@@ -4046,18 +4221,14 @@
sizeof(ExtendedRequestSense_T),
(char *) &RequestSense, sizeof(RequestSense_T));
-
- if (ret < 0)
- {
- return(ret);
- }
-
if ( ret > 0)
{
DecodeExtSense(ExtendedRequestSense, "RequestSense : ",debug_file);
- return(RequestSense.SenseKey);
+ ret = RequestSense.SenseKey;
}
- return(0);
+
+ dbprintf(("##### STOP RequestSense; ret=%d\n", ret));
+ return(ret);
}
@@ -4973,6 +5144,72 @@
return(ret);
}
+/*
+ * the following may be an Exabyte specific command
+ * No, At least the DLT2000/DLT2700 system supports it, as does the
+ * ARCHIVE 4586NP Autoloader
+ *
+ * Set/Clear the Prevent Medium Removal bit on the drive.
+ * On an Exabyte drive, Setting the bit will cause the drive to
+ * logically unload the drive without physically unloading it.
+ * Clearing the bit allows logical unload to also physically unload
+ */
+int SCSI_MediumRemoval(int DeviceFD, RequestSense_T *pRequestSense, unsigned prevent)
+{
+ CDB_T CDB;
+ int ret;
+
+ /* Inline a structure to see if it cures the problem.. */
+ struct SCSIMedRemovalCmd {
+ char cmd;
+#ifdef LITTLE_ENDIAN_BITFIELDS
+ PackedBit Rsvd1:5; /* Byte 01 Bits 0-4 */
+ PackedBit LUN:3; /* byte 01 Bits 5-7 */
+#else
+ PackedBit LUN:3; /* byte 01 Bits 5-7 */
+ PackedBit Rsvd1:5; /* Byte 01 Bits 0-4 */
+#endif
+ char Rsvd2[2];
+#ifdef LITTLE_ENDIAN_BITFIELDS
+ PackedBit Prevent:1; /* Byte 04 Bit 0 */
+ PackedBit Rsvd3:6; /* byte 04 Bits 1-7 */
+#else
+ PackedBit Rsvd3:6; /* byte 04 Bits 1-7 */
+ PackedBit Prevent:1; /* Byte 04 Bit 0 */
+#endif
+#ifdef LITTLE_ENDIAN_BITFIELDS
+ PackedBit Zero1:1; /* Byte 05 Bit 0 */
+ PackedBit Zero2:1; /* Byte 05 Bit 1 */
+ PackedBit Rsvd4:4; /* Byte 05 Bits 2-5 */
+ PackedBit VdrUnq:2; /* byte 05 Bits 6-7 */
+#else
+ PackedBit VdrUnq:2; /* byte 05 Bits 6-7 */
+ PackedBit Rsvd4:4; /* Byte 05 Bits 2-5 */
+ PackedBit Zero2:1; /* Byte 05 Bit 1 */
+ PackedBit Zero1:1; /* Byte 05 Bit 0 */
+#endif
+ } SCSIMedRemoval;
+
+
+ dbprintf(("##### START SCSI_MediumRemoval (prevent=%d)\n", prevent));
+
+ memset(&SCSIMedRemoval, 0, sizeof(struct SCSIMedRemovalCmd));
+
+ SCSIMedRemoval.cmd = 0x1E;
+ SCSIMedRemoval.Prevent = prevent;
+
+ memcpy(CDB, &SCSIMedRemoval, sizeof(SCSIMedRemoval));
+
+ ret = SCSI_ExecuteCommand(DeviceFD, Input, CDB,
+ sizeof(SCSIMedRemoval), 0, 0,
+ (char *) pRequestSense,
+ sizeof(RequestSense_T));
+
+ ret = (ret < 0);
+
+ dbprintf(("#### STOP SCSI_MediumRemoval : ret=%d\n", ret));
+ return(ret);
+}
int SCSI_Move(int DeviceFD, unsigned char chm, int from, int to)
{
@@ -5052,23 +5289,60 @@
return(ret);
}
-int SCSI_LoadUnload(int DeviceFD, RequestSense_T *pRequestSense, unsigned char byte1,
unsigned char load)
+int SCSI_LoadUnload(int DeviceFD, RequestSense_T *pRequestSense, unsigned char immed,
+unsigned char load)
{
CDB_T CDB;
int ret;
+ /* Inline a structure to see if it cures the problem.. */
+ struct SCSILoadCmd {
+ char cmd;
+#ifdef LITTLE_ENDIAN_BITFIELDS
+ PackedBit Immed:1; /* Byte 01 Bit 0 */
+ PackedBit Rsvd1:4; /* Byte 01 Bits 1-4 */
+ PackedBit LUN:3; /* byte 01 Bits 5-7 */
+#else
+ PackedBit LUN:3; /* byte 01 Bits 5-7 */
+ PackedBit Rsvd1:4; /* Byte 01 Bits 1-4 */
+ PackedBit Immed:1; /* Byte 01 Bit 0 */
+#endif
+ char Rsvd2[2];
+#ifdef LITTLE_ENDIAN_BITFIELDS
+ PackedBit Load:1; /* Byte 04 Bit 0 */
+ PackedBit Rtn:1; /* Byte 04 Bit 1 */
+ PackedBit EOT:1; /* Byte 04 Bit 2 */
+ PackedBit Rsvd3:3; /* byte 04 Bits 3-7 */
+#else
+ PackedBit Rsvd3:3; /* byte 04 Bits 3-7 */
+ PackedBit EOT:1; /* Byte 04 Bit 2 */
+ PackedBit Rtn:1; /* Byte 04 Bit 1 */
+ PackedBit Load:1; /* Byte 04 Bit 0 */
+#endif
+#ifdef LITTLE_ENDIAN_BITFIELDS
+ PackedBit Zero1:1; /* Byte 05 Bit 0 */
+ PackedBit Zero2:1; /* Byte 05 Bit 1 */
+ PackedBit Rsvd4:4; /* Byte 05 Bits 2-5 */
+ PackedBit VdrUnq:2; /* byte 05 Bits 6-7 */
+#else
+ PackedBit VdrUnq:2; /* byte 05 Bits 6-7 */
+ PackedBit Rsvd4:4; /* Byte 05 Bits 2-5 */
+ PackedBit Zero2:1; /* Byte 05 Bit 1 */
+ PackedBit Zero1:1; /* Byte 05 Bit 0 */
+#endif
+ } SCSILoad;
+
+
+ dbprintf(("##### START SCSI_LoadUnload (immed=%d, load=%d)\n", immed, load));
+
+ memset(&SCSILoad, 0, sizeof(struct SCSILoadCmd));
+
+ SCSILoad.cmd = SC_COM_UNLOAD;
+ SCSILoad.Immed = immed;
+ SCSILoad.Load = load;
- dbprintf(("##### START SCSI_LoadUnload\n"));
-
- CDB[0] = SC_COM_UNLOAD;
- CDB[1] = byte1;
- CDB[2] = 0;
- CDB[3] = 0;
- CDB[4] = load;
- CDB[5] = 0;
-
+ memcpy(CDB, &SCSILoad, sizeof(SCSILoad));
- ret = SCSI_ExecuteCommand(DeviceFD, Input, CDB, 6,
- 0, 0,
+ ret = SCSI_ExecuteCommand(DeviceFD, Input, CDB,
+ sizeof(SCSILoad), 0, 0,
(char *) pRequestSense,
sizeof(RequestSense_T));
@@ -5084,6 +5358,7 @@
int SCSI_TestUnitReady(int DeviceFD, RequestSense_T *pRequestSense)
{
CDB_T CDB;
+ int ret=0;
dbprintf(("##### START SCSI_TestUnitReady\n"));
@@ -5099,12 +5374,10 @@
(char *) pRequestSense,
sizeof(RequestSense_T));
- if (pRequestSense->ErrorCode == 0 && pRequestSense->SenseKey == 0)
- {
- return(1);
- }
+ ret = (pRequestSense->ErrorCode == 0 && pRequestSense->SenseKey == 0);
- return(0);
+ dbprintf(("##### STOP SCSI_TestUnitReady=%d\n", ret));
+ return(ret);
}
$NetBSD$
# Commentary:
# Re-ordered the opening of the `scsitapedev' control device. It is
# opened before the `dev' device. The failure to open `dev' was made
# non-fatal, as chg-scsi doesn't realy use `dev' for anything.
# The reasoning for the reordering is that on NetBSD, /dev/nrstX
# returns ENODEV on a tape device when the device does not have
# the medium ready. /dev/enrstX has no such restrictions, and makes
# an excellent `scsitapedev'
#
--- changer-src/chg-scsi.c.orig Tue Oct 24 18:49:39 2000
+++ changer-src/chg-scsi.c Sat Feb 17 22:32:27 2001
@@ -947,32 +947,32 @@
fd = pChangerDev->fd;
- if (tape_device != NULL)
+ if (scsitapedevice != NULL)
{
- if ((pTapeDev = OpenDevice(tape_device, "tape_device",
chg.conf[confnum].tapeident)) == NULL)
+ if ((pTapeDevCtl = OpenDevice(scsitapedevice, "scsitapedevice",
+chg.conf[confnum].tapeident)) == NULL)
{
- dbprintf(("warning open of %s: failed\n", tape_device));
+ dbprintf(("open: %s: failed: %s\n", scsitapedevice, strerror(errno)));
}
}
- /*
- if (pTapeDev != NULL)
- close(pTapeDev->fd);
- */
- if (scsitapedevice != NULL)
+ if (tape_device != NULL)
{
- if ((pTapeDevCtl = OpenDevice(scsitapedevice, "scsitapedevice",
chg.conf[confnum].tapeident)) == NULL)
+ if ((pTapeDev = OpenDevice(tape_device, "tape_device",
+chg.conf[confnum].tapeident)) == NULL)
{
- printf("open: %s: failed\n", scsitapedevice);
+ dbprintf(("warning: open of %s: failed: %s\n",
+ tape_device, strerror(errno)));
+ if ( scsitapedevice == NULL )
+ {
+ printf("open: %s: failed: %s\n", tape_device, strerror(errno));
return(2);
}
- } else {
- if (pTapeDev != NULL && pTapeDev->SCSI == 1)
- {
- pTapeDevCtl = pTapeDev;
}
}
+ /*
+ if (pTapeDev != NULL)
+ close(pTapeDev->fd);
+ */
if (pTapeDevCtl != NULL)
{
--- server-src/changer.c.orig Sun Feb 18 17:52:21 2001
+++ server-src/changer.c Sun Feb 18 17:54:02 2001
@@ -342,7 +342,7 @@
strerror(errno),
NULL);
exitcode = 2;
- goto done;
+ goto failed;
}
if(fd[0] < 0 || fd[0] >= FD_SETSIZE) {
ap_snprintf(num1, sizeof(num1), "%d", fd[0]);
@@ -479,7 +479,10 @@
}
done:
+ aclose(fd[0]);
+ aclose(fd[1]);
+failed:
dbprintf(("changer: got exit: %d str: %s\n", exitcode, changer_resultstr));
amfree(cmdstr);