SCO 2.2.1 tar question

William E. Davidsen Jr davidsen at steinmetz.ge.com
Wed May 4 06:07:32 AEST 1988


Okay people, I mentioned that this has been posted to unix.src before,
but since there is so much interest in this, here is the program which
reads from stdin and writes multiple output media (be they disk, tape,
or whatever). Don't use buffer size > 30k, I suggest size = 1 cylinder
for best speed.

I suspect that most of the response came not from the original question,
but from the first flaming response.

#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
#	Run the following text with /bin/sh to create:
#	  bundle.1
#	  bundle.c
#	  unbundle.c
#
echo "x - extracting bundle.1 (Text)"
sed 's/^X//' << 'SHAR_EOF' > bundle.1 &&
X'\"  Copyright 1986,87 by Bill Davidsen. This code may be used for
X'\"  personal or commercial purposes. It may be freely distributed
X'\"  in source form providing this notice is kept intact.
X.TH bundle 1 Local
X'\" Heading: name(sect)    center (paren)    name(sect)
X.SH NAME
Xbundle \- buffer and copy \fIstdin\fR to a physicaql device
Xunbundle \- buffer and copy a physical device to \fIstdout\fR
X.SH SYNOPSIS
X\fBbundle\fR special dev_size buf_size
X.br
X\fBunbundle\fR special buf_size
X.SH DESCRIPTION
XThese programs allow a physical device to be the head or end of a pipe,
Xallows software which does not know about volumes to operate on
Xmulti-volume sets, and improves the performance of programs such as
X\fItar\fR and \fIcpio\fR.
X.P
X\fBSpecial\fR is the name of a raw device, such as /dev/rmt0.
X\fBdev_size\fR is the size of the device, given in bytes or kilobytes.
XWhen \fBdev_size\fR bytes have been written to the output device, the
Xoperator will be prompted for a media change. \fBBuf_size\fR is the size
Xof the buffer for the write or read. For tape this should be the desired
Xtape block size. For disk this should be a multiple of the size of a
Xtrack. For disk output writing a track at a time rather than sectors
Xcan reduce real time by a factor of three.
X.SH EXAMPLES
X  ls *.c | cpio -o | bundle /dev/rfp021 395k 5k
X  unbundle /dev/rfp021 5k | cpio -idm
X  tar cf - /usr/local | bundle /dev/rmt0 4000k 8k
X  unbundle /dev/rmt0 8k | tar cf -
X.SH WARNINGS
X\fIunbundle\fR reads to EOF on the input device. There is no way to read
Xonly part of a volume. If the \fBdev_size\fR is not a multiple of the
X\fBbuf_size\fR, bizarre errors may occur.
X.SH FILES
X/dev/\fBspecial\fR
X.SH SEE ALSO
Xtar, cpio.
X.SH AUTHOR
XBill Davidsen (ihnp4!chinet!crdos1!davidsen)
X'\" For more details, see man(7), as well as man(1), manroff(1), and mmt(1)
SHAR_EOF
chmod 0644 bundle.1 || echo "restore of bundle.1 fails"
echo "x - extracting bundle.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > bundle.c &&
X/*****************************************************************
X |  Program name:  bundle.c
X |----------------------------------------------------------------
X |  accept standard input and write to a device named on the command
X |  line. The total bytes on the device and the buffer size are
X |  given on the command line. When the device is full, prompt
X |  for a new medium in the device and continue.
X |
X |  Command form:
X |   bundle device Dsize Bsize
X |----------------------------------------------------------------
X |  Author: Bill Davidsen, 8/16/86
X |  Version 1.6
X |  Last modified: 3/6/87
X |----------------------------------------------------------------
X |  Copyright 1986,87 by Bill Davidsen. This code may be used for
X |  personal or commercial purposes. It may be freely distributed
X |  in source form providing this notice is kept intact.
X *****************************************************************/
X
X#include <stdio.h>
X
X#ifdef DEBUG
X#define debug(f,v) fprintf(stderr, f, v)
X#else
X#define debug(f,v)
X#endif
X
Xstatic char *SCCS = "@(#) bundle 1.6";
X
Xmain (argc, argv)
X    int  argc;
X    char *argv[];
X{
X    char *buffer,		/* i/o buffer */
X         *malloc ();
X    register  long left;	/* room left in the buffer */
X    long  bufsize, devsize;	/* buffer and device size */
X    long  devleft = 0;		/* room left on device */
X    int  istat,			/* stdin read status */
X         ostat,			/* device write status */
X         dev,			/* device name from open */
X         MediaNum = 1;		/* sequential media # */
X    FILE *tty, *fopen ();
X    long getsize ();		/* get size from argument */
X
X /* validate arguments */
X    if (argc != 4)
X    { /* invalid */
X	printf ("Format:\n bundle device DevSize BufSize\n");
X	printf ("Where size may be bytes (as 5120) or k (as 5k)\n");
X	exit (1);
X    }
X
X    devsize = getsize (argv[2]);
X    debug ("Device size %ld", devsize);
X    bufsize = getsize (argv[3]);
X    debug (", buffer size %ld\n", bufsize);
X    if (devsize < 1 || devsize < bufsize)
X    { /* invalid specification of size */
X	printf ("Invalid buffer and/or device size\n");
X	exit (1);
X    }
X
X /* open the terminal for prompt */
X    tty = fopen ("/dev/tty", "r");
X    if (tty == NULL)
X    { /* mystery failure */
X	printf ("Unable to open /dev/tty for prompt\n");
X	exit (1);
X    }
X
X /* open the buffer */
X    buffer = malloc (bufsize);
X    debug ("Buffer allocated\n", 0);
X    if (buffer == NULL)
X    { /* can't mallocate */
X	printf ("Can't allocate space for the buffer\n");
X	exit (1);
X    }
X
X /* see if you can open the device */
X    printf ("Mount media #1 on %s and press RETURN", argv[1]);
X    while (getc (tty) != '\n');
X    dev = open (argv[1], 1);
X    if (dev < 0)
X    { /* invalid name */
X	printf ("Can't access device %s\n", argv[1]);
X	exit (1);
X    }
X    devleft = devsize; /* set media ready */
X    debug ("Enter copy loop\n\n", 0);
X
X /* main copy loop */
X    while (istat = fread (buffer, 1, (int) bufsize, stdin))
X    { /* until EOF */
X	debug ("Input read size %d\n", istat);
X
X	if (devleft < istat)
X	{ /* change media */
X	    close (dev);
X	    printf ("\007Mount media #%d on %s and press RETURN: ",
X		    ++MediaNum, argv[1]);
X	    while (getc (tty) != '\n');
X	    dev = open (argv[1], 1);
X	    devleft = devsize;
X	}
X
X    /* write the buffer */
X	ostat = write (dev, buffer, bufsize);
X	debug ("Output write size %d\n", ostat);
X
X	if (bufsize != ostat)
X	{ /* error on write */
X	    printf ("Error on device write!\n");
X	    exit (1);
X	}
X	devleft -= ostat;
X    }
X}
X
X/*
X |  Procedure:  getsize
X |-
X |  Convert the size string to bytes. If the last character is
X |  'k', multiply by 1024
X */
X
Xlong
Xgetsize (string)
X    char *string;
X{
X    register long  len = strlen (string),
X                   val = atol (string);
X
X    if (string[len - 1] == 'k')
X	val *= 1024;
X
X    return val;
X}
SHAR_EOF
chmod 0444 bundle.c || echo "restore of bundle.c fails"
echo "x - extracting unbundle.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > unbundle.c &&
X/*****************************************************************
X |  Program: unbundle
X |    accept input from a device and write to stdout
X |----------------------------------------------------------------
X |  Arguments:
X |   1) device name
X |   2) block size in bytes or k
X |  Version: 1.6
X |  Last modified: 3/6/87
X |----------------------------------------------------------------
X |  Copyright 1986,87 by Bill Davidsen. This code may be used for
X |  personal or commercial purposes. It may be freely distributed
X |  in source form providing this notice is kept intact.
X ****************************************************************/
X
X#include <stdio.h>
X
X#ifdef DEBUG
X#define debug(f,v) fprintf(stderr, f, v)
X#else
X#define debug(f,v)
X#endif
Xmain (argc, argv)
X    int  argc;
X    char *argv[];
X{
X    char *buf, *malloc ();
X    int  bufsize, dn, mnum = 1, ch, readsize;
X    static char *SCCSid = "@(#)unbundle 1.6";
X    long getsize ();		/* size of buffer */
X
X    if (argc != 3)
X    { /* bad calling sequence */
X	fprintf (stderr, "%s: wrong # of arguments\n", argv[0]);
X        fprintf (stderr, "Calling seq:\n  %s device bufsize\n", 
X                argv[0]);
X	exit (1);
X    }
X
X /* try to open the device */
X    dn = open (argv[1], 0);
X    if (dn < 0)
X    { /* open failed */
X	fprintf (stderr, "%s: can't open device %s\n", argv[0], argv[1]);
X	exit (1);
X    }
X    close (dn); /* so I can reopen */
X
X /* allocate the buffer */
X    bufsize = getsize (argv[2]);
X    debug ("Bufsize: %d\n", bufsize);
X
X    buf = malloc (bufsize);
X    if (buf == NULL)
X    { /* can't allocate the buffer */
X	fprintf (stderr, "Can't allocate %d byte buffer\n", bufsize);
X	exit (1);
X    }
X
X    for (;;)
X    { /* get a fresh mount and read it */
X	fprintf (stderr, "Mount input medium #%d on %s and press return: ",
X		mnum++, argv[1]);
X	read (0, &ch, 1);
X	open (argv[1], 0);
X
X	while (readsize = read (dn, buf, bufsize))
X	    write (1, buf, readsize);
X	close (dn);
X    }
X}
X
X/*
X |  Procedure:  getsize
X |-
X |  Convert the size string to bytes. If the last character is
X |  'k', multiply by 1024
X */
X
Xlong
Xgetsize (string)
X    char *string;
X{
X    register long  len = strlen (string),
X                   val = atol (string);
X
X    if (string[len - 1] == 'k')
X	val *= 1024;
X
X    return val;
X}
X
SHAR_EOF
chmod 0444 unbundle.c || echo "restore of unbundle.c fails"
exit 0

I wrote this because I needed it myself, hopefully it will be useful to
others.
-- 
	bill davidsen		(wedu at ge-crd.arpa)
  {uunet | philabs | seismo}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me



More information about the Comp.unix.xenix mailing list