|           Line data    Source code 
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * compress_none.c
       4             :  *   Routines for archivers to read or write an uncompressed stream.
       5             :  *
       6             :  * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  * IDENTIFICATION
      10             :  *     src/bin/pg_dump/compress_none.c
      11             :  *
      12             :  *-------------------------------------------------------------------------
      13             :  */
      14             : #include "postgres_fe.h"
      15             : #include <unistd.h>
      16             : 
      17             : #include "compress_none.h"
      18             : #include "pg_backup_utils.h"
      19             : 
      20             : /*----------------------
      21             :  * Compressor API
      22             :  *----------------------
      23             :  */
      24             : 
      25             : /*
      26             :  * We buffer outgoing data, just to ensure that data blocks written to the
      27             :  * archive file are of reasonable size.  The read side could use this struct,
      28             :  * but there's no need because it does not retain data across calls.
      29             :  */
      30             : typedef struct NoneCompressorState
      31             : {
      32             :     char       *buffer;         /* buffer for unwritten data */
      33             :     size_t      buflen;         /* allocated size of buffer */
      34             :     size_t      bufdata;        /* amount of valid data currently in buffer */
      35             : } NoneCompressorState;
      36             : 
      37             : /*
      38             :  * Private routines
      39             :  */
      40             : 
      41             : static void
      42           6 : ReadDataFromArchiveNone(ArchiveHandle *AH, CompressorState *cs)
      43             : {
      44             :     size_t      cnt;
      45             :     char       *buf;
      46             :     size_t      buflen;
      47             : 
      48           6 :     buflen = DEFAULT_IO_BUFFER_SIZE;
      49           6 :     buf = pg_malloc(buflen);
      50             : 
      51          16 :     while ((cnt = cs->readF(AH, &buf, &buflen)))
      52             :     {
      53          10 :         ahwrite(buf, 1, cnt, AH);
      54             :     }
      55             : 
      56           6 :     free(buf);
      57           6 : }
      58             : 
      59             : 
      60             : static void
      61           8 : WriteDataToArchiveNone(ArchiveHandle *AH, CompressorState *cs,
      62             :                        const void *data, size_t dLen)
      63             : {
      64           8 :     NoneCompressorState *nonecs = (NoneCompressorState *) cs->private_data;
      65           8 :     size_t      remaining = dLen;
      66             : 
      67          20 :     while (remaining > 0)
      68             :     {
      69             :         size_t      chunk;
      70             : 
      71             :         /* Dump buffer if full */
      72          12 :         if (nonecs->bufdata >= nonecs->buflen)
      73             :         {
      74           4 :             cs->writeF(AH, nonecs->buffer, nonecs->bufdata);
      75           4 :             nonecs->bufdata = 0;
      76             :         }
      77             :         /* And fill it */
      78          12 :         chunk = nonecs->buflen - nonecs->bufdata;
      79          12 :         if (chunk > remaining)
      80           8 :             chunk = remaining;
      81          12 :         memcpy(nonecs->buffer + nonecs->bufdata, data, chunk);
      82          12 :         nonecs->bufdata += chunk;
      83          12 :         data = ((const char *) data) + chunk;
      84          12 :         remaining -= chunk;
      85             :     }
      86           8 : }
      87             : 
      88             : static void
      89          12 : EndCompressorNone(ArchiveHandle *AH, CompressorState *cs)
      90             : {
      91          12 :     NoneCompressorState *nonecs = (NoneCompressorState *) cs->private_data;
      92             : 
      93          12 :     if (nonecs)
      94             :     {
      95             :         /* Dump buffer if nonempty */
      96           6 :         if (nonecs->bufdata > 0)
      97           6 :             cs->writeF(AH, nonecs->buffer, nonecs->bufdata);
      98             :         /* Free working state */
      99           6 :         pg_free(nonecs->buffer);
     100           6 :         pg_free(nonecs);
     101           6 :         cs->private_data = NULL;
     102             :     }
     103          12 : }
     104             : 
     105             : /*
     106             :  * Public interface
     107             :  */
     108             : 
     109             : void
     110          12 : InitCompressorNone(CompressorState *cs,
     111             :                    const pg_compress_specification compression_spec)
     112             : {
     113          12 :     cs->readData = ReadDataFromArchiveNone;
     114          12 :     cs->writeData = WriteDataToArchiveNone;
     115          12 :     cs->end = EndCompressorNone;
     116             : 
     117          12 :     cs->compression_spec = compression_spec;
     118             : 
     119             :     /*
     120             :      * If the caller has defined a write function, prepare the necessary
     121             :      * buffer.
     122             :      */
     123          12 :     if (cs->writeF)
     124             :     {
     125             :         NoneCompressorState *nonecs;
     126             : 
     127           6 :         nonecs = (NoneCompressorState *) pg_malloc(sizeof(NoneCompressorState));
     128           6 :         nonecs->buflen = DEFAULT_IO_BUFFER_SIZE;
     129           6 :         nonecs->buffer = pg_malloc(nonecs->buflen);
     130           6 :         nonecs->bufdata = 0;
     131             : 
     132           6 :         cs->private_data = nonecs;
     133             :     }
     134          12 : }
     135             : 
     136             : 
     137             : /*----------------------
     138             :  * Compress File API
     139             :  *----------------------
     140             :  */
     141             : 
     142             : /*
     143             :  * Private routines
     144             :  */
     145             : 
     146             : static size_t
     147       29574 : read_none(void *ptr, size_t size, CompressFileHandle *CFH)
     148             : {
     149       29574 :     FILE       *fp = (FILE *) CFH->private_data;
     150             :     size_t      ret;
     151             : 
     152       29574 :     ret = fread(ptr, 1, size, fp);
     153       29574 :     if (ferror(fp))
     154           0 :         pg_fatal("could not read from input file: %m");
     155             : 
     156       29574 :     return ret;
     157             : }
     158             : 
     159             : static void
     160     4242886 : write_none(const void *ptr, size_t size, CompressFileHandle *CFH)
     161             : {
     162             :     size_t      ret;
     163             : 
     164     4242886 :     errno = 0;
     165     4242886 :     ret = fwrite(ptr, 1, size, (FILE *) CFH->private_data);
     166     4242886 :     if (ret != size)
     167             :     {
     168           0 :         errno = (errno) ? errno : ENOSPC;
     169           0 :         pg_fatal("could not write to file: %m");
     170             :     }
     171     4242886 : }
     172             : 
     173             : static const char *
     174           0 : get_error_none(CompressFileHandle *CFH)
     175             : {
     176           0 :     return strerror(errno);
     177             : }
     178             : 
     179             : static char *
     180          16 : gets_none(char *ptr, int size, CompressFileHandle *CFH)
     181             : {
     182          16 :     return fgets(ptr, size, (FILE *) CFH->private_data);
     183             : }
     184             : 
     185             : static int
     186      263270 : getc_none(CompressFileHandle *CFH)
     187             : {
     188      263270 :     FILE       *fp = (FILE *) CFH->private_data;
     189             :     int         ret;
     190             : 
     191      263270 :     ret = fgetc(fp);
     192      263270 :     if (ret == EOF)
     193             :     {
     194           0 :         if (!feof(fp))
     195           0 :             pg_fatal("could not read from input file: %m");
     196             :         else
     197           0 :             pg_fatal("could not read from input file: end of file");
     198             :     }
     199             : 
     200      263270 :     return ret;
     201             : }
     202             : 
     203             : static bool
     204         826 : close_none(CompressFileHandle *CFH)
     205             : {
     206         826 :     FILE       *fp = (FILE *) CFH->private_data;
     207         826 :     int         ret = 0;
     208             : 
     209         826 :     CFH->private_data = NULL;
     210             : 
     211         826 :     if (fp)
     212             :     {
     213         826 :         errno = 0;
     214         826 :         ret = fclose(fp);
     215         826 :         if (ret != 0)
     216           0 :             pg_log_error("could not close file: %m");
     217             :     }
     218             : 
     219         826 :     return ret == 0;
     220             : }
     221             : 
     222             : static bool
     223           8 : eof_none(CompressFileHandle *CFH)
     224             : {
     225           8 :     return feof((FILE *) CFH->private_data) != 0;
     226             : }
     227             : 
     228             : static bool
     229         836 : open_none(const char *path, int fd, const char *mode, CompressFileHandle *CFH)
     230             : {
     231             :     Assert(CFH->private_data == NULL);
     232             : 
     233         836 :     if (fd >= 0)
     234         528 :         CFH->private_data = fdopen(dup(fd), mode);
     235             :     else
     236         308 :         CFH->private_data = fopen(path, mode);
     237             : 
     238         836 :     if (CFH->private_data == NULL)
     239           0 :         return false;
     240             : 
     241         836 :     return true;
     242             : }
     243             : 
     244             : static bool
     245          32 : open_write_none(const char *path, const char *mode, CompressFileHandle *CFH)
     246             : {
     247             :     Assert(CFH->private_data == NULL);
     248             : 
     249          32 :     CFH->private_data = fopen(path, mode);
     250          32 :     if (CFH->private_data == NULL)
     251           0 :         return false;
     252             : 
     253          32 :     return true;
     254             : }
     255             : 
     256             : /*
     257             :  * Public interface
     258             :  */
     259             : 
     260             : void
     261         868 : InitCompressFileHandleNone(CompressFileHandle *CFH,
     262             :                            const pg_compress_specification compression_spec)
     263             : {
     264         868 :     CFH->open_func = open_none;
     265         868 :     CFH->open_write_func = open_write_none;
     266         868 :     CFH->read_func = read_none;
     267         868 :     CFH->write_func = write_none;
     268         868 :     CFH->gets_func = gets_none;
     269         868 :     CFH->getc_func = getc_none;
     270         868 :     CFH->close_func = close_none;
     271         868 :     CFH->eof_func = eof_none;
     272         868 :     CFH->get_error_func = get_error_none;
     273             : 
     274         868 :     CFH->private_data = NULL;
     275         868 : }
 |