diff --git a/include/llvm/System/Path.h b/include/llvm/System/Path.h index f6b2be0fdf9..8192dc42929 100644 --- a/include/llvm/System/Path.h +++ b/include/llvm/System/Path.h @@ -123,7 +123,7 @@ namespace sys { /// Find the path to a library using its short name. Use the system /// dependent library paths to locate the library. /// @brief Find a library. - static Path FindLibrary(std::string& short_name); + static Path FindLibrary(std::string& short_name); /// Construct a path to the default LLVM configuration directory. The /// implementation must ensure that this is a well-known (same on many @@ -162,14 +162,14 @@ namespace sys { /// provided so that they can be used to indicate null or error results in /// other lib/System functionality. /// @brief Construct an empty (and invalid) path. - Path() : path() {} + Path() : path(), status(0) {} /// This constructor will accept a std::string as a path. No checking is /// done on this path to determine if it is valid. To determine validity /// of the path, use the isValid method. /// @param p The path to assign. /// @brief Construct a Path from a string. - explicit Path(const std::string& p) : path(p) {} + explicit Path(const std::string& p) : path(p), status(0) {} /// @} /// @name Operators @@ -265,6 +265,11 @@ namespace sys { /// @brief Determines if the path references the root directory. bool isRootDirectory() const; + /// This function determines if the path name is absolute, as opposed to + /// relative. + /// @breif Determine if the path is absolute. + bool isAbsolute() const; + /// This function opens the file associated with the path name provided by /// the Path object and reads its magic number. If the magic number at the /// start of the file matches \p magic, true is returned. In all other @@ -352,7 +357,11 @@ namespace sys { /// of the file system. This returns false on success, or true on error /// and fills in the specified error string if specified. /// @brief Get file status. - bool getFileStatus(FileStatus &Status, std::string *Error = 0) const; + bool getFileStatus( + FileStatus &Status, ///< The resulting file status + bool forceUpdate = false, ///< Force an update from the file system + std::string *Error = 0 ///< Optional place to return an error msg. + ) const; /// @} /// @name Path Mutators @@ -511,6 +520,7 @@ namespace sys { /// @{ private: mutable std::string path; ///< Storage for the path name. + mutable FileStatus *status; ///< Status information. /// @} }; diff --git a/lib/System/Unix/Path.inc b/lib/System/Unix/Path.inc index 9802b7e00da..b155213ec62 100644 --- a/lib/System/Unix/Path.inc +++ b/lib/System/Unix/Path.inc @@ -79,6 +79,12 @@ Path::isValid() const { return i >= len; } +bool +Path::isAbsolute() const { + if (path.empty()) + return false; + return path[0] == '/'; +} Path Path::GetRootDirectory() { Path result; @@ -357,18 +363,22 @@ Path::getLast() const { } bool -Path::getFileStatus(FileStatus &info, std::string *ErrStr) const { - struct stat buf; - if (0 != stat(path.c_str(), &buf)) - return MakeErrMsg(ErrStr, - path + ": can't get status of file '" + path + "'"); - info.fileSize = buf.st_size; - info.modTime.fromEpochTime(buf.st_mtime); - info.mode = buf.st_mode; - info.user = buf.st_uid; - info.group = buf.st_gid; - info.isDir = S_ISDIR(buf.st_mode); - info.isFile = S_ISREG(buf.st_mode); +Path::getFileStatus(FileStatus &info, bool update, std::string *ErrStr) const { + if (status == 0 || update) { + struct stat buf; + if (0 != stat(path.c_str(), &buf)) + return MakeErrMsg(ErrStr, path + ": can't get status of file"); + if (status == 0) + status = new FileStatus; + status->fileSize = buf.st_size; + status->modTime.fromEpochTime(buf.st_mtime); + status->mode = buf.st_mode; + status->user = buf.st_uid; + status->group = buf.st_gid; + status->isDir = S_ISDIR(buf.st_mode); + status->isFile = S_ISREG(buf.st_mode); + } + info = *status; return false; } diff --git a/lib/System/Win32/Path.inc b/lib/System/Win32/Path.inc index 1eee2bb3c1f..1f809ecfa56 100644 --- a/lib/System/Win32/Path.inc +++ b/lib/System/Win32/Path.inc @@ -105,6 +105,13 @@ Path::isValid() const { return true; } +bool +Path::isAbsolute() const { + if (path.length() < 3) + return false; + return path[0] == 'C' && path[1] == ':' && path[2] == '\\'; +} + static Path *TempDirectory = NULL; Path @@ -294,24 +301,30 @@ Path::getLast() const { } bool -Path::getFileStatus(FileStatus &info, std::string *ErrStr) const { - WIN32_FILE_ATTRIBUTE_DATA fi; - if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi)) - return MakeErrMsg(ErrStr, "getStatusInfo():" + std::string(path) + - ": Can't get status: "); +Path::getFileStatus(FileStatus &info, bool update, std::string *ErrStr) const { + if (status == 0 || update) { + WIN32_FILE_ATTRIBUTE_DATA fi; + if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi)) + return MakeErrMsg(ErrStr, "getStatusInfo():" + std::string(path) + + ": Can't get status: "); - info.fileSize = fi.nFileSizeHigh; - info.fileSize <<= sizeof(fi.nFileSizeHigh)*8; - info.fileSize += fi.nFileSizeLow; + if (status == 0) + status = new FileStatus; - info.mode = fi.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? 0555 : 0777; - info.user = 9999; // Not applicable to Windows, so... - info.group = 9999; // Not applicable to Windows, so... + status->fileSize = fi.nFileSizeHigh; + status->fileSize <<= sizeof(fi.nFileSizeHigh)*8; + status->fileSize += fi.nFileSizeLow; - __int64 ft = *reinterpret_cast<__int64*>(&fi.ftLastWriteTime); - info.modTime.fromWin32Time(ft); + status->mode = fi.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? 0555 : 0777; + status->user = 9999; // Not applicable to Windows, so... + status->group = 9999; // Not applicable to Windows, so... - info.isDir = fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; + __int64 ft = *reinterpret_cast<__int64*>(&fi.ftLastWriteTime); + status->modTime.fromWin32Time(ft); + + status->isDir = fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; + } + info = *status; return false; }