PostgreSQL Source Code: src/backend/storage/file/copydir.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
20
21#ifdef HAVE_COPYFILE_H
22#include <copyfile.h>
23#endif
24#include <fcntl.h>
26
32
33
35
36static void clone_file(const char *fromfile, const char *tofile);
37
38
39
40
41
42
43
44
45
46
47void
48copydir(const char *fromdir, const char *todir, bool recurse)
49{
50 DIR *xldir;
54
58 errmsg("could not create directory \"%s\": %m", todir)));
59
61
62 while ((xlde = ReadDir(xldir, fromdir)) != NULL)
63 {
65
66
68
69 if (strcmp(xlde->d_name, ".") == 0 ||
70 strcmp(xlde->d_name, "..") == 0)
71 continue;
72
73 snprintf(fromfile, sizeof(fromfile), "%s/%s", fromdir, xlde->d_name);
74 snprintf(tofile, sizeof(tofile), "%s/%s", todir, xlde->d_name);
75
77
79 {
80
81 if (recurse)
82 copydir(fromfile, tofile, true);
83 }
85 {
88 else
90 }
91 }
93
94
95
96
97
99 return;
100
102
103 while ((xlde = ReadDir(xldir, todir)) != NULL)
104 {
105 if (strcmp(xlde->d_name, ".") == 0 ||
106 strcmp(xlde->d_name, "..") == 0)
107 continue;
108
109 snprintf(tofile, sizeof(tofile), "%s/%s", todir, xlde->d_name);
110
111
112
113
114
117 }
119
120
121
122
123
124
125
127}
128
129
130
131
132void
133copy_file(const char *fromfile, const char *tofile)
134{
135 char *buffer;
136 int srcfd;
138 int nbytes;
139 off_t offset;
140 off_t flush_offset;
141
142
143#define COPY_BUF_SIZE (8 * BLCKSZ)
144
145
146
147
148
149
150
151#if defined(__darwin__)
152#define FLUSH_DISTANCE (32 * 1024 * 1024)
153#else
154#define FLUSH_DISTANCE (1024 * 1024)
155#endif
156
157
159
160
161
162
164 if (srcfd < 0)
167 errmsg("could not open file \"%s\": %m", fromfile)));
168
173 errmsg("could not create file \"%s\": %m", tofile)));
174
175
176
177
178 flush_offset = 0;
179 for (offset = 0;; offset += nbytes)
180 {
181
183
184
185
186
187
188
190 {
192 flush_offset = offset;
193 }
194
198 if (nbytes < 0)
201 errmsg("could not read file \"%s\": %m", fromfile)));
202 if (nbytes == 0)
203 break;
204 errno = 0;
206 if ((int) write(dstfd, buffer, nbytes) != nbytes)
207 {
208
209 if (errno == 0)
210 errno = ENOSPC;
213 errmsg("could not write to file \"%s\": %m", tofile)));
214 }
216 }
217
218 if (offset > flush_offset)
220
224 errmsg("could not close file \"%s\": %m", tofile)));
225
229 errmsg("could not close file \"%s\": %m", fromfile)));
230
232}
233
234
235
236
237static void
238clone_file(const char *fromfile, const char *tofile)
239{
240#if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE)
241 if (copyfile(fromfile, tofile, NULL, COPYFILE_CLONE_FORCE) < 0)
244 errmsg("could not clone file \"%s\" to \"%s\": %m",
245 fromfile, tofile)));
246#elif defined(HAVE_COPY_FILE_RANGE)
247 int srcfd;
249 ssize_t nbytes;
250
252 if (srcfd < 0)
255 errmsg("could not open file \"%s\": %m", fromfile)));
256
261 errmsg("could not create file \"%s\": %m", tofile)));
262
263 do
264 {
265
266
267
268
271 nbytes = copy_file_range(srcfd, NULL, dstfd, NULL, 1024 * 1024, 0);
272 if (nbytes < 0 && errno != EINTR)
275 errmsg("could not clone file \"%s\" to \"%s\": %m",
276 fromfile, tofile)));
278 }
279 while (nbytes != 0);
280
284 errmsg("could not close file \"%s\": %m", tofile)));
285
289 errmsg("could not close file \"%s\": %m", fromfile)));
290#else
291
293#endif
294}
static void clone_file(const char *fromfile, const char *tofile)
void copy_file(const char *fromfile, const char *tofile)
void copydir(const char *fromdir, const char *todir, bool recurse)
int errcode_for_file_access(void)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
void pg_flush_data(int fd, off_t offset, off_t nbytes)
int MakePGDirectory(const char *directoryName)
int CloseTransientFile(int fd)
void fsync_fname(const char *fname, bool isdir)
DIR * AllocateDir(const char *dirname)
struct dirent * ReadDir(DIR *dir, const char *dirname)
int OpenTransientFile(const char *fileName, int fileFlags)
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
void pfree(void *pointer)
#define CHECK_FOR_INTERRUPTS()
static void pgstat_report_wait_start(uint32 wait_event_info)
static void pgstat_report_wait_end(void)