Skip to content

Commit e045713

Browse files
committed
kiss
1 parent 3123486 commit e045713

1 file changed

Lines changed: 125 additions & 137 deletions

File tree

src/main.c

Lines changed: 125 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -584,134 +584,168 @@ static int extract_all(const char *path) {
584584
return 0;
585585
}
586586

587-
/* Decompress a gzip file (gunzip mode) */
588-
static int gunzip_file(const char *input_path, const char *output_path) {
589-
FILE *fin = fopen (input_path, "rb");
590-
if (!fin) {
591-
fprintf (stderr, "Cannot open input file: %s\n", input_path);
592-
return 1;
593-
}
594-
595-
/* Read entire input file */
596-
fseek (fin, 0, SEEK_END);
597-
long fsize = ftell (fin);
598-
fseek (fin, 0, SEEK_SET);
599-
600-
if (fsize <= 0) {
601-
fprintf (stderr, "Invalid input file size\n");
602-
fclose (fin);
603-
return 1;
604-
}
605-
size_t input_size = (size_t)fsize;
606-
607-
uint8_t *input_data = (uint8_t *)malloc (input_size);
608-
if (!input_data) {
609-
fprintf (stderr, "Out of memory\n");
610-
fclose (fin);
611-
return 1;
612-
}
613-
614-
if (fread (input_data, 1, input_size, fin) != input_size) {
615-
fprintf (stderr, "Failed to read input file\n");
616-
free (input_data);
617-
fclose (fin);
618-
return 1;
619-
}
620-
fclose (fin);
621-
622-
/* Initialize inflate with auto-detect (gzip or zlib) */
587+
/* Inflate (decompress) a buffer with auto-detect gzip/zlib header.
588+
* Returns a malloc'd buffer on success (caller frees), NULL on failure.
589+
* Sets *out_size to the decompressed size on success. */
590+
static uint8_t *inflate_buffer(const uint8_t *input_data, size_t input_size, size_t *out_size) {
623591
z_stream strm;
624592
memset (&strm, 0, sizeof (strm));
625-
strm.next_in = input_data;
593+
strm.next_in = (uint8_t *)input_data;
626594
strm.avail_in = UINT_CLAMP (input_size);
627595

628-
/* MAX_WBITS + 32 = auto-detect gzip or zlib header */
629-
int ret = inflateInit2 (&strm, MAX_WBITS + 32);
630-
if (ret != Z_OK) {
631-
fprintf (stderr, "inflateInit2 failed: %d\n", ret);
632-
free (input_data);
633-
return 1;
596+
if (inflateInit2 (&strm, MAX_WBITS + 32) != Z_OK) {
597+
fprintf (stderr, "inflateInit2 failed\n");
598+
return NULL;
634599
}
635600

636-
/* Allocate output buffer - start with 4x input size */
637-
size_t out_alloc = input_size * 4;
638-
if (out_alloc < 65536) {
639-
out_alloc = 65536;
601+
size_t alloc = input_size * 4;
602+
if (alloc < 65536) {
603+
alloc = 65536;
640604
}
641-
uint8_t *output_data = (uint8_t *)malloc (out_alloc);
642-
if (!output_data) {
605+
uint8_t *buf = (uint8_t *)malloc (alloc);
606+
if (!buf) {
643607
fprintf (stderr, "Out of memory for output buffer\n");
644608
inflateEnd (&strm);
645-
free (input_data);
646-
return 1;
609+
return NULL;
647610
}
648611

649-
strm.next_out = output_data;
650-
strm.avail_out = UINT_CLAMP (out_alloc);
612+
strm.next_out = buf;
613+
strm.avail_out = UINT_CLAMP (alloc);
614+
int ok = 0;
651615

652-
/* Decompress */
653616
while (1) {
654-
ret = inflate (&strm, Z_NO_FLUSH);
617+
int ret = inflate (&strm, Z_NO_FLUSH);
655618
if (ret == Z_STREAM_END) {
619+
ok = 1;
656620
break;
657621
}
658622
if (ret == Z_BUF_ERROR) {
659-
/* Refill clamped input */
660623
if (strm.avail_in == 0) {
661624
size_t consumed = (size_t)(strm.next_in - input_data);
662625
if (consumed < input_size) {
663626
strm.avail_in = UINT_CLAMP (input_size - consumed);
664627
continue;
665628
}
666-
/* All input consumed with output space available: truncated */
667629
if (strm.avail_out > 0) {
668630
fprintf (stderr, "inflate failed: truncated input\n");
669-
inflateEnd (&strm);
670-
free (output_data);
671-
free (input_data);
672-
return 1;
631+
break;
673632
}
674633
}
675-
/* Grow or refill output buffer */
676-
size_t produced = (size_t)(strm.next_out - output_data);
677-
if (produced >= out_alloc) {
678-
if (out_alloc > SIZE_MAX / 2) {
634+
size_t produced = (size_t)(strm.next_out - buf);
635+
if (produced >= alloc) {
636+
if (alloc > SIZE_MAX / 2) {
679637
fprintf (stderr, "Output buffer too large\n");
680-
inflateEnd (&strm);
681-
free (output_data);
682-
free (input_data);
683-
return 1;
638+
break;
684639
}
685-
size_t new_alloc = out_alloc * 2;
686-
uint8_t *new_buf = (uint8_t *)realloc (output_data, new_alloc);
640+
size_t new_alloc = alloc * 2;
641+
uint8_t *new_buf = (uint8_t *)realloc (buf, new_alloc);
687642
if (!new_buf) {
688643
fprintf (stderr, "Out of memory expanding output buffer\n");
689-
inflateEnd (&strm);
690-
free (output_data);
691-
free (input_data);
692-
return 1;
644+
break;
693645
}
694-
output_data = new_buf;
695-
out_alloc = new_alloc;
646+
buf = new_buf;
647+
alloc = new_alloc;
696648
}
697-
strm.next_out = output_data + produced;
698-
strm.avail_out = UINT_CLAMP (out_alloc - produced);
649+
strm.next_out = buf + produced;
650+
strm.avail_out = UINT_CLAMP (alloc - produced);
699651
continue;
700652
}
701653
if (ret != Z_OK) {
702-
fprintf (stderr, "inflate failed: %d (avail_in=%u avail_out=%u total_out=%lu)\n", ret, strm.avail_in, strm.avail_out, (unsigned long)strm.total_out);
703-
inflateEnd (&strm);
704-
free (output_data);
705-
free (input_data);
706-
return 1;
654+
fprintf (stderr, "inflate failed: %d (avail_in=%u avail_out=%u total_out=%lu)\n",
655+
ret, strm.avail_in, strm.avail_out, (unsigned long)strm.total_out);
656+
break;
707657
}
708658
}
709659

710-
size_t output_size = (size_t)(strm.next_out - output_data);
660+
*out_size = (size_t)(strm.next_out - buf);
711661
inflateEnd (&strm);
662+
if (!ok) {
663+
free (buf);
664+
return NULL;
665+
}
666+
return buf;
667+
}
668+
669+
/* Deflate (compress) a buffer with gzip framing.
670+
* Returns a malloc'd buffer on success (caller frees), NULL on failure.
671+
* Sets *out_size to the compressed size on success. */
672+
static uint8_t *deflate_to_gzip(const uint8_t *input_data, size_t input_size, size_t *out_size) {
673+
z_stream strm;
674+
memset (&strm, 0, sizeof (strm));
675+
676+
if (deflateInit2 (&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
677+
fprintf (stderr, "deflateInit2 failed\n");
678+
return NULL;
679+
}
680+
681+
size_t alloc = input_size + (input_size / 8) + 128;
682+
if (alloc < 256) {
683+
alloc = 256;
684+
}
685+
uint8_t *buf = (uint8_t *)malloc (alloc);
686+
if (!buf) {
687+
fprintf (stderr, "Out of memory for output buffer\n");
688+
deflateEnd (&strm);
689+
return NULL;
690+
}
691+
692+
strm.next_in = (uint8_t *)input_data;
693+
strm.avail_in = UINT_CLAMP (input_size);
694+
strm.next_out = buf;
695+
strm.avail_out = UINT_CLAMP (alloc);
696+
697+
int ret = deflate (&strm, Z_FINISH);
698+
*out_size = (size_t)(strm.next_out - buf);
699+
deflateEnd (&strm);
700+
if (ret != Z_STREAM_END) {
701+
fprintf (stderr, "deflate failed: %d\n", ret);
702+
free (buf);
703+
return NULL;
704+
}
705+
return buf;
706+
}
707+
708+
/* Decompress a gzip file (gunzip mode) */
709+
static int gunzip_file(const char *input_path, const char *output_path) {
710+
FILE *fin = fopen (input_path, "rb");
711+
if (!fin) {
712+
fprintf (stderr, "Cannot open input file: %s\n", input_path);
713+
return 1;
714+
}
715+
716+
fseek (fin, 0, SEEK_END);
717+
long fsize = ftell (fin);
718+
fseek (fin, 0, SEEK_SET);
719+
720+
if (fsize <= 0) {
721+
fprintf (stderr, "Invalid input file size\n");
722+
fclose (fin);
723+
return 1;
724+
}
725+
size_t input_size = (size_t)fsize;
726+
727+
uint8_t *input_data = (uint8_t *)malloc (input_size);
728+
if (!input_data) {
729+
fprintf (stderr, "Out of memory\n");
730+
fclose (fin);
731+
return 1;
732+
}
733+
734+
if (fread (input_data, 1, input_size, fin) != input_size) {
735+
fprintf (stderr, "Failed to read input file\n");
736+
free (input_data);
737+
fclose (fin);
738+
return 1;
739+
}
740+
fclose (fin);
741+
742+
size_t output_size = 0;
743+
uint8_t *output_data = inflate_buffer (input_data, input_size, &output_size);
712744
free (input_data);
745+
if (!output_data) {
746+
return 1;
747+
}
713748

714-
/* Write output */
715749
FILE *fout = fopen (output_path, "wb");
716750
if (!fout) {
717751
fprintf (stderr, "Cannot create output file: %s\n", output_path);
@@ -728,12 +762,8 @@ static int gunzip_file(const char *input_path, const char *output_path) {
728762

729763
fclose (fout);
730764
free (output_data);
731-
732765
printf ("Decompressed %s -> %s (%ld -> %lu bytes)\n",
733-
input_path,
734-
output_path,
735-
fsize,
736-
(unsigned long)output_size);
766+
input_path, output_path, fsize, (unsigned long)output_size);
737767
return 0;
738768
}
739769

@@ -745,7 +775,6 @@ static int gzip_file(const char *input_path, const char *output_path) {
745775
return 1;
746776
}
747777

748-
/* Read entire input file */
749778
fseek (fin, 0, SEEK_END);
750779
long fsize = ftell (fin);
751780
fseek (fin, 0, SEEK_SET);
@@ -774,50 +803,13 @@ static int gzip_file(const char *input_path, const char *output_path) {
774803
}
775804
fclose (fin);
776805

777-
/* Initialize deflate for gzip output (MAX_WBITS + 16) */
778-
z_stream strm;
779-
memset (&strm, 0, sizeof (strm));
780-
781-
int ret = deflateInit2 (&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY);
782-
if (ret != Z_OK) {
783-
fprintf (stderr, "deflateInit2 failed: %d\n", ret);
784-
free (input_data);
785-
return 1;
786-
}
787-
788-
/* Allocate output buffer */
789-
size_t out_alloc = input_size + (input_size / 8) + 128;
790-
if (out_alloc < 256) {
791-
out_alloc = 256;
792-
}
793-
uint8_t *output_data = (uint8_t *)malloc (out_alloc);
806+
size_t output_size = 0;
807+
uint8_t *output_data = deflate_to_gzip (input_data, input_size, &output_size);
808+
free (input_data);
794809
if (!output_data) {
795-
fprintf (stderr, "Out of memory for output buffer\n");
796-
deflateEnd (&strm);
797-
free (input_data);
798810
return 1;
799811
}
800812

801-
strm.next_in = input_data;
802-
strm.avail_in = UINT_CLAMP (input_size);
803-
strm.next_out = output_data;
804-
strm.avail_out = UINT_CLAMP (out_alloc);
805-
806-
/* Compress */
807-
ret = deflate (&strm, Z_FINISH);
808-
if (ret != Z_STREAM_END) {
809-
fprintf (stderr, "deflate failed: %d\n", ret);
810-
deflateEnd (&strm);
811-
free (output_data);
812-
free (input_data);
813-
return 1;
814-
}
815-
816-
size_t output_size = (size_t)(strm.next_out - output_data);
817-
deflateEnd (&strm);
818-
free (input_data);
819-
820-
/* Write output */
821813
FILE *fout = fopen (output_path, "wb");
822814
if (!fout) {
823815
fprintf (stderr, "Cannot create output file: %s\n", output_path);
@@ -834,12 +826,8 @@ static int gzip_file(const char *input_path, const char *output_path) {
834826

835827
fclose (fout);
836828
free (output_data);
837-
838829
printf ("Compressed %s -> %s (%ld -> %lu bytes)\n",
839-
input_path,
840-
output_path,
841-
fsize,
842-
(unsigned long)output_size);
830+
input_path, output_path, fsize, (unsigned long)output_size);
843831
return 0;
844832
}
845833

0 commit comments

Comments
 (0)