5656#include "compress_io.h"
5757#include "pg_backup_utils.h"
5858
59+ #ifdef HAVE_LIBZ
60+ #include <zlib.h>
61+ #endif
62+
63+ /*----------------------
64+ * Generic functions
65+ *----------------------
66+ */
67+
68+ /*
69+ * Checks whether a compression algorithm is supported.
70+ *
71+ * On success returns NULL, otherwise returns a malloc'ed string which can be
72+ * used by the caller in an error message.
73+ */
74+ char *
75+ supports_compression (const pg_compress_specification compression_spec )
76+ {
77+ const pg_compress_algorithm algorithm = compression_spec .algorithm ;
78+ bool supported = false;
79+
80+ if (algorithm == PG_COMPRESSION_NONE )
81+ supported = true;
82+ #ifdef HAVE_LIBZ
83+ if (algorithm == PG_COMPRESSION_GZIP )
84+ supported = true;
85+ #endif
86+
87+ if (!supported )
88+ return psprintf ("this build does not support compression with %s" ,
89+ get_compress_algorithm_name (algorithm ));
90+
91+ return NULL ;
92+ }
93+
5994/*----------------------
6095 * Compressor API
6196 *----------------------
@@ -490,16 +525,19 @@ cfopen_write(const char *path, const char *mode,
490525}
491526
492527/*
493- * Opens file 'path' in 'mode'. If compression is GZIP, the file
494- * is opened with libz gzopen(), otherwise with plain fopen().
528+ * This is the workhorse for cfopen() or cfdopen(). It opens file 'path' or
529+ * associates a stream 'fd', if 'fd' is a valid descriptor, in 'mode'. The
530+ * descriptor is not dup'ed and it is the caller's responsibility to do so.
531+ * The caller must verify that the 'compress_algorithm' is supported by the
532+ * current build.
495533 *
496534 * On failure, return NULL with an error code in errno.
497535 */
498- cfp *
499- cfopen (const char * path , const char * mode ,
500- const pg_compress_specification compression_spec )
536+ static cfp *
537+ cfopen_internal (const char * path , int fd , const char * mode ,
538+ pg_compress_specification compression_spec )
501539{
502- cfp * fp = pg_malloc (sizeof (cfp ));
540+ cfp * fp = pg_malloc0 (sizeof (cfp ));
503541
504542 if (compression_spec .algorithm == PG_COMPRESSION_GZIP )
505543 {
@@ -511,15 +549,20 @@ cfopen(const char *path, const char *mode,
511549
512550 snprintf (mode_compression , sizeof (mode_compression ), "%s%d" ,
513551 mode , compression_spec .level );
514- fp -> compressedfp = gzopen (path , mode_compression );
552+ if (fd >= 0 )
553+ fp -> compressedfp = gzdopen (fd , mode_compression );
554+ else
555+ fp -> compressedfp = gzopen (path , mode_compression );
515556 }
516557 else
517558 {
518559 /* don't specify a level, just use the zlib default */
519- fp -> compressedfp = gzopen (path , mode );
560+ if (fd >= 0 )
561+ fp -> compressedfp = gzdopen (fd , mode );
562+ else
563+ fp -> compressedfp = gzopen (path , mode );
520564 }
521565
522- fp -> uncompressedfp = NULL ;
523566 if (fp -> compressedfp == NULL )
524567 {
525568 free_keep_errno (fp );
@@ -531,10 +574,11 @@ cfopen(const char *path, const char *mode,
531574 }
532575 else
533576 {
534- #ifdef HAVE_LIBZ
535- fp -> compressedfp = NULL ;
536- #endif
537- fp -> uncompressedfp = fopen (path , mode );
577+ if (fd >= 0 )
578+ fp -> uncompressedfp = fdopen (fd , mode );
579+ else
580+ fp -> uncompressedfp = fopen (path , mode );
581+
538582 if (fp -> uncompressedfp == NULL )
539583 {
540584 free_keep_errno (fp );
@@ -545,6 +589,33 @@ cfopen(const char *path, const char *mode,
545589 return fp ;
546590}
547591
592+ /*
593+ * Opens file 'path' in 'mode' and compression as defined in
594+ * compression_spec. The caller must verify that the compression
595+ * is supported by the current build.
596+ *
597+ * On failure, return NULL with an error code in errno.
598+ */
599+ cfp *
600+ cfopen (const char * path , const char * mode ,
601+ const pg_compress_specification compression_spec )
602+ {
603+ return cfopen_internal (path , -1 , mode , compression_spec );
604+ }
605+
606+ /*
607+ * Associates a stream 'fd', if 'fd' is a valid descriptor, in 'mode'
608+ * and compression as defined in compression_spec. The caller must
609+ * verify that the compression is supported by the current build.
610+ *
611+ * On failure, return NULL with an error code in errno.
612+ */
613+ cfp *
614+ cfdopen (int fd , const char * mode ,
615+ const pg_compress_specification compression_spec )
616+ {
617+ return cfopen_internal (NULL , fd , mode , compression_spec );
618+ }
548619
549620int
550621cfread (void * ptr , int size , cfp * fp )
0 commit comments