PostgreSQL Source Code git master
Loading...
Searching...
No Matches
file.c
Go to the documentation of this file.
1/*
2 * file.c
3 *
4 * file system operations
5 *
6 * Copyright (c) 2010-2026, PostgreSQL Global Development Group
7 * src/bin/pg_upgrade/file.c
8 */
9
10#include "postgres_fe.h"
11
12#include <sys/stat.h>
13#include <limits.h>
14#include <fcntl.h>
15#ifdef HAVE_COPYFILE_H
16#include <copyfile.h>
17#endif
18#ifdef __linux__
19#include <sys/ioctl.h>
20#include <linux/fs.h>
21#endif
22
23#include "common/file_perm.h"
24#include "pg_upgrade.h"
25
26
27/*
28 * cloneFile()
29 *
30 * Clones/reflinks a relation file from src to dst.
31 *
32 * schemaName/relName are relation's SQL name (used for error messages only).
33 */
34void
35cloneFile(const char *src, const char *dst,
36 const char *schemaName, const char *relName)
37{
38#if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE)
39 if (copyfile(src, dst, NULL, COPYFILE_CLONE_FORCE) < 0)
40 pg_fatal("error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %m",
41 schemaName, relName, src, dst);
42#elif defined(__linux__) && defined(FICLONE)
43 int src_fd;
44 int dest_fd;
45
46 if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)
47 pg_fatal("error while cloning relation \"%s.%s\": could not open file \"%s\": %m",
48 schemaName, relName, src);
49
52 pg_fatal("error while cloning relation \"%s.%s\": could not create file \"%s\": %m",
54
55 if (ioctl(dest_fd, FICLONE, src_fd) < 0)
56 {
57 int save_errno = errno;
58
59 unlink(dst);
60
61 pg_fatal("error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s",
63 }
64
67#endif
68}
69
70
71/*
72 * copyFile()
73 *
74 * Copies a relation file from src to dst.
75 * schemaName/relName are relation's SQL name (used for error messages only).
76 */
77void
78copyFile(const char *src, const char *dst,
79 const char *schemaName, const char *relName)
80{
81#ifndef WIN32
82 int src_fd;
83 int dest_fd;
84 char *buffer;
85
86 if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)
87 pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m",
88 schemaName, relName, src);
89
92 pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m",
94
95 /* copy in fairly large chunks for best efficiency */
96#define COPY_BUF_SIZE (50 * BLCKSZ)
97
98 buffer = (char *) pg_malloc(COPY_BUF_SIZE);
99
100 /* perform data copying i.e read src source, write to destination */
101 while (true)
102 {
103 ssize_t nbytes = read(src_fd, buffer, COPY_BUF_SIZE);
104
105 if (nbytes < 0)
106 pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %m",
107 schemaName, relName, src);
108
109 if (nbytes == 0)
110 break;
111
112 errno = 0;
113 if (write(dest_fd, buffer, nbytes) != nbytes)
114 {
115 /* if write didn't set errno, assume problem is no disk space */
116 if (errno == 0)
117 errno = ENOSPC;
118 pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m",
120 }
121 }
122
123 pg_free(buffer);
124 close(src_fd);
125 close(dest_fd);
126
127#else /* WIN32 */
128
129 if (CopyFile(src, dst, true) == 0)
130 {
132 pg_fatal("error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %m",
133 schemaName, relName, src, dst);
134 }
135
136#endif /* WIN32 */
137}
138
139
140/*
141 * copyFileByRange()
142 *
143 * Copies a relation file from src to dst.
144 * schemaName/relName are relation's SQL name (used for error messages only).
145 */
146void
147copyFileByRange(const char *src, const char *dst,
148 const char *schemaName, const char *relName)
149{
150#ifdef HAVE_COPY_FILE_RANGE
151 int src_fd;
152 int dest_fd;
153 ssize_t nbytes;
154
155 if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)
156 pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m",
157 schemaName, relName, src);
158
161 pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %m",
163
164 do
165 {
167 if (nbytes < 0)
168 pg_fatal("error while copying relation \"%s.%s\": could not copy file range from \"%s\" to \"%s\": %m",
169 schemaName, relName, src, dst);
170 }
171 while (nbytes > 0);
172
173 close(src_fd);
174 close(dest_fd);
175#endif
176}
177
178
179/*
180 * linkFile()
181 *
182 * Hard-links a relation file from src to dst.
183 * schemaName/relName are relation's SQL name (used for error messages only).
184 */
185void
186linkFile(const char *src, const char *dst,
187 const char *schemaName, const char *relName)
188{
189 if (link(src, dst) < 0)
190 pg_fatal("error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %m",
191 schemaName, relName, src, dst);
192}
193
194
195void
197{
200
201 snprintf(existing_file, sizeof(existing_file), "%s/PG_VERSION", old_cluster.pgdata);
202 snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.clonetest", new_cluster.pgdata);
203 unlink(new_link_file); /* might fail */
204
205#if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE)
207 pg_fatal("could not clone file between old and new data directories: %m");
208#elif defined(__linux__) && defined(FICLONE)
209 {
210 int src_fd;
211 int dest_fd;
212
213 if ((src_fd = open(existing_file, O_RDONLY | PG_BINARY, 0)) < 0)
214 pg_fatal("could not open file \"%s\": %m",
216
219 pg_fatal("could not create file \"%s\": %m",
221
222 if (ioctl(dest_fd, FICLONE, src_fd) < 0)
223 pg_fatal("could not clone file between old and new data directories: %m");
224
225 close(src_fd);
226 close(dest_fd);
227 }
228#else
229 pg_fatal("file cloning not supported on this platform");
230#endif
231
233}
234
235void
237{
240
241 snprintf(existing_file, sizeof(existing_file), "%s/PG_VERSION", old_cluster.pgdata);
242 snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.copy_file_range_test", new_cluster.pgdata);
243 unlink(new_link_file); /* might fail */
244
245#if defined(HAVE_COPY_FILE_RANGE)
246 {
247 int src_fd;
248 int dest_fd;
249
250 if ((src_fd = open(existing_file, O_RDONLY | PG_BINARY, 0)) < 0)
251 pg_fatal("could not open file \"%s\": %m",
253
256 pg_fatal("could not create file \"%s\": %m",
258
260 pg_fatal("could not copy file range between old and new data directories: %m");
261
262 close(src_fd);
263 close(dest_fd);
264 }
265#else
266 pg_fatal("copy_file_range not supported on this platform");
267#endif
268
270}
271
272void
274{
277
278 snprintf(existing_file, sizeof(existing_file), "%s/PG_VERSION", old_cluster.pgdata);
279 snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.linktest", new_cluster.pgdata);
280 unlink(new_link_file); /* might fail */
281
283 {
284 if (transfer_mode == TRANSFER_MODE_LINK)
285 pg_fatal("could not create hard link between old and new data directories: %m\n"
286 "In link mode the old and new data directories must be on the same file system.");
287 else if (transfer_mode == TRANSFER_MODE_SWAP)
288 pg_fatal("could not create hard link between old and new data directories: %m\n"
289 "In swap mode the old and new data directories must be on the same file system.");
290 else
291 pg_fatal("unrecognized transfer mode");
292 }
293
295}
#define PG_BINARY
Definition c.h:1431
void * pg_malloc(size_t size)
Definition fe_memutils.c:53
void pg_free(void *ptr)
void linkFile(const char *src, const char *dst, const char *schemaName, const char *relName)
Definition file.c:186
void check_file_clone(void)
Definition file.c:196
void check_hard_link(transferMode transfer_mode)
Definition file.c:273
void cloneFile(const char *src, const char *dst, const char *schemaName, const char *relName)
Definition file.c:35
void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName)
Definition file.c:147
void copyFile(const char *src, const char *dst, const char *schemaName, const char *relName)
Definition file.c:78
void check_copy_file_range(void)
Definition file.c:236
#define COPY_BUF_SIZE
int pg_file_create_mode
Definition file_perm.c:19
#define close(a)
Definition win32.h:12
#define write(a, b, c)
Definition win32.h:14
#define read(a, b, c)
Definition win32.h:13
#define pg_fatal(...)
#define MAXPGPATH
ClusterInfo new_cluster
Definition pg_upgrade.c:74
ClusterInfo old_cluster
Definition pg_upgrade.c:73
transferMode
Definition pg_upgrade.h:243
@ TRANSFER_MODE_LINK
Definition pg_upgrade.h:247
@ TRANSFER_MODE_SWAP
Definition pg_upgrade.h:248
#define strerror
Definition port.h:274
#define snprintf
Definition port.h:261
static int fb(int x)
char * pgdata
Definition pg_upgrade.h:275
void _dosmaperr(unsigned long)
Definition win32error.c:177