1 /*-------------------------------------------------------------------------
6 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
9 * While "xcopy /e /i /q" works fine for copying directories, on Windows XP
10 * it requires a Window handle which prevents it from working when invoked
16 *-------------------------------------------------------------------------
25 #include "storage/fd.h"
28 * On Windows, call non-macro versions of palloc; we can't reference
29 * CurrentMemoryContext in this file because of PGDLLIMPORT conflict.
31 #if defined(WIN32) || defined(__CYGWIN__)
34 #define palloc(sz) pgport_palloc(sz)
35 #define pstrdup(str) pgport_pstrdup(str)
39 static void copy_file(char *fromfile
, char *tofile
);
43 * copydir: copy a directory
45 * If recurse is false, subdirectories are ignored. Anything that's not
46 * a directory or a regular file is ignored.
49 copydir(char *fromdir
, char *todir
, bool recurse
)
53 char fromfile
[MAXPGPATH
];
54 char tofile
[MAXPGPATH
];
56 if (mkdir(todir
, S_IRUSR
| S_IWUSR
| S_IXUSR
) != 0)
58 (errcode_for_file_access(),
59 errmsg("could not create directory \"%s\": %m", todir
)));
61 xldir
= AllocateDir(fromdir
);
64 (errcode_for_file_access(),
65 errmsg("could not open directory \"%s\": %m", fromdir
)));
67 while ((xlde
= ReadDir(xldir
, fromdir
)) != NULL
)
71 if (strcmp(xlde
->d_name
, ".") == 0 ||
72 strcmp(xlde
->d_name
, "..") == 0)
75 snprintf(fromfile
, MAXPGPATH
, "%s/%s", fromdir
, xlde
->d_name
);
76 snprintf(tofile
, MAXPGPATH
, "%s/%s", todir
, xlde
->d_name
);
78 if (lstat(fromfile
, &fst
) < 0)
80 (errcode_for_file_access(),
81 errmsg("could not stat file \"%s\": %m", fromfile
)));
83 if (S_ISDIR(fst
.st_mode
))
85 /* recurse to handle subdirectories */
87 copydir(fromfile
, tofile
, true);
89 else if (S_ISREG(fst
.st_mode
))
90 copy_file(fromfile
, tofile
);
100 copy_file(char *fromfile
, char *tofile
)
107 /* Use palloc to ensure we get a maxaligned buffer */
108 #define COPY_BUF_SIZE (8 * BLCKSZ)
110 buffer
= palloc(COPY_BUF_SIZE
);
115 srcfd
= BasicOpenFile(fromfile
, O_RDONLY
| PG_BINARY
, 0);
118 (errcode_for_file_access(),
119 errmsg("could not open file \"%s\": %m", fromfile
)));
121 dstfd
= BasicOpenFile(tofile
, O_RDWR
| O_CREAT
| O_EXCL
| PG_BINARY
,
125 (errcode_for_file_access(),
126 errmsg("could not create file \"%s\": %m", tofile
)));
129 * Do the data copying.
133 nbytes
= read(srcfd
, buffer
, COPY_BUF_SIZE
);
136 (errcode_for_file_access(),
137 errmsg("could not read file \"%s\": %m", fromfile
)));
141 if ((int) write(dstfd
, buffer
, nbytes
) != nbytes
)
143 /* if write didn't set errno, assume problem is no disk space */
147 (errcode_for_file_access(),
148 errmsg("could not write to file \"%s\": %m", tofile
)));
153 * Be paranoid here to ensure we catch problems.
155 if (pg_fsync(dstfd
) != 0)
157 (errcode_for_file_access(),
158 errmsg("could not fsync file \"%s\": %m", tofile
)));
162 (errcode_for_file_access(),
163 errmsg("could not close file \"%s\": %m", tofile
)));