NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
port-amd64/53890: st(4) driver for tapes not working o variable block size
>Number: 53890
>Category: port-amd64
>Synopsis: st(4) driver for tapes not working o variable block size
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: port-amd64-maintainer
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Jan 18 15:20:00 +0000 2019
>Originator: Gerard J van der Grinten
>Release: NetBSD 5.x 6.x 7.x 8.0
>Organization:
private
>Environment:
uname -a
NetBSD plato.net27.gri 8.0 NetBSD 8.0 (GENERIC) #0: Tue Jul 17 14:59:51 UTC 2018 mkrepro%mkrepro.NetBSD.org@localhost:/usr/src/sys/arch/amd64/compile/GENERIC amd64
>Description:
I have tried my problem under various versions of NetBSD AMD65 and I386.
I want to read and write .TAP files (SIMH containers)on various Tape drive
models (currently a DDS4 Drive.
To my great disappointment It works flawlessly under Debian Linux.
Here a sample session:
plato# ./mt2tap xxz
Converting tape to tap file xxz
rc NOP ioctl = 0
rc on set block size = 0
rc on set density = 0
rc on set compression = 0
len1 = 00486 rc NOP ioctl = 0
len2 = 00486
Reading block: Invalid argument
blocks = 00002
plato# ls -l xx*
-rw-r--r-- 1 root wheel 35670660 Jan 11 14:55 xx
-rw-r--r-- 1 root wheel 35670660 Jan 11 17:11 xx.tap
-rw-r--r-- 1 root wheel 10260 Jan 13 14:26 xx1
-rw-r--r-- 1 root wheel 2068 Jan 11 16:41 xxx
-rw-r--r-- 1 root wheel 35670660 Jan 12 13:32 xxx.tap
-rw-r--r-- 1 root wheel 35670660 Jan 11 14:31 xxxx
-rw-r--r-- 1 root wheel 20008 Jan 13 14:18 xxxx.t
-rw-r--r-- 1 root wheel 0 Jan 13 13:53 xxxx.tap
-rw-r--r-- 1 root wheel 494 Jan 18 14:14 xxz
plato# ./tap2mt xx.tap
3584 65536
rc on MTREW = 0
rc on set block size = 0
rc on set density = 0
rc on set compression = 0
len = 00486
len = 00930
Error writing tape (end?) act -1 exp 930.
plato# ./tap2mt -t /dev/rst0 xx.tap
3584 65536
rc on MTREW = 0
rc on set block size = 0
rc on set density = 0
rc on set compression = 0
len = 00486
len = 00930
Error writing tape (end?) act -1 exp 930.
plato#
Linux correctly reads and writes the tap files.
The ST I/O read and write give up after the fist record.
My record sizes vary fro 80 to 386
My mt2tap.c and tap2mt.c follow:
===============================================
/*
* tap2mt.c - Write a .tap file to a magnetic tape.
*
* Copyright 1998,1999,2000,2002,2015,2019 - G. J. van der Grinten
* All rights reserved by G. J. van der Grinten
* Pater L.A. Bleysstraat 7
* 5684 TR Best
* Netherlands
densityCode Format
0 Device default
1 1/2" 800 bpi
2 1/2" 1600 bpi
3 1/2" 6250 bpi
4 QIC-11
5 QIC-24
15 QIC-120
16 QIC-150
17 QIC-320/525
18 QIC-1320/1350
19 DDS
28 QIC-385M
29 QIC-410M
30 QIC-1000C
31 QIC-2100C
32 QIC-6GB
33 QIC-20GB
34 QIC-2GB
35 QIC-875M
36 DDS-2
37 DDS-3
38 DDS-4
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#if !defined(_WIN32)
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mtio.h>
#if defined(_WIN32)
#include "getopt.c"
#define TAPE "\\\\.\\TAPE0"
#else
#if defined(__linux__) || defined(__gnu_linux__) || defined(linux)
#define TAPE "/dev/st0"
#elif ((defined __NetBSD__) || defined (__FreeBSD__))
#define TAPE "/dev/rst0"
#endif
#endif
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#define MTSETBLK MTSETBSIZ
#define MTSETDENSITY MTSETDNSTY
#define MTCOMPRESSION MTCMPRESS
#endif
unsigned char buf[100000];
static union {
int number;
char bytes[4];
} endianCheck;
int endian = 0;
void init_endian()
{
endianCheck.number = 0;
endianCheck.bytes[3] = 1;
endian = endianCheck.number == 1 ? 1 : 0;
}
int to_intel(int a)
{
int _tmp;
if (endian) {
_tmp = a;
((char *)(void *)&a)[0] = ((char *)(void *)&_tmp)[3];
((char *)(void *)&a)[1] = ((char *)(void *)&_tmp)[2];
((char *)(void *)&a)[2] = ((char *)(void *)&_tmp)[1];
((char *)(void *)&a)[3] = ((char *)(void *)&_tmp)[0];
}
return a;
}
void usage()
{
fprintf(stderr, "Usage: tap2mt [[-d <density>] [-t <tape device>]] <tap_file> \n");
exit(1);
}
int main(int argc, char **argv)
{
FILE *infile;
int mt;
int recLen1;
int recLen2;
int len;
int rc;
int ch;
int dens = 0;
char *dev = TAPE;
struct stat stbuf;
struct mtop op;
init_endian();
while(( ch = getopt(argc, argv, "d:t:")) != -1) {
switch(ch) {
case 'd':
dens = atoi(optarg);
break;
case 't':
dev = optarg;
break;
default :
usage();
}
}
#if !defined(_WIN32)
argc -= optind;
argv += optind;
#endif
if (argc != 1) {
usage();
}
#if !defined(_WIN32)
#if defined __linux__
if (!stat(dev, &stbuf) && !S_ISCHR(stbuf.st_mode)) {
#elif ((defined __NetBSD__) || defined (__FreeBSD__))
if (!stat(dev, &stbuf) && !S_ISCHR(stbuf.st_mode)) {
#endif
fprintf(stderr, "The tape drive '%s' is not an expected device.\n", dev);
// exit( 1);
}
#endif
printf("%d %d\n", stbuf.st_rdev, stbuf.st_blksize);
if ((mt = open(dev, O_RDWR, 0)) < 0)
{
perror("could not open tape drive");
exit(1);
}
op.mt_op = MTREW;
op.mt_count = 1;
rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc on MTREW = %d\n",rc);
#if ((defined __NetBSD__) || defined (__FreeBSD__))
op.mt_op = MTSETBSIZ;
#else
op.mt_op = MTSETBLK;
#endif
op.mt_count = 0; /* blockize = 0 (variable) */
rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc on set block size = %d\n",rc);
#if ((defined __NetBSD__) || defined (__FreeBSD__))
op.mt_op = MTSETDNSTY;
#else
op.mt_op = MTSETDENSITY;
#endif
op.mt_count = dens; /* 1600 BPI */
rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc on set density = %d\n",rc);
#if ((defined __NetBSD__) || defined (__FreeBSD__))
op.mt_op = MTCMPRESS;
#elif defined __linux__
op.mt_op = MTCOMPRESSION;
#endif
op.mt_count = 0; /* no compression */
rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc on set compression = %d\n",rc);
if ((infile = fopen(argv[0], "rb")) == NULL) {
perror("could not open input file");
exit(1);
}
while(1) {
len = fread(&recLen1, sizeof(recLen1), 1, infile);
if (len <= 0) {
fprintf(stderr, "End of Information\n");
break;
}
recLen1 = to_intel(recLen1);
if (recLen1 > 0) {
len = fread(buf, 1, recLen1, infile);
if (recLen1 != len) {
fprintf(stderr, "Read %d bytes, expected %d\n",len,recLen1);
break;
}
len = fread(&recLen2, sizeof(recLen2), 1, infile);
recLen2 = to_intel(recLen2);
if (len <= 0 || recLen2 != recLen1) {
fprintf(stderr, "Mismatch in TAP record\n");
break;
}
}
#if 1
fprintf(stdout, "len = %05d\n", recLen1);
fflush(stdout);
#endif
if (recLen1 == 0) {
op.mt_op = MTWEOF;
op.mt_count = 1;
rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
fprintf(stderr, "zero length %d\n", rc);
} else {
if((rc = write(mt, buf, recLen1)) != recLen1) {
fprintf(stderr,"Error writing tape (end?) act %d exp %d.\n",rc, recLen1);
exit(1);
}
}
}
op.mt_op = MTWEOF;
op.mt_count = 2;
rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
fclose(infile);
close(mt);
return(0);
}
#else
int main(int argc, char **argv)
{
printf("this program is not supported under a MsWindows OS\n");
return(0);
}
#endif
======================================================================
/*
* mt2tap.c - Read a magntic tape to a .tap file.
*
* Copyright 1998,1999,2000,2002,2015,2019 - G. J. van der Grinten
* All rights reserved by G. J. van der Grinten
* Pater L.A. Bleysstraat 7
* 5684 TR Best
* Netherlands
*/
// #elif defined(__GNUC__) && (defined(__linux__) || defined(__SunOS) || defined (__FreeBSD__))
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#if !defined(_WIN32)
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/mtio.h>
#include <fcntl.h>
#if defined(_WIN32)
#include "getopt.c"
#define TAPE "\\\\.\\TAPE0"
#else
#if defined(__linux__) || defined(__gnu_linux__) || defined(linux)
#define TAPE "/dev/st0"
#elif ((defined __NetBSD__) || defined (__FreeBSD__)) || defined(__OpenBSD__)
#define TAPE "/dev/rst0"
#endif
#endif
unsigned char buf[20000];
static union {
int number;
char bytes[4];
} endianCheck;
int endian = 0;
void init_endian()
{
endianCheck.number = 0;
endianCheck.bytes[3] = 1;
endian = endianCheck.number == 1 ? 1 : 0;
}
int to_intel(a)
int a;
{
int _tmp;
if (endian) {
_tmp = a;
((char *)(void *)&a)[0] = ((char *)(void *)&_tmp)[3];
((char *)(void *)&a)[1] = ((char *)(void *)&_tmp)[2];
((char *)(void *)&a)[2] = ((char *)(void *)&_tmp)[1];
((char *)(void *)&a)[3] = ((char *)(void *)&_tmp)[0];
}
return a;
}
void usage()
{
fprintf(stderr, "Usage: mt2tap [[-d <density>] [-t <tape device>]] <tap_file> \n");
exit(1);
}
int main(int argc, char **argv)
{
FILE *tapfile;
int mt;
int ic;
int oc;
int zero = 0;
int ch;
int rc;
int blocks = 0;
int dens = 38;
char *dev = TAPE;
struct stat stbuf;
struct mtop op;
init_endian();
while(( ch = getopt(argc, argv, "d:t:")) != -1) {
switch(ch) {
case 'd':
dens = atoi(optarg);
break;
case 't':
dev = optarg;
break;
default :
usage();
}
}
#if !defined(_WIN32)
argc -= optind;
argv += optind;
#endif
if (argc != 1) {
usage();
}
printf("Converting tape to tap file %s \n",argv[0]);
#if !defined(_WIN32)
#if defined __linux__
if (!stat(dev, &stbuf) && !S_ISCHR(stbuf.st_mode)) {
#elif ((defined __NetBSD__) || defined (__FreeBSD__))
if (!stat(dev, &stbuf) && !S_ISCHR(stbuf.st_mode)) {
#endif
fprintf(stderr, "The tape drive '%s' is not an expected device.\n", dev);
// exit( 1);
}
#endif
if ((mt = open(dev, O_RDONLY | O_NONBLOCK ,0)) < 0)
{
perror("could not open tape device");
exit(1);
}
if ((tapfile = fopen(argv[0], "wb")) == NULL)
{
perror("open TAP file");
exit(1);
}
#if !defined(_WIN32)
op.mt_op = MTNOP;
op.mt_count = 0; /* no compression */
rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc NOP ioctl = %d\n",rc);
#endif
op.mt_op = MTREW;
op.mt_count = 1;
rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
#if ((defined __NetBSD__) || defined (__FreeBSD__))
op.mt_op = MTSETBSIZ;
#else
op.mt_op = MTSETBLK;
#endif
op.mt_count = 0; /* blockize = 0 (variable) */
rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc on set block size = %d\n",rc);
#if ((defined __NetBSD__) || defined (__FreeBSD__))
op.mt_op = MTSETDNSTY;
#else
op.mt_op = MTSETDENSITY;
#endif
op.mt_count = dens; /* 1600 BPI */
rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc on set density = %d\n",rc);
#if ((defined __NetBSD__) || defined (__FreeBSD__))
op.mt_op = MTCMPRESS;
#elif defined __linux__
op.mt_op = MTCOMPRESSION;
#endif
op.mt_count = 0; /* no compression */
rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc on set compression = %d\n",rc);
while ((ic = read(mt, buf, sizeof(buf))) >= 0) {
#if 1
fprintf(stdout, "len1 = %05d ", ic);
fflush(stdout);
op.mt_op = MTNOP;
op.mt_count = 0;
rc = ioctl(mt, MTIOCTOP, &op, sizeof(op));
printf("rc NOP ioctl = %d\n",rc);
#endif
blocks++;
if (ic == 0) {
zero += 1;
if (zero >= 2) { /* write trailing EOF's */
oc = 0;
for (ic = 0 ; ic < 2; ic++) { /* write 2 EOF markers */
if (fwrite(&oc, sizeof(oc), 1, tapfile) != 1) {
perror("fwrite eoi");
exit(1);
}
}
break;
}
} else {
zero = 0;
}
oc = to_intel(ic);
if (fwrite(&oc, sizeof(oc), 1, tapfile) != 1) {
perror("fwrite1");
exit(1);
}
if (ic > 0) {
if (fwrite(&buf, 1, ic, tapfile) != ic) {
perror("fwrite2");
exit(1);
}
#if 1
fprintf(stdout, "len2 = %05d\n", ic);
fflush(stdout);
#endif
if (fwrite(&oc, sizeof(oc), 1, tapfile) != 1) {
perror("fwrite3");
exit(1);
}
}
blocks++;
}
if (ic < 0) {
perror("Reading block");
#if 1
fprintf(stdout, "blocks = %05d\n", blocks);
fflush(stdout);
#endif
}
fclose(tapfile);
close(mt);
return(0);
}
#else
int main(int argc, char **argv)
{
printf("this program is not supported under a MsWindows OS\n");
return(0);
}
#endif
=========================================================
Gerard.
>How-To-Repeat:
create a few blocks and try the programs.
If I did miss somthtig , please tell me.
>Fix:
Unknown
Home |
Main Index |
Thread Index |
Old Index