home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / linux / backup / star-1.3.1.tar.gz / star-1.3.1.tar / star-1.3.1 / star / buffer.c < prev    next >
C/C++ Source or Header  |  2001-04-06  |  19KB  |  1,027 lines

  1. /* @(#)buffer.c    1.46 01/04/07 Copyright 1985, 1995 J. Schilling */
  2. #ifndef lint
  3. static    char sccsid[] =
  4.     "@(#)buffer.c    1.46 01/04/07 Copyright 1985, 1995 J. Schilling";
  5. #endif
  6. /*
  7.  *    Buffer handling routines
  8.  *
  9.  *    Copyright (c) 1985, 1995 J. Schilling
  10.  */
  11. /*
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2, or (at your option)
  15.  * any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; see the file COPYING.  If not, write to
  24.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  25.  */
  26.  
  27. #include <mconfig.h>
  28. #include <stdio.h>
  29. #include <fctldefs.h>
  30. #include <sys/types.h>
  31. #include <sys/ioctl.h>
  32. #include <vadefs.h>
  33. #include "star.h"
  34. #include <errno.h>
  35. #include <standard.h>
  36. #include "fifo.h"
  37. #include <stdxlib.h>
  38. #include <unixstd.h>
  39. #include <strdefs.h>
  40. #include <waitdefs.h>
  41. #include <schily.h>
  42. #ifdef    HAVE_SYS_MTIO_H
  43. #include <sys/mtio.h>
  44. #else
  45. #include "mtio.h"
  46. #endif
  47. #include "starsubs.h"
  48. #include "remote.h"
  49.  
  50. long    bigcnt    = 0;
  51. int    bigsize    = 0;        /* Tape block size */
  52. int    bufsize    = 0;        /* Available buffer size */
  53. char    *bigbuf    = NULL;
  54. char    *bigptr    = NULL;
  55. char    *eofptr    = NULL;
  56.  
  57. m_stats    bstat;
  58. m_stats    *stats    = &bstat;
  59. int    pid;
  60.  
  61. #ifdef    timerclear
  62. LOCAL    struct    timeval    starttime;
  63. LOCAL    struct    timeval    stoptime;
  64. #endif
  65.  
  66. LOCAL    BOOL    isremote = FALSE;
  67. LOCAL    int    remfd    = -1;
  68. LOCAL    char    *remfn;
  69. LOCAL    char    host[128];
  70.  
  71. extern    FILE    *tarf;
  72. extern    FILE    *tty;
  73. extern    FILE    *vpr;
  74. extern    char    *tarfile;
  75. extern    BOOL    use_fifo;
  76. extern    int    swapflg;
  77. extern    BOOL    debug;
  78. extern    BOOL    showtime;
  79. extern    BOOL    no_stats;
  80. extern    BOOL    do_fifostats;
  81. extern    BOOL    cflag;
  82. extern    BOOL    uflag;
  83. extern    BOOL    rflag;
  84. extern    BOOL    zflag;
  85. extern    BOOL    bzflag;
  86. extern    BOOL    multblk;
  87. extern    BOOL    partial;
  88. extern    BOOL    wready;
  89. extern    BOOL    nullout;
  90. extern    BOOL    nowarn;
  91.  
  92. extern    int    intr;
  93.  
  94. EXPORT    BOOL    openremote    __PR((void));
  95. EXPORT    void    opentape    __PR((void));
  96. EXPORT    void    closetape    __PR((void));
  97. EXPORT    void    changetape    __PR((void));
  98. EXPORT    void    nexttape    __PR((void));
  99. EXPORT    void    initbuf        __PR((int nblocks));
  100. EXPORT    void    markeof        __PR((void));
  101. EXPORT    void    syncbuf        __PR((void));
  102. EXPORT    int    readblock    __PR((char* buf));
  103. LOCAL    int    readtblock    __PR((char* buf, int amount));
  104. LOCAL    void    readbuf        __PR((void));
  105. EXPORT    int    readtape    __PR((char* buf, int amount));
  106. EXPORT    void    *get_block    __PR((void));
  107. EXPORT    void    put_block    __PR((void));
  108. EXPORT    void    writeblock    __PR((char* buf));
  109. EXPORT    int    writetape    __PR((char* buf, int amount));
  110. LOCAL    void    writebuf    __PR((void));
  111. LOCAL    void    flushbuf    __PR((void));
  112. EXPORT    void    writeempty    __PR((void));
  113. EXPORT    void    weof        __PR((void));
  114. EXPORT    void    buf_sync    __PR((void));
  115. EXPORT    void    buf_drain    __PR((void));
  116. EXPORT    int    buf_wait    __PR((int amount));
  117. EXPORT    void    buf_wake    __PR((int amount));
  118. EXPORT    int    buf_rwait    __PR((int amount));
  119. EXPORT    void    buf_rwake    __PR((int amount));
  120. EXPORT    void    buf_resume    __PR((void));
  121. EXPORT    void    backtape    __PR((void));
  122. EXPORT    int    mtioctl        __PR((int cmd, int count));
  123. EXPORT    long    mtseek        __PR((long offset, int whence));
  124. EXPORT    int    tblocks        __PR((void));
  125. EXPORT    void    prstats        __PR((void));
  126. EXPORT    BOOL    checkerrs    __PR((void));
  127. EXPORT    void    exprstats    __PR((int ret));
  128. EXPORT    void    excomerrno    __PR((int err, char* fmt, ...)) __printflike__(2, 3);
  129. EXPORT    void    excomerr    __PR((char* fmt, ...)) __printflike__(1, 2);
  130. EXPORT    void    die        __PR((int err));
  131. LOCAL    void    compressopen    __PR((void));
  132.  
  133. EXPORT BOOL
  134. openremote()
  135. {
  136.     register char *hp;
  137.     register char *fp;
  138.     register int  i;
  139.  
  140.     if ((!nullout || (uflag || rflag)) && strchr(tarfile, ':')) {
  141.  
  142. #ifdef    USE_REMOTE
  143.         isremote = TRUE;
  144.         remfn = strchr(tarfile, ':');
  145.         for (fp = tarfile, hp = host, i = 1;
  146.                 fp < remfn && i < sizeof(host); i++) {
  147.             *hp++ = *fp++;
  148.         }
  149.         *hp = '\0';
  150.         remfn++;
  151.         if (debug)
  152.             errmsgno(EX_BAD, "Remote: %s Host: %s file: %s\n",
  153.                             tarfile, host, remfn);
  154.  
  155.         if ((remfd = rmtgetconn(host, bigsize)) < 0)
  156.             comerrno(EX_BAD, "Cannot get connection to '%s'.\n",
  157.                 /* errno not valid !! */        host);
  158. #else
  159.         comerrno(EX_BAD, "Remote tape support not present.\n");
  160. #endif
  161.     }
  162.     return (isremote);
  163. }
  164.  
  165. EXPORT void
  166. opentape()
  167. {
  168.     int    n = 0;
  169.  
  170.     if (nullout && !(uflag || rflag)) {
  171.         tarfile = "null";
  172.         tarf = (FILE *)NULL;
  173.     } else if (streql(tarfile, "-")) {
  174.         if (cflag) {
  175.             tarfile = "stdout";
  176.             tarf = stdout;
  177.         } else {
  178.             tarfile = "stdin";
  179.             tarf = stdin;
  180.             multblk = TRUE;
  181.         }
  182.         setbuf(tarf, (char *)NULL);
  183. #if    defined(__CYGWIN32__)
  184.         setmode(fileno(tarf), O_BINARY);
  185. #endif
  186.     } else if (isremote) {
  187. #ifdef    USE_REMOTE
  188.         /*
  189.          * isremote will always be FALSE if USE_REMOTE is not defined.
  190.          * NOTE any open flag bejond O_RDWR is not portable across
  191.          * different platforms. The remote tape library will check
  192.          * whether the current /etc/rmt server supports symbolic
  193.          * open flags. If there is no symbolic support in the
  194.          * remote server, our rmt client code will mask off all
  195.          * non portable bits.
  196.          */
  197.         while (rmtopen(remfd, remfn, (cflag ? O_RDWR|O_CREAT:O_RDONLY)|O_BINARY) < 0) {
  198.             if (!wready || n++ > 6 || geterrno() != EIO)
  199.                 comerr("Cannot open remote '%s'.\n", tarfile);
  200.             else
  201.                 sleep(10);
  202.         }
  203. #endif    
  204.     } else {
  205.         FINFO    finfo;
  206.     extern    BOOL    follow;
  207.     extern    BOOL    fcompat;
  208.  
  209.         if (fcompat && cflag) {
  210.             /*
  211.              * The old syntax has a high risk of corrupting
  212.              * files if the user disorders the args.
  213.              * For this reason, we do not allow to overwrite
  214.              * a plain file in compat mode.
  215.              * XXX What if we implement 'r' & 'u' ???
  216.              */
  217.             follow++;
  218.             n = getinfo(tarfile, &finfo);
  219.             follow--;
  220.             if (n >= 0 && is_file(&finfo) && finfo.f_size > 0L) {
  221.                 comerrno(EX_BAD,
  222.                 "Will not overwrite non empty plain files in compat mode.\n");
  223.             }
  224.         }
  225.  
  226.         n = 0;
  227.         while ((tarf = fileopen(tarfile, cflag?"rwcub":"rub")) ==
  228.                                 (FILE *)NULL) {
  229.             if (!wready || n++ > 6 || geterrno() != EIO)
  230.                 comerr("Cannot open '%s'.\n", tarfile);
  231.             else
  232.                 sleep(10);
  233.         }
  234.     }
  235.     if (!isremote && (!nullout || (uflag || rflag))) {
  236.         file_raise(tarf, FALSE);
  237.         checkarch(tarf);
  238.     }
  239.     vpr = tarf == stdout ? stderr : stdout;
  240.  
  241.     if (zflag || bzflag) {
  242.         extern    long    tape_dev;
  243.         extern    long    tape_ino;
  244.  
  245.         if (isremote)
  246.             comerrno(EX_BAD, "Cannot compress remote archives (yet).\n");
  247.         if (tape_dev || tape_ino)
  248.             compressopen();
  249.         else
  250.             comerrno(EX_BAD, "Can only compress files.\n");
  251.     }
  252.  
  253. #ifdef    timerclear
  254.     if (showtime && gettimeofday(&starttime, (struct timezone *)0) < 0)
  255.         comerr("Cannot get starttime\n");
  256. #endif
  257. }
  258.  
  259. EXPORT void
  260. closetape()
  261. {
  262.     if (isremote) {
  263. #ifdef    USE_REMOTE
  264.         /*
  265.          * isremote will always be FALSE if USE_REMOTE is not defined.
  266.          */
  267.         if (rmtclose(remfd) < 0)
  268.             errmsg("Remote close failed.\n");
  269. #endif
  270.     } else {
  271.         if (tarf)
  272.             fclose(tarf);
  273.     }
  274. }
  275.  
  276. EXPORT void
  277. changetape()
  278. {
  279.     char    ans[2];
  280.  
  281.     prstats();
  282.     stats->Tblocks += stats->blocks;
  283.     stats->Tparts += stats->parts;
  284.     stats->blocks = 0L;
  285.     stats->parts = 0L;
  286.     closetape();
  287.     errmsgno(EX_BAD, "Mount volume #%d and hit <RETURN>", ++stats->volno);
  288.     fgetline(tty, ans, sizeof(ans));
  289.     if (feof(tty))
  290.         exit(1);
  291.     opentape();
  292. }
  293.  
  294. EXPORT void
  295. nexttape()
  296. {
  297.     weof();
  298. #ifdef    FIFO
  299.     if (use_fifo) {
  300.         fifo_chtape();
  301.     } else
  302. #endif
  303.     changetape();
  304.     if (intr)
  305.         exit(2);
  306. }
  307.  
  308. EXPORT void
  309. initbuf(nblocks)
  310.     int    nblocks;
  311. {
  312.     pid = getpid();
  313.     bufsize = bigsize = nblocks * TBLOCK;
  314. #ifdef    FIFO
  315.     if (use_fifo) {
  316.         initfifo();
  317.     } else
  318. #endif
  319.     {
  320.         if ((bigptr = bigbuf = malloc((unsigned) bufsize)) == NULL)
  321.             comerr("Cannot alloc buf.\n");
  322.         fillbytes(bigbuf, bufsize, '\0');
  323.     }
  324.     stats->blocksize = bigsize;
  325.     stats->volno = 1;
  326.     stats->swapflg = -1;
  327. }
  328.  
  329. EXPORT void
  330. markeof()
  331. {
  332. #ifdef    FIFO
  333.     if (use_fifo) {
  334.         /*
  335.          * Remember current FIFO status.
  336.          */
  337.     }
  338. #endif
  339.     eofptr = bigptr - TBLOCK;
  340.  
  341.     if (debug) {
  342.         error("Blocks: %d\n", tblocks());
  343.         error("bigptr - bigbuff: %d %p %p %p lastsize: %ld\n",
  344.             bigptr - bigbuf, bigbuf, bigptr, eofptr, stats->lastsize);
  345.     }
  346. }
  347.  
  348. EXPORT void
  349. syncbuf()
  350. {
  351. #ifdef    FIFO
  352.     if (use_fifo) {
  353.         /*
  354.          * Switch FIFO direction.
  355.          */
  356.         excomerr("Cannot update tape with FIFO.\n");
  357.     }
  358. #endif
  359.     bigptr = eofptr;
  360.     bigcnt = eofptr - bigbuf;
  361. }
  362.  
  363. EXPORT int
  364. readblock(buf)
  365.     char    *buf;
  366. {
  367.     if (buf_rwait(TBLOCK) == 0)
  368.         return (EOF);
  369.     movebytes(bigptr, buf, TBLOCK);
  370.     buf_rwake(TBLOCK);
  371.     return TBLOCK;
  372. }
  373.  
  374. LOCAL int
  375. readtblock(buf, amount)
  376.     char    *buf;
  377.     int    amount;
  378. {
  379.     int    cnt;
  380.  
  381.     stats->reading = TRUE;
  382.     if (isremote) {
  383. #ifdef    USE_REMOTE
  384.         /*
  385.          * isremote will always be FALSE if USE_REMOTE is not defined.
  386.          */
  387.         if ((cnt = rmtread(remfd, buf, amount)) < 0)
  388.             excomerr("Error reading '%s'.\n", tarfile);
  389. #endif
  390.     } else {
  391.         if ((cnt = ffileread(tarf, buf, amount)) < 0)
  392.             excomerr("Error reading '%s'.\n", tarfile);
  393.     }
  394.     return (cnt);
  395. }
  396.  
  397. LOCAL void
  398. readbuf()
  399. {
  400.     bigcnt = readtape(bigbuf, bigsize);    
  401.     bigptr = bigbuf;
  402. }
  403.  
  404. EXPORT int
  405. readtape(buf, amount)
  406.     char    *buf;
  407.     int    amount;
  408. {
  409.     int    amt;
  410.     int    cnt;
  411.     char    *bp;
  412.     int    size;
  413.  
  414.     amt = 0;
  415.     bp = buf;
  416.     size = amount;
  417.  
  418.     do {
  419.         cnt = readtblock(bp, size);
  420.  
  421.         amt += cnt;
  422.         bp += cnt;
  423.         size -= cnt;
  424.     } while (amt < amount && cnt > 0 && multblk);
  425.  
  426.     if (amt == 0)
  427.         return (amt);
  428.     if (amt < TBLOCK)
  429.         excomerrno(EX_BAD, "Error reading '%s' size (%d) too small.\n",
  430.                             tarfile, amt);
  431.     /*
  432.      * First block
  433.      */
  434.     if (stats->swapflg < 0) {
  435.         if ((amt % TBLOCK) != 0)
  436.             comerrno(EX_BAD, "Invalid blocksize %d bytes.\n", amt);
  437.         if (amt < amount) {
  438.             stats->blocksize = bigsize = amt;
  439. #ifdef    FIFO
  440.             if (use_fifo)
  441.                 fifo_ibs_shrink(amt);
  442. #endif
  443.             errmsgno(EX_BAD, "Blocksize = %ld records.\n",
  444.                         stats->blocksize/TBLOCK);
  445.         }
  446.     }
  447.     if (stats->swapflg > 0)
  448.         swabbytes(buf, amt);
  449.  
  450.     if (amt == stats->blocksize)
  451.         stats->blocks++;
  452.     else
  453.         stats->parts += amt;
  454.     stats->lastsize = amt;
  455. #ifdef    DEBUG
  456.     error("readbuf: cnt: %d.\n", amt);
  457. #endif
  458.     return (amt);
  459. }
  460.  
  461. /*#define    MY_SWABBYTES*/
  462. #ifdef    MY_SWABBYTES
  463. #define    DO8(a)    a;a;a;a;a;a;a;a;
  464.  
  465. void swabbytes(bp, cnt)
  466.     register char    *bp;
  467.     register int    cnt;
  468. {
  469.     register char    c;
  470.  
  471.     cnt /= 2;    /* even count only */
  472.     while ((cnt -= 8) >= 0) {
  473.         DO8(c = *bp++; bp[-1] = *bp; *bp++ = c;);
  474.     }
  475.     cnt += 8;
  476.  
  477.     while (--cnt >= 0) {
  478.         c = *bp++; bp[-1] = *bp; *bp++ = c;
  479.     }
  480. }
  481. #endif
  482.  
  483. EXPORT void *
  484. get_block()
  485. {
  486.     buf_wait(TBLOCK);
  487.     return ((void *)bigptr);
  488. }
  489.  
  490. EXPORT void
  491. put_block()
  492. {
  493.     buf_wake(TBLOCK);
  494. }
  495.  
  496. EXPORT void
  497. writeblock(buf)
  498.     char    *buf;
  499. {
  500.     buf_wait(TBLOCK);
  501.     movebytes(buf, bigptr, TBLOCK);
  502.     buf_wake(TBLOCK);
  503. }
  504.  
  505. EXPORT int
  506. writetape(buf, amount)
  507.     char    *buf;
  508.     int    amount;
  509. {
  510.     int    cnt;
  511.     int    err = 0;
  512.                     /* hartes oder weiches EOF ??? */
  513.                     /* d.h. < 0 oder <= 0          */
  514.     stats->reading = FALSE;
  515.     if (nullout) {
  516.         cnt = amount;
  517. #ifdef    USE_REMOTE
  518.     } else if (isremote) {
  519.         cnt = rmtwrite(remfd, buf, amount);
  520. #endif
  521.     } else {
  522.         cnt = ffilewrite(tarf, buf, amount);
  523.     }
  524.     if (cnt == 0) {
  525.         err = EFBIG;
  526.     } else if (cnt < 0) {
  527.         err = geterrno();
  528.     }
  529.     if (cnt <= 0)
  530.         excomerrno(err, "Error writing '%s'.\n", tarfile);
  531.  
  532.     if (cnt == stats->blocksize)
  533.         stats->blocks++;
  534.     else
  535.         stats->parts += cnt;
  536.     return (cnt);
  537. }
  538.  
  539. LOCAL void
  540. writebuf()
  541. {
  542.     long    cnt;
  543.  
  544.     cnt = writetape(bigbuf, bigsize);
  545.  
  546.     bigptr = bigbuf;
  547.     bigcnt = 0;
  548. }
  549.  
  550. LOCAL void
  551. flushbuf()
  552. {
  553.     long    cnt;
  554.  
  555. #ifdef    FIFO
  556.     if (!use_fifo)
  557. #endif
  558.     {
  559.         cnt = writetape(bigbuf, bigcnt);
  560.  
  561.         bigptr = bigbuf;
  562.         bigcnt = 0;
  563.     }
  564. }
  565.  
  566. EXPORT void
  567. writeempty()
  568. {
  569.     char    buf[TBLOCK];
  570.  
  571.     fillbytes(buf, TBLOCK, '\0');
  572.     writeblock(buf);
  573. }
  574.  
  575. EXPORT void
  576. weof()
  577. {
  578.     writeempty();
  579.     writeempty();
  580.     if (!partial)
  581.         buf_sync();
  582.     flushbuf();
  583. }
  584.  
  585. EXPORT void
  586. buf_sync()
  587. {
  588. #ifdef    FIFO
  589.     if (use_fifo) {
  590.         fifo_sync();
  591.     } else
  592. #endif
  593.     {
  594.         fillbytes(bigptr, bigsize - bigcnt, '\0');
  595.         bigcnt = bigsize;
  596.     }
  597. }
  598.  
  599. EXPORT void
  600. buf_drain()
  601. {
  602. #ifdef    FIFO
  603.     if (use_fifo) {
  604.         fifo_oflush();
  605.         wait(0);
  606.     }
  607. #endif
  608. }
  609.  
  610. EXPORT int
  611. buf_wait(amount)
  612.     int    amount;
  613. {
  614. #ifdef    FIFO
  615.     if (use_fifo) {
  616.         return (fifo_iwait(amount));
  617.     } else
  618. #endif
  619.     {
  620.         if (bigcnt >= bigsize)
  621.             writebuf();
  622.         return (bigsize - bigcnt);
  623.     }
  624. }
  625.  
  626. EXPORT void
  627. buf_wake(amount)
  628.     int    amount;
  629. {
  630. #ifdef    FIFO
  631.     if (use_fifo) {
  632.         fifo_owake(amount);
  633.     } else
  634. #endif
  635.     {
  636.         bigptr += amount;
  637.         bigcnt += amount;
  638.     }
  639. }
  640.  
  641. EXPORT int
  642. buf_rwait(amount)
  643.     int    amount;
  644. {
  645. #ifdef    FIFO
  646.     if (use_fifo) {
  647.         return (fifo_owait(amount));
  648.     } else
  649. #endif
  650.     {
  651. /*        if (bigcnt < amount)*/ /* neu ?? */
  652.         if (bigcnt <= 0)
  653.             readbuf();
  654.         return (bigcnt);
  655.     }
  656. }
  657.  
  658. EXPORT void
  659. buf_rwake(amount)
  660.     int    amount;
  661. {
  662. #ifdef    FIFO
  663.     if (use_fifo) {
  664.         fifo_iwake(amount);
  665.     } else
  666. #endif
  667.     {
  668.         bigptr += amount;
  669.         bigcnt -= amount;
  670.     }
  671. }
  672.  
  673. EXPORT void
  674. buf_resume()
  675. {
  676.     stats->swapflg = swapflg;    /* copy over for fifo process */
  677.     bigsize = stats->blocksize;    /* copy over for tar process */
  678. #ifdef    FIFO
  679.     if (use_fifo)
  680.         fifo_resume();
  681. #endif
  682. }
  683.  
  684. EXPORT void
  685. backtape()
  686. {
  687.     long    ret;
  688.  
  689.     if (debug) {
  690.         error("Blocks: %d\n", tblocks());
  691.         error("filepos: %ld seeking to: %ld bigsize: %d\n",
  692.         mtseek(0L, SEEK_CUR), mtseek(0L, SEEK_CUR)-stats->lastsize, bigsize);
  693.     }
  694.  
  695.     if (mtioctl(MTNOP, 0) >= 0) {
  696.         if (debug)
  697.             error("Is a tape: BSR 1...\n");
  698.         ret = mtioctl(MTBSR, 1);
  699.     } else {
  700.         if (debug)
  701.             error("Is a file: lseek()\n");
  702.         ret = mtseek(-stats->lastsize, SEEK_CUR);
  703.     }
  704.     if (ret < 0)
  705.         excomerr("Cannot backspace tape.\n");
  706.  
  707.     if (stats->lastsize == stats->blocksize)
  708.         stats->blocks--;
  709.     else
  710.         stats->parts -= stats->lastsize;
  711. }
  712.  
  713. EXPORT int
  714. mtioctl(cmd, count)
  715.     int    cmd;
  716.     int    count;
  717. {
  718.     int    ret;
  719.  
  720.     if (nullout && !(uflag || rflag)) {
  721.         return (0);
  722. #ifdef    USE_REMOTE
  723.     } else if (isremote) {
  724.         ret = rmtioctl(remfd, cmd, count);
  725. #endif
  726.     } else {
  727. #ifdef    MTIOCTOP
  728.         struct mtop mtop;
  729.  
  730.         mtop.mt_op = cmd;
  731.         mtop.mt_count = count;
  732.  
  733.         ret = ioctl(fdown(tarf), MTIOCTOP, &mtop);
  734. #else
  735.         return (-1);
  736. #endif
  737.     }
  738.     if (ret < 0 && debug)
  739.         errmsg("Error sending mtioctl(%d, %d) to '%s'.\n", cmd, count, tarfile);
  740.     return (ret);
  741. }
  742.  
  743. EXPORT long
  744. mtseek(offset, whence)
  745.     long    offset;
  746.     int    whence;
  747. {
  748.     if (nullout && !(uflag || rflag)) {
  749.         return (0L);
  750. #ifdef    USE_REMOTE
  751.     } else if (isremote) {
  752.         return (rmtseek(remfd, offset, whence));
  753. #endif
  754.     } else {
  755.         return (fseek(tarf, offset, whence));
  756.     }
  757. }
  758.  
  759. EXPORT int
  760. tblocks()
  761. {
  762.     long    fifo_cnt = 0;
  763.  
  764. #ifdef    FIFO
  765.     if (use_fifo)
  766.         fifo_cnt = fifo_amount()/TBLOCK;
  767. #endif
  768.     if (debug) {
  769.         error("blocks: %ld blocksize: %ld parts: %ld bigcnt: %ld fifo_cnt: %ld\n", 
  770.         stats->blocks, stats->blocksize, stats->parts, bigcnt, fifo_cnt);
  771.     }
  772.     if (stats->reading)
  773.         return (-fifo_cnt + (stats->blocks * stats->blocksize +
  774.                     stats->parts - (bigcnt+TBLOCK))/TBLOCK);
  775.     else
  776.         return (fifo_cnt + (stats->blocks * stats->blocksize +
  777.                     stats->parts + bigcnt)/TBLOCK);
  778. }
  779.  
  780. EXPORT void
  781. prstats()
  782. {
  783.     Llong    bytes;
  784.     long    kbytes;
  785.     long    hibytes;
  786.     long    lobytes;
  787.     char    cbytes[32];
  788.     int    per;
  789. #ifdef    timerclear
  790.     int    sec;
  791.     int    usec;
  792.     int    tmsec;
  793. #endif
  794.  
  795.     if (no_stats)
  796.         return;
  797.     if (pid == 0)    /* child */
  798.         return;
  799.  
  800. #ifdef    timerclear
  801.     if (showtime && gettimeofday(&stoptime, (struct timezone *)0) < 0)
  802.         comerr("Cannot get stoptime\n");
  803. #endif
  804. #ifdef    FIFO
  805.     if (use_fifo && do_fifostats)
  806.         fifo_stats();
  807. #endif
  808.  
  809.     bytes = (Llong)stats->blocks * (Llong)stats->blocksize + stats->parts;
  810.     kbytes = bytes >> 10;
  811.     per = ((bytes&1023)<<10)/10485;
  812.  
  813.     cbytes[0] = '\0';
  814.     hibytes = bytes / 1000000000;
  815.     lobytes = bytes % 1000000000;
  816.     if (hibytes)
  817.         sprintf(cbytes, "%ld%09ld", hibytes, lobytes);
  818.     else
  819.         sprintf(cbytes, "%ld", lobytes);
  820.  
  821.     errmsgno(EX_BAD,
  822.         "%ld blocks + %ld bytes (total of %s bytes = %ld.%02dk).\n",
  823.         stats->blocks, stats->parts, cbytes, kbytes, per);
  824.  
  825.     if (stats->Tblocks + stats->Tparts) {
  826.         bytes = (Llong)stats->Tblocks * (Llong)stats->blocksize +
  827.                                 stats->Tparts;
  828.         kbytes = bytes >> 10;
  829.         per = ((bytes&1023)<<10)/10485;
  830.  
  831.         cbytes[0] = '\0';
  832.         hibytes = bytes / 1000000000;
  833.         lobytes = bytes % 1000000000;
  834.         if (hibytes)
  835.             sprintf(cbytes, "%ld%09ld", hibytes, lobytes);
  836.         else
  837.             sprintf(cbytes, "%ld", lobytes);
  838.  
  839.         errmsgno(EX_BAD,
  840.         "Total %ld blocks + %ld bytes (total of %s bytes = %ld.%02dk).\n",
  841.         stats->Tblocks, stats->Tparts, cbytes, kbytes, per);
  842.     }
  843. #ifdef    timerclear
  844.     if (showtime) {
  845.         Llong    kbs;
  846.  
  847.         sec = stoptime.tv_sec - starttime.tv_sec;
  848.         usec = stoptime.tv_usec - starttime.tv_usec;
  849.         tmsec = sec*1000 + usec/1000;
  850.         if (usec < 0) {
  851.             sec--;
  852.             usec += 1000000;
  853.         }
  854.         if (tmsec == 0)
  855.             tmsec++;
  856.  
  857.         kbs = (Llong)kbytes*(Llong)1000/tmsec;
  858.         lobytes = kbs;
  859.  
  860.         errmsgno(EX_BAD, "Total time %d.%03dsec (%ld kBytes/sec)\n",
  861.                 sec, usec/1000, lobytes);
  862.     }
  863. #endif
  864. }
  865.  
  866. EXPORT BOOL
  867. checkerrs()
  868. {
  869.     if (xstats.s_staterrs    ||
  870.         xstats.s_openerrs    ||
  871.         xstats.s_rwerrs    ||
  872.         xstats.s_misslinks    ||
  873.         xstats.s_toolong    ||
  874.         xstats.s_toobig    ||
  875.         xstats.s_isspecial    ||
  876.         xstats.s_sizeerrs) {
  877.         if (nowarn || no_stats || (pid == 0)/* child */)
  878.             return (TRUE);
  879.  
  880.         errmsgno(EX_BAD, "The following problems occurred during archive processing:\n");
  881.         errmsgno(EX_BAD, "Cannot: stat %d, open %d, read/write %d. Size changed %d.\n",
  882.                 xstats.s_staterrs,
  883.                 xstats.s_openerrs,
  884.                 xstats.s_rwerrs,
  885.                 xstats.s_sizeerrs);
  886.         errmsgno(EX_BAD, "Missing links %d, Name too long %d, File too big %d, Not dumped %d.\n",
  887.                 xstats.s_misslinks,
  888.                 xstats.s_toolong,
  889.                 xstats.s_toobig,
  890.                 xstats.s_isspecial);
  891.         return (TRUE);
  892.     }
  893.     return (FALSE);
  894. }
  895.  
  896. EXPORT void
  897. exprstats(ret)
  898.     int    ret;
  899. {
  900.     prstats();
  901.     exit(ret);
  902. }
  903.  
  904. /* VARARGS2 */
  905. #ifdef    PROTOTYPES
  906. EXPORT void
  907. excomerrno(int err, char *fmt, ...)
  908. #else
  909. EXPORT void
  910. excomerrno(err, fmt, va_alist)
  911.     int    err;
  912.     char    *fmt;
  913.     va_dcl
  914. #endif
  915. {
  916.     va_list    args;
  917.  
  918. #ifdef    PROTOTYPES
  919.     va_start(args, fmt);
  920. #else
  921.     va_start(args);
  922. #endif
  923.     errmsgno(err, "%r", fmt, args);
  924.     va_end(args);
  925. #ifdef    FIFO
  926.     fifo_exit();
  927. #endif
  928.     exprstats(err);
  929.     /* NOTREACHED */
  930. }
  931.  
  932. /* VARARGS1 */
  933. #ifdef    PROTOTYPES
  934. EXPORT void
  935. excomerr(char *fmt, ...)
  936. #else
  937. EXPORT void
  938. excomerr(fmt, va_alist)
  939.     char    *fmt;
  940.     va_dcl
  941. #endif
  942. {
  943.     va_list    args;
  944.     int    err = geterrno();
  945.  
  946. #ifdef    PROTOTYPES
  947.     va_start(args, fmt);
  948. #else
  949.     va_start(args);
  950. #endif
  951.     errmsgno(err, "%r", fmt, args);
  952.     va_end(args);
  953. #ifdef    FIFO
  954.     fifo_exit();
  955. #endif
  956.     exprstats(err);
  957.     /* NOTREACHED */
  958. }
  959.  
  960. EXPORT void
  961. die(err)
  962.     int    err;
  963. {
  964.     excomerrno(err, "Cannot recover from error - exiting.\n");
  965. }
  966.  
  967. /*
  968.  * Quick hack to implement a -z flag. May be changed soon.
  969.  */
  970. #include <signal.h>
  971. #if    defined(SIGDEFER) || defined(SVR4)
  972. #define    signal    sigset
  973. #endif
  974. LOCAL void
  975. compressopen()
  976. {
  977.     FILE    *pp[2];
  978.     int    mypid;
  979.     char    *zip_prog = "gzip";
  980.         
  981.     if (bzflag)
  982.         zip_prog = "bzip2";
  983.  
  984.     multblk = TRUE;
  985.  
  986.     if (fpipe(pp) == 0)
  987.         comerr("Compress pipe failed\n");
  988.     mypid = fork();
  989.     if (mypid < 0)
  990.         comerr("Compress fork failed\n");
  991.     if (mypid == 0) {
  992.         FILE    *null;
  993.         char    *flg = getenv("STAR_COMPRESS_FLAG"); /* Temporary ? */
  994.  
  995.         signal(SIGQUIT, SIG_IGN);
  996.         if (cflag)
  997.             fclose(pp[1]);
  998.         else
  999.             fclose(pp[0]);
  1000.  
  1001. #if    defined(__CYGWIN32__)
  1002.         if (cflag)
  1003.             setmode(fileno(pp[0]), O_BINARY);
  1004.         else
  1005.             setmode(fileno(pp[1]), O_BINARY);
  1006. #endif
  1007.  
  1008.         /* We don't want to see errors */
  1009.         null = fileopen("/dev/null", "rw");
  1010.  
  1011.         if (cflag)
  1012.             fexecl(zip_prog, pp[0], tarf, null, zip_prog, flg, NULL);
  1013.         else
  1014.             fexecl(zip_prog, tarf, pp[1], null, zip_prog, "-d", NULL);
  1015.         errmsg("Compress: exec of '%s' failed\n", zip_prog);
  1016.         _exit(-1);
  1017.     }
  1018.     fclose(tarf);
  1019.     if (cflag) {
  1020.         tarf = pp[1];
  1021.         fclose(pp[0]);
  1022.     } else {
  1023.         tarf = pp[0];
  1024.         fclose(pp[1]);
  1025.     }
  1026. }
  1027.