Annotation of pgsql/src/port/copydir.c, revision 1.16.2.3
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.3! stark 14: * $PostgreSQL: pgsql/src/port/copydir.c,v 1.16.2.2 2010/02/14 17:50:34 stark 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.12 tgl 53: char fromfile[MAXPGPATH];
54: char tofile[MAXPGPATH];
1.1 momjian 55:
1.12 tgl 56: if (mkdir(todir, S_IRUSR | S_IWUSR | S_IXUSR) != 0)
57: ereport(ERROR,
1.3 tgl 58: (errcode_for_file_access(),
59: errmsg("could not create directory \"%s\": %m", todir)));
1.12 tgl 60:
1.8 tgl 61: xldir = AllocateDir(fromdir);
1.1 momjian 62: if (xldir == NULL)
1.12 tgl 63: ereport(ERROR,
1.3 tgl 64: (errcode_for_file_access(),
65: errmsg("could not open directory \"%s\": %m", fromdir)));
1.12 tgl 66:
67: while ((xlde = ReadDir(xldir, fromdir)) != NULL)
68: {
1.15 momjian 69: struct stat fst;
1.12 tgl 70:
1.15 momjian 71: if (strcmp(xlde->d_name, ".") == 0 ||
1.12 tgl 72: strcmp(xlde->d_name, "..") == 0)
1.15 momjian 73: continue;
1.12 tgl 74:
75: snprintf(fromfile, MAXPGPATH, "%s/%s", fromdir, xlde->d_name);
76: snprintf(tofile, MAXPGPATH, "%s/%s", todir, xlde->d_name);
77:
78: if (stat(fromfile, &fst) < 0)
79: ereport(ERROR,
80: (errcode_for_file_access(),
1.16 petere 81: errmsg("could not stat file \"%s\": %m", fromfile)));
1.12 tgl 82:
1.16.2.1 tgl 83: if (S_ISDIR(fst.st_mode))
1.12 tgl 84: {
85: /* recurse to handle subdirectories */
86: if (recurse)
87: copydir(fromfile, tofile, true);
88: }
1.16.2.1 tgl 89: else if (S_ISREG(fst.st_mode))
1.12 tgl 90: copy_file(fromfile, tofile);
1.1 momjian 91: }
92:
1.12 tgl 93: FreeDir(xldir);
94: }
95:
96: /*
97: * copy one file
98: */
99: static void
100: copy_file(char *fromfile, char *tofile)
101: {
1.13 tgl 102: char *buffer;
1.12 tgl 103: int srcfd;
104: int dstfd;
105: int nbytes;
106:
1.13 tgl 107: /* Use palloc to ensure we get a maxaligned buffer */
108: #define COPY_BUF_SIZE (8 * BLCKSZ)
109:
110: buffer = palloc(COPY_BUF_SIZE);
111:
1.12 tgl 112: /*
113: * Open the files
114: */
115: srcfd = BasicOpenFile(fromfile, O_RDONLY | PG_BINARY, 0);
116: if (srcfd < 0)
117: ereport(ERROR,
118: (errcode_for_file_access(),
119: errmsg("could not open file \"%s\": %m", fromfile)));
120:
121: dstfd = BasicOpenFile(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
122: S_IRUSR | S_IWUSR);
123: if (dstfd < 0)
124: ereport(ERROR,
125: (errcode_for_file_access(),
126: errmsg("could not create file \"%s\": %m", tofile)));
127:
128: /*
129: * Do the data copying.
130: */
131: for (;;)
1.1 momjian 132: {
1.13 tgl 133: nbytes = read(srcfd, buffer, COPY_BUF_SIZE);
1.12 tgl 134: if (nbytes < 0)
135: ereport(ERROR,
136: (errcode_for_file_access(),
137: errmsg("could not read file \"%s\": %m", fromfile)));
138: if (nbytes == 0)
139: break;
140: errno = 0;
141: if ((int) write(dstfd, buffer, nbytes) != nbytes)
1.4 momjian 142: {
1.12 tgl 143: /* if write didn't set errno, assume problem is no disk space */
144: if (errno == 0)
145: errno = ENOSPC;
146: ereport(ERROR,
1.4 momjian 147: (errcode_for_file_access(),
1.12 tgl 148: errmsg("could not write to file \"%s\": %m", tofile)));
1.4 momjian 149: }
1.11 tgl 150: }
151:
152: /*
1.12 tgl 153: * Be paranoid here to ensure we catch problems.
1.11 tgl 154: */
1.12 tgl 155: if (pg_fsync(dstfd) != 0)
156: ereport(ERROR,
157: (errcode_for_file_access(),
158: errmsg("could not fsync file \"%s\": %m", tofile)));
159:
160: if (close(dstfd))
161: ereport(ERROR,
1.11 tgl 162: (errcode_for_file_access(),
1.12 tgl 163: errmsg("could not close file \"%s\": %m", tofile)));
1.1 momjian 164:
1.12 tgl 165: close(srcfd);
1.13 tgl 166:
167: pfree(buffer);
1.1 momjian 168: }
PostgreSQL CVSweb <[email protected]>