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 CHECK_FOR_INTERRUPTS, CloseTransientFile(), COPY_BUF_SIZE, dstfd, ereport, errcode_for_file_access(), errmsg(), ERROR, OpenTransientFile(), palloc(), pfree(), PG_BINARY, pg_flush_data(), read, 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 
172  nbytes = read(srcfd, buffer, COPY_BUF_SIZE);
173  if (nbytes < 0)
174  ereport(ERROR,
176  errmsg("could not read file \"%s\": %m", fromfile)));
177  if (nbytes == 0)
178  break;
179  errno = 0;
180  if ((int) write(dstfd, buffer, nbytes) != nbytes)
181  {
182  /* if write didn't set errno, assume problem is no disk space */
183  if (errno == 0)
184  errno = ENOSPC;
185  ereport(ERROR,
187  errmsg("could not write to file \"%s\": %m", tofile)));
188  }
189 
190  /*
191  * We fsync the files later but first flush them to avoid spamming the
192  * cache and hopefully get the kernel to start writing them out before
193  * the fsync comes.
194  */
195  pg_flush_data(dstfd, offset, nbytes);
196  }
197 
198  if (CloseTransientFile(dstfd))
199  ereport(ERROR,
201  errmsg("could not close file \"%s\": %m", tofile)));
202 
203  CloseTransientFile(srcfd);
204 
205  pfree(buffer);
206 }
static int dstfd
Definition: file_ops.c:29
#define write(a, b, c)
Definition: win32.h:19
#define PG_BINARY
Definition: c.h:1038
#define COPY_BUF_SIZE
void pfree(void *pointer)
Definition: mcxt.c:992
#define ERROR
Definition: elog.h:43
int OpenTransientFile(FileName fileName, int fileFlags, int fileMode)
Definition: fd.c:2093
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
int CloseTransientFile(int fd)
Definition: fd.c:2254
void pg_flush_data(int fd, off_t offset, off_t nbytes)
Definition: fd.c:407
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
#define read(a, b, c)
Definition: win32.h:18
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];
42  char tofile[MAXPGPATH];
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, MAXPGPATH, "%s/%s", fromdir, xlde->d_name);
67  snprintf(tofile, MAXPGPATH, "%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, MAXPGPATH, "%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:65
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:2284
#define ereport(elevel, rest)
Definition: elog.h:122
#define NULL
Definition: c.h:226
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2350
bool enableFsync
Definition: globals.c:110
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
char d_name[MAX_PATH]
Definition: dirent.h:14
#define lstat(path, sb)
Definition: win32.h:272
int FreeDir(DIR *dir)
Definition: fd.c:2393