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 : 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 19272 : read_none(void *ptr, size_t size, CompressFileHandle *CFH)
148 : {
149 19272 : FILE *fp = (FILE *) CFH->private_data;
150 : size_t ret;
151 :
152 19272 : ret = fread(ptr, 1, size, fp);
153 19272 : if (ferror(fp))
154 0 : pg_fatal("could not read from input file: %m");
155 :
156 19272 : return ret;
157 : }
158 :
159 : static void
160 2186559 : write_none(const void *ptr, size_t size, CompressFileHandle *CFH)
161 : {
162 : size_t ret;
163 :
164 2186559 : errno = 0;
165 2186559 : ret = fwrite(ptr, 1, size, (FILE *) CFH->private_data);
166 2186559 : if (ret != size)
167 : {
168 0 : errno = (errno) ? errno : ENOSPC;
169 0 : pg_fatal("could not write to file: %m");
170 : }
171 2186559 : }
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 176680 : getc_none(CompressFileHandle *CFH)
187 : {
188 176680 : FILE *fp = (FILE *) CFH->private_data;
189 : int ret;
190 :
191 176680 : ret = fgetc(fp);
192 176680 : 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 176680 : return ret;
201 : }
202 :
203 : static bool
204 743 : close_none(CompressFileHandle *CFH)
205 : {
206 743 : FILE *fp = (FILE *) CFH->private_data;
207 743 : int ret = 0;
208 :
209 743 : CFH->private_data = NULL;
210 :
211 743 : if (fp)
212 : {
213 743 : errno = 0;
214 743 : ret = fclose(fp);
215 743 : if (ret != 0)
216 0 : pg_log_error("could not close file: %m");
217 : }
218 :
219 743 : 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 702 : open_none(const char *path, int fd, const char *mode, CompressFileHandle *CFH)
230 : {
231 : Assert(CFH->private_data == NULL);
232 :
233 702 : if (fd >= 0)
234 418 : CFH->private_data = fdopen(dup(fd), mode);
235 : else
236 284 : CFH->private_data = fopen(path, mode);
237 :
238 702 : if (CFH->private_data == NULL)
239 0 : return false;
240 :
241 702 : return true;
242 : }
243 :
244 : static bool
245 63 : open_write_none(const char *path, const char *mode, CompressFileHandle *CFH)
246 : {
247 : Assert(CFH->private_data == NULL);
248 :
249 63 : CFH->private_data = fopen(path, mode);
250 63 : if (CFH->private_data == NULL)
251 0 : return false;
252 :
253 63 : return true;
254 : }
255 :
256 : /*
257 : * Public interface
258 : */
259 :
260 : void
261 765 : InitCompressFileHandleNone(CompressFileHandle *CFH,
262 : const pg_compress_specification compression_spec)
263 : {
264 765 : CFH->open_func = open_none;
265 765 : CFH->open_write_func = open_write_none;
266 765 : CFH->read_func = read_none;
267 765 : CFH->write_func = write_none;
268 765 : CFH->gets_func = gets_none;
269 765 : CFH->getc_func = getc_none;
270 765 : CFH->close_func = close_none;
271 765 : CFH->eof_func = eof_none;
272 765 : CFH->get_error_func = get_error_none;
273 :
274 765 : CFH->private_data = NULL;
275 765 : }
|