Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 6711999

Browse files
committed
Move a couple of initdb's subroutines into src/port/.
mkdir_p and check_data_dir will be useful in CREATE TABLESPACE, since we have agreed that that command should handle subdirectory creation just like initdb creates the PGDATA directory. Push them into src/port/ so that they are available to both initdb and the backend. Rename to pg_mkdir_p and pg_check_dir, just to be on the safe side. Add FreeBSD's copyright notice to pgmkdirp.c, since that's where the code came from originally (this really should have been in initdb.c). Very marginal code/comment cleanup.
1 parent 04f4e10 commit 6711999

File tree

5 files changed

+240
-169
lines changed

5 files changed

+240
-169
lines changed

src/bin/initdb/initdb.c

Lines changed: 7 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
*
4141
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
4242
* Portions Copyright (c) 1994, Regents of the University of California
43-
* Portions taken from FreeBSD.
4443
*
4544
* src/bin/initdb/initdb.c
4645
*
@@ -152,11 +151,9 @@ static char **filter_lines_with_token(char **lines, const char *token);
152151
static char **readfile(const char *path);
153152
static void writefile(char *path, char **lines);
154153
static FILE *popen_check(const char *command, const char *mode);
155-
static int mkdir_p(char *path, mode_t omode);
156154
static void exit_nicely(void);
157155
static char *get_id(void);
158156
static char *get_encoding_id(char *encoding_name);
159-
static int check_data_dir(char *dir);
160157
static bool mkdatadir(const char *subdir);
161158
static void set_input(char **dest, char *filename);
162159
static void check_input(char *path);
@@ -470,110 +467,6 @@ popen_check(const char *command, const char *mode)
470467
return cmdfd;
471468
}
472469

473-
/* source stolen from FreeBSD /src/bin/mkdir/mkdir.c and adapted */
474-
475-
/*
476-
* this tries to build all the elements of a path to a directory a la mkdir -p
477-
* we assume the path is in canonical form, i.e. uses / as the separator
478-
* we also assume it isn't null.
479-
*
480-
* note that on failure, the path arg has been modified to show the particular
481-
* directory level we had problems with.
482-
*/
483-
static int
484-
mkdir_p(char *path, mode_t omode)
485-
{
486-
struct stat sb;
487-
mode_t numask,
488-
oumask;
489-
int first,
490-
last,
491-
retval;
492-
char *p;
493-
494-
p = path;
495-
oumask = 0;
496-
retval = 0;
497-
498-
#ifdef WIN32
499-
/* skip network and drive specifiers for win32 */
500-
if (strlen(p) >= 2)
501-
{
502-
if (p[0] == '/' && p[1] == '/')
503-
{
504-
/* network drive */
505-
p = strstr(p + 2, "/");
506-
if (p == NULL)
507-
return 1;
508-
}
509-
else if (p[1] == ':' &&
510-
((p[0] >= 'a' && p[0] <= 'z') ||
511-
(p[0] >= 'A' && p[0] <= 'Z')))
512-
{
513-
/* local drive */
514-
p += 2;
515-
}
516-
}
517-
#endif
518-
519-
if (p[0] == '/') /* Skip leading '/'. */
520-
++p;
521-
for (first = 1, last = 0; !last; ++p)
522-
{
523-
if (p[0] == '\0')
524-
last = 1;
525-
else if (p[0] != '/')
526-
continue;
527-
*p = '\0';
528-
if (!last && p[1] == '\0')
529-
last = 1;
530-
if (first)
531-
{
532-
/*
533-
* POSIX 1003.2: For each dir operand that does not name an
534-
* existing directory, effects equivalent to those caused by the
535-
* following command shall occcur:
536-
*
537-
* mkdir -p -m $(umask -S),u+wx $(dirname dir) && mkdir [-m mode]
538-
* dir
539-
*
540-
* We change the user's umask and then restore it, instead of
541-
* doing chmod's.
542-
*/
543-
oumask = umask(0);
544-
numask = oumask & ~(S_IWUSR | S_IXUSR);
545-
(void) umask(numask);
546-
first = 0;
547-
}
548-
if (last)
549-
(void) umask(oumask);
550-
551-
/* check for pre-existing directory; ok if it's a parent */
552-
if (stat(path, &sb) == 0)
553-
{
554-
if (!S_ISDIR(sb.st_mode))
555-
{
556-
if (last)
557-
errno = EEXIST;
558-
else
559-
errno = ENOTDIR;
560-
retval = 1;
561-
break;
562-
}
563-
}
564-
else if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0)
565-
{
566-
retval = 1;
567-
break;
568-
}
569-
if (!last)
570-
*p = '/';
571-
}
572-
if (!first && !last)
573-
(void) umask(oumask);
574-
return retval;
575-
}
576-
577470
/*
578471
* clean up any files we created on failure
579472
* if we created the data directory remove it too
@@ -801,59 +694,6 @@ find_matching_ts_config(const char *lc_type)
801694
}
802695

803696

804-
/*
805-
* make sure the directory either doesn't exist or is empty
806-
*
807-
* Returns 0 if nonexistent, 1 if exists and empty, 2 if not empty,
808-
* or -1 if trouble accessing directory
809-
*/
810-
static int
811-
check_data_dir(char *dir)
812-
{
813-
DIR *chkdir;
814-
struct dirent *file;
815-
int result = 1;
816-
817-
errno = 0;
818-
819-
chkdir = opendir(dir);
820-
821-
if (!chkdir)
822-
return (errno == ENOENT) ? 0 : -1;
823-
824-
while ((file = readdir(chkdir)) != NULL)
825-
{
826-
if (strcmp(".", file->d_name) == 0 ||
827-
strcmp("..", file->d_name) == 0)
828-
{
829-
/* skip this and parent directory */
830-
continue;
831-
}
832-
else
833-
{
834-
result = 2; /* not empty */
835-
break;
836-
}
837-
}
838-
839-
#ifdef WIN32
840-
841-
/*
842-
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
843-
* released version
844-
*/
845-
if (GetLastError() == ERROR_NO_MORE_FILES)
846-
errno = 0;
847-
#endif
848-
849-
closedir(chkdir);
850-
851-
if (errno != 0)
852-
result = -1; /* some kind of I/O error? */
853-
854-
return result;
855-
}
856-
857697
/*
858698
* make the data directory (or one of its subdirectories if subdir is not NULL)
859699
*/
@@ -870,7 +710,7 @@ mkdatadir(const char *subdir)
870710
else
871711
strcpy(path, pg_data);
872712

873-
if (mkdir_p(path, S_IRWXU) == 0)
713+
if (pg_mkdir_p(path, S_IRWXU) == 0)
874714
return true;
875715

876716
fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
@@ -2929,7 +2769,7 @@ main(int argc, char *argv[])
29292769
pqsignal(SIGPIPE, SIG_IGN);
29302770
#endif
29312771

2932-
switch (check_data_dir(pg_data))
2772+
switch (pg_check_dir(pg_data))
29332773
{
29342774
case 0:
29352775
/* PGDATA not there, must create it */
@@ -2995,16 +2835,16 @@ main(int argc, char *argv[])
29952835
exit_nicely();
29962836
}
29972837

2998-
/* check if the specified xlog directory is empty */
2999-
switch (check_data_dir(xlog_dir))
2838+
/* check if the specified xlog directory exists/is empty */
2839+
switch (pg_check_dir(xlog_dir))
30002840
{
30012841
case 0:
30022842
/* xlog directory not there, must create it */
30032843
printf(_("creating directory %s ... "),
30042844
xlog_dir);
30052845
fflush(stdout);
30062846

3007-
if (mkdir_p(xlog_dir, S_IRWXU) != 0)
2847+
if (pg_mkdir_p(xlog_dir, S_IRWXU) != 0)
30082848
{
30092849
fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
30102850
progname, xlog_dir, strerror(errno));
@@ -3015,6 +2855,7 @@ main(int argc, char *argv[])
30152855

30162856
made_new_xlogdir = true;
30172857
break;
2858+
30182859
case 1:
30192860
/* Present but empty, fix permissions and use it */
30202861
printf(_("fixing permissions on existing directory %s ... "),
@@ -3032,6 +2873,7 @@ main(int argc, char *argv[])
30322873

30332874
found_existing_xlogdir = true;
30342875
break;
2876+
30352877
case 2:
30362878
/* Present and not empty */
30372879
fprintf(stderr,

src/include/port.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,4 +441,10 @@ extern int pg_get_encoding_from_locale(const char *ctype);
441441
extern char *inet_net_ntop(int af, const void *src, int bits,
442442
char *dst, size_t size);
443443

444+
/* port/pgcheckdir.c */
445+
extern int pg_check_dir(const char *dir);
446+
447+
/* port/pgmkdirp.c */
448+
extern int pg_mkdir_p(char *path, int omode);
449+
444450
#endif /* PG_PORT_H */

src/port/Makefile

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
# libpgport_srv.a - contains object files without FRONTEND defined,
1515
# for use only by the backend binaries
1616
#
17-
# LIBOBJS is set by configure (via Makefile.global) to be the list of
18-
# object files that are conditionally needed as determined by configure's probing.
17+
# LIBOBJS is set by configure (via Makefile.global) to be the list of object
18+
# files that are conditionally needed as determined by configure's probing.
1919
# OBJS adds additional object files that are always compiled.
2020
#
2121
# IDENTIFICATION
@@ -30,8 +30,10 @@ include $(top_builddir)/src/Makefile.global
3030
override CPPFLAGS := -I$(top_builddir)/src/port -DFRONTEND $(CPPFLAGS)
3131
LIBS += $(PTHREAD_LIBS)
3232

33-
OBJS = $(LIBOBJS) chklocale.o dirmod.o exec.o inet_net_ntop.o noblock.o path.o \
34-
pgsleep.o pgstrcasecmp.o qsort.o qsort_arg.o sprompt.o thread.o
33+
OBJS = $(LIBOBJS) chklocale.o dirmod.o exec.o inet_net_ntop.o noblock.o \
34+
path.o pgcheckdir.o pgmkdirp.o pgsleep.o pgstrcasecmp.o \
35+
qsort.o qsort_arg.o sprompt.o thread.o
36+
3537
ifneq (,$(filter $(PORTNAME),cygwin win32))
3638
OBJS += pipe.o
3739
endif

src/port/pgcheckdir.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* src/port/pgcheckdir.c
4+
*
5+
* A simple subroutine to check whether a directory exists and is empty or not.
6+
* Useful in both initdb and the backend.
7+
*
8+
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
9+
* Portions Copyright (c) 1994, Regents of the University of California
10+
*
11+
*-------------------------------------------------------------------------
12+
*/
13+
14+
#include "c.h"
15+
16+
#include <dirent.h>
17+
18+
19+
/*
20+
* Test to see if a directory exists and is empty or not.
21+
*
22+
* Returns:
23+
* 0 if nonexistent
24+
* 1 if exists and empty
25+
* 2 if exists and not empty
26+
* -1 if trouble accessing directory (errno reflects the error)
27+
*/
28+
int
29+
pg_check_dir(const char *dir)
30+
{
31+
int result = 1;
32+
DIR *chkdir;
33+
struct dirent *file;
34+
35+
errno = 0;
36+
37+
chkdir = opendir(dir);
38+
39+
if (chkdir == NULL)
40+
return (errno == ENOENT) ? 0 : -1;
41+
42+
while ((file = readdir(chkdir)) != NULL)
43+
{
44+
if (strcmp(".", file->d_name) == 0 ||
45+
strcmp("..", file->d_name) == 0)
46+
{
47+
/* skip this and parent directory */
48+
continue;
49+
}
50+
else
51+
{
52+
result = 2; /* not empty */
53+
break;
54+
}
55+
}
56+
57+
#ifdef WIN32
58+
59+
/*
60+
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
61+
* released version
62+
*/
63+
if (GetLastError() == ERROR_NO_MORE_FILES)
64+
errno = 0;
65+
#endif
66+
67+
closedir(chkdir);
68+
69+
if (errno != 0)
70+
result = -1; /* some kind of I/O error? */
71+
72+
return result;
73+
}

0 commit comments

Comments
 (0)