Port-sparc archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Installation from a tape



Happy hacking in new year.

On Tue, 30 Dec 2025 13:17:13 +0900 (JST),
Nobuyoshi SATO <nobu-s%iwate-pu.ac.jp@localhost> wrote:

>>> Then, I booted my SS20 from the tape.  Kernel is successfully loaded
>>> and asked name of tape drive and place of tapefile2 and block size.
>> 
>>> Then I got errors as following:
>> 
>>> [198.2459840] st0: 4096-byte tape record too big for 4-byte user buffer
>>> [198.2609645] st0(esp0:0:4:0): Sense Key 0x00, info = -4092 (decimal), data = 00
>>>  00 00 00 00 00 00 00 00 00 00 00
>>> gzip: can't read stdin: Input/output error
>>> tar: End of archive volume 1 reached
>>> tar: Sorry, unable to determine archive format.
>> 
>> That looks to me like a bug in tar: when running gzip, it apparently
>> treats the input like an octet stream instead of a block stream,
>> breaking use on real tapes.  (At a guess, based on the above, it does
>> this by simply passing stdin to a forked gunzipper process.)
>> 
>> The _right_ fix of course is to fix that tar variant, so that it reads
>> the input itself when forking gunzip, so as to preserve the
>> stream-of-blocks paradigm.  But that's likely more work than you're
>> interested in getting into for this.
>> 
>> The next thing that comes to mind is to gunzip the file before writing
>> it to the tame, assuming of course that the uncompressed file fits on
>> the tape:
>> 
>> # gunzip < tapefile2 | dd obs=4k of=/dev/nrst0
>> 
>> Then drop the "gunzip the input" flag from tar (z? I don't know that
>> tar version; I normally use my own variant) when reading the tape.
> 
> This inference seems to be correct. It will be a bug in pax or
> its variant to create ramdisk image. Following Mouse's suggestion,
> I created yet another "gunzipped" tape and read it as following:
>     # dd if=tapefile1 of=/dev/nrst0 bs=4k conv=sync
>     # gunzip < tapefile2 | dd obs=4k of=/dev/nrst0 conv=sync
>     # mt rewind
>     # mt fsf 1
>     # /usr/obj/distrib/sparc/ramdisk/ramdiskbin tar tf /dev/nrst0 | more
>     .
>     ./bin
>     ./bin/cat
>     ./bin/chmod
>     ./bin/cp

So, quick and dirty fix is change executing tar with zip option at 
distrib/sparc/ramdisk/dotprofile from
    echo "Extracting installation utilities... "
    (cd $INSTFS_MP && tar $bsa -z -x -p -f $dev) || return 1
to without zip option
    echo "Extracting installation utilities... "
    (cd $INSTFS_MP && tar $bsa -x -p -f $dev) || return 1
and use "unzipped" tapefile2. It's OK, but untested yet.


>> The _right_ fix of course is to fix that tar variant, so that it reads
>> the input itself when forking gunzip, so as to preserve the
>> stream-of-blocks paradigm.  But that's likely more work than you're
> 
> I'll try to read source code of pax and gzip, but someone
> fixing the bug will be faster than I will find it...

To find out right fix, I added many fprintf(stderr, ...)s into
pax and gzip source codes and rebuilt ramdiskbin. And I checked
which part of the code causes the error, tested in "gzipped" tape:

# mt rewind
# mt fsf 1
# ./ramdiskbin tar ztf /dev/nrst0
pax invoked
ar_start_gzip(): gzp = gzip
XXX ramdiskbin gzip invoked
handle_stdin(): calling read_retry().
read_retry(): fd = 0, sz = 4
called and returned from read_retry().
gzip: can't read stdin: Input/output error
tar: End of archive volume 1 reached
tar: Sorry, unable to determine archive format.

As result, I found handle_stdin() in usr.bin/gzip/gzip.c is called
(it's OK, should be normal), and handle_stdin() calls read_retry(),
and read_retry() calls read() with 4 bytes buffer, and this triggers
the error:

static void
handle_stdin(void)
{
...
        fprintf(stderr, "handle_stdin(): calling read_retry().\n");
        bytes_read = read_retry(STDIN_FILENO, fourbytes, sizeof fourbytes);
        if (bytes_read == -1) {
                fprintf(stderr, "called and returned from read_retry().\n");
                maybe_warn("can't read stdin");
                goto out;
	}
...
}
...
static ssize_t
read_retry(int fd, void *buf, size_t sz)
{
        char *cp = buf;
        size_t left = MIN(sz, (size_t) SSIZE_MAX);

        fprintf(stderr, "read_retry(): fd = %d, sz = %d\n", fd, sz);
        while (left > 0) {
                ssize_t ret;

                ret = read(fd, cp, left);
	}
...
}

These codes seems to be normal behavior, and mostly similar
to other BSDs' codes.

If tape device had raw device such like disks (ex. /dev/rsd0 for
/dev/sd0), solution would be very easy.

According to manpage st(4), /dev/rst0 is "Mode 0, Rewind on close", 
however, in manpage mtio(4) describes:
     The raw device name is the block device name with an "r" prepended, e.g.
     /dev/rst0.

Hmm... This inconsistency that all device files of st(4) work
as only block device seems to be introduced some tens years
ago. Fixing st(4) so that it work with raw devices is correct way,
but quick and dirty fix above might be realistic solution
because capacities of tape cartridges might not be a problem
since they are at least 150MB for old Sun QIC tape drives.
(More older QIC-11 or QIC-24? size of base.tgz goes over the
capacity!)


Lecturer / Faculty of Software & Info. Sci., Iwate Prefectural Univ.
Nobuyoshi Sato, Ph.D / nobu-s%iwate-pu.ac.jp@localhost / +81-19-694-2612


Home | Main Index | Thread Index | Old Index