1 diff -ru ..\release\mt-st-0.9b/Makefile ./Makefile
2 --- ..\release\mt-st-0.9b/Makefile 2005-08-16 12:16:28.000000000 -0700
3 +++ ./Makefile 2006-08-09 03:26:58.292856500 -0700
9 -MANDIR= /usr/share/man
11 +SBINDIR= $(PREFIX)/sbin
12 +BINDIR= $(PREFIX)/bin
13 +MANDIR= $(PREFIX)/man
19 - $(CC) $(CFLAGS) -o mt mt.c
21 + $(CC) $(CFLAGS) -o mt.exe mt.c mtops.c
25 $(CC) $(CFLAGS) -o stinit stinit.c
28 - install -s mt $(BINDIR)
30 + install mt.exe $(BINDIR)
31 install -c -m 444 mt.1 $(MANDIR)/man1
32 (if [ -f $(MANDIR)/man1/mt.1.gz ] ; then \
33 rm -f $(MANDIR)/man1/mt.1.gz; gzip $(MANDIR)/man1/mt.1; fi)
34 - install -s stinit $(SBINDIR)
35 - install -c -m 444 stinit.8 $(MANDIR)/man8
36 - (if [ -f $(MANDIR)/man8/stinit.8.gz ] ; then \
37 - rm -f $(MANDIR)/man8/stinit.8.gz; gzip $(MANDIR)/man8/stinit.8; fi)
40 (mydir=`basename \`pwd\``;\
41 cd .. && tar cvvf - $$mydir | gzip -9 > $${mydir}.tar.gz)
44 - rm -f *~ \#*\# *.o mt stinit
45 + rm -f *~ \#*\# *.o mt.exe stinit.exe
46 diff -ru ..\release\mt-st-0.9b/mt.1 ./mt.1
47 --- ..\release\mt-st-0.9b/mt.1 2005-08-21 11:53:50.000000000 -0700
48 +++ ./mt.1 2006-08-09 03:26:58.302871100 -0700
51 The tape is positioned on the first block of the next file.
57 -The tape is positioned on the last block of the previous file.
58 +file marks, then backward space one file record.
59 +This leaves the tape positioned on the last block of the file that is count-1
60 +files past the current file.
65 The tape is positioned on the last block of the previous file.
71 -The tape is positioned on the first block of the next file.
72 +file marks, then forward space one file record.
73 +This leaves the tape positioned on the first block of the file that is count-1
74 +files before the current file.
76 The tape is positioned at the beginning of the
78 diff -ru ..\release\mt-st-0.9b/mt.c ./mt.c
79 --- ..\release\mt-st-0.9b/mt.c 2005-08-21 11:48:06.000000000 -0700
80 +++ ./mt.c 2006-08-09 04:00:01.093525100 -0700
82 Last Modified: Sun Aug 21 21:48:06 2005 by kai.makisara
86 +#include <winioctl.h>
92 +#if !defined(_MSC_VER)
100 #include <sys/types.h>
101 -#include <sys/ioctl.h>
106 +#define ioctl tape_ioctl
109 -#define DEFTAPE "/dev/tape" /* default tape device */
110 +#define DEFTAPE "Tape0" /* default tape device */
113 -#define VERSION "0.9b"
114 +#define VERSION "0.9b-bacula"
116 -typedef int (* cmdfunc)(/* int, struct cmdef_tr *, int, char ** */);
117 +typedef int (* cmdfunc)(int, struct cmdef_tr *, int, char **);
119 typedef struct cmdef_tr {
121 @@ -143,12 +153,14 @@
122 FD_RDONLY, ONE_ARG, 0},
123 { "defcompression", MTSETDRVBUFFER, do_drvbuffer, MT_ST_DEF_COMPRESSION,
124 FD_RDONLY, ONE_ARG, 0},
126 { "stsetcln", MTSETDRVBUFFER, do_drvbuffer, MT_ST_SET_CLN,
127 FD_RDONLY, ONE_ARG, 0},
128 { "sttimeout", MTSETDRVBUFFER, do_drvbuffer, MT_ST_SET_TIMEOUT,
129 FD_RDONLY, ONE_ARG, 0},
130 { "stlongtimeout", MTSETDRVBUFFER, do_drvbuffer, MT_ST_SET_LONG_TIMEOUT,
131 FD_RDONLY, ONE_ARG, 0},
133 { "densities", 0, print_densities, 0, NO_FD, NO_ARGS,
135 { "setpartition", MTSETPART, do_standard, 0, FD_RDONLY, ONE_ARG,
136 @@ -211,13 +223,19 @@
137 {0x30, "AIT-1 or MLR3"},
141 + {0x33, "AIT-4 or SLR6"},
143 + {0x38, "AIT-E Turbo"},
144 + {0x39, "AIT-1 Turbo"},
145 + {0x3A, "AIT-2 Turbo"},
147 {0x40, "DLT1 40 GB, or Ultrium"},
148 {0x41, "DLT 40GB, or Ultrium2"},
150 {0x45, "QIC-3095-MC (TR-4)"},
152 + {0x48, "Quantum SDLT220"},
153 + {0x49, "Quantum SDLT320"},
154 {0x80, "DLT 15GB uncomp. or Ecrix"},
155 {0x81, "DLT 15GB compressed"},
156 {0x82, "DLT 20GB uncompressed"},
157 @@ -254,20 +272,25 @@
158 {"no-blklimits", MT_ST_NO_BLKLIMS, "drive doesn't support read block limits"},
159 {"can-partitions",MT_ST_CAN_PARTITIONS,"drive can handle partitioned tapes"},
160 {"scsi2logical", MT_ST_SCSI2LOGICAL, "logical block addresses used with SCSI-2"},
162 {"no-wait", MT_ST_NOWAIT, "immediate mode for rewind, etc."},
165 {"sysv", MT_ST_SYSV, "enable the SystemV semantics"},
168 {"cleaning", MT_ST_SET_CLN, "set the cleaning bit location and mask"},
172 static char *tape_name; /* The tape name for messages */
177 main(int argc, char **argv)
179 - int mtfd, cmd_code, i, argn, len, oflags;
180 + int mtfd, cmd_code, i, argn, oflags;
183 cmdef_tr *comp, *comp2;
186 oflags = comp->cmd_fdtype == FD_RDONLY ? O_RDONLY : O_RDWR;
187 if ((comp->error_tests & ET_ONLINE) == 0)
188 oflags |= O_NONBLOCK;
189 - if ((mtfd = open(tape_name, oflags)) < 0) {
190 + if ((mtfd = tape_open(tape_name, oflags, 0)) < 0) {
204 do_standard(int mtfd, cmdef_tr *cmd, int argc, char **argv)
210 - mt_com.mt_op = cmd->cmd_code;
211 + mt_com.mt_op = (short)cmd->cmd_code;
212 mt_com.mt_count = (argc > 0 ? strtol(*argv, &endp, 0) : 1);
213 if (argc > 0 && endp != *argv) {
217 do_options(int mtfd, cmdef_tr *cmd, int argc, char **argv)
224 mt_com.mt_op = MTSETDRVBUFFER;
227 else if (status.mt_type == MT_ISSCSI2)
230 else if (status.mt_type == MT_ISONSTREAM_SC)
231 type = "OnStream SC-, DI-, DP-, or USB";
237 printf("IDE-Tape (type code 0) ?\n");
239 printf("Unknown tape drive type (type code %ld)\n", status.mt_type);
240 - printf("File number=%d, block number=%d.\n",
241 + printf("File number=%ld, block number=%ld.\n",
242 status.mt_fileno, status.mt_blkno);
243 printf("mt_resid: %ld, mt_erreg: 0x%lx\n",
244 status.mt_resid, status.mt_erreg);
245 @@ -617,14 +643,17 @@
247 printf("%s tape drive:\n", type);
248 if (status.mt_type == MT_ISSCSI2)
249 - printf("File number=%d, block number=%d, partition=%ld.\n",
250 + printf("File number=%ld, block number=%ld, partition=%ld.\n",
251 status.mt_fileno, status.mt_blkno, (status.mt_resid & 0xff));
253 - printf("File number=%d, block number=%d.\n",
254 + printf("File number=%ld, block number=%ld.\n",
255 status.mt_fileno, status.mt_blkno);
256 - if (status.mt_type == MT_ISSCSI1 ||
257 - status.mt_type == MT_ISSCSI2 ||
258 - status.mt_type == MT_ISONSTREAM_SC) {
259 + if (status.mt_type == MT_ISSCSI1
260 + || status.mt_type == MT_ISSCSI2
262 + || status.mt_type == MT_ISONSTREAM_SC
265 dens = (status.mt_dsreg & MT_ST_DENSITY_MASK) >> MT_ST_DENSITY_SHIFT;
266 density = "no translation";
267 for (i=0; i < NBR_DENSITIES; i++)
270 if (GMT_IM_REP_EN(status.mt_gstat))
271 printf(" IM_REP_EN");
273 if (GMT_CLN(status.mt_gstat))
279 diff -ru ..\release\mt-st-0.9b/mtio.h ./mtio.h
280 --- ..\release\mt-st-0.9b/mtio.h 2005-08-16 12:16:28.000000000 -0700
281 +++ ./mtio.h 2006-08-09 03:26:58.352944100 -0700
283 #ifndef _LINUX_MTIO_H
284 #define _LINUX_MTIO_H
286 -#include <linux/types.h>
287 -#include <linux/ioctl.h>
288 -#include <linux/qic117.h>
289 +#include <sys/types.h>
292 * Structures and definitions for mag tape io control commands
298 /* structure for MTIOCGETCONFIG/MTIOCSETCONFIG primarily intended
299 * as an interim solution for QIC-02 until DDI is fully implemented.
307 /* mag tape io control commands */
308 #define MTIOCTOP _IOW('m', 1, struct mtop) /* do a mag tape op */
309 diff -ru ..\release\mt-st-0.9b/stinit.def.examples ./stinit.def.examples
310 --- ..\release\mt-st-0.9b/stinit.def.examples 2005-08-16 12:16:28.000000000 -0700
311 +++ ./stinit.def.examples 2006-08-09 03:26:58.362958700 -0700
313 mode3 blocksize=0 density=1 # 800 bpi
317 +manufacturer="QUANTUM" model = "DLT2000" {
329 +# If your stinit supports the timeouts:
330 +timeout=3600 # 1 hour
331 +long-timeout=14400 # 4 hours
333 +mode1 blocksize=0 density=0x81 # 10GB + compression on DLTtape III, 15+ with DLTtape IIIXT in 2000XT
334 +mode2 blocksize=0 density=0x80 # 10GB, no compression on DLTtape III, 15 with DLTtape IIIXT in 2000XT
335 +mode3 blocksize=0 density=0x18 # 6GB, compression not available, on DLTtape III
336 +mode4 blocksize=0 density=0x17 #2.6GB, compression not available, on DLTtape III
340 +manufacturer="QUANTUM" model = "DLT4000" {
352 +# If your stinit supports the timeouts:
353 +timeout=3600 # 1 hour
354 +long-timeout=14400 # 4 hours
356 +# Drive is backwards compatible, use older modes (e.g. from above) as required
357 +mode1 blocksize=0 density=0x83 # 20GB + compression
358 +mode2 blocksize=0 density=0x82 # 20GB, no compression
359 +mode3 blocksize=0 density=0x81 # 10GB + compression (DLT2000 mode) with DLTtape III, 15+ with DLTtape IIIXT in 2000XT
360 +mode4 blocksize=0 density=0x80 # 10GB, no compression (DLT2000 mode) with DLTtape III, 15 with DLTtape IIIXT in 2000XT
364 +manufacturer="QUANTUM" model = "DLT7000" {
376 +# If your stinit supports the timeouts:
377 +timeout=3600 # 1 hour
378 +long-timeout=14400 # 4 hours
380 +# Drive is backwards compatible, use older modes (e.g. from above) as required.
381 +mode1 blocksize=0 density=0x85 # 35GB + compression
382 +mode2 blocksize=0 density=0x84 # 35GB, no compression
383 +mode3 blocksize=0 density=0x83 # 20GB + compression (DLT4000 mode)
384 +mode4 blocksize=0 density=0x82 # 20GB, no compression (DLT4000 mode)
388 +manufacturer="QUANTUM" model = "DLT8000" {
400 +# If your stinit supports the timeouts:
401 +timeout=3600 # 1 hour
402 +long-timeout=14400 # 4 hours
404 +# Drive is backwards compatible to DLT7000, use older modes (e.g. from above) as required. Modes <10GB (<0x19) not supported!
405 +mode1 blocksize=0 density=0x89 # 40GB + compression
406 +mode2 blocksize=0 density=0x88 # 40GB, no compression
407 +mode3 blocksize=0 density=0x85 # 35GB + compression (DLT7000 mode)
408 +mode4 blocksize=0 density=0x84 # 35GB, no compression (DLT7000 mode)
413 +manufacturer="QUANTUM" model = "SuperDLT1" {
425 +# If your stinit supports the timeouts:
426 +timeout=3600 # 1 hour
427 +long-timeout=14400 # 4 hours
429 +# Drive is backwards read compatible to DLT4000/7000/8000. Mode settings are only required for writing, so no need to define any other modes here.
430 +mode1 blocksize=0 density=0x48 compression=1 # 110 GB + compression
431 +mode2 blocksize=0 density=0x48 compression=0 # 110 GB, no ompression
435 +manufacturer="QUANTUM" model = "SDLT320" {
447 +# If your stinit supports the timeouts:
448 +timeout=3600 # 1 hour
449 +long-timeout=14400 # 4 hours
451 +# Drive is backwards write compatible to SDLT220 and read compatible to DLT4000/7000/8000. Mode settings are only required for writing, so we need only the SDL220/320 modes here
452 +mode1 blocksize=0 density=0x49 compression=1 # 160 GB + compression
453 +mode2 blocksize=0 density=0x49 compression=0 # 160 GB, no ompression
454 +mode3 blocksize=0 density=0x48 compression=1 # 110 GB + compression
455 +mode4 blocksize=0 density=0x48 compression=0 # 110 GB, no ompression
459 +manufacturer="QUANTUM" model = "SDLT600" {
471 +# If your stinit supports the timeouts:
472 +timeout=3600 # 1 hour
473 +long-timeout=14400 # 4 hours
475 +# Drive is backwards read compatible to SDLT220/320 and VS160. Mode settings are only required for writing, so we need only the native SDLT600 mode here.
476 +mode1 blocksize=0 density=0x4a compression=1 # 300 GB + compression
477 +mode2 blocksize=0 density=0x4a compression=0 # 300 GB, no ompression
478 +mode3 blocksize=0 density=0x4a compression=1 # 300 GB + compression
479 +mode4 blocksize=0 density=0x4a compression=0 # 300 GB, no ompression
483 --- /dev/null 1969-12-31 16:00:00.000000000 -0800
484 +++ mtops.c 2006-08-09 04:03:09.307917500 -0700
487 + * mtops.cpp - Emulate the Linux st (scsi tape) driver on Microsoft Windows.
489 + * Author: Robert Nelson, May, 2006 <robertn@the-nelsons.org>
493 + * Copyright (C) 2006 Kern Sibbald
495 + * This file was contributed to the Bacula project by Robert Nelson.
497 + * Robert Nelson has been granted a perpetual, worldwide,
498 + * non-exclusive, no-charge, royalty-free, irrevocable copyright
499 + * license to reproduce, prepare derivative works of, publicly
500 + * display, publicly perform, sublicense, and distribute the original
501 + * work contributed by Robert Nelson to the Bacula project in source
504 + * If you wish to license contributions from Robert Nelson
505 + * under an alternate open source license please contact
506 + * Robert Nelson <robertn@the-nelsons.org>.
509 + Copyright (C) 2006 Kern Sibbald
511 + This program is free software; you can redistribute it and/or
512 + modify it under the terms of the GNU General Public License
513 + version 2 as amended with additional clauses defined in the
514 + file LICENSE in the main source directory.
516 + This program is distributed in the hope that it will be useful,
517 + but WITHOUT ANY WARRANTY; without even the implied warranty of
518 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
519 + the file LICENSE for additional details.
526 +#include <windows.h>
531 +#if defined(_MSC_VER)
532 +#include <winioctl.h>
533 +#include <ntddscsi.h>
535 +#include <ddk/ntddstor.h>
536 +#include <ddk/ntddscsi.h>
546 +// SCSI bus status codes.
549 +#define SCSISTAT_GOOD 0x00
550 +#define SCSISTAT_CHECK_CONDITION 0x02
551 +#define SCSISTAT_CONDITION_MET 0x04
552 +#define SCSISTAT_BUSY 0x08
553 +#define SCSISTAT_INTERMEDIATE 0x10
554 +#define SCSISTAT_INTERMEDIATE_COND_MET 0x14
555 +#define SCSISTAT_RESERVATION_CONFLICT 0x18
556 +#define SCSISTAT_COMMAND_TERMINATED 0x22
557 +#define SCSISTAT_QUEUE_FULL 0x28
559 +/* Forward referenced functions */
561 +extern char my_name[];
562 +extern int debug_level;
564 +inline SHORT Read16BitSigned(const unsigned char *pValue)
566 + return (SHORT)(((USHORT)pValue[0] << 8) | (USHORT)pValue[1]);
569 +inline USHORT Read16BitUnsigned(const unsigned char *pValue)
571 + return (((USHORT)pValue[0] << 8) | (USHORT)pValue[1]);
574 +inline LONG Read24BitSigned(const unsigned char *pValue)
576 + return ((LONG)(((ULONG)pValue[0] << 16) | ((ULONG)pValue[1] << 8) |
577 + (ULONG)pValue[2])) << 8 >> 8;
580 +inline ULONG Read24BitUnsigned(const unsigned char *pValue)
582 + return ((ULONG)pValue[0] << 16) | ((ULONG)pValue[1] << 8) | (ULONG)pValue[2];
585 +inline LONG Read32BitSigned(const unsigned char *pValue)
587 + return (LONG)(((ULONG)pValue[0] << 24) | ((ULONG)pValue[1] << 16) |
588 + ((ULONG)pValue[2] << 8) | (ULONG)pValue[3]);
591 +inline ULONG Read32BitUnsigned(const unsigned char *pValue)
593 + return (((ULONG)pValue[0] << 24) | ((ULONG)pValue[1] << 16) |
594 + ((ULONG)pValue[2] << 8) | (ULONG)pValue[3]);
597 +inline LONGLONG Read64BitSigned(const unsigned char *pValue)
599 + return (LONGLONG)(((ULONGLONG)pValue[0] << 56) | ((ULONGLONG)pValue[1] << 48) |
600 + ((ULONGLONG)pValue[2] << 40) | ((ULONGLONG)pValue[3] << 32) |
601 + ((ULONGLONG)pValue[4] << 24) | ((ULONGLONG)pValue[5] << 16) |
602 + ((ULONGLONG)pValue[6] << 8) | (ULONGLONG)pValue[7]);
605 +inline ULONGLONG Read64BitUnsigned(const unsigned char *pValue)
607 + return (LONGLONG)(((ULONGLONG)pValue[0] << 56) | ((ULONGLONG)pValue[1] << 48) |
608 + ((ULONGLONG)pValue[2] << 40) | ((ULONGLONG)pValue[3] << 32) |
609 + ((ULONGLONG)pValue[4] << 24) | ((ULONGLONG)pValue[5] << 16) |
610 + ((ULONGLONG)pValue[6] << 8) | (ULONGLONG)pValue[7]);
613 +typedef struct _TAPE_POSITION_INFO
615 + UCHAR AtPartitionStart:1;
616 + UCHAR AtPartitionEnd:1;
617 + UCHAR PartitionBlockValid:1;
618 + UCHAR FileSetValid:1;
620 + UCHAR Reserved1[3];
622 + ULONGLONG BlockNumber;
623 + ULONGLONG FileNumber;
624 + ULONGLONG SetNumber;
625 +} TAPE_POSITION_INFO, *PTAPE_POSITION_INFO;
627 +typedef struct _TAPE_HANDLE_INFO
635 + ULONG FeaturesHigh;
637 + ULONGLONG ullFileStart;
639 +} TAPE_HANDLE_INFO, *PTAPE_HANDLE_INFO;
641 +TAPE_HANDLE_INFO TapeHandleTable[] =
643 + { INVALID_HANDLE_VALUE },
644 + { INVALID_HANDLE_VALUE },
645 + { INVALID_HANDLE_VALUE },
646 + { INVALID_HANDLE_VALUE },
647 + { INVALID_HANDLE_VALUE },
648 + { INVALID_HANDLE_VALUE },
649 + { INVALID_HANDLE_VALUE },
650 + { INVALID_HANDLE_VALUE },
651 + { INVALID_HANDLE_VALUE },
652 + { INVALID_HANDLE_VALUE },
653 + { INVALID_HANDLE_VALUE },
654 + { INVALID_HANDLE_VALUE },
655 + { INVALID_HANDLE_VALUE },
656 + { INVALID_HANDLE_VALUE },
657 + { INVALID_HANDLE_VALUE },
658 + { INVALID_HANDLE_VALUE }
661 +#define NUMBER_HANDLE_ENTRIES (sizeof(TapeHandleTable) / sizeof(TapeHandleTable[0]))
663 +DWORD GetTapePositionInfo(HANDLE hDevice, PTAPE_POSITION_INFO TapePositionInfo);
664 +DWORD GetDensityBlockSize(HANDLE hDevice, DWORD *pdwDensity, DWORD *pdwBlockSize);
666 +int tape_get(int fd, struct mtget *mt_get);
667 +int tape_op(int fd, struct mtop *mt_com);
668 +int tape_pos(int fd, struct mtpos *mt_pos);
671 +tape_open(const char *file, int flags, int mode)
673 + HANDLE hDevice = INVALID_HANDLE_VALUE;
674 + char szDeviceName[256] = "\\\\.\\";
678 + for (idxFile = 0; idxFile < (int)NUMBER_HANDLE_ENTRIES; idxFile++) {
679 + if (TapeHandleTable[idxFile].OSHandle == INVALID_HANDLE_VALUE) {
684 + if (idxFile >= (int)NUMBER_HANDLE_ENTRIES) {
688 + memset(&TapeHandleTable[idxFile], 0, sizeof(TapeHandleTable[idxFile]));
690 + if (file[0] != '\\' && file[0] != '/') {
691 + strncpy(&szDeviceName[4], file, sizeof(szDeviceName) - 4);
693 + strncpy(&szDeviceName[0], file, sizeof(szDeviceName));
696 + szDeviceName[sizeof(szDeviceName) - 1] = '\0';
698 + hDevice = CreateFile(szDeviceName, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, 0, NULL);
700 + if (hDevice != INVALID_HANDLE_VALUE) {
701 + PTAPE_HANDLE_INFO pHandleInfo = &TapeHandleTable[idxFile];
703 + memset(pHandleInfo, 0, sizeof(*pHandleInfo));
705 + pHandleInfo->OSHandle = hDevice;
707 + TAPE_GET_DRIVE_PARAMETERS TapeDriveParameters;
708 + DWORD dwSize = sizeof(TapeDriveParameters);
710 + dwResult = GetTapeParameters(pHandleInfo->OSHandle, GET_TAPE_DRIVE_INFORMATION, &dwSize, &TapeDriveParameters);
711 + if (dwResult == NO_ERROR) {
712 + pHandleInfo->FeaturesLow = TapeDriveParameters.FeaturesLow;
713 + pHandleInfo->FeaturesHigh = TapeDriveParameters.FeaturesHigh;
716 + TAPE_POSITION_INFO TapePositionInfo;
718 + dwResult = GetTapePositionInfo(pHandleInfo->OSHandle, &TapePositionInfo);
720 + if (dwResult == NO_ERROR) {
721 + if (TapePositionInfo.AtPartitionStart || TapePositionInfo.AtPartitionEnd ||
722 + (TapePositionInfo.PartitionBlockValid && TapePositionInfo.BlockNumber == 0)) {
723 + pHandleInfo->ulFile = 0;
724 + pHandleInfo->bBlockValid = true;
725 + pHandleInfo->ullFileStart = 0;
726 + } else if (TapePositionInfo.FileSetValid) {
727 + pHandleInfo->ulFile = (ULONG)TapePositionInfo.FileNumber;
731 + DWORD dwError = GetLastError();
734 + case ERROR_FILE_NOT_FOUND:
735 + case ERROR_PATH_NOT_FOUND:
739 + case ERROR_TOO_MANY_OPEN_FILES:
744 + case ERROR_ACCESS_DENIED:
745 + case ERROR_SHARING_VIOLATION:
746 + case ERROR_LOCK_VIOLATION:
747 + case ERROR_INVALID_NAME:
751 + case ERROR_FILE_EXISTS:
755 + case ERROR_INVALID_PARAMETER:
763 + return (int)idxFile + 3;
767 +tape_read(int fd, void *buffer, unsigned int count)
769 + if (buffer == NULL) {
774 + if (fd < 3 || fd >= (int)(NUMBER_HANDLE_ENTRIES + 3) ||
775 + TapeHandleTable[fd - 3].OSHandle == INVALID_HANDLE_VALUE)
781 + PTAPE_HANDLE_INFO pHandleInfo = &TapeHandleTable[fd - 3];
786 + bResult = ReadFile(pHandleInfo->OSHandle, buffer, count, &bytes_read, NULL);
789 + pHandleInfo->bEOF = false;
790 + pHandleInfo->bEOT = false;
791 + pHandleInfo->bEOD = false;
794 + int iReturnValue = 0;
795 + DWORD last_error = GetLastError();
797 + switch (last_error) {
799 + case ERROR_FILEMARK_DETECTED:
800 + pHandleInfo->bEOF = true;
803 + case ERROR_END_OF_MEDIA:
804 + pHandleInfo->bEOT = true;
807 + case ERROR_NO_MEDIA_IN_DRIVE:
808 + pHandleInfo->bEOF = false;
809 + pHandleInfo->bEOT = false;
810 + pHandleInfo->bEOD = false;
815 + case ERROR_NO_DATA_DETECTED:
816 + pHandleInfo->bEOD = true;
819 + case ERROR_INVALID_HANDLE:
820 + case ERROR_ACCESS_DENIED:
821 + case ERROR_LOCK_VIOLATION:
827 + pHandleInfo->bEOF = false;
828 + pHandleInfo->bEOT = false;
829 + pHandleInfo->bEOD = false;
834 + return iReturnValue;
839 +tape_write(int fd, const void *buffer, unsigned int count)
841 + if (buffer == NULL) {
846 + if (fd < 3 || fd >= (int)(NUMBER_HANDLE_ENTRIES + 3) || TapeHandleTable[fd - 3].OSHandle == INVALID_HANDLE_VALUE)
852 + PTAPE_HANDLE_INFO pHandleInfo = &TapeHandleTable[fd - 3];
854 + DWORD bytes_written;
857 + bResult = WriteFile(pHandleInfo->OSHandle, buffer, count, &bytes_written, NULL);
860 + pHandleInfo->bEOF = false;
861 + pHandleInfo->bEOT = false;
862 + return bytes_written;
864 + DWORD last_error = GetLastError();
866 + switch (last_error) {
867 + case ERROR_END_OF_MEDIA:
868 + case ERROR_DISK_FULL:
869 + pHandleInfo->bEOT = true;
873 + case ERROR_NO_MEDIA_IN_DRIVE:
874 + pHandleInfo->bEOF = false;
875 + pHandleInfo->bEOT = false;
876 + pHandleInfo->bEOD = false;
880 + case ERROR_INVALID_HANDLE:
881 + case ERROR_ACCESS_DENIED:
886 + pHandleInfo->bEOF = false;
887 + pHandleInfo->bEOT = false;
888 + pHandleInfo->bEOD = false;
899 + if (fd < 3 || fd >= (int)(NUMBER_HANDLE_ENTRIES + 3) ||
900 + TapeHandleTable[fd - 3].OSHandle == INVALID_HANDLE_VALUE) {
905 + PTAPE_HANDLE_INFO pHandleInfo = &TapeHandleTable[fd - 3];
907 + if (!CloseHandle(pHandleInfo->OSHandle)) {
908 + pHandleInfo->OSHandle = INVALID_HANDLE_VALUE;
913 + pHandleInfo->OSHandle = INVALID_HANDLE_VALUE;
919 +tape_ioctl(int fd, unsigned long int request, ...)
924 + va_start(argp, request);
928 + result = tape_op(fd, va_arg(argp, struct mtop *));
932 + result = tape_get(fd, va_arg(argp, struct mtget *));
936 + result = tape_pos(fd, va_arg(argp, struct mtpos *));
950 +int tape_op(int fd, struct mtop *mt_com)
952 + DWORD result = NO_ERROR;
955 + if (fd < 3 || fd >= (int)(NUMBER_HANDLE_ENTRIES + 3) ||
956 + TapeHandleTable[fd - 3].OSHandle == INVALID_HANDLE_VALUE)
962 + PTAPE_HANDLE_INFO pHandleInfo = &TapeHandleTable[fd - 3];
964 + switch (mt_com->mt_op)
968 + case MTSETDRVBUFFER:
977 + result = (DWORD)-1;
981 + for (index = 0; index < mt_com->mt_count; index++) {
982 + result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_FILEMARKS, 0, 1, 0, FALSE);
983 + if (result == NO_ERROR) {
984 + pHandleInfo->ulFile++;
985 + pHandleInfo->bEOF = true;
986 + pHandleInfo->bEOT = false;
992 + for (index = 0; index < mt_com->mt_count; index++) {
993 + result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_FILEMARKS, 0, (DWORD)-1, ~0, FALSE);
994 + if (result == NO_ERROR) {
995 + pHandleInfo->ulFile--;
996 + pHandleInfo->bBlockValid = false;
997 + pHandleInfo->bEOD = false;
998 + pHandleInfo->bEOF = false;
999 + pHandleInfo->bEOT = false;
1005 + result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_RELATIVE_BLOCKS, 0, mt_com->mt_count, 0, FALSE);
1006 + if (result == NO_ERROR) {
1007 + pHandleInfo->bEOD = false;
1008 + pHandleInfo->bEOF = false;
1009 + pHandleInfo->bEOT = false;
1010 + } else if (result == ERROR_FILEMARK_DETECTED) {
1011 + pHandleInfo->bEOF = true;
1016 + result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_RELATIVE_BLOCKS, 0, -mt_com->mt_count, ~0, FALSE);
1017 + if (result == NO_ERROR) {
1018 + pHandleInfo->bEOD = false;
1019 + pHandleInfo->bEOF = false;
1020 + pHandleInfo->bEOT = false;
1021 + } else if (result == ERROR_FILEMARK_DETECTED) {
1022 + pHandleInfo->ulFile--;
1023 + pHandleInfo->bBlockValid = false;
1024 + pHandleInfo->bEOD = false;
1025 + pHandleInfo->bEOF = false;
1026 + pHandleInfo->bEOT = false;
1031 + result = WriteTapemark(pHandleInfo->OSHandle, TAPE_FILEMARKS, mt_com->mt_count, FALSE);
1032 + if (result == NO_ERROR) {
1033 + pHandleInfo->bEOF = true;
1034 + pHandleInfo->bEOT = false;
1035 + pHandleInfo->ulFile += mt_com->mt_count;
1036 + pHandleInfo->bBlockValid = true;
1037 + pHandleInfo->ullFileStart = 0;
1042 + result = SetTapePosition(pHandleInfo->OSHandle, TAPE_REWIND, 0, 0, 0, FALSE);
1043 + if (result == NO_ERROR) {
1044 + pHandleInfo->bEOD = false;
1045 + pHandleInfo->bEOF = false;
1046 + pHandleInfo->bEOT = false;
1047 + pHandleInfo->ulFile = 0;
1048 + pHandleInfo->bBlockValid = true;
1049 + pHandleInfo->ullFileStart = 0;
1054 + result = PrepareTape(pHandleInfo->OSHandle, TAPE_UNLOAD, FALSE);
1055 + if (result == NO_ERROR) {
1056 + pHandleInfo->bEOD = false;
1057 + pHandleInfo->bEOF = false;
1058 + pHandleInfo->bEOT = false;
1059 + pHandleInfo->ulFile = 0;
1060 + pHandleInfo->ullFileStart = 0;
1065 + result = PrepareTape(pHandleInfo->OSHandle, TAPE_TENSION, FALSE);
1066 + if (result == NO_ERROR) {
1067 + pHandleInfo->bEOD = false;
1068 + pHandleInfo->bEOF = false;
1069 + pHandleInfo->bEOT = false;
1070 + pHandleInfo->ulFile = 0;
1071 + pHandleInfo->bBlockValid = true;
1072 + pHandleInfo->ullFileStart = 0;
1077 + for (index = 0; index < mt_com->mt_count; index++) {
1078 + result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_FILEMARKS, 0, (DWORD)-1, ~0, FALSE);
1079 + if (result == NO_ERROR) {
1080 + result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_FILEMARKS, 0, 1, 0, FALSE);
1081 + pHandleInfo->bEOD = false;
1082 + pHandleInfo->bEOF = false;
1083 + pHandleInfo->bEOT = false;
1089 + for (index = 0; index < mt_com->mt_count; index++) {
1090 + result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_FILEMARKS, 0, mt_com->mt_count, 0, FALSE);
1091 + if (result == NO_ERROR) {
1092 + result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_FILEMARKS, 0, (DWORD)-1, ~0, FALSE);
1093 + pHandleInfo->bEOD = false;
1094 + pHandleInfo->bEOF = false;
1095 + pHandleInfo->bEOT = false;
1102 + result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_FILEMARKS, 0, 1, 0, FALSE);
1103 + if (result != NO_ERROR) {
1104 + pHandleInfo->bEOF = false;
1106 + if (result == ERROR_END_OF_MEDIA) {
1107 + pHandleInfo->bEOD = true;
1108 + pHandleInfo->bEOT = true;
1111 + if (result == ERROR_NO_DATA_DETECTED) {
1112 + pHandleInfo->bEOD = true;
1113 + pHandleInfo->bEOT = false;
1118 + pHandleInfo->bEOF = true;
1119 + pHandleInfo->ulFile++;
1125 + result = EraseTape(pHandleInfo->OSHandle, TAPE_ERASE_LONG, FALSE);
1126 + if (result == NO_ERROR) {
1127 + pHandleInfo->bEOD = true;
1128 + pHandleInfo->bEOF = false;
1129 + pHandleInfo->bEOT = false;
1130 + pHandleInfo->ulFile = 0;
1131 + pHandleInfo->bBlockValid = true;
1132 + pHandleInfo->ullFileStart = 0;
1138 + TAPE_SET_MEDIA_PARAMETERS SetMediaParameters;
1140 + SetMediaParameters.BlockSize = mt_com->mt_count;
1141 + result = SetTapeParameters(pHandleInfo->OSHandle, SET_TAPE_MEDIA_INFORMATION, &SetMediaParameters);
1147 + TAPE_POSITION_INFO TapePositionInfo;
1149 + result = SetTapePosition(pHandleInfo->OSHandle, TAPE_ABSOLUTE_BLOCK, 0, mt_com->mt_count, 0, FALSE);
1151 + memset(&TapePositionInfo, 0, sizeof(TapePositionInfo));
1152 + DWORD dwPosResult = GetTapePositionInfo(pHandleInfo->OSHandle, &TapePositionInfo);
1153 + if (dwPosResult == NO_ERROR && TapePositionInfo.FileSetValid) {
1154 + pHandleInfo->ulFile = (ULONG)TapePositionInfo.FileNumber;
1156 + pHandleInfo->ulFile = ~0U;
1167 + result = GetTapePosition(pHandleInfo->OSHandle, TAPE_ABSOLUTE_BLOCK, &partition, &offset, &offsetHi);
1168 + if (result == NO_ERROR) {
1175 + result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_SETMARKS, 0, mt_com->mt_count, 0, FALSE);
1179 + result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_SETMARKS, 0, -mt_com->mt_count, ~0, FALSE);
1183 + result = WriteTapemark(pHandleInfo->OSHandle, TAPE_SETMARKS, mt_com->mt_count, FALSE);
1187 + result = PrepareTape(pHandleInfo->OSHandle, TAPE_LOCK, FALSE);
1191 + result = PrepareTape(pHandleInfo->OSHandle, TAPE_UNLOCK, FALSE);
1195 + result = PrepareTape(pHandleInfo->OSHandle, TAPE_LOAD, FALSE);
1199 + result = PrepareTape(pHandleInfo->OSHandle, TAPE_UNLOAD, FALSE);
1202 + case MTCOMPRESSION:
1204 + TAPE_GET_DRIVE_PARAMETERS GetDriveParameters;
1205 + TAPE_SET_DRIVE_PARAMETERS SetDriveParameters;
1208 + size = sizeof(GetDriveParameters);
1210 + result = GetTapeParameters(pHandleInfo->OSHandle, GET_TAPE_DRIVE_INFORMATION, &size, &GetDriveParameters);
1212 + if (result == NO_ERROR)
1214 + SetDriveParameters.ECC = GetDriveParameters.ECC;
1215 + SetDriveParameters.Compression = (BOOLEAN)mt_com->mt_count;
1216 + SetDriveParameters.DataPadding = GetDriveParameters.DataPadding;
1217 + SetDriveParameters.ReportSetmarks = GetDriveParameters.ReportSetmarks;
1218 + SetDriveParameters.EOTWarningZoneSize = GetDriveParameters.EOTWarningZoneSize;
1220 + result = SetTapeParameters(pHandleInfo->OSHandle, SET_TAPE_DRIVE_INFORMATION, &SetDriveParameters);
1226 + result = SetTapePosition(pHandleInfo->OSHandle, TAPE_LOGICAL_BLOCK, mt_com->mt_count, 0, 0, FALSE);
1230 + if (mt_com->mt_count == 0)
1232 + result = CreateTapePartition(pHandleInfo->OSHandle, TAPE_INITIATOR_PARTITIONS, 1, 0);
1236 + result = CreateTapePartition(pHandleInfo->OSHandle, TAPE_INITIATOR_PARTITIONS, 2, mt_com->mt_count);
1241 + if ((result == NO_ERROR && pHandleInfo->bEOF) ||
1242 + (result == ERROR_FILEMARK_DETECTED && mt_com->mt_op == MTFSR)) {
1244 + TAPE_POSITION_INFO TapePositionInfo;
1246 + if (GetTapePositionInfo(pHandleInfo->OSHandle, &TapePositionInfo) == NO_ERROR) {
1247 + pHandleInfo->bBlockValid = true;
1248 + pHandleInfo->ullFileStart = TapePositionInfo.BlockNumber;
1254 + case (DWORD)-1: /* Error has already been translated into errno */
1258 + case ERROR_FILEMARK_DETECTED:
1262 + case ERROR_END_OF_MEDIA:
1263 + pHandleInfo->bEOT = true;
1267 + case ERROR_NO_DATA_DETECTED:
1268 + pHandleInfo->bEOD = true;
1272 + case ERROR_NO_MEDIA_IN_DRIVE:
1273 + pHandleInfo->bEOF = false;
1274 + pHandleInfo->bEOT = false;
1275 + pHandleInfo->bEOD = false;
1276 + errno = ENOMEDIUM;
1279 + case ERROR_INVALID_HANDLE:
1280 + case ERROR_ACCESS_DENIED:
1281 + case ERROR_LOCK_VIOLATION:
1286 + return result == NO_ERROR ? 0 : -1;
1289 +int tape_get(int fd, struct mtget *mt_get)
1291 + TAPE_POSITION_INFO pos_info;
1294 + if (fd < 3 || fd >= (int)(NUMBER_HANDLE_ENTRIES + 3) ||
1295 + TapeHandleTable[fd - 3].OSHandle == INVALID_HANDLE_VALUE) {
1300 + PTAPE_HANDLE_INFO pHandleInfo = &TapeHandleTable[fd - 3];
1302 + if (GetTapePositionInfo(pHandleInfo->OSHandle, &pos_info) != NO_ERROR) {
1306 + DWORD density = 0;
1307 + DWORD blocksize = 0;
1309 + result = GetDensityBlockSize(pHandleInfo->OSHandle, &density, &blocksize);
1311 + if (result != NO_ERROR) {
1312 + TAPE_GET_DRIVE_PARAMETERS drive_params;
1315 + size = sizeof(drive_params);
1317 + result = GetTapeParameters(pHandleInfo->OSHandle, GET_TAPE_DRIVE_INFORMATION, &size, &drive_params);
1319 + if (result == NO_ERROR) {
1320 + blocksize = drive_params.DefaultBlockSize;
1324 + mt_get->mt_type = MT_ISSCSI2;
1327 + mt_get->mt_resid = pos_info.PartitionBlockValid ? pos_info.Partition : (ULONG)-1;
1329 + // Density / Block Size
1330 + mt_get->mt_dsreg = ((density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK) |
1331 + ((blocksize << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK);
1333 + mt_get->mt_gstat = 0x00010000; /* Immediate report mode.*/
1335 + if (pHandleInfo->bEOF) {
1336 + mt_get->mt_gstat |= 0x80000000; // GMT_EOF
1339 + if (pos_info.PartitionBlockValid && pos_info.BlockNumber == 0) {
1340 + mt_get->mt_gstat |= 0x40000000; // GMT_BOT
1343 + if (pHandleInfo->bEOT) {
1344 + mt_get->mt_gstat |= 0x20000000; // GMT_EOT
1347 + if (pHandleInfo->bEOD) {
1348 + mt_get->mt_gstat |= 0x08000000; // GMT_EOD
1351 + TAPE_GET_MEDIA_PARAMETERS media_params;
1352 + DWORD size = sizeof(media_params);
1354 + result = GetTapeParameters(pHandleInfo->OSHandle, GET_TAPE_MEDIA_INFORMATION, &size, &media_params);
1356 + if (result == NO_ERROR && media_params.WriteProtected) {
1357 + mt_get->mt_gstat |= 0x04000000; // GMT_WR_PROT
1360 + result = GetTapeStatus(pHandleInfo->OSHandle);
1362 + if (result != NO_ERROR) {
1363 + if (result == ERROR_NO_MEDIA_IN_DRIVE) {
1364 + mt_get->mt_gstat |= 0x00040000; // GMT_DR_OPEN
1367 + mt_get->mt_gstat |= 0x01000000; // GMT_ONLINE
1370 + // Recovered Error Count
1371 + mt_get->mt_erreg = 0;
1374 + mt_get->mt_fileno = (__kernel_daddr_t)pHandleInfo->ulFile;
1377 + mt_get->mt_blkno = (__kernel_daddr_t)(pHandleInfo->bBlockValid ? pos_info.BlockNumber - pHandleInfo->ullFileStart : (ULONGLONG)-1);
1382 +#define SERVICEACTION_SHORT_FORM_BLOCKID 0
1383 +#define SERVICEACTION_SHORT_FORM_VENDOR_SPECIFIC 1
1384 +#define SERVICEACTION_LONG_FORM 6
1385 +#define SERVICEACTION_EXTENDED_FORM 8
1388 +typedef struct _SCSI_READ_POSITION_SHORT_BUFFER
1399 + UCHAR Reserved1[2];
1400 + UCHAR FirstBlock[4];
1401 + UCHAR LastBlock[4];
1403 + UCHAR NumberBufferBlocks[3];
1404 + UCHAR NumberBufferBytes[4];
1405 +} SCSI_READ_POSITION_SHORT_BUFFER, *PSCSI_READ_POSITION_SHORT_BUFFER;
1407 +typedef struct _SCSI_READ_POSITION_LONG_BUFFER
1415 + UCHAR Reserved3[3];
1416 + UCHAR Partition[4];
1417 + UCHAR BlockNumber[8];
1418 + UCHAR FileNumber[8];
1419 + UCHAR SetNumber[8];
1420 +} SCSI_READ_POSITION_LONG_BUFFER, *PSCSI_READ_POSITION_LONG_BUFFER;
1422 +typedef struct _SCSI_READ_POSITION_EXTENDED_BUFFER
1433 + UCHAR AdditionalLength[2];
1435 + UCHAR NumberBufferObjects[3];
1436 + UCHAR FirstLogicalObject[8];
1437 + UCHAR LastLogicalObject[8];
1438 + UCHAR NumberBufferObjectBytes[8];
1439 +} SCSI_READ_POSITION_EXTENDED_BUFFER, *PSCSI_READ_POSITION_EXTENDED_BUFFER;
1441 +typedef union _READ_POSITION_RESULT {
1442 + SCSI_READ_POSITION_SHORT_BUFFER ShortBuffer;
1443 + SCSI_READ_POSITION_LONG_BUFFER LongBuffer;
1444 + SCSI_READ_POSITION_EXTENDED_BUFFER ExtendedBuffer;
1445 +} READ_POSITION_RESULT, *PREAD_POSITION_RESULT;
1447 +DWORD GetTapePositionInfo(HANDLE hDevice, PTAPE_POSITION_INFO TapePositionInfo)
1449 + PSCSI_PASS_THROUGH ScsiPassThrough;
1451 + DWORD dwBytesReturned;
1454 + const DWORD dwBufferSize = sizeof(SCSI_PASS_THROUGH) + sizeof(READ_POSITION_RESULT) + 28;
1456 + memset(TapePositionInfo, 0, sizeof(*TapePositionInfo));
1458 + ScsiPassThrough = (PSCSI_PASS_THROUGH)malloc(dwBufferSize);
1460 + for (pass = 0; pass < 2; pass++)
1462 + memset(ScsiPassThrough, 0, dwBufferSize);
1464 + ScsiPassThrough->Length = sizeof(SCSI_PASS_THROUGH);
1466 + ScsiPassThrough->CdbLength = 10;
1467 + ScsiPassThrough->SenseInfoLength = 28;
1468 + ScsiPassThrough->DataIn = 1;
1469 + ScsiPassThrough->DataTransferLength = sizeof(SCSI_READ_POSITION_LONG_BUFFER);
1470 + ScsiPassThrough->TimeOutValue = 1000;
1471 + ScsiPassThrough->DataBufferOffset = sizeof(SCSI_PASS_THROUGH) + 28;
1472 + ScsiPassThrough->SenseInfoOffset = sizeof(SCSI_PASS_THROUGH);
1474 + ScsiPassThrough->Cdb[0] = 0x34; // READ POSITION
1479 + ScsiPassThrough->Cdb[1] = SERVICEACTION_LONG_FORM;
1483 + ScsiPassThrough->Cdb[1] = SERVICEACTION_SHORT_FORM_BLOCKID;
1487 + bResult = DeviceIoControl( hDevice,
1488 + IOCTL_SCSI_PASS_THROUGH,
1489 + ScsiPassThrough, sizeof(SCSI_PASS_THROUGH),
1490 + ScsiPassThrough, dwBufferSize,
1494 + if (bResult && dwBytesReturned >= (offsetof(SCSI_PASS_THROUGH, ScsiStatus) + sizeof(ScsiPassThrough->ScsiStatus))) {
1495 + if (ScsiPassThrough->ScsiStatus == SCSISTAT_GOOD) {
1496 + PREAD_POSITION_RESULT pPosResult = (PREAD_POSITION_RESULT)((PUCHAR)ScsiPassThrough + ScsiPassThrough->DataBufferOffset);
1500 + case 0: // SERVICEACTION_LONG_FORM
1502 + TapePositionInfo->AtPartitionStart = pPosResult->LongBuffer.BOP;
1503 + TapePositionInfo->AtPartitionEnd = pPosResult->LongBuffer.EOP;
1505 + if (!TapePositionInfo->PartitionBlockValid) {
1506 + TapePositionInfo->PartitionBlockValid = !pPosResult->LongBuffer.BPU;
1508 + if (TapePositionInfo->PartitionBlockValid) {
1509 + TapePositionInfo->Partition = Read32BitUnsigned(pPosResult->LongBuffer.Partition);
1510 + TapePositionInfo->BlockNumber = Read64BitUnsigned(pPosResult->LongBuffer.BlockNumber);
1514 + TapePositionInfo->FileSetValid = !pPosResult->LongBuffer.MPU;
1515 + if (TapePositionInfo->FileSetValid) {
1516 + TapePositionInfo->FileNumber = Read64BitUnsigned(pPosResult->LongBuffer.FileNumber);
1517 + TapePositionInfo->SetNumber = Read64BitUnsigned(pPosResult->LongBuffer.SetNumber);
1522 + case 1: // SERVICEACTION_SHORT_FORM_BLOCKID
1524 + // pPosResult->ShortBuffer.PERR;
1525 + // pPosResult->ShortBuffer.BYCU;
1526 + // pPosResult->ShortBuffer.BCU;
1527 + TapePositionInfo->AtPartitionStart = pPosResult->ShortBuffer.BOP;
1528 + TapePositionInfo->AtPartitionEnd = pPosResult->ShortBuffer.EOP;
1530 + if (!TapePositionInfo->PartitionBlockValid) {
1531 + TapePositionInfo->PartitionBlockValid = !pPosResult->ShortBuffer.BPU;
1533 + if (TapePositionInfo->PartitionBlockValid) {
1534 + TapePositionInfo->Partition = pPosResult->ShortBuffer.Partition;
1535 + TapePositionInfo->BlockNumber = Read32BitUnsigned(pPosResult->ShortBuffer.FirstBlock);
1538 + // Read32BitsUnsigned(pPosResult->ShortBuffer.LastBlock);
1539 + // Read24BitsUnsigned(pPosResult->ShortBuffer.NumberBufferBlocks);
1540 + // Read32BitsUnsigned(pPosResult->ShortBuffer.NumberBufferBytes);
1547 + free(ScsiPassThrough);
1552 +DWORD GetDensityBlockSize(HANDLE hDevice, DWORD *pdwDensity, DWORD *pdwBlockSize)
1554 + DWORD dwBufferSize = sizeof(GET_MEDIA_TYPES) + 5 * sizeof(DEVICE_MEDIA_INFO);
1555 + GET_MEDIA_TYPES * pGetMediaTypes = (GET_MEDIA_TYPES *)malloc(dwBufferSize);
1560 + if (pGetMediaTypes == NULL) {
1561 + return ERROR_OUTOFMEMORY;
1565 + DWORD dwBytesReturned;
1567 + bResult = DeviceIoControl( hDevice,
1568 + IOCTL_STORAGE_GET_MEDIA_TYPES_EX,
1570 + (LPVOID)pGetMediaTypes, dwBufferSize,
1575 + dwResult = GetLastError();
1577 + if (dwResult != ERROR_INSUFFICIENT_BUFFER) {
1578 + free(pGetMediaTypes);
1582 + dwBufferSize += 6 * sizeof(DEVICE_MEDIA_INFO);
1584 + GET_MEDIA_TYPES * pNewBuffer = (GET_MEDIA_TYPES *)realloc(pGetMediaTypes, dwBufferSize);
1586 + if (pNewBuffer != pGetMediaTypes) {
1587 + free(pGetMediaTypes);
1589 + if (pNewBuffer == NULL) {
1590 + return ERROR_OUTOFMEMORY;
1593 + pGetMediaTypes = pNewBuffer;
1596 + } while (!bResult);
1598 + if (pGetMediaTypes->DeviceType != FILE_DEVICE_TAPE) {
1599 + free(pGetMediaTypes);
1600 + return ERROR_BAD_DEVICE;
1603 + for (idxMedia = 0; idxMedia < pGetMediaTypes->MediaInfoCount; idxMedia++) {
1605 + if (pGetMediaTypes->MediaInfo[idxMedia].DeviceSpecific.TapeInfo.MediaCharacteristics & MEDIA_CURRENTLY_MOUNTED) {
1607 + if (pGetMediaTypes->MediaInfo[idxMedia].DeviceSpecific.TapeInfo.BusType == BusTypeScsi) {
1608 + *pdwDensity = pGetMediaTypes->MediaInfo[idxMedia].DeviceSpecific.TapeInfo.BusSpecificData.ScsiInformation.DensityCode;
1613 + *pdwBlockSize = pGetMediaTypes->MediaInfo[idxMedia].DeviceSpecific.TapeInfo.CurrentBlockSize;
1615 + free(pGetMediaTypes);
1621 + free(pGetMediaTypes);
1623 + return ERROR_NO_MEDIA_IN_DRIVE;
1626 +int tape_pos(int fd, struct mtpos *mt_pos)
1633 + if (fd < 3 || fd >= (int)(NUMBER_HANDLE_ENTRIES + 3) ||
1634 + TapeHandleTable[fd - 3].OSHandle == INVALID_HANDLE_VALUE) {
1639 + PTAPE_HANDLE_INFO pHandleInfo = &TapeHandleTable[fd - 3];
1641 + result = GetTapePosition(pHandleInfo->OSHandle, TAPE_ABSOLUTE_BLOCK, &partition, &offset, &offsetHi);
1642 + if (result == NO_ERROR) {
1643 + mt_pos->mt_blkno = offset;
1649 --- /dev/null 1969-12-31 16:00:00.000000000 -0800
1650 +++ mtops.h 2006-08-09 03:26:58.372973300 -0700
1652 +int tape_open(const char *file, int flags, int mode);
1653 +int tape_read(int fd, void *buffer, unsigned int count);
1654 +int tape_write(int fd, const void *buffer, unsigned int count);
1655 +int tape_ioctl(int fd, unsigned long int request, ...);
1656 +int tape_close(int fd);
1658 +typedef unsigned long __kernel_daddr_t;
1661 +#define ENOMEDIUM 123
1665 +#define PATH_MAX 1024
1667 --- /dev/null 1969-12-31 16:00:00.000000000 -0800
1668 +++ Makefile.msc 2006-08-09 04:00:53.970613100 -0700
1671 +CFLAGS= /nologo /Ox /Gy /Zi /W3 /TP \
1672 + /D_CRT_SECURE_NO_DEPRECATE
1673 +LDFLAGS= /link /DEBUG /INCREMENTAL:NO /OPT:NOREF /PDB:$*.pdb /OUT:$@
1679 + $(CC) $(CFLAGS) mt.c mtops.c $(LDFLAGS)
1681 +stinit.exe: stinit.c
1682 + $(CC) $(CFLAGS) stinit.c $(LDFLAGS)
1685 + if not exist $(PREFIX)\bin\nul mkdir $(PREFIX)\bin
1686 + !copy /y $** $(PREFIX)\bin
1689 + del /f *~ *.obj mt.exe stinit.exe