rs@uunet.UU.NET (Rich Salz) (08/14/87)
Submitted-by: <steinmetz!crdos1!davidsen> Posting-number: Volume 11, Issue 9 Archive-name: bundle These programs allow a physical device to be the head or end of a pipe, allowing software which does not know about volumes to operate on multi-volume sets, and improving the performance of programs such as tar and cpio. It works on systems with 16 bit ints such as PC/IX, Xenix, and Microport. bill davidsen (davidsen@ge-crd.ARPA) ihnp4!seismo!rochester!steinmetz! \ chinet! ->--- crdos1!davidsen [ Another spliced-in Makefile. --r$ ] #!/bin/sh # shar+ created from directory /usr2/davidsen echo 'x - bundle.1 (text)' sed << 'E!O!F' 's/^X//' > 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) E!O!F newsize=`wc -c < bundle.1` if [ $newsize -ne 1832 ] then echo "File bundle.1 was $newsize bytes, 1832 expected" fi echo 'x - bundle.c (text)' sed << 'E!O!F' 's/^X//' > 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} E!O!F newsize=`wc -c < bundle.c` if [ $newsize -ne 3803 ] then echo "File bundle.c was $newsize bytes, 3803 expected" fi echo 'x - unbundle.c (text)' sed << 'E!O!F' 's/^X//' > 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 E!O!F newsize=`wc -c < unbundle.c` if [ $newsize -ne 2271 ] then echo "File unbundle.c was $newsize bytes, 2271 expected" fi echo x - Makefile sed -e 's/^X// >Makefile <\SHAR_EOF #all: bundle unbundle #bundle: bundle.c # $(CC) -o bundle $(CFLAGS) bundle.c #unbundle: unbundle.c # $(CC) -o unbundle $(CFLAGS) unbundle.c #install: all bundle.c # @echo Copy programs and manpage to appropriate directories SHAR_EOF echo No error check, lazy moderator... -- Rich $alz Cronus Project, BBN Labs rsalz@bbn.com Moderator, comp.sources.unix sources@uunet.uu.net