@@ -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
480492fname = psprintf ("%s.gz" ,path );
481493fp = 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)
508522char * fname ;
509523
510524fname = 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
514528exit_horribly (modulename ,"not built with zlib support\n" );
515529fp = 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)
530546if (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 );
534554fp -> uncompressedfp = NULL ;
535555if (fp -> compressedfp == NULL )
536556{
537- free (fp );
557+ free_keep_errno (fp );
538558fp = NULL ;
539559}
540560#else
@@ -549,7 +569,7 @@ cfopen(const char *path, const char *mode, int compression)
549569fp -> uncompressedfp = fopen (path ,mode );
550570if (fp -> uncompressedfp == NULL )
551571{
552- free (fp );
572+ free_keep_errno (fp );
553573fp = NULL ;
554574}
555575}
@@ -658,7 +678,7 @@ cfclose(cfp *fp)
658678result = fclose (fp -> uncompressedfp );
659679fp -> uncompressedfp = NULL ;
660680}
661- free (fp );
681+ free_keep_errno (fp );
662682
663683return result ;
664684}