diff --git a/SystemTools.cxx b/SystemTools.cxx index 7eecde7d04f950add01d59411682863c590abba4..9b40e17e76f6d550d931c803f9a4bd571072244f 100644 --- a/SystemTools.cxx +++ b/SystemTools.cxx @@ -1252,6 +1252,43 @@ bool SystemTools::FileExists(const kwsys_stl::string& filename, bool isFile) return false; } +//---------------------------------------------------------------------------- +bool SystemTools::TestFileAccess(const char* filename, + TestFilePermissions permissions) +{ + if(!filename) + { + return false; + } + return SystemTools::TestFileAccess(kwsys_stl::string(filename), + permissions); +} + +//---------------------------------------------------------------------------- +bool SystemTools::TestFileAccess(const kwsys_stl::string& filename, + TestFilePermissions permissions) +{ + if(filename.empty()) + { + return false; + } +#if defined(_WIN32) && !defined(__CYGWIN__) + // If execute set, change to read permission (all files on Windows + // are executable if they are readable). The CRT will always fail + // if you pass an execute bit. + if(permissions & TEST_FILE_EXECUTE) + { + permissions &= ~TEST_FILE_EXECUTE; + permissions |= TEST_FILE_READ; + } + return _waccess( + SystemTools::ConvertToWindowsExtendedPath(filename).c_str(), + permissions) == 0; +#else + return access(filename.c_str(), permissions) == 0; +#endif +} + //---------------------------------------------------------------------------- #ifdef __CYGWIN__ bool SystemTools::PathCygwinToWin32(const char *path, char *win32_path) diff --git a/SystemTools.hxx.in b/SystemTools.hxx.in index ca22b6c192c16c3bb959b5a145ab85954af0355d..d181dc024d53d4fe7e89a97b6160d06bed22bb40 100644 --- a/SystemTools.hxx.in +++ b/SystemTools.hxx.in @@ -21,6 +21,9 @@ #include <@KWSYS_NAMESPACE@/String.hxx> #include <sys/types.h> +#if !defined(_WIN32) || defined(__CYGWIN__) +# include <unistd.h> // For access permissions for use with access() +#endif // Required for va_list #include <stdarg.h> @@ -72,6 +75,24 @@ public: // before it is used and is the last static object destroyed. static SystemToolsManager SystemToolsManagerInstance; +// Flags for use with TestFileAccess. Use a typedef in case any operating +// system in the future needs a special type. These are flags that may be +// combined using the | operator. +typedef int TestFilePermissions; +#if defined(_WIN32) && !defined(__CYGWIN__) + // On Windows (VC and Borland), no system header defines these constants... + static const TestFilePermissions TEST_FILE_OK = 0; + static const TestFilePermissions TEST_FILE_READ = 4; + static const TestFilePermissions TEST_FILE_WRITE = 2; + static const TestFilePermissions TEST_FILE_EXECUTE = 1; +#else + // Standard POSIX constants + static const TestFilePermissions TEST_FILE_OK = F_OK; + static const TestFilePermissions TEST_FILE_READ = R_OK; + static const TestFilePermissions TEST_FILE_WRITE = W_OK; + static const TestFilePermissions TEST_FILE_EXECUTE = X_OK; +#endif + /** \class SystemTools * \brief A collection of useful platform-independent system functions. */ @@ -301,6 +322,21 @@ public: static bool FileExists(const char* filename); static bool FileExists(const kwsys_stl::string& filename); + /** + * Test if a file exists and can be accessed with the requested + * permissions. Symbolic links are followed. Returns true if + * the access test was successful. + * + * On POSIX systems (including Cygwin), this maps to the access + * function. On Windows systems, all existing files are + * considered readable, and writable files are considered to + * have the read-only file attribute cleared. + */ + static bool TestFileAccess(const char* filename, + TestFilePermissions permissions); + static bool TestFileAccess(const kwsys_stl::string& filename, + TestFilePermissions permissions); + /** * Converts Cygwin path to Win32 path. Uses dictionary container for * caching and calls to cygwin_conv_to_win32_path from Cygwin dll