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 4242952 : write_none(const void *ptr, size_t size, CompressFileHandle *CFH)
161 : {
162 : size_t ret;
163 :
164 4242952 : errno = 0;
165 4242952 : ret = fwrite(ptr, 1, size, (FILE *) CFH->private_data);
166 4242952 : if (ret != size)
167 : {
168 0 : errno = (errno) ? errno : ENOSPC;
169 0 : pg_fatal("could not write to file: %m");
170 : }
171 4242952 : }
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 : }
|