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