cpio/cpio-2.10-mt.patch

641 lines
16 KiB
Diff

--- doc/mt.1
+++ doc/mt.1
@@ -76,9 +76,6 @@
.IR count .
Equivalent to rewind followed by fsf
.IR count .
-.IP seek
-Seek to block number
-.IR count .
.IP eom
Space to the end of the recorded media on the tape
(for appending files onto tapes).
@@ -93,6 +90,69 @@
then rewind it again.
.IP erase
Erase the tape.
+.IP fss
+(SCSI tapes) Forward space
+.I count
+setmarks.
+.IP bss
+(SCSI tapes) Backward space
+.I count
+setmarks.
+.IP "wset"
+(SCSI tapes) Write
+.I count
+setmarks at current position (only SCSI tape).
+.IP "eod, seod"
+Space to end of valid data. Used on streamer tape
+drives to append data to the logical and of tape.
+.IP setblk
+(SCSI tapes) Set the block size of the drive to
+.I count
+bytes per record.
+.IP setdensity
+(SCSI tapes) Set the tape density code to
+.I count.
+The proper codes to use with each drive should be looked up from the
+drive documentation.
+.IP drvbuffer
+(SCSI tapes) Set the tape drive buffer code to
+.I number.
+The proper value for unbuffered operation is zero and "normal" buffered
+operation one. The meanings of other values can be found in the drive
+documentation or, in case of a SCSI-2 drive, from the SCSI-2 standard.
+.IP stoptions
+(SCSI tapes) Set the driver options bits to
+.I count
+for the device.
+The bits can be set by oring the following values: 1 to enable write
+buffering, 2 to enable asynchronous writes, 4 to enable read ahead,
+8 to enable debugging output (if it has been compiled to the driver).
+.IP stwrthreshold
+(SCSI tapes) The write threshold for the tape device is set to
+.I count
+kilobytes. The value must be smaller than or equal to the driver
+buffer size.
+.IP seek
+(SCSI tapes) Seek to the
+.I count
+block on the tape. This operation is available on some
+Tandberg and Wangtek streamers and some SCSI-2 tape drives.
+.IP tell
+(SCSI tapes) Tell the current block on tape. This operation is available on some
+Tandberg and Wangtek streamers and some SCSI-2 tape drives.
+.IP densities
+(SCSI tapes) Write explanation of some common density codes to
+standard output.
+.IP datcompression
+(some SCSI-2 DAT tapes) Inquire or set the compression status
+(on/off). If the
+.I count
+is one the compression status is printed. If the
+.I count
+is zero, compression is disabled. Otherwise, compression is
+enabled. The command uses the SCSI ioctl to read and write the Data
+Compression Characteristics mode page (15). ONLY ROOT CAN USE THIS
+COMMAND.
.PP
.B mt
exits with a status of 0 if the operation succeeded, 1 if the
--- lib/system.h
+++ lib/system.h
@@ -431,10 +431,11 @@
#if HAVE_LOCALE_H
# include <locale.h>
-#endif
+#else
#if !HAVE_SETLOCALE
# define setlocale(category, locale) /* empty */
#endif
+#endif
#include <time.h>
#ifdef TIME_WITH_SYS_TIME
--- src/Makefile.am
+++ src/Makefile.am
@@ -18,7 +18,7 @@
INCLUDES=-I. -I.. -I$(top_srcdir)/lib
-bin_PROGRAMS=cpio @CPIO_MT_PROG@
+bin_PROGRAMS=cpio mt
EXTRA_PROGRAMS=mt
cpio_SOURCES = \
--- src/copyin.c
+++ src/copyin.c
@@ -768,7 +768,7 @@
static void
copyin_file (struct cpio_file_stat* file_hdr, int in_file_des)
{
- int existing_dir;
+ int existing_dir=0;
if (!to_stdout_option
&& try_existing_file (file_hdr, in_file_des, &existing_dir) < 0)
@@ -1355,6 +1355,7 @@
int in_file_des; /* Input file descriptor. */
char skip_file; /* Flag for use with patterns. */
int i; /* Loop index variable. */
+ int lastpattern = 0;
umask (0); /* Reset umask to preserve modes of
created files */
@@ -1463,8 +1464,10 @@
for (i = 0; i < num_patterns
&& skip_file == copy_matching_files; i++)
{
- if (fnmatch (save_patterns[i], file_hdr.c_name, 0) == 0)
+ if (fnmatch (save_patterns[lastpattern], file_hdr.c_name, 0) == 0)
skip_file = !copy_matching_files;
+ else if (++lastpattern >= num_patterns)
+ lastpattern = 0;
}
}
--- src/mt.c
+++ src/mt.c
@@ -17,6 +17,10 @@
02110-1301 USA
*/
+/* Modified for the Linux SCSI tape driver by Brian Mays from code
+ written by Kai Makisara.
+ Last Modified: Tue Apr 23 15:37:54 EDT 1996
+*/
/* If -f is not given, the environment variable TAPE is used;
if that is not set, a default device defined in sys/mtio.h is used.
@@ -51,6 +55,48 @@
retension Rewind the tape, then wind it to the end of the reel,
then rewind it again.
erase Erase the tape.
+ fss (SCSI tapes) Forward space COUNT setmarks.
+ bss (SCSI tapes) Backward space COUNT setmarks.
+ wset (SCSI tapes) Write COUNT setmarks at current position
+ (only SCSI tape).
+ eod, seod Space to end of valid data. Used on streamer tape
+ drives to append data to the logical and of tape.
+ setblk (SCSI tapes) Set the block size of the drive to COUNT
+ bytes per record.
+ setdensity (SCSI tapes) Set the tape density code to COUNT. The
+ proper codes to use with each drive should be looked
+ up from the drive documentation.
+ drvbuffer (SCSI tapes) Set the tape drive buffer code to
+ NUMBER. The proper value for unbuffered operation is
+ zero and "normal" buffered operation one. The meanings
+ of other values can be found in the drive
+ documentation or, in case of a SCSI-2 drive, from the
+ SCSI-2 standard.
+ stoptions (SCSI tapes) Set the driver options bits to COUNT for
+ the device. The bits can be set by oring the
+ following values: 1 to enable write buffering, 2 to
+ enable asynchronous writes, 4 to enable read ahead, 8
+ to enable debugging output (if it has been compiled to
+ the driver).
+ stwrthreshold
+ (SCSI tapes) The write threshold for the tape device
+ is set to COUNT kilobytes. The value must be smaller
+ than or equal to the driver buffer size.
+ seek (SCSI tapes) Seek to the COUNT block on the tape.
+ This operation is available on some Tandberg and
+ Wangtek streamers and some SCSI-2 tape drives.
+ tell (SCSI tapes) Tell the current block on tape. This
+ operation is available on some Tandberg and Wangtek
+ streamers and some SCSI-2 tape drives.
+ densities (SCSI tapes) Write explanation of some common density
+ codes to standard output.
+ datcompression
+ (some SCSI-2 DAT tapes) Inquire or set the compression
+ status (on/off). If the COUNT is one the compression
+ status is printed. If the COUNT is zero, compression
+ is disabled. Otherwise, compression is enabled.
David MacKenzie <djm@gnu.ai.mit.edu> */
+
+#include <configmake.h>
@@ -105,6 +147,43 @@
void exit ();
#endif
+#if defined(linux) || defined(__linux)
+#define MTDATCOMP 1000 /* Random unused number. */
+#define MTDENS 1001 /* Random unused number. */
+
+struct densities {
+ int code;
+ char *name;
+} density_tbl[] = {
+ {0x00, "default"},
+ {0x01, "NRZI (800 bpi)"},
+ {0x02, "PE (1600 bpi)"},
+ {0x03, "GCR (6250 bpi)"},
+ {0x05, "QIC-45/60 (GCR, 8000 bpi)"},
+ {0x06, "PE (3200 bpi)"},
+ {0x07, "IMFM (6400 bpi)"},
+ {0x08, "GCR (8000 bpi)"},
+ {0x09, "GCR /37871 bpi)"},
+ {0x0a, "MFM (6667 bpi)"},
+ {0x0b, "PE (1600 bpi)"},
+ {0x0c, "GCR (12960 bpi)"},
+ {0x0d, "GCR (25380 bpi)"},
+ {0x0f, "QIC-120 (GCR 10000 bpi)"},
+ {0x10, "QIC-150/250 (GCR 10000 bpi)"},
+ {0x11, "QIC-320/525 (GCR 16000 bpi)"},
+ {0x12, "QIC-1350 (RLL 51667 bpi)"},
+ {0x13, "DDS (61000 bpi)"},
+ {0x14, "EXB-8200 (RLL 43245 bpi)"},
+ {0x15, "EXB-8500 (RLL 45434 bpi)"},
+ {0x16, "MFM 10000 bpi"},
+ {0x17, "MFM 42500 bpi"},
+ {0x24, "DDS-2"},
+ {140, "EXB-8505 compressed"},
+ {144, "EXB-8205 compressed"},
+ {-1, NULL}};
+#endif
+
+
char *opnames[] =
{
"eof", "weof", "fsf", "bsf", "fsr", "bsr",
@@ -114,6 +197,8 @@
#endif
#ifdef MTEOM
"eom",
+ "eod",
+ "seod",
#endif
#ifdef MTRETEN
"retension",
@@ -128,6 +213,39 @@
#ifdef MTSEEK
"seek",
#endif
+#ifdef MTTELL
+ "tell",
+#endif
+#ifdef MTFSS
+ "fss",
+#endif
+#ifdef MTBSS
+ "bss",
+#endif
+#ifdef MTWSM
+ "wset",
+#endif
+#ifdef MTSETBLK
+ "setblk",
+#endif
+#ifdef MTSETDENSITY
+ "setdensity",
+#endif
+#ifdef MTSETDRVBUFFER
+ "drvbuffer",
+#ifdef MT_ST_BOOLEANS
+ "stoptions",
+#endif
+#ifdef MT_ST_WRITE_THRESHOLD
+ "stwrthreshold",
+#endif
+#endif
+#ifdef MTDATCOMP
+ "datcompression",
+#endif
+#ifdef MTDENS
+ "densities",
+#endif
NULL
};
@@ -141,6 +259,8 @@
#endif
#ifdef MTEOM
MTEOM,
+ MTEOM,
+ MTEOM,
#endif
#ifdef MTRETEN
MTRETEN,
@@ -155,9 +275,69 @@
#ifdef MTSEEK
MTSEEK,
#endif
+#ifdef MTTELL
+ MTTELL,
+#endif
+#ifdef MTFSS
+ MTFSS,
+#endif
+#ifdef MTBSS
+ MTBSS,
+#endif
+#ifdef MTWSM
+ MTWSM,
+#endif
+#ifdef MTSETBLK
+ MTSETBLK,
+#endif
+#ifdef MTSETDENSITY
+ MTSETDENSITY,
+#endif
+#ifdef MTSETDRVBUFFER
+ MTSETDRVBUFFER,
+#ifdef MT_ST_BOOLEANS
+ MTSETDRVBUFFER,
+#endif
+#ifdef MT_ST_WRITE_THRESHOLD
+ MTSETDRVBUFFER,
+#endif
+#endif
+#ifdef MTDATCOMP
+ MTDATCOMP,
+#endif
+#ifdef MTDENS
+ MTDENS,
+#endif
0
};
+char *cbnames[] =
+{
+#ifdef MT_ST_BOOLEANS
+ "stoptions",
+#endif
+#ifdef MT_ST_WRITE_THRESHOLD
+ "stwrthreshold",
+#endif
+ NULL
+};
+
+int count_bits[] =
+{
+#ifdef MT_ST_BOOLEANS
+ MT_ST_BOOLEANS,
+#endif
+#ifdef MT_ST_WRITE_THRESHOLD
+ MT_ST_WRITE_THRESHOLD,
+#endif
+ 0
+};
+
+#ifdef MT_TAPE_INFO
+ struct mt_tape_info tapes[] = MT_TAPE_INFO;
+#endif
+
+
struct option longopts[] =
{
{"file", 1, NULL, 'f'},
@@ -200,10 +380,22 @@
print_status (char *dev, int desc)
{
struct mtget status;
+#ifdef MT_TAPE_INFO
+ struct mt_tape_info *mt;
+#endif
if (rmtioctl (desc, MTIOCGET, (char*)&status) == -1)
error (2, errno, _("%s: rmtioctl failed"), dev);
+#ifdef MT_TAPE_INFO
+ for (mt = tapes; mt->t_type; mt++)
+ if (mt->t_type == status.mt_type) break;
+ if (mt->t_type != 0)
+ {
+ printf ("drive type = %s\n", mt->t_name);
+ }
+ else
+#endif
printf ("drive type = %d\n", (int) status.mt_type);
#if defined(hpux) || defined(__hpux)
printf ("drive status (high) = %d\n", (int) status.mt_dsreg1);
@@ -217,7 +409,177 @@
printf ("file number = %d\n", (int) status.mt_fileno);
printf ("block number = %d\n", (int) status.mt_blkno);
#endif
+#if defined(linux) || defined(__linux)
+ if (status.mt_type == MT_ISSCSI1 ||
+ status.mt_type == MT_ISSCSI2)
+ {
+ int dens, i;
+ char *density;
+ dens = (status.mt_dsreg & MT_ST_DENSITY_MASK) >> MT_ST_DENSITY_SHIFT;
+ density = "unknown";
+ for (i=0; density_tbl[i].code >= 0; i++)
+ if (density_tbl[i].code == dens)
+ {
+ density = density_tbl[i].name;
+ break;
+ }
+ printf("Tape block size %ld bytes. Density code 0x%x (%s).\n",
+ ((status.mt_dsreg & MT_ST_BLKSIZE_MASK) >> MT_ST_BLKSIZE_SHIFT),
+ dens, density);
+
+ printf("Soft error count since last status=%ld\n",
+ (status.mt_erreg & MT_ST_SOFTERR_MASK) >> MT_ST_SOFTERR_SHIFT);
+ printf("General status bits on (%lx):\n", status.mt_gstat);
+ if (GMT_EOF(status.mt_gstat))
+ printf(" EOF");
+ if (GMT_BOT(status.mt_gstat))
+ printf(" BOT");
+ if (GMT_EOT(status.mt_gstat))
+ printf(" EOT");
+ if (GMT_SM(status.mt_gstat))
+ printf(" SM");
+ if (GMT_EOD(status.mt_gstat))
+ printf(" EOD");
+ if (GMT_WR_PROT(status.mt_gstat))
+ printf(" WR_PROT");
+ if (GMT_ONLINE(status.mt_gstat))
+ printf(" ONLINE");
+ if (GMT_D_6250(status.mt_gstat))
+ printf(" D_6250");
+ if (GMT_D_1600(status.mt_gstat))
+ printf(" D_1600");
+ if (GMT_D_800(status.mt_gstat))
+ printf(" D_800");
+ if (GMT_DR_OPEN(status.mt_gstat))
+ printf(" DR_OPEN");
+ if (GMT_IM_REP_EN(status.mt_gstat))
+ printf(" IM_REP_EN");
+ if (status.mt_gstat != 0)
+ putchar ('\n');
+ }
+ else
+ {
+ printf("gstat = %0lx\n", status.mt_gstat);
+ }
+#endif
+}
+
+
+#if defined(linux) || defined(__linux)
+/*** Get and set the DAT compression (Mode Page 15) ***/
+
+#define MODE_SENSE 0x1a
+#define MODE_SELECT 0x15
+
+int
+read_mode_page(int fn, int page, int length, unsigned char *buffer,
+ int do_mask)
+{
+ int result, *ip;
+ unsigned char tmpbuffer[30], *cmd;
+
+ memset(tmpbuffer, 0, 14);
+ ip = (int *)&(tmpbuffer[0]);
+ *ip = 0;
+ *(ip+1) = length + 4;
+
+ cmd = &(tmpbuffer[8]);
+ cmd[0] = MODE_SENSE;
+ cmd[1] = 8;
+ cmd[2] = page;
+ if (do_mask)
+ cmd[2] |= 0x40; /* Get changeable parameter mask */
+ cmd[4] = length + 4;
+
+ result = ioctl(fn, 1, tmpbuffer);
+ if (result) {
+ fprintf(stderr, "Can't read mode page. Are you sure you are root?\n");
+ return 0;
+ }
+ memcpy(buffer, tmpbuffer + 8, length + 4);
+ return 1;
+}
+
+
+int
+write_mode_page(int fn, int page, int length, unsigned char *buffer)
+{
+ int result, *ip;
+ unsigned char tmpbuffer[40], *cmd;
+
+ memset(tmpbuffer, 0, 14);
+ ip = (int *)&(tmpbuffer[0]);
+ *ip = length + 4;
+ *(ip+1) = 0;
+
+ cmd = &(tmpbuffer[8]);
+ cmd[0] = MODE_SELECT;
+ cmd[1] = 0x10;
+ cmd[4] = length + 4;
+
+ memcpy(tmpbuffer + 14, buffer, length + 4);
+ tmpbuffer[14] = 0; /* reserved data length */
+ tmpbuffer[18] &= 0x3f; /* reserved bits in page code byte */
+
+ result = ioctl(fn, 1, tmpbuffer);
+ if (result) {
+ fprintf(stderr, "Can't write mode page.\n");
+ return 0;
+ }
+ return 1;
+}
+
+
+int
+do_dat_compression(char *dev, int fn, int count)
+{
+ int i;
+ unsigned char buffer[30], mask[30];
+
+ if (!read_mode_page(fn, 0x0f, 16, buffer, 0)) {
+ error (2, errno, "%s", dev);
+ }
+
+ if (count != -1) {
+ if (count == 0)
+ buffer[4+2] &= 0x7f;
+ else
+ buffer[4+2] |= 0x80;
+/* if (read_mode_page(fn, 0x0f, 16, mask, 1))
+ for (i=3; i < 16; i++)
+ buffer[4+i] |= mask[4+i]; bug #223494 */
+ if (!write_mode_page(fn, 0x0f, 16, buffer)) {
+ error (2, errno, "%s", dev);
+ }
+ if (!read_mode_page(fn, 0x0f, 16, buffer, 0)) { /* Re-read to check */
+ error (2, errno, "%s", dev);
+ }
+ }
+
+ if (buffer[4+2] & 0x80)
+ printf("Compression on.\n");
+ else
+ printf("Compression off.\n");
+
+ return 1;
}
+#endif
+
+#ifdef MTTELL
+void
+print_position (dev, desc)
+ char *dev;
+ int desc;
+{
+ struct mtpos position;
+
+ if (rmtioctl (desc, MTIOCPOS, &position) == -1)
+ error (2, errno, "%s", dev);
+ printf("At block %ld.\n", position.mt_blkno);
+
+}
+#endif
+
void
usage (FILE *fp,int status)
@@ -276,7 +638,7 @@
if (optind == argc)
usage (stderr, 1);
- i = argmatch (argv[optind], opnames);
+ i = argmatch (argv[optind], opnames,NULL,0);
if (i < 0)
{
argmatch_invalid ("tape operation", argv[optind], i);
@@ -308,10 +670,29 @@
#endif
}
+#ifdef MTDENS
+ if (operation == MTDENS)
+ {
+ printf("Some SCSI tape density codes:\ncode explanation\n");
+ for (i=0; density_tbl[i].code >= 0; i++)
+ printf("0x%02x %s\n", density_tbl[i].code, density_tbl[i].name);
+ exit (0);
+ }
+#endif
+
if ( (operation == MTWEOF)
#ifdef MTERASE
|| (operation == MTERASE)
#endif
+#ifdef MTWSM
+ || (operation == MTWSM)
+#endif
+#ifdef MTSETDRVBUFFER
+ || (operation == MTSETDRVBUFFER)
+#endif
+#ifdef MTDATCOMP
+ || (operation == MTDATCOMP)
+#endif
)
tapedesc = rmtopen (tapedev, O_WRONLY, 0, rsh_command_option);
else
@@ -320,6 +701,17 @@
error (1, errno, _("%s: rmtopen failed"), tapedev);
check_type (tapedev, tapedesc);
+#ifdef MTDATCOMP
+ if (operation == MTDATCOMP)
+ do_dat_compression(tapedev, tapedesc, count);
+ else
+#endif
+#ifdef MTTELL
+ if (operation == MTTELL)
+ print_position (tapedev, tapedesc);
+ else
+#endif
+ {
if (operation == MTASF)
{
perform_operation (tapedev, tapedesc, MTREW, 1);
@@ -328,6 +720,7 @@
perform_operation (tapedev, tapedesc, operation, count);
if (operation == MTNOP)
print_status (tapedev, tapedesc);
+ }
if (rmtclose (tapedesc) == -1)
error (2, errno, _("%s: rmtclose failed"), tapedev);