blob: 61be8dd950136a04988313e8b32ff765b75ac6b6 [file] [log] [blame]
Wayne Davisond67c8bd2004-06-18 16:22:14 +00001/*
Wayne Davison0f78b812006-04-25 20:23:34 +00002 * Routines used by the file-transfer code.
3 *
4 * Copyright (C) 1996 Andrew Tridgell
5 * Copyright (C) 1996 Paul Mackerras
Wayne Davison3ba4db72020-04-16 09:29:22 -07006 * Copyright (C) 2003-2020 Wayne Davison
Wayne Davison0f78b812006-04-25 20:23:34 +00007 *
8 * This program is free software; you can redistribute it and/or modify
Wayne Davison8e41b682007-07-10 13:55:49 +00009 * 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.
Wayne Davison0f78b812006-04-25 20:23:34 +000012 *
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 *
Wayne Davisone7c67062006-04-25 23:51:12 +000018 * You should have received a copy of the GNU General Public License along
Wayne Davison4fd842f2007-07-07 05:33:14 +000019 * with this program; if not, visit the http://fsf.org website.
Wayne Davison0f78b812006-04-25 20:23:34 +000020 */
Andrew Tridgell70d794d1996-07-01 05:55:05 +000021
22#include "rsync.h"
Wayne Davison5dd14f02008-09-01 19:09:21 -070023#include "itypes.h"
Wayne Davison7da17142011-11-21 09:22:14 -080024#include <zlib.h>
Wayne Davison4aaadc22020-05-25 13:31:30 -070025#ifdef SUPPORT_ZSTD
26#include <zstd.h>
27#endif
Wayne Davisonc394e862020-05-25 13:43:25 -070028#ifdef SUPPORT_LZ4
29#include <lz4.h>
30#endif
Wayne Davison7da17142011-11-21 09:22:14 -080031
Andrew Tridgell70d794d1996-07-01 05:55:05 +000032extern int do_compression;
Wayne Davisoncbdff742011-11-21 09:13:11 -080033extern int protocol_version;
Wayne Davisond67c8bd2004-06-18 16:22:14 +000034extern int module_id;
Wayne Davisond999efe2020-05-25 10:47:57 -070035extern int do_compression_level;
Wayne Davison6e058b42007-07-14 19:24:35 +000036extern char *skip_compress;
Wayne Davisond67c8bd2004-06-18 16:22:14 +000037
Wayne Davison64d5ea32020-05-24 15:45:59 -070038#ifndef Z_INSERT_ONLY
39#define Z_INSERT_ONLY Z_SYNC_FLUSH
40#endif
41
Wayne Davison4c9fdb92020-06-02 17:58:24 -070042static int compression_level; /* The compression level for the current file. */
43static int skip_compression_level; /* The least possible compressing for handling skip-compress files. */
44static int per_file_default_level; /* The default level that each new file gets prior to checking its suffix. */
Andrew Tridgell70d794d1996-07-01 05:55:05 +000045
Wayne Davison6e058b42007-07-14 19:24:35 +000046struct suffix_tree {
47 struct suffix_tree *sibling;
48 struct suffix_tree *child;
49 char letter, word_end;
50};
51
52static char *match_list;
53static struct suffix_tree *suftree;
54
Wayne Davisond999efe2020-05-25 10:47:57 -070055void init_compression_level(void)
56{
57 int min_level, max_level, def_level, off_level;
58
59 switch (do_compression) {
Wayne Davison778f0df2020-06-04 16:17:12 -070060 case CPRES_NONE:
Wayne Davison7dbbde82020-06-07 18:58:30 -070061 return;
Wayne Davisond999efe2020-05-25 10:47:57 -070062 case CPRES_ZLIB:
63 case CPRES_ZLIBX:
64 min_level = 1;
65 max_level = Z_BEST_COMPRESSION;
66 def_level = 6; /* Z_DEFAULT_COMPRESSION is -1, so set it to the real default */
Wayne Davison4c9fdb92020-06-02 17:58:24 -070067 off_level = skip_compression_level = Z_NO_COMPRESSION;
Wayne Davisond999efe2020-05-25 10:47:57 -070068 if (do_compression_level == Z_DEFAULT_COMPRESSION)
69 do_compression_level = def_level;
70 break;
Wayne Davison4aaadc22020-05-25 13:31:30 -070071#ifdef SUPPORT_ZSTD
72 case CPRES_ZSTD:
Wayne Davison4c9fdb92020-06-02 17:58:24 -070073 min_level = skip_compression_level = ZSTD_minCLevel();
Wayne Davison4aaadc22020-05-25 13:31:30 -070074 max_level = ZSTD_maxCLevel();
Wayne Davison7dbbde82020-06-07 18:58:30 -070075 def_level = ZSTD_CLEVEL_DEFAULT;
Wayne Davison4aaadc22020-05-25 13:31:30 -070076 off_level = CLVL_NOT_SPECIFIED;
Wayne Davison7dbbde82020-06-07 18:58:30 -070077 if (do_compression_level == 0)
78 do_compression_level = def_level;
Wayne Davison4aaadc22020-05-25 13:31:30 -070079 break;
80#endif
Wayne Davisonc394e862020-05-25 13:43:25 -070081#ifdef SUPPORT_LZ4
82 case CPRES_LZ4:
Wayne Davison4c9fdb92020-06-02 17:58:24 -070083 min_level = skip_compression_level = 0;
Wayne Davisonc394e862020-05-25 13:43:25 -070084 max_level = 0;
85 def_level = 0;
86 off_level = CLVL_NOT_SPECIFIED;
87 break;
88#endif
Wayne Davisond999efe2020-05-25 10:47:57 -070089 default: /* paranoia to prevent missing case values */
Wayne Davisonab110fc2020-07-08 12:19:16 -070090 NOISY_DEATH("Unknown do_compression value");
Wayne Davisond999efe2020-05-25 10:47:57 -070091 }
92
Wayne Davisonabef92c2020-05-25 13:02:56 -070093 if (do_compression_level == CLVL_NOT_SPECIFIED)
94 do_compression_level = def_level;
95 else if (do_compression_level == off_level) {
Wayne Davisond999efe2020-05-25 10:47:57 -070096 do_compression = CPRES_NONE;
97 return;
98 }
99
100 /* We don't bother with any errors or warnings -- just make sure that the values are valid. */
Wayne Davisonabef92c2020-05-25 13:02:56 -0700101 if (do_compression_level < min_level)
Wayne Davisond999efe2020-05-25 10:47:57 -0700102 do_compression_level = min_level;
103 else if (do_compression_level > max_level)
104 do_compression_level = max_level;
105}
106
Wayne Davison6e058b42007-07-14 19:24:35 +0000107static void add_suffix(struct suffix_tree **prior, char ltr, const char *str)
Andrew Tridgell83fff1a1998-11-20 22:26:29 +0000108{
Wayne Davison6e058b42007-07-14 19:24:35 +0000109 struct suffix_tree *node, *newnode;
110
111 if (ltr == '[') {
112 const char *after = strchr(str, ']');
Wayne Davison2f1fb732009-09-05 10:25:42 -0700113 /* Treat "[foo" and "[]" as having a literal '['. */
114 if (after && after++ != str+1) {
115 while ((ltr = *str++) != ']')
116 add_suffix(prior, ltr, after);
Wayne Davison6e058b42007-07-14 19:24:35 +0000117 return;
Wayne Davison2f1fb732009-09-05 10:25:42 -0700118 }
Wayne Davison6e058b42007-07-14 19:24:35 +0000119 }
120
121 for (node = *prior; node; prior = &node->sibling, node = node->sibling) {
122 if (node->letter == ltr) {
123 if (*str)
124 add_suffix(&node->child, *str, str+1);
125 else
126 node->word_end = 1;
127 return;
128 }
129 if (node->letter > ltr)
130 break;
131 }
Wayne Davison11eb67e2020-06-25 19:59:19 -0700132 newnode = new(struct suffix_tree);
Wayne Davison6e058b42007-07-14 19:24:35 +0000133 newnode->sibling = node;
134 newnode->child = NULL;
135 newnode->letter = ltr;
136 *prior = newnode;
137 if (*str) {
138 add_suffix(&newnode->child, *str, str+1);
139 newnode->word_end = 0;
140 } else
141 newnode->word_end = 1;
142}
143
144static void add_nocompress_suffixes(const char *str)
145{
146 char *buf, *t;
147 const char *f = str;
148
Wayne Davison11eb67e2020-06-25 19:59:19 -0700149 buf = new_array(char, strlen(f) + 1);
Wayne Davison6e058b42007-07-14 19:24:35 +0000150
151 while (*f) {
152 if (*f == '/') {
153 f++;
154 continue;
155 }
156
157 t = buf;
158 do {
159 if (isUpper(f))
160 *t++ = toLower(f);
161 else
162 *t++ = *f;
163 } while (*++f != '/' && *f);
164 *t++ = '\0';
165
Wayne Davison6e058b42007-07-14 19:24:35 +0000166 add_suffix(&suftree, *buf, buf+1);
167 }
168
169 free(buf);
170}
171
172static void init_set_compression(void)
173{
174 const char *f;
175 char *t, *start;
176
177 if (skip_compress)
178 add_nocompress_suffixes(skip_compress);
179
180 /* A non-daemon transfer skips the default suffix list if the
181 * user specified --skip-compress. */
182 if (skip_compress && module_id < 0)
183 f = "";
184 else
185 f = lp_dont_compress(module_id);
186
Wayne Davison11eb67e2020-06-25 19:59:19 -0700187 match_list = t = new_array(char, strlen(f) + 2);
Wayne Davison6e058b42007-07-14 19:24:35 +0000188
Wayne Davisond999efe2020-05-25 10:47:57 -0700189 per_file_default_level = do_compression_level;
Wayne Davison6e058b42007-07-14 19:24:35 +0000190
191 while (*f) {
192 if (*f == ' ') {
193 f++;
194 continue;
195 }
196
197 start = t;
198 do {
199 if (isUpper(f))
200 *t++ = toLower(f);
201 else
202 *t++ = *f;
203 } while (*++f != ' ' && *f);
204 *t++ = '\0';
205
206 if (t - start == 1+1 && *start == '*') {
207 /* Optimize a match-string of "*". */
208 *match_list = '\0';
209 suftree = NULL;
Wayne Davison4c9fdb92020-06-02 17:58:24 -0700210 per_file_default_level = skip_compression_level;
Wayne Davison6e058b42007-07-14 19:24:35 +0000211 break;
212 }
213
214 /* Move *.foo items into the stuffix tree. */
215 if (*start == '*' && start[1] == '.' && start[2]
Wayne Davison0d585182007-07-14 19:36:52 +0000216 && !strpbrk(start+2, ".?*")) {
Wayne Davison6e058b42007-07-14 19:24:35 +0000217 add_suffix(&suftree, start[2], start+3);
218 t = start;
219 }
220 }
221 *t++ = '\0';
222}
223
224/* determine the compression level based on a wildcard filename list */
225void set_compression(const char *fname)
226{
227 const struct suffix_tree *node;
228 const char *s;
229 char ltr;
Andrew Tridgell83fff1a1998-11-20 22:26:29 +0000230
Wayne Davisond67c8bd2004-06-18 16:22:14 +0000231 if (!do_compression)
232 return;
Andrew Tridgell83fff1a1998-11-20 22:26:29 +0000233
Wayne Davison6e058b42007-07-14 19:24:35 +0000234 if (!match_list)
235 init_set_compression();
David Dykstra63f07741998-11-25 15:37:50 +0000236
Wayne Davisonec497df2005-12-30 07:19:16 +0000237 compression_level = per_file_default_level;
Wayne Davison0fe987e2005-12-30 06:03:40 +0000238
Wayne Davison6e058b42007-07-14 19:24:35 +0000239 if (!*match_list && !suftree)
Wayne Davisond67c8bd2004-06-18 16:22:14 +0000240 return;
Andrew Tridgell83fff1a1998-11-20 22:26:29 +0000241
Wayne Davisonec497df2005-12-30 07:19:16 +0000242 if ((s = strrchr(fname, '/')) != NULL)
243 fname = s + 1;
Andrew Tridgell83fff1a1998-11-20 22:26:29 +0000244
Wayne Davisonec497df2005-12-30 07:19:16 +0000245 for (s = match_list; *s; s += strlen(s) + 1) {
246 if (iwildmatch(s, fname)) {
Wayne Davison4c9fdb92020-06-02 17:58:24 -0700247 compression_level = skip_compression_level;
Wayne Davison6e058b42007-07-14 19:24:35 +0000248 return;
Andrew Tridgell83fff1a1998-11-20 22:26:29 +0000249 }
250 }
Wayne Davison6e058b42007-07-14 19:24:35 +0000251
252 if (!(node = suftree) || !(s = strrchr(fname, '.'))
253 || s == fname || !(ltr = *++s))
254 return;
255
256 while (1) {
Wayne Davison3be1d9b2010-06-19 09:47:00 -0700257 if (isUpper(&ltr))
258 ltr = toLower(&ltr);
Wayne Davison6e058b42007-07-14 19:24:35 +0000259 while (node->letter != ltr) {
260 if (node->letter > ltr)
261 return;
262 if (!(node = node->sibling))
263 return;
264 }
265 if ((ltr = *++s) == '\0') {
266 if (node->word_end)
Wayne Davison4c9fdb92020-06-02 17:58:24 -0700267 compression_level = skip_compression_level;
Wayne Davison6e058b42007-07-14 19:24:35 +0000268 return;
269 }
270 if (!(node = node->child))
271 return;
272 }
Andrew Tridgell83fff1a1998-11-20 22:26:29 +0000273}
Andrew Tridgell70d794d1996-07-01 05:55:05 +0000274
275/* non-compressing recv token */
Wayne Davison7fcbf9e2005-01-01 21:08:20 +0000276static int32 simple_recv_token(int f, char **data)
Andrew Tridgell70d794d1996-07-01 05:55:05 +0000277{
Wayne Davisonacc461c2005-02-14 08:19:32 +0000278 static int32 residue;
Andrew Tridgellc5eb3651998-05-21 05:57:15 +0000279 static char *buf;
Wayne Davison7fcbf9e2005-01-01 21:08:20 +0000280 int32 n;
Andrew Tridgell70d794d1996-07-01 05:55:05 +0000281
Wayne Davison11eb67e2020-06-25 19:59:19 -0700282 if (!buf)
Wayne Davison58cadc82003-12-06 21:07:27 +0000283 buf = new_array(char, CHUNK_SIZE);
Andrew Tridgell70d794d1996-07-01 05:55:05 +0000284
Andrew Tridgellc5eb3651998-05-21 05:57:15 +0000285 if (residue == 0) {
Wayne Davison7fcbf9e2005-01-01 21:08:20 +0000286 int32 i = read_int(f);
Wayne Davisond67c8bd2004-06-18 16:22:14 +0000287 if (i <= 0)
288 return i;
Andrew Tridgellc5eb3651998-05-21 05:57:15 +0000289 residue = i;
290 }
Andrew Tridgell70d794d1996-07-01 05:55:05 +0000291
Andrew Tridgellc5eb3651998-05-21 05:57:15 +0000292 *data = buf;
293 n = MIN(CHUNK_SIZE,residue);
294 residue -= n;
295 read_buf(f,buf,n);
296 return n;
Andrew Tridgell70d794d1996-07-01 05:55:05 +0000297}
298
Andrew Tridgell70d794d1996-07-01 05:55:05 +0000299/* non-compressing send token */
Wayne Davisone63ff702020-06-13 18:19:12 -0700300static void simple_send_token(int f, int32 token, struct map_struct *buf, OFF_T offset, int32 n)
Andrew Tridgell70d794d1996-07-01 05:55:05 +0000301{
Andrew Tridgellc5eb3651998-05-21 05:57:15 +0000302 if (n > 0) {
Wayne Davison7fcbf9e2005-01-01 21:08:20 +0000303 int32 len = 0;
304 while (len < n) {
305 int32 n1 = MIN(CHUNK_SIZE, n-len);
306 write_int(f, n1);
307 write_buf(f, map_ptr(buf, offset+len, n1), n1);
308 len += n1;
Andrew Tridgellc5eb3651998-05-21 05:57:15 +0000309 }
310 }
Andrew Tridgell45f133b1998-05-22 01:53:02 +0000311 /* a -2 token means to send data only and no token */
Wayne Davison7fcbf9e2005-01-01 21:08:20 +0000312 if (token != -2)
313 write_int(f, -(token+1));
Andrew Tridgell70d794d1996-07-01 05:55:05 +0000314}
315
Paul Mackerras861c20b1996-07-03 04:05:46 +0000316/* Flag bytes in compressed stream are encoded as follows: */
317#define END_FLAG 0 /* that's all folks */
318#define TOKEN_LONG 0x20 /* followed by 32-bit token number */
319#define TOKENRUN_LONG 0x21 /* ditto with 16-bit run count */
320#define DEFLATED_DATA 0x40 /* + 6-bit high len, then low len byte */
321#define TOKEN_REL 0x80 /* + 6-bit relative token number */
322#define TOKENRUN_REL 0xc0 /* ditto with 16-bit run count */
323
324#define MAX_DATA_COUNT 16383 /* fit 14 bit count into 2 bytes with flags */
325
Wayne Davison24733912003-07-04 07:47:09 +0000326/* zlib.h says that if we want to be able to compress something in a single
327 * call, avail_out must be at least 0.1% larger than avail_in plus 12 bytes.
328 * We'll add in 0.1%+16, just to be safe (and we'll avoid floating point,
329 * to ensure that this is a compile-time value). */
330#define AVAIL_OUT_SIZE(avail_in_size) ((avail_in_size)*1001/1000+16)
331
Paul Mackerras861c20b1996-07-03 04:05:46 +0000332/* For coding runs of tokens */
Wayne Davisonacc461c2005-02-14 08:19:32 +0000333static int32 last_token = -1;
334static int32 run_start;
335static int32 last_run_end;
Paul Mackerras861c20b1996-07-03 04:05:46 +0000336
337/* Deflation state */
338static z_stream tx_strm;
339
340/* Output buffer */
Andrew Tridgell3a6a3661998-03-23 12:52:57 +0000341static char *obuf;
Wayne Davison24733912003-07-04 07:47:09 +0000342
343/* We want obuf to be able to hold both MAX_DATA_COUNT+2 bytes as well as
344 * AVAIL_OUT_SIZE(CHUNK_SIZE) bytes, so make sure that it's large enough. */
345#if MAX_DATA_COUNT+2 > AVAIL_OUT_SIZE(CHUNK_SIZE)
346#define OBUF_SIZE (MAX_DATA_COUNT+2)
347#else
348#define OBUF_SIZE AVAIL_OUT_SIZE(CHUNK_SIZE)
349#endif
Paul Mackerras861c20b1996-07-03 04:05:46 +0000350
351/* Send a deflated token */
352static void
Wayne Davisone63ff702020-06-13 18:19:12 -0700353send_deflated_token(int f, int32 token, struct map_struct *buf, OFF_T offset, int32 nb, int32 toklen)
Paul Mackerras861c20b1996-07-03 04:05:46 +0000354{
Paul Mackerras5914bf11998-05-22 06:58:52 +0000355 static int init_done, flush_pending;
Wayne Davison4496e0e2020-05-24 18:08:09 -0700356 int32 n, r;
Paul Mackerras861c20b1996-07-03 04:05:46 +0000357
Paul Mackerras5914bf11998-05-22 06:58:52 +0000358 if (last_token == -1) {
359 /* initialization */
360 if (!init_done) {
361 tx_strm.next_in = NULL;
362 tx_strm.zalloc = NULL;
363 tx_strm.zfree = NULL;
Andrew Tridgell83fff1a1998-11-20 22:26:29 +0000364 if (deflateInit2(&tx_strm, compression_level,
Paul Mackerras5914bf11998-05-22 06:58:52 +0000365 Z_DEFLATED, -15, 8,
366 Z_DEFAULT_STRATEGY) != Z_OK) {
367 rprintf(FERROR, "compression init failed\n");
Wayne Davisone4c598c2009-11-16 12:35:17 -0800368 exit_cleanup(RERR_PROTOCOL);
Paul Mackerras5914bf11998-05-22 06:58:52 +0000369 }
Wayne Davison11eb67e2020-06-25 19:59:19 -0700370 obuf = new_array(char, OBUF_SIZE);
Paul Mackerras5914bf11998-05-22 06:58:52 +0000371 init_done = 1;
372 } else
373 deflateReset(&tx_strm);
374 last_run_end = 0;
375 run_start = token;
376 flush_pending = 0;
Paul Mackerras5914bf11998-05-22 06:58:52 +0000377 } else if (last_token == -2) {
378 run_start = token;
Wayne Davison85e62c32020-07-04 15:27:47 -0700379 } else if (nb != 0 || token != last_token + 1 || token >= run_start + 65536) {
Paul Mackerras5914bf11998-05-22 06:58:52 +0000380 /* output previous run */
381 r = run_start - last_run_end;
382 n = last_token - run_start;
383 if (r >= 0 && r <= 63) {
384 write_byte(f, (n==0? TOKEN_REL: TOKENRUN_REL) + r);
385 } else {
386 write_byte(f, (n==0? TOKEN_LONG: TOKENRUN_LONG));
387 write_int(f, run_start);
Paul Mackerras861c20b1996-07-03 04:05:46 +0000388 }
Paul Mackerras5914bf11998-05-22 06:58:52 +0000389 if (n != 0) {
390 write_byte(f, n);
391 write_byte(f, n >> 8);
392 }
393 last_run_end = last_token;
394 run_start = token;
Paul Mackerras861c20b1996-07-03 04:05:46 +0000395 }
396
Paul Mackerras5914bf11998-05-22 06:58:52 +0000397 last_token = token;
398
399 if (nb != 0 || flush_pending) {
400 /* deflate the data starting at offset */
401 int flush = Z_NO_FLUSH;
402 tx_strm.avail_in = 0;
403 tx_strm.avail_out = 0;
404 do {
405 if (tx_strm.avail_in == 0 && nb != 0) {
406 /* give it some more input */
407 n = MIN(nb, CHUNK_SIZE);
408 tx_strm.next_in = (Bytef *)
409 map_ptr(buf, offset, n);
410 tx_strm.avail_in = n;
411 nb -= n;
412 offset += n;
413 }
414 if (tx_strm.avail_out == 0) {
415 tx_strm.next_out = (Bytef *)(obuf + 2);
416 tx_strm.avail_out = MAX_DATA_COUNT;
417 if (flush != Z_NO_FLUSH) {
418 /*
419 * We left the last 4 bytes in the
420 * buffer, in case they are the
421 * last 4. Move them to the front.
422 */
Wayne Davisone63ff702020-06-13 18:19:12 -0700423 memcpy(tx_strm.next_out, obuf+MAX_DATA_COUNT-2, 4);
Paul Mackerras5914bf11998-05-22 06:58:52 +0000424 tx_strm.next_out += 4;
425 tx_strm.avail_out -= 4;
426 }
427 }
428 if (nb == 0 && token != -2)
429 flush = Z_SYNC_FLUSH;
430 r = deflate(&tx_strm, flush);
431 if (r != Z_OK) {
432 rprintf(FERROR, "deflate returned %d\n", r);
Andrew Tridgell65417571998-11-03 07:08:27 +0000433 exit_cleanup(RERR_STREAMIO);
Paul Mackerras5914bf11998-05-22 06:58:52 +0000434 }
435 if (nb == 0 || tx_strm.avail_out == 0) {
436 n = MAX_DATA_COUNT - tx_strm.avail_out;
437 if (flush != Z_NO_FLUSH) {
438 /*
439 * We have to trim off the last 4
440 * bytes of output when flushing
441 * (they are just 0, 0, ff, ff).
442 */
443 n -= 4;
444 }
445 if (n > 0) {
446 obuf[0] = DEFLATED_DATA + (n >> 8);
447 obuf[1] = n;
448 write_buf(f, obuf, n+2);
449 }
450 }
451 } while (nb != 0 || tx_strm.avail_out == 0);
452 flush_pending = token == -2;
453 }
454
455 if (token == -1) {
456 /* end of file - clean up */
457 write_byte(f, END_FLAG);
Wayne Davison4496e0e2020-05-24 18:08:09 -0700458 } else if (token != -2 && do_compression == CPRES_ZLIB) {
Wayne Davisonacc461c2005-02-14 08:19:32 +0000459 /* Add the data in the current block to the compressor's
460 * history and hash table. */
Wayne Davison01f439e2005-02-14 08:28:00 +0000461 do {
462 /* Break up long sections in the same way that
463 * see_deflate_token() does. */
464 int32 n1 = toklen > 0xffff ? 0xffff : toklen;
465 toklen -= n1;
466 tx_strm.next_in = (Bytef *)map_ptr(buf, offset, n1);
467 tx_strm.avail_in = n1;
Wayne Davisoncbdff742011-11-21 09:13:11 -0800468 if (protocol_version >= 31) /* Newer protocols avoid a data-duplicating bug */
469 offset += n1;
Wayne Davison22a3ac02014-04-19 12:11:11 -0700470 tx_strm.next_out = (Bytef *) obuf;
471 tx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
472 r = deflate(&tx_strm, Z_INSERT_ONLY);
473 if (r != Z_OK || tx_strm.avail_in != 0) {
474 rprintf(FERROR, "deflate on token returned %d (%d bytes left)\n",
475 r, tx_strm.avail_in);
476 exit_cleanup(RERR_STREAMIO);
477 }
Wayne Davison01f439e2005-02-14 08:28:00 +0000478 } while (toklen > 0);
Paul Mackerras5914bf11998-05-22 06:58:52 +0000479 }
Paul Mackerras861c20b1996-07-03 04:05:46 +0000480}
481
Paul Mackerras861c20b1996-07-03 04:05:46 +0000482/* tells us what the receiver is in the middle of doing */
483static enum { r_init, r_idle, r_running, r_inflating, r_inflated } recv_state;
484
485/* for inflating stuff */
486static z_stream rx_strm;
487static char *cbuf;
488static char *dbuf;
489
490/* for decoding runs of tokens */
Wayne Davison7fcbf9e2005-01-01 21:08:20 +0000491static int32 rx_token;
492static int32 rx_run;
Paul Mackerras861c20b1996-07-03 04:05:46 +0000493
494/* Receive a deflated token and inflate it */
Wayne Davison7fcbf9e2005-01-01 21:08:20 +0000495static int32 recv_deflated_token(int f, char **data)
Paul Mackerras861c20b1996-07-03 04:05:46 +0000496{
Paul Mackerras5914bf11998-05-22 06:58:52 +0000497 static int init_done;
Wayne Davisonacc461c2005-02-14 08:19:32 +0000498 static int32 saved_flag;
499 int32 n, flag;
500 int r;
Paul Mackerras861c20b1996-07-03 04:05:46 +0000501
Paul Mackerras5914bf11998-05-22 06:58:52 +0000502 for (;;) {
503 switch (recv_state) {
504 case r_init:
505 if (!init_done) {
506 rx_strm.next_out = NULL;
507 rx_strm.zalloc = NULL;
508 rx_strm.zfree = NULL;
509 if (inflateInit2(&rx_strm, -15) != Z_OK) {
510 rprintf(FERROR, "inflate init failed\n");
Wayne Davisone4c598c2009-11-16 12:35:17 -0800511 exit_cleanup(RERR_PROTOCOL);
Paul Mackerras5914bf11998-05-22 06:58:52 +0000512 }
Wayne Davison11eb67e2020-06-25 19:59:19 -0700513 cbuf = new_array(char, MAX_DATA_COUNT);
514 dbuf = new_array(char, AVAIL_OUT_SIZE(CHUNK_SIZE));
Paul Mackerras5914bf11998-05-22 06:58:52 +0000515 init_done = 1;
516 } else {
517 inflateReset(&rx_strm);
518 }
Paul Mackerrasb8d45241996-11-06 04:49:53 +0000519 recv_state = r_idle;
Paul Mackerras5914bf11998-05-22 06:58:52 +0000520 rx_token = 0;
521 break;
522
523 case r_idle:
524 case r_inflated:
525 if (saved_flag) {
526 flag = saved_flag & 0xff;
527 saved_flag = 0;
528 } else
529 flag = read_byte(f);
530 if ((flag & 0xC0) == DEFLATED_DATA) {
531 n = ((flag & 0x3f) << 8) + read_byte(f);
532 read_buf(f, cbuf, n);
533 rx_strm.next_in = (Bytef *)cbuf;
534 rx_strm.avail_in = n;
535 recv_state = r_inflating;
536 break;
537 }
538 if (recv_state == r_inflated) {
539 /* check previous inflated stuff ended correctly */
540 rx_strm.avail_in = 0;
541 rx_strm.next_out = (Bytef *)dbuf;
Wayne Davison1dbb94c2003-08-20 10:37:53 +0000542 rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
Paul Mackerras5914bf11998-05-22 06:58:52 +0000543 r = inflate(&rx_strm, Z_SYNC_FLUSH);
Wayne Davison1dbb94c2003-08-20 10:37:53 +0000544 n = AVAIL_OUT_SIZE(CHUNK_SIZE) - rx_strm.avail_out;
Paul Mackerras5914bf11998-05-22 06:58:52 +0000545 /*
546 * Z_BUF_ERROR just means no progress was
547 * made, i.e. the decompressor didn't have
548 * any pending output for us.
549 */
550 if (r != Z_OK && r != Z_BUF_ERROR) {
551 rprintf(FERROR, "inflate flush returned %d (%d bytes)\n",
552 r, n);
Andrew Tridgell65417571998-11-03 07:08:27 +0000553 exit_cleanup(RERR_STREAMIO);
Paul Mackerras5914bf11998-05-22 06:58:52 +0000554 }
555 if (n != 0 && r != Z_BUF_ERROR) {
556 /* have to return some more data and
557 save the flag for later. */
558 saved_flag = flag + 0x10000;
559 *data = dbuf;
560 return n;
561 }
562 /*
563 * At this point the decompressor should
564 * be expecting to see the 0, 0, ff, ff bytes.
565 */
566 if (!inflateSyncPoint(&rx_strm)) {
567 rprintf(FERROR, "decompressor lost sync!\n");
Andrew Tridgell65417571998-11-03 07:08:27 +0000568 exit_cleanup(RERR_STREAMIO);
Paul Mackerras5914bf11998-05-22 06:58:52 +0000569 }
570 rx_strm.avail_in = 4;
571 rx_strm.next_in = (Bytef *)cbuf;
572 cbuf[0] = cbuf[1] = 0;
573 cbuf[2] = cbuf[3] = 0xff;
574 inflate(&rx_strm, Z_SYNC_FLUSH);
575 recv_state = r_idle;
576 }
577 if (flag == END_FLAG) {
578 /* that's all folks */
579 recv_state = r_init;
580 return 0;
581 }
582
583 /* here we have a token of some kind */
584 if (flag & TOKEN_REL) {
585 rx_token += flag & 0x3f;
586 flag >>= 6;
587 } else
588 rx_token = read_int(f);
589 if (flag & 1) {
590 rx_run = read_byte(f);
591 rx_run += read_byte(f) << 8;
592 recv_state = r_running;
593 }
594 return -1 - rx_token;
595
596 case r_inflating:
597 rx_strm.next_out = (Bytef *)dbuf;
Wayne Davison1dbb94c2003-08-20 10:37:53 +0000598 rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
Paul Mackerras5914bf11998-05-22 06:58:52 +0000599 r = inflate(&rx_strm, Z_NO_FLUSH);
Wayne Davison1dbb94c2003-08-20 10:37:53 +0000600 n = AVAIL_OUT_SIZE(CHUNK_SIZE) - rx_strm.avail_out;
Paul Mackerras5914bf11998-05-22 06:58:52 +0000601 if (r != Z_OK) {
602 rprintf(FERROR, "inflate returned %d (%d bytes)\n", r, n);
Andrew Tridgell65417571998-11-03 07:08:27 +0000603 exit_cleanup(RERR_STREAMIO);
Paul Mackerras5914bf11998-05-22 06:58:52 +0000604 }
605 if (rx_strm.avail_in == 0)
606 recv_state = r_inflated;
607 if (n != 0) {
608 *data = dbuf;
609 return n;
610 }
611 break;
612
613 case r_running:
614 ++rx_token;
615 if (--rx_run == 0)
616 recv_state = r_idle;
617 return -1 - rx_token;
Paul Mackerrasb8d45241996-11-06 04:49:53 +0000618 }
Paul Mackerras861c20b1996-07-03 04:05:46 +0000619 }
Paul Mackerras861c20b1996-07-03 04:05:46 +0000620}
621
622/*
623 * put the data corresponding to a token that we've just returned
624 * from recv_deflated_token into the decompressor's history buffer.
625 */
Wayne Davison7fcbf9e2005-01-01 21:08:20 +0000626static void see_deflate_token(char *buf, int32 len)
Paul Mackerras861c20b1996-07-03 04:05:46 +0000627{
Wayne Davisonacc461c2005-02-14 08:19:32 +0000628 int r;
629 int32 blklen;
Paul Mackerras5914bf11998-05-22 06:58:52 +0000630 unsigned char hdr[5];
Paul Mackerras861c20b1996-07-03 04:05:46 +0000631
Paul Mackerras5914bf11998-05-22 06:58:52 +0000632 rx_strm.avail_in = 0;
633 blklen = 0;
634 hdr[0] = 0;
635 do {
636 if (rx_strm.avail_in == 0 && len != 0) {
637 if (blklen == 0) {
638 /* Give it a fake stored-block header. */
639 rx_strm.next_in = (Bytef *)hdr;
640 rx_strm.avail_in = 5;
641 blklen = len;
642 if (blklen > 0xffff)
643 blklen = 0xffff;
644 hdr[1] = blklen;
645 hdr[2] = blklen >> 8;
646 hdr[3] = ~hdr[1];
647 hdr[4] = ~hdr[2];
648 } else {
649 rx_strm.next_in = (Bytef *)buf;
650 rx_strm.avail_in = blklen;
Wayne Davisoncbdff742011-11-21 09:13:11 -0800651 if (protocol_version >= 31) /* Newer protocols avoid a data-duplicating bug */
652 buf += blklen;
Paul Mackerras5914bf11998-05-22 06:58:52 +0000653 len -= blklen;
654 blklen = 0;
655 }
656 }
657 rx_strm.next_out = (Bytef *)dbuf;
Wayne Davison1dbb94c2003-08-20 10:37:53 +0000658 rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
Paul Mackerras5914bf11998-05-22 06:58:52 +0000659 r = inflate(&rx_strm, Z_SYNC_FLUSH);
Wayne Davison4286ea62009-12-21 10:13:52 -0800660 if (r != Z_OK && r != Z_BUF_ERROR) {
Paul Mackerras5914bf11998-05-22 06:58:52 +0000661 rprintf(FERROR, "inflate (token) returned %d\n", r);
Andrew Tridgell65417571998-11-03 07:08:27 +0000662 exit_cleanup(RERR_STREAMIO);
Paul Mackerras5914bf11998-05-22 06:58:52 +0000663 }
664 } while (len || rx_strm.avail_out == 0);
Paul Mackerras861c20b1996-07-03 04:05:46 +0000665}
Andrew Tridgell70d794d1996-07-01 05:55:05 +0000666
Wayne Davison4aaadc22020-05-25 13:31:30 -0700667#ifdef SUPPORT_ZSTD
668
669static ZSTD_inBuffer zstd_in_buff;
670static ZSTD_outBuffer zstd_out_buff;
671static ZSTD_CCtx *zstd_cctx;
672
Wayne Davisone63ff702020-06-13 18:19:12 -0700673static void send_zstd_token(int f, int32 token, struct map_struct *buf, OFF_T offset, int32 nb)
Wayne Davison4aaadc22020-05-25 13:31:30 -0700674{
675 static int comp_init_done, flush_pending;
676 ZSTD_EndDirective flush = ZSTD_e_continue;
677 int32 n, r;
678
679 /* initialization */
680 if (!comp_init_done) {
Wayne Davison4aaadc22020-05-25 13:31:30 -0700681 zstd_cctx = ZSTD_createCCtx();
682 if (!zstd_cctx) {
683 rprintf(FERROR, "compression init failed\n");
684 exit_cleanup(RERR_PROTOCOL);
685 }
686
Wayne Davisonc7f10de2020-05-28 11:40:52 -0700687 obuf = new_array(char, OBUF_SIZE);
Wayne Davison4aaadc22020-05-25 13:31:30 -0700688
Wayne Davisone63ff702020-06-13 18:19:12 -0700689 ZSTD_CCtx_setParameter(zstd_cctx, ZSTD_c_compressionLevel, do_compression_level);
Wayne Davison4aaadc22020-05-25 13:31:30 -0700690 zstd_out_buff.dst = obuf + 2;
691
692 comp_init_done = 1;
693 }
694
695 if (last_token == -1) {
696 last_run_end = 0;
697 run_start = token;
698 flush_pending = 0;
699 } else if (last_token == -2) {
700 run_start = token;
Wayne Davison85e62c32020-07-04 15:27:47 -0700701 } else if (nb != 0 || token != last_token + 1 || token >= run_start + 65536) {
Wayne Davison4aaadc22020-05-25 13:31:30 -0700702 /* output previous run */
703 r = run_start - last_run_end;
704 n = last_token - run_start;
705
706 if (r >= 0 && r <= 63) {
707 write_byte(f, (n==0? TOKEN_REL: TOKENRUN_REL) + r);
708 } else {
709 write_byte(f, (n==0? TOKEN_LONG: TOKENRUN_LONG));
710 write_int(f, run_start);
711 }
712 if (n != 0) {
713 write_byte(f, n);
714 write_byte(f, n >> 8);
715 }
716 last_run_end = last_token;
717 run_start = token;
718 }
719
720 last_token = token;
721
722 if (nb || flush_pending) {
723
724 zstd_in_buff.src = map_ptr(buf, offset, nb);
725 zstd_in_buff.size = nb;
726 zstd_in_buff.pos = 0;
727
728 do {
729 if (zstd_out_buff.size == 0) {
730 zstd_out_buff.size = MAX_DATA_COUNT;
731 zstd_out_buff.pos = 0;
732 }
733
734 /* File ended, flush */
735 if (token != -2)
736 flush = ZSTD_e_flush;
737
738 r = ZSTD_compressStream2(zstd_cctx, &zstd_out_buff, &zstd_in_buff, flush);
739 if (ZSTD_isError(r)) {
740 rprintf(FERROR, "ZSTD_compressStream returned %d\n", r);
741 exit_cleanup(RERR_STREAMIO);
742 }
743
744 /*
745 * Nothing is sent if the buffer isn't full so avoid smaller
746 * transfers. If a file is finished then we flush the internal
747 * state and send a smaller buffer so that the remote side can
748 * finish the file.
749 */
750 if (zstd_out_buff.pos == zstd_out_buff.size || flush == ZSTD_e_flush) {
751 n = zstd_out_buff.pos;
752
753 obuf[0] = DEFLATED_DATA + (n >> 8);
754 obuf[1] = n;
755 write_buf(f, obuf, n+2);
756
757 zstd_out_buff.size = 0;
758 }
759 /*
760 * Loop while the input buffer isn't full consumed or the
761 * internal state isn't fully flushed.
762 */
763 } while (zstd_in_buff.pos < zstd_in_buff.size || r > 0);
764 flush_pending = token == -2;
765 }
766
767 if (token == -1) {
768 /* end of file - clean up */
769 write_byte(f, END_FLAG);
770 }
771}
772
773static ZSTD_DCtx *zstd_dctx;
774
775static int32 recv_zstd_token(int f, char **data)
776{
777 static int decomp_init_done;
778 static int out_buffer_size;
779 int32 n, flag;
780 int r;
781
782 if (!decomp_init_done) {
Wayne Davison4aaadc22020-05-25 13:31:30 -0700783 zstd_dctx = ZSTD_createDCtx();
784 if (!zstd_dctx) {
785 rprintf(FERROR, "ZSTD_createDStream failed\n");
786 exit_cleanup(RERR_PROTOCOL);
787 }
788
789 /* Output buffer fits two decompressed blocks */
790 out_buffer_size = ZSTD_DStreamOutSize() * 2;
791 cbuf = new_array(char, MAX_DATA_COUNT);
792 dbuf = new_array(char, out_buffer_size);
Wayne Davison4aaadc22020-05-25 13:31:30 -0700793
794 zstd_in_buff.src = cbuf;
795 zstd_out_buff.dst = dbuf;
796
797 decomp_init_done = 1;
798 }
799
Wayne Davison85e62c32020-07-04 15:27:47 -0700800 for (;;) {
801 switch (recv_state) {
802 case r_init:
803 recv_state = r_idle;
804 rx_token = 0;
805 break;
Wayne Davison4aaadc22020-05-25 13:31:30 -0700806
Wayne Davison85e62c32020-07-04 15:27:47 -0700807 case r_idle:
808 flag = read_byte(f);
809 if ((flag & 0xC0) == DEFLATED_DATA) {
810 n = ((flag & 0x3f) << 8) + read_byte(f);
811 read_buf(f, cbuf, n);
Wayne Davison4aaadc22020-05-25 13:31:30 -0700812
Wayne Davison85e62c32020-07-04 15:27:47 -0700813 zstd_in_buff.size = n;
814 zstd_in_buff.pos = 0;
Wayne Davison4aaadc22020-05-25 13:31:30 -0700815
Wayne Davison85e62c32020-07-04 15:27:47 -0700816 recv_state = r_inflating;
817 break;
818 }
Wayne Davison4aaadc22020-05-25 13:31:30 -0700819
Wayne Davison85e62c32020-07-04 15:27:47 -0700820 if (flag == END_FLAG) {
821 /* that's all folks */
822 recv_state = r_init;
823 return 0;
824 }
Wayne Davison4aaadc22020-05-25 13:31:30 -0700825 /* here we have a token of some kind */
826 if (flag & TOKEN_REL) {
827 rx_token += flag & 0x3f;
828 flag >>= 6;
829 } else
830 rx_token = read_int(f);
831 if (flag & 1) {
832 rx_run = read_byte(f);
833 rx_run += read_byte(f) << 8;
834 recv_state = r_running;
835 }
836 return -1 - rx_token;
Wayne Davison85e62c32020-07-04 15:27:47 -0700837
838 case r_inflated: /* zstd doesn't get into this state */
839 break;
840
841 case r_inflating:
842 zstd_out_buff.size = out_buffer_size;
843 zstd_out_buff.pos = 0;
844
845 r = ZSTD_decompressStream(zstd_dctx, &zstd_out_buff, &zstd_in_buff);
846 n = zstd_out_buff.pos;
847 if (ZSTD_isError(r)) {
848 rprintf(FERROR, "ZSTD decomp returned %d (%d bytes)\n", r, n);
849 exit_cleanup(RERR_STREAMIO);
850 }
851
852 /*
853 * If the input buffer is fully consumed and the output
854 * buffer is not full then next step is to read more
855 * data.
856 */
857 if (zstd_in_buff.size == zstd_in_buff.pos && n < out_buffer_size)
858 recv_state = r_idle;
859
860 if (n != 0) {
861 *data = dbuf;
862 return n;
863 }
864 break;
865
866 case r_running:
867 ++rx_token;
868 if (--rx_run == 0)
869 recv_state = r_idle;
870 return -1 - rx_token;
Wayne Davison4aaadc22020-05-25 13:31:30 -0700871 }
Wayne Davison4aaadc22020-05-25 13:31:30 -0700872 }
Wayne Davison4aaadc22020-05-25 13:31:30 -0700873}
Wayne Davisonc394e862020-05-25 13:43:25 -0700874#endif /* SUPPORT_ZSTD */
875
876#ifdef SUPPORT_LZ4
877static void
878send_compressed_token(int f, int32 token, struct map_struct *buf, OFF_T offset, int32 nb)
879{
880 static int init_done, flush_pending;
881 int size = MAX(LZ4_compressBound(CHUNK_SIZE), MAX_DATA_COUNT+2);
882 int32 n, r;
883
884 if (last_token == -1) {
885 if (!init_done) {
Wayne Davison11eb67e2020-06-25 19:59:19 -0700886 obuf = new_array(char, size);
Wayne Davisonc394e862020-05-25 13:43:25 -0700887 init_done = 1;
888 }
889 last_run_end = 0;
890 run_start = token;
891 flush_pending = 0;
892 } else if (last_token == -2) {
893 run_start = token;
Wayne Davison85e62c32020-07-04 15:27:47 -0700894 } else if (nb != 0 || token != last_token + 1 || token >= run_start + 65536) {
Wayne Davisonc394e862020-05-25 13:43:25 -0700895 /* output previous run */
896 r = run_start - last_run_end;
897 n = last_token - run_start;
898 if (r >= 0 && r <= 63) {
899 write_byte(f, (n==0? TOKEN_REL: TOKENRUN_REL) + r);
900 } else {
901 write_byte(f, (n==0? TOKEN_LONG: TOKENRUN_LONG));
902 write_int(f, run_start);
903 }
904 if (n != 0) {
905 write_byte(f, n);
906 write_byte(f, n >> 8);
907 }
908 last_run_end = last_token;
909 run_start = token;
910 }
911
912 last_token = token;
913
914 if (nb != 0 || flush_pending) {
915 int available_in, available_out = 0;
916 const char *next_in;
917
918 do {
Wayne Davisonc394e862020-05-25 13:43:25 -0700919 char *next_out = obuf + 2;
920
921 if (available_out == 0) {
922 available_in = MIN(nb, MAX_DATA_COUNT);
923 next_in = map_ptr(buf, offset, available_in);
924 } else
925 available_in /= 2;
926
Wayne Davisonc7f10de2020-05-28 11:40:52 -0700927 available_out = LZ4_compress_default(next_in, next_out, available_in, size - 2);
Wayne Davisonc394e862020-05-25 13:43:25 -0700928 if (!available_out) {
929 rprintf(FERROR, "compress returned %d\n", available_out);
930 exit_cleanup(RERR_STREAMIO);
931 }
932 if (available_out <= MAX_DATA_COUNT) {
Wayne Davison2bee3072020-07-04 15:58:56 -0700933 obuf[0] = DEFLATED_DATA + (available_out >> 8);
934 obuf[1] = available_out;
Wayne Davisonc394e862020-05-25 13:43:25 -0700935
Wayne Davison2bee3072020-07-04 15:58:56 -0700936 write_buf(f, obuf, available_out + 2);
Wayne Davisonc394e862020-05-25 13:43:25 -0700937
938 available_out = 0;
939 nb -= available_in;
940 offset += available_in;
941 }
942 } while (nb != 0);
943 flush_pending = token == -2;
944 }
Wayne Davison2bee3072020-07-04 15:58:56 -0700945 if (token == -1) {
Wayne Davisonc394e862020-05-25 13:43:25 -0700946 /* end of file - clean up */
947 write_byte(f, END_FLAG);
Wayne Davison2bee3072020-07-04 15:58:56 -0700948 }
Wayne Davisonc394e862020-05-25 13:43:25 -0700949}
950
951static int32 recv_compressed_token(int f, char **data)
952{
Wayne Davisonc394e862020-05-25 13:43:25 -0700953 static int init_done;
954 int32 n, flag;
955 int size = MAX(LZ4_compressBound(CHUNK_SIZE), MAX_DATA_COUNT+2);
956 static const char *next_in;
957 static int avail_in;
958 int avail_out;
959
960 for (;;) {
961 switch (recv_state) {
962 case r_init:
963 if (!init_done) {
Wayne Davison11eb67e2020-06-25 19:59:19 -0700964 cbuf = new_array(char, MAX_DATA_COUNT);
965 dbuf = new_array(char, size);
Wayne Davisonc394e862020-05-25 13:43:25 -0700966 init_done = 1;
967 }
968 recv_state = r_idle;
969 rx_token = 0;
970 break;
Wayne Davison2bee3072020-07-04 15:58:56 -0700971
Wayne Davisonc394e862020-05-25 13:43:25 -0700972 case r_idle:
Wayne Davison2bee3072020-07-04 15:58:56 -0700973 flag = read_byte(f);
Wayne Davisonc394e862020-05-25 13:43:25 -0700974 if ((flag & 0xC0) == DEFLATED_DATA) {
975 n = ((flag & 0x3f) << 8) + read_byte(f);
976 read_buf(f, cbuf, n);
977 next_in = (char *)cbuf;
978 avail_in = n;
979 recv_state = r_inflating;
980 break;
981 }
982
Wayne Davisonc394e862020-05-25 13:43:25 -0700983 if (flag == END_FLAG) {
984 /* that's all folks */
985 recv_state = r_init;
986 return 0;
987 }
988
989 /* here we have a token of some kind */
990 if (flag & TOKEN_REL) {
991 rx_token += flag & 0x3f;
992 flag >>= 6;
993 } else
994 rx_token = read_int(f);
995 if (flag & 1) {
996 rx_run = read_byte(f);
997 rx_run += read_byte(f) << 8;
998 recv_state = r_running;
999 }
1000 return -1 - rx_token;
1001
1002 case r_inflating:
1003 avail_out = LZ4_decompress_safe(next_in, dbuf, avail_in, size);
1004 if (avail_out < 0) {
1005 rprintf(FERROR, "uncompress failed: %d\n", avail_out);
1006 exit_cleanup(RERR_STREAMIO);
1007 }
Wayne Davison2bee3072020-07-04 15:58:56 -07001008 recv_state = r_idle;
Wayne Davisonc394e862020-05-25 13:43:25 -07001009 *data = dbuf;
1010 return avail_out;
1011
Wayne Davison2bee3072020-07-04 15:58:56 -07001012 case r_inflated: /* lz4 doesn't get into this state */
1013 break;
1014
Wayne Davisonc394e862020-05-25 13:43:25 -07001015 case r_running:
1016 ++rx_token;
1017 if (--rx_run == 0)
1018 recv_state = r_idle;
1019 return -1 - rx_token;
1020 }
1021 }
Wayne Davisonc394e862020-05-25 13:43:25 -07001022}
Wayne Davisonc394e862020-05-25 13:43:25 -07001023#endif /* SUPPORT_LZ4 */
Wayne Davison4aaadc22020-05-25 13:31:30 -07001024
Martin Pool79f671c2002-04-08 08:35:30 +00001025/**
1026 * Transmit a verbatim buffer of length @p n followed by a token.
Wayne Davisond67c8bd2004-06-18 16:22:14 +00001027 * If token == -1 then we have reached EOF
Andrew Tridgell70d794d1996-07-01 05:55:05 +00001028 * If n == 0 then don't send a buffer
Andrew Tridgell70d794d1996-07-01 05:55:05 +00001029 */
Wayne Davisonacc461c2005-02-14 08:19:32 +00001030void send_token(int f, int32 token, struct map_struct *buf, OFF_T offset,
Wayne Davison7fcbf9e2005-01-01 21:08:20 +00001031 int32 n, int32 toklen)
Andrew Tridgell70d794d1996-07-01 05:55:05 +00001032{
Wayne Davison778f0df2020-06-04 16:17:12 -07001033 switch (do_compression) {
1034 case CPRES_NONE:
Wayne Davison7fcbf9e2005-01-01 21:08:20 +00001035 simple_send_token(f, token, buf, offset, n);
Wayne Davison778f0df2020-06-04 16:17:12 -07001036 break;
1037 case CPRES_ZLIB:
1038 case CPRES_ZLIBX:
1039 send_deflated_token(f, token, buf, offset, n, toklen);
1040 break;
Wayne Davison4aaadc22020-05-25 13:31:30 -07001041#ifdef SUPPORT_ZSTD
Wayne Davison778f0df2020-06-04 16:17:12 -07001042 case CPRES_ZSTD:
Wayne Davison4aaadc22020-05-25 13:31:30 -07001043 send_zstd_token(f, token, buf, offset, n);
Wayne Davison778f0df2020-06-04 16:17:12 -07001044 break;
Wayne Davison4aaadc22020-05-25 13:31:30 -07001045#endif
Wayne Davisonc394e862020-05-25 13:43:25 -07001046#ifdef SUPPORT_LZ4
Wayne Davison778f0df2020-06-04 16:17:12 -07001047 case CPRES_LZ4:
Wayne Davisonc394e862020-05-25 13:43:25 -07001048 send_compressed_token(f, token, buf, offset, n);
Wayne Davison778f0df2020-06-04 16:17:12 -07001049 break;
Wayne Davisonc394e862020-05-25 13:43:25 -07001050#endif
Wayne Davison778f0df2020-06-04 16:17:12 -07001051 default:
Wayne Davisonab110fc2020-07-08 12:19:16 -07001052 NOISY_DEATH("Unknown do_compression value");
Wayne Davison778f0df2020-06-04 16:17:12 -07001053 }
Andrew Tridgell70d794d1996-07-01 05:55:05 +00001054}
1055
Andrew Tridgell70d794d1996-07-01 05:55:05 +00001056/*
Wayne Davisond2970212020-04-15 17:42:23 -07001057 * receive a token or buffer from the other end. If the return value is >0 then
Andrew Tridgell70d794d1996-07-01 05:55:05 +00001058 * it is a data buffer of that length, and *data will point at the data.
1059 * if the return value is -i then it represents token i-1
1060 * if the return value is 0 then the end has been reached
1061 */
Wayne Davison7fcbf9e2005-01-01 21:08:20 +00001062int32 recv_token(int f, char **data)
Andrew Tridgell70d794d1996-07-01 05:55:05 +00001063{
Wayne Davison778f0df2020-06-04 16:17:12 -07001064 switch (do_compression) {
1065 case CPRES_NONE:
Wayne Davison73053f22020-06-19 09:55:48 -07001066 return simple_recv_token(f,data);
Wayne Davison778f0df2020-06-04 16:17:12 -07001067 case CPRES_ZLIB:
1068 case CPRES_ZLIBX:
Wayne Davison73053f22020-06-19 09:55:48 -07001069 return recv_deflated_token(f, data);
Wayne Davison4aaadc22020-05-25 13:31:30 -07001070#ifdef SUPPORT_ZSTD
Wayne Davison778f0df2020-06-04 16:17:12 -07001071 case CPRES_ZSTD:
Wayne Davison73053f22020-06-19 09:55:48 -07001072 return recv_zstd_token(f, data);
Wayne Davison4aaadc22020-05-25 13:31:30 -07001073#endif
Wayne Davisonc394e862020-05-25 13:43:25 -07001074#ifdef SUPPORT_LZ4
Wayne Davison778f0df2020-06-04 16:17:12 -07001075 case CPRES_LZ4:
Wayne Davison73053f22020-06-19 09:55:48 -07001076 return recv_compressed_token(f, data);
Wayne Davisonc394e862020-05-25 13:43:25 -07001077#endif
Wayne Davison778f0df2020-06-04 16:17:12 -07001078 default:
Wayne Davisonab110fc2020-07-08 12:19:16 -07001079 NOISY_DEATH("Unknown do_compression value");
Wayne Davison778f0df2020-06-04 16:17:12 -07001080 }
Paul Mackerras861c20b1996-07-03 04:05:46 +00001081}
1082
1083/*
1084 * look at the data corresponding to a token, if necessary
1085 */
Wayne Davison7fcbf9e2005-01-01 21:08:20 +00001086void see_token(char *data, int32 toklen)
Paul Mackerras861c20b1996-07-03 04:05:46 +00001087{
Wayne Davison778f0df2020-06-04 16:17:12 -07001088 switch (do_compression) {
1089 case CPRES_NONE:
1090 break;
1091 case CPRES_ZLIB:
Paul Mackerras5914bf11998-05-22 06:58:52 +00001092 see_deflate_token(data, toklen);
Wayne Davison778f0df2020-06-04 16:17:12 -07001093 break;
1094 case CPRES_ZLIBX:
1095 break;
Wayne Davisonbb1365d2020-07-10 09:47:16 -07001096#ifdef SUPPORT_ZSTD
1097 case CPRES_ZSTD:
Wayne Davison778f0df2020-06-04 16:17:12 -07001098 break;
Wayne Davisonc394e862020-05-25 13:43:25 -07001099#endif
Wayne Davison778f0df2020-06-04 16:17:12 -07001100#ifdef SUPPORT_LZ4
Wayne Davisonbb1365d2020-07-10 09:47:16 -07001101 case CPRES_LZ4:
1102 /*see_uncompressed_token(data, toklen);*/
Wayne Davison778f0df2020-06-04 16:17:12 -07001103 break;
1104#endif
1105 default:
Wayne Davisonab110fc2020-07-08 12:19:16 -07001106 NOISY_DEATH("Unknown do_compression value");
Wayne Davison778f0df2020-06-04 16:17:12 -07001107 }
Andrew Tridgell70d794d1996-07-01 05:55:05 +00001108}