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)