@@ -2004,3 +2004,118 @@ fsync_fname(char *fname, bool isdir)
20042004
20052005 close (fd );
20062006}
2007+
2008+ /*
2009+ * Hint to the OS that it should get ready to fsync() this file.
2010+ *
2011+ * Adapted from pre_sync_fname in initdb.c
2012+ */
2013+ void
2014+ pre_sync_fname (char * fname , bool isdir )
2015+ {
2016+ int fd ;
2017+
2018+ fd = open (fname , O_RDONLY | PG_BINARY );
2019+
2020+ /*
2021+ * Some OSs don't allow us to open directories at all (Windows returns
2022+ * EACCES)
2023+ */
2024+ if (fd < 0 && isdir && (errno == EISDIR || errno == EACCES ))
2025+ return ;
2026+
2027+ if (fd < 0 )
2028+ ereport (FATAL ,
2029+ (errmsg ("could not open file \"%s\" before fsync" ,
2030+ fname )));
2031+
2032+ pg_flush_data (fd , 0 , 0 );
2033+
2034+ close (fd );
2035+ }
2036+
2037+ /*
2038+ * walkdir: recursively walk a directory, applying the action to each
2039+ * regular file and directory (including the named directory itself)
2040+ * and following symbolic links.
2041+ *
2042+ * NB: There is another version of walkdir in initdb.c, but that version
2043+ * behaves differently with respect to symbolic links. Caveat emptor!
2044+ */
2045+ void
2046+ walkdir (char * path , void (* action ) (char * fname , bool isdir ))
2047+ {
2048+ DIR * dir ;
2049+ struct dirent * de ;
2050+
2051+ dir = AllocateDir (path );
2052+ while ((de = ReadDir (dir , path )) != NULL )
2053+ {
2054+ char subpath [MAXPGPATH ];
2055+ struct stat fst ;
2056+
2057+ CHECK_FOR_INTERRUPTS ();
2058+
2059+ if (strcmp (de -> d_name , "." ) == 0 ||
2060+ strcmp (de -> d_name , ".." ) == 0 )
2061+ continue ;
2062+
2063+ snprintf (subpath , MAXPGPATH , "%s/%s" , path , de -> d_name );
2064+
2065+ if (lstat (subpath , & fst ) < 0 )
2066+ ereport (ERROR ,
2067+ (errcode_for_file_access (),
2068+ errmsg ("could not stat file \"%s\": %m" , subpath )));
2069+
2070+ if (S_ISREG (fst .st_mode ))
2071+ (* action ) (subpath , false);
2072+ else if (S_ISDIR (fst .st_mode ))
2073+ walkdir (subpath , action );
2074+ #ifndef WIN32
2075+ else if (S_ISLNK (fst .st_mode ))
2076+ #else
2077+ else if (pg_win32_is_junction (subpath ))
2078+ #endif
2079+ {
2080+ #if defined(HAVE_READLINK ) || defined(WIN32 )
2081+ char linkpath [MAXPGPATH ];
2082+ int len ;
2083+ struct stat lst ;
2084+
2085+ len = readlink (subpath , linkpath , sizeof (linkpath )- 1 );
2086+ if (len < 0 )
2087+ ereport (ERROR ,
2088+ (errcode_for_file_access (),
2089+ errmsg ("could not read symbolic link \"%s\": %m" ,
2090+ subpath )));
2091+
2092+ if (len >= sizeof (linkpath )- 1 )
2093+ ereport (ERROR ,
2094+ (errmsg ("symbolic link \"%s\" target is too long" ,
2095+ subpath )));
2096+
2097+ linkpath [len ] = '\0' ;
2098+
2099+ if (lstat (linkpath , & lst ) == 0 )
2100+ {
2101+ if (S_ISREG (lst .st_mode ))
2102+ (* action ) (linkpath , false);
2103+ else if (S_ISDIR (lst .st_mode ))
2104+ walkdir (subpath , action );
2105+ }
2106+ else if (errno != ENOENT )
2107+ ereport (ERROR ,
2108+ (errcode_for_file_access (),
2109+ errmsg ("could not stat file \"%s\": %m" , linkpath )));
2110+ #else
2111+ ereport (WARNING ,
2112+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
2113+ errmsg ("this platform does not support symbolic links; ignoring \"%s\"" ,
2114+ subpath )));
2115+ #endif
2116+ }
2117+ }
2118+ FreeDir (dir );
2119+
2120+ (* action ) (path , true);
2121+ }
0 commit comments