Age Owner Branch data TLA 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
977 tomas.vondra@postgre 42 :GBC 3 : ReadDataFromArchiveNone(ArchiveHandle *AH, CompressorState *cs)
43 : : {
44 : : size_t cnt;
45 : : char *buf;
46 : : size_t buflen;
47 : :
949 48 : 3 : buflen = DEFAULT_IO_BUFFER_SIZE;
49 : 3 : buf = pg_malloc(buflen);
50 : :
977 51 [ + + ]: 8 : while ((cnt = cs->readF(AH, &buf, &buflen)))
52 : : {
53 : 5 : ahwrite(buf, 1, cnt, AH);
54 : : }
55 : :
56 : 3 : free(buf);
57 : 3 : }
58 : :
59 : :
60 : : static void
61 : 4 : WriteDataToArchiveNone(ArchiveHandle *AH, CompressorState *cs,
62 : : const void *data, size_t dLen)
63 : : {
11 tgl@sss.pgh.pa.us 64 :GNC 4 : NoneCompressorState *nonecs = (NoneCompressorState *) cs->private_data;
65 : 4 : size_t remaining = dLen;
66 : :
67 [ + + ]: 10 : while (remaining > 0)
68 : : {
69 : : size_t chunk;
70 : :
71 : : /* Dump buffer if full */
72 [ + + ]: 6 : if (nonecs->bufdata >= nonecs->buflen)
73 : : {
74 : 2 : cs->writeF(AH, nonecs->buffer, nonecs->bufdata);
75 : 2 : nonecs->bufdata = 0;
76 : : }
77 : : /* And fill it */
78 : 6 : chunk = nonecs->buflen - nonecs->bufdata;
79 [ + + ]: 6 : if (chunk > remaining)
80 : 4 : chunk = remaining;
81 : 6 : memcpy(nonecs->buffer + nonecs->bufdata, data, chunk);
82 : 6 : nonecs->bufdata += chunk;
83 : 6 : data = ((const char *) data) + chunk;
84 : 6 : remaining -= chunk;
85 : : }
977 tomas.vondra@postgre 86 :GBC 4 : }
87 : :
88 : : static void
89 : 6 : EndCompressorNone(ArchiveHandle *AH, CompressorState *cs)
90 : : {
11 tgl@sss.pgh.pa.us 91 :GNC 6 : NoneCompressorState *nonecs = (NoneCompressorState *) cs->private_data;
92 : :
93 [ + + ]: 6 : if (nonecs)
94 : : {
95 : : /* Dump buffer if nonempty */
96 [ + - ]: 3 : if (nonecs->bufdata > 0)
97 : 3 : cs->writeF(AH, nonecs->buffer, nonecs->bufdata);
98 : : /* Free working state */
99 : 3 : pg_free(nonecs->buffer);
100 : 3 : pg_free(nonecs);
101 : 3 : cs->private_data = NULL;
102 : : }
977 tomas.vondra@postgre 103 :GBC 6 : }
104 : :
105 : : /*
106 : : * Public interface
107 : : */
108 : :
109 : : void
110 : 6 : InitCompressorNone(CompressorState *cs,
111 : : const pg_compress_specification compression_spec)
112 : : {
113 : 6 : cs->readData = ReadDataFromArchiveNone;
114 : 6 : cs->writeData = WriteDataToArchiveNone;
115 : 6 : cs->end = EndCompressorNone;
116 : :
117 : 6 : cs->compression_spec = compression_spec;
118 : :
119 : : /*
120 : : * If the caller has defined a write function, prepare the necessary
121 : : * buffer.
122 : : */
11 tgl@sss.pgh.pa.us 123 [ + + ]:GNC 6 : if (cs->writeF)
124 : : {
125 : : NoneCompressorState *nonecs;
126 : :
127 : 3 : nonecs = (NoneCompressorState *) pg_malloc(sizeof(NoneCompressorState));
128 : 3 : nonecs->buflen = DEFAULT_IO_BUFFER_SIZE;
129 : 3 : nonecs->buffer = pg_malloc(nonecs->buflen);
130 : 3 : nonecs->bufdata = 0;
131 : :
132 : 3 : cs->private_data = nonecs;
133 : : }
977 tomas.vondra@postgre 134 :GBC 6 : }
135 : :
136 : :
137 : : /*----------------------
138 : : * Compress File API
139 : : *----------------------
140 : : */
141 : :
142 : : /*
143 : : * Private routines
144 : : */
145 : :
146 : : static size_t
59 dgustafsson@postgres 147 :CBC 14787 : read_none(void *ptr, size_t size, CompressFileHandle *CFH)
148 : : {
977 tomas.vondra@postgre 149 : 14787 : FILE *fp = (FILE *) CFH->private_data;
150 : : size_t ret;
151 : :
152 : 14787 : ret = fread(ptr, 1, size, fp);
59 dgustafsson@postgres 153 [ - + ]: 14787 : if (ferror(fp))
594 michael@paquier.xyz 154 :UBC 0 : pg_fatal("could not read from input file: %m");
155 : :
59 dgustafsson@postgres 156 :CBC 14787 : return ret;
157 : : }
158 : :
159 : : static void
977 tomas.vondra@postgre 160 : 2138998 : write_none(const void *ptr, size_t size, CompressFileHandle *CFH)
161 : : {
162 : : size_t ret;
163 : :
59 dgustafsson@postgres 164 : 2138998 : errno = 0;
949 tomas.vondra@postgre 165 : 2138998 : ret = fwrite(ptr, 1, size, (FILE *) CFH->private_data);
166 [ - + ]: 2138998 : if (ret != size)
167 : : {
59 dgustafsson@postgres 168 [ # # ]:UBC 0 : errno = (errno) ? errno : ENOSPC;
169 : 0 : pg_fatal("could not write to file: %m");
170 : : }
977 tomas.vondra@postgre 171 :CBC 2138998 : }
172 : :
173 : : static const char *
977 tomas.vondra@postgre 174 :UBC 0 : get_error_none(CompressFileHandle *CFH)
175 : : {
176 : 0 : return strerror(errno);
177 : : }
178 : :
179 : : static char *
977 tomas.vondra@postgre 180 :CBC 8 : gets_none(char *ptr, int size, CompressFileHandle *CFH)
181 : : {
182 : 8 : return fgets(ptr, size, (FILE *) CFH->private_data);
183 : : }
184 : :
185 : : static int
186 : 131635 : getc_none(CompressFileHandle *CFH)
187 : : {
188 : 131635 : FILE *fp = (FILE *) CFH->private_data;
189 : : int ret;
190 : :
191 : 131635 : ret = fgetc(fp);
192 [ - + ]: 131635 : if (ret == EOF)
193 : : {
977 tomas.vondra@postgre 194 [ # # ]:UBC 0 : if (!feof(fp))
594 michael@paquier.xyz 195 : 0 : pg_fatal("could not read from input file: %m");
196 : : else
977 tomas.vondra@postgre 197 : 0 : pg_fatal("could not read from input file: end of file");
198 : : }
199 : :
977 tomas.vondra@postgre 200 :CBC 131635 : return ret;
201 : : }
202 : :
203 : : static bool
204 : 425 : close_none(CompressFileHandle *CFH)
205 : : {
206 : 425 : FILE *fp = (FILE *) CFH->private_data;
207 : 425 : int ret = 0;
208 : :
209 : 425 : CFH->private_data = NULL;
210 : :
211 [ + - ]: 425 : if (fp)
212 : : {
59 dgustafsson@postgres 213 : 425 : errno = 0;
977 tomas.vondra@postgre 214 : 425 : ret = fclose(fp);
59 dgustafsson@postgres 215 [ - + ]: 425 : if (ret != 0)
59 dgustafsson@postgres 216 :UBC 0 : pg_log_error("could not close file: %m");
217 : : }
218 : :
949 tomas.vondra@postgre 219 :CBC 425 : return ret == 0;
220 : : }
221 : :
222 : : static bool
977 223 : 4 : eof_none(CompressFileHandle *CFH)
224 : : {
949 225 : 4 : return feof((FILE *) CFH->private_data) != 0;
226 : : }
227 : :
228 : : static bool
977 229 : 428 : open_none(const char *path, int fd, const char *mode, CompressFileHandle *CFH)
230 : : {
231 [ - + ]: 428 : Assert(CFH->private_data == NULL);
232 : :
233 [ + + ]: 428 : if (fd >= 0)
234 : 271 : CFH->private_data = fdopen(dup(fd), mode);
235 : : else
236 : 157 : CFH->private_data = fopen(path, mode);
237 : :
238 [ - + ]: 428 : if (CFH->private_data == NULL)
949 tomas.vondra@postgre 239 :UBC 0 : return false;
240 : :
949 tomas.vondra@postgre 241 :CBC 428 : return true;
242 : : }
243 : :
244 : : static bool
977 245 : 18 : open_write_none(const char *path, const char *mode, CompressFileHandle *CFH)
246 : : {
247 [ - + ]: 18 : Assert(CFH->private_data == NULL);
248 : :
249 : 18 : CFH->private_data = fopen(path, mode);
250 [ - + ]: 18 : if (CFH->private_data == NULL)
949 tomas.vondra@postgre 251 :UBC 0 : return false;
252 : :
949 tomas.vondra@postgre 253 :CBC 18 : return true;
254 : : }
255 : :
256 : : /*
257 : : * Public interface
258 : : */
259 : :
260 : : void
977 261 : 446 : InitCompressFileHandleNone(CompressFileHandle *CFH,
262 : : const pg_compress_specification compression_spec)
263 : : {
264 : 446 : CFH->open_func = open_none;
265 : 446 : CFH->open_write_func = open_write_none;
266 : 446 : CFH->read_func = read_none;
267 : 446 : CFH->write_func = write_none;
268 : 446 : CFH->gets_func = gets_none;
269 : 446 : CFH->getc_func = getc_none;
270 : 446 : CFH->close_func = close_none;
271 : 446 : CFH->eof_func = eof_none;
272 : 446 : CFH->get_error_func = get_error_none;
273 : :
274 : 446 : CFH->private_data = NULL;
275 : 446 : }
|