00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "postgres_fe.h"
00011
00012 #include "pg_upgrade.h"
00013
00014 #include <fcntl.h>
00015
00016
00017
00018 #ifndef WIN32
00019 static int copy_file(const char *fromfile, const char *tofile, bool force);
00020 #else
00021 static int win32_pghardlink(const char *src, const char *dst);
00022 #endif
00023
00024
00025
00026
00027
00028
00029
00030
00031 const char *
00032 copyAndUpdateFile(pageCnvCtx *pageConverter,
00033 const char *src, const char *dst, bool force)
00034 {
00035 if (pageConverter == NULL)
00036 {
00037 if (pg_copy_file(src, dst, force) == -1)
00038 return getErrorText(errno);
00039 else
00040 return NULL;
00041 }
00042 else
00043 {
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #ifdef PAGE_CONVERSION
00055 if (pageConverter->convertFile)
00056 return pageConverter->convertFile(pageConverter->pluginData,
00057 dst, src);
00058 else
00059 #endif
00060 {
00061 int src_fd;
00062 int dstfd;
00063 char buf[BLCKSZ];
00064 ssize_t bytesRead;
00065 const char *msg = NULL;
00066
00067 if ((src_fd = open(src, O_RDONLY, 0)) < 0)
00068 return "could not open source file";
00069
00070 if ((dstfd = open(dst, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) < 0)
00071 {
00072 close(src_fd);
00073 return "could not create destination file";
00074 }
00075
00076 while ((bytesRead = read(src_fd, buf, BLCKSZ)) == BLCKSZ)
00077 {
00078 #ifdef PAGE_CONVERSION
00079 if ((msg = pageConverter->convertPage(pageConverter->pluginData, buf, buf)) != NULL)
00080 break;
00081 #endif
00082 if (write(dstfd, buf, BLCKSZ) != BLCKSZ)
00083 {
00084 msg = "could not write new page to destination";
00085 break;
00086 }
00087 }
00088
00089 close(src_fd);
00090 close(dstfd);
00091
00092 if (msg)
00093 return msg;
00094 else if (bytesRead != 0)
00095 return "found partial page in source file";
00096 else
00097 return NULL;
00098 }
00099 }
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 const char *
00113 linkAndUpdateFile(pageCnvCtx *pageConverter,
00114 const char *src, const char *dst)
00115 {
00116 if (pageConverter != NULL)
00117 return "Cannot in-place update this cluster, page-by-page conversion is required";
00118
00119 if (pg_link_file(src, dst) == -1)
00120 return getErrorText(errno);
00121 else
00122 return NULL;
00123 }
00124
00125
00126 #ifndef WIN32
00127 static int
00128 copy_file(const char *srcfile, const char *dstfile, bool force)
00129 {
00130
00131 #define COPY_BUF_SIZE (50 * BLCKSZ)
00132
00133 int src_fd;
00134 int dest_fd;
00135 char *buffer;
00136 int ret = 0;
00137 int save_errno = 0;
00138
00139 if ((srcfile == NULL) || (dstfile == NULL))
00140 return -1;
00141
00142 if ((src_fd = open(srcfile, O_RDONLY, 0)) < 0)
00143 return -1;
00144
00145 if ((dest_fd = open(dstfile, O_RDWR | O_CREAT | (force ? 0 : O_EXCL), S_IRUSR | S_IWUSR)) < 0)
00146 {
00147 if (src_fd != 0)
00148 close(src_fd);
00149
00150 return -1;
00151 }
00152
00153 buffer = (char *) pg_malloc(COPY_BUF_SIZE);
00154
00155
00156 while (true)
00157 {
00158 ssize_t nbytes = read(src_fd, buffer, COPY_BUF_SIZE);
00159
00160 if (nbytes < 0)
00161 {
00162 save_errno = errno;
00163 ret = -1;
00164 break;
00165 }
00166
00167 if (nbytes == 0)
00168 break;
00169
00170 errno = 0;
00171
00172 if (write(dest_fd, buffer, nbytes) != nbytes)
00173 {
00174 save_errno = errno;
00175 ret = -1;
00176 break;
00177 }
00178 }
00179
00180 pg_free(buffer);
00181
00182 if (src_fd != 0)
00183 close(src_fd);
00184
00185 if (dest_fd != 0)
00186 close(dest_fd);
00187
00188 if (save_errno != 0)
00189 errno = save_errno;
00190
00191 return ret;
00192 }
00193 #endif
00194
00195
00196 void
00197 check_hard_link(void)
00198 {
00199 char existing_file[MAXPGPATH];
00200 char new_link_file[MAXPGPATH];
00201
00202 snprintf(existing_file, sizeof(existing_file), "%s/PG_VERSION", old_cluster.pgdata);
00203 snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.linktest", new_cluster.pgdata);
00204 unlink(new_link_file);
00205
00206 if (pg_link_file(existing_file, new_link_file) == -1)
00207 {
00208 pg_log(PG_FATAL,
00209 "Could not create hard link between old and new data directories: %s\n"
00210 "In link mode the old and new data directories must be on the same file system volume.\n",
00211 getErrorText(errno));
00212 }
00213 unlink(new_link_file);
00214 }
00215
00216 #ifdef WIN32
00217 static int
00218 win32_pghardlink(const char *src, const char *dst)
00219 {
00220
00221
00222
00223
00224 if (CreateHardLinkA(dst, src, NULL) == 0)
00225 return -1;
00226 else
00227 return 0;
00228 }
00229 #endif
00230
00231
00232
00233 FILE *
00234 fopen_priv(const char *path, const char *mode)
00235 {
00236 mode_t old_umask = umask(S_IRWXG | S_IRWXO);
00237 FILE *fp;
00238
00239 fp = fopen(path, mode);
00240 umask(old_umask);
00241
00242 return fp;
00243 }