1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39#define _ISOC11_SOURCE
40#define _DEFAULT_SOURCE
41
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <unistd.h>
46#include <stdint.h>
47#include <sys/types.h>
48#include <sys/stat.h>
49#include <sys/time.h>
50#include <sys/fcntl.h>
51#include <sys/mman.h>
52#include <endian.h>
53#include <bits/endian.h>
54#include <sys/ioctl.h>
55#include <assert.h>
56#include <errno.h>
57#include <signal.h>
58#include "nxu.h"
59#include "nx.h"
60#include "crb.h"
61
62int nx_dbg;
63FILE *nx_gzip_log;
64
65#define NX_MIN(X, Y) (((X) < (Y))?(X):(Y))
66#define NX_MAX(X, Y) (((X) > (Y))?(X):(Y))
67
68#define GETINPC(X) fgetc(X)
69#define FNAME_MAX 1024
70
71
72#define fifo_used_bytes(used) (used)
73#define fifo_free_bytes(used, len) ((len)-(used))
74
75#define fifo_free_first_bytes(cur, used, len) ((((cur)+(used)) <= (len)) \
76 ? (len)-((cur)+(used)) : 0)
77#define fifo_free_last_bytes(cur, used, len) ((((cur)+(used)) <= (len)) \
78 ? (cur) : (len)-(used))
79
80#define fifo_used_first_bytes(cur, used, len) ((((cur)+(used)) <= (len)) \
81 ? (used) : (len)-(cur))
82#define fifo_used_last_bytes(cur, used, len) ((((cur)+(used)) <= (len)) \
83 ? 0 : ((used)+(cur))-(len))
84
85#define fifo_free_first_offset(cur, used) ((cur)+(used))
86#define fifo_free_last_offset(cur, used, len) \
87 fifo_used_last_bytes(cur, used, len)
88
89#define fifo_used_first_offset(cur) (cur)
90#define fifo_used_last_offset(cur) (0)
91
92const int fifo_in_len = 1<<24;
93const int fifo_out_len = 1<<24;
94const int page_sz = 1<<16;
95const int line_sz = 1<<7;
96const int window_max = 1<<15;
97
98
99
100
101
102
103
104
105
106
107
108
109static inline uint32_t nx_append_dde(struct nx_dde_t *ddl, void *addr,
110 uint32_t len)
111{
112 uint32_t ddecnt;
113 uint32_t bytes;
114
115 if (addr == NULL && len == 0) {
116 clearp_dde(ddl);
117 return 0;
118 }
119
120 NXPRT(fprintf(stderr, "%d: %s addr %p len %x\n", __LINE__, addr,
121 __func__, len));
122
123
124 ddecnt = getpnn(ddl, dde_count);
125 bytes = getp32(ddl, ddebc);
126
127 if (ddecnt == 0 && bytes == 0) {
128
129 bytes = len;
130 putp32(ddl, ddebc, bytes);
131 putp64(ddl, ddead, (uint64_t) addr);
132 } else if (ddecnt == 0) {
133
134
135
136
137 ddl[1] = ddl[0];
138
139
140 clear_dde(ddl[2]);
141 put32(ddl[2], ddebc, len);
142 put64(ddl[2], ddead, (uint64_t) addr);
143
144
145 ddecnt = 2;
146 putpnn(ddl, dde_count, ddecnt);
147 bytes = bytes + len;
148 putp32(ddl, ddebc, bytes);
149
150 putp64(ddl, ddead, (uint64_t) &ddl[1]);
151 } else {
152
153 ++ddecnt;
154 clear_dde(ddl[ddecnt]);
155 put64(ddl[ddecnt], ddead, (uint64_t) addr);
156 put32(ddl[ddecnt], ddebc, len);
157
158 putpnn(ddl, dde_count, ddecnt);
159 bytes = bytes + len;
160 putp32(ddl, ddebc, bytes);
161 }
162 return bytes;
163}
164
165
166
167
168
169
170
171
172static int nx_touch_pages_dde(struct nx_dde_t *ddep, long buf_sz, long page_sz,
173 int wr)
174{
175 uint32_t indirect_count;
176 uint32_t buf_len;
177 long total;
178 uint64_t buf_addr;
179 struct nx_dde_t *dde_list;
180 int i;
181
182 assert(!!ddep);
183
184 indirect_count = getpnn(ddep, dde_count);
185
186 NXPRT(fprintf(stderr, "%s dde_count %d request len ", __func__,
187 indirect_count));
188 NXPRT(fprintf(stderr, "0x%lx\n", buf_sz));
189
190 if (indirect_count == 0) {
191
192 buf_len = getp32(ddep, ddebc);
193 buf_addr = getp64(ddep, ddead);
194
195 NXPRT(fprintf(stderr, "touch direct ddebc 0x%x ddead %p\n",
196 buf_len, (void *)buf_addr));
197
198 if (buf_sz == 0)
199 nxu_touch_pages((void *)buf_addr, buf_len, page_sz, wr);
200 else
201 nxu_touch_pages((void *)buf_addr, NX_MIN(buf_len,
202 buf_sz), page_sz, wr);
203
204 return ERR_NX_OK;
205 }
206
207
208 if (indirect_count > MAX_DDE_COUNT)
209 return ERR_NX_EXCESSIVE_DDE;
210
211
212 dde_list = (struct nx_dde_t *) getp64(ddep, ddead);
213
214 if (buf_sz == 0)
215 buf_sz = getp32(ddep, ddebc);
216
217 total = 0;
218 for (i = 0; i < indirect_count; i++) {
219 buf_len = get32(dde_list[i], ddebc);
220 buf_addr = get64(dde_list[i], ddead);
221 total += buf_len;
222
223 NXPRT(fprintf(stderr, "touch loop len 0x%x ddead %p total ",
224 buf_len, (void *)buf_addr));
225 NXPRT(fprintf(stderr, "0x%lx\n", total));
226
227
228 if (total > buf_sz) {
229 buf_len = NX_MIN(buf_len, total - buf_sz);
230 nxu_touch_pages((void *)buf_addr, buf_len, page_sz, wr);
231 NXPRT(fprintf(stderr, "touch loop break len 0x%x ",
232 buf_len));
233 NXPRT(fprintf(stderr, "ddead %p\n", (void *)buf_addr));
234 break;
235 }
236 nxu_touch_pages((void *)buf_addr, buf_len, page_sz, wr);
237 }
238 return ERR_NX_OK;
239}
240
241
242
243
244
245static int nx_submit_job(struct nx_dde_t *src, struct nx_dde_t *dst,
246 struct nx_gzip_crb_cpb_t *cmdp, void *handle)
247{
248 uint64_t csbaddr;
249
250 memset((void *)&cmdp->crb.csb, 0, sizeof(cmdp->crb.csb));
251
252 cmdp->crb.source_dde = *src;
253 cmdp->crb.target_dde = *dst;
254
255
256 csbaddr = ((uint64_t) &cmdp->crb.csb) & csb_address_mask;
257 put64(cmdp->crb, csb_address, csbaddr);
258
259
260 cmdp->cpb.out_spbc_comp_wrap = 0;
261 cmdp->cpb.out_spbc_comp_with_count = 0;
262 cmdp->cpb.out_spbc_decomp = 0;
263
264
265 put32(cmdp->cpb, out_crc, INIT_CRC);
266 put32(cmdp->cpb, out_adler, INIT_ADLER);
267
268
269 return nxu_submit_job(cmdp, handle);
270}
271
272int decompress_file(int argc, char **argv, void *devhandle)
273{
274 FILE *inpf = NULL;
275 FILE *outf = NULL;
276
277 int c, expect, i, cc, rc = 0;
278 char gzfname[FNAME_MAX];
279
280
281 char *fifo_in, *fifo_out;
282 int used_in, cur_in, used_out, cur_out, read_sz, n;
283 int first_free, last_free, first_used, last_used;
284 int first_offset, last_offset;
285 int write_sz, free_space, source_sz;
286 int source_sz_estimate, target_sz_estimate;
287 uint64_t last_comp_ratio = 0;
288 uint64_t total_out = 0;
289 int is_final, is_eof;
290
291
292 int sfbt, subc, spbc, tpbc, nx_ce, fc, resuming = 0;
293 int history_len = 0;
294 struct nx_gzip_crb_cpb_t cmd, *cmdp;
295 struct nx_dde_t *ddl_in;
296 struct nx_dde_t dde_in[6] __aligned(128);
297 struct nx_dde_t *ddl_out;
298 struct nx_dde_t dde_out[6] __aligned(128);
299 int pgfault_retries;
300
301
302 off_t input_file_offset;
303
304 if (argc > 2) {
305 fprintf(stderr, "usage: %s <fname> or stdin\n", argv[0]);
306 fprintf(stderr, " writes to stdout or <fname>.nx.gunzip\n");
307 return -1;
308 }
309
310 if (argc == 1) {
311 inpf = stdin;
312 outf = stdout;
313 } else if (argc == 2) {
314 char w[1024];
315 char *wp;
316
317 inpf = fopen(argv[1], "r");
318 if (inpf == NULL) {
319 perror(argv[1]);
320 return -1;
321 }
322
323
324 wp = (NULL != (wp = strrchr(argv[1], '/'))) ? (wp+1) : argv[1];
325 strcpy(w, wp);
326 strcat(w, ".nx.gunzip");
327
328 outf = fopen(w, "w");
329 if (outf == NULL) {
330 perror(w);
331 return -1;
332 }
333 }
334
335
336 c = GETINPC(inpf); expect = 0x1f;
337 if (c != expect)
338 goto err1;
339
340 c = GETINPC(inpf); expect = 0x8b;
341 if (c != expect)
342 goto err1;
343
344 c = GETINPC(inpf); expect = 0x08;
345 if (c != expect)
346 goto err1;
347
348 int flg = GETINPC(inpf);
349
350 if (flg & 0xE0 || flg & 0x4 || flg == EOF)
351 goto err2;
352
353 fprintf(stderr, "gzHeader FLG %x\n", flg);
354
355
356
357
358 for (i = 0; i < 6; i++) {
359 char tmp[10];
360
361 tmp[i] = GETINPC(inpf);
362 if (tmp[i] == EOF)
363 goto err3;
364 fprintf(stderr, "%02x ", tmp[i]);
365 if (i == 5)
366 fprintf(stderr, "\n");
367 }
368 fprintf(stderr, "gzHeader MTIME, XFL, OS ignored\n");
369
370
371 if (flg & 0x8) {
372 int k = 0;
373
374 do {
375 c = GETINPC(inpf);
376 if (c == EOF || k >= FNAME_MAX)
377 goto err3;
378 gzfname[k++] = c;
379 } while (c);
380 fprintf(stderr, "gzHeader FNAME: %s\n", gzfname);
381 }
382
383
384 if (flg & 0x2) {
385 c = GETINPC(inpf);
386 if (c == EOF)
387 goto err3;
388 c = GETINPC(inpf);
389 if (c == EOF)
390 goto err3;
391 fprintf(stderr, "gzHeader FHCRC: ignored\n");
392 }
393
394 used_in = cur_in = used_out = cur_out = 0;
395 is_final = is_eof = 0;
396
397
398
399
400
401
402 assert((fifo_in = (char *)(uintptr_t)aligned_alloc(line_sz,
403 fifo_in_len + page_sz)) != NULL);
404 assert((fifo_out = (char *)(uintptr_t)aligned_alloc(line_sz,
405 fifo_out_len + page_sz + line_sz)) != NULL);
406
407 fifo_out = fifo_out + line_sz;
408 nxu_touch_pages(fifo_out, fifo_out_len, page_sz, 1);
409
410 ddl_in = &dde_in[0];
411 ddl_out = &dde_out[0];
412 cmdp = &cmd;
413 memset(&cmdp->crb, 0, sizeof(cmdp->crb));
414
415read_state:
416
417
418
419 NXPRT(fprintf(stderr, "read_state:\n"));
420
421 if (is_eof != 0)
422 goto write_state;
423
424
425
426
427
428
429
430 cur_in = (used_in == 0) ? 0 : cur_in;
431
432
433 free_space = NX_MAX(0, fifo_free_bytes(used_in, fifo_in_len)
434 - line_sz);
435
436
437 first_free = fifo_free_first_bytes(cur_in, used_in, fifo_in_len);
438 last_free = fifo_free_last_bytes(cur_in, used_in, fifo_in_len);
439
440
441 first_offset = fifo_free_first_offset(cur_in, used_in);
442 last_offset = fifo_free_last_offset(cur_in, used_in, fifo_in_len);
443
444
445 read_sz = NX_MIN(free_space, first_free);
446 n = 0;
447 if (read_sz > 0) {
448
449 n = fread(fifo_in + first_offset, 1, read_sz, inpf);
450 used_in = used_in + n;
451 free_space = free_space - n;
452 assert(n <= read_sz);
453 if (n != read_sz) {
454
455 is_eof = 1;
456 goto write_state;
457 }
458 }
459
460
461 if (last_free > 0) {
462
463 read_sz = NX_MIN(free_space, last_free);
464 n = 0;
465 if (read_sz > 0) {
466 n = fread(fifo_in + last_offset, 1, read_sz, inpf);
467 used_in = used_in + n;
468 free_space = free_space - n;
469 assert(n <= read_sz);
470 if (n != read_sz) {
471
472 is_eof = 1;
473 goto write_state;
474 }
475 }
476 }
477
478
479
480
481
482write_state:
483
484
485
486 NXPRT(fprintf(stderr, "write_state:\n"));
487
488 if (used_out == 0)
489 goto decomp_state;
490
491
492
493
494
495
496 first_used = fifo_used_first_bytes(cur_out, used_out, fifo_out_len);
497 last_used = fifo_used_last_bytes(cur_out, used_out, fifo_out_len);
498
499 write_sz = first_used;
500
501 n = 0;
502 if (write_sz > 0) {
503 n = fwrite(fifo_out + cur_out, 1, write_sz, outf);
504 used_out = used_out - n;
505
506 cur_out = (cur_out + n) % fifo_out_len;
507 assert(n <= write_sz);
508 if (n != write_sz) {
509 fprintf(stderr, "error: write\n");
510 rc = -1;
511 goto err5;
512 }
513 }
514
515 if (last_used > 0) {
516 write_sz = last_used;
517 n = 0;
518 if (write_sz > 0) {
519 n = fwrite(fifo_out, 1, write_sz, outf);
520 used_out = used_out - n;
521 cur_out = (cur_out + n) % fifo_out_len;
522 assert(n <= write_sz);
523 if (n != write_sz) {
524 fprintf(stderr, "error: write\n");
525 rc = -1;
526 goto err5;
527 }
528 }
529 }
530
531decomp_state:
532
533
534
535 NXPRT(fprintf(stderr, "decomp_state:\n"));
536
537 if (is_final)
538 goto finish_state;
539
540
541 clearp_dde(ddl_in);
542 clearp_dde(ddl_out);
543
544
545 if (resuming) {
546
547
548
549
550
551 fc = GZIP_FC_DECOMPRESS_RESUME;
552
553 cmdp->cpb.in_crc = cmdp->cpb.out_crc;
554 cmdp->cpb.in_adler = cmdp->cpb.out_adler;
555
556
557 history_len = (history_len + 15) / 16;
558 putnn(cmdp->cpb, in_histlen, history_len);
559 history_len = history_len * 16;
560
561 if (history_len > 0) {
562
563 if (cur_out >= history_len) {
564 nx_append_dde(ddl_in, fifo_out
565 + (cur_out - history_len),
566 history_len);
567 } else {
568 nx_append_dde(ddl_in, fifo_out
569 + ((fifo_out_len + cur_out)
570 - history_len),
571 history_len - cur_out);
572
573 nx_append_dde(ddl_in, fifo_out, cur_out);
574 }
575
576 }
577 } else {
578
579 fc = GZIP_FC_DECOMPRESS;
580
581 history_len = 0;
582
583 cmdp->cpb.in_histlen = 0;
584 total_out = 0;
585
586 put32(cmdp->cpb, in_crc, INIT_CRC);
587 put32(cmdp->cpb, in_adler, INIT_ADLER);
588 put32(cmdp->cpb, out_crc, INIT_CRC);
589 put32(cmdp->cpb, out_adler, INIT_ADLER);
590
591
592
593
594
595
596
597
598 last_comp_ratio = 100UL;
599 }
600 cmdp->crb.gzip_fc = 0;
601 putnn(cmdp->crb, gzip_fc, fc);
602
603
604
605
606 first_used = fifo_used_first_bytes(cur_in, used_in, fifo_in_len);
607 last_used = fifo_used_last_bytes(cur_in, used_in, fifo_in_len);
608
609 if (first_used > 0)
610 nx_append_dde(ddl_in, fifo_in + cur_in, first_used);
611
612 if (last_used > 0)
613 nx_append_dde(ddl_in, fifo_in, last_used);
614
615
616
617
618 first_free = fifo_free_first_bytes(cur_out, used_out, fifo_out_len);
619 last_free = fifo_free_last_bytes(cur_out, used_out, fifo_out_len);
620
621
622 int target_max = NX_MAX(0, fifo_free_bytes(used_out, fifo_out_len)
623 - (1<<16));
624
625 NXPRT(fprintf(stderr, "target_max %d (0x%x)\n", target_max,
626 target_max));
627
628 first_free = NX_MIN(target_max, first_free);
629 if (first_free > 0) {
630 first_offset = fifo_free_first_offset(cur_out, used_out);
631 nx_append_dde(ddl_out, fifo_out + first_offset, first_free);
632 }
633
634 if (last_free > 0) {
635 last_free = NX_MIN(target_max - first_free, last_free);
636 if (last_free > 0) {
637 last_offset = fifo_free_last_offset(cur_out, used_out,
638 fifo_out_len);
639 nx_append_dde(ddl_out, fifo_out + last_offset,
640 last_free);
641 }
642 }
643
644
645
646
647
648
649 source_sz = getp32(ddl_in, ddebc);
650 assert(source_sz > history_len);
651 source_sz = source_sz - history_len;
652
653
654
655
656
657
658
659
660 source_sz_estimate = ((uint64_t)target_max * last_comp_ratio * 3UL)
661 / 4000;
662
663 if (source_sz_estimate < source_sz) {
664
665
666
667 source_sz = source_sz_estimate;
668 target_sz_estimate = target_max;
669 } else {
670
671
672
673 target_sz_estimate = ((uint64_t)source_sz * 1000UL)
674 / (last_comp_ratio + 1);
675 target_sz_estimate = NX_MIN(2 * target_sz_estimate,
676 target_max);
677 }
678
679 source_sz = source_sz + history_len;
680
681
682
683
684
685 pgfault_retries = NX_MAX_FAULTS;
686
687restart_nx:
688
689 putp32(ddl_in, ddebc, source_sz);
690
691
692 nxu_touch_pages(cmdp, sizeof(struct nx_gzip_crb_cpb_t), page_sz, 1);
693 nx_touch_pages_dde(ddl_in, 0, page_sz, 0);
694 nx_touch_pages_dde(ddl_out, target_sz_estimate, page_sz, 1);
695
696
697 cc = nx_submit_job(ddl_in, ddl_out, cmdp, devhandle);
698
699 switch (cc) {
700
701 case ERR_NX_AT_FAULT:
702
703
704
705
706
707 NXPRT(fprintf(stderr, "ERR_NX_AT_FAULT %p\n",
708 (void *)cmdp->crb.csb.fsaddr));
709
710 if (pgfault_retries == NX_MAX_FAULTS) {
711
712 --pgfault_retries;
713 goto restart_nx;
714 } else if (pgfault_retries > 0) {
715
716
717
718 if (source_sz > page_sz)
719 source_sz = NX_MAX(source_sz / 2, page_sz);
720 --pgfault_retries;
721 goto restart_nx;
722 } else {
723 fprintf(stderr, "cannot make progress; too many ");
724 fprintf(stderr, "page fault retries cc= %d\n", cc);
725 rc = -1;
726 goto err5;
727 }
728
729 case ERR_NX_DATA_LENGTH:
730
731 NXPRT(fprintf(stderr, "ERR_NX_DATA_LENGTH; "));
732 NXPRT(fprintf(stderr, "stream may have trailing data\n"));
733
734
735
736
737
738
739
740 nx_ce = get_csb_ce_ms3b(cmdp->crb.csb);
741
742 if (!csb_ce_termination(nx_ce) &&
743 csb_ce_partial_completion(nx_ce)) {
744
745
746
747 sfbt = getnn(cmdp->cpb, out_sfbt);
748 subc = getnn(cmdp->cpb, out_subc);
749 spbc = get32(cmdp->cpb, out_spbc_decomp);
750 tpbc = get32(cmdp->crb.csb, tpbc);
751 assert(target_max >= tpbc);
752
753 goto ok_cc3;
754 } else {
755
756 rc = -1;
757 fprintf(stderr, "history length error cc= %d\n", cc);
758 goto err5;
759 }
760
761 case ERR_NX_TARGET_SPACE:
762
763
764
765
766 assert(source_sz > history_len);
767 source_sz = ((source_sz - history_len + 2) / 2) + history_len;
768 NXPRT(fprintf(stderr, "ERR_NX_TARGET_SPACE; retry with "));
769 NXPRT(fprintf(stderr, "smaller input data src %d hist %d\n",
770 source_sz, history_len));
771 goto restart_nx;
772
773 case ERR_NX_OK:
774
775
776
777
778 fprintf(stderr, "ERR_NX_OK\n");
779 spbc = get32(cmdp->cpb, out_spbc_decomp);
780 tpbc = get32(cmdp->crb.csb, tpbc);
781 assert(target_max >= tpbc);
782 assert(spbc >= history_len);
783 source_sz = spbc - history_len;
784 goto offsets_state;
785
786 default:
787 fprintf(stderr, "error: cc= %d\n", cc);
788 rc = -1;
789 goto err5;
790 }
791
792ok_cc3:
793
794 NXPRT(fprintf(stderr, "cc3: sfbt: %x\n", sfbt));
795
796 assert(spbc > history_len);
797 source_sz = spbc - history_len;
798
799
800
801
802
803
804
805
806
807 switch (sfbt) {
808 int dhtlen;
809
810 case 0x0:
811
812
813
814 source_sz = source_sz - subc / 8;
815 is_final = 1;
816 break;
817
818
819
820
821
822
823 case 0x8:
824 case 0x9:
825
826
827 source_sz = source_sz - ((subc + 7) / 8);
828
829
830
831
832
833
834 cmdp->cpb.in_subc = 0;
835 cmdp->cpb.in_sfbt = 0;
836 putnn(cmdp->cpb, in_subc, subc % 8);
837 putnn(cmdp->cpb, in_sfbt, sfbt);
838 putnn(cmdp->cpb, in_rembytecnt, getnn(cmdp->cpb,
839 out_rembytecnt));
840 break;
841
842 case 0xA:
843 case 0xB:
844
845 source_sz = source_sz - ((subc + 7) / 8);
846
847
848 cmdp->cpb.in_subc = 0;
849 cmdp->cpb.in_sfbt = 0;
850 putnn(cmdp->cpb, in_subc, subc % 8);
851 putnn(cmdp->cpb, in_sfbt, sfbt);
852 break;
853
854 case 0xC:
855 case 0xD:
856
857 source_sz = source_sz - ((subc + 7) / 8);
858
859
860 cmdp->cpb.in_subc = 0;
861 cmdp->cpb.in_sfbt = 0;
862 putnn(cmdp->cpb, in_subc, subc % 8);
863 putnn(cmdp->cpb, in_sfbt, sfbt);
864
865 dhtlen = getnn(cmdp->cpb, out_dhtlen);
866 putnn(cmdp->cpb, in_dhtlen, dhtlen);
867 assert(dhtlen >= 42);
868
869
870 dhtlen = (dhtlen + 127) / 128;
871
872 while (dhtlen > 0) {
873 --dhtlen;
874 cmdp->cpb.in_dht[dhtlen] = cmdp->cpb.out_dht[dhtlen];
875 }
876 break;
877
878 case 0xE:
879
880
881
882
883 case 0xF:
884
885 source_sz = source_sz - ((subc + 7) / 8);
886
887
888 cmdp->cpb.in_subc = 0;
889 cmdp->cpb.in_sfbt = 0;
890 putnn(cmdp->cpb, in_subc, subc % 8);
891 putnn(cmdp->cpb, in_sfbt, sfbt);
892
893
894 if (is_eof && (source_sz == 0))
895 is_final = 1;
896 }
897
898offsets_state:
899
900
901
902 NXPRT(fprintf(stderr, "offsets_state:\n"));
903
904
905 used_in = used_in - source_sz;
906 cur_in = (cur_in + source_sz) % fifo_in_len;
907 input_file_offset = input_file_offset + source_sz;
908
909
910 used_out = used_out + tpbc;
911
912 assert(used_out <= fifo_out_len);
913
914 total_out = total_out + tpbc;
915
916
917
918
919 history_len = (total_out > window_max) ? window_max : total_out;
920
921
922
923
924 last_comp_ratio = (1000UL * ((uint64_t)source_sz + 1))
925 / ((uint64_t)tpbc + 1);
926 last_comp_ratio = NX_MAX(NX_MIN(1000UL, last_comp_ratio), 1);
927 NXPRT(fprintf(stderr, "comp_ratio %ld source_sz %d spbc %d tpbc %d\n",
928 last_comp_ratio, source_sz, spbc, tpbc));
929
930 resuming = 1;
931
932finish_state:
933
934 NXPRT(fprintf(stderr, "finish_state:\n"));
935
936 if (is_final) {
937 if (used_out)
938 goto write_state;
939 else if (used_in < 8) {
940
941
942
943 rc = -1;
944 goto err4;
945 } else {
946
947 int i;
948 unsigned char tail[8];
949 uint32_t cksum, isize;
950
951 for (i = 0; i < 8; i++)
952 tail[i] = fifo_in[(cur_in + i) % fifo_in_len];
953 fprintf(stderr, "computed checksum %08x isize %08x\n",
954 cmdp->cpb.out_crc, (uint32_t) (total_out
955 % (1ULL<<32)));
956 cksum = ((uint32_t) tail[0] | (uint32_t) tail[1]<<8
957 | (uint32_t) tail[2]<<16
958 | (uint32_t) tail[3]<<24);
959 isize = ((uint32_t) tail[4] | (uint32_t) tail[5]<<8
960 | (uint32_t) tail[6]<<16
961 | (uint32_t) tail[7]<<24);
962 fprintf(stderr, "stored checksum %08x isize %08x\n",
963 cksum, isize);
964
965 if (cksum == cmdp->cpb.out_crc && isize == (uint32_t)
966 (total_out % (1ULL<<32))) {
967 rc = 0; goto ok1;
968 } else {
969 rc = -1; goto err4;
970 }
971 }
972 } else
973 goto read_state;
974
975 return -1;
976
977err1:
978 fprintf(stderr, "error: not a gzip file, expect %x, read %x\n",
979 expect, c);
980 return -1;
981
982err2:
983 fprintf(stderr, "error: the FLG byte is wrong or not being handled\n");
984 return -1;
985
986err3:
987 fprintf(stderr, "error: gzip header\n");
988 return -1;
989
990err4:
991 fprintf(stderr, "error: checksum missing or mismatch\n");
992
993err5:
994ok1:
995 fprintf(stderr, "decomp is complete: fclose\n");
996 fclose(outf);
997
998 return rc;
999}
1000
1001
1002int main(int argc, char **argv)
1003{
1004 int rc;
1005 struct sigaction act;
1006 void *handle;
1007
1008 nx_dbg = 0;
1009 nx_gzip_log = NULL;
1010 act.sa_handler = 0;
1011 act.sa_sigaction = nxu_sigsegv_handler;
1012 act.sa_flags = SA_SIGINFO;
1013 act.sa_restorer = 0;
1014 sigemptyset(&act.sa_mask);
1015 sigaction(SIGSEGV, &act, NULL);
1016
1017 handle = nx_function_begin(NX_FUNC_COMP_GZIP, 0);
1018 if (!handle) {
1019 fprintf(stderr, "Unable to init NX, errno %d\n", errno);
1020 exit(-1);
1021 }
1022
1023 rc = decompress_file(argc, argv, handle);
1024
1025 nx_function_end(handle);
1026
1027 return rc;
1028}
1029