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]>