| 997 | } |
| 998 | |
| 999 | static int32 recv_compressed_token(int f, char **data) |
| 1000 | { |
| 1001 | static int init_done; |
| 1002 | int32 n, flag; |
| 1003 | int size = MAX(LZ4_compressBound(CHUNK_SIZE), MAX_DATA_COUNT+2); |
| 1004 | static const char *next_in; |
| 1005 | static int avail_in; |
| 1006 | int avail_out; |
| 1007 | |
| 1008 | for (;;) { |
| 1009 | switch (recv_state) { |
| 1010 | case r_init: |
| 1011 | if (!init_done) { |
| 1012 | cbuf = new_array(char, MAX_DATA_COUNT); |
| 1013 | dbuf = new_array(char, size); |
| 1014 | init_done = 1; |
| 1015 | } |
| 1016 | recv_state = r_idle; |
| 1017 | rx_token = 0; |
| 1018 | break; |
| 1019 | |
| 1020 | case r_idle: |
| 1021 | flag = read_byte(f); |
| 1022 | if ((flag & 0xC0) == DEFLATED_DATA) { |
| 1023 | n = ((flag & 0x3f) << 8) + read_byte(f); |
| 1024 | read_buf(f, cbuf, n); |
| 1025 | next_in = (char *)cbuf; |
| 1026 | avail_in = n; |
| 1027 | recv_state = r_inflating; |
| 1028 | break; |
| 1029 | } |
| 1030 | |
| 1031 | if (flag == END_FLAG) { |
| 1032 | /* that's all folks */ |
| 1033 | recv_state = r_init; |
| 1034 | return 0; |
| 1035 | } |
| 1036 | |
| 1037 | /* here we have a token of some kind */ |
| 1038 | return recv_compressed_token_num(f, flag); |
| 1039 | |
| 1040 | case r_inflating: |
| 1041 | avail_out = LZ4_decompress_safe(next_in, dbuf, avail_in, size); |
| 1042 | if (avail_out < 0) { |
| 1043 | rprintf(FERROR, "uncompress failed: %d\n", avail_out); |
| 1044 | exit_cleanup(RERR_STREAMIO); |
| 1045 | } |
| 1046 | recv_state = r_idle; |
| 1047 | *data = dbuf; |
| 1048 | return avail_out; |
| 1049 | |
| 1050 | case r_inflated: /* lz4 doesn't get into this state */ |
| 1051 | break; |
| 1052 | |
| 1053 | case r_running: |
| 1054 | return recv_compressed_token_run(); |
| 1055 | } |
| 1056 | } |
no test coverage detected