PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
copydir.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void copydir (char *fromdir, char *todir, bool recurse)
 
void copy_file (char *fromfile, char *tofile)
 

Function Documentation

void copy_file ( char *  fromfile,
char *  tofile 
)

Definition at line 135 of file copydir.c.

References buffer, CHECK_FOR_INTERRUPTS, CloseTransientFile(), COPY_BUF_SIZE, dstfd, ereport, errcode_for_file_access(), errmsg(), ERROR, OpenTransientFile(), palloc(), pfree(), PG_BINARY, pg_flush_data(), pgstat_report_wait_end(), pgstat_report_wait_start(), read, WAIT_EVENT_COPY_FILE_READ, WAIT_EVENT_COPY_FILE_WRITE, and write.

Referenced by copydir(), and ResetUnloggedRelationsInDbspaceDir().

136 {
137  char *buffer;
138  int srcfd;
139  int dstfd;
140  int nbytes;
141  off_t offset;
142 
143  /* Use palloc to ensure we get a maxaligned buffer */
144 #define COPY_BUF_SIZE (8 * BLCKSZ)
145 
146  buffer = palloc(COPY_BUF_SIZE);
147 
148  /*
149  * Open the files
150  */
151  srcfd = OpenTransientFile(fromfile, O_RDONLY | PG_BINARY, 0);
152  if (srcfd < 0)
153  ereport(ERROR,
155  errmsg("could not open file \"%s\": %m", fromfile)));
156 
157  dstfd = OpenTransientFile(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
158  S_IRUSR | S_IWUSR);
159  if (dstfd < 0)
160  ereport(ERROR,
162  errmsg("could not create file \"%s\": %m", tofile)));
163 
164  /*
165  * Do the data copying.
166  */
167  for (offset = 0;; offset += nbytes)
168  {
169  /* If we got a cancel signal during the copy of the file, quit */
171 
173  nbytes = read(srcfd, buffer, COPY_BUF_SIZE);
175  if (nbytes < 0)
176  ereport(ERROR,
178  errmsg("could not read file \"%s\": %m", fromfile)));
179  if (nbytes == 0)
180  break;
181  errno = 0;
183  if ((int) write(dstfd, buffer, nbytes) != nbytes)
184  {
186  /* if write didn't set errno, assume problem is no disk space */
187  if (errno == 0)
188  errno = ENOSPC;
189  ereport(ERROR,
191  errmsg("could not write to file \"%s\": %m", tofile)));
192  }
194 
195  /*
196  * We fsync the files later but first flush them to avoid spamming the
197  * cache and hopefully get the kernel to start writing them out before
198  * the fsync comes.
199  */
200  pg_flush_data(dstfd, offset, nbytes);
201  }
202 
203  if (CloseTransientFile(dstfd))
204  ereport(ERROR,
206  errmsg("could not close file \"%s\": %m", tofile)));
207 
208  CloseTransientFile(srcfd);
209 
210  pfree(buffer);
211 }
static int dstfd
Definition: file_ops.c:29
#define write(a, b, c)
Definition: win32.h:14
#define PG_BINARY
Definition: c.h:1039
#define COPY_BUF_SIZE
void pfree(void *pointer)
Definition: mcxt.c:950
#define ERROR
Definition: elog.h:43
int OpenTransientFile(FileName fileName, int fileFlags, int fileMode)
Definition: fd.c:2144
int errcode_for_file_access(void)
Definition: elog.c:598
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1235
#define ereport(elevel, rest)
Definition: elog.h:122
int CloseTransientFile(int fd)
Definition: fd.c:2305
void pg_flush_data(int fd, off_t offset, off_t nbytes)
Definition: fd.c:407
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1211
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define read(a, b, c)
Definition: win32.h:13
void copydir ( char *  fromdir,
char *  todir,
bool  recurse 
)

Definition at line 37 of file copydir.c.

References AllocateDir(), CHECK_FOR_INTERRUPTS, copy_file(), copydir(), dirent::d_name, enableFsync, ereport, errcode_for_file_access(), errmsg(), ERROR, FreeDir(), fsync_fname(), lstat, MAXPGPATH, mkdir, NULL, ReadDir(), and snprintf().

Referenced by copydir(), createdb(), dbase_redo(), and movedb().

38 {
39  DIR *xldir;
40  struct dirent *xlde;
41  char fromfile[MAXPGPATH * 2];
42  char tofile[MAXPGPATH * 2];
43 
44  if (mkdir(todir, S_IRWXU) != 0)
45  ereport(ERROR,
47  errmsg("could not create directory \"%s\": %m", todir)));
48 
49  xldir = AllocateDir(fromdir);
50  if (xldir == NULL)
51  ereport(ERROR,
53  errmsg("could not open directory \"%s\": %m", fromdir)));
54 
55  while ((xlde = ReadDir(xldir, fromdir)) != NULL)
56  {
57  struct stat fst;
58 
59  /* If we got a cancel signal during the copy of the directory, quit */
61 
62  if (strcmp(xlde->d_name, ".") == 0 ||
63  strcmp(xlde->d_name, "..") == 0)
64  continue;
65 
66  snprintf(fromfile, sizeof(fromfile), "%s/%s", fromdir, xlde->d_name);
67  snprintf(tofile, sizeof(tofile), "%s/%s", todir, xlde->d_name);
68 
69  if (lstat(fromfile, &fst) < 0)
70  ereport(ERROR,
72  errmsg("could not stat file \"%s\": %m", fromfile)));
73 
74  if (S_ISDIR(fst.st_mode))
75  {
76  /* recurse to handle subdirectories */
77  if (recurse)
78  copydir(fromfile, tofile, true);
79  }
80  else if (S_ISREG(fst.st_mode))
81  copy_file(fromfile, tofile);
82  }
83  FreeDir(xldir);
84 
85  /*
86  * Be paranoid here and fsync all files to ensure the copy is really done.
87  * But if fsync is disabled, we're done.
88  */
89  if (!enableFsync)
90  return;
91 
92  xldir = AllocateDir(todir);
93  if (xldir == NULL)
94  ereport(ERROR,
96  errmsg("could not open directory \"%s\": %m", todir)));
97 
98  while ((xlde = ReadDir(xldir, todir)) != NULL)
99  {
100  struct stat fst;
101 
102  if (strcmp(xlde->d_name, ".") == 0 ||
103  strcmp(xlde->d_name, "..") == 0)
104  continue;
105 
106  snprintf(tofile, sizeof(tofile), "%s/%s", todir, xlde->d_name);
107 
108  /*
109  * We don't need to sync subdirectories here since the recursive
110  * copydir will do it before it returns
111  */
112  if (lstat(tofile, &fst) < 0)
113  ereport(ERROR,
115  errmsg("could not stat file \"%s\": %m", tofile)));
116 
117  if (S_ISREG(fst.st_mode))
118  fsync_fname(tofile, false);
119  }
120  FreeDir(xldir);
121 
122  /*
123  * It's important to fsync the destination directory itself as individual
124  * file fsyncs don't guarantee that the directory entry for the file is
125  * synced. Recent versions of ext4 have made the window much wider but
126  * it's been true for ext3 and other filesystems in the past.
127  */
128  fsync_fname(todir, true);
129 }
#define mkdir(a, b)
Definition: win32.h:57
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:567
void copydir(char *fromdir, char *todir, bool recurse)
Definition: copydir.c:37
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
Definition: dirent.h:9
Definition: dirent.c:25
#define ERROR
Definition: elog.h:43
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:598
void copy_file(char *fromfile, char *tofile)
Definition: copydir.c:135
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2335
#define ereport(elevel, rest)
Definition: elog.h:122
#define NULL
Definition: c.h:229
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2401
bool enableFsync
Definition: globals.c:111
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
char d_name[MAX_PATH]
Definition: dirent.h:14
#define lstat(path, sb)
Definition: win32.h:262
int FreeDir(DIR *dir)
Definition: fd.c:2444