Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 7 Sep 1997 10:30:22 +0200
From:      j@uriah.heep.sax.de (J Wunsch)
To:        hackers@FreeBSD.ORG
Cc:        handy@sag.space.lockheed.com (Brian N. Handy)
Subject:   Re: Tape question
Message-ID:  <19970907103022.YU02721@uriah.heep.sax.de>
In-Reply-To: <Pine.OSF.3.96.970902141656.16187M-100000@sag.space.lockheed.com>; from Brian N. Handy on Sep 2, 1997 14:19:30 -0700
References:  <Pine.OSF.3.96.970902141656.16187M-100000@sag.space.lockheed.com>

next in thread | previous in thread | raw e-mail | index | archive | help
As Brian N. Handy wrote:

> The problem is easily described:
> 
> - The Exabyte tapes to be read have a variable (logical) block size,
>   it typically is 8192 bytes, but often shorter.
> 
> - My original c program always attempted to read a 8192 byte block:
> 
>   nn = read(unit,buffer,8192);
> 
> - On the sun this worked, it would read one (logical) block, and
>   return the actual number of bytes read.
> 
> - In FreeBSD this created unpredictable results, if the logical block
>   was shorter than 8192.

This must be a problem with the Exabyte then.  It works fine for me,
with a Tandberg TDC4222, and a QIC-525 cartridge (QIC-150, of course,
doesn't work since it's fixed-length blocking).

Also, i know that restore(8) basically relies on this feature in order
to determine the tape block size.  ISTR that this once was broken, but
that's been quite some time ago.

Here's my test program:

#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int
main(int argc, char **argv) {
	size_t table[] = {512, 1024, 2048, 4096, 8192, 20480, 10240,
			15555, 33333, 0};
	int i, fd, mode;
	ssize_t rv;
	char buf[65536], obuf[65536];
	const char *op;
	ssize_t (*func)(int, void *, size_t);

	if (argc != 2) {
		fprintf(stderr, "usage: foo {read|write}\n");
		return 1;
	}
	if (strcmp(argv[1], "write") == 0) {
		mode = O_WRONLY;
		func = (ssize_t (*)(int, void *, size_t))write;
		op = "write()";
	} else {
		mode = O_RDONLY;
		func = read;
		op = "read()";
	}

	if ((fd = open("/dev/rst0", mode)) == -1) {
		fprintf(stderr, "open() failed\n");
		return 1;
	}

	for (i = 0; i < 65536; i++)
		obuf[i] = buf[i] = (char)random();

	for (i = 0; table[i]; i++) {
		size_t amnt = func == read? 65536: table[i];

		rv = func(fd, buf, amnt);

		if (rv == -1) {
			fprintf(stderr, "%s failed\n", op);
			return -1;
		}
		printf("%s returned %d out of %d\n", op, rv, amnt);
		if (func == read && memcmp(buf, obuf, rv))
			fprintf(stderr, "buffer fails comparision\n");
	}
	return 0;
}

And the results are:

j@uriah 1010% ./foo write
write() returned 512 out of 512
write() returned 1024 out of 1024
write() returned 2048 out of 2048
write() returned 4096 out of 4096
write() returned 8192 out of 8192
write() returned 20480 out of 20480
write() returned 10240 out of 10240
write() returned 15555 out of 15555
write() returned 33333 out of 33333
j@uriah 1011% ./foo read
read() returned 512 out of 65536
read() returned 1024 out of 65536
read() returned 2048 out of 65536
read() returned 4096 out of 65536
read() returned 8192 out of 65536
read() returned 20480 out of 65536
read() returned 10240 out of 65536
read() returned 15555 out of 65536
read() returned 33333 out of 65536

-- 
cheers, J"org

joerg_wunsch@uriah.heep.sax.de -- http://www.sax.de/~joerg/ -- NIC: JW11-RIPE
Never trust an operating system you don't have sources for. ;-)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19970907103022.YU02721>