token.c

説明を見る。
00001 /*
00002    Copyright (C) Andrew Tridgell 1996
00003    Copyright (C) Paul Mackerras 1996
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 2 of the License, or
00008    (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program; if not, write to the Free Software
00017    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 */
00019 
00020 #include "rsync.h"
00021 #include "zlib/zlib.h"
00022 
00023 extern int do_compression;
00024 extern int module_id;
00025 extern int def_compress_level;
00026 
00027 static int compression_level, per_file_default_level;
00028 
00029 /* determine the compression level based on a wildcard filename list */
00030 void set_compression(char *fname)
00031 {
00032         static char *match_list;
00033         char *s;
00034 
00035         if (!do_compression)
00036                 return;
00037 
00038         if (!match_list) {
00039                 char *t, *f = lp_dont_compress(module_id);
00040                 int len = strlen(f);
00041                 if (!(match_list = t = new_array(char, len + 2)))
00042                         out_of_memory("set_compression");
00043                 while (*f) {
00044                         if (*f == ' ') {
00045                                 f++;
00046                                 continue;
00047                         }
00048                         do {
00049                                 if (isupper(*(unsigned char *)f))
00050                                         *t++ = tolower(*(unsigned char *)f);
00051                                 else
00052                                         *t++ = *f;
00053                         } while (*++f != ' ' && *f);
00054                         *t++ = '\0';
00055                 }
00056                 /* Optimize a match-string of "*". */
00057                 if (t - match_list == 2 && match_list[0] == '*') {
00058                         t = match_list;
00059                         per_file_default_level = 0;
00060                 } else
00061                         per_file_default_level = def_compress_level;
00062                 *t++ = '\0';
00063         }
00064 
00065         compression_level = per_file_default_level;
00066 
00067         if (!*match_list)
00068                 return;
00069 
00070         if ((s = strrchr(fname, '/')) != NULL)
00071                 fname = s + 1;
00072 
00073         for (s = match_list; *s; s += strlen(s) + 1) {
00074                 if (iwildmatch(s, fname)) {
00075                         compression_level = 0;
00076                         break;
00077                 }
00078         }
00079 }
00080 
00081 /* non-compressing recv token */
00082 static int32 simple_recv_token(int f, char **data)
00083 {
00084         static int32 residue;
00085         static char *buf;
00086         int32 n;
00087 
00088         if (!buf) {
00089                 buf = new_array(char, CHUNK_SIZE);
00090                 if (!buf)
00091                         out_of_memory("simple_recv_token");
00092         }
00093 
00094         if (residue == 0) {
00095                 int32 i = read_int(f);
00096                 if (i <= 0)
00097                         return i;
00098                 residue = i;
00099         }
00100 
00101         *data = buf;
00102         n = MIN(CHUNK_SIZE,residue);
00103         residue -= n;
00104         read_buf(f,buf,n);
00105         return n;
00106 }
00107 
00108 
00109 /* non-compressing send token */
00110 static void simple_send_token(int f, int32 token, struct map_struct *buf,
00111                               OFF_T offset, int32 n)
00112 {
00113         if (n > 0) {
00114                 int32 len = 0;
00115                 while (len < n) {
00116                         int32 n1 = MIN(CHUNK_SIZE, n-len);
00117                         write_int(f, n1);
00118                         write_buf(f, map_ptr(buf, offset+len, n1), n1);
00119                         len += n1;
00120                 }
00121         }
00122         /* a -2 token means to send data only and no token */
00123         if (token != -2)
00124                 write_int(f, -(token+1));
00125 }
00126 
00127 
00128 /* Flag bytes in compressed stream are encoded as follows: */
00129 #define END_FLAG        0       /* that's all folks */
00130 #define TOKEN_LONG      0x20    /* followed by 32-bit token number */
00131 #define TOKENRUN_LONG   0x21    /* ditto with 16-bit run count */
00132 #define DEFLATED_DATA   0x40    /* + 6-bit high len, then low len byte */
00133 #define TOKEN_REL       0x80    /* + 6-bit relative token number */
00134 #define TOKENRUN_REL    0xc0    /* ditto with 16-bit run count */
00135 
00136 #define MAX_DATA_COUNT  16383   /* fit 14 bit count into 2 bytes with flags */
00137 
00138 /* zlib.h says that if we want to be able to compress something in a single
00139  * call, avail_out must be at least 0.1% larger than avail_in plus 12 bytes.
00140  * We'll add in 0.1%+16, just to be safe (and we'll avoid floating point,
00141  * to ensure that this is a compile-time value). */
00142 #define AVAIL_OUT_SIZE(avail_in_size) ((avail_in_size)*1001/1000+16)
00143 
00144 /* For coding runs of tokens */
00145 static int32 last_token = -1;
00146 static int32 run_start;
00147 static int32 last_run_end;
00148 
00149 /* Deflation state */
00150 static z_stream tx_strm;
00151 
00152 /* Output buffer */
00153 static char *obuf;
00154 
00155 /* We want obuf to be able to hold both MAX_DATA_COUNT+2 bytes as well as
00156  * AVAIL_OUT_SIZE(CHUNK_SIZE) bytes, so make sure that it's large enough. */
00157 #if MAX_DATA_COUNT+2 > AVAIL_OUT_SIZE(CHUNK_SIZE)
00158 #define OBUF_SIZE       (MAX_DATA_COUNT+2)
00159 #else
00160 #define OBUF_SIZE       AVAIL_OUT_SIZE(CHUNK_SIZE)
00161 #endif
00162 
00163 /* Send a deflated token */
00164 static void
00165 send_deflated_token(int f, int32 token, struct map_struct *buf, OFF_T offset,
00166                     int32 nb, int32 toklen)
00167 {
00168         int32 n, r;
00169         static int init_done, flush_pending;
00170 
00171         if (last_token == -1) {
00172                 /* initialization */
00173                 if (!init_done) {
00174                         tx_strm.next_in = NULL;
00175                         tx_strm.zalloc = NULL;
00176                         tx_strm.zfree = NULL;
00177                         if (deflateInit2(&tx_strm, compression_level,
00178                                          Z_DEFLATED, -15, 8,
00179                                          Z_DEFAULT_STRATEGY) != Z_OK) {
00180                                 rprintf(FERROR, "compression init failed\n");
00181                                 exit_cleanup(RERR_STREAMIO);
00182                         }
00183                         if ((obuf = new_array(char, OBUF_SIZE)) == NULL)
00184                                 out_of_memory("send_deflated_token");
00185                         init_done = 1;
00186                 } else
00187                         deflateReset(&tx_strm);
00188                 last_run_end = 0;
00189                 run_start = token;
00190                 flush_pending = 0;
00191 
00192         } else if (last_token == -2) {
00193                 run_start = token;
00194 
00195         } else if (nb != 0 || token != last_token + 1
00196                    || token >= run_start + 65536) {
00197                 /* output previous run */
00198                 r = run_start - last_run_end;
00199                 n = last_token - run_start;
00200                 if (r >= 0 && r <= 63) {
00201                         write_byte(f, (n==0? TOKEN_REL: TOKENRUN_REL) + r);
00202                 } else {
00203                         write_byte(f, (n==0? TOKEN_LONG: TOKENRUN_LONG));
00204                         write_int(f, run_start);
00205                 }
00206                 if (n != 0) {
00207                         write_byte(f, n);
00208                         write_byte(f, n >> 8);
00209                 }
00210                 last_run_end = last_token;
00211                 run_start = token;
00212         }
00213 
00214         last_token = token;
00215 
00216         if (nb != 0 || flush_pending) {
00217                 /* deflate the data starting at offset */
00218                 int flush = Z_NO_FLUSH;
00219                 tx_strm.avail_in = 0;
00220                 tx_strm.avail_out = 0;
00221                 do {
00222                         if (tx_strm.avail_in == 0 && nb != 0) {
00223                                 /* give it some more input */
00224                                 n = MIN(nb, CHUNK_SIZE);
00225                                 tx_strm.next_in = (Bytef *)
00226                                         map_ptr(buf, offset, n);
00227                                 tx_strm.avail_in = n;
00228                                 nb -= n;
00229                                 offset += n;
00230                         }
00231                         if (tx_strm.avail_out == 0) {
00232                                 tx_strm.next_out = (Bytef *)(obuf + 2);
00233                                 tx_strm.avail_out = MAX_DATA_COUNT;
00234                                 if (flush != Z_NO_FLUSH) {
00235                                         /*
00236                                          * We left the last 4 bytes in the
00237                                          * buffer, in case they are the
00238                                          * last 4.  Move them to the front.
00239                                          */
00240                                         memcpy(tx_strm.next_out,
00241                                                obuf+MAX_DATA_COUNT-2, 4);
00242                                         tx_strm.next_out += 4;
00243                                         tx_strm.avail_out -= 4;
00244                                 }
00245                         }
00246                         if (nb == 0 && token != -2)
00247                                 flush = Z_SYNC_FLUSH;
00248                         r = deflate(&tx_strm, flush);
00249                         if (r != Z_OK) {
00250                                 rprintf(FERROR, "deflate returned %d\n", r);
00251                                 exit_cleanup(RERR_STREAMIO);
00252                         }
00253                         if (nb == 0 || tx_strm.avail_out == 0) {
00254                                 n = MAX_DATA_COUNT - tx_strm.avail_out;
00255                                 if (flush != Z_NO_FLUSH) {
00256                                         /*
00257                                          * We have to trim off the last 4
00258                                          * bytes of output when flushing
00259                                          * (they are just 0, 0, ff, ff).
00260                                          */
00261                                         n -= 4;
00262                                 }
00263                                 if (n > 0) {
00264                                         obuf[0] = DEFLATED_DATA + (n >> 8);
00265                                         obuf[1] = n;
00266                                         write_buf(f, obuf, n+2);
00267                                 }
00268                         }
00269                 } while (nb != 0 || tx_strm.avail_out == 0);
00270                 flush_pending = token == -2;
00271         }
00272 
00273         if (token == -1) {
00274                 /* end of file - clean up */
00275                 write_byte(f, END_FLAG);
00276         } else if (token != -2) {
00277                 /* Add the data in the current block to the compressor's
00278                  * history and hash table. */
00279                 do {
00280                         /* Break up long sections in the same way that
00281                          * see_deflate_token() does. */
00282                         int32 n1 = toklen > 0xffff ? 0xffff : toklen;
00283                         toklen -= n1;
00284                         tx_strm.next_in = (Bytef *)map_ptr(buf, offset, n1);
00285                         tx_strm.avail_in = n1;
00286                         tx_strm.next_out = (Bytef *) obuf;
00287                         tx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
00288                         r = deflate(&tx_strm, Z_INSERT_ONLY);
00289                         if (r != Z_OK || tx_strm.avail_in != 0) {
00290                                 rprintf(FERROR, "deflate on token returned %d (%d bytes left)\n",
00291                                         r, tx_strm.avail_in);
00292                                 exit_cleanup(RERR_STREAMIO);
00293                         }
00294                 } while (toklen > 0);
00295         }
00296 }
00297 
00298 
00299 /* tells us what the receiver is in the middle of doing */
00300 static enum { r_init, r_idle, r_running, r_inflating, r_inflated } recv_state;
00301 
00302 /* for inflating stuff */
00303 static z_stream rx_strm;
00304 static char *cbuf;
00305 static char *dbuf;
00306 
00307 /* for decoding runs of tokens */
00308 static int32 rx_token;
00309 static int32 rx_run;
00310 
00311 /* Receive a deflated token and inflate it */
00312 static int32 recv_deflated_token(int f, char **data)
00313 {
00314         static int init_done;
00315         static int32 saved_flag;
00316         int32 n, flag;
00317         int r;
00318 
00319         for (;;) {
00320                 switch (recv_state) {
00321                 case r_init:
00322                         if (!init_done) {
00323                                 rx_strm.next_out = NULL;
00324                                 rx_strm.zalloc = NULL;
00325                                 rx_strm.zfree = NULL;
00326                                 if (inflateInit2(&rx_strm, -15) != Z_OK) {
00327                                         rprintf(FERROR, "inflate init failed\n");
00328                                         exit_cleanup(RERR_STREAMIO);
00329                                 }
00330                                 if (!(cbuf = new_array(char, MAX_DATA_COUNT))
00331                                     || !(dbuf = new_array(char, AVAIL_OUT_SIZE(CHUNK_SIZE))))
00332                                         out_of_memory("recv_deflated_token");
00333                                 init_done = 1;
00334                         } else {
00335                                 inflateReset(&rx_strm);
00336                         }
00337                         recv_state = r_idle;
00338                         rx_token = 0;
00339                         break;
00340 
00341                 case r_idle:
00342                 case r_inflated:
00343                         if (saved_flag) {
00344                                 flag = saved_flag & 0xff;
00345                                 saved_flag = 0;
00346                         } else
00347                                 flag = read_byte(f);
00348                         if ((flag & 0xC0) == DEFLATED_DATA) {
00349                                 n = ((flag & 0x3f) << 8) + read_byte(f);
00350                                 read_buf(f, cbuf, n);
00351                                 rx_strm.next_in = (Bytef *)cbuf;
00352                                 rx_strm.avail_in = n;
00353                                 recv_state = r_inflating;
00354                                 break;
00355                         }
00356                         if (recv_state == r_inflated) {
00357                                 /* check previous inflated stuff ended correctly */
00358                                 rx_strm.avail_in = 0;
00359                                 rx_strm.next_out = (Bytef *)dbuf;
00360                                 rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
00361                                 r = inflate(&rx_strm, Z_SYNC_FLUSH);
00362                                 n = AVAIL_OUT_SIZE(CHUNK_SIZE) - rx_strm.avail_out;
00363                                 /*
00364                                  * Z_BUF_ERROR just means no progress was
00365                                  * made, i.e. the decompressor didn't have
00366                                  * any pending output for us.
00367                                  */
00368                                 if (r != Z_OK && r != Z_BUF_ERROR) {
00369                                         rprintf(FERROR, "inflate flush returned %d (%d bytes)\n",
00370                                                 r, n);
00371                                         exit_cleanup(RERR_STREAMIO);
00372                                 }
00373                                 if (n != 0 && r != Z_BUF_ERROR) {
00374                                         /* have to return some more data and
00375                                            save the flag for later. */
00376                                         saved_flag = flag + 0x10000;
00377                                         *data = dbuf;
00378                                         return n;
00379                                 }
00380                                 /*
00381                                  * At this point the decompressor should
00382                                  * be expecting to see the 0, 0, ff, ff bytes.
00383                                  */
00384                                 if (!inflateSyncPoint(&rx_strm)) {
00385                                         rprintf(FERROR, "decompressor lost sync!\n");
00386                                         exit_cleanup(RERR_STREAMIO);
00387                                 }
00388                                 rx_strm.avail_in = 4;
00389                                 rx_strm.next_in = (Bytef *)cbuf;
00390                                 cbuf[0] = cbuf[1] = 0;
00391                                 cbuf[2] = cbuf[3] = 0xff;
00392                                 inflate(&rx_strm, Z_SYNC_FLUSH);
00393                                 recv_state = r_idle;
00394                         }
00395                         if (flag == END_FLAG) {
00396                                 /* that's all folks */
00397                                 recv_state = r_init;
00398                                 return 0;
00399                         }
00400 
00401                         /* here we have a token of some kind */
00402                         if (flag & TOKEN_REL) {
00403                                 rx_token += flag & 0x3f;
00404                                 flag >>= 6;
00405                         } else
00406                                 rx_token = read_int(f);
00407                         if (flag & 1) {
00408                                 rx_run = read_byte(f);
00409                                 rx_run += read_byte(f) << 8;
00410                                 recv_state = r_running;
00411                         }
00412                         return -1 - rx_token;
00413 
00414                 case r_inflating:
00415                         rx_strm.next_out = (Bytef *)dbuf;
00416                         rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
00417                         r = inflate(&rx_strm, Z_NO_FLUSH);
00418                         n = AVAIL_OUT_SIZE(CHUNK_SIZE) - rx_strm.avail_out;
00419                         if (r != Z_OK) {
00420                                 rprintf(FERROR, "inflate returned %d (%d bytes)\n", r, n);
00421                                 exit_cleanup(RERR_STREAMIO);
00422                         }
00423                         if (rx_strm.avail_in == 0)
00424                                 recv_state = r_inflated;
00425                         if (n != 0) {
00426                                 *data = dbuf;
00427                                 return n;
00428                         }
00429                         break;
00430 
00431                 case r_running:
00432                         ++rx_token;
00433                         if (--rx_run == 0)
00434                                 recv_state = r_idle;
00435                         return -1 - rx_token;
00436                 }
00437         }
00438 }
00439 
00440 /*
00441  * put the data corresponding to a token that we've just returned
00442  * from recv_deflated_token into the decompressor's history buffer.
00443  */
00444 static void see_deflate_token(char *buf, int32 len)
00445 {
00446         int r;
00447         int32 blklen;
00448         unsigned char hdr[5];
00449 
00450         rx_strm.avail_in = 0;
00451         blklen = 0;
00452         hdr[0] = 0;
00453         do {
00454                 if (rx_strm.avail_in == 0 && len != 0) {
00455                         if (blklen == 0) {
00456                                 /* Give it a fake stored-block header. */
00457                                 rx_strm.next_in = (Bytef *)hdr;
00458                                 rx_strm.avail_in = 5;
00459                                 blklen = len;
00460                                 if (blklen > 0xffff)
00461                                         blklen = 0xffff;
00462                                 hdr[1] = blklen;
00463                                 hdr[2] = blklen >> 8;
00464                                 hdr[3] = ~hdr[1];
00465                                 hdr[4] = ~hdr[2];
00466                         } else {
00467                                 rx_strm.next_in = (Bytef *)buf;
00468                                 rx_strm.avail_in = blklen;
00469                                 len -= blklen;
00470                                 blklen = 0;
00471                         }
00472                 }
00473                 rx_strm.next_out = (Bytef *)dbuf;
00474                 rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
00475                 r = inflate(&rx_strm, Z_SYNC_FLUSH);
00476                 if (r != Z_OK) {
00477                         rprintf(FERROR, "inflate (token) returned %d\n", r);
00478                         exit_cleanup(RERR_STREAMIO);
00479                 }
00480         } while (len || rx_strm.avail_out == 0);
00481 }
00482 
00483 /**
00484  * Transmit a verbatim buffer of length @p n followed by a token.
00485  * If token == -1 then we have reached EOF
00486  * If n == 0 then don't send a buffer
00487  */
00488 void send_token(int f, int32 token, struct map_struct *buf, OFF_T offset,
00489                 int32 n, int32 toklen)
00490 {
00491         if (!do_compression)
00492                 simple_send_token(f, token, buf, offset, n);
00493         else
00494                 send_deflated_token(f, token, buf, offset, n, toklen);
00495 }
00496 
00497 
00498 /*
00499  * receive a token or buffer from the other end. If the reurn value is >0 then
00500  * it is a data buffer of that length, and *data will point at the data.
00501  * if the return value is -i then it represents token i-1
00502  * if the return value is 0 then the end has been reached
00503  */
00504 int32 recv_token(int f, char **data)
00505 {
00506         int tok;
00507 
00508         if (!do_compression) {
00509                 tok = simple_recv_token(f,data);
00510         } else {
00511                 tok = recv_deflated_token(f, data);
00512         }
00513         return tok;
00514 }
00515 
00516 /*
00517  * look at the data corresponding to a token, if necessary
00518  */
00519 void see_token(char *data, int32 toklen)
00520 {
00521         if (do_compression)
00522                 see_deflate_token(data, toklen);
00523 }

rsyncに対してSat Dec 5 19:45:42 2009に生成されました。  doxygen 1.4.7