On Fri, Mar 09, 2012 at 10:41:53AM -0500, Tom Lane wrote: > Bruce Momjian <br...@momjian.us> writes: > > The problem is that these files are being created often by shell > > redirects, e.g. pg_dump -f out 2> log_file. There is no clean way to > > control the file creation permissions in this case --- only umask gives > > us a process-level setting. Actually, one crafty idea would be to do > > the umask only when I exec something, and when I create the initial > > files with the new banner you suggested. Let me look into that. > > You could create empty log files with the desired permissions, and then > do the execs with >>log_file, and thereby not have to globally change > umask.
Yes, that is what I have done, with the attached patch. I basically wrapped the fopen call with umask calls, and have the system() call wrapped too. That takes care of all the files pg_upgrade creates. > > Frankly, the permissions are already being modified by the default > > umask, e.g. 0022. Do we want a zero umask? > > I'm not so worried about default umask; nobody's complained yet about > wrong permissions on pg_upgrade output files. But umask 077 would be > likely to do things like get rid of group access to postgresql.conf, > which some people intentionally set. Yes, that was my conclusion too, but I wanted to ask. FYI, this doesn't affect the install itself, just what pg_upgrade changes, and it doesn't touch postgresql.conf, but, as you, I am worried there might be long-term problems with an aggressive umask that covered the entire executable. -- Bruce Momjian <br...@momjian.us> http://momjian.us EnterpriseDB http://enterprisedb.com + It's impossible for everything to be true. +
diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c new file mode 100644 index a5f63eb..7905534 *** a/contrib/pg_upgrade/check.c --- b/contrib/pg_upgrade/check.c *************** issue_warnings(char *sequence_script_fil *** 165,176 **** if (sequence_script_file_name) { prep_status("Adjusting sequences"); ! exec_prog(true, ! SYSTEMQUOTE "\"%s/psql\" --set ON_ERROR_STOP=on " "--no-psqlrc --port %d --username \"%s\" " ! "-f \"%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE, new_cluster.bindir, new_cluster.port, os_info.user, ! sequence_script_file_name, log_opts.filename2); unlink(sequence_script_file_name); check_ok(); } --- 165,177 ---- if (sequence_script_file_name) { prep_status("Adjusting sequences"); ! exec_prog(true, UTILITY_LOG_FILE, ! SYSTEMQUOTE "\"%s/psql\" --echo-queries " ! "--set ON_ERROR_STOP=on " "--no-psqlrc --port %d --username \"%s\" " ! "-f \"%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE, new_cluster.bindir, new_cluster.port, os_info.user, ! sequence_script_file_name, UTILITY_LOG_FILE); unlink(sequence_script_file_name); check_ok(); } diff --git a/contrib/pg_upgrade/controldata.c b/contrib/pg_upgrade/controldata.c new file mode 100644 index 5239601..e01280d *** a/contrib/pg_upgrade/controldata.c --- b/contrib/pg_upgrade/controldata.c *************** get_control_data(ClusterInfo *cluster, b *** 126,136 **** /* we have the result of cmd in "output". so parse it line by line now */ while (fgets(bufin, sizeof(bufin), output)) { ! if (log_opts.debug) ! fputs(bufin, log_opts.debug_fd); #ifdef WIN32 - /* * Due to an installer bug, LANG=C doesn't work for PG 8.3.3, but does * work 8.2.6 and 8.3.7, so check for non-ASCII output and suggest a --- 126,134 ---- /* we have the result of cmd in "output". so parse it line by line now */ while (fgets(bufin, sizeof(bufin), output)) { ! pg_log(PG_VERBOSE, "%s", bufin); #ifdef WIN32 /* * Due to an installer bug, LANG=C doesn't work for PG 8.3.3, but does * work 8.2.6 and 8.3.7, so check for non-ASCII output and suggest a diff --git a/contrib/pg_upgrade/dump.c b/contrib/pg_upgrade/dump.c new file mode 100644 index 772ca37..b1d4034 *** a/contrib/pg_upgrade/dump.c --- b/contrib/pg_upgrade/dump.c *************** *** 11,16 **** --- 11,17 ---- #include "pg_upgrade.h" + #include <sys/types.h> void generate_old_dump(void) *************** generate_old_dump(void) *** 22,31 **** * --binary-upgrade records the width of dropped columns in pg_class, and * restores the frozenid's for databases and relations. */ ! exec_prog(true, SYSTEMQUOTE "\"%s/pg_dumpall\" --port %d --username \"%s\" " ! "--schema-only --binary-upgrade > \"%s/" ALL_DUMP_FILE "\"" ! SYSTEMQUOTE, new_cluster.bindir, old_cluster.port, os_info.user, os_info.cwd); check_ok(); } --- 23,33 ---- * --binary-upgrade records the width of dropped columns in pg_class, and * restores the frozenid's for databases and relations. */ ! exec_prog(true, UTILITY_LOG_FILE, SYSTEMQUOTE "\"%s/pg_dumpall\" --port %d --username \"%s\" " ! "--schema-only --binary-upgrade > \"%s/%s\" 2>> \"%s\"" ! SYSTEMQUOTE, new_cluster.bindir, old_cluster.port, os_info.user, ! os_info.cwd, ALL_DUMP_FILE, UTILITY_LOG_FILE); check_ok(); } *************** split_old_dump(void) *** 55,60 **** --- 57,63 ---- char create_role_str_quote[MAX_STRING]; char filename[MAXPGPATH]; bool suppressed_username = false; + mode_t old_umask = umask(S_IRWXG | S_IRWXO); snprintf(filename, sizeof(filename), "%s/%s", os_info.cwd, ALL_DUMP_FILE); if ((all_dump = fopen(filename, "r")) == NULL) *************** split_old_dump(void) *** 65,70 **** --- 68,75 ---- snprintf(filename, sizeof(filename), "%s/%s", os_info.cwd, DB_DUMP_FILE); if ((db_dump = fopen(filename, "w")) == NULL) pg_log(PG_FATAL, "Could not write to dump file \"%s\": %s\n", filename, getErrorText(errno)); + + umask(old_umask); current_output = globals_dump; /* patterns used to prevent our own username from being recreated */ diff --git a/contrib/pg_upgrade/exec.c b/contrib/pg_upgrade/exec.c new file mode 100644 index b870ded..1f6b25a *** a/contrib/pg_upgrade/exec.c --- b/contrib/pg_upgrade/exec.c *************** *** 13,19 **** #include <fcntl.h> #include <unistd.h> ! static void check_data_dir(const char *pg_data); static void check_bin_dir(ClusterInfo *cluster); --- 13,19 ---- #include <fcntl.h> #include <unistd.h> ! #include <sys/types.h> static void check_data_dir(const char *pg_data); static void check_bin_dir(ClusterInfo *cluster); *************** static int win32_check_directory_write_p *** 34,57 **** * instead of returning should an error occur. */ int ! exec_prog(bool throw_error, const char *fmt,...) { va_list args; int result; char cmd[MAXPGPATH]; va_start(args, fmt); vsnprintf(cmd, MAXPGPATH, fmt, args); va_end(args); ! pg_log(PG_INFO, "%s\n", cmd); result = system(cmd); if (result != 0) { ! pg_log(throw_error ? PG_FATAL : PG_INFO, ! "There were problems executing \"%s\"\n", cmd); return 1; } --- 34,65 ---- * instead of returning should an error occur. */ int ! exec_prog(bool throw_error, const char *log_file, const char *fmt,...) { va_list args; int result; char cmd[MAXPGPATH]; + mode_t old_umask = umask(S_IRWXG | S_IRWXO); va_start(args, fmt); vsnprintf(cmd, MAXPGPATH, fmt, args); va_end(args); ! pg_log(PG_VERBOSE, "%s\n", cmd); result = system(cmd); + umask(old_umask); + if (result != 0) { ! report_status(PG_REPORT, "*failure*"); ! fflush(stdout); ! pg_log(PG_VERBOSE, "There were problems executing \"%s\"\n", cmd); ! pg_log(throw_error ? PG_FATAL : PG_REPORT, ! "Consult the last few lines of \"%s\" for\n" ! "the probable cause of the failure.\n", ! log_file); return 1; } diff --git a/contrib/pg_upgrade/info.c b/contrib/pg_upgrade/info.c new file mode 100644 index 692cdc2..36683fa *** a/contrib/pg_upgrade/info.c --- b/contrib/pg_upgrade/info.c *************** create_rel_filename_map(const char *old_ *** 132,150 **** void print_maps(FileNameMap *maps, int n_maps, const char *db_name) { ! if (log_opts.debug) { int mapnum; ! pg_log(PG_DEBUG, "mappings for database \"%s\":\n", db_name); for (mapnum = 0; mapnum < n_maps; mapnum++) ! pg_log(PG_DEBUG, "%s.%s: %u to %u\n", maps[mapnum].nspname, maps[mapnum].relname, maps[mapnum].old_relfilenode, maps[mapnum].new_relfilenode); ! pg_log(PG_DEBUG, "\n\n"); } } --- 132,150 ---- void print_maps(FileNameMap *maps, int n_maps, const char *db_name) { ! if (log_opts.verbose) { int mapnum; ! pg_log(PG_VERBOSE, "mappings for database \"%s\":\n", db_name); for (mapnum = 0; mapnum < n_maps; mapnum++) ! pg_log(PG_VERBOSE, "%s.%s: %u to %u\n", maps[mapnum].nspname, maps[mapnum].relname, maps[mapnum].old_relfilenode, maps[mapnum].new_relfilenode); ! pg_log(PG_VERBOSE, "\n\n"); } } *************** get_db_and_rel_infos(ClusterInfo *cluste *** 168,178 **** for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) get_rel_infos(cluster, &cluster->dbarr.dbs[dbnum]); ! if (log_opts.debug) ! { ! pg_log(PG_DEBUG, "\n%s databases:\n", CLUSTER_NAME(cluster)); print_db_infos(&cluster->dbarr); - } } --- 168,176 ---- for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) get_rel_infos(cluster, &cluster->dbarr.dbs[dbnum]); ! pg_log(PG_VERBOSE, "\n%s databases:\n", CLUSTER_NAME(cluster)); ! if (log_opts.verbose) print_db_infos(&cluster->dbarr); } *************** print_db_infos(DbInfoArr *db_arr) *** 368,376 **** for (dbnum = 0; dbnum < db_arr->ndbs; dbnum++) { ! pg_log(PG_DEBUG, "Database: %s\n", db_arr->dbs[dbnum].db_name); print_rel_infos(&db_arr->dbs[dbnum].rel_arr); ! pg_log(PG_DEBUG, "\n\n"); } } --- 366,374 ---- for (dbnum = 0; dbnum < db_arr->ndbs; dbnum++) { ! pg_log(PG_VERBOSE, "Database: %s\n", db_arr->dbs[dbnum].db_name); print_rel_infos(&db_arr->dbs[dbnum].rel_arr); ! pg_log(PG_VERBOSE, "\n\n"); } } *************** print_rel_infos(RelInfoArr *arr) *** 381,387 **** int relnum; for (relnum = 0; relnum < arr->nrels; relnum++) ! pg_log(PG_DEBUG, "relname: %s.%s: reloid: %u reltblspace: %s\n", arr->rels[relnum].nspname, arr->rels[relnum].relname, arr->rels[relnum].reloid, arr->rels[relnum].tablespace); } --- 379,385 ---- int relnum; for (relnum = 0; relnum < arr->nrels; relnum++) ! pg_log(PG_VERBOSE, "relname: %s.%s: reloid: %u reltblspace: %s\n", arr->rels[relnum].nspname, arr->rels[relnum].relname, arr->rels[relnum].reloid, arr->rels[relnum].tablespace); } diff --git a/contrib/pg_upgrade/option.c b/contrib/pg_upgrade/option.c new file mode 100644 index 0a105ef..1cc780d *** a/contrib/pg_upgrade/option.c --- b/contrib/pg_upgrade/option.c *************** *** 11,18 **** #include "pg_upgrade.h" ! #include "getopt_long.h" ! #ifdef WIN32 #include <io.h> #endif --- 11,20 ---- #include "pg_upgrade.h" ! #include <getopt_long.h> ! #include <time.h> ! #include <sys/types.h> ! #include <sys/stat.h> #ifdef WIN32 #include <io.h> #endif *************** parseCommandLine(int argc, char *argv[]) *** 46,63 **** {"user", required_argument, NULL, 'u'}, {"check", no_argument, NULL, 'c'}, - {"debug", no_argument, NULL, 'g'}, - {"debugfile", required_argument, NULL, 'G'}, {"link", no_argument, NULL, 'k'}, ! {"logfile", required_argument, NULL, 'l'}, {"verbose", no_argument, NULL, 'v'}, {NULL, 0, NULL, 0} }; int option; /* Command line option */ int optindex = 0; /* used by getopt_long */ int os_user_effective_id; char *return_buf; ! user_opts.transfer_mode = TRANSFER_MODE_COPY; os_info.progname = get_progname(argv[0]); --- 48,66 ---- {"user", required_argument, NULL, 'u'}, {"check", no_argument, NULL, 'c'}, {"link", no_argument, NULL, 'k'}, ! {"retain", no_argument, NULL, 'r'}, {"verbose", no_argument, NULL, 'v'}, {NULL, 0, NULL, 0} }; int option; /* Command line option */ int optindex = 0; /* used by getopt_long */ int os_user_effective_id; + FILE *fp; char *return_buf; ! int i; ! time_t run_time = time(NULL); ! user_opts.transfer_mode = TRANSFER_MODE_COPY; os_info.progname = get_progname(argv[0]); *************** parseCommandLine(int argc, char *argv[]) *** 98,104 **** if (return_buf == NULL) pg_log(PG_FATAL, "Could not access current working directory: %s\n", getErrorText(errno)); ! while ((option = getopt_long(argc, argv, "d:D:b:B:cgG:kl:o:O:p:P:u:v", long_options, &optindex)) != -1) { switch (option) --- 101,116 ---- if (return_buf == NULL) pg_log(PG_FATAL, "Could not access current working directory: %s\n", getErrorText(errno)); ! { ! mode_t old_umask = umask(S_IRWXG | S_IRWXO); ! ! if ((log_opts.fp = fopen(INTERNAL_LOG_FILE, "a")) == NULL) ! pg_log(PG_FATAL, "cannot write to log file %s\n", INTERNAL_LOG_FILE); ! ! umask(old_umask); ! } ! ! while ((option = getopt_long(argc, argv, "d:D:b:B:cko:O:p:P:ru:v", long_options, &optindex)) != -1) { switch (option) *************** parseCommandLine(int argc, char *argv[]) *** 125,151 **** new_cluster.pgconfig = pg_strdup(optarg); break; - case 'g': - pg_log(PG_REPORT, "Running in debug mode\n"); - log_opts.debug = true; - break; - - case 'G': - if ((log_opts.debug_fd = fopen(optarg, "w")) == NULL) - { - pg_log(PG_FATAL, "cannot open debug file\n"); - exit(1); - } - break; - case 'k': user_opts.transfer_mode = TRANSFER_MODE_LINK; break; - case 'l': - log_opts.filename = pg_strdup(optarg); - break; - case 'o': old_cluster.pgopts = pg_strdup(optarg); break; --- 137,146 ---- *************** parseCommandLine(int argc, char *argv[]) *** 175,180 **** --- 170,179 ---- } break; + case 'r': + log_opts.retain = true; + break; + case 'u': pg_free(os_info.user); os_info.user = pg_strdup(optarg); *************** parseCommandLine(int argc, char *argv[]) *** 199,234 **** } } ! if (log_opts.filename != NULL) { ! /* ! * We must use append mode so output generated by child processes via ! * ">>" will not be overwritten, and we want the file truncated on ! * start. ! */ ! /* truncate */ ! if ((log_opts.fd = fopen(log_opts.filename, "w")) == NULL) ! pg_log(PG_FATAL, "cannot write to log file %s\n", log_opts.filename); ! fclose(log_opts.fd); ! if ((log_opts.fd = fopen(log_opts.filename, "a")) == NULL) ! pg_log(PG_FATAL, "cannot write to log file %s\n", log_opts.filename); ! } ! else ! log_opts.filename = pg_strdup(DEVNULL); ! /* WIN32 files do not accept writes from multiple processes */ ! #ifndef WIN32 ! log_opts.filename2 = pg_strdup(log_opts.filename); ! #else ! log_opts.filename2 = pg_strdup(DEVNULL); ! #endif ! ! /* if no debug file name, output to the terminal */ ! if (log_opts.debug && !log_opts.debug_fd) ! { ! log_opts.debug_fd = fopen(DEVTTY, "w"); ! if (!log_opts.debug_fd) ! pg_log(PG_FATAL, "cannot write to terminal\n"); } /* Get values from env if not already set */ --- 198,219 ---- } } ! /* label start of upgrade in logfiles */ ! for (i = 0; i < NUM_LOG_FILES; i++) { ! mode_t old_umask = umask(S_IRWXG | S_IRWXO); ! if ((fp = fopen(output_files[i], "a")) == NULL) ! pg_log(PG_FATAL, "cannot write to log file %s\n", ! output_files[i]); ! fprintf(fp, "\n" ! "-----------------------------------------------------------------\n" ! " pg_upgrade run on %s" ! "-----------------------------------------------------------------\n\n", ! ctime(&run_time)); ! fclose(fp); ! ! umask(old_umask); } /* Get values from env if not already set */ *************** Options:\n\ *** 256,271 **** -c, --check check clusters only, don't change any data\n\ -d, --old-datadir=OLDDATADIR old cluster data directory\n\ -D, --new-datadir=NEWDATADIR new cluster data directory\n\ - -g, --debug enable debugging\n\ - -G, --debugfile=FILENAME output debugging activity to file\n\ -k, --link link instead of copying files to new cluster\n\ - -l, --logfile=FILENAME log internal activity to file\n\ -o, --old-options=OPTIONS old cluster options to pass to the server\n\ -O, --new-options=OPTIONS new cluster options to pass to the server\n\ -p, --old-port=OLDPORT old cluster port number (default %d)\n\ -P, --new-port=NEWPORT new cluster port number (default %d)\n\ -u, --user=NAME cluster superuser (default \"%s\")\n\ ! -v, --verbose enable verbose output\n\ -V, --version display version information, then exit\n\ -h, --help show this help, then exit\n\ \n\ --- 241,254 ---- -c, --check check clusters only, don't change any data\n\ -d, --old-datadir=OLDDATADIR old cluster data directory\n\ -D, --new-datadir=NEWDATADIR new cluster data directory\n\ -k, --link link instead of copying files to new cluster\n\ -o, --old-options=OPTIONS old cluster options to pass to the server\n\ -O, --new-options=OPTIONS new cluster options to pass to the server\n\ -p, --old-port=OLDPORT old cluster port number (default %d)\n\ -P, --new-port=NEWPORT new cluster port number (default %d)\n\ + -r, --retain retain SQL and log files after success\n\ -u, --user=NAME cluster superuser (default \"%s\")\n\ ! -v, --verbose enable verbose internal logging\n\ -V, --version display version information, then exit\n\ -h, --help show this help, then exit\n\ \n\ *************** adjust_data_dir(ClusterInfo *cluster) *** 354,372 **** { char filename[MAXPGPATH]; char cmd[MAXPGPATH], cmd_output[MAX_STRING]; ! FILE *fd, *output; /* If there is no postgresql.conf, it can't be a config-only dir */ snprintf(filename, sizeof(filename), "%s/postgresql.conf", cluster->pgconfig); ! if ((fd = fopen(filename, "r")) == NULL) return; ! fclose(fd); /* If PG_VERSION exists, it can't be a config-only dir */ snprintf(filename, sizeof(filename), "%s/PG_VERSION", cluster->pgconfig); ! if ((fd = fopen(filename, "r")) != NULL) { ! fclose(fd); return; } --- 337,355 ---- { char filename[MAXPGPATH]; char cmd[MAXPGPATH], cmd_output[MAX_STRING]; ! FILE *fp, *output; /* If there is no postgresql.conf, it can't be a config-only dir */ snprintf(filename, sizeof(filename), "%s/postgresql.conf", cluster->pgconfig); ! if ((fp = fopen(filename, "r")) == NULL) return; ! fclose(fp); /* If PG_VERSION exists, it can't be a config-only dir */ snprintf(filename, sizeof(filename), "%s/PG_VERSION", cluster->pgconfig); ! if ((fp = fopen(filename, "r")) != NULL) { ! fclose(fp); return; } diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c new file mode 100644 index 3078bcd..a4511bb *** a/contrib/pg_upgrade/pg_upgrade.c --- b/contrib/pg_upgrade/pg_upgrade.c *************** ClusterInfo old_cluster, *** 55,60 **** --- 55,68 ---- new_cluster; OSInfo os_info; + char *output_files[NUM_LOG_FILES] = { + SERVER_LOG_FILE, + RESTORE_LOG_FILE, + UTILITY_LOG_FILE, + INTERNAL_LOG_FILE + }; + + int main(int argc, char **argv) { *************** main(int argc, char **argv) *** 127,135 **** * because there is no need to have the schema load use new oids. */ prep_status("Setting next OID for new cluster"); ! exec_prog(true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -o %u \"%s\" > " ! DEVNULL SYSTEMQUOTE, ! new_cluster.bindir, old_cluster.controldata.chkpnt_nxtoid, new_cluster.pgdata); check_ok(); create_script_for_old_cluster_deletion(&deletion_script_file_name); --- 135,145 ---- * because there is no need to have the schema load use new oids. */ prep_status("Setting next OID for new cluster"); ! exec_prog(true, UTILITY_LOG_FILE, ! SYSTEMQUOTE "\"%s/pg_resetxlog\" -o %u \"%s\" >> \"%s\" 2>&1" ! SYSTEMQUOTE, ! new_cluster.bindir, old_cluster.controldata.chkpnt_nxtoid, ! new_cluster.pgdata, UTILITY_LOG_FILE); check_ok(); create_script_for_old_cluster_deletion(&deletion_script_file_name); *************** prepare_new_cluster(void) *** 193,202 **** * --analyze so autovacuum doesn't update statistics later */ prep_status("Analyzing all rows in the new cluster"); ! exec_prog(true, SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" " "--all --analyze >> \"%s\" 2>&1" SYSTEMQUOTE, ! new_cluster.bindir, new_cluster.port, os_info.user, log_opts.filename2); check_ok(); /* --- 203,212 ---- * --analyze so autovacuum doesn't update statistics later */ prep_status("Analyzing all rows in the new cluster"); ! exec_prog(true, UTILITY_LOG_FILE, SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" " "--all --analyze >> \"%s\" 2>&1" SYSTEMQUOTE, ! new_cluster.bindir, new_cluster.port, os_info.user, UTILITY_LOG_FILE); check_ok(); /* *************** prepare_new_cluster(void) *** 206,215 **** * later. */ prep_status("Freezing all rows on the new cluster"); ! exec_prog(true, SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" " "--all --freeze >> \"%s\" 2>&1" SYSTEMQUOTE, ! new_cluster.bindir, new_cluster.port, os_info.user, log_opts.filename2); check_ok(); get_pg_database_relfilenode(&new_cluster); --- 216,225 ---- * later. */ prep_status("Freezing all rows on the new cluster"); ! exec_prog(true, UTILITY_LOG_FILE, SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" " "--all --freeze >> \"%s\" 2>&1" SYSTEMQUOTE, ! new_cluster.bindir, new_cluster.port, os_info.user, UTILITY_LOG_FILE); check_ok(); get_pg_database_relfilenode(&new_cluster); *************** prepare_new_databases(void) *** 243,255 **** * support functions in template1 but pg_dumpall creates database using * the template0 template. */ ! exec_prog(true, ! SYSTEMQUOTE "\"%s/psql\" --set ON_ERROR_STOP=on " ! /* --no-psqlrc prevents AUTOCOMMIT=off */ "--no-psqlrc --port %d --username \"%s\" " ! "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE, new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd, ! GLOBALS_DUMP_FILE, log_opts.filename2); check_ok(); /* we load this to get a current list of databases */ --- 253,266 ---- * support functions in template1 but pg_dumpall creates database using * the template0 template. */ ! exec_prog(true, RESTORE_LOG_FILE, ! SYSTEMQUOTE "\"%s/psql\" --echo-queries " ! "--set ON_ERROR_STOP=on " ! /* --no-psqlrc prevents AUTOCOMMIT=off */ "--no-psqlrc --port %d --username \"%s\" " ! "-f \"%s/%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE, new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd, ! GLOBALS_DUMP_FILE, RESTORE_LOG_FILE); check_ok(); /* we load this to get a current list of databases */ *************** create_new_objects(void) *** 275,286 **** check_ok(); prep_status("Restoring database schema to new cluster"); ! exec_prog(true, ! SYSTEMQUOTE "\"%s/psql\" --set ON_ERROR_STOP=on " "--no-psqlrc --port %d --username \"%s\" " ! "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE, new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd, ! DB_DUMP_FILE, log_opts.filename2); check_ok(); /* regenerate now that we have objects in the databases */ --- 286,298 ---- check_ok(); prep_status("Restoring database schema to new cluster"); ! exec_prog(true, RESTORE_LOG_FILE, ! SYSTEMQUOTE "\"%s/psql\" --echo-queries " ! "--set ON_ERROR_STOP=on " "--no-psqlrc --port %d --username \"%s\" " ! "-f \"%s/%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE, new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd, ! DB_DUMP_FILE, RESTORE_LOG_FILE); check_ok(); /* regenerate now that we have objects in the databases */ *************** copy_clog_xlog_xid(void) *** 306,334 **** check_ok(); prep_status("Copying old commit clogs to new server"); #ifndef WIN32 ! exec_prog(true, SYSTEMQUOTE "%s \"%s\" \"%s\"" SYSTEMQUOTE, "cp -Rf", #else /* flags: everything, no confirm, quiet, overwrite read-only */ ! exec_prog(true, SYSTEMQUOTE "%s \"%s\" \"%s\\\"" SYSTEMQUOTE, "xcopy /e /y /q /r", #endif ! old_clog_path, new_clog_path); check_ok(); /* set the next transaction id of the new cluster */ prep_status("Setting next transaction ID for new cluster"); ! exec_prog(true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -f -x %u \"%s\" > " DEVNULL SYSTEMQUOTE, ! new_cluster.bindir, old_cluster.controldata.chkpnt_nxtxid, new_cluster.pgdata); check_ok(); /* now reset the wal archives in the new cluster */ prep_status("Resetting WAL archives"); ! exec_prog(true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE, ! new_cluster.bindir, old_cluster.controldata.chkpnt_tli, ! old_cluster.controldata.logid, old_cluster.controldata.nxtlogseg, ! new_cluster.pgdata, log_opts.filename2); check_ok(); } --- 318,355 ---- check_ok(); prep_status("Copying old commit clogs to new server"); + exec_prog(true, UTILITY_LOG_FILE, #ifndef WIN32 ! SYSTEMQUOTE "%s \"%s\" \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE, "cp -Rf", #else /* flags: everything, no confirm, quiet, overwrite read-only */ ! SYSTEMQUOTE "%s \"%s\" \"%s\\\" >> \"%s\" 2>&1" SYSTEMQUOTE, "xcopy /e /y /q /r", #endif ! old_clog_path, new_clog_path, UTILITY_LOG_FILE); check_ok(); /* set the next transaction id of the new cluster */ prep_status("Setting next transaction ID for new cluster"); ! exec_prog(true, UTILITY_LOG_FILE, ! SYSTEMQUOTE ! "\"%s/pg_resetxlog\" -f -x %u \"%s\" >> \"%s\" 2>&1" ! SYSTEMQUOTE, new_cluster.bindir, ! old_cluster.controldata.chkpnt_nxtxid, ! new_cluster.pgdata, UTILITY_LOG_FILE); check_ok(); /* now reset the wal archives in the new cluster */ prep_status("Resetting WAL archives"); ! exec_prog(true, UTILITY_LOG_FILE, ! SYSTEMQUOTE ! "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1" ! SYSTEMQUOTE, new_cluster.bindir, ! old_cluster.controldata.chkpnt_tli, ! old_cluster.controldata.logid, ! old_cluster.controldata.nxtlogseg, ! new_cluster.pgdata, UTILITY_LOG_FILE); check_ok(); } *************** set_frozenxids(void) *** 421,438 **** static void cleanup(void) { ! char filename[MAXPGPATH]; ! if (log_opts.fd) ! fclose(log_opts.fd); ! if (log_opts.debug_fd) ! fclose(log_opts.debug_fd); ! snprintf(filename, sizeof(filename), "%s/%s", os_info.cwd, ALL_DUMP_FILE); ! unlink(filename); ! snprintf(filename, sizeof(filename), "%s/%s", os_info.cwd, GLOBALS_DUMP_FILE); ! unlink(filename); ! snprintf(filename, sizeof(filename), "%s/%s", os_info.cwd, DB_DUMP_FILE); ! unlink(filename); } --- 442,472 ---- static void cleanup(void) { ! ! fclose(log_opts.fp); ! /* Remove dump and log files? */ ! if (!log_opts.retain) ! { ! char filename[MAXPGPATH]; ! int i; ! for (i = 0; i < NUM_LOG_FILES; i++) ! { ! snprintf(filename, sizeof(filename), "%s/%s", os_info.cwd, ! output_files[i]); ! unlink(filename); ! } ! /* remove SQL files */ ! snprintf(filename, sizeof(filename), "%s/%s", os_info.cwd, ! ALL_DUMP_FILE); ! unlink(filename); ! snprintf(filename, sizeof(filename), "%s/%s", os_info.cwd, ! GLOBALS_DUMP_FILE); ! unlink(filename); ! snprintf(filename, sizeof(filename), "%s/%s", os_info.cwd, ! DB_DUMP_FILE); ! unlink(filename); ! } } diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h new file mode 100644 index a954815..cf7d78f *** a/contrib/pg_upgrade/pg_upgrade.h --- b/contrib/pg_upgrade/pg_upgrade.h *************** *** 35,40 **** --- 35,68 ---- #define GLOBALS_DUMP_FILE "pg_upgrade_dump_globals.sql" #define DB_DUMP_FILE "pg_upgrade_dump_db.sql" + #define SERVER_LOG_FILE "pg_upgrade_server.log" + #define RESTORE_LOG_FILE "pg_upgrade_restore.log" + #define UTILITY_LOG_FILE "pg_upgrade_utility.log" + #define INTERNAL_LOG_FILE "pg_upgrade_internal.log" + + #define NUM_LOG_FILES 4 + extern char *output_files[]; + + /* + * WIN32 files do not accept writes from multiple processes + * + * On Win32, we can't send both pg_upgrade output and command output to the + * same file because we get the error: "The process cannot access the file + * because it is being used by another process." so send the pg_ctl + * command-line output to the utility log file on Windows, rather than + * into the server log file. + * + * We could use the Windows pgwin32_open() flags to allow shared file + * writes but is unclear how all other tools would use those flags, so + * we just avoid it and log a little differently on Windows; we adjust + * the error message appropriately. + */ + #ifndef WIN32 + #define SERVER_LOG_FILE2 SERVER_LOG_FILE + #else + #define SERVER_LOG_FILE2 UTILITY_LOG_FILE + #endif + #ifndef WIN32 #define pg_copy_file copy_file #define pg_mv_file rename *************** typedef enum *** 166,176 **** */ typedef enum { ! PG_INFO, PG_REPORT, PG_WARNING, ! PG_FATAL, ! PG_DEBUG } eLogType; --- 194,203 ---- */ typedef enum { ! PG_VERBOSE, PG_REPORT, PG_WARNING, ! PG_FATAL } eLogType; *************** typedef struct *** 204,228 **** */ typedef struct { ! char *filename; /* name of log file (may be /dev/null) */ ! /* ! * WIN32 files do not accept writes from multiple processes ! * ! * On Win32, we can't send both pg_upgrade output and command output to the ! * same file because we get the error: "The process cannot access the file ! * because it is being used by another process." so we have to send all ! * other output to 'nul'. Therefore, we set this to DEVNULL on Win32, and ! * it equals 'filename' on all other platforms. ! * ! * We could use the Windows pgwin32_open() flags to allow shared file ! * writes but is unclear how all other tools would use those flags, so ! * we just avoid it and log a little less on Windows. ! */ ! char *filename2; ! FILE *fd; /* log FILE */ ! bool debug; /* TRUE -> log more information */ ! FILE *debug_fd; /* debug-level log FILE */ bool verbose; /* TRUE -> be verbose in messages */ } LogOpts; --- 231,239 ---- */ typedef struct { ! FILE *fp; /* log FILE */ bool verbose; /* TRUE -> be verbose in messages */ + bool retain; /* retain log files on success */ } LogOpts; *************** void split_old_dump(void); *** 294,301 **** /* exec.c */ ! int exec_prog(bool throw_error, const char *cmd, ...) ! __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3))); void verify_directories(void); bool is_server_running(const char *datadir); --- 305,312 ---- /* exec.c */ ! int exec_prog(bool throw_error, const char *log_file, const char *cmd, ...) ! __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4))); void verify_directories(void); bool is_server_running(const char *datadir); diff --git a/contrib/pg_upgrade/relfilenode.c b/contrib/pg_upgrade/relfilenode.c new file mode 100644 index a1e30b1..45d6c54 *** a/contrib/pg_upgrade/relfilenode.c --- b/contrib/pg_upgrade/relfilenode.c *************** transfer_relfile(pageCnvCtx *pageConvert *** 267,273 **** if (user_opts.transfer_mode == TRANSFER_MODE_COPY) { ! pg_log(PG_INFO, "copying \"%s\" to \"%s\"\n", old_file, new_file); if ((msg = copyAndUpdateFile(pageConverter, old_file, new_file, true)) != NULL) pg_log(PG_FATAL, "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n", --- 267,273 ---- if (user_opts.transfer_mode == TRANSFER_MODE_COPY) { ! pg_log(PG_VERBOSE, "copying \"%s\" to \"%s\"\n", old_file, new_file); if ((msg = copyAndUpdateFile(pageConverter, old_file, new_file, true)) != NULL) pg_log(PG_FATAL, "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n", *************** transfer_relfile(pageCnvCtx *pageConvert *** 275,281 **** } else { ! pg_log(PG_INFO, "linking \"%s\" to \"%s\"\n", old_file, new_file); if ((msg = linkAndUpdateFile(pageConverter, old_file, new_file)) != NULL) pg_log(PG_FATAL, --- 275,281 ---- } else { ! pg_log(PG_VERBOSE, "linking \"%s\" to \"%s\"\n", old_file, new_file); if ((msg = linkAndUpdateFile(pageConverter, old_file, new_file)) != NULL) pg_log(PG_FATAL, diff --git a/contrib/pg_upgrade/server.c b/contrib/pg_upgrade/server.c new file mode 100644 index 989af63..f8d7326 *** a/contrib/pg_upgrade/server.c --- b/contrib/pg_upgrade/server.c *************** executeQueryOrDie(PGconn *conn, const ch *** 80,86 **** vsnprintf(command, sizeof(command), fmt, args); va_end(args); ! pg_log(PG_DEBUG, "executing: %s\n", command); result = PQexec(conn, command); status = PQresultStatus(result); --- 80,86 ---- vsnprintf(command, sizeof(command), fmt, args); va_end(args); ! pg_log(PG_VERBOSE, "executing: %s\n", command); result = PQexec(conn, command); status = PQresultStatus(result); *************** start_postmaster(ClusterInfo *cluster) *** 161,177 **** snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" " "-o \"-p %d %s %s\" start >> \"%s\" 2>&1" SYSTEMQUOTE, ! cluster->bindir, log_opts.filename2, cluster->pgconfig, cluster->port, (cluster->controldata.cat_ver >= BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" : "-c autovacuum=off -c autovacuum_freeze_max_age=2000000000", ! cluster->pgopts ? cluster->pgopts : "", log_opts.filename2); /* * Don't throw an error right away, let connecting throw the error because * it might supply a reason for the failure. */ ! pg_ctl_return = exec_prog(false, "%s", cmd); /* Check to see if we can connect to the server; if not, report it. */ if ((conn = get_db_conn(cluster, "template1")) == NULL || --- 161,182 ---- snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" " "-o \"-p %d %s %s\" start >> \"%s\" 2>&1" SYSTEMQUOTE, ! cluster->bindir, SERVER_LOG_FILE, cluster->pgconfig, cluster->port, (cluster->controldata.cat_ver >= BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" : "-c autovacuum=off -c autovacuum_freeze_max_age=2000000000", ! cluster->pgopts ? cluster->pgopts : "", SERVER_LOG_FILE2); /* * Don't throw an error right away, let connecting throw the error because * it might supply a reason for the failure. */ ! pg_ctl_return = exec_prog(false, ! /* pass both file names if the differ */ ! (strcmp(SERVER_LOG_FILE, SERVER_LOG_FILE2) == 0) ? ! SERVER_LOG_FILE : ! SERVER_LOG_FILE " or " SERVER_LOG_FILE2, ! "%s", cmd); /* Check to see if we can connect to the server; if not, report it. */ if ((conn = get_db_conn(cluster, "template1")) == NULL || *************** stop_postmaster(bool fast) *** 211,221 **** snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"%s\" " "%s stop >> \"%s\" 2>&1" SYSTEMQUOTE, ! cluster->bindir, log_opts.filename2, cluster->pgconfig, cluster->pgopts ? cluster->pgopts : "", ! fast ? "-m fast" : "", log_opts.filename2); ! exec_prog(fast ? false : true, "%s", cmd); os_info.running_cluster = NULL; } --- 216,226 ---- snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"%s\" " "%s stop >> \"%s\" 2>&1" SYSTEMQUOTE, ! cluster->bindir, SERVER_LOG_FILE2, cluster->pgconfig, cluster->pgopts ? cluster->pgopts : "", ! fast ? "-m fast" : "", SERVER_LOG_FILE2); ! exec_prog(fast ? false : true, SERVER_LOG_FILE2, "%s", cmd); os_info.running_cluster = NULL; } diff --git a/contrib/pg_upgrade/util.c b/contrib/pg_upgrade/util.c new file mode 100644 index 94eaa18..b039269 *** a/contrib/pg_upgrade/util.c --- b/contrib/pg_upgrade/util.c *************** pg_log(eLogType type, char *fmt,...) *** 77,94 **** vsnprintf(message, sizeof(message), fmt, args); va_end(args); ! if (log_opts.fd != NULL) { ! fwrite(message, strlen(message), 1, log_opts.fd); /* if we are using OVERWRITE_MESSAGE, add newline */ if (strchr(message, '\r') != NULL) ! fwrite("\n", 1, 1, log_opts.fd); ! fflush(log_opts.fd); } switch (type) { ! case PG_INFO: if (log_opts.verbose) printf("%s", _(message)); break; --- 77,95 ---- vsnprintf(message, sizeof(message), fmt, args); va_end(args); ! /* PG_VERBOSE is only output in verbose mode */ ! if (type != PG_VERBOSE || log_opts.verbose) { ! fwrite(message, strlen(message), 1, log_opts.fp); /* if we are using OVERWRITE_MESSAGE, add newline */ if (strchr(message, '\r') != NULL) ! fwrite("\n", 1, 1, log_opts.fp); ! fflush(log_opts.fp); } switch (type) { ! case PG_VERBOSE: if (log_opts.verbose) printf("%s", _(message)); break; *************** pg_log(eLogType type, char *fmt,...) *** 104,114 **** exit(1); break; - case PG_DEBUG: - if (log_opts.debug) - fprintf(log_opts.debug_fd, "%s\n", _(message)); - break; - default: break; } --- 105,110 ---- diff --git a/doc/src/sgml/pgupgrade.sgml b/doc/src/sgml/pgupgrade.sgml new file mode 100644 index 4f263fe..6ecdfda *** a/doc/src/sgml/pgupgrade.sgml --- b/doc/src/sgml/pgupgrade.sgml *************** *** 91,120 **** </varlistentry> <varlistentry> - <term><option>-g</option></term> - <term><option>--debug</option></term> - <listitem><para>enable debugging</para></listitem> - </varlistentry> - - <varlistentry> - <term><option>-G</option> <replaceable>debug_filename</></term> - <term><option>--debugfile=</option><replaceable>debug_filename</></term> - <listitem><para>output debugging activity to file</para></listitem> - </varlistentry> - - <varlistentry> <term><option>-k</option></term> <term><option>--link</option></term> <listitem><para>use hard links instead of copying files to the new cluster</para></listitem> </varlistentry> <varlistentry> - <term><option>-l</option> <replaceable>log_filename</></term> - <term><option>--logfile=</option><replaceable>log_filename</></term> - <listitem><para>log internal activity to file</para></listitem> - </varlistentry> - - <varlistentry> <term><option>-o</option> <replaceable class="parameter">options</replaceable></term> <term><option>--old-options</option> <replaceable class="parameter">options</replaceable></term> <listitem><para>options to be passed directly to the --- 91,102 ---- *************** *** 143,148 **** --- 125,137 ---- </varlistentry> <varlistentry> + <term><option>-r</option></term> + <term><option>--retain</option></term> + <listitem><para>retain SQL and log files even after successful completion + </para></listitem> + </varlistentry> + + <varlistentry> <term><option>-u</option> <replaceable>user_name</></term> <term><option>--user=</option><replaceable>user_name</></term> <listitem><para>cluster's super user name; environment *************** *** 152,158 **** <varlistentry> <term><option>-v</option></term> <term><option>--verbose</option></term> ! <listitem><para>enable verbose output</para></listitem> </varlistentry> <varlistentry> --- 141,147 ---- <varlistentry> <term><option>-v</option></term> <term><option>--verbose</option></term> ! <listitem><para>enable verbose internal logging</para></listitem> </varlistentry> <varlistentry>
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers