]> granicus.if.org Git - postgresql/commitdiff
Use plain mkdir() not pg_mkdir_p() to create subdirectories of PGDATA.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 7 Jan 2016 20:22:01 +0000 (15:22 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 7 Jan 2016 20:22:24 +0000 (15:22 -0500)
When we're creating subdirectories of PGDATA during initdb, we know darn
well that the parent directory exists (or should exist) and that the new
subdirectory doesn't (or shouldn't).  There is therefore no need to use
anything more complicated than mkdir().  Using pg_mkdir_p() just opens us
up to unexpected failure modes, such as the one exhibited in bug #13853
from Nuri Boardman.  It's not very clear why pg_mkdir_p() went wrong there,
but it is clear that we didn't need to be trying to create parent
directories in the first place.  We're not even saving any code, as proven
by the fact that this patch nets out at minus five lines.

Since this is a response to a field bug report, back-patch to all branches.

src/bin/initdb/initdb.c

index 3ed0d95df44e5c6570b3bc0f56fb9a39e577bcf9..bfd29c0c60fb5ba46b2ec60b5f1a90602975b1cc 100644 (file)
@@ -203,6 +203,7 @@ static const char *const subdirs[] = {
        "pg_snapshots",
        "pg_subtrans",
        "pg_twophase",
+       "pg_multixact",
        "pg_multixact/members",
        "pg_multixact/offsets",
        "base",
@@ -240,7 +241,6 @@ static FILE *popen_check(const char *command, const char *mode);
 static void exit_nicely(void);
 static char *get_id(void);
 static char *get_encoding_id(char *encoding_name);
-static bool mkdatadir(const char *subdir);
 static void set_input(char **dest, char *filename);
 static void check_input(char *path);
 static void write_version_file(char *extrapath);
@@ -928,29 +928,6 @@ find_matching_ts_config(const char *lc_type)
 }
 
 
-/*
- * make the data directory (or one of its subdirectories if subdir is not NULL)
- */
-static bool
-mkdatadir(const char *subdir)
-{
-       char       *path;
-
-       if (subdir)
-               path = psprintf("%s/%s", pg_data, subdir);
-       else
-               path = pg_strdup(pg_data);
-
-       if (pg_mkdir_p(path, S_IRWXU) == 0)
-               return true;
-
-       fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
-                       progname, path, strerror(errno));
-
-       return false;
-}
-
-
 /*
  * set name of given input file variable under data directory
  */
@@ -2915,8 +2892,12 @@ create_data_directory(void)
                                   pg_data);
                        fflush(stdout);
 
-                       if (!mkdatadir(NULL))
+                       if (pg_mkdir_p(pg_data, S_IRWXU) != 0)
+                       {
+                               fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
+                                               progname, pg_data, strerror(errno));
                                exit_nicely();
+                       }
                        else
                                check_ok();
 
@@ -3099,10 +3080,24 @@ initialize_data_directory(void)
        printf(_("creating subdirectories ... "));
        fflush(stdout);
 
-       for (i = 0; i < (sizeof(subdirs) / sizeof(char *)); i++)
+       for (i = 0; i < lengthof(subdirs); i++)
        {
-               if (!mkdatadir(subdirs[i]))
+               char       *path;
+
+               path = psprintf("%s/%s", pg_data, subdirs[i]);
+
+               /*
+                * The parent directory already exists, so we only need mkdir() not
+                * pg_mkdir_p() here, which avoids some failure modes; cf bug #13853.
+                */
+               if (mkdir(path, S_IRWXU) < 0)
+               {
+                       fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
+                                       progname, path, strerror(errno));
                        exit_nicely();
+               }
+
+               free(path);
        }
 
        check_ok();