home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / rsync221.zip / token.c < prev    next >
C/C++ Source or Header  |  1999-03-04  |  12KB  |  486 lines

  1. /* 
  2.    Copyright (C) Andrew Tridgell 1996
  3.    Copyright (C) Paul Mackerras 1996
  4.    
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2 of the License, or
  8.    (at your option) any later version.
  9.    
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.    
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19.  
  20. #include "rsync.h"
  21. #include "zlib/zlib.h"
  22.  
  23. extern int do_compression;
  24. static int compression_level = Z_DEFAULT_COMPRESSION;
  25.  
  26. /* determine the compression level based on a wildcard filename list */
  27. void set_compression(char *fname)
  28. {
  29.     extern int module_id;
  30.     char *dont;
  31.     char *tok;
  32.  
  33.     if (!do_compression) return;
  34.  
  35.     compression_level = Z_DEFAULT_COMPRESSION;
  36.     dont = lp_dont_compress(module_id);
  37.  
  38.     if (!dont || !*dont) return;
  39.  
  40.     if ((dont[0] == '*') && (!dont[1])) {
  41.         /* an optimization to skip the rest of this routine */
  42.         compression_level = 0;
  43.         return;
  44.     }
  45.  
  46.     dont = strdup(dont);
  47.     fname = strdup(fname);
  48.     if (!dont || !fname) return;
  49.  
  50.     strlower(dont);
  51.     strlower(fname);
  52.  
  53.     for (tok=strtok(dont," ");tok;tok=strtok(NULL," ")) {
  54.         if (fnmatch(tok, fname, 0) == 0) {
  55.             compression_level = 0;
  56.             break;
  57.         }
  58.     }
  59.     free(dont);
  60.     free(fname);
  61. }
  62.  
  63. /* non-compressing recv token */
  64. static int simple_recv_token(int f,char **data)
  65. {
  66.     static int residue;
  67.     static char *buf;
  68.     int n;
  69.  
  70.     if (!buf) {
  71.         buf = (char *)malloc(CHUNK_SIZE);
  72.         if (!buf) out_of_memory("simple_recv_token");
  73.     }
  74.  
  75.     if (residue == 0) {
  76.         int i = read_int(f);
  77.         if (i <= 0) return i;
  78.         residue = i;
  79.     }
  80.  
  81.     *data = buf;
  82.     n = MIN(CHUNK_SIZE,residue);
  83.     residue -= n;
  84.     read_buf(f,buf,n);
  85.     return n;
  86. }
  87.  
  88.  
  89. /* non-compressing send token */
  90. static void simple_send_token(int f,int token,
  91.                   struct map_struct *buf,OFF_T offset,int n)
  92. {
  93.     if (n > 0) {
  94.         int l = 0;
  95.         while (l < n) {
  96.             int n1 = MIN(CHUNK_SIZE,n-l);
  97.             write_int(f,n1);
  98.             write_buf(f,map_ptr(buf,offset+l,n1),n1);
  99.             l += n1;
  100.         }
  101.     }
  102.     /* a -2 token means to send data only and no token */
  103.     if (token != -2) {
  104.         write_int(f,-(token+1));
  105.     }
  106. }
  107.  
  108.  
  109. /* Flag bytes in compressed stream are encoded as follows: */
  110. #define END_FLAG    0    /* that's all folks */
  111. #define TOKEN_LONG    0x20    /* followed by 32-bit token number */
  112. #define TOKENRUN_LONG    0x21    /* ditto with 16-bit run count */
  113. #define DEFLATED_DATA    0x40    /* + 6-bit high len, then low len byte */
  114. #define TOKEN_REL    0x80    /* + 6-bit relative token number */
  115. #define TOKENRUN_REL    0xc0    /* ditto with 16-bit run count */
  116.  
  117. #define MAX_DATA_COUNT    16383    /* fit 14 bit count into 2 bytes with flags */
  118.  
  119. /* For coding runs of tokens */
  120. static int last_token = -1;
  121. static int run_start;
  122. static int last_run_end;
  123.  
  124. /* Deflation state */
  125. static z_stream tx_strm;
  126.  
  127. /* Output buffer */
  128. static char *obuf;
  129.  
  130. /* Send a deflated token */
  131. static void
  132. send_deflated_token(int f, int token,
  133.             struct map_struct *buf, OFF_T offset, int nb, int toklen)
  134. {
  135.     int n, r;
  136.     static int init_done, flush_pending;
  137.  
  138.     if (last_token == -1) {
  139.         /* initialization */
  140.         if (!init_done) {
  141.             tx_strm.next_in = NULL;
  142.             tx_strm.zalloc = NULL;
  143.             tx_strm.zfree = NULL;
  144.             if (deflateInit2(&tx_strm, compression_level,
  145.                      Z_DEFLATED, -15, 8,
  146.                      Z_DEFAULT_STRATEGY) != Z_OK) {
  147.                 rprintf(FERROR, "compression init failed\n");
  148.                 exit_cleanup(RERR_STREAMIO);
  149.             }
  150.             if ((obuf = malloc(MAX_DATA_COUNT+2)) == NULL)
  151.                 out_of_memory("send_deflated_token");
  152.             init_done = 1;
  153.         } else
  154.             deflateReset(&tx_strm);
  155.         last_run_end = 0;
  156.         run_start = token;
  157.         flush_pending = 0;
  158.  
  159.     } else if (last_token == -2) {
  160.         run_start = token;
  161.  
  162.     } else if (nb != 0 || token != last_token + 1
  163.            || token >= run_start + 65536) {
  164.         /* output previous run */
  165.         r = run_start - last_run_end;
  166.         n = last_token - run_start;
  167.         if (r >= 0 && r <= 63) {
  168.             write_byte(f, (n==0? TOKEN_REL: TOKENRUN_REL) + r);
  169.         } else {
  170.             write_byte(f, (n==0? TOKEN_LONG: TOKENRUN_LONG));
  171.             write_int(f, run_start);
  172.         }
  173.         if (n != 0) {
  174.             write_byte(f, n);
  175.             write_byte(f, n >> 8);
  176.         }
  177.         last_run_end = last_token;
  178.         run_start = token;
  179.     }
  180.  
  181.     last_token = token;
  182.  
  183.     if (nb != 0 || flush_pending) {
  184.         /* deflate the data starting at offset */
  185.         int flush = Z_NO_FLUSH;
  186.         tx_strm.avail_in = 0;
  187.         tx_strm.avail_out = 0;
  188.         do {
  189.             if (tx_strm.avail_in == 0 && nb != 0) {
  190.                 /* give it some more input */
  191.                 n = MIN(nb, CHUNK_SIZE);
  192.                 tx_strm.next_in = (Bytef *)
  193.                     map_ptr(buf, offset, n);
  194.                 tx_strm.avail_in = n;
  195.                 nb -= n;
  196.                 offset += n;
  197.             }
  198.             if (tx_strm.avail_out == 0) {
  199.                 tx_strm.next_out = (Bytef *)(obuf + 2);
  200.                 tx_strm.avail_out = MAX_DATA_COUNT;
  201.                 if (flush != Z_NO_FLUSH) {
  202.                     /*
  203.                      * We left the last 4 bytes in the
  204.                      * buffer, in case they are the
  205.                      * last 4.  Move them to the front.
  206.                      */
  207.                     memcpy(tx_strm.next_out,
  208.                            obuf+MAX_DATA_COUNT-2, 4);
  209.                     tx_strm.next_out += 4;
  210.                     tx_strm.avail_out -= 4;
  211.                 }
  212.             }
  213.             if (nb == 0 && token != -2)
  214.                 flush = Z_SYNC_FLUSH;
  215.             r = deflate(&tx_strm, flush);
  216.             if (r != Z_OK) {
  217.                 rprintf(FERROR, "deflate returned %d\n", r);
  218.                 exit_cleanup(RERR_STREAMIO);
  219.             }
  220.             if (nb == 0 || tx_strm.avail_out == 0) {
  221.                 n = MAX_DATA_COUNT - tx_strm.avail_out;
  222.                 if (flush != Z_NO_FLUSH) {
  223.                     /*
  224.                      * We have to trim off the last 4
  225.                      * bytes of output when flushing
  226.                      * (they are just 0, 0, ff, ff).
  227.                      */
  228.                     n -= 4;
  229.                 }
  230.                 if (n > 0) {
  231.                     obuf[0] = DEFLATED_DATA + (n >> 8);
  232.                     obuf[1] = n;
  233.                     write_buf(f, obuf, n+2);
  234.                 }
  235.             }
  236.         } while (nb != 0 || tx_strm.avail_out == 0);
  237.         flush_pending = token == -2;
  238.     }
  239.  
  240.     if (token == -1) {
  241.         /* end of file - clean up */
  242.         write_byte(f, END_FLAG);
  243.  
  244.     } else if (token != -2) {
  245.         /* add the data in the current block to the compressor's
  246.            history and hash table */
  247.         tx_strm.next_in = (Bytef *) map_ptr(buf, offset, toklen);
  248.         tx_strm.avail_in = toklen;
  249.         tx_strm.next_out = (Bytef *) obuf;
  250.         tx_strm.avail_out = MAX_DATA_COUNT;
  251.         r = deflate(&tx_strm, Z_INSERT_ONLY);
  252.         if (r != Z_OK || tx_strm.avail_in != 0) {
  253.             rprintf(FERROR, "deflate on token returned %d (%d bytes left)\n",
  254.                 r, tx_strm.avail_in);
  255.             exit_cleanup(RERR_STREAMIO);
  256.         }
  257.     }
  258. }
  259.  
  260.  
  261. /* tells us what the receiver is in the middle of doing */
  262. static enum { r_init, r_idle, r_running, r_inflating, r_inflated } recv_state;
  263.  
  264. /* for inflating stuff */
  265. static z_stream rx_strm;
  266. static char *cbuf;
  267. static char *dbuf;
  268.  
  269. /* for decoding runs of tokens */
  270. static int rx_token;
  271. static int rx_run;
  272.  
  273. /* Receive a deflated token and inflate it */
  274. static int
  275. recv_deflated_token(int f, char **data)
  276. {
  277.     int n, r, flag;
  278.     static int init_done;
  279.     static int saved_flag;
  280.  
  281.     for (;;) {
  282.         switch (recv_state) {
  283.         case r_init:
  284.             if (!init_done) {
  285.                 rx_strm.next_out = NULL;
  286.                 rx_strm.zalloc = NULL;
  287.                 rx_strm.zfree = NULL;
  288.                 if (inflateInit2(&rx_strm, -15) != Z_OK) {
  289.                     rprintf(FERROR, "inflate init failed\n");
  290.                     exit_cleanup(RERR_STREAMIO);
  291.                 }
  292.                 if ((cbuf = malloc(MAX_DATA_COUNT)) == NULL
  293.                     || (dbuf = malloc(CHUNK_SIZE)) == NULL)
  294.                     out_of_memory("recv_deflated_token");
  295.                 init_done = 1;
  296.             } else {
  297.                 inflateReset(&rx_strm);
  298.             }
  299.             recv_state = r_idle;
  300.             rx_token = 0;
  301.             break;
  302.  
  303.         case r_idle:
  304.         case r_inflated:
  305.             if (saved_flag) {
  306.                 flag = saved_flag & 0xff;
  307.                 saved_flag = 0;
  308.             } else
  309.                 flag = read_byte(f);
  310.             if ((flag & 0xC0) == DEFLATED_DATA) {
  311.                 n = ((flag & 0x3f) << 8) + read_byte(f);
  312.                 read_buf(f, cbuf, n);
  313.                 rx_strm.next_in = (Bytef *)cbuf;
  314.                 rx_strm.avail_in = n;
  315.                 recv_state = r_inflating;
  316.                 break;
  317.             }
  318.             if (recv_state == r_inflated) {
  319.                 /* check previous inflated stuff ended correctly */
  320.                 rx_strm.avail_in = 0;
  321.                 rx_strm.next_out = (Bytef *)dbuf;
  322.                 rx_strm.avail_out = CHUNK_SIZE;
  323.                 r = inflate(&rx_strm, Z_SYNC_FLUSH);
  324.                 n = CHUNK_SIZE - rx_strm.avail_out;
  325.                 /*
  326.                  * Z_BUF_ERROR just means no progress was
  327.                  * made, i.e. the decompressor didn't have
  328.                  * any pending output for us.
  329.                  */
  330.                 if (r != Z_OK && r != Z_BUF_ERROR) {
  331.                     rprintf(FERROR, "inflate flush returned %d (%d bytes)\n",
  332.                         r, n);
  333.                     exit_cleanup(RERR_STREAMIO);
  334.                 }
  335.                 if (n != 0 && r != Z_BUF_ERROR) {
  336.                     /* have to return some more data and
  337.                        save the flag for later. */
  338.                     saved_flag = flag + 0x10000;
  339.                     *data = dbuf;
  340.                     return n;
  341.                 }
  342.                 /*
  343.                  * At this point the decompressor should
  344.                  * be expecting to see the 0, 0, ff, ff bytes.
  345.                  */
  346.                 if (!inflateSyncPoint(&rx_strm)) {
  347.                     rprintf(FERROR, "decompressor lost sync!\n");
  348.                     exit_cleanup(RERR_STREAMIO);
  349.                 }
  350.                 rx_strm.avail_in = 4;
  351.                 rx_strm.next_in = (Bytef *)cbuf;
  352.                 cbuf[0] = cbuf[1] = 0;
  353.                 cbuf[2] = cbuf[3] = 0xff;
  354.                 inflate(&rx_strm, Z_SYNC_FLUSH);
  355.                 recv_state = r_idle;
  356.             }
  357.             if (flag == END_FLAG) {
  358.                 /* that's all folks */
  359.                 recv_state = r_init;
  360.                 return 0;
  361.             }
  362.  
  363.             /* here we have a token of some kind */
  364.             if (flag & TOKEN_REL) {
  365.                 rx_token += flag & 0x3f;
  366.                 flag >>= 6;
  367.             } else
  368.                 rx_token = read_int(f);
  369.             if (flag & 1) {
  370.                 rx_run = read_byte(f);
  371.                 rx_run += read_byte(f) << 8;
  372.                 recv_state = r_running;
  373.             }
  374.             return -1 - rx_token;
  375.  
  376.         case r_inflating:
  377.             rx_strm.next_out = (Bytef *)dbuf;
  378.             rx_strm.avail_out = CHUNK_SIZE;
  379.             r = inflate(&rx_strm, Z_NO_FLUSH);
  380.             n = CHUNK_SIZE - rx_strm.avail_out;
  381.             if (r != Z_OK) {
  382.                 rprintf(FERROR, "inflate returned %d (%d bytes)\n", r, n);
  383.                 exit_cleanup(RERR_STREAMIO);
  384.             }
  385.             if (rx_strm.avail_in == 0)
  386.                 recv_state = r_inflated;
  387.             if (n != 0) {
  388.                 *data = dbuf;
  389.                 return n;
  390.             }
  391.             break;
  392.  
  393.         case r_running:
  394.             ++rx_token;
  395.             if (--rx_run == 0)
  396.                 recv_state = r_idle;
  397.             return -1 - rx_token;
  398.         }
  399.     }
  400. }
  401.  
  402. /*
  403.  * put the data corresponding to a token that we've just returned
  404.  * from recv_deflated_token into the decompressor's history buffer.
  405.  */
  406. static void see_deflate_token(char *buf, int len)
  407. {
  408.     int r, blklen;
  409.     unsigned char hdr[5];
  410.  
  411.     rx_strm.avail_in = 0;
  412.     blklen = 0;
  413.     hdr[0] = 0;
  414.     do {
  415.         if (rx_strm.avail_in == 0 && len != 0) {
  416.             if (blklen == 0) {
  417.                 /* Give it a fake stored-block header. */
  418.                 rx_strm.next_in = (Bytef *)hdr;
  419.                 rx_strm.avail_in = 5;
  420.                 blklen = len;
  421.                 if (blklen > 0xffff)
  422.                     blklen = 0xffff;
  423.                 hdr[1] = blklen;
  424.                 hdr[2] = blklen >> 8;
  425.                 hdr[3] = ~hdr[1];
  426.                 hdr[4] = ~hdr[2];
  427.             } else {
  428.                 rx_strm.next_in = (Bytef *)buf;
  429.                 rx_strm.avail_in = blklen;
  430.                 len -= blklen;
  431.                 blklen = 0;
  432.             }
  433.         }
  434.         rx_strm.next_out = (Bytef *)dbuf;
  435.         rx_strm.avail_out = CHUNK_SIZE;
  436.         r = inflate(&rx_strm, Z_SYNC_FLUSH);
  437.         if (r != Z_OK) {
  438.             rprintf(FERROR, "inflate (token) returned %d\n", r);
  439.             exit_cleanup(RERR_STREAMIO);
  440.         }
  441.     } while (len || rx_strm.avail_out == 0);
  442. }
  443.  
  444. /*
  445.  * transmit a verbatim buffer of length n followed by a token 
  446.  * If token == -1 then we have reached EOF 
  447.  * If n == 0 then don't send a buffer
  448.  */
  449. void send_token(int f,int token,struct map_struct *buf,OFF_T offset,
  450.         int n,int toklen)
  451. {
  452.     if (!do_compression) {
  453.         simple_send_token(f,token,buf,offset,n);
  454.     } else {
  455.         send_deflated_token(f, token, buf, offset, n, toklen);
  456.     }
  457. }
  458.  
  459.  
  460. /*
  461.  * receive a token or buffer from the other end. If the reurn value is >0 then
  462.  * it is a data buffer of that length, and *data will point at the data.
  463.  * if the return value is -i then it represents token i-1
  464.  * if the return value is 0 then the end has been reached
  465.  */
  466. int recv_token(int f,char **data)
  467. {
  468.     int tok;
  469.  
  470.     if (!do_compression) {
  471.         tok = simple_recv_token(f,data);
  472.     } else {
  473.         tok = recv_deflated_token(f, data);
  474.     }
  475.     return tok;
  476. }
  477.  
  478. /*
  479.  * look at the data corresponding to a token, if necessary
  480.  */
  481. void see_token(char *data, int toklen)
  482. {
  483.     if (do_compression)
  484.         see_deflate_token(data, toklen);
  485. }
  486.