home *** CD-ROM | disk | FTP | other *** search
Text File | 1986-11-30 | 23.2 KB | 1,076 lines |
- Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site mirror.UUCP
- Path: mirror!cca!decvax!genrad!panda!husc6!seismo!munnari!sources-request
- From: sources-request@munnari.UUCP
- Newsgroups: mod.sources
- Subject: v07i13: Multivol V1.00 - multivolume backup utility, part02/02
- Message-ID: <1231@munnari.OZ>
- Date: 29 Aug 86 15:30:36 GMT
- Date-Received: 2 Sep 86 20:59:29 GMT
- Sender: kre@munnari.OZ
- Lines: 1063
- Approved: kre@munnari.oz
-
- Submitted-by: Tony O'Hagan <tony%uqcspe.oz@seismo.css.gov>
- Mod.sources: Volume 17, Issue 13
- Archive-name: multivol
-
- # this is a shell archive, extract with sh, not csh
- echo x - "ask.c" 2>&1
- sed "s/^X//" >"ask.c" <<'!The!End!'
- X#include <stdio.h>
- X#define bool short
- X#define TRUE 1
- X#define FALSE 0
- X
- Xchar *
- Xask(prompt)
- X char *prompt;
- X{
- X static char ans[256];
- X static bool ttyclosed = TRUE;
- X static FILE *tty;
- X
- X if (ttyclosed)
- X if ((tty = fopen("/dev/tty", "r")) == NULL) {
- X perror("/dev/tty");
- X exit(1);
- X } else
- X ttyclosed = FALSE;
- X
- X fprintf(stderr, prompt);
- X fgets(ans, sizeof(ans), tty);
- X /* fclose(tty); */
- X return ans;
- X}
- X
- X/* VARARGS1 */
- Xchar *
- Xaskf(format, val1, val2, val3, val4)
- X char *format;
- X int val1, val2, val3, val4;
- X{
- X char prompt[80];
- X
- X sprintf(prompt, format, val1, val2, val3, val4);
- X return ask(prompt);
- X}
- X
- Xbool
- Xy_or_n(prompt)
- X char *prompt;
- X{
- X char *ans;
- X bool yes, no;
- X
- X char *ask();
- X
- X do {
- X ans = ask(prompt);
- X no = ans[1] == '\n' && (ans[0] == 'n' || ans[0] == 'N' );
- X yes = ans[1] == '\n' && (ans[0] == 'y' || ans[0] == 'Y' );
- X } while (! (yes || no) );
- X return(yes);
- X}
- !The!End!
-
- echo x - "bcopy.c" 2>&1
- sed "s/^X//" >"bcopy.c" <<'!The!End!'
- X#ifdef vax
- Xbcopy(from, to, len)
- X char *from, *to;
- X int len;
- X{
- X asm(" movc3 12(ap),*4(ap),*8(ap)");
- X}
- X#else
- X#ifdef SYSV
- X/*
- X * Added by moderator, bcopy.c for Sys V.
- X *
- X */
- X
- Xextern char *memcpy();
- X
- Xchar *
- Xbcopy(from, to, count)
- X char *from;
- X char *to;
- X int count;
- X{
- X return (memcpy(to, from, count));
- X}
- X#else
- Xbcopy(from, to, len)
- X register char *to, *from;
- X register int len;
- X{
- X if (from > to) {
- X while(len--)
- X *to++ = *from++;
- X } else { /* not handled in standard version of bcopy() */
- X to += len;
- X from += len;
- X while(len--)
- X *--to = *--from;
- X }
- X}
- X#endif
- X#endif
- !The!End!
-
- echo x - "error.c" 2>&1
- sed "s/^X//" >"error.c" <<'!The!End!'
- X#include <stdio.h>
- X extern int errno;
- X extern char *O_name;
- X/*VARARGS1*/
- Xfatal(fmt, arg1, arg2, arg3)
- X char *fmt;
- X int arg1, arg2, arg3;
- X{
- X warning(fmt, arg1, arg2, arg3);
- X#ifdef DEBUG
- X abort();
- X#else
- X exit(1);
- X#endif
- X}
- X
- Xsfatal(str)
- X char *str;
- X{
- X swarning(str);
- X#ifdef DEBUG
- X abort();
- X#else
- X exit(1);
- X#endif
- X}
- X
- X/*VARARGS1*/
- Xwarning(fmt, arg1, arg2, arg3)
- X char *fmt;
- X int arg1, arg2, arg3;
- X{
- X fprintf(stderr, "%s: ", O_name);
- X fprintf(stderr, fmt, arg1, arg2, arg3);
- X fprintf(stderr, "\n");
- X}
- X
- Xswarning(str)
- X char *str;
- X{
- X#ifdef DEBUG
- X fprintf(stderr, "(%d) ", errno);
- X#endif
- X fprintf(stderr, "%s: ", O_name);
- X perror(str);
- X}
- !The!End!
-
- echo x - "mount.c" 2>&1
- sed "s/^X//" >"mount.c" <<'!The!End!'
- X/* multivol V1.00 5-Jun-85 Tony O'Hagan
- X * multivol (8) - handle multivolume files
- X * wrvols() - function of multivol main()
- X */
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X
- X#include "multivol.h"
- X
- X/* Globals */
- X extern bool dsp_vols, vfy_vols, rd_flag, wr_flag;
- X extern char *label;
- X
- Xup_vhdr *
- Xmount_vol(vol_nam, vol_num, timestamp)
- X /* returns header read on mounted volume */
- X char *vol_nam;
- X int vol_num;
- X long timestamp;
- X{
- X up_vhdr *upvh; /* returned value */
- X bool ok;
- X
- X bool vol_ok();
- X void print_vhdr();
- X bool y_or_n();
- X up_vhdr *rd_vhdr();
- X char *askf();
- X#ifdef REWIND
- X char *ask();
- X#endif
- X
- X tracef((tr, "+ mount_vol(%s, %d, %ld)", vol_nam, vol_num, timestamp));
- X
- X do {
- X askf("Mount volume #%d and type <return> ", vol_num);
- X
- X if (rd_flag || dsp_vols || vfy_vols)
- X upvh = rd_vhdr(vol_nam); /* Read volume header */
- X else {
- X upvh = NULVHD;
- X trace("goto no_vhdr");
- X goto no_vhdr; /* no volume header was read */
- X }
- X
- X if (upvh == NULVHD) {
- X ok = !rd_flag; /* ok unless attempting to read volume */
- X } else {
- X if (dsp_vols || vfy_vols) {
- X /* Print header & check correct volume is read/overwritten */
- X putc('\n', stderr);
- X print_vhdr(upvh);
- X putc('\n', stderr);
- X }
- X ok = vol_ok(upvh, vol_num, timestamp);
- X }
- X tracef((tr, "vfy_vols=%d, ok=%d upvh=x%x", vfy_vols, ok, upvh));
- X } while ( (vfy_vols || !ok) && y_or_n("Remount required [y/n] ? ") );
- X
- X#ifdef REWIND
- X ask("Ensure volume is rewound and type <return> ");
- X#endif
- X
- Xno_vhdr:
- X trace("- mount_vol()");
- X return(upvh);
- X}
- X
- Xbool
- Xvol_ok(upvh, vol_num, timestamp)
- Xup_vhdr *upvh;
- X int vol_num;
- X long timestamp;
- X/* Check correct volume is mounted
- X * vol_num = volume no. expected on this volume
- X * timestamp = timestamp on volumes being written
- X * upvh = unpacked volume header on volume about to be read/overwritten.
- X */
- X{
- X bool ok = TRUE; /* returns ok */
- X static up_vhdr up_1st; /* first volume header read */
- X
- X trace("+ vol_ok()");
- X if (wr_flag) { /* if writing volumes */
- X if (timestamp == upvh->up_timestamp) {
- X fprintf(stderr,
- X "** This clobbers a volume just written !\n");
- X ok = FALSE;
- X }
- X } else if (rd_flag) { /* if reading volumes */
- X if (vol_num == 1) { /* record header of first volume */
- X bcopy((char *)upvh, (char *)&up_1st, sizeof(up_vhdr));
- X if (label != NULL &&strcmp(label, upvh->up_label) != 0){
- X fprintf(stderr, "** Label does not match\n");
- X ok = FALSE;
- X }
- X }
- X if (vol_num >= 2 && up_1st.up_timestamp != upvh->up_timestamp) {
- X fprintf(stderr, "** Volume not part of volume set\n");
- X ok = FALSE;
- X } else if (upvh->up_vol_num != vol_num) {
- X fprintf(stderr, "** Volume no. out of sequence\n");
- X ok = FALSE;
- X }
- X }
- X trace("- vol_ok()");
- X return(ok);
- X}
- !The!End!
-
- echo x - "multivol.c" 2>&1
- sed "s/^X//" >"multivol.c" <<'!The!End!'
- X/* multivol V1.00 5-Jun-85 Tony O'Hagan
- X * multivol (8) - handle multivolume files
- X * multivol [-i] [-o] [-v] [-w] [-t] [-b blocksize]
- X * [-n blocks-per-vol] [-l label] [device]
- X * Source files:
- X * ask.c bcopy.c error.c mount.c multivol.c rd.c testdata.c trace.c vhdr.c wr.c
- X * multivol.h options.h trace.h
- X * Other files:
- X * Makefile READ_ME multivol.8 testdata.c
- X */
- X#include <stdio.h>
- X#include <ctype.h>
- X#include "options.h"
- X#include "multivol.h"
- X
- X#define ACCREAD 4
- X#define ACCWRIT 2
- X
- X#ifndef DEFBSIZ
- X# include <sys/param.h>
- X# undef bcopy
- X# define DEFBSIZ BSIZE /* default block size */
- X#endif
- X
- X#ifndef DEFBLIM
- X# define DEFBLIM NOLIMIT /* default block limit (no. per volume) */
- X#endif
- X
- X#define DEFLABEL "no_label" /* Default label */
- X
- X#ifndef DEFDEV /* may be cc -DDEFDEV= */
- X# define DEFDEV "/dev/multivol"
- X#endif
- X
- X/* Globals */
- X export char *prog_name, *label = DEFLABEL, *device = DEFDEV;
- X export bool dsp_blks, dsp_vols, vfy_vols, rd_flag , wr_flag;
- X export long blk_lim = DEFBLIM;
- X export long blk_siz = DEFBSIZ;
- X
- Xvoid
- Xmain(argc, argv) /* multivol main() */
- X int argc;
- X char *argv[];
- X{
- X char *bsizstr;
- X up_vhdr *upvh;
- X
- X void rd_vols(), wrvols(), print_vhdr();
- X up_vhdr *rd_vhdr();
- X long kval(), atol();
- X char *vol_file();
- X int t_int;
- X bool y_or_n();
- X
- X trace( "+ main()");
- X
- X rd_flag = wr_flag = dsp_vols = dsp_blks = vfy_vols = FALSE;
- X OPTIONS ("[-i] [-o] [-v] [-w] [-t] [-b blocksize] [-n blocks-per-vol] [-l label] [device]")
- X FLAG ('i', rd_flag)
- X#ifdef DEBUG
- X FLAG ('D', tron)
- X#endif
- X FLAG ('o', wr_flag)
- X FLAG ('t', dsp_vols)
- X FLAG ('v', dsp_blks)
- X FLAG ('w', vfy_vols)
- X STRING ('b', bsizstr)
- X if ((blk_siz = kval(bsizstr)) == -1)
- X fatal("** Illegal block size %s", bsizstr);
- X else if (blk_siz < MINBLK)
- X fatal("** Minimum block size is %d", MINBLK);
- X else { /* test if blk_siz value fits in int */
- X t_int = blk_siz;
- X if (blk_siz != t_int)
- X fatal("** Block size too big");
- X }
- X NUMBER ('n', blk_lim)
- X STRING ('l', label)
- X if (index(label, ' ') != 0)
- X fatal("** Label must not contain white space");
- X ENDOPTS
- X prog_name = argv[0];
- X if (argc > 1)
- X device = argv[1];
- X
- X tracef((tr, "BHDSIZ = %d VHDSIZ = %d", BHDSIZ, VHDSIZ));
- X tracef((tr, "prog_name:%s label:%s blk_siz:%ld",
- X prog_name, label, blk_siz));
- X tracef((tr, "blk_lim:%ld dsp_blks:%d dsp_vols:%d vfy_vols:%d",
- X blk_lim, dsp_blks, dsp_vols, vfy_vols));
- X
- X if (rd_flag && wr_flag)
- X fatal("** Only -i or -o may be specified");
- X else if (rd_flag) {
- X if (access(device, ACCREAD) == -1)
- X sfatal(device);
- X rd_vols();
- X } else if (wr_flag) {
- X if (access(device, ACCREAD & ACCWRIT) == -1)
- X sfatal(device);
- X wrvols();
- X } else {
- X /* Print details of volume header */
- X /* Note: No prompt to mount volume */
- X if (access(device, ACCREAD) == -1)
- X sfatal(device);
- X if ((upvh = rd_vhdr(vol_file(device, 1))) != NULVHD)
- X print_vhdr(upvh);
- X }
- X
- X trace("- main()");
- X exit(0);
- X}
- X
- Xlong
- Xkval(kstr)
- X char *kstr;
- X{
- X long n, atol(); /* return n */
- X char c;
- X
- X trace("+ kstr()");
- X n = atol(kstr);
- X c = kstr[strlen(kstr)-1];
- X if (! isdigit(c)) {
- X switch (c) {
- X case 'b':case 'B':
- X n *= 512; break;
- X case 'k':case 'K':
- X n *= 1024; break;
- X /* case 'm':case 'M':
- X n *= 1024*1024; break; */
- X default:
- X n = -1;
- X }
- X }
- X trace("- kstr()");
- X return(n);
- X}
- !The!End!
-
- echo x - "rd.c" 2>&1
- sed "s/^X//" >"rd.c" <<'!The!End!'
- X/* multivol(8) V1.00 5-Jun-85 Tony O'Hagan
- X * Handles multivolume files
- X */
- X#include <stdio.h>
- X#include "multivol.h"
- X
- X/* Globals */
- X extern char *label, *device;
- X extern long blk_lim;
- X extern long blk_siz;
- X
- X /* TRUE when block containing ENDBLK block type has been read */
- X static bool END_read;
- X static long blk_num;
- X
- Xvoid
- Xrd_vols()
- X{
- X char *dta_ptr;
- X long dta_got;
- X
- X void show_blks();
- X long rd_get_dta(), rd_put_dta();
- X
- X trace("+ rd_vols()");
- X
- X END_read = FALSE;
- X do {
- X dta_got = rd_get_dta(&dta_ptr);
- X tracef((tr, "dta_got = %ld", dta_got));
- X if (dta_got > 0L)
- X rd_put_dta(dta_ptr, dta_got);
- X } while (!END_read);
- X
- X show_blks(-1L); /* terminate display of blocks */
- X trace("- rd_vols()");
- X return;
- X}
- X
- Xlong
- Xrd_put_dta(dta_ptr, dta_len)
- X char *dta_ptr;
- X long dta_len;
- X{
- X long n_writ;
- X trace("+ rd_put_dta()");
- X
- X if ((n_writ = write(fileno(stdout), dta_ptr, (int)dta_len)) == -1L) {
- X n_writ = 0L;
- X swarning("stdout");
- X } else if (n_writ < dta_len)
- X warning("** Only output %ld bytes of %ld bytes in block #%ld",
- X n_writ, dta_len, blk_num);
- X
- X tracef((tr, "- rd_put_dta() n_writ = %ld", n_writ));
- X return n_writ ;
- X}
- X
- X/* Controls when volumes require mounting and
- X * allocates buffer space for the 1st volume.
- X */
- Xlong
- Xrd_get_dta(dta_ptr)
- X char **dta_ptr;
- X{
- X void show_blks();
- X long rd_blk();
- X char *new_buf(), *vol_file();
- X up_vhdr *mount_vol();
- X
- X char *vol_nam;
- X long n_read;
- X up_vhdr *upvh;
- X
- X static char *blk_ptr;
- X static int dev, vol_num = 0;
- X static bool new_vol = TRUE;
- X
- X tracef((tr, "+ rd_get_dta(%x)", *dta_ptr));
- X
- X if (new_vol) {
- X blk_num = 0L;
- X new_vol = FALSE;
- X vol_nam = vol_file(device, ++vol_num);
- X if (vol_num > 1) {
- X show_blks(-1L);
- X trace("close");
- X close(dev); /* Last volume is closed by exit() */
- X }
- X if ((upvh = mount_vol(vol_nam, vol_num, 0L )) == NULVHD) {
- X END_read = TRUE;
- X trace("- rd_get_dta()");
- X return 0L;
- X }
- X
- X trace("set blk_siz & blk_lim from vol header");
- X blk_siz = upvh->up_siz_blk;
- X blk_lim = upvh->up_lim_blk;
- X
- X if (vol_num == 1) {
- X blk_ptr = new_buf(blk_siz + VHDSIZ);
- X }
- X
- X if ((dev = open(vol_nam, READ)) == -1)
- X sfatal(vol_nam);
- X
- X /* setup pointer to data in block */
- X *dta_ptr = blk_ptr + BHDSIZ + VHDSIZ;
- X } else
- X *dta_ptr = blk_ptr + BHDSIZ;
- X
- X if ((n_read = rd_blk(dev, blk_ptr)) == 0L) {
- X /* Couldn't read last block on current volume */
- X new_vol = TRUE;
- X if (blk_lim != NOLIMIT && !END_read)
- X fprintf(stderr,
- X "** Could only read %ld blocks on volume", blk_num);
- X trace("- rd_get_dta()");
- X return 0L ;
- X } else {
- X if (blk_lim != NOLIMIT && blk_num >= blk_lim)
- X new_vol = TRUE;
- X trace("- rd_get_dta()");
- X /* return amount of data written (excl. headers - See diag.) */
- X return(n_read - (*dta_ptr - blk_ptr));
- X }
- X}
- X
- Xlong
- Xrd_blk(dev, blk_ptr)
- X int dev;
- X char *blk_ptr;
- X#define bh_ptr ((blk_hdr *) blk_ptr)
- X{
- X int chk_sum;
- X char xor_sum();
- X long blk_len, n_read;
- X
- X trace("+ rd_blk()");
- X n_read = read(dev, blk_ptr, (int)blk_siz);
- X if (n_read == blk_siz) {
- X show_blks(++blk_num);
- X } else {
- X if (n_read == -1L)
- X swarning(device);
- X else
- X warning("** Block #%ld is only %ld bytes",
- X blk_num+1, n_read);
- X /* END_read = TRUE; - abort gracefully */
- X trace("- rd_blk()");
- X return 0L ;
- X }
- X
- X END_read = bh_ptr->bh_blktyp == ENDBLK;
- X
- X sscanf(bh_ptr->bh_dtalen, "%6ld", &blk_len);
- X tracef((tr, "blk_len = %ld", blk_len));
- X
- X /* Calc. checksum */
- X if (chk_sum = xor_sum(blk_ptr, blk_siz) != '\0')
- X warning("** Block #%ld check sum error (sum = %x hex)\n",
- X blk_num, chk_sum);
- X
- X trace("- rd_blk()");
- X return(blk_len);
- X}
- !The!End!
-
- echo x - "testdata.c" 2>&1
- sed "s/^X//" >"testdata.c" <<'!The!End!'
- X#include <stdio.h>
- Xmain(argc, argv) /* garbo main() */
- X int argc;
- X char *argv[];
- X{
- X long atol();
- X register long j;
- X register char *str;
- X register int no_eoln, i;
- X
- X if (no_eoln = (*argv[1] == '-' && *++argv[1] == 'n')) {
- X argv++;
- X argc--;
- X }
- X for (i = 1; i < argc; i += 2) {
- X str = argv[i+1];
- X for (j = atol(argv[i]); j--; ) {
- X printf("%s", str);
- X if (!no_eoln)
- X putc('\n', stdout);
- X }
- X }
- X}
- !The!End!
-
- echo x - "trace.c" 2>&1
- sed "s/^X//" >"trace.c" <<'!The!End!'
- X#ifdef DEBUG /* Only used if DEBUG is defined */
- X#include <stdio.h>
- X int tron; /* global = trace on */
- X char tr[160];
- X
- Xstrace(file, line, step)
- X char *file, *step;
- X int line;
- X{
- X static int indent = 0;
- X register i;
- X
- X if (*step == '-')
- X indent--;
- X if (tron) {
- X fprintf(stderr, "%14s: %5d: ", file, line);
- X for (i = indent; i--; )
- X fprintf(stderr, ". ");
- X fprintf(stderr, "%s\n", step);
- X }
- X if (*step == '+')
- X indent++;
- X}
- X#endif
- !The!End!
-
- echo x - "vhdr.c" 2>&1
- sed "s/^X//" >"vhdr.c" <<'!The!End!'
- X/* multivol V1.00 5-Jun-85 Tony O'Hagan
- X * multivol (8) - handle multivolume files
- X * vhdr.c - functions performed on volume header
- X */
- X#include <stdio.h>
- X#include "multivol.h"
- X
- X extern long blk_siz, blk_lim;
- X extern char *label;
- X
- Xup_vhdr *
- Xrd_vhdr(devname)
- X char *devname;
- X/* Read volume header from the first block and rewind (close()) the volume */
- X{
- X up_vhdr *ans;
- X int dev;
- X int n_read;
- X char *blk;
- X
- X char *new_buf();
- X up_vhdr *unpack_vhdr();
- X void free();
- X
- X tracef((tr, "+ rd_vhdr(%s)", devname));
- X if ((dev = open(devname, READ)) == -1) {
- X swarning(devname);
- X trace("- rd_vhdr()");
- X return(NULVHD);
- X }
- X
- X blk = new_buf(blk_siz);
- X trace("reading volume header");
- X
- X tracef((tr, "read(%d, %x, %d)", dev, blk, (int)blk_siz));
- X if ((n_read = read(dev, blk, (int)blk_siz) ) == -1) {
- X swarning(devname);
- X ans = NULVHD;
- X } else {
- X if (n_read == 0) {
- X fprintf(stderr, "** No header found on volume\n");
- X ans = NULVHD;
- X } else if (n_read < MINBLK) {
- X fprintf(stderr,
- X "** Header block is only %d bytes\n", n_read);
- X ans = NULVHD;
- X } else { /* vol_hdr after blk_hdr */
- X tracef((tr, "blk+BHDSIZ = %x",
- X (vol_hdr *)(blk + BHDSIZ)));
- X if (NULVHD ==
- X (ans = unpack_vhdr((vol_hdr *)(blk + BHDSIZ))) )
- X fprintf(stderr, "** Invalid volume header\n");
- X }
- X }
- X close(dev);
- X trace("free(blk)");
- X free(blk);
- X trace("- rd_vhdr()");
- X return ans ;
- X}
- X
- Xvoid
- Xprint_vhdr(up)
- X up_vhdr *up;
- X/* Print volume header details */
- X{
- X#ifndef time_t
- X# include <sys/types.h>
- X#endif
- X char *ctime();
- X time_t t_stamp;
- X
- X trace("+print_vhdr()");
- X t_stamp = (time_t) up->up_timestamp;
- X
- X /* Note: ctime() returns date & time with a \n following */
- X fprintf(stderr,
- X "Written using: %s V%s Label: %s %s", up->up_prog_name,
- X up->up_version, up->up_label, ctime(&t_stamp) );
- X fprintf(stderr,
- X "Vol. no.: %d Block size: %ld Blocks per volume: %ld\n",
- X up->up_vol_num, up->up_siz_blk, up->up_lim_blk);
- X
- X trace("-print_vhdr()");
- X}
- X
- Xvoid
- Xpack_vhdr(pk, vol_num, timestamp)
- X char *pk;
- X int vol_num;
- X long timestamp;
- X{
- X sprintf(pk, VHDPACK,
- X vol_num, PROGNAM, VERSION, label, timestamp, blk_siz, blk_lim);
- X}
- X
- Xup_vhdr *
- Xunpack_vhdr(pk)
- X vol_hdr *pk;
- X{
- X static up_vhdr up;
- X
- X tracef((tr, "+ unpack_vhdr(pk = %x)", pk));
- X if(VHDFIELDS == sscanf((char *)pk, VHDUNPACK,
- X &up.up_vol_num, up.up_prog_name, up.up_version,
- X up.up_label, &up.up_timestamp, &up.up_siz_blk, &up.up_lim_blk)) {
- X trace("- unpack_vhdr");
- X return &up;
- X } else {
- X trace("- unpack_vhdr = NULVHD");
- X return NULVHD;
- X }
- X}
- !The!End!
-
- echo x - "wr.c" 2>&1
- sed "s/^X//" >"wr.c" <<'!The!End!'
- X/* multivol(8) V1.00 5-Jun-85 Tony O'Hagan */
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <errno.h>
- X extern int errno;
- X
- X#include "multivol.h"
- X
- X/* Globals */
- X extern bool dsp_blks;
- X extern char *label, *device;
- X extern long blk_lim;
- X extern long blk_siz;
- X
- X /* TRUE when ENDBLK block type has been written */
- X static bool END_written;
- X static long blk_num;
- X
- Xvoid
- Xwrvols()
- X{
- X char *buf_ptr, *dta_ptr;
- X long usu_dta, dta_left, dta_put;
- X
- X void bcopy(), show_blks();
- X char *new_buf();
- X long wr_get_dta(), wr_put_dta();
- X
- X trace("+ wrvols()");
- X
- X buf_ptr = new_buf(blk_siz+VHDSIZ);
- X
- X dta_left = 0L;
- X END_written = FALSE;
- X dta_ptr = buf_ptr + BHDSIZ + VHDSIZ; /* See diag. of buffer */
- X usu_dta = blk_siz - BHDSIZ; /* usual amount of data per block */
- X
- X while ( TRUE ) {
- X /* Attempt to fill up data buffer to 'usu_dta' chars &
- X append new data after data left over */
- X dta_left += wr_get_dta(dta_ptr + dta_left, usu_dta - dta_left);
- X tracef((tr, "after wr_get_dta dta_left = %ld", dta_left));
- X
- X if (dta_left <= 0L && END_written)
- X break;
- X
- X /* Attempt to dispose of whatever is in data buffer */
- X dta_left -= (dta_put = wr_put_dta(dta_ptr, dta_left));
- X tracef((tr, "after wr_put_dta dta_left = %ld", dta_left));
- X
- X /* if any left, copy to top of data buffer */
- X if (dta_left > 0L && dta_put > 0L)
- X bcopy(dta_ptr + dta_put, dta_ptr, (int)dta_left);
- X }
- X show_blks(-1L); /* terminate display of blocks */
- X if (dsp_blks)
- X fprintf(stderr, "%ld blocks on last volume", blk_num);
- X trace("- wrvols()");
- X}
- X
- Xlong
- Xwr_get_dta(dta_ptr, dta_req)
- X char *dta_ptr;
- X long dta_req;
- X{
- X long n_read, tot_read;
- X
- X tracef((tr, "+ wr_get_dta(%x, %ld)", dta_ptr, dta_req));
- X
- X /* Get at least the required amount of data */
- X for (tot_read = 0L; tot_read < dta_req; tot_read += n_read) {
- X n_read = read(fileno(stdin),
- X dta_ptr + tot_read, (int)(dta_req - tot_read));
- X tracef((tr, "n_read = %ld", n_read));
- X if (n_read == -1) {
- X n_read = 0L;
- X swarning("stdin");
- X }
- X if (n_read == 0L)
- X break;
- X }
- X
- X tracef((tr, "- wr_get_dta() tot_read = %ld", tot_read));
- X return tot_read ;
- X}
- X
- X/* Controls when volumes require mounting */
- Xlong
- Xwr_put_dta(dta_ptr, dta_len)
- X char *dta_ptr;
- X long dta_len;
- X{
- X void wr_vol(), show_blks();
- X char *blk_ptr;
- X long wr_blk(), n_writ, blk_len;
- X
- X static int dev;
- X static bool new_vol = TRUE;
- X
- X tracef((tr, "+ wr_put_dta(%x, %ld)", dta_ptr, dta_len));
- X
- X blk_ptr = dta_ptr;
- X blk_len = dta_len;
- X
- X if (new_vol) {
- X blk_ptr -= VHDSIZ;
- X blk_len += VHDSIZ;
- X /* mount next volume & pre-pend volume header to data buffer */
- X wr_vol(&dev, blk_ptr);
- X blk_num = 0L;
- X new_vol = FALSE;
- X }
- X
- X blk_ptr -= BHDSIZ;
- X blk_len += BHDSIZ;
- X if ((n_writ = wr_blk(dev, blk_ptr, blk_len)) == 0L) {
- X /* last block won't fit on current volume */
- X new_vol = TRUE;
- X if (blk_lim != NOLIMIT)
- X fprintf(stderr,
- X "\n** Could only fit %ld block(s) on volume\n",blk_num);
- X trace("- wr_put_dta()");
- X return(0L);
- X } else {
- X show_blks(++blk_num);
- X /* test volume block limit */
- X if (blk_lim != NOLIMIT && blk_num >= blk_lim)
- X new_vol = TRUE;
- X /* return amount of data written (excl. headers - See diag.) */
- X trace("- wr_put_dta()");
- X return(n_writ - (dta_ptr - blk_ptr));
- X }
- X}
- X
- Xlong
- Xwr_blk(dev, blk_ptr, blk_len)
- X int dev;
- X char *blk_ptr;
- X long blk_len;
- X{
- X#define BSZDIG 6 /* number of digits for block size string */
- X
- X char len_str[BSZDIG+1];
- X char xor_sum(), *strncpy();
- X blk_hdr *bhd_ptr;
- X long n_writ, nulls;
- X
- X tracef((tr, "+ wr_blk(%d, %x, %ld)", dev, blk_ptr, blk_len));
- X
- X if (blk_len > blk_siz)
- X blk_len = blk_siz; /* write at most blk_siz chars */
- X
- X bhd_ptr = (blk_hdr *) blk_ptr;
- X
- X sprintf(len_str, "%6ld", blk_len);
- X strncpy(bhd_ptr->bh_dtalen, len_str, BSZDIG);
- X
- X if (blk_len < blk_siz) {
- X /* move nulls to end of last block of last volume */
- X register char *p;
- X nulls = blk_siz - blk_len;
- X p = blk_ptr + blk_len;
- X while (blk_len++ < blk_siz)
- X *p++ = '\0';
- X bhd_ptr->bh_blktyp = ENDBLK;
- X END_written = TRUE;
- X } else {
- X nulls = 0L;
- X bhd_ptr->bh_blktyp = DTABLK;
- X }
- X tracef((tr, "blk_typ = %c", bhd_ptr->bh_blktyp));
- X
- X /* Calc. checksum */
- X bhd_ptr->bh_chksum = 0;
- X bhd_ptr->bh_chksum = xor_sum(blk_ptr, blk_siz);
- X
- X tracef((tr, "dev=%d, blk_ptr=%x blk_siz=%d",
- X dev, blk_ptr, (int)blk_siz));
- X
- X n_writ = write(dev, blk_ptr, (int)blk_siz);
- X tracef((tr, "n_writ = %ld", n_writ));
- X if (n_writ < blk_siz ) {
- X /* Assume can't fit last block & need new volume */
- X if (n_writ == -1)
- X swarning(device);
- X n_writ = 0L;
- X END_written = FALSE;
- X errno = 0;
- X } else
- X /* return size of data & headers written
- X less nulls used to fill the last block */
- X n_writ -= nulls;
- X
- X trace("- wr_blk()");
- X return (n_writ);
- X}
- X
- Xvoid
- Xwr_vol(dev, vhd_ptr)
- X int *dev;
- X char *vhd_ptr;
- X{
- X#ifndef time_t
- X# include <sys/types.h>
- X#endif
- X /* mount and open next volume for writing */
- X void pack_vhdr();
- X up_vhdr *mount_vol();
- X char *vol_file(), *vol_nam;
- X time_t time();
- X
- X static int vol_num = 0;
- X static long timestamp;
- X
- X tracef((tr, "+ wr_vol(%x, %x)", dev, vhd_ptr));
- X if (++vol_num == 1)
- X timestamp = time((time_t *) 0);
- X else { /* Note: the last volume is closed by exit() */
- X show_blks(-1L);
- X trace("close");
- X close(*dev);
- X }
- X
- X pack_vhdr(vhd_ptr, vol_num, timestamp);
- X
- X vol_nam = vol_file(device, vol_num);
- X
- X mount_vol(vol_nam, vol_num, timestamp);
- X
- X if ((*dev = open(vol_nam, WRITE)) == -1)
- X sfatal(vol_nam);
- X
- X trace("- wr_vol()");
- X}
- X
- X/* ARGSUSED */
- Xchar *
- Xvol_file(devname, vol_num)
- X char *devname;
- X int vol_num;
- X{
- X static char vol_name[15];
- X
- X#ifdef VOLNUM
- X /* used for testing when writting to files pretending to be volumes */
- X sprintf(vol_name, "%s.%d", devname, vol_num);
- X#else
- X sprintf(vol_name, "%s", devname);
- X#endif
- X return((char *)vol_name);
- X}
- X
- Xchar
- Xxor_sum(ptr, siz)
- X char *ptr;
- X long siz;
- X{
- X register char sum;
- X register int i;
- X
- X sum = 0;
- X for (i = siz; i-- ; )
- X sum ^= *ptr++;
- X return sum;
- X}
- X
- X/* show_blks() is called from rd.c and wr.c */
- Xvoid
- Xshow_blks(blk_num)
- X long blk_num;
- X{
- X bool y_or_n();
- X#define DOTBLKS 10
- X#define DOTCH '.'
- X /* Every DOTBLKS blocks print a dot */
- X tracef((tr, "show_blks(#%ld)", blk_num));
- X if (dsp_blks) {
- X if (blk_num == -1L)
- X putc('\n', stderr);
- X else if (blk_num % DOTBLKS == 0)
- X#ifdef DEBUG
- X fprintf(stderr, "%8ld", blk_num);
- X#else
- X putc(DOTCH, stderr);
- X#endif
- X }
- X}
- X
- Xchar *
- Xnew_buf(buf_siz)
- X long buf_siz;
- X{
- X char *buf_ptr;
- X char *malloc();
- X
- X tracef((tr, "+ new_buf(%ld)", buf_siz));
- X if ((buf_ptr = malloc( (unsigned)buf_siz )) == (char *)NULL) {
- X fatal("Insufficient memory for block size");
- X }
- X trace("- new_buf()");
- X return buf_ptr;
- X}
- !The!End!
- exit
-