@@ -58,6 +58,7 @@ static TablespaceList tablespace_dirs = {NULL, NULL};
5858static char * xlog_dir = "" ;
5959static char format = 'p' ;/* p(lain)/t(ar) */
6060static char * label = "pg_basebackup base backup" ;
61+ static bool noclean = false;
6162static bool showprogress = false;
6263static int verbose = 0 ;
6364static int compresslevel = 0 ;
@@ -69,6 +70,13 @@ static intstandby_message_timeout = 10 * 1000;/* 10 sec = default */
6970static pg_time_t last_progress_report = 0 ;
7071static int32 maxrate = 0 ;/* no limit by default */
7172
73+ static bool success = false;
74+ static bool made_new_pgdata = false;
75+ static bool found_existing_pgdata = false;
76+ static bool made_new_xlogdir = false;
77+ static bool found_existing_xlogdir = false;
78+ static bool made_tablespace_dirs = false;
79+ static bool found_tablespace_dirs = false;
7280
7381/* Progress counters */
7482static uint64 totalsize ;
@@ -82,6 +90,7 @@ static intbgpipe[2] = {-1, -1};
8290
8391/* Handle to child process */
8492static pid_t bgchild = -1 ;
93+ static bool in_log_streamer = false;
8594
8695/* End position for xlog streaming, empty string if unknown yet */
8796static XLogRecPtr xlogendptr ;
@@ -98,7 +107,7 @@ static PQExpBuffer recoveryconfcontents = NULL;
98107/* Function headers */
99108static void usage (void );
100109static void disconnect_and_exit (int code );
101- static void verify_dir_is_empty_or_create (char * dirname );
110+ static void verify_dir_is_empty_or_create (char * dirname , bool * created , bool * found );
102111static void progress_report (int tablespacenum ,const char * filename ,bool force );
103112
104113static void ReceiveTarFile (PGconn * conn ,PGresult * res ,int rownum );
@@ -114,6 +123,69 @@ static const char *get_tablespace_mapping(const char *dir);
114123static void tablespace_list_append (const char * arg );
115124
116125
126+ static void
127+ cleanup_directories_atexit (void )
128+ {
129+ if (success || in_log_streamer )
130+ return ;
131+
132+ if (!noclean )
133+ {
134+ if (made_new_pgdata )
135+ {
136+ fprintf (stderr ,_ ("%s: removing data directory \"%s\"\n" ),
137+ progname ,basedir );
138+ if (!rmtree (basedir , true))
139+ fprintf (stderr ,_ ("%s: failed to remove data directory\n" ),
140+ progname );
141+ }
142+ else if (found_existing_pgdata )
143+ {
144+ fprintf (stderr ,
145+ _ ("%s: removing contents of data directory \"%s\"\n" ),
146+ progname ,basedir );
147+ if (!rmtree (basedir , false))
148+ fprintf (stderr ,_ ("%s: failed to remove contents of data directory\n" ),
149+ progname );
150+ }
151+
152+ if (made_new_xlogdir )
153+ {
154+ fprintf (stderr ,_ ("%s: removing transaction log directory \"%s\"\n" ),
155+ progname ,xlog_dir );
156+ if (!rmtree (xlog_dir , true))
157+ fprintf (stderr ,_ ("%s: failed to remove transaction log directory\n" ),
158+ progname );
159+ }
160+ else if (found_existing_xlogdir )
161+ {
162+ fprintf (stderr ,
163+ _ ("%s: removing contents of transaction log directory \"%s\"\n" ),
164+ progname ,xlog_dir );
165+ if (!rmtree (xlog_dir , false))
166+ fprintf (stderr ,_ ("%s: failed to remove contents of transaction log directory\n" ),
167+ progname );
168+ }
169+ }
170+ else
171+ {
172+ if (made_new_pgdata || found_existing_pgdata )
173+ fprintf (stderr ,
174+ _ ("%s: data directory \"%s\" not removed at user's request\n" ),
175+ progname ,basedir );
176+
177+ if (made_new_xlogdir || found_existing_xlogdir )
178+ fprintf (stderr ,
179+ _ ("%s: transaction log directory \"%s\" not removed at user's request\n" ),
180+ progname ,xlog_dir );
181+ }
182+
183+ if (made_tablespace_dirs || found_tablespace_dirs )
184+ fprintf (stderr ,
185+ _ ("%s: changes to tablespace directories will not be undone" ),
186+ progname );
187+ }
188+
117189static void
118190disconnect_and_exit (int code )
119191{
@@ -253,6 +325,7 @@ usage(void)
253325printf (_ (" -c, --checkpoint=fast|spread\n"
254326" set fast or spread checkpointing\n" ));
255327printf (_ (" -l, --label=LABEL set backup label\n" ));
328+ printf (_ (" -n, --noclean do not clean up after errors\n" ));
256329printf (_ (" -P, --progress show progress information\n" ));
257330printf (_ (" -v, --verbose output verbose messages\n" ));
258331printf (_ (" -V, --version output version information, then exit\n" ));
@@ -375,6 +448,8 @@ LogStreamerMain(logstreamer_param *param)
375448{
376449StreamCtl stream ;
377450
451+ in_log_streamer = true;
452+
378453MemSet (& stream ,0 ,sizeof (stream ));
379454stream .startpos = param -> startptr ;
380455stream .timeline = param -> timeline ;
@@ -501,7 +576,7 @@ StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier)
501576 * be give and the process ended.
502577 */
503578static void
504- verify_dir_is_empty_or_create (char * dirname )
579+ verify_dir_is_empty_or_create (char * dirname , bool * created , bool * found )
505580{
506581switch (pg_check_dir (dirname ))
507582{
@@ -517,12 +592,16 @@ verify_dir_is_empty_or_create(char *dirname)
517592progname ,dirname ,strerror (errno ));
518593disconnect_and_exit (1 );
519594}
595+ if (created )
596+ * created = true;
520597return ;
521598case 1 :
522599
523600/*
524601 * Exists, empty
525602 */
603+ if (found )
604+ * found = true;
526605return ;
527606case 2 :
528607case 3 :
@@ -1683,7 +1762,7 @@ BaseBackup(void)
16831762{
16841763char * path = (char * )get_tablespace_mapping (PQgetvalue (res ,i ,1 ));
16851764
1686- verify_dir_is_empty_or_create (path );
1765+ verify_dir_is_empty_or_create (path , & made_tablespace_dirs , & found_tablespace_dirs );
16871766}
16881767}
16891768
@@ -1892,6 +1971,7 @@ main(int argc, char **argv)
18921971{"gzip" ,no_argument ,NULL ,'z' },
18931972{"compress" ,required_argument ,NULL ,'Z' },
18941973{"label" ,required_argument ,NULL ,'l' },
1974+ {"noclean" ,no_argument ,NULL ,'n' },
18951975{"dbname" ,required_argument ,NULL ,'d' },
18961976{"host" ,required_argument ,NULL ,'h' },
18971977{"port" ,required_argument ,NULL ,'p' },
@@ -1926,7 +2006,9 @@ main(int argc, char **argv)
19262006}
19272007}
19282008
1929- while ((c = getopt_long (argc ,argv ,"D:F:r:RT:xX:l:zZ:d:c:h:p:U:s:S:wWvP" ,
2009+ atexit (cleanup_directories_atexit );
2010+
2011+ while ((c = getopt_long (argc ,argv ,"D:F:r:RT:xX:l:nzZ:d:c:h:p:U:s:S:wWvP" ,
19302012long_options ,& option_index ))!= -1 )
19312013{
19322014switch (c )
@@ -2001,6 +2083,9 @@ main(int argc, char **argv)
20012083case 'l' :
20022084label = pg_strdup (optarg );
20032085break ;
2086+ case 'n' :
2087+ noclean = true;
2088+ break ;
20042089case 'z' :
20052090#ifdef HAVE_LIBZ
20062091compresslevel = Z_DEFAULT_COMPRESSION ;
@@ -2170,14 +2255,14 @@ main(int argc, char **argv)
21702255 * unless we are writing to stdout.
21712256 */
21722257if (format == 'p' || strcmp (basedir ,"-" )!= 0 )
2173- verify_dir_is_empty_or_create (basedir );
2258+ verify_dir_is_empty_or_create (basedir , & made_new_pgdata , & found_existing_pgdata );
21742259
21752260/* Create transaction log symlink, if required */
21762261if (strcmp (xlog_dir ,"" )!= 0 )
21772262{
21782263char * linkloc ;
21792264
2180- verify_dir_is_empty_or_create (xlog_dir );
2265+ verify_dir_is_empty_or_create (xlog_dir , & made_new_xlogdir , & found_existing_xlogdir );
21812266
21822267/* form name of the place where the symlink must go */
21832268linkloc = psprintf ("%s/pg_xlog" ,basedir );
@@ -2198,5 +2283,6 @@ main(int argc, char **argv)
21982283
21992284BaseBackup ();
22002285
2286+ success = true;
22012287return 0 ;
22022288}