2121
2222
2323static void usage (void );
24- static void check_required_directory (char * * dirpath ,char * * configpath ,
25- const char * envVarName ,const char * cmdLineOption ,const char * description );
24+ static void check_required_directory (char * * dirpath ,
25+ const char * envVarName ,bool useCwd ,
26+ const char * cmdLineOption ,const char * description );
2627#define FIX_DEFAULT_READ_ONLY "-c default_transaction_read_only=false"
2728
2829
@@ -52,6 +53,7 @@ parseCommandLine(int argc, char *argv[])
5253{"link" ,no_argument ,NULL ,'k' },
5354{"retain" ,no_argument ,NULL ,'r' },
5455{"jobs" ,required_argument ,NULL ,'j' },
56+ {"socketdir" ,required_argument ,NULL ,'s' },
5557{"verbose" ,no_argument ,NULL ,'v' },
5658{"clone" ,no_argument ,NULL ,1 },
5759
@@ -102,7 +104,7 @@ parseCommandLine(int argc, char *argv[])
102104if ((log_opts .internal = fopen_priv (INTERNAL_LOG_FILE ,"a" ))== NULL )
103105pg_fatal ("could not write to log file \"%s\"\n" ,INTERNAL_LOG_FILE );
104106
105- while ((option = getopt_long (argc ,argv ,"d:D:b:B:cj:ko:O:p:P:rU :v" ,
107+ while ((option = getopt_long (argc ,argv ,"d:D:b:B:cj:ko:O:p:P:rs:U :v" ,
106108long_options ,& optindex ))!= -1 )
107109{
108110switch (option )
@@ -121,12 +123,10 @@ parseCommandLine(int argc, char *argv[])
121123
122124case 'd' :
123125old_cluster .pgdata = pg_strdup (optarg );
124- old_cluster .pgconfig = pg_strdup (optarg );
125126break ;
126127
127128case 'D' :
128129new_cluster .pgdata = pg_strdup (optarg );
129- new_cluster .pgconfig = pg_strdup (optarg );
130130break ;
131131
132132case 'j' :
@@ -188,6 +188,10 @@ parseCommandLine(int argc, char *argv[])
188188log_opts .retain = true;
189189break ;
190190
191+ case 's' :
192+ user_opts .socketdir = pg_strdup (optarg );
193+ break ;
194+
191195case 'U' :
192196pg_free (os_info .user );
193197os_info .user = pg_strdup (optarg );
@@ -244,14 +248,16 @@ parseCommandLine(int argc, char *argv[])
244248pg_putenv ("PGOPTIONS" ,FIX_DEFAULT_READ_ONLY );
245249
246250/* Get values from env if not already set */
247- check_required_directory (& old_cluster .bindir ,NULL ,"PGBINOLD" ,"-b" ,
248- _ ("old cluster binaries reside" ));
249- check_required_directory (& new_cluster .bindir ,NULL ,"PGBINNEW" ,"-B" ,
250- _ ("new cluster binaries reside" ));
251- check_required_directory (& old_cluster .pgdata ,& old_cluster .pgconfig ,
252- "PGDATAOLD" ,"-d" ,_ ("old cluster data resides" ));
253- check_required_directory (& new_cluster .pgdata ,& new_cluster .pgconfig ,
254- "PGDATANEW" ,"-D" ,_ ("new cluster data resides" ));
251+ check_required_directory (& old_cluster .bindir ,"PGBINOLD" , false,
252+ "-b" ,_ ("old cluster binaries reside" ));
253+ check_required_directory (& new_cluster .bindir ,"PGBINNEW" , false,
254+ "-B" ,_ ("new cluster binaries reside" ));
255+ check_required_directory (& old_cluster .pgdata ,"PGDATAOLD" , false,
256+ "-d" ,_ ("old cluster data resides" ));
257+ check_required_directory (& new_cluster .pgdata ,"PGDATANEW" , false,
258+ "-D" ,_ ("new cluster data resides" ));
259+ check_required_directory (& user_opts .socketdir ,"PGSOCKETDIR" , true,
260+ "-s" ,_ ("sockets will be created" ));
255261
256262#ifdef WIN32
257263
@@ -296,6 +302,7 @@ usage(void)
296302printf (_ (" -p, --old-port=PORT old cluster port number (default %d)\n" ),old_cluster .port );
297303printf (_ (" -P, --new-port=PORT new cluster port number (default %d)\n" ),new_cluster .port );
298304printf (_ (" -r, --retain retain SQL and log files after success\n" ));
305+ printf (_ (" -s, --socketdir=DIR socket directory to use (default CWD)\n" ));
299306printf (_ (" -U, --username=NAME cluster superuser (default \"%s\")\n" ),os_info .user );
300307printf (_ (" -v, --verbose enable verbose internal logging\n" ));
301308printf (_ (" -V, --version display version information, then exit\n" ));
@@ -337,29 +344,32 @@ usage(void)
337344 * check_required_directory()
338345 *
339346 * Checks a directory option.
340- *dirpath - the directory name supplied on the command line
341- *configpath - optional configuration directory
347+ *dirpath - the directory name supplied on the command line, or NULL
342348 *envVarName - the name of an environment variable to get if dirpath is NULL
343- *cmdLineOption - the command line option corresponds to this directory (-o, -O, -n, -N)
349+ *useCwd - true if OK to default to CWD
350+ *cmdLineOption - the command line option for this directory
344351 *description - a description of this directory option
345352 *
346353 * We use the last two arguments to construct a meaningful error message if the
347354 * user hasn't provided the required directory name.
348355 */
349356static void
350- check_required_directory (char * * dirpath ,char * * configpath ,
351- const char * envVarName ,const char * cmdLineOption ,
352- const char * description )
357+ check_required_directory (char * * dirpath ,const char * envVarName ,bool useCwd ,
358+ const char * cmdLineOption ,const char * description )
353359{
354360if (* dirpath == NULL || strlen (* dirpath )== 0 )
355361{
356362const char * envVar ;
357363
358364if ((envVar = getenv (envVarName ))&& strlen (envVar ))
359- {
360365* dirpath = pg_strdup (envVar );
361- if (configpath )
362- * configpath = pg_strdup (envVar );
366+ else if (useCwd )
367+ {
368+ char cwd [MAXPGPATH ];
369+
370+ if (!getcwd (cwd ,MAXPGPATH ))
371+ pg_fatal ("could not determine current directory\n" );
372+ * dirpath = pg_strdup (cwd );
363373}
364374else
365375pg_fatal ("You must identify the directory where the %s.\n"
@@ -368,16 +378,10 @@ check_required_directory(char **dirpath, char **configpath,
368378}
369379
370380/*
371- *Trim off any trailing path separators because we construct paths by
372- * appending to this path.
381+ *Clean up the path, in particular trimming any trailing path separators,
382+ *because we construct paths by appending to this path.
373383 */
374- #ifndef WIN32
375- if ((* dirpath )[strlen (* dirpath )- 1 ]== '/' )
376- #else
377- if ((* dirpath )[strlen (* dirpath )- 1 ]== '/' ||
378- (* dirpath )[strlen (* dirpath )- 1 ]== '\\' )
379- #endif
380- (* dirpath )[strlen (* dirpath )- 1 ]= 0 ;
384+ canonicalize_path (* dirpath );
381385}
382386
383387/*
@@ -386,6 +390,10 @@ check_required_directory(char **dirpath, char **configpath,
386390 * If a configuration-only directory was specified, find the real data dir
387391 * by querying the running server. This has limited checking because we
388392 * can't check for a running server because we can't find postmaster.pid.
393+ *
394+ * On entry, cluster->pgdata has been set from command line or env variable,
395+ * but cluster->pgconfig isn't set. We fill both variables with corrected
396+ * values.
389397 */
390398void
391399adjust_data_dir (ClusterInfo * cluster )
@@ -396,6 +404,9 @@ adjust_data_dir(ClusterInfo *cluster)
396404FILE * fp ,
397405* output ;
398406
407+ /* Initially assume config dir and data dir are the same */
408+ cluster -> pgconfig = pg_strdup (cluster -> pgdata );
409+
399410/* If there is no postgresql.conf, it can't be a config-only dir */
400411snprintf (filename ,sizeof (filename ),"%s/postgresql.conf" ,cluster -> pgconfig );
401412if ((fp = fopen (filename ,"r" ))== NULL )
@@ -462,12 +473,7 @@ get_sock_dir(ClusterInfo *cluster, bool live_check)
462473if (GET_MAJOR_VERSION (cluster -> major_version ) >=901 )
463474{
464475if (!live_check )
465- {
466- /* Use the current directory for the socket */
467- cluster -> sockdir = pg_malloc (MAXPGPATH );
468- if (!getcwd (cluster -> sockdir ,MAXPGPATH ))
469- pg_fatal ("could not determine current directory\n" );
470- }
476+ cluster -> sockdir = user_opts .socketdir ;
471477else
472478{
473479/*