@@ -452,13 +452,25 @@ struct cfp
452452static int hasSuffix (const char * filename , const char * suffix );
453453#endif
454454
455+ /* free() without changing errno; useful in several places below */
456+ static void
457+ free_keep_errno (void * p )
458+ {
459+ int save_errno = errno ;
460+
461+ free (p );
462+ errno = save_errno ;
463+ }
464+
455465/*
456466 * Open a file for reading. 'path' is the file to open, and 'mode' should
457467 * be either "r" or "rb".
458468 *
459469 * If the file at 'path' does not exist, we append the ".gz" suffix (if 'path'
460470 * doesn't already have it) and try again. So if you pass "foo" as 'path',
461471 * this will open either "foo" or "foo.gz".
472+ *
473+ * On failure, return NULL with an error code in errno.
462474 */
463475cfp *
464476cfopen_read (const char * path , const char * mode )
@@ -479,7 +491,7 @@ cfopen_read(const char *path, const char *mode)
479491
480492 fname = psprintf ("%s.gz" , path );
481493 fp = cfopen (fname , mode , 1 );
482- free (fname );
494+ free_keep_errno (fname );
483495 }
484496#endif
485497 }
@@ -492,8 +504,10 @@ cfopen_read(const char *path, const char *mode)
492504 * ("w", "wb", "a", or "ab").
493505 *
494506 * If 'compression' is non-zero, a gzip compressed stream is opened, and
495- * and 'compression' indicates the compression level used. The ".gz" suffix
507+ * 'compression' indicates the compression level used. The ".gz" suffix
496508 * is automatically added to 'path' in that case.
509+ *
510+ * On failure, return NULL with an error code in errno.
497511 */
498512cfp *
499513cfopen_write (const char * path , const char * mode , int compression )
@@ -508,8 +522,8 @@ cfopen_write(const char *path, const char *mode, int compression)
508522 char * fname ;
509523
510524 fname = psprintf ("%s.gz" , path );
511- fp = cfopen (fname , mode , 1 );
512- free (fname );
525+ fp = cfopen (fname , mode , compression );
526+ free_keep_errno (fname );
513527#else
514528 exit_horribly (modulename , "not built with zlib support\n" );
515529 fp = NULL ; /* keep compiler quiet */
@@ -520,7 +534,9 @@ cfopen_write(const char *path, const char *mode, int compression)
520534
521535/*
522536 * Opens file 'path' in 'mode'. If 'compression' is non-zero, the file
523- * is opened with libz gzopen(), otherwise with plain fopen()
537+ * is opened with libz gzopen(), otherwise with plain fopen().
538+ *
539+ * On failure, return NULL with an error code in errno.
524540 */
525541cfp *
526542cfopen (const char * path , const char * mode , int compression )
@@ -530,11 +546,15 @@ cfopen(const char *path, const char *mode, int compression)
530546 if (compression != 0 )
531547 {
532548#ifdef HAVE_LIBZ
533- fp -> compressedfp = gzopen (path , mode );
549+ char mode_compression [32 ];
550+
551+ snprintf (mode_compression , sizeof (mode_compression ), "%s%d" ,
552+ mode , compression );
553+ fp -> compressedfp = gzopen (path , mode_compression );
534554 fp -> uncompressedfp = NULL ;
535555 if (fp -> compressedfp == NULL )
536556 {
537- free (fp );
557+ free_keep_errno (fp );
538558 fp = NULL ;
539559 }
540560#else
@@ -549,7 +569,7 @@ cfopen(const char *path, const char *mode, int compression)
549569 fp -> uncompressedfp = fopen (path , mode );
550570 if (fp -> uncompressedfp == NULL )
551571 {
552- free (fp );
572+ free_keep_errno (fp );
553573 fp = NULL ;
554574 }
555575 }
@@ -658,7 +678,7 @@ cfclose(cfp *fp)
658678 result = fclose (fp -> uncompressedfp );
659679 fp -> uncompressedfp = NULL ;
660680 }
661- free (fp );
681+ free_keep_errno (fp );
662682
663683 return result ;
664684}
0 commit comments