18
18
#include <time.h>
19
19
20
20
#include "access/xlog_internal.h" /* for pg_start/stop_backup */
21
+ #include "catalog/catalog.h"
21
22
#include "catalog/pg_type.h"
22
23
#include "lib/stringinfo.h"
23
24
#include "libpq/libpq.h"
@@ -43,6 +44,7 @@ typedef struct
43
44
44
45
45
46
static int64 sendDir (char * path ,int basepathlen ,bool sizeonly );
47
+ static int64 sendTablespace (char * path ,bool sizeonly );
46
48
static bool sendFile (char * readfilename ,char * tarfilename ,
47
49
struct stat * statbuf ,bool missing_ok );
48
50
static void sendFileWithContent (const char * filename ,const char * content );
@@ -137,7 +139,7 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
137
139
ti = palloc (sizeof (tablespaceinfo ));
138
140
ti -> oid = pstrdup (de -> d_name );
139
141
ti -> path = pstrdup (linkpath );
140
- ti -> size = opt -> progress ?sendDir ( linkpath , strlen ( linkpath ) , true) :-1 ;
142
+ ti -> size = opt -> progress ?sendTablespace ( fullpath , true) :-1 ;
141
143
tablespaces = lappend (tablespaces ,ti );
142
144
#else
143
145
/*
@@ -171,13 +173,26 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
171
173
pq_sendint (& buf ,0 ,2 );/* natts */
172
174
pq_endmessage (& buf );
173
175
174
- /* In the main tar, include the backup_label first. */
175
176
if (ti -> path == NULL )
177
+ {
178
+ struct stat statbuf ;
179
+
180
+ /* In the main tar, include the backup_label first... */
176
181
sendFileWithContent (BACKUP_LABEL_FILE ,labelfile );
177
182
178
- sendDir (ti -> path == NULL ?"." :ti -> path ,
179
- ti -> path == NULL ?1 :strlen (ti -> path ),
180
- false);
183
+ /* ... then the bulk of the files ... */
184
+ sendDir ("." ,1 , false);
185
+
186
+ /* ... and pg_control after everything else. */
187
+ if (lstat (XLOG_CONTROL_FILE ,& statbuf )!= 0 )
188
+ ereport (ERROR ,
189
+ (errcode_for_file_access (),
190
+ errmsg ("could not stat control file \"%s\": %m" ,
191
+ XLOG_CONTROL_FILE )));
192
+ sendFile (XLOG_CONTROL_FILE ,XLOG_CONTROL_FILE ,& statbuf , false);
193
+ }
194
+ else
195
+ sendTablespace (ti -> path , false);
181
196
182
197
/*
183
198
* If we're including WAL, and this is the main data directory we
@@ -552,6 +567,49 @@ sendFileWithContent(const char *filename, const char *content)
552
567
}
553
568
}
554
569
570
+ /*
571
+ * Include the tablespace directory pointed to by 'path' in the output tar
572
+ * stream. If 'sizeonly' is true, we just calculate a total length and return
573
+ * it, without actually sending anything.
574
+ */
575
+ static int64
576
+ sendTablespace (char * path ,bool sizeonly )
577
+ {
578
+ int64 size ;
579
+ char pathbuf [MAXPGPATH ];
580
+ struct stat statbuf ;
581
+
582
+ /*
583
+ * 'path' points to the tablespace location, but we only want to include
584
+ * the version directory in it that belongs to us.
585
+ */
586
+ snprintf (pathbuf ,sizeof (pathbuf ),"%s/%s" ,path ,
587
+ TABLESPACE_VERSION_DIRECTORY );
588
+
589
+ /*
590
+ * Store a directory entry in the tar file so we get the permissions right.
591
+ */
592
+ if (lstat (pathbuf ,& statbuf )!= 0 )
593
+ {
594
+ if (errno != ENOENT )
595
+ ereport (ERROR ,
596
+ (errcode_for_file_access (),
597
+ errmsg ("could not stat file or directory \"%s\": %m" ,
598
+ pathbuf )));
599
+
600
+ /* If the tablespace went away while scanning, it's no error. */
601
+ return 0 ;
602
+ }
603
+ if (!sizeonly )
604
+ _tarWriteHeader (TABLESPACE_VERSION_DIRECTORY ,NULL ,& statbuf );
605
+ size = 512 ;/* Size of the header just added */
606
+
607
+ /* Send all the files in the tablespace version directory */
608
+ size += sendDir (pathbuf ,strlen (path ),sizeonly );
609
+
610
+ return size ;
611
+ }
612
+
555
613
/*
556
614
* Include all files from the given directory in the output tar stream. If
557
615
* 'sizeonly' is true, we just calculate a total length and return it, without