Annotation of pgsql/src/port/copydir.c, revision 1.16.2.2
1.6 momjian 1: /*-------------------------------------------------------------------------
2: *
3: * copydir.c
4: * copies a directory
5: *
1.10 pgsql 6: * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
1.6 momjian 7: * Portions Copyright (c) 1994, Regents of the University of California
8: *
1.1 momjian 9: * While "xcopy /e /i /q" works fine for copying directories, on Windows XP
1.5 tgl 10: * it requires a Window handle which prevents it from working when invoked
1.1 momjian 11: * as a service.
1.5 tgl 12: *
1.6 momjian 13: * IDENTIFICATION
1.16.2.2! stark 14: * $PostgreSQL: pgsql/src/port/copydir.c,v 1.16.2.1 2008/03/31 01:32:48 tgl Exp $
1.6 momjian 15: *
16: *-------------------------------------------------------------------------
1.1 momjian 17: */
18:
19: #include "postgres.h"
20:
1.12 tgl 21: #include <fcntl.h>
22: #include <unistd.h>
23: #include <sys/stat.h>
24:
1.8 tgl 25: #include "storage/fd.h"
26:
1.14 tgl 27: /*
28: * On Windows, call non-macro versions of palloc; we can't reference
29: * CurrentMemoryContext in this file because of DLLIMPORT conflict.
30: */
31: #if defined(WIN32) || defined(__CYGWIN__)
32: #undef palloc
33: #undef pstrdup
34: #define palloc(sz) pgport_palloc(sz)
35: #define pstrdup(str) pgport_pstrdup(str)
36: #endif
37:
1.12 tgl 38:
39: static void copy_file(char *fromfile, char *tofile);
1.2 momjian 40:
41:
1.5 tgl 42: /*
1.12 tgl 43: * copydir: copy a directory
1.5 tgl 44: *
1.12 tgl 45: * If recurse is false, subdirectories are ignored. Anything that's not
46: * a directory or a regular file is ignored.
1.5 tgl 47: */
1.12 tgl 48: void
49: copydir(char *fromdir, char *todir, bool recurse)
1.1 momjian 50: {
51: DIR *xldir;
52: struct dirent *xlde;
1.16.2.2! stark 53: int dirfd;
1.12 tgl 54: char fromfile[MAXPGPATH];
55: char tofile[MAXPGPATH];
1.1 momjian 56:
1.12 tgl 57: if (mkdir(todir, S_IRUSR | S_IWUSR | S_IXUSR) != 0)
58: ereport(ERROR,
1.3 tgl 59: (errcode_for_file_access(),
60: errmsg("could not create directory \"%s\": %m", todir)));
1.12 tgl 61:
1.8 tgl 62: xldir = AllocateDir(fromdir);
1.1 momjian 63: if (xldir == NULL)
1.12 tgl 64: ereport(ERROR,
1.3 tgl 65: (errcode_for_file_access(),
66: errmsg("could not open directory \"%s\": %m", fromdir)));
1.12 tgl 67:
68: while ((xlde = ReadDir(xldir, fromdir)) != NULL)
69: {
1.15 momjian 70: struct stat fst;
1.12 tgl 71:
1.15 momjian 72: if (strcmp(xlde->d_name, ".") == 0 ||
1.12 tgl 73: strcmp(xlde->d_name, "..") == 0)
1.15 momjian 74: continue;
1.12 tgl 75:
76: snprintf(fromfile, MAXPGPATH, "%s/%s", fromdir, xlde->d_name);
77: snprintf(tofile, MAXPGPATH, "%s/%s", todir, xlde->d_name);
78:
79: if (stat(fromfile, &fst) < 0)
80: ereport(ERROR,
81: (errcode_for_file_access(),
1.16 petere 82: errmsg("could not stat file \"%s\": %m", fromfile)));
1.12 tgl 83:
1.16.2.1 tgl 84: if (S_ISDIR(fst.st_mode))
1.12 tgl 85: {
86: /* recurse to handle subdirectories */
87: if (recurse)
88: copydir(fromfile, tofile, true);
89: }
1.16.2.1 tgl 90: else if (S_ISREG(fst.st_mode))
1.12 tgl 91: copy_file(fromfile, tofile);
1.1 momjian 92: }
93:
1.12 tgl 94: FreeDir(xldir);
1.16.2.2! stark 95:
! 96: /*
! 97: * fsync the directory to make sure not just the data but also the
! 98: * new directory file entries have reached the disk. While needed
! 99: * by most filesystems, the window got bigger with newer ones like
! 100: * ext4.
! 101: */
! 102: dirfd = BasicOpenFile(todir,
! 103: O_RDONLY | PG_BINARY,
! 104: S_IRUSR | S_IWUSR);
! 105: if(dirfd == -1)
! 106: ereport(ERROR,
! 107: (errcode_for_file_access(),
! 108: errmsg("could not open directory for fsync \"%s\": %m", todir)));
! 109:
! 110: if(pg_fsync(dirfd) == -1)
! 111: ereport(ERROR,
! 112: (errcode_for_file_access(),
! 113: errmsg("could not fsync directory \"%s\": %m", todir)));
! 114: close(dirfd);
1.12 tgl 115: }
116:
117: /*
118: * copy one file
119: */
120: static void
121: copy_file(char *fromfile, char *tofile)
122: {
1.13 tgl 123: char *buffer;
1.12 tgl 124: int srcfd;
125: int dstfd;
126: int nbytes;
127:
1.13 tgl 128: /* Use palloc to ensure we get a maxaligned buffer */
129: #define COPY_BUF_SIZE (8 * BLCKSZ)
130:
131: buffer = palloc(COPY_BUF_SIZE);
132:
1.12 tgl 133: /*
134: * Open the files
135: */
136: srcfd = BasicOpenFile(fromfile, O_RDONLY | PG_BINARY, 0);
137: if (srcfd < 0)
138: ereport(ERROR,
139: (errcode_for_file_access(),
140: errmsg("could not open file \"%s\": %m", fromfile)));
141:
142: dstfd = BasicOpenFile(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
143: S_IRUSR | S_IWUSR);
144: if (dstfd < 0)
145: ereport(ERROR,
146: (errcode_for_file_access(),
147: errmsg("could not create file \"%s\": %m", tofile)));
148:
149: /*
150: * Do the data copying.
151: */
152: for (;;)
1.1 momjian 153: {
1.13 tgl 154: nbytes = read(srcfd, buffer, COPY_BUF_SIZE);
1.12 tgl 155: if (nbytes < 0)
156: ereport(ERROR,
157: (errcode_for_file_access(),
158: errmsg("could not read file \"%s\": %m", fromfile)));
159: if (nbytes == 0)
160: break;
161: errno = 0;
162: if ((int) write(dstfd, buffer, nbytes) != nbytes)
1.4 momjian 163: {
1.12 tgl 164: /* if write didn't set errno, assume problem is no disk space */
165: if (errno == 0)
166: errno = ENOSPC;
167: ereport(ERROR,
1.4 momjian 168: (errcode_for_file_access(),
1.12 tgl 169: errmsg("could not write to file \"%s\": %m", tofile)));
1.4 momjian 170: }
1.11 tgl 171: }
172:
173: /*
1.12 tgl 174: * Be paranoid here to ensure we catch problems.
1.11 tgl 175: */
1.12 tgl 176: if (pg_fsync(dstfd) != 0)
177: ereport(ERROR,
178: (errcode_for_file_access(),
179: errmsg("could not fsync file \"%s\": %m", tofile)));
180:
181: if (close(dstfd))
182: ereport(ERROR,
1.11 tgl 183: (errcode_for_file_access(),
1.12 tgl 184: errmsg("could not close file \"%s\": %m", tofile)));
1.1 momjian 185:
1.12 tgl 186: close(srcfd);
1.13 tgl 187:
188: pfree(buffer);
1.1 momjian 189: }
PostgreSQL CVSweb <[email protected]>