PostgreSQL Source Code: src/bin/pg_combinebackup/copy_file.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
12
13#ifdef HAVE_COPYFILE_H
14#include <copyfile.h>
15#endif
16#ifdef __linux__
17#include <sys/ioctl.h>
18#include <linux/fs.h>
19#endif
20#include <fcntl.h>
21#include <limits.h>
22#include <sys/stat.h>
24
28
31
34
37
38#ifdef WIN32
39static void copy_file_copyfile(const char *src, const char *dst,
41#endif
42
45
46
47
48
49
50
51void
52copy_file(const char *src, const char *dst,
55{
56 char *strategy_name = NULL;
57 void (*strategy_implementation) (const char *, const char *,
59
60
61
62
63
65 {
66 int fd;
67
68 if ((fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)
69 pg_fatal("could not open file \"%s\": %m", src);
71 pg_fatal("could not close file \"%s\": %m", src);
72 }
73
74#ifdef WIN32
75
76
77
78
79
80
82 copy_method = COPY_METHOD_COPYFILE;
83#endif
84
85
86 switch (copy_method)
87 {
89 strategy_name = "clone";
91 break;
93
95 break;
97 strategy_name = "copy_file_range";
99 break;
100#ifdef WIN32
101 case COPY_METHOD_COPYFILE:
102 strategy_name = "CopyFile";
103 strategy_implementation = copy_file_copyfile;
104 break;
105#endif
107 strategy_name = "link";
109 break;
110 }
111
113 {
114 if (strategy_name)
115 pg_log_debug("would copy \"%s\" to \"%s\" using strategy %s",
116 src, dst, strategy_name);
117 else
119 src, dst);
120 }
121 else
122 {
123 if (strategy_name)
124 pg_log_debug("copying \"%s\" to \"%s\" using strategy %s",
125 src, dst, strategy_name);
128 src, dst);
129 else
130 pg_log_debug("copying \"%s\" to \"%s\" and checksumming with %s",
132
133 strategy_implementation(src, dst, checksum_ctx);
134 }
135}
136
137
138
139
140static void
142{
143 int src_fd;
145 const int buffer_size = 50 * BLCKSZ;
146 ssize_t rb;
147
148
150 return;
151
152 if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)
153 pg_fatal("could not open file \"%s\": %m", src);
154
156
157 while ((rb = read(src_fd, buffer, buffer_size)) > 0)
158 {
160 pg_fatal("could not update checksum of file \"%s\"", src);
161 }
162
163 if (rb < 0)
164 pg_fatal("could not read file \"%s\": %m", src);
165
168}
169
170
171
172
173static void
176{
177 int src_fd;
178 int dest_fd;
180 const int buffer_size = 50 * BLCKSZ;
181 ssize_t rb;
182 unsigned offset = 0;
183
184 if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)
185 pg_fatal("could not open file \"%s\": %m", src);
186
187 if ((dest_fd = open(dst, O_WRONLY | O_CREAT | O_EXCL | PG_BINARY,
189 pg_fatal("could not open file \"%s\": %m", dst);
190
192
193 while ((rb = read(src_fd, buffer, buffer_size)) > 0)
194 {
195 ssize_t wb;
196
197 if ((wb = write(dest_fd, buffer, rb)) != rb)
198 {
199 if (wb < 0)
200 pg_fatal("could not write to file \"%s\": %m", dst);
201 else
202 pg_fatal("could not write to file \"%s\", offset %u: wrote %d of %d",
203 dst, offset, (int) wb, (int) rb);
204 }
205
207 pg_fatal("could not update checksum of file \"%s\"", dst);
208
209 offset += rb;
210 }
211
212 if (rb < 0)
213 pg_fatal("could not read from file \"%s\": %m", dst);
214
218}
219
220
221
222
223
224
225
226static void
229{
230#if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE)
231 if (copyfile(src, dest, NULL, COPYFILE_CLONE_FORCE) < 0)
232 pg_fatal("error while cloning file \"%s\" to \"%s\": %m", src, dest);
233#elif defined(__linux__) && defined(FICLONE)
234 {
235 int src_fd;
236 int dest_fd;
237
238 if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)
239 pg_fatal("could not open file \"%s\": %m", src);
240
241 if ((dest_fd = open(dest, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
243 pg_fatal("could not create file \"%s\": %m", dest);
244
245 if (ioctl(dest_fd, FICLONE, src_fd) < 0)
246 {
247 int save_errno = errno;
248
249 unlink(dest);
250
251 pg_fatal("error while cloning file \"%s\" to \"%s\": %s",
253 }
254
257 }
258#else
259 pg_fatal("file cloning not supported on this platform");
260#endif
261
262
264}
265
266
267
268
269
270
271
272static void
275{
276#if defined(HAVE_COPY_FILE_RANGE)
277 int src_fd;
278 int dest_fd;
279 ssize_t nbytes;
280
281 if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)
282 pg_fatal("could not open file \"%s\": %m", src);
283
284 if ((dest_fd = open(dest, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
286 pg_fatal("could not create file \"%s\": %m", dest);
287
288 do
289 {
290 nbytes = copy_file_range(src_fd, NULL, dest_fd, NULL, SSIZE_MAX, 0);
291 if (nbytes < 0)
292 pg_fatal("error while copying file range from \"%s\" to \"%s\": %m",
294 } while (nbytes > 0);
295
298#else
299 pg_fatal("copy_file_range not supported on this platform");
300#endif
301
302
304}
305
306#ifdef WIN32
307static void
308copy_file_copyfile(const char *src, const char *dst,
310{
311 if (CopyFile(src, dst, true) == 0)
312 {
314 pg_fatal("could not copy file \"%s\" to \"%s\": %m", src, dst);
315 }
316
317
319}
320#endif
321
322
323
324
325
326
327
328static void
331{
333 pg_fatal("could not create link from \"%s\" to \"%s\": %m",
335
336
338}
char * pg_checksum_type_name(pg_checksum_type type)
int pg_checksum_update(pg_checksum_context *context, const uint8 *input, size_t len)
static void copy_file_blocks(const char *src, const char *dst, pg_checksum_context *checksum_ctx)
static void copy_file_clone(const char *src, const char *dest, pg_checksum_context *checksum_ctx)
void copy_file(const char *src, const char *dst, pg_checksum_context *checksum_ctx, CopyMethod copy_method, bool dry_run)
static void checksum_file(const char *src, pg_checksum_context *checksum_ctx)
static void copy_file_link(const char *src, const char *dest, pg_checksum_context *checksum_ctx)
static void copy_file_by_range(const char *src, const char *dest, pg_checksum_context *checksum_ctx)
@ COPY_METHOD_COPY_FILE_RANGE
void * pg_malloc(size_t size)
#define pg_log_debug(...)
static int fd(const char *x, int i)
void _dosmaperr(unsigned long)
int link(const char *src, const char *dst)