@@ -25,7 +25,6 @@ const char *pgdata_exclude_dir[] =
25
25
"pg_xlog" ,
26
26
"pg_stat_tmp" ,
27
27
"pgsql_tmp" ,
28
- NULL , /* arclog_path will be set later */
29
28
NULL , /* pg_log will be set later */
30
29
NULL
31
30
};
@@ -41,12 +40,18 @@ static char *pgdata_exclude_files[] =
41
40
pgFile * pgFileNew (const char * path , bool omit_symlink );
42
41
static int BlackListCompare (const void * str1 , const void * str2 );
43
42
44
- /* create directory, also create parent directories if necessary */
43
+ static void dir_list_file_internal (parray * files , const char * root ,
44
+ bool exclude , bool omit_symlink ,
45
+ bool add_root , parray * black_list );
46
+
47
+ /*
48
+ * Create directory, also create parent directories if necessary.
49
+ */
45
50
int
46
51
dir_create_dir (const char * dir , mode_t mode )
47
52
{
48
- char copy [MAXPGPATH ];
49
- char parent [MAXPGPATH ];
53
+ char copy [MAXPGPATH ];
54
+ char parent [MAXPGPATH ];
50
55
51
56
strncpy (copy , dir , MAXPGPATH );
52
57
strncpy (parent , dirname (copy ), MAXPGPATH );
@@ -60,8 +65,7 @@ dir_create_dir(const char *dir, mode_t mode)
60
65
{
61
66
if (errno == EEXIST ) /* already exist */
62
67
return 0 ;
63
- elog (ERROR , "cannot create directory \"%s\": %s" , dir ,
64
- strerror (errno ));
68
+ elog (ERROR , "cannot create directory \"%s\": %s" , dir , strerror (errno ));
65
69
}
66
70
67
71
return 0 ;
@@ -295,7 +299,7 @@ dir_list_file(parray *files, const char *root, bool exclude, bool omit_symlink,
295
299
parray_qsort (files , pgFileComparePath );
296
300
}
297
301
298
- void
302
+ static void
299
303
dir_list_file_internal (parray * files , const char * root , bool exclude ,
300
304
bool omit_symlink , bool add_root , parray * black_list )
301
305
{
@@ -327,11 +331,7 @@ dir_list_file_internal(parray *files, const char *root, bool exclude,
327
331
else
328
332
file_name ++ ;
329
333
330
- /*
331
- * If the item in the exclude list starts with '/', compare to the
332
- * absolute path of the directory. Otherwise compare to the directory
333
- * name portion.
334
- */
334
+ /* Check if we need to exclude file by name */
335
335
for (i = 0 ; pgdata_exclude_files [i ]; i ++ )
336
336
if (strcmp (file_name , pgdata_exclude_files [i ]) == 0 )
337
337
/* Skip */
@@ -416,13 +416,10 @@ dir_list_file_internal(parray *files, const char *root, bool exclude,
416
416
break ;
417
417
}
418
418
}
419
- else
419
+ else if ( strcmp ( dirname , pgdata_exclude_dir [ i ]) == 0 )
420
420
{
421
- if (strcmp (dirname , pgdata_exclude_dir [i ]) == 0 )
422
- {
423
- skip = true;
424
- break ;
425
- }
421
+ skip = true;
422
+ break ;
426
423
}
427
424
}
428
425
if (skip )
@@ -468,74 +465,159 @@ dir_list_file_internal(parray *files, const char *root, bool exclude,
468
465
}
469
466
}
470
467
471
- /* print mkdirs.sh */
468
+ /*
469
+ * List data directories excluding directories from
470
+ * pgdata_exclude_dir array.
471
+ *
472
+ * **is_root** is a little bit hack. We exclude only first level of directories
473
+ * and on the first level we check all files and directories.
474
+ */
472
475
void
473
- dir_print_mkdirs_sh (FILE * out , const parray * files , const char * root )
476
+ list_data_directories (parray * files , const char * path , bool is_root ,
477
+ bool exclude )
474
478
{
475
- int i ;
476
-
477
- for (i = 0 ; i < parray_num (files ); i ++ )
479
+ DIR * dir ;
480
+ struct dirent * dent ;
481
+ int prev_errno ;
482
+ bool has_child_dirs = false;
483
+
484
+ /* open directory and list contents */
485
+ dir = opendir (path );
486
+ if (dir == NULL )
487
+ elog (ERROR , "cannot open directory \"%s\": %s" , path , strerror (errno ));
488
+
489
+ errno = 0 ;
490
+ while ((dent = readdir (dir )))
478
491
{
479
- pgFile * file = (pgFile * ) parray_get (files , i );
480
- if (S_ISDIR (file -> mode ))
492
+ char child [MAXPGPATH ];
493
+ bool skip = false;
494
+ struct stat st ;
495
+
496
+ /* skip entries point current dir or parent dir */
497
+ if (strcmp (dent -> d_name , "." ) == 0 ||
498
+ strcmp (dent -> d_name , ".." ) == 0 )
499
+ continue ;
500
+
501
+ join_path_components (child , path , dent -> d_name );
502
+
503
+ if (lstat (child , & st ) == -1 )
504
+ elog (ERROR , "cannot stat file \"%s\": %s" , child , strerror (errno ));
505
+
506
+ if (!S_ISDIR (st .st_mode ))
481
507
{
482
- if (strstr (file -> path , root ) == file -> path &&
483
- * (file -> path + strlen (root )) == '/' )
484
- {
485
- fprintf (out , "mkdir -m 700 -p %s\n" , file -> path + strlen (root ) + 1 );
486
- }
508
+ /* Stop reading the directory if we met file */
509
+ if (!is_root )
510
+ break ;
487
511
else
512
+ continue ;
513
+ }
514
+
515
+ /* Check for exclude for the first level of listing */
516
+ if (is_root && exclude )
517
+ {
518
+ int i ;
519
+
520
+ for (i = 0 ; pgdata_exclude_dir [i ]; i ++ )
488
521
{
489
- fprintf (out , "mkdir -m 700 -p %s\n" , file -> path );
522
+ if (strcmp (dent -> d_name , pgdata_exclude_dir [i ]) == 0 )
523
+ {
524
+ skip = true;
525
+ break ;
526
+ }
490
527
}
491
528
}
492
- }
529
+ if (skip )
530
+ continue ;
493
531
494
- fprintf (out , "\n" );
532
+ has_child_dirs = true;
533
+ list_data_directories (files , child , false, exclude );
534
+ }
495
535
496
- for (i = 0 ; i < parray_num (files ); i ++ )
536
+ /* List only full and last directories */
537
+ if (!is_root && !has_child_dirs )
497
538
{
498
- pgFile * file = (pgFile * ) parray_get (files , i );
499
- if (S_ISLNK (file -> mode ))
500
- {
501
- fprintf (out , "rm -f %s\n" , file -> path + strlen (root ) + 1 );
502
- fprintf (out , "ln -s %s %s\n" , file -> linked , file -> path + strlen (root ) + 1 );
503
- }
539
+ pgFile * dir ;
540
+
541
+ dir = pgFileNew (path , false);
542
+ parray_append (files , dir );
504
543
}
544
+
545
+ prev_errno = errno ;
546
+ closedir (dir );
547
+
548
+ if (prev_errno && prev_errno != ENOENT )
549
+ elog (ERROR , "cannot read directory \"%s\": %s" ,
550
+ path , strerror (prev_errno ));
505
551
}
506
552
507
- /* print file list */
553
+ /*
554
+ * Read names of symbolik names of tablespaces with links to directories from
555
+ * tablespace_map or tablespace_map.txt.
556
+ */
508
557
void
509
- dir_print_file_list ( FILE * out , const parray * files , const char * root , const char * prefix )
558
+ read_tablespace_map ( parray * files , const char * backup_dir )
510
559
{
511
- int i ;
512
- int root_len = 0 ;
560
+ FILE * fp ;
561
+ char db_path [MAXPGPATH ],
562
+ map_path [MAXPGPATH ];
563
+ char buf [MAXPGPATH * 2 ];
513
564
514
- /* calculate length of root directory portion */
515
- if (root )
565
+ join_path_components (db_path , backup_dir , DATABASE_DIR );
566
+ join_path_components (map_path , db_path , "tablespace_map" );
567
+
568
+ /* Exit if database/tablespace_map don't exists */
569
+ if (!fileExists (map_path ))
516
570
{
517
- root_len = strlen (root );
518
- if (root [root_len - 1 ] != '/' )
519
- root_len ++ ;
571
+ elog (LOG , "there is no file tablespace_map" );
572
+ return ;
520
573
}
521
574
575
+ fp = fopen (map_path , "rt" );
576
+ if (fp == NULL )
577
+ elog (ERROR , "cannot open \"%s\": %s" , map_path , strerror (errno ));
578
+
579
+ while (fgets (buf , lengthof (buf ), fp ))
580
+ {
581
+ char link_name [MAXPGPATH ],
582
+ path [MAXPGPATH ];
583
+ pgFile * file ;
584
+
585
+ if (sscanf (buf , "%s %s" , link_name , path ) != 2 )
586
+ elog (ERROR , "invalid format found in \"%s\"" , map_path );
587
+
588
+ file = pgut_new (pgFile );
589
+ memset (file , 0 , sizeof (pgFile ));
590
+
591
+ file -> path = pgut_malloc (strlen (link_name ) + 1 );
592
+ strcpy (file -> path , link_name );
593
+
594
+ file -> linked = pgut_malloc (strlen (path ) + 1 );
595
+ strcpy (file -> linked , path );
596
+
597
+ parray_append (files , file );
598
+ }
599
+
600
+ fclose (fp );
601
+ }
602
+
603
+ /*
604
+ * Print file list.
605
+ */
606
+ void
607
+ print_file_list (FILE * out , const parray * files , const char * root )
608
+ {
609
+ size_t i ;
610
+
522
611
/* print each file in the list */
523
612
for (i = 0 ; i < parray_num (files ); i ++ )
524
613
{
525
- pgFile * file = (pgFile * )parray_get (files , i );
526
- char path [MAXPGPATH ];
527
- char * ptr = file -> path ;
528
- char type ;
614
+ pgFile * file = (pgFile * ) parray_get (files , i );
615
+ char * path = file -> path ;
616
+ char type ;
529
617
530
618
/* omit root directory portion */
531
- if (root && strstr (ptr , root ) == ptr )
532
- ptr = JoinPathEnd (ptr , root );
533
-
534
- /* append prefix if not NULL */
535
- if (prefix )
536
- join_path_components (path , prefix , ptr );
537
- else
538
- strcpy (path , ptr );
619
+ if (root && strstr (path , root ) == path )
620
+ path = JoinPathEnd (path , root );
539
621
540
622
if (S_ISREG (file -> mode ) && file -> is_datafile )
541
623
type = 'F' ;
@@ -556,7 +638,8 @@ dir_print_file_list(FILE *out, const parray *files, const char *root, const char
556
638
fprintf (out , " %s" , file -> linked );
557
639
else
558
640
{
559
- char timestamp [20 ];
641
+ char timestamp [20 ];
642
+
560
643
time2iso (timestamp , 20 , file -> mtime );
561
644
fprintf (out , " %s" , timestamp );
562
645
}
@@ -683,45 +766,39 @@ dir_read_file_list(const char *root, const char *file_txt)
683
766
}
684
767
685
768
/*
686
- * Copy contents of directory from_root into to_root .
769
+ * Check if directory empty .
687
770
*/
688
- void
689
- dir_copy_files (const char * from_root , const char * to_root )
771
+ bool
772
+ dir_is_empty (const char * path )
690
773
{
691
- size_t i ;
692
- parray * files = parray_new () ;
774
+ DIR * dir ;
775
+ struct dirent * dir_ent ;
693
776
694
- /* don't copy root directory */
695
- dir_list_file (files , from_root , false, true, false);
696
-
697
- for (i = 0 ; i < parray_num (files ); i ++ )
777
+ dir = opendir (path );
778
+ if (dir == NULL )
698
779
{
699
- pgFile * file = ( pgFile * ) parray_get ( files , i );
700
-
701
- if ( S_ISDIR ( file -> mode ))
702
- {
703
- char to_path [ MAXPGPATH ];
780
+ /* Directory in path doesn't exist */
781
+ if ( errno == ENOENT )
782
+ return true;
783
+ elog ( ERROR , "cannot open directory \"%s\": %s" , path , strerror ( errno ));
784
+ }
704
785
705
- join_path_components (to_path , to_root ,
706
- file -> path + strlen (from_root ) + 1 );
786
+ errno = 0 ;
787
+ while ((dir_ent = readdir (dir )))
788
+ {
789
+ /* Skip entries point current dir or parent dir */
790
+ if (strcmp (dir_ent -> d_name , "." ) == 0 ||
791
+ strcmp (dir_ent -> d_name , ".." ) == 0 )
792
+ continue ;
707
793
708
- if (verbose && !check )
709
- elog (LOG , "creating directory \"%s\"" ,
710
- file -> path + strlen (from_root ) + 1 );
711
- if (!check )
712
- dir_create_dir (to_path , DIR_PERMISSION );
713
- }
714
- else if (S_ISREG (file -> mode ))
715
- {
716
- if (verbose && !check )
717
- elog (LOG , "copying \"%s\"" ,
718
- file -> path + strlen (from_root ) + 1 );
719
- if (!check )
720
- copy_file (from_root , to_root , file );
721
- }
794
+ /* Directory is not empty */
795
+ closedir (dir );
796
+ return false;
722
797
}
798
+ if (errno )
799
+ elog (ERROR , "cannot read directory \"%s\": %s" , path , strerror (errno ));
800
+
801
+ closedir (dir );
723
802
724
- /* cleanup */
725
- parray_walk (files , pgFileFree );
726
- parray_free (files );
803
+ return true;
727
804
}
0 commit comments