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