@@ -118,7 +118,7 @@ typedef struct TablespaceCreatedList
118118
119119static int BlackListCompare (const void * str1 , const void * str2 );
120120
121- static bool dir_check_file (const char * root , pgFile * file );
121+ static char dir_check_file (const char * root , pgFile * file );
122122static void dir_list_file_internal (parray * files , const char * root ,
123123 pgFile * parent , bool exclude ,
124124 bool omit_symlink , parray * black_list );
@@ -448,6 +448,10 @@ dir_list_file(parray *files, const char *root, bool exclude, bool omit_symlink,
448448 pgFileFree (file );
449449}
450450
451+ #define CHECK_FALSE 0
452+ #define CHECK_TRUE 1
453+ #define CHECK_EXCLUDE_FALSE 2
454+
451455/*
452456 * Check file or directory.
453457 *
@@ -456,16 +460,21 @@ dir_list_file(parray *files, const char *root, bool exclude, bool omit_symlink,
456460 * Skip files:
457461 * - skip temp tables files
458462 * - skip unlogged tables files
463+ * Skip recursive tablespace content
459464 * Set flags for:
460465 * - database directories
461466 * - datafiles
462467 */
463- static bool
468+ static char
464469dir_check_file (const char * root , pgFile * file )
465470{
466471 const char * rel_path ;
467472 int i ;
468473 int sscanf_res ;
474+ bool in_tablespace = false;
475+
476+ rel_path = GetRelativePath (file -> path , root );
477+ in_tablespace = path_is_prefix_of_path (PG_TBLSPC_DIR , rel_path );
469478
470479 /* Check if we need to exclude file by name */
471480 if (S_ISREG (file -> mode ))
@@ -478,7 +487,7 @@ dir_check_file(const char *root, pgFile *file)
478487 {
479488 /* Skip */
480489 elog (VERBOSE , "Excluding file: %s" , file -> name );
481- return false ;
490+ return CHECK_FALSE ;
482491 }
483492 }
484493
@@ -487,14 +496,14 @@ dir_check_file(const char *root, pgFile *file)
487496 {
488497 /* Skip */
489498 elog (VERBOSE , "Excluding file: %s" , file -> name );
490- return false ;
499+ return CHECK_FALSE ;
491500 }
492501 }
493502 /*
494503 * If the directory name is in the exclude list, do not list the
495504 * contents.
496505 */
497- else if (S_ISDIR (file -> mode ))
506+ else if (S_ISDIR (file -> mode ) && ! in_tablespace )
498507 {
499508 /*
500509 * If the item in the exclude list starts with '/', compare to
@@ -510,20 +519,18 @@ dir_check_file(const char *root, pgFile *file)
510519 {
511520 elog (VERBOSE , "Excluding directory content: %s" ,
512521 file -> name );
513- return false ;
522+ return CHECK_EXCLUDE_FALSE ;
514523 }
515524 }
516525 else if (strcmp (file -> name , pgdata_exclude_dir [i ]) == 0 )
517526 {
518527 elog (VERBOSE , "Excluding directory content: %s" ,
519528 file -> name );
520- return false ;
529+ return CHECK_EXCLUDE_FALSE ;
521530 }
522531 }
523532 }
524533
525- rel_path = GetRelativePath (file -> path , root );
526-
527534 /*
528535 * Do not copy tablespaces twice. It may happen if the tablespace is located
529536 * inside the PGDATA.
@@ -539,14 +546,33 @@ dir_check_file(const char *root, pgFile *file)
539546 * pg_tblspc/tblsOid/TABLESPACE_VERSION_DIRECTORY
540547 */
541548 if (!path_is_prefix_of_path (PG_TBLSPC_DIR , rel_path ))
542- return false ;
549+ return CHECK_FALSE ;
543550 sscanf_res = sscanf (rel_path , PG_TBLSPC_DIR "/%u/%s" ,
544551 & tblspcOid , tmp_rel_path );
545552 if (sscanf_res == 0 )
546- return false ;
553+ return CHECK_FALSE ;
547554 }
548555
549- if (path_is_prefix_of_path ("global" , rel_path ))
556+ if (in_tablespace )
557+ {
558+ char tmp_rel_path [MAXPGPATH ];
559+
560+ sscanf_res = sscanf (rel_path , PG_TBLSPC_DIR "/%u/%[^/]/%u/" ,
561+ & (file -> tblspcOid ), tmp_rel_path ,
562+ & (file -> dbOid ));
563+
564+ /*
565+ * We should skip other files and directories rather than
566+ * TABLESPACE_VERSION_DIRECTORY, if this is recursive tablespace.
567+ */
568+ if (sscanf_res == 2 && strcmp (tmp_rel_path , TABLESPACE_VERSION_DIRECTORY ) != 0 )
569+ return CHECK_FALSE ;
570+
571+ if (sscanf_res == 3 && S_ISDIR (file -> mode ) &&
572+ strcmp (tmp_rel_path , TABLESPACE_VERSION_DIRECTORY ) == 0 )
573+ file -> is_database = true;
574+ }
575+ else if (path_is_prefix_of_path ("global" , rel_path ))
550576 {
551577 file -> tblspcOid = GLOBALTABLESPACE_OID ;
552578
@@ -562,22 +588,10 @@ dir_check_file(const char *root, pgFile *file)
562588 if (S_ISDIR (file -> mode ) && strcmp (file -> name , "base" ) != 0 )
563589 file -> is_database = true;
564590 }
565- else if (path_is_prefix_of_path (PG_TBLSPC_DIR , rel_path ))
566- {
567- char tmp_rel_path [MAXPGPATH ];
568-
569- sscanf_res = sscanf (rel_path , PG_TBLSPC_DIR "/%u/%[^/]/%u/" ,
570- & (file -> tblspcOid ), tmp_rel_path ,
571- & (file -> dbOid ));
572-
573- if (sscanf_res == 3 && S_ISDIR (file -> mode ) &&
574- strcmp (tmp_rel_path , TABLESPACE_VERSION_DIRECTORY ) == 0 )
575- file -> is_database = true;
576- }
577591
578592 /* Do not backup ptrack_init files */
579593 if (S_ISREG (file -> mode ) && strcmp (file -> name , "ptrack_init" ) == 0 )
580- return false ;
594+ return CHECK_FALSE ;
581595
582596 /*
583597 * Check files located inside database directories including directory
@@ -587,10 +601,10 @@ dir_check_file(const char *root, pgFile *file)
587601 file -> name && file -> name [0 ])
588602 {
589603 if (strcmp (file -> name , "pg_internal.init" ) == 0 )
590- return false ;
604+ return CHECK_FALSE ;
591605 /* Do not backup temp files */
592606 else if (file -> name [0 ] == 't' && isdigit (file -> name [1 ]))
593- return false ;
607+ return CHECK_FALSE ;
594608 else if (isdigit (file -> name [0 ]))
595609 {
596610 char * fork_name ;
@@ -605,14 +619,14 @@ dir_check_file(const char *root, pgFile *file)
605619
606620 /* Do not backup ptrack files */
607621 if (strcmp (file -> forkName , "ptrack" ) == 0 )
608- return false ;
622+ return CHECK_FALSE ;
609623 }
610624 else
611625 {
612626 len = strlen (file -> name );
613627 /* reloid.cfm */
614628 if (len > 3 && strcmp (file -> name + len - 3 , "cfm" ) == 0 )
615- return true ;
629+ return CHECK_TRUE ;
616630
617631 sscanf_res = sscanf (file -> name , "%u.%d.%s" , & (file -> relOid ),
618632 & (file -> segno ), suffix );
@@ -624,7 +638,7 @@ dir_check_file(const char *root, pgFile *file)
624638 }
625639 }
626640
627- return true ;
641+ return CHECK_TRUE ;
628642}
629643
630644/*
@@ -659,6 +673,7 @@ dir_list_file_internal(parray *files, const char *root, pgFile *parent,
659673 {
660674 pgFile * file ;
661675 char child [MAXPGPATH ];
676+ char check_res ;
662677
663678 join_path_components (child , parent -> path , dent -> d_name );
664679
@@ -694,21 +709,24 @@ dir_list_file_internal(parray *files, const char *root, pgFile *parent,
694709 continue ;
695710 }
696711
697- /* We add the directory anyway */
698- if (S_ISDIR (file -> mode ))
699- parray_append (files , file );
700-
701- if (exclude && !dir_check_file (root , file ))
712+ if (exclude )
702713 {
703- if (S_ISREG (file -> mode ))
714+ check_res = dir_check_file (root , file );
715+ if (check_res == CHECK_FALSE )
716+ {
717+ /* Skip */
704718 pgFileFree (file );
705- /* Skip */
706- continue ;
719+ continue ;
720+ }
721+ else if (check_res == CHECK_EXCLUDE_FALSE )
722+ {
723+ /* We add the directory itself which content was excluded */
724+ parray_append (files , file );
725+ continue ;
726+ }
707727 }
708728
709- /* At least add the file */
710- if (S_ISREG (file -> mode ))
711- parray_append (files , file );
729+ parray_append (files , file );
712730
713731 /*
714732 * If the entry is a directory call dir_list_file_internal()
@@ -1219,11 +1237,7 @@ print_file_list(FILE *out, const parray *files, const char *root)
12191237 if (file -> is_datafile )
12201238 fprintf (out , ",\"segno\":\"%d\"" , file -> segno );
12211239
1222- #ifndef WIN32
1223- if (S_ISLNK (file -> mode ))
1224- #else
1225- if (pgwin32_is_junction (file -> path ))
1226- #endif
1240+ if (file -> linked )
12271241 fprintf (out , ",\"linked\":\"%s\"" , file -> linked );
12281242
12291243 if (file -> n_blocks != BLOCKNUM_INVALID )
0 commit comments