Skip to content

Commit a7ad5cf

Browse files
committed
Fix failure to honor -Z compression level option in pg_dump -Fd.
cfopen() and cfopen_write() failed to pass the compression level through to zlib, so that you always got the default compression level if you got any at all. In passing, also fix these and related functions so that the correct errno is reliably returned on failure; the original coding supposes that free() cannot change errno, which is untrue on at least some platforms. Per bug #12779 from Christoph Berg. Back-patch to 9.1 where the faulty code was introduced. Michael Paquier
1 parent 4ea2d2d commit a7ad5cf

File tree

1 file changed

+29
-9
lines changed

1 file changed

+29
-9
lines changed

src/bin/pg_dump/compress_io.c

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -464,13 +464,25 @@ struct cfp
464464
static int hasSuffix(const char *filename, const char *suffix);
465465
#endif
466466

467+
/* free() without changing errno; useful in several places below */
468+
static void
469+
free_keep_errno(void *p)
470+
{
471+
int save_errno = errno;
472+
473+
free(p);
474+
errno = save_errno;
475+
}
476+
467477
/*
468478
* Open a file for reading. 'path' is the file to open, and 'mode' should
469479
* be either "r" or "rb".
470480
*
471481
* If the file at 'path' does not exist, we append the ".gz" suffix (if 'path'
472482
* doesn't already have it) and try again. So if you pass "foo" as 'path',
473483
* this will open either "foo" or "foo.gz".
484+
*
485+
* On failure, return NULL with an error code in errno.
474486
*/
475487
cfp *
476488
cfopen_read(const char *path, const char *mode)
@@ -492,7 +504,7 @@ cfopen_read(const char *path, const char *mode)
492504

493505
snprintf(fname, fnamelen, "%s%s", path, ".gz");
494506
fp = cfopen(fname, mode, 1);
495-
free(fname);
507+
free_keep_errno(fname);
496508
}
497509
#endif
498510
}
@@ -505,8 +517,10 @@ cfopen_read(const char *path, const char *mode)
505517
* ("w", "wb", "a", or "ab").
506518
*
507519
* If 'compression' is non-zero, a gzip compressed stream is opened, and
508-
* and 'compression' indicates the compression level used. The ".gz" suffix
520+
* 'compression' indicates the compression level used. The ".gz" suffix
509521
* is automatically added to 'path' in that case.
522+
*
523+
* On failure, return NULL with an error code in errno.
510524
*/
511525
cfp *
512526
cfopen_write(const char *path, const char *mode, int compression)
@@ -522,8 +536,8 @@ cfopen_write(const char *path, const char *mode, int compression)
522536
char *fname = pg_malloc(fnamelen);
523537

524538
snprintf(fname, fnamelen, "%s%s", path, ".gz");
525-
fp = cfopen(fname, mode, 1);
526-
free(fname);
539+
fp = cfopen(fname, mode, compression);
540+
free_keep_errno(fname);
527541
#else
528542
exit_horribly(modulename, "not built with zlib support\n");
529543
fp = NULL; /* keep compiler quiet */
@@ -534,7 +548,9 @@ cfopen_write(const char *path, const char *mode, int compression)
534548

535549
/*
536550
* Opens file 'path' in 'mode'. If 'compression' is non-zero, the file
537-
* is opened with libz gzopen(), otherwise with plain fopen()
551+
* is opened with libz gzopen(), otherwise with plain fopen().
552+
*
553+
* On failure, return NULL with an error code in errno.
538554
*/
539555
cfp *
540556
cfopen(const char *path, const char *mode, int compression)
@@ -544,11 +560,15 @@ cfopen(const char *path, const char *mode, int compression)
544560
if (compression != 0)
545561
{
546562
#ifdef HAVE_LIBZ
547-
fp->compressedfp = gzopen(path, mode);
563+
char mode_compression[32];
564+
565+
snprintf(mode_compression, sizeof(mode_compression), "%s%d",
566+
mode, compression);
567+
fp->compressedfp = gzopen(path, mode_compression);
548568
fp->uncompressedfp = NULL;
549569
if (fp->compressedfp == NULL)
550570
{
551-
free(fp);
571+
free_keep_errno(fp);
552572
fp = NULL;
553573
}
554574
#else
@@ -563,7 +583,7 @@ cfopen(const char *path, const char *mode, int compression)
563583
fp->uncompressedfp = fopen(path, mode);
564584
if (fp->uncompressedfp == NULL)
565585
{
566-
free(fp);
586+
free_keep_errno(fp);
567587
fp = NULL;
568588
}
569589
}
@@ -638,7 +658,7 @@ cfclose(cfp *fp)
638658
result = fclose(fp->uncompressedfp);
639659
fp->uncompressedfp = NULL;
640660
}
641-
free(fp);
661+
free_keep_errno(fp);
642662

643663
return result;
644664
}

0 commit comments

Comments
 (0)