home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume7 / multivol / part2 < prev    next >
Encoding:
Text File  |  1986-11-30  |  23.2 KB  |  1,076 lines

  1. Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site mirror.UUCP
  2. Path: mirror!cca!decvax!genrad!panda!husc6!seismo!munnari!sources-request
  3. From: sources-request@munnari.UUCP
  4. Newsgroups: mod.sources
  5. Subject: v07i13: Multivol V1.00 - multivolume backup utility, part02/02
  6. Message-ID: <1231@munnari.OZ>
  7. Date: 29 Aug 86 15:30:36 GMT
  8. Date-Received: 2 Sep 86 20:59:29 GMT
  9. Sender: kre@munnari.OZ
  10. Lines: 1063
  11. Approved: kre@munnari.oz
  12.  
  13. Submitted-by: Tony O'Hagan <tony%uqcspe.oz@seismo.css.gov>
  14. Mod.sources: Volume 17, Issue 13
  15. Archive-name: multivol
  16.  
  17. # this is a shell archive, extract with sh, not csh
  18. echo x - "ask.c" 2>&1
  19. sed "s/^X//" >"ask.c" <<'!The!End!'
  20. X#include <stdio.h>
  21. X#define    bool    short
  22. X#define    TRUE    1
  23. X#define FALSE    0
  24. X
  25. Xchar *
  26. Xask(prompt)
  27. X    char    *prompt;
  28. X{
  29. X    static    char    ans[256];
  30. X    static    bool    ttyclosed = TRUE;
  31. X    static    FILE    *tty;
  32. X
  33. X    if (ttyclosed)
  34. X        if ((tty = fopen("/dev/tty", "r")) == NULL) {
  35. X            perror("/dev/tty");
  36. X            exit(1);
  37. X        } else
  38. X            ttyclosed = FALSE;
  39. X
  40. X    fprintf(stderr, prompt);
  41. X    fgets(ans, sizeof(ans), tty);
  42. X    /* fclose(tty); */
  43. X    return ans;
  44. X}
  45. X
  46. X/* VARARGS1 */
  47. Xchar *
  48. Xaskf(format, val1, val2, val3, val4)
  49. X    char    *format;
  50. X    int    val1, val2, val3, val4;
  51. X{
  52. X    char    prompt[80];
  53. X
  54. X    sprintf(prompt, format, val1, val2, val3, val4);
  55. X    return ask(prompt);
  56. X}
  57. X
  58. Xbool
  59. Xy_or_n(prompt)
  60. X    char    *prompt;
  61. X{
  62. X    char    *ans;
  63. X    bool    yes, no;
  64. X
  65. X    char    *ask();
  66. X
  67. X    do {
  68. X        ans = ask(prompt);
  69. X        no  = ans[1] == '\n' && (ans[0]  == 'n' || ans[0]  == 'N' );
  70. X        yes = ans[1] == '\n' && (ans[0]  == 'y' || ans[0]  == 'Y' );
  71. X    } while (! (yes || no) );
  72. X    return(yes);
  73. X}
  74. !The!End!
  75.  
  76. echo x - "bcopy.c" 2>&1
  77. sed "s/^X//" >"bcopy.c" <<'!The!End!'
  78. X#ifdef vax
  79. Xbcopy(from, to, len)
  80. X    char *from, *to;
  81. X    int len;
  82. X{
  83. X    asm("    movc3    12(ap),*4(ap),*8(ap)");
  84. X}
  85. X#else 
  86. X#ifdef    SYSV
  87. X/*
  88. X * Added by moderator, bcopy.c for Sys V.
  89. X *
  90. X */
  91. X
  92. Xextern char *memcpy();
  93. X
  94. Xchar *
  95. Xbcopy(from, to, count)
  96. X    char *from;
  97. X    char *to;
  98. X    int count;
  99. X{
  100. X    return (memcpy(to, from, count));
  101. X}
  102. X#else
  103. Xbcopy(from, to, len)
  104. X    register char    *to, *from;
  105. X    register int    len;
  106. X{
  107. X    if (from > to) {
  108. X        while(len--)
  109. X            *to++ = *from++;
  110. X    } else {    /* not handled in standard version of bcopy() */
  111. X        to    += len;
  112. X        from    += len;
  113. X        while(len--)
  114. X            *--to = *--from;
  115. X    }
  116. X}
  117. X#endif
  118. X#endif
  119. !The!End!
  120.  
  121. echo x - "error.c" 2>&1
  122. sed "s/^X//" >"error.c" <<'!The!End!'
  123. X#include <stdio.h>
  124. X    extern    int    errno;
  125. X    extern    char    *O_name;
  126. X/*VARARGS1*/
  127. Xfatal(fmt, arg1, arg2, arg3)
  128. X    char    *fmt;
  129. X    int    arg1, arg2, arg3;
  130. X{
  131. X    warning(fmt, arg1, arg2, arg3);
  132. X#ifdef    DEBUG
  133. X    abort();
  134. X#else
  135. X    exit(1);
  136. X#endif
  137. X}
  138. X
  139. Xsfatal(str)
  140. X    char    *str;
  141. X{
  142. X    swarning(str);
  143. X#ifdef    DEBUG
  144. X    abort();
  145. X#else
  146. X    exit(1);
  147. X#endif
  148. X}
  149. X
  150. X/*VARARGS1*/
  151. Xwarning(fmt, arg1, arg2, arg3)
  152. X    char    *fmt;
  153. X    int    arg1, arg2, arg3;
  154. X{
  155. X    fprintf(stderr, "%s: ", O_name);
  156. X    fprintf(stderr, fmt, arg1, arg2, arg3);
  157. X    fprintf(stderr, "\n");
  158. X}
  159. X
  160. Xswarning(str)
  161. X    char    *str;
  162. X{
  163. X#ifdef    DEBUG
  164. X    fprintf(stderr, "(%d)  ", errno);
  165. X#endif
  166. X    fprintf(stderr, "%s: ", O_name);
  167. X    perror(str);
  168. X}
  169. !The!End!
  170.  
  171. echo x - "mount.c" 2>&1
  172. sed "s/^X//" >"mount.c" <<'!The!End!'
  173. X/* multivol  V1.00  5-Jun-85  Tony O'Hagan
  174. X * multivol (8) - handle multivolume files
  175. X * wrvols() - function of multivol main()
  176. X */
  177. X
  178. X#include <stdio.h>
  179. X#include <ctype.h>
  180. X
  181. X#include "multivol.h"
  182. X
  183. X/*  Globals */
  184. X    extern    bool    dsp_vols, vfy_vols, rd_flag, wr_flag;
  185. X    extern    char    *label;
  186. X
  187. Xup_vhdr *
  188. Xmount_vol(vol_nam, vol_num, timestamp)
  189. X    /* returns header read on mounted volume */
  190. X    char    *vol_nam;
  191. X    int    vol_num;
  192. X    long    timestamp;
  193. X{
  194. X    up_vhdr    *upvh; /* returned value */
  195. X    bool    ok;
  196. X
  197. X    bool    vol_ok();
  198. X    void    print_vhdr();
  199. X    bool    y_or_n();
  200. X    up_vhdr *rd_vhdr();
  201. X    char    *askf();
  202. X#ifdef    REWIND
  203. X    char    *ask();
  204. X#endif
  205. X
  206. X    tracef((tr, "+ mount_vol(%s, %d, %ld)", vol_nam, vol_num, timestamp));
  207. X
  208. X    do {    
  209. X        askf("Mount volume #%d and type <return> ", vol_num);
  210. X
  211. X        if (rd_flag || dsp_vols || vfy_vols)
  212. X            upvh = rd_vhdr(vol_nam); /* Read volume header */
  213. X        else {
  214. X            upvh = NULVHD; 
  215. X            trace("goto no_vhdr");
  216. X            goto no_vhdr;  /* no volume header was read */
  217. X        }
  218. X
  219. X        if (upvh == NULVHD) {
  220. X            ok = !rd_flag; /* ok unless attempting to read volume */
  221. X        } else {
  222. X            if (dsp_vols || vfy_vols) {
  223. X        /* Print header & check correct volume is read/overwritten */
  224. X                putc('\n', stderr);
  225. X                print_vhdr(upvh);
  226. X                putc('\n', stderr);
  227. X            }
  228. X            ok = vol_ok(upvh, vol_num, timestamp);
  229. X        }
  230. X        tracef((tr, "vfy_vols=%d, ok=%d upvh=x%x", vfy_vols, ok, upvh));
  231. X    } while ( (vfy_vols || !ok) && y_or_n("Remount required [y/n] ? ") );
  232. X
  233. X#ifdef    REWIND
  234. X    ask("Ensure volume is rewound and type <return> ");
  235. X#endif
  236. X
  237. Xno_vhdr:
  238. X    trace("- mount_vol()");
  239. X    return(upvh);
  240. X}
  241. X
  242. Xbool
  243. Xvol_ok(upvh, vol_num, timestamp)
  244. Xup_vhdr    *upvh;
  245. X    int    vol_num;
  246. X    long    timestamp;
  247. X/* Check correct volume is mounted
  248. X * vol_num    = volume no. expected on this volume
  249. X * timestamp    = timestamp on volumes being written
  250. X * upvh        = unpacked volume header on volume about to be read/overwritten.
  251. X */
  252. X{
  253. X    bool    ok = TRUE;    /* returns ok */
  254. X    static    up_vhdr    up_1st;    /* first volume header read */
  255. X
  256. X    trace("+ vol_ok()");
  257. X    if (wr_flag) {    /* if writing volumes */
  258. X        if (timestamp == upvh->up_timestamp) {
  259. X            fprintf(stderr, 
  260. X            "** This clobbers a volume just written !\n");
  261. X            ok = FALSE;
  262. X        }
  263. X    } else if (rd_flag) { /* if reading volumes */
  264. X        if (vol_num == 1) { /* record header of first volume */
  265. X            bcopy((char *)upvh, (char *)&up_1st, sizeof(up_vhdr));
  266. X            if (label != NULL &&strcmp(label, upvh->up_label) != 0){
  267. X                fprintf(stderr, "** Label does not match\n");
  268. X                ok = FALSE;
  269. X            }
  270. X        }
  271. X        if (vol_num >= 2 && up_1st.up_timestamp != upvh->up_timestamp) {
  272. X            fprintf(stderr, "** Volume not part of volume set\n");
  273. X            ok = FALSE;
  274. X        } else if (upvh->up_vol_num != vol_num) {
  275. X            fprintf(stderr, "** Volume no. out of sequence\n");
  276. X            ok = FALSE;
  277. X        }
  278. X    }
  279. X    trace("- vol_ok()");
  280. X    return(ok);
  281. X}
  282. !The!End!
  283.  
  284. echo x - "multivol.c" 2>&1
  285. sed "s/^X//" >"multivol.c" <<'!The!End!'
  286. X/* multivol  V1.00  5-Jun-85  Tony O'Hagan
  287. X * multivol (8) - handle multivolume files
  288. X * multivol [-i] [-o] [-v] [-w] [-t] [-b blocksize]
  289. X *      [-n blocks-per-vol] [-l label] [device]
  290. X * Source files:
  291. X *   ask.c bcopy.c error.c mount.c multivol.c rd.c testdata.c trace.c vhdr.c wr.c
  292. X *   multivol.h options.h trace.h
  293. X * Other files:
  294. X *   Makefile READ_ME multivol.8 testdata.c
  295. X */
  296. X#include <stdio.h>
  297. X#include <ctype.h>
  298. X#include "options.h"
  299. X#include "multivol.h"
  300. X
  301. X#define    ACCREAD    4
  302. X#define ACCWRIT    2
  303. X
  304. X#ifndef DEFBSIZ
  305. X#    include <sys/param.h>
  306. X#    undef    bcopy
  307. X#    define DEFBSIZ    BSIZE    /* default block size */
  308. X#endif
  309. X
  310. X#ifndef DEFBLIM
  311. X#    define DEFBLIM    NOLIMIT    /* default block limit (no. per volume) */
  312. X#endif
  313. X
  314. X#define DEFLABEL    "no_label"    /* Default label */
  315. X
  316. X#ifndef DEFDEV  /* may be cc -DDEFDEV= */
  317. X#    define DEFDEV    "/dev/multivol"
  318. X#endif
  319. X
  320. X/*  Globals */
  321. X    export    char    *prog_name, *label = DEFLABEL, *device = DEFDEV;
  322. X    export    bool    dsp_blks, dsp_vols, vfy_vols, rd_flag , wr_flag;
  323. X    export    long    blk_lim = DEFBLIM;
  324. X    export    long    blk_siz = DEFBSIZ;
  325. X
  326. Xvoid
  327. Xmain(argc, argv)    /* multivol main() */
  328. X    int    argc;
  329. X    char    *argv[];
  330. X{
  331. X    char    *bsizstr;
  332. X    up_vhdr    *upvh;
  333. X
  334. X    void    rd_vols(), wrvols(), print_vhdr();
  335. X    up_vhdr *rd_vhdr(); 
  336. X    long    kval(), atol();
  337. X    char    *vol_file();
  338. X    int    t_int;
  339. X    bool    y_or_n();
  340. X
  341. X    trace( "+ main()");
  342. X
  343. X    rd_flag = wr_flag = dsp_vols = dsp_blks = vfy_vols = FALSE;
  344. X    OPTIONS ("[-i] [-o] [-v] [-w] [-t] [-b blocksize] [-n blocks-per-vol] [-l label] [device]")
  345. X        FLAG    ('i', rd_flag)
  346. X#ifdef DEBUG
  347. X        FLAG    ('D', tron)
  348. X#endif
  349. X        FLAG    ('o', wr_flag)
  350. X        FLAG    ('t', dsp_vols)
  351. X        FLAG    ('v', dsp_blks)
  352. X        FLAG    ('w', vfy_vols)
  353. X        STRING    ('b', bsizstr)
  354. X            if ((blk_siz = kval(bsizstr)) == -1) 
  355. X                fatal("** Illegal block size %s", bsizstr);
  356. X            else if (blk_siz < MINBLK)
  357. X                fatal("** Minimum block size is %d", MINBLK);
  358. X            else { /* test if blk_siz value fits in int */
  359. X                t_int = blk_siz;
  360. X                if (blk_siz != t_int)
  361. X                    fatal("** Block size too big");
  362. X            }
  363. X        NUMBER    ('n', blk_lim)
  364. X        STRING    ('l', label)
  365. X            if (index(label, ' ') != 0)
  366. X                fatal("** Label must not contain white space");
  367. X    ENDOPTS
  368. X    prog_name = argv[0];
  369. X    if (argc > 1)
  370. X        device = argv[1];
  371. X
  372. X    tracef((tr, "BHDSIZ = %d   VHDSIZ = %d", BHDSIZ, VHDSIZ));
  373. X    tracef((tr, "prog_name:%s  label:%s  blk_siz:%ld",
  374. X        prog_name, label, blk_siz));
  375. X    tracef((tr, "blk_lim:%ld  dsp_blks:%d  dsp_vols:%d  vfy_vols:%d",
  376. X        blk_lim, dsp_blks, dsp_vols, vfy_vols));
  377. X    
  378. X    if (rd_flag && wr_flag)
  379. X        fatal("** Only -i or -o may be specified");
  380. X    else if (rd_flag) {
  381. X        if (access(device, ACCREAD) == -1)
  382. X            sfatal(device);
  383. X        rd_vols();
  384. X    } else if (wr_flag) {
  385. X        if (access(device, ACCREAD & ACCWRIT) == -1)
  386. X            sfatal(device);
  387. X        wrvols();
  388. X    } else {
  389. X        /* Print details of volume header */
  390. X        /* Note: No prompt to mount volume */
  391. X        if (access(device, ACCREAD) == -1)
  392. X            sfatal(device);
  393. X        if ((upvh = rd_vhdr(vol_file(device, 1))) != NULVHD)
  394. X            print_vhdr(upvh);
  395. X    }
  396. X
  397. X    trace("- main()");
  398. X    exit(0);
  399. X}
  400. X
  401. Xlong
  402. Xkval(kstr) 
  403. X    char *kstr;
  404. X{
  405. X    long    n, atol();  /* return n */
  406. X    char    c;
  407. X
  408. X    trace("+ kstr()");
  409. X    n = atol(kstr);
  410. X    c = kstr[strlen(kstr)-1];
  411. X    if (! isdigit(c)) {
  412. X        switch (c) {
  413. X        case 'b':case 'B': 
  414. X            n *= 512; break;
  415. X        case 'k':case 'K': 
  416. X            n *= 1024; break;
  417. X    /*    case 'm':case 'M': 
  418. X            n *= 1024*1024; break;    */
  419. X        default:
  420. X            n = -1;
  421. X        }
  422. X    }
  423. X    trace("- kstr()");
  424. X    return(n);
  425. X}
  426. !The!End!
  427.  
  428. echo x - "rd.c" 2>&1
  429. sed "s/^X//" >"rd.c" <<'!The!End!'
  430. X/* multivol(8)  V1.00  5-Jun-85  Tony O'Hagan
  431. X * Handles multivolume files
  432. X */
  433. X#include <stdio.h>
  434. X#include "multivol.h"
  435. X
  436. X/*  Globals */
  437. X    extern    char    *label, *device;
  438. X    extern    long    blk_lim;
  439. X    extern    long    blk_siz;
  440. X
  441. X    /* TRUE when block containing ENDBLK block type has been read */
  442. X    static    bool    END_read;  
  443. X    static    long    blk_num;
  444. X
  445. Xvoid
  446. Xrd_vols()
  447. X{
  448. X    char    *dta_ptr;
  449. X    long    dta_got;
  450. X
  451. X    void    show_blks();
  452. X    long    rd_get_dta(), rd_put_dta();
  453. X
  454. X    trace("+ rd_vols()");
  455. X
  456. X    END_read = FALSE;
  457. X    do {
  458. X        dta_got = rd_get_dta(&dta_ptr);
  459. X        tracef((tr, "dta_got = %ld", dta_got));
  460. X        if (dta_got > 0L)
  461. X            rd_put_dta(dta_ptr, dta_got);
  462. X    } while (!END_read);
  463. X
  464. X    show_blks(-1L);    /* terminate display of blocks */
  465. X    trace("- rd_vols()");
  466. X    return;
  467. X}
  468. X
  469. Xlong
  470. Xrd_put_dta(dta_ptr, dta_len)
  471. X    char    *dta_ptr;
  472. X    long    dta_len;
  473. X{
  474. X    long    n_writ;
  475. X    trace("+ rd_put_dta()");
  476. X
  477. X    if ((n_writ = write(fileno(stdout), dta_ptr, (int)dta_len)) == -1L) {
  478. X        n_writ = 0L;
  479. X        swarning("stdout");
  480. X    } else if (n_writ < dta_len)
  481. X        warning("** Only output %ld bytes of %ld bytes in block #%ld",
  482. X            n_writ, dta_len, blk_num);
  483. X
  484. X    tracef((tr, "- rd_put_dta() n_writ = %ld", n_writ));
  485. X    return n_writ ;
  486. X}
  487. X
  488. X/* Controls when volumes require mounting and
  489. X * allocates buffer space for the 1st volume.
  490. X */
  491. Xlong
  492. Xrd_get_dta(dta_ptr)
  493. X    char    **dta_ptr;
  494. X{
  495. X    void    show_blks();
  496. X    long    rd_blk();
  497. X    char    *new_buf(), *vol_file();
  498. X    up_vhdr    *mount_vol();
  499. X
  500. X    char    *vol_nam;
  501. X    long    n_read;
  502. X    up_vhdr    *upvh;
  503. X
  504. X    static    char    *blk_ptr;
  505. X    static    int    dev, vol_num = 0;
  506. X    static    bool    new_vol = TRUE;
  507. X
  508. X    tracef((tr, "+ rd_get_dta(%x)", *dta_ptr));
  509. X
  510. X    if (new_vol) {
  511. X        blk_num = 0L;
  512. X        new_vol = FALSE;
  513. X        vol_nam = vol_file(device, ++vol_num);
  514. X        if (vol_num > 1) {
  515. X            show_blks(-1L);    
  516. X            trace("close");
  517. X            close(dev);    /* Last volume is closed by exit() */
  518. X        }
  519. X        if ((upvh = mount_vol(vol_nam, vol_num, 0L )) == NULVHD) {
  520. X            END_read = TRUE;
  521. X            trace("- rd_get_dta()");
  522. X            return 0L;
  523. X        } 
  524. X
  525. X        trace("set blk_siz & blk_lim from vol header");
  526. X        blk_siz = upvh->up_siz_blk;
  527. X        blk_lim = upvh->up_lim_blk;
  528. X
  529. X        if (vol_num == 1) {
  530. X            blk_ptr = new_buf(blk_siz + VHDSIZ);
  531. X        }
  532. X
  533. X        if ((dev = open(vol_nam, READ)) == -1)
  534. X            sfatal(vol_nam);
  535. X
  536. X        /* setup pointer to data in block */
  537. X        *dta_ptr = blk_ptr + BHDSIZ + VHDSIZ;
  538. X    } else
  539. X        *dta_ptr = blk_ptr + BHDSIZ;
  540. X
  541. X    if ((n_read = rd_blk(dev, blk_ptr)) == 0L) {
  542. X        /* Couldn't read last block on current volume */
  543. X        new_vol = TRUE;
  544. X        if (blk_lim != NOLIMIT && !END_read)
  545. X            fprintf(stderr,
  546. X            "** Could only read %ld blocks on volume", blk_num);
  547. X        trace("- rd_get_dta()");
  548. X        return 0L ;
  549. X    } else {
  550. X        if (blk_lim != NOLIMIT && blk_num >= blk_lim)
  551. X            new_vol = TRUE;
  552. X        trace("- rd_get_dta()");
  553. X        /* return amount of data written (excl. headers - See diag.) */
  554. X        return(n_read - (*dta_ptr - blk_ptr));
  555. X    }
  556. X}
  557. X
  558. Xlong
  559. Xrd_blk(dev, blk_ptr)
  560. X    int    dev;
  561. X    char    *blk_ptr;
  562. X#define bh_ptr    ((blk_hdr *) blk_ptr)
  563. X{
  564. X    int    chk_sum;
  565. X    char    xor_sum();
  566. X    long    blk_len, n_read;
  567. X
  568. X    trace("+ rd_blk()");
  569. X    n_read = read(dev, blk_ptr, (int)blk_siz);
  570. X    if (n_read == blk_siz) {
  571. X        show_blks(++blk_num);
  572. X    } else {
  573. X        if (n_read == -1L)
  574. X            swarning(device);
  575. X        else
  576. X            warning("** Block #%ld is only %ld bytes",
  577. X                blk_num+1, n_read);
  578. X        /* END_read = TRUE;    - abort gracefully */
  579. X        trace("- rd_blk()");
  580. X        return 0L ;
  581. X    }
  582. X
  583. X    END_read = bh_ptr->bh_blktyp == ENDBLK;
  584. X
  585. X    sscanf(bh_ptr->bh_dtalen, "%6ld", &blk_len);
  586. X    tracef((tr, "blk_len = %ld", blk_len));
  587. X
  588. X        /* Calc. checksum */
  589. X    if (chk_sum = xor_sum(blk_ptr, blk_siz) != '\0')
  590. X        warning("** Block #%ld check sum error (sum = %x hex)\n",
  591. X            blk_num, chk_sum);
  592. X
  593. X    trace("- rd_blk()");
  594. X    return(blk_len);
  595. X}
  596. !The!End!
  597.  
  598. echo x - "testdata.c" 2>&1
  599. sed "s/^X//" >"testdata.c" <<'!The!End!'
  600. X#include <stdio.h>
  601. Xmain(argc, argv)    /* garbo main() */
  602. X    int    argc;
  603. X    char    *argv[];
  604. X{
  605. X    long    atol();
  606. X    register long    j;
  607. X    register char    *str;
  608. X    register int    no_eoln, i;
  609. X    
  610. X    if (no_eoln = (*argv[1] == '-' && *++argv[1] == 'n')) {
  611. X        argv++;
  612. X        argc--;
  613. X    }
  614. X    for (i = 1; i < argc; i += 2) {
  615. X        str = argv[i+1];
  616. X        for (j = atol(argv[i]); j--; ) {
  617. X            printf("%s", str);
  618. X            if (!no_eoln)
  619. X                putc('\n', stdout);
  620. X        }
  621. X    }
  622. X}
  623. !The!End!
  624.  
  625. echo x - "trace.c" 2>&1
  626. sed "s/^X//" >"trace.c" <<'!The!End!'
  627. X#ifdef DEBUG    /* Only used if DEBUG is defined */
  628. X#include <stdio.h>
  629. X    int    tron;    /* global = trace on */
  630. X    char    tr[160];
  631. X
  632. Xstrace(file, line, step)
  633. X    char    *file, *step;
  634. X    int    line;
  635. X{
  636. X    static int    indent = 0;
  637. X    register    i;
  638. X
  639. X    if (*step == '-')
  640. X        indent--; 
  641. X    if (tron) {
  642. X        fprintf(stderr, "%14s: %5d: ", file, line);
  643. X        for (i = indent; i--; )
  644. X            fprintf(stderr, ".  ");
  645. X        fprintf(stderr, "%s\n", step);
  646. X    }
  647. X    if (*step == '+')
  648. X        indent++; 
  649. X}
  650. X#endif
  651. !The!End!
  652.  
  653. echo x - "vhdr.c" 2>&1
  654. sed "s/^X//" >"vhdr.c" <<'!The!End!'
  655. X/* multivol  V1.00  5-Jun-85  Tony O'Hagan
  656. X * multivol (8) - handle multivolume files
  657. X * vhdr.c - functions performed on volume header
  658. X */
  659. X#include <stdio.h>
  660. X#include "multivol.h"
  661. X
  662. X    extern    long    blk_siz, blk_lim;
  663. X    extern    char    *label;
  664. X
  665. Xup_vhdr *
  666. Xrd_vhdr(devname)
  667. X    char    *devname;
  668. X/* Read volume header from the first block and rewind (close()) the volume */
  669. X{
  670. X    up_vhdr *ans;
  671. X    int    dev;
  672. X    int    n_read;
  673. X    char    *blk;
  674. X
  675. X    char    *new_buf();
  676. X    up_vhdr    *unpack_vhdr();
  677. X    void    free();
  678. X
  679. X    tracef((tr, "+ rd_vhdr(%s)", devname));
  680. X    if ((dev = open(devname, READ)) == -1) {
  681. X        swarning(devname);
  682. X        trace("- rd_vhdr()");
  683. X        return(NULVHD);
  684. X    }
  685. X
  686. X    blk = new_buf(blk_siz);
  687. X    trace("reading volume header");
  688. X
  689. X    tracef((tr, "read(%d, %x, %d)", dev, blk, (int)blk_siz));
  690. X    if ((n_read = read(dev, blk, (int)blk_siz) ) == -1) {
  691. X        swarning(devname);
  692. X        ans = NULVHD;
  693. X    } else {
  694. X        if (n_read == 0) {
  695. X            fprintf(stderr, "** No header found on volume\n");
  696. X            ans = NULVHD;
  697. X        } else if (n_read < MINBLK) {
  698. X            fprintf(stderr,
  699. X                "** Header block is only %d bytes\n", n_read);
  700. X            ans = NULVHD;
  701. X        } else {    /* vol_hdr after blk_hdr */
  702. X            tracef((tr, "blk+BHDSIZ = %x",
  703. X                (vol_hdr *)(blk + BHDSIZ)));
  704. X            if (NULVHD ==
  705. X                (ans = unpack_vhdr((vol_hdr *)(blk + BHDSIZ))) )
  706. X                fprintf(stderr, "** Invalid volume header\n");
  707. X        }
  708. X    }
  709. X    close(dev);
  710. X    trace("free(blk)");
  711. X    free(blk);
  712. X    trace("- rd_vhdr()");
  713. X    return ans ;
  714. X}
  715. X
  716. Xvoid
  717. Xprint_vhdr(up)
  718. X    up_vhdr    *up;
  719. X/* Print volume header details */
  720. X{
  721. X#ifndef    time_t
  722. X#    include <sys/types.h>
  723. X#endif
  724. X    char    *ctime();
  725. X    time_t    t_stamp;
  726. X
  727. X    trace("+print_vhdr()");
  728. X    t_stamp = (time_t) up->up_timestamp;
  729. X
  730. X    /* Note: ctime() returns date & time with a \n following */
  731. X    fprintf(stderr, 
  732. X        "Written using: %s V%s  Label: %s  %s", up->up_prog_name,
  733. X        up->up_version, up->up_label, ctime(&t_stamp) );
  734. X    fprintf(stderr, 
  735. X        "Vol. no.: %d   Block size: %ld   Blocks per volume: %ld\n",
  736. X        up->up_vol_num, up->up_siz_blk, up->up_lim_blk);
  737. X
  738. X    trace("-print_vhdr()");
  739. X}
  740. X
  741. Xvoid
  742. Xpack_vhdr(pk, vol_num, timestamp)
  743. X    char    *pk;
  744. X    int    vol_num;
  745. X    long    timestamp;
  746. X{
  747. X    sprintf(pk, VHDPACK,
  748. X        vol_num, PROGNAM, VERSION, label, timestamp, blk_siz, blk_lim);
  749. X}
  750. X
  751. Xup_vhdr *
  752. Xunpack_vhdr(pk)
  753. X    vol_hdr        *pk;
  754. X{
  755. X    static    up_vhdr        up;
  756. X    
  757. X    tracef((tr, "+ unpack_vhdr(pk = %x)", pk));
  758. X    if(VHDFIELDS == sscanf((char *)pk, VHDUNPACK,
  759. X        &up.up_vol_num, up.up_prog_name, up.up_version,
  760. X        up.up_label, &up.up_timestamp, &up.up_siz_blk, &up.up_lim_blk)) {
  761. X        trace("- unpack_vhdr");
  762. X        return &up;
  763. X    } else {
  764. X        trace("- unpack_vhdr = NULVHD");
  765. X        return NULVHD;
  766. X    }
  767. X}
  768. !The!End!
  769.  
  770. echo x - "wr.c" 2>&1
  771. sed "s/^X//" >"wr.c" <<'!The!End!'
  772. X/* multivol(8)  V1.00  5-Jun-85  Tony O'Hagan */
  773. X#include <stdio.h>
  774. X#include <ctype.h>
  775. X#include <errno.h>
  776. X    extern    int    errno;
  777. X
  778. X#include "multivol.h"
  779. X
  780. X/*  Globals */
  781. X    extern    bool    dsp_blks;
  782. X    extern    char    *label, *device;
  783. X    extern    long    blk_lim;
  784. X    extern    long    blk_siz;
  785. X
  786. X    /* TRUE when ENDBLK block type has been written */
  787. X    static    bool    END_written;
  788. X    static    long    blk_num;
  789. X
  790. Xvoid
  791. Xwrvols()
  792. X{
  793. X    char    *buf_ptr, *dta_ptr;
  794. X    long    usu_dta, dta_left, dta_put;
  795. X
  796. X    void    bcopy(), show_blks();
  797. X    char    *new_buf();
  798. X    long    wr_get_dta(), wr_put_dta();
  799. X
  800. X    trace("+ wrvols()");
  801. X
  802. X    buf_ptr = new_buf(blk_siz+VHDSIZ);
  803. X
  804. X    dta_left = 0L;
  805. X    END_written = FALSE;
  806. X    dta_ptr = buf_ptr + BHDSIZ + VHDSIZ; /* See diag. of buffer */
  807. X    usu_dta = blk_siz - BHDSIZ;    /* usual amount of data per block */
  808. X
  809. X    while ( TRUE ) {
  810. X            /* Attempt to fill up data buffer to 'usu_dta' chars &
  811. X                append new data after data left over */
  812. X        dta_left += wr_get_dta(dta_ptr + dta_left, usu_dta - dta_left);
  813. X        tracef((tr, "after wr_get_dta dta_left = %ld", dta_left));
  814. X
  815. X        if (dta_left <= 0L && END_written)
  816. X            break;
  817. X
  818. X            /* Attempt to dispose of whatever is in data buffer */
  819. X        dta_left -= (dta_put = wr_put_dta(dta_ptr, dta_left));
  820. X        tracef((tr, "after wr_put_dta dta_left = %ld", dta_left));
  821. X
  822. X            /* if any left, copy to top of data buffer */
  823. X        if (dta_left > 0L && dta_put > 0L)
  824. X            bcopy(dta_ptr + dta_put, dta_ptr, (int)dta_left);
  825. X    }
  826. X    show_blks(-1L);    /* terminate display of blocks */
  827. X    if (dsp_blks)
  828. X        fprintf(stderr, "%ld blocks on last volume", blk_num);
  829. X    trace("- wrvols()");
  830. X}
  831. X
  832. Xlong
  833. Xwr_get_dta(dta_ptr, dta_req)
  834. X    char    *dta_ptr;
  835. X    long    dta_req;
  836. X{
  837. X    long    n_read, tot_read;
  838. X
  839. X    tracef((tr, "+ wr_get_dta(%x, %ld)", dta_ptr, dta_req));
  840. X
  841. X    /* Get at least the required amount of data */
  842. X    for (tot_read = 0L; tot_read < dta_req; tot_read += n_read) {
  843. X        n_read = read(fileno(stdin),
  844. X            dta_ptr + tot_read, (int)(dta_req - tot_read));
  845. X        tracef((tr, "n_read = %ld", n_read));
  846. X        if (n_read == -1) {
  847. X            n_read = 0L;
  848. X            swarning("stdin");
  849. X        }
  850. X        if (n_read == 0L)
  851. X            break;
  852. X    }
  853. X
  854. X    tracef((tr, "- wr_get_dta() tot_read = %ld", tot_read));
  855. X    return tot_read ;
  856. X}
  857. X
  858. X/* Controls when volumes require mounting */
  859. Xlong
  860. Xwr_put_dta(dta_ptr, dta_len)
  861. X    char    *dta_ptr;
  862. X    long    dta_len;
  863. X{
  864. X    void    wr_vol(), show_blks();
  865. X    char    *blk_ptr;
  866. X    long    wr_blk(), n_writ, blk_len;
  867. X
  868. X    static    int    dev;
  869. X    static    bool    new_vol = TRUE;
  870. X
  871. X    tracef((tr, "+ wr_put_dta(%x, %ld)", dta_ptr, dta_len));
  872. X
  873. X    blk_ptr = dta_ptr;
  874. X    blk_len = dta_len;
  875. X
  876. X    if (new_vol) {
  877. X        blk_ptr -= VHDSIZ;
  878. X        blk_len += VHDSIZ;
  879. X        /* mount next volume & pre-pend volume header to data buffer */
  880. X        wr_vol(&dev, blk_ptr);
  881. X        blk_num = 0L;
  882. X        new_vol = FALSE;
  883. X    }
  884. X
  885. X    blk_ptr -= BHDSIZ;
  886. X    blk_len += BHDSIZ;
  887. X    if ((n_writ = wr_blk(dev, blk_ptr, blk_len)) == 0L) { 
  888. X        /* last block won't fit on current volume */
  889. X        new_vol = TRUE;
  890. X        if (blk_lim != NOLIMIT)
  891. X            fprintf(stderr,
  892. X            "\n** Could only fit %ld block(s) on volume\n",blk_num);
  893. X        trace("- wr_put_dta()");
  894. X        return(0L);
  895. X    } else { 
  896. X        show_blks(++blk_num);
  897. X        /* test volume block limit */
  898. X        if (blk_lim != NOLIMIT && blk_num >= blk_lim)
  899. X            new_vol = TRUE;
  900. X        /* return amount of data written (excl. headers - See diag.) */
  901. X        trace("- wr_put_dta()");
  902. X        return(n_writ - (dta_ptr - blk_ptr));
  903. X    }
  904. X}
  905. X
  906. Xlong
  907. Xwr_blk(dev, blk_ptr, blk_len)
  908. X    int    dev;
  909. X    char    *blk_ptr;
  910. X    long    blk_len;
  911. X{
  912. X#define BSZDIG    6    /* number of digits for block size string */
  913. X
  914. X    char         len_str[BSZDIG+1];
  915. X    char    xor_sum(), *strncpy();
  916. X    blk_hdr    *bhd_ptr;
  917. X    long    n_writ, nulls;
  918. X
  919. X    tracef((tr, "+ wr_blk(%d, %x, %ld)", dev, blk_ptr, blk_len));
  920. X
  921. X    if (blk_len > blk_siz)
  922. X        blk_len = blk_siz;    /* write at most blk_siz chars */
  923. X
  924. X    bhd_ptr = (blk_hdr *) blk_ptr;
  925. X
  926. X    sprintf(len_str, "%6ld", blk_len);
  927. X    strncpy(bhd_ptr->bh_dtalen, len_str, BSZDIG);
  928. X
  929. X    if (blk_len < blk_siz) {
  930. X        /* move nulls to end of last block of last volume */
  931. X        register char    *p;
  932. X        nulls = blk_siz - blk_len;
  933. X        p = blk_ptr + blk_len;
  934. X        while (blk_len++ < blk_siz)
  935. X            *p++ = '\0';
  936. X        bhd_ptr->bh_blktyp = ENDBLK;
  937. X        END_written = TRUE;
  938. X    } else {
  939. X        nulls = 0L;
  940. X        bhd_ptr->bh_blktyp = DTABLK;
  941. X    }
  942. X    tracef((tr, "blk_typ = %c", bhd_ptr->bh_blktyp));
  943. X        
  944. X        /* Calc. checksum */
  945. X    bhd_ptr->bh_chksum = 0;
  946. X    bhd_ptr->bh_chksum = xor_sum(blk_ptr, blk_siz);
  947. X
  948. X    tracef((tr, "dev=%d,  blk_ptr=%x  blk_siz=%d",
  949. X        dev, blk_ptr, (int)blk_siz));
  950. X
  951. X    n_writ = write(dev, blk_ptr, (int)blk_siz);
  952. X    tracef((tr, "n_writ = %ld", n_writ));
  953. X    if (n_writ < blk_siz ) {
  954. X        /* Assume can't fit last block & need new volume */
  955. X        if (n_writ == -1)
  956. X            swarning(device);
  957. X        n_writ = 0L;
  958. X        END_written = FALSE;
  959. X        errno = 0;
  960. X    } else 
  961. X        /* return size of data & headers written
  962. X        less nulls used to fill the last block */
  963. X        n_writ -= nulls;
  964. X
  965. X    trace("- wr_blk()");
  966. X    return (n_writ);    
  967. X}
  968. X
  969. Xvoid
  970. Xwr_vol(dev, vhd_ptr)
  971. X    int    *dev;
  972. X    char    *vhd_ptr;
  973. X{
  974. X#ifndef    time_t
  975. X#    include    <sys/types.h>
  976. X#endif
  977. X    /* mount and open next volume for writing */
  978. X    void    pack_vhdr();
  979. X    up_vhdr    *mount_vol();
  980. X    char    *vol_file(), *vol_nam;
  981. X    time_t    time();
  982. X
  983. X    static    int    vol_num = 0;
  984. X    static    long    timestamp;
  985. X
  986. X    tracef((tr, "+ wr_vol(%x, %x)", dev, vhd_ptr));
  987. X    if (++vol_num == 1)
  988. X        timestamp = time((time_t *) 0);
  989. X    else {    /* Note: the last volume is closed by exit() */
  990. X        show_blks(-1L);    
  991. X        trace("close");
  992. X        close(*dev);
  993. X    }
  994. X    
  995. X    pack_vhdr(vhd_ptr, vol_num, timestamp);
  996. X    
  997. X    vol_nam = vol_file(device, vol_num);
  998. X
  999. X    mount_vol(vol_nam, vol_num, timestamp);
  1000. X
  1001. X    if ((*dev = open(vol_nam, WRITE)) == -1)
  1002. X        sfatal(vol_nam);
  1003. X
  1004. X    trace("- wr_vol()");
  1005. X}
  1006. X
  1007. X/* ARGSUSED */
  1008. Xchar *
  1009. Xvol_file(devname, vol_num)
  1010. X    char    *devname;
  1011. X    int    vol_num;
  1012. X{
  1013. X    static    char    vol_name[15];
  1014. X
  1015. X#ifdef    VOLNUM
  1016. X    /* used for testing when writting to files pretending to be volumes */
  1017. X    sprintf(vol_name, "%s.%d", devname, vol_num);
  1018. X#else
  1019. X    sprintf(vol_name, "%s", devname);
  1020. X#endif
  1021. X    return((char *)vol_name);
  1022. X}
  1023. X
  1024. Xchar
  1025. Xxor_sum(ptr, siz)
  1026. X    char    *ptr;
  1027. X    long    siz;
  1028. X{
  1029. X    register char    sum;
  1030. X    register int    i;
  1031. X
  1032. X    sum = 0;
  1033. X    for (i = siz; i-- ; )
  1034. X        sum ^= *ptr++;
  1035. X    return sum;
  1036. X}
  1037. X
  1038. X/* show_blks() is called from rd.c and wr.c */
  1039. Xvoid
  1040. Xshow_blks(blk_num)
  1041. X    long    blk_num;
  1042. X{
  1043. X    bool    y_or_n();
  1044. X#define    DOTBLKS    10
  1045. X#define    DOTCH    '.'
  1046. X    /* Every DOTBLKS blocks print a dot */
  1047. X    tracef((tr, "show_blks(#%ld)", blk_num));
  1048. X    if (dsp_blks) {
  1049. X        if (blk_num == -1L) 
  1050. X            putc('\n', stderr);
  1051. X        else if (blk_num % DOTBLKS == 0)    
  1052. X#ifdef    DEBUG
  1053. X            fprintf(stderr, "%8ld", blk_num);
  1054. X#else
  1055. X            putc(DOTCH, stderr);
  1056. X#endif
  1057. X    }
  1058. X}
  1059. X
  1060. Xchar *
  1061. Xnew_buf(buf_siz)
  1062. X    long    buf_siz;
  1063. X{
  1064. X    char    *buf_ptr;
  1065. X    char    *malloc();
  1066. X
  1067. X    tracef((tr, "+ new_buf(%ld)", buf_siz));
  1068. X    if ((buf_ptr = malloc( (unsigned)buf_siz )) == (char *)NULL) {
  1069. X        fatal("Insufficient memory for block size");
  1070. X    }
  1071. X    trace("- new_buf()");
  1072. X    return buf_ptr;
  1073. X}
  1074. !The!End!
  1075. exit
  1076.