v07i13: Multivol V1.00 - multivolume backup utility, part02/02
sources-request at munnari.OZ
sources-request at munnari.OZ
Sat Aug 30 01:30:36 AEST 1986
Submitted-by: Tony O'Hagan <tony%uqcspe.oz at 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
More information about the Mod.sources
mailing list