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 / hole.c < prev    next >
C/C++ Source or Header  |  2000-05-07  |  17KB  |  727 lines

  1. /*#define    DEBUG*/
  2. /* @(#)hole.c    1.18 00/05/07 Copyright 1990 J. Schilling */
  3. #ifndef lint
  4. static    char sccsid[] =
  5.     "@(#)hole.c    1.18 00/05/07 Copyright 1990 J. Schilling";
  6. #endif
  7. /*
  8.  *    Handle files with holes (sparse files)
  9.  *
  10.  *    Copyright (c) 1990 J. Schilling
  11.  */
  12. /*
  13.  * This program is free software; you can redistribute it and/or modify
  14.  * it under the terms of the GNU General Public License as published by
  15.  * the Free Software Foundation; either version 2, or (at your option)
  16.  * any later version.
  17.  *
  18.  * This program is distributed in the hope that it will be useful,
  19.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  * GNU General Public License for more details.
  22.  *
  23.  * You should have received a copy of the GNU General Public License
  24.  * along with this program; see the file COPYING.  If not, write to
  25.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  26.  */
  27.  
  28. #include <mconfig.h>
  29. #include <stdio.h>
  30. #include <stdxlib.h>
  31. #include <sys/types.h>
  32. #include <unixstd.h>
  33. #include <standard.h>
  34. #include <schily.h>
  35. #include "star.h"
  36. #include "props.h"
  37. #include "table.h"
  38. #include "starsubs.h"
  39. #ifdef    sun
  40. #    include <sys/filio.h>
  41. #    if    _FIOAI == _FIOOBSOLETE67
  42. #    undef    _FIOAI
  43. #    endif
  44. #    ifdef    _FIOAI
  45. #    include <sys/fs/ufs_filio.h>
  46. #    endif
  47. #endif    /* sun */
  48.  
  49. #ifdef DEBUG
  50. #define    EDEBUG(a)    if (debug) error a
  51. #else
  52. #define    EDEBUG(a)
  53. #endif
  54.  
  55. extern    int    bigcnt;
  56. extern    char    *bigptr;
  57.  
  58. extern    BOOL    debug;
  59. extern    BOOL    nullout;
  60.  
  61. char    zeroblk[TBLOCK];
  62.  
  63. typedef    struct {
  64.     FILE    *fh_file;
  65.     char    *fh_name;
  66.     long    fh_size;
  67.     long    fh_newpos;
  68.     sp_t    *fh_sparse;
  69.     int    fh_nsparse;
  70.     int    fh_spindex;
  71.     int    fh_diffs;
  72. } fh_t;
  73.  
  74. LOCAL    int    force_hole_func    __PR((fh_t * fh, char* p, int amount));
  75. EXPORT    int    get_forced_hole    __PR((FILE * f, FINFO * info));
  76. LOCAL    int    get_sparse_func    __PR((fh_t * fh, char* p, int amount));
  77. LOCAL    int    cmp_sparse_func    __PR((fh_t * fh, char* p, int amount));
  78. LOCAL    int    put_sparse_func    __PR((fh_t * fh, char* p, int amount));
  79. LOCAL    sp_t*    grow_sp_list    __PR((sp_t * sparse, int* nspp));
  80. LOCAL    sp_t*    get_sp_list    __PR((FINFO * info));
  81. LOCAL    int    mk_sp_list    __PR((int *fp, FINFO * info, sp_t ** spp));
  82. EXPORT    int    gnu_skip_extended __PR((TCB * ptb));
  83. EXPORT    int    get_sparse    __PR((FILE * f, FINFO * info));
  84. EXPORT    BOOL    cmp_sparse    __PR((FILE * f, FINFO * info));
  85. EXPORT    void    put_sparse    __PR((int *fp, FINFO * info));
  86. LOCAL    void    put_sp_list    __PR((FINFO * info, sp_t * sparse, int nsparse));
  87.  
  88. #define    vp_force_hole_func ((int(*)__PR((void *, char *, int)))force_hole_func)
  89.  
  90. LOCAL int
  91. force_hole_func(fh, p, amount)
  92.     register fh_t    *fh;
  93.     register char    *p;
  94.          int    amount;
  95. {
  96.     register int    cnt;
  97.  
  98.     fh->fh_newpos += amount;
  99.     if (amount < fh->fh_size &&
  100.                 cmpbytes(bigptr, zeroblk, amount) >= amount) {
  101.         if (lseek(fdown(fh->fh_file), fh->fh_newpos, SEEK_SET) < 0) {
  102.             xstats.s_rwerrs++;
  103.             errmsg("Error seeking '%s'.\n", fh->fh_name);
  104.         }
  105.  
  106.         fh->fh_size -= amount;
  107.         return (amount);
  108.     }
  109.     cnt = ffilewrite(fh->fh_file, p, amount);
  110.     fh->fh_size -= amount;
  111.     return (cnt);
  112. }
  113.  
  114. EXPORT BOOL
  115. get_forced_hole(f, info)
  116.     FILE    *f;
  117.     FINFO    *info;
  118. {
  119.     fh_t    fh;
  120.  
  121.     fh.fh_file = f;
  122.     fh.fh_name = info->f_name;
  123.     fh.fh_size = info->f_rsize;
  124.     fh.fh_newpos = 0L;
  125.     return (xt_file(info, vp_force_hole_func, &fh, TBLOCK, "writing"));
  126. }
  127.  
  128. #define    vp_get_sparse_func ((int(*)__PR((void *, char *, int)))get_sparse_func)
  129.  
  130. LOCAL int
  131. get_sparse_func(fh, p, amount)
  132.     register fh_t    *fh;
  133.     register char    *p;
  134.          int    amount;
  135. {
  136.     register int    cnt;
  137.  
  138.     EDEBUG(("amount: %d newpos: %d index: %d\n",
  139.                     amount, fh->fh_newpos, fh->fh_spindex));
  140.  
  141.     if (fh->fh_sparse[fh->fh_spindex].sp_offset > fh->fh_newpos) {
  142.  
  143.         EDEBUG(("seek to: %d\n",
  144.                 fh->fh_sparse[fh->fh_spindex].sp_offset));
  145.  
  146.         if (lseek(fdown(fh->fh_file),
  147.                 fh->fh_sparse[fh->fh_spindex].sp_offset, SEEK_SET) < 0) {
  148.             xstats.s_rwerrs++;
  149.             errmsg("Error seeking '%s'.\n", fh->fh_name);
  150.         }
  151.  
  152.         fh->fh_newpos = fh->fh_sparse[fh->fh_spindex].sp_offset;
  153.     }
  154.     EDEBUG(("write %d at: %d\n", amount, fh->fh_newpos));
  155.  
  156.     cnt = ffilewrite(fh->fh_file, p, amount);
  157.     fh->fh_size -= cnt;
  158.     fh->fh_newpos += cnt;
  159.  
  160.     EDEBUG(("off: %d numb: %d cnt: %d off+numb: %d newpos: %d index: %d\n", 
  161.         fh->fh_sparse[fh->fh_spindex].sp_offset,
  162.         fh->fh_sparse[fh->fh_spindex].sp_numbytes, cnt,
  163.         fh->fh_sparse[fh->fh_spindex].sp_offset +
  164.         fh->fh_sparse[fh->fh_spindex].sp_numbytes,
  165.         fh->fh_newpos,
  166.         fh->fh_spindex));
  167.  
  168.     if ((fh->fh_sparse[fh->fh_spindex].sp_offset +
  169.         fh->fh_sparse[fh->fh_spindex].sp_numbytes)
  170.                  <= fh->fh_newpos) {
  171.         fh->fh_spindex++;
  172.  
  173.         EDEBUG(("new index: %d\n", fh->fh_spindex));
  174.     }
  175.     EDEBUG(("return (%d)\n", cnt));
  176.     return (cnt);
  177. }
  178.  
  179. #define    vp_cmp_sparse_func ((int(*)__PR((void *, char *, int)))cmp_sparse_func)
  180.  
  181. LOCAL int
  182. cmp_sparse_func(fh, p, amount)
  183.     register fh_t    *fh;
  184.     register char    *p;
  185.          int    amount;
  186. {
  187.     register int    cnt;
  188.          char    *cmp_buf[TBLOCK];
  189.  
  190.     EDEBUG(("amount: %d newpos: %d index: %d\n",
  191.                     amount, fh->fh_newpos, fh->fh_spindex));
  192.     /*
  193.      * If we already found diffs we save time and only pass tape ...
  194.      */
  195.     if (fh->fh_diffs)
  196.         return (amount);
  197.  
  198.     if (fh->fh_sparse[fh->fh_spindex].sp_offset > fh->fh_newpos) {
  199.         EDEBUG(("seek to: %d\n",
  200.                 fh->fh_sparse[fh->fh_spindex].sp_offset));
  201.  
  202.         while (fh->fh_newpos < fh->fh_sparse[fh->fh_spindex].sp_offset){
  203.             register int    amt;
  204.  
  205.             amt = min(TBLOCK,
  206.                 fh->fh_sparse[fh->fh_spindex].sp_offset -
  207.                 fh->fh_newpos);
  208.  
  209.             cnt = ffileread(fh->fh_file, cmp_buf, amt);
  210.             if (cnt != amt)
  211.                 fh->fh_diffs++;
  212.  
  213.             if (cmpbytes(cmp_buf, zeroblk, amt) < cnt)
  214.                 fh->fh_diffs++;
  215.  
  216.             fh->fh_newpos += cnt;
  217.  
  218.             if (fh->fh_diffs)
  219.                 return (amount);
  220.         }
  221.     }
  222.     EDEBUG(("read %d at: %d\n", amount, fh->fh_newpos));
  223.  
  224.     cnt = ffileread(fh->fh_file, cmp_buf, amount);
  225.     if (cnt != amount)
  226.         fh->fh_diffs++;
  227.  
  228.     if (cmpbytes(cmp_buf, p, cnt) < cnt)
  229.         fh->fh_diffs++;
  230.  
  231.     fh->fh_size -= cnt;
  232.     fh->fh_newpos += cnt;
  233.  
  234.     EDEBUG(("off: %d numb: %d cnt: %d off+numb: %d newpos: %d index: %d\n", 
  235.         fh->fh_sparse[fh->fh_spindex].sp_offset,
  236.         fh->fh_sparse[fh->fh_spindex].sp_numbytes, cnt,
  237.         fh->fh_sparse[fh->fh_spindex].sp_offset +
  238.         fh->fh_sparse[fh->fh_spindex].sp_numbytes,
  239.         fh->fh_newpos,
  240.         fh->fh_spindex));
  241.  
  242.     if ((fh->fh_sparse[fh->fh_spindex].sp_offset +
  243.         fh->fh_sparse[fh->fh_spindex].sp_numbytes)
  244.                  <= fh->fh_newpos) {
  245.         fh->fh_spindex++;
  246.  
  247.         EDEBUG(("new index: %d\n", fh->fh_spindex));
  248.     }
  249.     EDEBUG(("return (%d) diffs: %d\n", cnt, fh->fh_diffs));
  250.     return (cnt);
  251. }
  252.  
  253. #define    vp_put_sparse_func ((int(*)__PR((void *, char *, int)))put_sparse_func)
  254.  
  255. LOCAL int
  256. put_sparse_func(fh, p, amount)
  257.     register fh_t    *fh;
  258.     register char    *p;
  259.          int    amount;
  260. {
  261.     register int    cnt;
  262.  
  263.     EDEBUG(("amount: %d newpos: %d index: %d\n",
  264.                     amount, fh->fh_newpos, fh->fh_spindex));
  265.  
  266.     if (fh->fh_spindex < fh->fh_nsparse &&
  267.         fh->fh_sparse[fh->fh_spindex].sp_offset > fh->fh_newpos) {
  268.  
  269.         EDEBUG(("seek to: %d\n",
  270.                 fh->fh_sparse[fh->fh_spindex].sp_offset));
  271.  
  272.         if (lseek(*(int *)(fh->fh_file),
  273.                 fh->fh_sparse[fh->fh_spindex].sp_offset, SEEK_SET) < 0) {
  274.             xstats.s_rwerrs++;
  275.             errmsg("Error seeking '%s'.\n", fh->fh_name);
  276.         }
  277.  
  278.         fh->fh_newpos = fh->fh_sparse[fh->fh_spindex].sp_offset;
  279.     }
  280.     EDEBUG(("read %d at: %d\n", amount, fh->fh_newpos));
  281.  
  282.     if (nullout) {
  283.         cnt = amount;
  284.         if (cnt > fh->fh_size)
  285.             cnt = fh->fh_size;
  286.     } else {
  287.         cnt = _fileread((int *)fh->fh_file, p, amount);
  288.     }
  289.     fh->fh_size -= cnt;
  290.     fh->fh_newpos += cnt;
  291. /*    if (cnt < TBLOCK)*/
  292. /*        fillbytes(&p[cnt], TBLOCK-cnt, '\0');*/
  293.  
  294.     EDEBUG(("off: %d numb: %d cnt: %d off+numb: %d newpos: %d index: %d\n", 
  295.         fh->fh_sparse[fh->fh_spindex].sp_offset,
  296.         fh->fh_sparse[fh->fh_spindex].sp_numbytes, cnt,
  297.         fh->fh_sparse[fh->fh_spindex].sp_offset +
  298.         fh->fh_sparse[fh->fh_spindex].sp_numbytes,
  299.         fh->fh_newpos,
  300.         fh->fh_spindex));
  301.  
  302.     if ((fh->fh_sparse[fh->fh_spindex].sp_offset +
  303.         fh->fh_sparse[fh->fh_spindex].sp_numbytes)
  304.                  <= fh->fh_newpos) {
  305.         fh->fh_spindex++;
  306.  
  307.         EDEBUG(("new index: %d\n", fh->fh_spindex));
  308.     }
  309.     EDEBUG(("return (%d)\n", cnt));
  310.     return (cnt);
  311. }
  312.  
  313. LOCAL sp_t *
  314. grow_sp_list(sparse, nspp)
  315.     sp_t    *sparse;
  316.     int    *nspp;
  317. {
  318.     sp_t    *new;
  319.  
  320.     if (*nspp < 512)
  321.         *nspp *= 2;
  322.     else
  323.         *nspp += 512;
  324.     new = (sp_t *)realloc(sparse, *nspp*sizeof(sp_t));
  325.     if (new == 0) {
  326.         errmsg("Cannot grow sparse buf.\n");
  327.         free(sparse);
  328.     }
  329.     return (new);
  330. }
  331.  
  332. LOCAL sp_t *
  333. get_sp_list(info)
  334.     FINFO    *info;
  335. {
  336.     TCB    tb;
  337.     TCB    *ptb = info->f_tcb;
  338.     sp_t    *sparse;
  339.     int    nsparse = 25;
  340.     int    extended;
  341.     register int    i;
  342.     register int    sparse_in_hdr = props.pr_sparse_in_hdr;
  343.     register int    ind;
  344.         char    *p;
  345. /*XXX*/extern int hdrtype;
  346.  
  347.     EDEBUG(("rsize: %d\n" , info->f_rsize));
  348.  
  349.     sparse = (sp_t *)malloc(nsparse*sizeof(sp_t));
  350.     if (sparse == 0) {
  351.         errmsg("Cannot alloc sparse buf.\n");
  352.         return (sparse);
  353.     }
  354.  
  355.     if (H_TYPE(hdrtype) == H_GNUTAR) {
  356.         p = (char *)ptb->gnu_in_dbuf.t_sp;
  357.     } else {
  358.         p = (char *)ptb->xstar_in_dbuf.t_sp;
  359.  
  360.         if (ptb->xstar_dbuf.t_prefix[0] == '\0' &&
  361.             ptb->xstar_in_dbuf.t_sp[0].t_offset[10] != '\0') {
  362.             static    BOOL    warned;
  363.             extern    BOOL    nowarn;
  364.  
  365.             if (!nowarn && !warned) {
  366.                 errmsgno(EX_BAD, "WARNING: Archive uses old sparse format. Please upgrade!\n");
  367.                 warned = TRUE;
  368.             }
  369.             sparse_in_hdr = SPARSE_IN_HDR;
  370.         }
  371.     }
  372.  
  373.     for (i= 0; i < sparse_in_hdr; i++) {
  374.         astoo(p, &sparse[i].sp_offset);   p += 12;
  375.         astoo(p, &sparse[i].sp_numbytes); p += 12;
  376.         if (sparse[i].sp_numbytes == 0)
  377.             break;
  378.     }
  379. #ifdef    DEBUG
  380.     if (debug) for (i = 0; i < sparse_in_hdr; i++) {
  381.         error("i: %d offset: %d numbytes: %d\n", i,
  382.                 sparse[i].sp_offset,
  383.                 sparse[i].sp_numbytes);
  384.         if (sparse[i].sp_numbytes == 0)
  385.             break;
  386.     }
  387. #endif
  388.     ind = sparse_in_hdr-SPARSE_EXT_HDR;
  389.  
  390.     if (H_TYPE(hdrtype) == H_GNUTAR)
  391.         extended = ptb->gnu_in_dbuf.t_isextended;
  392.     else
  393.         extended = ptb->xstar_in_dbuf.t_isextended;
  394.  
  395.     extended |= sparse_in_hdr == 0;
  396.  
  397.     EDEBUG(("isextended: %d\n", extended));
  398.  
  399.     ptb = &tb;    /* don't destroy orig TCB */
  400.     while (extended) {
  401.         if (readblock((char *)ptb) == EOF) {
  402.             free(sparse);
  403.             return (0);
  404.         }
  405.         if ((props.pr_flags & PR_GNU_SPARSE_BUG) == 0)
  406.             info->f_rsize -= TBLOCK;
  407.  
  408.         EDEBUG(("rsize: %d\n" , info->f_rsize));
  409.  
  410.         ind += SPARSE_EXT_HDR;
  411.  
  412.         EDEBUG(("ind: %d\n", ind));
  413.  
  414.         if (i+ind > nsparse+1) {
  415.             if ((sparse = grow_sp_list(sparse, &nsparse)) == 0)
  416.                 return ((sp_t *)0);
  417.         }
  418.         p = (char *)ptb;
  419.         for (i = 0; i < SPARSE_EXT_HDR; i++) {
  420.             astoo(p, &sparse[i+ind].sp_offset);   p += 12;
  421.             astoo(p, &sparse[i+ind].sp_numbytes); p += 12;
  422.  
  423.             EDEBUG(("i: %d offset: %d numbytes: %d\n", i,
  424.                 sparse[i+ind].sp_offset,
  425.                 sparse[i+ind].sp_numbytes));
  426.  
  427.             if (sparse[i+ind].sp_numbytes == 0)
  428.                 break;
  429.         }
  430.         extended = ptb->gnu_ext_dbuf.t_isextended;
  431.     }
  432. #ifdef    DEBUG
  433.     ind += i;
  434.     EDEBUG(("ind: %d\n", ind));
  435.     if (debug) for (i = 0; i < ind; i++) {
  436.         error("i: %d offset: %d numbytes: %d\n", i,
  437.                 sparse[i].sp_offset,
  438.                 sparse[i].sp_numbytes);
  439.         if (sparse[i].sp_numbytes == 0)
  440.             break;
  441.     }
  442.     EDEBUG(("rsize: %d\n" , info->f_rsize));
  443. #endif
  444.     return (sparse);
  445. }
  446.  
  447. LOCAL int
  448. mk_sp_list(fp, info, spp)
  449.     int    *fp;
  450.     FINFO    *info;
  451.     sp_t    **spp;
  452. {
  453.     char    rbuf[TBLOCK];
  454.     sp_t    *sparse;
  455.     int    nsparse = 25;
  456.     register int    amount = 0;
  457.     register long    pos = 0;
  458.     register int    i = 0;
  459.     register BOOL    data = FALSE;
  460.     register BOOL    use_ai = FALSE;
  461.     register BOOL    is_hole = FALSE;
  462. #ifdef    _FIOAI
  463.         int    fai_idx;
  464.     struct fioai    fai;
  465.     struct fioai    *faip;
  466. #    define    NFAI    1024
  467.     daddr_t        fai_arr[NFAI];
  468. #endif    /* _FIOAI */
  469.  
  470. #ifdef    _FIOAI
  471.     fai.fai_off = 0;
  472.     fai.fai_size = 512;
  473.     fai.fai_num = 1;
  474.     fai.fai_daddr = fai_arr;
  475.     use_ai = ioctl(*fp, _FIOAI, &fai) >= 0;    /* Use if operational*/
  476.     fai_idx = 0;
  477. #endif    /* _FIOAI */
  478.  
  479.     *spp = (sp_t *)0;
  480.     info->f_rsize = 0;
  481.     sparse = (sp_t *)malloc(nsparse*sizeof(sp_t));
  482.     if (sparse == 0) {
  483.         errmsg("Cannot alloc sparse buf.\n");
  484.         return (i);
  485.     }
  486.     for (;;) {
  487.         if (use_ai) {
  488. #ifdef    _FIOAI
  489.             if (fai_idx >= fai.fai_num) {
  490.                 fai.fai_off = pos;
  491.                 fai.fai_size = 512 * NFAI;
  492.                 fai.fai_num = NFAI;
  493.                 ioctl(*fp, _FIOAI, &fai);
  494.                 if (fai.fai_num == 0)
  495.                     break;
  496.                 fai_idx = 0;
  497.             }
  498.             is_hole = fai.fai_daddr[fai_idx++] == _FIOAI_HOLE;
  499.             amount = 512;
  500. #endif    /* _FIOAI */
  501.         } else {
  502.             if ((amount = _fileread(fp, rbuf, TBLOCK)) == 0)
  503.                 break;
  504.             is_hole = cmpbytes(rbuf, zeroblk, amount) >= amount;
  505.         }
  506.  
  507.         if (is_hole) {
  508.             if (data) {
  509.                 sparse[i].sp_numbytes =
  510.                         pos - sparse[i].sp_offset;
  511.                 info->f_rsize += sparse[i].sp_numbytes;
  512.  
  513.                 EDEBUG(("i: %d offset: %d numbytes: %d\n", i,
  514.                     sparse[i].sp_offset,
  515.                     sparse[i].sp_numbytes));
  516.  
  517.                 data = FALSE;
  518.                 i++;
  519.                 if (i >= nsparse) {
  520.                     if ((sparse = grow_sp_list(sparse,
  521.                             &nsparse)) == 0) {
  522.                         lseek(*fp, 0L, SEEK_SET);
  523.                         return (0);
  524.                     }
  525.                 }
  526.             }
  527.         } else {
  528.             if (!data) {
  529.                 sparse[i].sp_offset = pos;
  530.                 data = TRUE;
  531.             }
  532.         }
  533.         pos += amount;
  534.     }
  535.     EDEBUG(("data: %d\n", data));
  536.  
  537.     if (data) {
  538.         sparse[i].sp_numbytes = pos - sparse[i].sp_offset;
  539.         info->f_rsize += sparse[i].sp_numbytes;
  540.  
  541.         EDEBUG(("i: %d offset: %d numbytes: %d\n", i,
  542.                 sparse[i].sp_offset,
  543.                 sparse[i].sp_numbytes));
  544.     } else {
  545.         sparse[i].sp_offset = pos -1;
  546.         sparse[i].sp_numbytes = 1;
  547.         info->f_rsize += 1;
  548.  
  549.         EDEBUG(("i: %d offset: %d numbytes: %d\n", i,
  550.                 sparse[i].sp_offset,
  551.                 sparse[i].sp_numbytes));
  552.     }
  553.     lseek(*fp, 0L, SEEK_SET);
  554.     *spp = sparse;
  555.     return (++i);
  556. }
  557.  
  558. EXPORT int
  559. gnu_skip_extended(ptb)
  560.     TCB    *ptb;
  561. {
  562.     if (ptb->gnu_in_dbuf.t_isextended) do {
  563.         if (readblock((char *)ptb) == EOF)
  564.             return (EOF);
  565.     } while(ptb->gnu_ext_dbuf.t_isextended);
  566.     return (0);
  567. }
  568.  
  569. EXPORT int
  570. get_sparse(f, info)
  571.     FILE    *f;
  572.     FINFO    *info;
  573. {
  574.     fh_t    fh;
  575.     sp_t    *sparse = get_sp_list(info);
  576.     int    ret;
  577.  
  578.     if (sparse == 0) {
  579.         errmsgno(EX_BAD, "Skipping '%s' sorry ...\n", info->f_name);
  580.         errmsgno(EX_BAD, "Warning  '%s' is damaged\n", info->f_name);
  581.         void_file(info);
  582.         return (FALSE);
  583.     }
  584.     fh.fh_file = f;
  585.     fh.fh_name = info->f_name;
  586.     fh.fh_size = info->f_rsize;
  587.     fh.fh_newpos = 0L;
  588.     fh.fh_sparse = sparse;
  589.     fh.fh_spindex = 0;
  590.     ret = xt_file(info, vp_get_sparse_func, &fh, TBLOCK, "writing");
  591.     free(sparse);
  592.     return (ret);
  593. }
  594.  
  595. EXPORT BOOL
  596. cmp_sparse(f, info)
  597.     FILE    *f;
  598.     FINFO    *info;
  599. {
  600.     fh_t    fh;
  601.     sp_t    *sparse = get_sp_list(info);
  602.  
  603.     if (sparse == 0) {
  604.         errmsgno(EX_BAD, "Skipping '%s' sorry ...\n", info->f_name);
  605.         void_file(info);
  606.         fclose(f);
  607.         return (FALSE);
  608.     }
  609.     fh.fh_file = f;
  610.     fh.fh_name = info->f_name;
  611.     fh.fh_size = info->f_rsize;
  612.     fh.fh_newpos = 0L;
  613.     fh.fh_sparse = sparse;
  614.     fh.fh_spindex = 0;
  615.     fh.fh_diffs = 0;
  616.     if (xt_file(info, vp_cmp_sparse_func, &fh, TBLOCK, "reading") < 0)
  617.         die(EX_BAD);
  618.     if (fclose(f) != 0)
  619.         xstats.s_rwerrs++;
  620.     free(sparse);
  621.     return (fh.fh_diffs == 0);
  622. }
  623.  
  624. EXPORT void
  625. put_sparse(fp, info)
  626.     int    *fp;
  627.     FINFO    *info;
  628. {
  629.     fh_t    fh;
  630.     sp_t    *sparse;
  631.     int    nsparse;
  632.     long    rsize;
  633.  
  634.     nsparse = mk_sp_list(fp, info, &sparse);
  635.     if (nsparse == 0) {
  636.         info->f_rsize = info->f_size;
  637.         put_tcb(info->f_tcb, info);
  638.         vprint(info);
  639.         errmsgno(EX_BAD, "Dumping SPARSE '%s' as file\n", info->f_name);
  640.         put_file(fp, info);
  641.         return;
  642.     }
  643.     rsize = info->f_rsize;
  644.  
  645.     EDEBUG(("rsize: %d\n", rsize));
  646.  
  647.     put_sp_list(info, sparse, nsparse);
  648.     fh.fh_file = (FILE *)fp;
  649.     fh.fh_name = info->f_name;
  650.     fh.fh_size = info->f_rsize = rsize;
  651.     fh.fh_newpos = 0L;
  652.     fh.fh_sparse = sparse;
  653.     fh.fh_nsparse = nsparse;
  654.     fh.fh_spindex = 0;
  655.     cr_file(info, vp_put_sparse_func, &fh, TBLOCK, "reading");
  656.     free(sparse);
  657. }
  658.  
  659. LOCAL void
  660. put_sp_list(info, sparse, nsparse)
  661.     FINFO    *info;
  662.     sp_t    *sparse;
  663.     int    nsparse;
  664. {
  665.     register int    i;
  666.     register int    sparse_in_hdr = props.pr_sparse_in_hdr;
  667.     register char    *p;
  668.          TCB    tb;
  669.          TCB    *ptb = info->f_tcb;
  670. /*XXX*/extern int hdrtype;
  671.  
  672.     EDEBUG(("1nsparse: %d rsize: %d\n", nsparse, info->f_rsize));
  673.  
  674.     if (nsparse > sparse_in_hdr) {
  675.         if ((props.pr_flags & PR_GNU_SPARSE_BUG) == 0)
  676.             info->f_rsize +=
  677.                 (((nsparse-sparse_in_hdr)+SPARSE_EXT_HDR-1)/
  678.                 SPARSE_EXT_HDR)*TBLOCK;
  679.     }
  680.     EDEBUG(("2nsparse: %d rsize: %d added: %d\n", nsparse, info->f_rsize,
  681.                 (((nsparse-sparse_in_hdr)+SPARSE_EXT_HDR-1)/
  682.                 SPARSE_EXT_HDR)*TBLOCK));
  683.     EDEBUG(("addr sp: %d\n", &((TCB *)0)->xstar_in_dbuf.t_sp));
  684.     EDEBUG(("addr rs: %d\n", &((TCB *)0)->xstar_in_dbuf.t_realsize));
  685.     EDEBUG(("flags: 0x%X\n", info->f_flags));
  686.  
  687.     info->f_xftype = XT_SPARSE;
  688.     if (info->f_flags & F_SPLIT_NAME && props.pr_nflags & PR_PREFIX_REUSED)
  689.         tcb_undo_split(ptb, info);
  690.     info_to_tcb(info, ptb);
  691.  
  692.     if (H_TYPE(hdrtype) == H_GNUTAR)
  693.         p = (char *)ptb->gnu_in_dbuf.t_sp;
  694.     else
  695.         p = (char *)ptb->xstar_in_dbuf.t_sp;
  696.     for (i=0; i < sparse_in_hdr && i < nsparse; i++) {
  697.         otoa(p, sparse[i].sp_offset, 11); p += 12;
  698.         otoa(p, sparse[i].sp_numbytes, 11); p += 12;
  699.     }
  700.     if (sparse_in_hdr > 0 && nsparse > sparse_in_hdr) {
  701.         if (H_TYPE(hdrtype) == H_GNUTAR)
  702.             ptb->gnu_in_dbuf.t_isextended = 1;
  703.         else
  704.             ptb->xstar_in_dbuf.t_isextended = '1';
  705.     }
  706.  
  707.     put_tcb(ptb, info);
  708.     vprint(info);
  709.  
  710.     nsparse -= sparse_in_hdr;
  711.     sparse += sparse_in_hdr;
  712.     ptb = &tb;
  713.     while (nsparse > 0) {
  714.         fillbytes((char *)ptb, TBLOCK, '\0');
  715.         p = (char *)ptb;
  716.         for (i=0; i < SPARSE_EXT_HDR && i < nsparse; i++) {
  717.             otoa(p, sparse[i].sp_offset, 11); p += 12;
  718.             otoa(p, sparse[i].sp_numbytes, 11); p += 12;
  719.         }
  720.         nsparse -= SPARSE_EXT_HDR;
  721.         sparse += SPARSE_EXT_HDR;
  722.         if (nsparse > 0)
  723.             ptb->gnu_ext_dbuf.t_isextended = '1';
  724.         writeblock((char *)ptb);
  725.     }
  726. }
  727.