1 /*-------------------------------------------------------------------------
6 * Portions Copyright (c) 1996-2009, 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
14 * $PostgreSQL: pgsql/src/port/copydir.c,v 1.23 2009/01/01 17:24:04 momjian Exp $
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)));