File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / token.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 14 07:51:14 2013 UTC (10 years, 9 months ago) by misho
Branches: rsync, MAIN
CVS tags: RSYNC3_1_0, HEAD
v 3.1.0

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

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