home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / OPENSTEP / UNIX / Utilities / rsync-1.6.3-MIH / src / token.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-11  |  9.3 KB  |  391 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 "lib/zlib.h"
  22.  
  23. extern int do_compression;
  24.  
  25.  
  26. /* non-compressing recv token */
  27. static int simple_recv_token(int f,char **data)
  28. {
  29.   static int residue = 0;
  30.   static char *buf = NULL;
  31.   int n;
  32.  
  33.   if (!buf) {
  34.     buf = (char *)malloc(CHUNK_SIZE);
  35.     if (!buf) out_of_memory("simple_recv_token");
  36.   }
  37.  
  38.  
  39.   if (residue == 0) {
  40.     int i = read_int(f);
  41.     if (i <= 0) return i;
  42.     residue = i;
  43.   }
  44.  
  45.   *data = buf;
  46.   n = MIN(CHUNK_SIZE,residue);
  47.   residue -= n;
  48.   read_buf(f,buf,n);
  49.   return n;
  50. }
  51.  
  52.  
  53. /* non-compressing send token */
  54. static void simple_send_token(int f,int token,
  55.                   struct map_struct *buf,int offset,int n)
  56. {
  57.   if (n > 0) {
  58.     int l = 0;
  59.     while (l < n) {
  60.       int n1 = MIN(CHUNK_SIZE,n-l);
  61.       write_int(f,n1);
  62.       write_buf(f,map_ptr(buf,offset+l,n1),n1);
  63.       l += n1;
  64.     }
  65.   }
  66.   write_int(f,-(token+1));
  67. }
  68.  
  69.  
  70. /* Memory allocation/freeing routines, called by zlib stuff. */
  71. static void *
  72. z_alloc(void *opaque, uInt items, uInt size)
  73. {
  74.     return malloc(items * size);
  75. }
  76.  
  77. static void
  78. z_free(void *opaque, void *adrs, uInt nbytes)
  79. {
  80.     free(adrs);
  81. }
  82.  
  83. /* Flag bytes in compressed stream are encoded as follows: */
  84. #define END_FLAG    0    /* that's all folks */
  85. #define TOKEN_LONG    0x20    /* followed by 32-bit token number */
  86. #define TOKENRUN_LONG    0x21    /* ditto with 16-bit run count */
  87. #define DEFLATED_DATA    0x40    /* + 6-bit high len, then low len byte */
  88. #define TOKEN_REL    0x80    /* + 6-bit relative token number */
  89. #define TOKENRUN_REL    0xc0    /* ditto with 16-bit run count */
  90.  
  91. #define MAX_DATA_COUNT    16383    /* fit 14 bit count into 2 bytes with flags */
  92.  
  93. /* For coding runs of tokens */
  94. static int last_token = -1;
  95. static int run_start;
  96. static int last_run_end;
  97.  
  98. /* Deflation state */
  99. static z_stream tx_strm;
  100.  
  101. /* Output buffer */
  102. static char *obuf = NULL;
  103.  
  104. /* Send a deflated token */
  105. static void
  106. send_deflated_token(int f, int token,
  107.             struct map_struct *buf, int offset, int nb, int toklen)
  108. {
  109.     int n, r;
  110.     static int init_done;
  111.  
  112.     if (last_token == -1) {
  113.     /* initialization */
  114.     if (!init_done) {
  115.         tx_strm.next_in = NULL;
  116.         tx_strm.zalloc = z_alloc;
  117.         tx_strm.zfree = z_free;
  118.         if (deflateInit2(&tx_strm, Z_DEFAULT_COMPRESSION, 8,
  119.                  -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
  120.         fprintf(FERROR, "compression init failed\n");
  121.         exit_cleanup(1);
  122.         }
  123.         if ((obuf = malloc(MAX_DATA_COUNT+2)) == NULL)
  124.         out_of_memory("send_deflated_token");
  125.         init_done = 1;
  126.     } else
  127.         deflateReset(&tx_strm);
  128.     run_start = token;
  129.     last_run_end = 0;
  130.  
  131.     } else if (nb != 0 || token != last_token + 1
  132.            || token >= run_start + 65536) {
  133.     /* output previous run */
  134.     r = run_start - last_run_end;
  135.     n = last_token - run_start;
  136.     if (r >= 0 && r <= 63) {
  137.         write_byte(f, (n==0? TOKEN_REL: TOKENRUN_REL) + r);
  138.     } else {
  139.         write_byte(f, (n==0? TOKEN_LONG: TOKENRUN_LONG));
  140.         write_int(f, run_start);
  141.     }
  142.     if (n != 0) {
  143.         write_byte(f, n);
  144.         write_byte(f, n >> 8);
  145.     }
  146.     last_run_end = last_token;
  147.     run_start = token;
  148.     }
  149.  
  150.     last_token = token;
  151.  
  152.     if (nb != 0) {
  153.     /* deflate the data starting at offset */
  154.     tx_strm.avail_in = 0;
  155.     tx_strm.avail_out = 0;
  156.     do {
  157.         if (tx_strm.avail_in == 0 && nb != 0) {
  158.         /* give it some more input */
  159.         n = MIN(nb, CHUNK_SIZE);
  160.         tx_strm.next_in = map_ptr(buf, offset, n);
  161.         tx_strm.avail_in = n;
  162.         nb -= n;
  163.         offset += n;
  164.         }
  165.         if (tx_strm.avail_out == 0) {
  166.         tx_strm.next_out = obuf + 2;
  167.         tx_strm.avail_out = MAX_DATA_COUNT;
  168.         }
  169.         r = deflate(&tx_strm, nb? Z_NO_FLUSH: Z_PACKET_FLUSH);
  170.         if (r != Z_OK) {
  171.         fprintf(FERROR, "deflate returned %d\n", r);
  172.         exit_cleanup(1);
  173.         }
  174.         if (nb == 0 || tx_strm.avail_out == 0) {
  175.         n = MAX_DATA_COUNT - tx_strm.avail_out;
  176.         if (n > 0) {
  177.             obuf[0] = DEFLATED_DATA + (n >> 8);
  178.             obuf[1] = n;
  179.             write_buf(f, obuf, n+2);
  180.         }
  181.         }
  182.     } while (nb != 0 || tx_strm.avail_out == 0);
  183.     }
  184.  
  185.     if (token != -1) {
  186.     /* add the data in the current block to the compressor's
  187.        history and hash table */
  188.     tx_strm.next_in = map_ptr(buf, offset, toklen);
  189.     tx_strm.avail_in = toklen;
  190.     tx_strm.next_out = NULL;
  191.     tx_strm.avail_out = 2 * toklen;
  192.     r = deflate(&tx_strm, Z_INSERT_ONLY);
  193.     if (r != Z_OK || tx_strm.avail_in != 0) {
  194.         fprintf(FERROR, "deflate on token returned %d (%d bytes left)\n",
  195.             r, tx_strm.avail_in);
  196.         exit_cleanup(1);
  197.     }
  198.  
  199.     } else {
  200.     /* end of file - clean up */
  201.     write_byte(f, END_FLAG);
  202.     }
  203. }
  204.  
  205.  
  206. /* tells us what the receiver is in the middle of doing */
  207. static enum { r_init, r_idle, r_running, r_inflating, r_inflated } recv_state;
  208.  
  209. /* for inflating stuff */
  210. static z_stream rx_strm;
  211. static char *cbuf;
  212. static char *dbuf;
  213.  
  214. /* for decoding runs of tokens */
  215. static int rx_token;
  216. static int rx_run;
  217.  
  218. /* Receive a deflated token and inflate it */
  219. static int
  220. recv_deflated_token(int f, char **data)
  221. {
  222.     int n, r, flag;
  223.     static int init_done = 0;
  224.     static int saved_flag = 0;
  225.  
  226.     for (;;) {
  227.     switch (recv_state) {
  228.     case r_init:
  229.         if (!init_done) {
  230.         rx_strm.next_out = NULL;
  231.         rx_strm.zalloc = z_alloc;
  232.         rx_strm.zfree = z_free;
  233.         if (inflateInit2(&rx_strm, -15) != Z_OK) {
  234.             fprintf(FERROR, "inflate init failed\n");
  235.             exit_cleanup(1);
  236.         }
  237.         if ((cbuf = malloc(MAX_DATA_COUNT)) == NULL
  238.             || (dbuf = malloc(CHUNK_SIZE)) == NULL)
  239.             out_of_memory("recv_deflated_token");
  240.         init_done = 1;
  241.         } else {
  242.         inflateReset(&rx_strm);
  243.         }
  244.         recv_state = r_idle;
  245.         rx_token = 0;
  246.         break;
  247.         
  248.     case r_idle:
  249.     case r_inflated:
  250.         if (saved_flag) {
  251.         flag = saved_flag & 0xff;
  252.         saved_flag = 0;
  253.         } else
  254.         flag = read_byte(f);
  255.         if ((flag & 0xC0) == DEFLATED_DATA) {
  256.         n = ((flag & 0x3f) << 8) + read_byte(f);
  257.         read_buf(f, cbuf, n);
  258.         rx_strm.next_in = cbuf;
  259.         rx_strm.avail_in = n;
  260.         recv_state = r_inflating;
  261.         break;
  262.         }
  263.         if (recv_state == r_inflated) {
  264.         /* check previous inflated stuff ended correctly */
  265.         rx_strm.avail_in = 0;
  266.         rx_strm.next_out = dbuf;
  267.         rx_strm.avail_out = CHUNK_SIZE;
  268.         r = inflate(&rx_strm, Z_PACKET_FLUSH);
  269.         n = CHUNK_SIZE - rx_strm.avail_out;
  270.         if (r != Z_OK) {
  271.             fprintf(FERROR, "inflate flush returned %d (%d bytes)\n",
  272.                 r, n);
  273.             exit_cleanup(1);
  274.         }
  275.         if (n != 0) {
  276.             /* have to return some more data and
  277.                save the flag for later. */
  278.             saved_flag = flag + 0x10000;
  279.             if (rx_strm.avail_out != 0)
  280.             recv_state = r_idle;
  281.             *data = dbuf;
  282.             return n;
  283.         }
  284.         recv_state = r_idle;
  285.         }
  286.         if (flag == END_FLAG) {
  287.         /* that's all folks */
  288.         recv_state = r_init;
  289.         return 0;
  290.         }
  291.  
  292.         /* here we have a token of some kind */
  293.         if (flag & TOKEN_REL) {
  294.         rx_token += flag & 0x3f;
  295.         flag >>= 6;
  296.         } else
  297.         rx_token = read_int(f);
  298.         if (flag & 1) {
  299.         rx_run = read_byte(f);
  300.         rx_run += read_byte(f) << 8;
  301.         recv_state = r_running;
  302.         }
  303.         return -1 - rx_token;
  304.  
  305.     case r_inflating:
  306.         rx_strm.next_out = dbuf;
  307.         rx_strm.avail_out = CHUNK_SIZE;
  308.         r = inflate(&rx_strm, Z_NO_FLUSH);
  309.         n = CHUNK_SIZE - rx_strm.avail_out;
  310.         if (r != Z_OK) {
  311.         fprintf(FERROR, "inflate returned %d (%d bytes)\n", r, n);
  312.         exit_cleanup(1);
  313.         }
  314.         if (rx_strm.avail_in == 0)
  315.         recv_state = r_inflated;
  316.         if (n != 0) {
  317.         *data = dbuf;
  318.         return n;
  319.         }
  320.         break;
  321.  
  322.     case r_running:
  323.         ++rx_token;
  324.         if (--rx_run == 0)
  325.         recv_state = r_idle;
  326.         return -1 - rx_token;
  327.     }
  328.     }
  329. }
  330.  
  331. /*
  332.  * put the data corresponding to a token that we've just returned
  333.  * from recv_deflated_token into the decompressor's history buffer.
  334.  */
  335. void
  336. see_deflate_token(char *buf, int len)
  337. {
  338.     int r;
  339.  
  340.     rx_strm.next_in = buf;
  341.     rx_strm.avail_in = len;
  342.     r = inflateIncomp(&rx_strm);
  343.     if (r != Z_OK) {
  344.     fprintf(FERROR, "inflateIncomp returned %d\n", r);
  345.     exit_cleanup(1);
  346.     }
  347. }
  348.  
  349. /*
  350.  * transmit a verbatim buffer of length n followed by a token 
  351.  * If token == -1 then we have reached EOF 
  352.  * If n == 0 then don't send a buffer
  353.  */
  354. void send_token(int f,int token,struct map_struct *buf,int offset,
  355.         int n,int toklen)
  356. {
  357.   if (!do_compression) {
  358.     simple_send_token(f,token,buf,offset,n);
  359.   } else {
  360.     send_deflated_token(f, token, buf, offset, n, toklen);
  361.   }
  362. }
  363.  
  364.  
  365. /*
  366.  * receive a token or buffer from the other end. If the reurn value is >0 then
  367.  * it is a data buffer of that length, and *data will point at the data.
  368.  * if the return value is -i then it represents token i-1
  369.  * if the return value is 0 then the end has been reached
  370.  */
  371. int recv_token(int f,char **data)
  372. {
  373.   int tok;
  374.  
  375.   if (!do_compression) {
  376.     tok = simple_recv_token(f,data);
  377.   } else {
  378.     tok = recv_deflated_token(f, data);
  379.   }
  380.   return tok;
  381. }
  382.  
  383. /*
  384.  * look at the data corresponding to a token, if necessary
  385.  */
  386. void see_token(char *data, int toklen)
  387. {
  388.     if (do_compression)
  389.     see_deflate_token(data, toklen);
  390. }
  391.