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)