sources-request@munnari.OZ (08/29/86)
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