Branch data 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-2026, 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 : 3 : ReadDataFromArchiveNone(ArchiveHandle *AH, CompressorState *cs)
43 : : {
44 : : size_t cnt;
45 : : char *buf;
46 : : size_t buflen;
47 : :
48 : 3 : buflen = DEFAULT_IO_BUFFER_SIZE;
49 : 3 : buf = pg_malloc(buflen);
50 : :
51 [ + + ]: 8 : while ((cnt = cs->readF(AH, &buf, &buflen)))
52 : : {
53 : 5 : ahwrite(buf, 1, cnt, AH);
54 : : }
55 : :
56 : 3 : pg_free(buf);
57 : 3 : }
58 : :
59 : :
60 : : static void
61 : 4 : WriteDataToArchiveNone(ArchiveHandle *AH, CompressorState *cs,
62 : : const void *data, size_t dLen)
63 : : {
64 : 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 : : }
86 : 4 : }
87 : :
88 : : static void
89 : 6 : EndCompressorNone(ArchiveHandle *AH, CompressorState *cs)
90 : : {
91 : 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 : : }
103 : 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 : : */
123 [ + + ]: 6 : if (cs->writeF)
124 : : {
125 : : NoneCompressorState *nonecs;
126 : :
127 : 3 : nonecs = pg_malloc_object(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 : : }
134 : 6 : }
135 : :
136 : :
137 : : /*----------------------
138 : : * Compress File API
139 : : *----------------------
140 : : */
141 : :
142 : : /*
143 : : * Private routines
144 : : */
145 : :
146 : : static size_t
147 : 15300 : read_none(void *ptr, size_t size, CompressFileHandle *CFH)
148 : : {
149 : 15300 : FILE *fp = (FILE *) CFH->private_data;
150 : : size_t ret;
151 : :
152 : 15300 : ret = fread(ptr, 1, size, fp);
153 [ - + ]: 15300 : if (ferror(fp))
154 : 0 : pg_fatal("could not read from input file: %m");
155 : :
156 : 15300 : return ret;
157 : : }
158 : :
159 : : static void
160 : 2149431 : write_none(const void *ptr, size_t size, CompressFileHandle *CFH)
161 : : {
162 : : size_t ret;
163 : :
164 : 2149431 : errno = 0;
165 : 2149431 : ret = fwrite(ptr, 1, size, (FILE *) CFH->private_data);
166 [ - + ]: 2149431 : if (ret != size)
167 : : {
168 [ # # ]: 0 : errno = (errno) ? errno : ENOSPC;
169 : 0 : pg_fatal("could not write to file: %m");
170 : : }
171 : 2149431 : }
172 : :
173 : : static const char *
174 : 0 : get_error_none(CompressFileHandle *CFH)
175 : : {
176 : 0 : return strerror(errno);
177 : : }
178 : :
179 : : static char *
180 : 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 : 136240 : getc_none(CompressFileHandle *CFH)
187 : : {
188 : 136240 : FILE *fp = (FILE *) CFH->private_data;
189 : : int ret;
190 : :
191 : 136240 : ret = fgetc(fp);
192 [ - + ]: 136240 : 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 : 136240 : return ret;
201 : : }
202 : :
203 : : static bool
204 : 434 : close_none(CompressFileHandle *CFH)
205 : : {
206 : 434 : FILE *fp = (FILE *) CFH->private_data;
207 : 434 : int ret = 0;
208 : :
209 : 434 : CFH->private_data = NULL;
210 : :
211 [ + - ]: 434 : if (fp)
212 : : {
213 : 434 : errno = 0;
214 : 434 : ret = fclose(fp);
215 [ - + ]: 434 : if (ret != 0)
216 : 0 : pg_log_error("could not close file: %m");
217 : : }
218 : :
219 : 434 : return ret == 0;
220 : : }
221 : :
222 : : static bool
223 : 4 : eof_none(CompressFileHandle *CFH)
224 : : {
225 : 4 : return feof((FILE *) CFH->private_data) != 0;
226 : : }
227 : :
228 : : static bool
229 : 439 : open_none(const char *path, int fd, const char *mode, CompressFileHandle *CFH)
230 : : {
231 : : Assert(CFH->private_data == NULL);
232 : :
233 [ + + ]: 439 : if (fd >= 0)
234 : : {
235 : 276 : int dup_fd = dup(fd);
236 : :
237 [ - + ]: 276 : if (dup_fd < 0)
238 : 0 : return false;
239 : 276 : CFH->private_data = fdopen(dup_fd, mode);
240 [ - + ]: 276 : if (CFH->private_data == NULL)
241 : : {
242 : 0 : close(dup_fd);
243 : 0 : return false;
244 : : }
245 : : }
246 : : else
247 : : {
248 : 163 : CFH->private_data = fopen(path, mode);
249 [ - + ]: 163 : if (CFH->private_data == NULL)
250 : 0 : return false;
251 : : }
252 : :
253 : 439 : return true;
254 : : }
255 : :
256 : : static bool
257 : 16 : open_write_none(const char *path, const char *mode, CompressFileHandle *CFH)
258 : : {
259 : : Assert(CFH->private_data == NULL);
260 : :
261 : 16 : CFH->private_data = fopen(path, mode);
262 [ - + ]: 16 : if (CFH->private_data == NULL)
263 : 0 : return false;
264 : :
265 : 16 : return true;
266 : : }
267 : :
268 : : /*
269 : : * Public interface
270 : : */
271 : :
272 : : void
273 : 455 : InitCompressFileHandleNone(CompressFileHandle *CFH,
274 : : const pg_compress_specification compression_spec)
275 : : {
276 : 455 : CFH->open_func = open_none;
277 : 455 : CFH->open_write_func = open_write_none;
278 : 455 : CFH->read_func = read_none;
279 : 455 : CFH->write_func = write_none;
280 : 455 : CFH->gets_func = gets_none;
281 : 455 : CFH->getc_func = getc_none;
282 : 455 : CFH->close_func = close_none;
283 : 455 : CFH->eof_func = eof_none;
284 : 455 : CFH->get_error_func = get_error_none;
285 : :
286 : 455 : CFH->private_data = NULL;
287 : 455 : }
|