Annotation of embedaddon/rsync/token.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Routines used by the file-transfer code.
        !             3:  *
        !             4:  * Copyright (C) 1996 Andrew Tridgell
        !             5:  * Copyright (C) 1996 Paul Mackerras
        !             6:  * Copyright (C) 2003-2009 Wayne Davison
        !             7:  *
        !             8:  * This program is free software; you can redistribute it and/or modify
        !             9:  * it under the terms of the GNU General Public License as published by
        !            10:  * the Free Software Foundation; either version 3 of the License, or
        !            11:  * (at your option) any later version.
        !            12:  *
        !            13:  * This program is distributed in the hope that it will be useful,
        !            14:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            15:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            16:  * GNU General Public License for more details.
        !            17:  *
        !            18:  * You should have received a copy of the GNU General Public License along
        !            19:  * with this program; if not, visit the http://fsf.org website.
        !            20:  */
        !            21: 
        !            22: #include "rsync.h"
        !            23: #include "ifuncs.h"
        !            24: #include "zlib/zlib.h"
        !            25: 
        !            26: extern int do_compression;
        !            27: extern int module_id;
        !            28: extern int def_compress_level;
        !            29: extern char *skip_compress;
        !            30: 
        !            31: static int compression_level, per_file_default_level;
        !            32: 
        !            33: struct suffix_tree {
        !            34:        struct suffix_tree *sibling;
        !            35:        struct suffix_tree *child;
        !            36:        char letter, word_end;
        !            37: };
        !            38: 
        !            39: static char *match_list;
        !            40: static struct suffix_tree *suftree;
        !            41: 
        !            42: static void add_suffix(struct suffix_tree **prior, char ltr, const char *str)
        !            43: {
        !            44:        struct suffix_tree *node, *newnode;
        !            45: 
        !            46:        if (ltr == '[') {
        !            47:                const char *after = strchr(str, ']');
        !            48:                /* Treat "[foo" and "[]" as having a literal '['. */
        !            49:                if (after && after++ != str+1) {
        !            50:                        while ((ltr = *str++) != ']')
        !            51:                                add_suffix(prior, ltr, after);
        !            52:                        return;
        !            53:                }
        !            54:        }
        !            55: 
        !            56:        for (node = *prior; node; prior = &node->sibling, node = node->sibling) {
        !            57:                if (node->letter == ltr) {
        !            58:                        if (*str)
        !            59:                                add_suffix(&node->child, *str, str+1);
        !            60:                        else
        !            61:                                node->word_end = 1;
        !            62:                        return;
        !            63:                }
        !            64:                if (node->letter > ltr)
        !            65:                        break;
        !            66:        }
        !            67:        if (!(newnode = new(struct suffix_tree)))
        !            68:                out_of_memory("add_suffix");
        !            69:        newnode->sibling = node;
        !            70:        newnode->child = NULL;
        !            71:        newnode->letter = ltr;
        !            72:        *prior = newnode;
        !            73:        if (*str) {
        !            74:                add_suffix(&newnode->child, *str, str+1);
        !            75:                newnode->word_end = 0;
        !            76:        } else
        !            77:                newnode->word_end = 1;
        !            78: }
        !            79: 
        !            80: static void add_nocompress_suffixes(const char *str)
        !            81: {
        !            82:        char *buf, *t;
        !            83:        const char *f = str;
        !            84: 
        !            85:        if (!(buf = new_array(char, strlen(f) + 1)))
        !            86:                out_of_memory("add_nocompress_suffixes");
        !            87: 
        !            88:        while (*f) {
        !            89:                if (*f == '/') {
        !            90:                        f++;
        !            91:                        continue;
        !            92:                }
        !            93: 
        !            94:                t = buf;
        !            95:                do {
        !            96:                        if (isUpper(f))
        !            97:                                *t++ = toLower(f);
        !            98:                        else
        !            99:                                *t++ = *f;
        !           100:                } while (*++f != '/' && *f);
        !           101:                *t++ = '\0';
        !           102: 
        !           103:                add_suffix(&suftree, *buf, buf+1);
        !           104:        }
        !           105: 
        !           106:        free(buf);
        !           107: }
        !           108: 
        !           109: static void init_set_compression(void)
        !           110: {
        !           111:        const char *f;
        !           112:        char *t, *start;
        !           113: 
        !           114:        if (skip_compress)
        !           115:                add_nocompress_suffixes(skip_compress);
        !           116: 
        !           117:        /* A non-daemon transfer skips the default suffix list if the
        !           118:         * user specified --skip-compress. */
        !           119:        if (skip_compress && module_id < 0)
        !           120:                f = "";
        !           121:        else
        !           122:                f = lp_dont_compress(module_id);
        !           123: 
        !           124:        if (!(match_list = t = new_array(char, strlen(f) + 2)))
        !           125:                out_of_memory("set_compression");
        !           126: 
        !           127:        per_file_default_level = def_compress_level;
        !           128: 
        !           129:        while (*f) {
        !           130:                if (*f == ' ') {
        !           131:                        f++;
        !           132:                        continue;
        !           133:                }
        !           134: 
        !           135:                start = t;
        !           136:                do {
        !           137:                        if (isUpper(f))
        !           138:                                *t++ = toLower(f);
        !           139:                        else
        !           140:                                *t++ = *f;
        !           141:                } while (*++f != ' ' && *f);
        !           142:                *t++ = '\0';
        !           143: 
        !           144:                if (t - start == 1+1 && *start == '*') {
        !           145:                        /* Optimize a match-string of "*". */
        !           146:                        *match_list = '\0';
        !           147:                        suftree = NULL;
        !           148:                        per_file_default_level = 0;
        !           149:                        break;
        !           150:                }
        !           151: 
        !           152:                /* Move *.foo items into the stuffix tree. */
        !           153:                if (*start == '*' && start[1] == '.' && start[2]
        !           154:                 && !strpbrk(start+2, ".?*")) {
        !           155:                        add_suffix(&suftree, start[2], start+3);
        !           156:                        t = start;
        !           157:                }
        !           158:        }
        !           159:        *t++ = '\0';
        !           160: }
        !           161: 
        !           162: /* determine the compression level based on a wildcard filename list */
        !           163: void set_compression(const char *fname)
        !           164: {
        !           165:        const struct suffix_tree *node;
        !           166:        const char *s;
        !           167:        char ltr;
        !           168: 
        !           169:        if (!do_compression)
        !           170:                return;
        !           171: 
        !           172:        if (!match_list)
        !           173:                init_set_compression();
        !           174: 
        !           175:        compression_level = per_file_default_level;
        !           176: 
        !           177:        if (!*match_list && !suftree)
        !           178:                return;
        !           179: 
        !           180:        if ((s = strrchr(fname, '/')) != NULL)
        !           181:                fname = s + 1;
        !           182: 
        !           183:        for (s = match_list; *s; s += strlen(s) + 1) {
        !           184:                if (iwildmatch(s, fname)) {
        !           185:                        compression_level = 0;
        !           186:                        return;
        !           187:                }
        !           188:        }
        !           189: 
        !           190:        if (!(node = suftree) || !(s = strrchr(fname, '.'))
        !           191:         || s == fname || !(ltr = *++s))
        !           192:                return;
        !           193: 
        !           194:        while (1) {
        !           195:                if (isUpper(&ltr))
        !           196:                        ltr = toLower(&ltr);
        !           197:                while (node->letter != ltr) {
        !           198:                        if (node->letter > ltr)
        !           199:                                return;
        !           200:                        if (!(node = node->sibling))
        !           201:                                return;
        !           202:                }
        !           203:                if ((ltr = *++s) == '\0') {
        !           204:                        if (node->word_end)
        !           205:                                compression_level = 0;
        !           206:                        return;
        !           207:                }
        !           208:                if (!(node = node->child))
        !           209:                        return;
        !           210:        }
        !           211: }
        !           212: 
        !           213: /* non-compressing recv token */
        !           214: static int32 simple_recv_token(int f, char **data)
        !           215: {
        !           216:        static int32 residue;
        !           217:        static char *buf;
        !           218:        int32 n;
        !           219: 
        !           220:        if (!buf) {
        !           221:                buf = new_array(char, CHUNK_SIZE);
        !           222:                if (!buf)
        !           223:                        out_of_memory("simple_recv_token");
        !           224:        }
        !           225: 
        !           226:        if (residue == 0) {
        !           227:                int32 i = read_int(f);
        !           228:                if (i <= 0)
        !           229:                        return i;
        !           230:                residue = i;
        !           231:        }
        !           232: 
        !           233:        *data = buf;
        !           234:        n = MIN(CHUNK_SIZE,residue);
        !           235:        residue -= n;
        !           236:        read_buf(f,buf,n);
        !           237:        return n;
        !           238: }
        !           239: 
        !           240: /* non-compressing send token */
        !           241: static void simple_send_token(int f, int32 token, struct map_struct *buf,
        !           242:                              OFF_T offset, int32 n)
        !           243: {
        !           244:        if (n > 0) {
        !           245:                int32 len = 0;
        !           246:                while (len < n) {
        !           247:                        int32 n1 = MIN(CHUNK_SIZE, n-len);
        !           248:                        write_int(f, n1);
        !           249:                        write_buf(f, map_ptr(buf, offset+len, n1), n1);
        !           250:                        len += n1;
        !           251:                }
        !           252:        }
        !           253:        /* a -2 token means to send data only and no token */
        !           254:        if (token != -2)
        !           255:                write_int(f, -(token+1));
        !           256: }
        !           257: 
        !           258: /* Flag bytes in compressed stream are encoded as follows: */
        !           259: #define END_FLAG       0       /* that's all folks */
        !           260: #define TOKEN_LONG     0x20    /* followed by 32-bit token number */
        !           261: #define TOKENRUN_LONG  0x21    /* ditto with 16-bit run count */
        !           262: #define DEFLATED_DATA  0x40    /* + 6-bit high len, then low len byte */
        !           263: #define TOKEN_REL      0x80    /* + 6-bit relative token number */
        !           264: #define TOKENRUN_REL   0xc0    /* ditto with 16-bit run count */
        !           265: 
        !           266: #define MAX_DATA_COUNT 16383   /* fit 14 bit count into 2 bytes with flags */
        !           267: 
        !           268: /* zlib.h says that if we want to be able to compress something in a single
        !           269:  * call, avail_out must be at least 0.1% larger than avail_in plus 12 bytes.
        !           270:  * We'll add in 0.1%+16, just to be safe (and we'll avoid floating point,
        !           271:  * to ensure that this is a compile-time value). */
        !           272: #define AVAIL_OUT_SIZE(avail_in_size) ((avail_in_size)*1001/1000+16)
        !           273: 
        !           274: /* For coding runs of tokens */
        !           275: static int32 last_token = -1;
        !           276: static int32 run_start;
        !           277: static int32 last_run_end;
        !           278: 
        !           279: /* Deflation state */
        !           280: static z_stream tx_strm;
        !           281: 
        !           282: /* Output buffer */
        !           283: static char *obuf;
        !           284: 
        !           285: /* We want obuf to be able to hold both MAX_DATA_COUNT+2 bytes as well as
        !           286:  * AVAIL_OUT_SIZE(CHUNK_SIZE) bytes, so make sure that it's large enough. */
        !           287: #if MAX_DATA_COUNT+2 > AVAIL_OUT_SIZE(CHUNK_SIZE)
        !           288: #define OBUF_SIZE      (MAX_DATA_COUNT+2)
        !           289: #else
        !           290: #define OBUF_SIZE      AVAIL_OUT_SIZE(CHUNK_SIZE)
        !           291: #endif
        !           292: 
        !           293: /* Send a deflated token */
        !           294: static void
        !           295: send_deflated_token(int f, int32 token, struct map_struct *buf, OFF_T offset,
        !           296:                    int32 nb, int32 toklen)
        !           297: {
        !           298:        int32 n, r;
        !           299:        static int init_done, flush_pending;
        !           300: 
        !           301:        if (last_token == -1) {
        !           302:                /* initialization */
        !           303:                if (!init_done) {
        !           304:                        tx_strm.next_in = NULL;
        !           305:                        tx_strm.zalloc = NULL;
        !           306:                        tx_strm.zfree = NULL;
        !           307:                        if (deflateInit2(&tx_strm, compression_level,
        !           308:                                         Z_DEFLATED, -15, 8,
        !           309:                                         Z_DEFAULT_STRATEGY) != Z_OK) {
        !           310:                                rprintf(FERROR, "compression init failed\n");
        !           311:                                exit_cleanup(RERR_STREAMIO);
        !           312:                        }
        !           313:                        if ((obuf = new_array(char, OBUF_SIZE)) == NULL)
        !           314:                                out_of_memory("send_deflated_token");
        !           315:                        init_done = 1;
        !           316:                } else
        !           317:                        deflateReset(&tx_strm);
        !           318:                last_run_end = 0;
        !           319:                run_start = token;
        !           320:                flush_pending = 0;
        !           321:        } else if (last_token == -2) {
        !           322:                run_start = token;
        !           323:        } else if (nb != 0 || token != last_token + 1
        !           324:                   || token >= run_start + 65536) {
        !           325:                /* output previous run */
        !           326:                r = run_start - last_run_end;
        !           327:                n = last_token - run_start;
        !           328:                if (r >= 0 && r <= 63) {
        !           329:                        write_byte(f, (n==0? TOKEN_REL: TOKENRUN_REL) + r);
        !           330:                } else {
        !           331:                        write_byte(f, (n==0? TOKEN_LONG: TOKENRUN_LONG));
        !           332:                        write_int(f, run_start);
        !           333:                }
        !           334:                if (n != 0) {
        !           335:                        write_byte(f, n);
        !           336:                        write_byte(f, n >> 8);
        !           337:                }
        !           338:                last_run_end = last_token;
        !           339:                run_start = token;
        !           340:        }
        !           341: 
        !           342:        last_token = token;
        !           343: 
        !           344:        if (nb != 0 || flush_pending) {
        !           345:                /* deflate the data starting at offset */
        !           346:                int flush = Z_NO_FLUSH;
        !           347:                tx_strm.avail_in = 0;
        !           348:                tx_strm.avail_out = 0;
        !           349:                do {
        !           350:                        if (tx_strm.avail_in == 0 && nb != 0) {
        !           351:                                /* give it some more input */
        !           352:                                n = MIN(nb, CHUNK_SIZE);
        !           353:                                tx_strm.next_in = (Bytef *)
        !           354:                                        map_ptr(buf, offset, n);
        !           355:                                tx_strm.avail_in = n;
        !           356:                                nb -= n;
        !           357:                                offset += n;
        !           358:                        }
        !           359:                        if (tx_strm.avail_out == 0) {
        !           360:                                tx_strm.next_out = (Bytef *)(obuf + 2);
        !           361:                                tx_strm.avail_out = MAX_DATA_COUNT;
        !           362:                                if (flush != Z_NO_FLUSH) {
        !           363:                                        /*
        !           364:                                         * We left the last 4 bytes in the
        !           365:                                         * buffer, in case they are the
        !           366:                                         * last 4.  Move them to the front.
        !           367:                                         */
        !           368:                                        memcpy(tx_strm.next_out,
        !           369:                                               obuf+MAX_DATA_COUNT-2, 4);
        !           370:                                        tx_strm.next_out += 4;
        !           371:                                        tx_strm.avail_out -= 4;
        !           372:                                }
        !           373:                        }
        !           374:                        if (nb == 0 && token != -2)
        !           375:                                flush = Z_SYNC_FLUSH;
        !           376:                        r = deflate(&tx_strm, flush);
        !           377:                        if (r != Z_OK) {
        !           378:                                rprintf(FERROR, "deflate returned %d\n", r);
        !           379:                                exit_cleanup(RERR_STREAMIO);
        !           380:                        }
        !           381:                        if (nb == 0 || tx_strm.avail_out == 0) {
        !           382:                                n = MAX_DATA_COUNT - tx_strm.avail_out;
        !           383:                                if (flush != Z_NO_FLUSH) {
        !           384:                                        /*
        !           385:                                         * We have to trim off the last 4
        !           386:                                         * bytes of output when flushing
        !           387:                                         * (they are just 0, 0, ff, ff).
        !           388:                                         */
        !           389:                                        n -= 4;
        !           390:                                }
        !           391:                                if (n > 0) {
        !           392:                                        obuf[0] = DEFLATED_DATA + (n >> 8);
        !           393:                                        obuf[1] = n;
        !           394:                                        write_buf(f, obuf, n+2);
        !           395:                                }
        !           396:                        }
        !           397:                } while (nb != 0 || tx_strm.avail_out == 0);
        !           398:                flush_pending = token == -2;
        !           399:        }
        !           400: 
        !           401:        if (token == -1) {
        !           402:                /* end of file - clean up */
        !           403:                write_byte(f, END_FLAG);
        !           404:        } else if (token != -2) {
        !           405:                /* Add the data in the current block to the compressor's
        !           406:                 * history and hash table. */
        !           407:                do {
        !           408:                        /* Break up long sections in the same way that
        !           409:                         * see_deflate_token() does. */
        !           410:                        int32 n1 = toklen > 0xffff ? 0xffff : toklen;
        !           411:                        toklen -= n1;
        !           412:                        tx_strm.next_in = (Bytef *)map_ptr(buf, offset, n1);
        !           413:                        tx_strm.avail_in = n1;
        !           414:                        tx_strm.next_out = (Bytef *) obuf;
        !           415:                        tx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
        !           416:                        r = deflate(&tx_strm, Z_INSERT_ONLY);
        !           417:                        if (r != Z_OK || tx_strm.avail_in != 0) {
        !           418:                                rprintf(FERROR, "deflate on token returned %d (%d bytes left)\n",
        !           419:                                        r, tx_strm.avail_in);
        !           420:                                exit_cleanup(RERR_STREAMIO);
        !           421:                        }
        !           422:                } while (toklen > 0);
        !           423:        }
        !           424: }
        !           425: 
        !           426: /* tells us what the receiver is in the middle of doing */
        !           427: static enum { r_init, r_idle, r_running, r_inflating, r_inflated } recv_state;
        !           428: 
        !           429: /* for inflating stuff */
        !           430: static z_stream rx_strm;
        !           431: static char *cbuf;
        !           432: static char *dbuf;
        !           433: 
        !           434: /* for decoding runs of tokens */
        !           435: static int32 rx_token;
        !           436: static int32 rx_run;
        !           437: 
        !           438: /* Receive a deflated token and inflate it */
        !           439: static int32 recv_deflated_token(int f, char **data)
        !           440: {
        !           441:        static int init_done;
        !           442:        static int32 saved_flag;
        !           443:        int32 n, flag;
        !           444:        int r;
        !           445: 
        !           446:        for (;;) {
        !           447:                switch (recv_state) {
        !           448:                case r_init:
        !           449:                        if (!init_done) {
        !           450:                                rx_strm.next_out = NULL;
        !           451:                                rx_strm.zalloc = NULL;
        !           452:                                rx_strm.zfree = NULL;
        !           453:                                if (inflateInit2(&rx_strm, -15) != Z_OK) {
        !           454:                                        rprintf(FERROR, "inflate init failed\n");
        !           455:                                        exit_cleanup(RERR_STREAMIO);
        !           456:                                }
        !           457:                                if (!(cbuf = new_array(char, MAX_DATA_COUNT))
        !           458:                                    || !(dbuf = new_array(char, AVAIL_OUT_SIZE(CHUNK_SIZE))))
        !           459:                                        out_of_memory("recv_deflated_token");
        !           460:                                init_done = 1;
        !           461:                        } else {
        !           462:                                inflateReset(&rx_strm);
        !           463:                        }
        !           464:                        recv_state = r_idle;
        !           465:                        rx_token = 0;
        !           466:                        break;
        !           467: 
        !           468:                case r_idle:
        !           469:                case r_inflated:
        !           470:                        if (saved_flag) {
        !           471:                                flag = saved_flag & 0xff;
        !           472:                                saved_flag = 0;
        !           473:                        } else
        !           474:                                flag = read_byte(f);
        !           475:                        if ((flag & 0xC0) == DEFLATED_DATA) {
        !           476:                                n = ((flag & 0x3f) << 8) + read_byte(f);
        !           477:                                read_buf(f, cbuf, n);
        !           478:                                rx_strm.next_in = (Bytef *)cbuf;
        !           479:                                rx_strm.avail_in = n;
        !           480:                                recv_state = r_inflating;
        !           481:                                break;
        !           482:                        }
        !           483:                        if (recv_state == r_inflated) {
        !           484:                                /* check previous inflated stuff ended correctly */
        !           485:                                rx_strm.avail_in = 0;
        !           486:                                rx_strm.next_out = (Bytef *)dbuf;
        !           487:                                rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
        !           488:                                r = inflate(&rx_strm, Z_SYNC_FLUSH);
        !           489:                                n = AVAIL_OUT_SIZE(CHUNK_SIZE) - rx_strm.avail_out;
        !           490:                                /*
        !           491:                                 * Z_BUF_ERROR just means no progress was
        !           492:                                 * made, i.e. the decompressor didn't have
        !           493:                                 * any pending output for us.
        !           494:                                 */
        !           495:                                if (r != Z_OK && r != Z_BUF_ERROR) {
        !           496:                                        rprintf(FERROR, "inflate flush returned %d (%d bytes)\n",
        !           497:                                                r, n);
        !           498:                                        exit_cleanup(RERR_STREAMIO);
        !           499:                                }
        !           500:                                if (n != 0 && r != Z_BUF_ERROR) {
        !           501:                                        /* have to return some more data and
        !           502:                                           save the flag for later. */
        !           503:                                        saved_flag = flag + 0x10000;
        !           504:                                        *data = dbuf;
        !           505:                                        return n;
        !           506:                                }
        !           507:                                /*
        !           508:                                 * At this point the decompressor should
        !           509:                                 * be expecting to see the 0, 0, ff, ff bytes.
        !           510:                                 */
        !           511:                                if (!inflateSyncPoint(&rx_strm)) {
        !           512:                                        rprintf(FERROR, "decompressor lost sync!\n");
        !           513:                                        exit_cleanup(RERR_STREAMIO);
        !           514:                                }
        !           515:                                rx_strm.avail_in = 4;
        !           516:                                rx_strm.next_in = (Bytef *)cbuf;
        !           517:                                cbuf[0] = cbuf[1] = 0;
        !           518:                                cbuf[2] = cbuf[3] = 0xff;
        !           519:                                inflate(&rx_strm, Z_SYNC_FLUSH);
        !           520:                                recv_state = r_idle;
        !           521:                        }
        !           522:                        if (flag == END_FLAG) {
        !           523:                                /* that's all folks */
        !           524:                                recv_state = r_init;
        !           525:                                return 0;
        !           526:                        }
        !           527: 
        !           528:                        /* here we have a token of some kind */
        !           529:                        if (flag & TOKEN_REL) {
        !           530:                                rx_token += flag & 0x3f;
        !           531:                                flag >>= 6;
        !           532:                        } else
        !           533:                                rx_token = read_int(f);
        !           534:                        if (flag & 1) {
        !           535:                                rx_run = read_byte(f);
        !           536:                                rx_run += read_byte(f) << 8;
        !           537:                                recv_state = r_running;
        !           538:                        }
        !           539:                        return -1 - rx_token;
        !           540: 
        !           541:                case r_inflating:
        !           542:                        rx_strm.next_out = (Bytef *)dbuf;
        !           543:                        rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
        !           544:                        r = inflate(&rx_strm, Z_NO_FLUSH);
        !           545:                        n = AVAIL_OUT_SIZE(CHUNK_SIZE) - rx_strm.avail_out;
        !           546:                        if (r != Z_OK) {
        !           547:                                rprintf(FERROR, "inflate returned %d (%d bytes)\n", r, n);
        !           548:                                exit_cleanup(RERR_STREAMIO);
        !           549:                        }
        !           550:                        if (rx_strm.avail_in == 0)
        !           551:                                recv_state = r_inflated;
        !           552:                        if (n != 0) {
        !           553:                                *data = dbuf;
        !           554:                                return n;
        !           555:                        }
        !           556:                        break;
        !           557: 
        !           558:                case r_running:
        !           559:                        ++rx_token;
        !           560:                        if (--rx_run == 0)
        !           561:                                recv_state = r_idle;
        !           562:                        return -1 - rx_token;
        !           563:                }
        !           564:        }
        !           565: }
        !           566: 
        !           567: /*
        !           568:  * put the data corresponding to a token that we've just returned
        !           569:  * from recv_deflated_token into the decompressor's history buffer.
        !           570:  */
        !           571: static void see_deflate_token(char *buf, int32 len)
        !           572: {
        !           573:        int r;
        !           574:        int32 blklen;
        !           575:        unsigned char hdr[5];
        !           576: 
        !           577:        rx_strm.avail_in = 0;
        !           578:        blklen = 0;
        !           579:        hdr[0] = 0;
        !           580:        do {
        !           581:                if (rx_strm.avail_in == 0 && len != 0) {
        !           582:                        if (blklen == 0) {
        !           583:                                /* Give it a fake stored-block header. */
        !           584:                                rx_strm.next_in = (Bytef *)hdr;
        !           585:                                rx_strm.avail_in = 5;
        !           586:                                blklen = len;
        !           587:                                if (blklen > 0xffff)
        !           588:                                        blklen = 0xffff;
        !           589:                                hdr[1] = blklen;
        !           590:                                hdr[2] = blklen >> 8;
        !           591:                                hdr[3] = ~hdr[1];
        !           592:                                hdr[4] = ~hdr[2];
        !           593:                        } else {
        !           594:                                rx_strm.next_in = (Bytef *)buf;
        !           595:                                rx_strm.avail_in = blklen;
        !           596:                                len -= blklen;
        !           597:                                blklen = 0;
        !           598:                        }
        !           599:                }
        !           600:                rx_strm.next_out = (Bytef *)dbuf;
        !           601:                rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
        !           602:                r = inflate(&rx_strm, Z_SYNC_FLUSH);
        !           603:                if (r != Z_OK && r != Z_BUF_ERROR) {
        !           604:                        rprintf(FERROR, "inflate (token) returned %d\n", r);
        !           605:                        exit_cleanup(RERR_STREAMIO);
        !           606:                }
        !           607:        } while (len || rx_strm.avail_out == 0);
        !           608: }
        !           609: 
        !           610: /**
        !           611:  * Transmit a verbatim buffer of length @p n followed by a token.
        !           612:  * If token == -1 then we have reached EOF
        !           613:  * If n == 0 then don't send a buffer
        !           614:  */
        !           615: void send_token(int f, int32 token, struct map_struct *buf, OFF_T offset,
        !           616:                int32 n, int32 toklen)
        !           617: {
        !           618:        if (!do_compression)
        !           619:                simple_send_token(f, token, buf, offset, n);
        !           620:        else
        !           621:                send_deflated_token(f, token, buf, offset, n, toklen);
        !           622: }
        !           623: 
        !           624: /*
        !           625:  * receive a token or buffer from the other end. If the reurn value is >0 then
        !           626:  * it is a data buffer of that length, and *data will point at the data.
        !           627:  * if the return value is -i then it represents token i-1
        !           628:  * if the return value is 0 then the end has been reached
        !           629:  */
        !           630: int32 recv_token(int f, char **data)
        !           631: {
        !           632:        int tok;
        !           633: 
        !           634:        if (!do_compression) {
        !           635:                tok = simple_recv_token(f,data);
        !           636:        } else {
        !           637:                tok = recv_deflated_token(f, data);
        !           638:        }
        !           639:        return tok;
        !           640: }
        !           641: 
        !           642: /*
        !           643:  * look at the data corresponding to a token, if necessary
        !           644:  */
        !           645: void see_token(char *data, int32 toklen)
        !           646: {
        !           647:        if (do_compression)
        !           648:                see_deflate_token(data, toklen);
        !           649: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>