@@ -2439,3 +2439,118 @@ looks_like_temp_rel_name(const char *name)
2439
2439
return false;
2440
2440
return true;
2441
2441
}
2442
+
2443
+ /*
2444
+ * Hint to the OS that it should get ready to fsync() this file.
2445
+ *
2446
+ * Adapted from pre_sync_fname in initdb.c
2447
+ */
2448
+ void
2449
+ pre_sync_fname (char * fname , bool isdir )
2450
+ {
2451
+ int fd ;
2452
+
2453
+ fd = open (fname , O_RDONLY | PG_BINARY );
2454
+
2455
+ /*
2456
+ * Some OSs don't allow us to open directories at all (Windows returns
2457
+ * EACCES)
2458
+ */
2459
+ if (fd < 0 && isdir && (errno == EISDIR || errno == EACCES ))
2460
+ return ;
2461
+
2462
+ if (fd < 0 )
2463
+ ereport (FATAL ,
2464
+ (errmsg ("could not open file \"%s\" before fsync" ,
2465
+ fname )));
2466
+
2467
+ pg_flush_data (fd , 0 , 0 );
2468
+
2469
+ close (fd );
2470
+ }
2471
+
2472
+ /*
2473
+ * walkdir: recursively walk a directory, applying the action to each
2474
+ * regular file and directory (including the named directory itself)
2475
+ * and following symbolic links.
2476
+ *
2477
+ * NB: There is another version of walkdir in initdb.c, but that version
2478
+ * behaves differently with respect to symbolic links. Caveat emptor!
2479
+ */
2480
+ void
2481
+ walkdir (char * path , void (* action ) (char * fname , bool isdir ))
2482
+ {
2483
+ DIR * dir ;
2484
+ struct dirent * de ;
2485
+
2486
+ dir = AllocateDir (path );
2487
+ while ((de = ReadDir (dir , path )) != NULL )
2488
+ {
2489
+ char subpath [MAXPGPATH ];
2490
+ struct stat fst ;
2491
+
2492
+ CHECK_FOR_INTERRUPTS ();
2493
+
2494
+ if (strcmp (de -> d_name , "." ) == 0 ||
2495
+ strcmp (de -> d_name , ".." ) == 0 )
2496
+ continue ;
2497
+
2498
+ snprintf (subpath , MAXPGPATH , "%s/%s" , path , de -> d_name );
2499
+
2500
+ if (lstat (subpath , & fst ) < 0 )
2501
+ ereport (ERROR ,
2502
+ (errcode_for_file_access (),
2503
+ errmsg ("could not stat file \"%s\": %m" , subpath )));
2504
+
2505
+ if (S_ISREG (fst .st_mode ))
2506
+ (* action ) (subpath , false);
2507
+ else if (S_ISDIR (fst .st_mode ))
2508
+ walkdir (subpath , action );
2509
+ #ifndef WIN32
2510
+ else if (S_ISLNK (fst .st_mode ))
2511
+ #else
2512
+ else if (pg_win32_is_junction (subpath ))
2513
+ #endif
2514
+ {
2515
+ #if defined(HAVE_READLINK ) || defined(WIN32 )
2516
+ char linkpath [MAXPGPATH ];
2517
+ int len ;
2518
+ struct stat lst ;
2519
+
2520
+ len = readlink (subpath , linkpath , sizeof (linkpath )- 1 );
2521
+ if (len < 0 )
2522
+ ereport (ERROR ,
2523
+ (errcode_for_file_access (),
2524
+ errmsg ("could not read symbolic link \"%s\": %m" ,
2525
+ subpath )));
2526
+
2527
+ if (len >= sizeof (linkpath )- 1 )
2528
+ ereport (ERROR ,
2529
+ (errmsg ("symbolic link \"%s\" target is too long" ,
2530
+ subpath )));
2531
+
2532
+ linkpath [len ] = '\0' ;
2533
+
2534
+ if (lstat (linkpath , & lst ) == 0 )
2535
+ {
2536
+ if (S_ISREG (lst .st_mode ))
2537
+ (* action ) (linkpath , false);
2538
+ else if (S_ISDIR (lst .st_mode ))
2539
+ walkdir (subpath , action );
2540
+ }
2541
+ else if (errno != ENOENT )
2542
+ ereport (ERROR ,
2543
+ (errcode_for_file_access (),
2544
+ errmsg ("could not stat file \"%s\": %m" , linkpath )));
2545
+ #else
2546
+ ereport (WARNING ,
2547
+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
2548
+ errmsg ("this platform does not support symbolic links; ignoring \"%s\"" ,
2549
+ subpath )));
2550
+ #endif
2551
+ }
2552
+ }
2553
+ FreeDir (dir );
2554
+
2555
+ (* action ) (path , true);
2556
+ }
0 commit comments