@@ -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