14b6829f0d28990dd645e16386eb226d0f10c8731shiqian// Copyright 2008, Google Inc. 24b6829f0d28990dd645e16386eb226d0f10c8731shiqian// All rights reserved. 34b6829f0d28990dd645e16386eb226d0f10c8731shiqian// 44b6829f0d28990dd645e16386eb226d0f10c8731shiqian// Redistribution and use in source and binary forms, with or without 54b6829f0d28990dd645e16386eb226d0f10c8731shiqian// modification, are permitted provided that the following conditions are 64b6829f0d28990dd645e16386eb226d0f10c8731shiqian// met: 74b6829f0d28990dd645e16386eb226d0f10c8731shiqian// 84b6829f0d28990dd645e16386eb226d0f10c8731shiqian// * Redistributions of source code must retain the above copyright 94b6829f0d28990dd645e16386eb226d0f10c8731shiqian// notice, this list of conditions and the following disclaimer. 104b6829f0d28990dd645e16386eb226d0f10c8731shiqian// * Redistributions in binary form must reproduce the above 114b6829f0d28990dd645e16386eb226d0f10c8731shiqian// copyright notice, this list of conditions and the following disclaimer 124b6829f0d28990dd645e16386eb226d0f10c8731shiqian// in the documentation and/or other materials provided with the 134b6829f0d28990dd645e16386eb226d0f10c8731shiqian// distribution. 144b6829f0d28990dd645e16386eb226d0f10c8731shiqian// * Neither the name of Google Inc. nor the names of its 154b6829f0d28990dd645e16386eb226d0f10c8731shiqian// contributors may be used to endorse or promote products derived from 164b6829f0d28990dd645e16386eb226d0f10c8731shiqian// this software without specific prior written permission. 174b6829f0d28990dd645e16386eb226d0f10c8731shiqian// 184b6829f0d28990dd645e16386eb226d0f10c8731shiqian// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 194b6829f0d28990dd645e16386eb226d0f10c8731shiqian// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 204b6829f0d28990dd645e16386eb226d0f10c8731shiqian// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 214b6829f0d28990dd645e16386eb226d0f10c8731shiqian// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 224b6829f0d28990dd645e16386eb226d0f10c8731shiqian// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 234b6829f0d28990dd645e16386eb226d0f10c8731shiqian// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 244b6829f0d28990dd645e16386eb226d0f10c8731shiqian// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 254b6829f0d28990dd645e16386eb226d0f10c8731shiqian// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 264b6829f0d28990dd645e16386eb226d0f10c8731shiqian// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 274b6829f0d28990dd645e16386eb226d0f10c8731shiqian// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 284b6829f0d28990dd645e16386eb226d0f10c8731shiqian// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 294b6829f0d28990dd645e16386eb226d0f10c8731shiqian// 304b6829f0d28990dd645e16386eb226d0f10c8731shiqian// Authors: keith.ray@gmail.com (Keith Ray) 314b6829f0d28990dd645e16386eb226d0f10c8731shiqian 322733a36231e9e59dfe0648562ac021ccea0e27d8zhanyong.wan#include "gtest/gtest-message.h" 332620c79810d4741922e9fa89050c0af564994f24zhanyong.wan#include "gtest/internal/gtest-filepath.h" 342620c79810d4741922e9fa89050c0af564994f24zhanyong.wan#include "gtest/internal/gtest-port.h" 354b6829f0d28990dd645e16386eb226d0f10c8731shiqian 36c3b4de35a18a1f011e8009d4d794f787f7e4e0c1shiqian#include <stdlib.h> 37c3b4de35a18a1f011e8009d4d794f787f7e4e0c1shiqian 38fff033497b70e96a5dcadb6ba9570c12b5921d74zhanyong.wan#if GTEST_OS_WINDOWS_MOBILE 39733a54a398766289b74cf3daebe083d7115cf388zhanyong.wan# include <windows.h> 404cd62602913a032a7aec091d4c8055ff9af95e37zhanyong.wan#elif GTEST_OS_WINDOWS 41733a54a398766289b74cf3daebe083d7115cf388zhanyong.wan# include <direct.h> 42733a54a398766289b74cf3daebe083d7115cf388zhanyong.wan# include <io.h> 43a92a6f792395e1ad462472d474ab0c76949813favladlosev#elif GTEST_OS_SYMBIAN 44a92a6f792395e1ad462472d474ab0c76949813favladlosev// Symbian OpenC has PATH_MAX in sys/syslimits.h 45733a54a398766289b74cf3daebe083d7115cf388zhanyong.wan# include <sys/syslimits.h> 46dd4a17bc20377d250ed116b1083d851adbe45f25shiqian#else 47733a54a398766289b74cf3daebe083d7115cf388zhanyong.wan# include <limits.h> 48733a54a398766289b74cf3daebe083d7115cf388zhanyong.wan# include <climits> // Some Linux distributions define PATH_MAX here. 49fff033497b70e96a5dcadb6ba9570c12b5921d74zhanyong.wan#endif // GTEST_OS_WINDOWS_MOBILE 50941b5ee8ebaad627df59eaa03509021b3cfa3bafshiqian 514cd62602913a032a7aec091d4c8055ff9af95e37zhanyong.wan#if GTEST_OS_WINDOWS 52733a54a398766289b74cf3daebe083d7115cf388zhanyong.wan# define GTEST_PATH_MAX_ _MAX_PATH 53941b5ee8ebaad627df59eaa03509021b3cfa3bafshiqian#elif defined(PATH_MAX) 54733a54a398766289b74cf3daebe083d7115cf388zhanyong.wan# define GTEST_PATH_MAX_ PATH_MAX 55941b5ee8ebaad627df59eaa03509021b3cfa3bafshiqian#elif defined(_XOPEN_PATH_MAX) 56733a54a398766289b74cf3daebe083d7115cf388zhanyong.wan# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX 57941b5ee8ebaad627df59eaa03509021b3cfa3bafshiqian#else 58733a54a398766289b74cf3daebe083d7115cf388zhanyong.wan# define GTEST_PATH_MAX_ _POSIX_PATH_MAX 59941b5ee8ebaad627df59eaa03509021b3cfa3bafshiqian#endif // GTEST_OS_WINDOWS 604b6829f0d28990dd645e16386eb226d0f10c8731shiqian 612620c79810d4741922e9fa89050c0af564994f24zhanyong.wan#include "gtest/internal/gtest-string.h" 624b6829f0d28990dd645e16386eb226d0f10c8731shiqian 634b6829f0d28990dd645e16386eb226d0f10c8731shiqiannamespace testing { 644b6829f0d28990dd645e16386eb226d0f10c8731shiqiannamespace internal { 654b6829f0d28990dd645e16386eb226d0f10c8731shiqian 664cd62602913a032a7aec091d4c8055ff9af95e37zhanyong.wan#if GTEST_OS_WINDOWS 678236131e25705a809d496672a3819e1741166c4bzhanyong.wan// On Windows, '\\' is the standard path separator, but many tools and the 688236131e25705a809d496672a3819e1741166c4bzhanyong.wan// Windows API also accept '/' as an alternate path separator. Unless otherwise 698236131e25705a809d496672a3819e1741166c4bzhanyong.wan// noted, a file path can contain either kind of path separators, or a mixture 708236131e25705a809d496672a3819e1741166c4bzhanyong.wan// of them. 714b6829f0d28990dd645e16386eb226d0f10c8731shiqianconst char kPathSeparator = '\\'; 728236131e25705a809d496672a3819e1741166c4bzhanyong.wanconst char kAlternatePathSeparator = '/'; 738236131e25705a809d496672a3819e1741166c4bzhanyong.wanconst char kAlternatePathSeparatorString[] = "/"; 74733a54a398766289b74cf3daebe083d7115cf388zhanyong.wan# if GTEST_OS_WINDOWS_MOBILE 75dd4a17bc20377d250ed116b1083d851adbe45f25shiqian// Windows CE doesn't have a current directory. You should not use 76dd4a17bc20377d250ed116b1083d851adbe45f25shiqian// the current directory in tests on Windows CE, but this at least 77dd4a17bc20377d250ed116b1083d851adbe45f25shiqian// provides a reasonable fallback. 78dd4a17bc20377d250ed116b1083d851adbe45f25shiqianconst char kCurrentDirectoryString[] = "\\"; 79dd4a17bc20377d250ed116b1083d851adbe45f25shiqian// Windows CE doesn't define INVALID_FILE_ATTRIBUTES 80dd4a17bc20377d250ed116b1083d851adbe45f25shiqianconst DWORD kInvalidFileAttributes = 0xffffffff; 81733a54a398766289b74cf3daebe083d7115cf388zhanyong.wan# else 824b6829f0d28990dd645e16386eb226d0f10c8731shiqianconst char kCurrentDirectoryString[] = ".\\"; 83733a54a398766289b74cf3daebe083d7115cf388zhanyong.wan# endif // GTEST_OS_WINDOWS_MOBILE 844b6829f0d28990dd645e16386eb226d0f10c8731shiqian#else 854b6829f0d28990dd645e16386eb226d0f10c8731shiqianconst char kPathSeparator = '/'; 864b6829f0d28990dd645e16386eb226d0f10c8731shiqianconst char kCurrentDirectoryString[] = "./"; 874b6829f0d28990dd645e16386eb226d0f10c8731shiqian#endif // GTEST_OS_WINDOWS 884b6829f0d28990dd645e16386eb226d0f10c8731shiqian 898236131e25705a809d496672a3819e1741166c4bzhanyong.wan// Returns whether the given character is a valid path separator. 908236131e25705a809d496672a3819e1741166c4bzhanyong.wanstatic bool IsPathSeparator(char c) { 918236131e25705a809d496672a3819e1741166c4bzhanyong.wan#if GTEST_HAS_ALT_PATH_SEP_ 928236131e25705a809d496672a3819e1741166c4bzhanyong.wan return (c == kPathSeparator) || (c == kAlternatePathSeparator); 938236131e25705a809d496672a3819e1741166c4bzhanyong.wan#else 948236131e25705a809d496672a3819e1741166c4bzhanyong.wan return c == kPathSeparator; 958236131e25705a809d496672a3819e1741166c4bzhanyong.wan#endif 968236131e25705a809d496672a3819e1741166c4bzhanyong.wan} 978236131e25705a809d496672a3819e1741166c4bzhanyong.wan 98c3b4de35a18a1f011e8009d4d794f787f7e4e0c1shiqian// Returns the current working directory, or "" if unsuccessful. 99c3b4de35a18a1f011e8009d4d794f787f7e4e0c1shiqianFilePath FilePath::GetCurrentDir() { 100f0d7f455d0ba1b1da1891c3ee54961a162e8fbc4billydonahue@google.com#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT 101fff033497b70e96a5dcadb6ba9570c12b5921d74zhanyong.wan // Windows CE doesn't have a current directory, so we just return 102fff033497b70e96a5dcadb6ba9570c12b5921d74zhanyong.wan // something reasonable. 103c3b4de35a18a1f011e8009d4d794f787f7e4e0c1shiqian return FilePath(kCurrentDirectoryString); 1044cd62602913a032a7aec091d4c8055ff9af95e37zhanyong.wan#elif GTEST_OS_WINDOWS 10598efcc49448a78cae3af3ed793a3ad6927620fc4zhanyong.wan char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; 106c3b4de35a18a1f011e8009d4d794f787f7e4e0c1shiqian return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); 107c3b4de35a18a1f011e8009d4d794f787f7e4e0c1shiqian#else 10898efcc49448a78cae3af3ed793a3ad6927620fc4zhanyong.wan char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; 1094650552ff637bb44ecf7784060091cbed3252211kosak@google.com char* result = getcwd(cwd, sizeof(cwd)); 1104650552ff637bb44ecf7784060091cbed3252211kosak@google.com# if GTEST_OS_NACL 1114650552ff637bb44ecf7784060091cbed3252211kosak@google.com // getcwd will likely fail in NaCl due to the sandbox, so return something 1124650552ff637bb44ecf7784060091cbed3252211kosak@google.com // reasonable. The user may have provided a shim implementation for getcwd, 1134650552ff637bb44ecf7784060091cbed3252211kosak@google.com // however, so fallback only when failure is detected. 1144650552ff637bb44ecf7784060091cbed3252211kosak@google.com return FilePath(result == NULL ? kCurrentDirectoryString : cwd); 1154650552ff637bb44ecf7784060091cbed3252211kosak@google.com# endif // GTEST_OS_NACL 1164650552ff637bb44ecf7784060091cbed3252211kosak@google.com return FilePath(result == NULL ? "" : cwd); 117fff033497b70e96a5dcadb6ba9570c12b5921d74zhanyong.wan#endif // GTEST_OS_WINDOWS_MOBILE 118c3b4de35a18a1f011e8009d4d794f787f7e4e0c1shiqian} 119c3b4de35a18a1f011e8009d4d794f787f7e4e0c1shiqian 1204b6829f0d28990dd645e16386eb226d0f10c8731shiqian// Returns a copy of the FilePath with the case-insensitive extension removed. 1214b6829f0d28990dd645e16386eb226d0f10c8731shiqian// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns 1224b6829f0d28990dd645e16386eb226d0f10c8731shiqian// FilePath("dir/file"). If a case-insensitive extension is not 1234b6829f0d28990dd645e16386eb226d0f10c8731shiqian// found, returns a copy of the original FilePath. 1244b6829f0d28990dd645e16386eb226d0f10c8731shiqianFilePath FilePath::RemoveExtension(const char* extension) const { 12503c314931649a999b0cf5deb0a434a1009157416jgm@google.com const std::string dot_extension = std::string(".") + extension; 12603c314931649a999b0cf5deb0a434a1009157416jgm@google.com if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) { 12703c314931649a999b0cf5deb0a434a1009157416jgm@google.com return FilePath(pathname_.substr( 12803c314931649a999b0cf5deb0a434a1009157416jgm@google.com 0, pathname_.length() - dot_extension.length())); 1294b6829f0d28990dd645e16386eb226d0f10c8731shiqian } 1304b6829f0d28990dd645e16386eb226d0f10c8731shiqian return *this; 1314b6829f0d28990dd645e16386eb226d0f10c8731shiqian} 1324b6829f0d28990dd645e16386eb226d0f10c8731shiqian 1338236131e25705a809d496672a3819e1741166c4bzhanyong.wan// Returns a pointer to the last occurence of a valid path separator in 1348236131e25705a809d496672a3819e1741166c4bzhanyong.wan// the FilePath. On Windows, for example, both '/' and '\' are valid path 1358236131e25705a809d496672a3819e1741166c4bzhanyong.wan// separators. Returns NULL if no path separator was found. 1368236131e25705a809d496672a3819e1741166c4bzhanyong.wanconst char* FilePath::FindLastPathSeparator() const { 1378236131e25705a809d496672a3819e1741166c4bzhanyong.wan const char* const last_sep = strrchr(c_str(), kPathSeparator); 1388236131e25705a809d496672a3819e1741166c4bzhanyong.wan#if GTEST_HAS_ALT_PATH_SEP_ 1398236131e25705a809d496672a3819e1741166c4bzhanyong.wan const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator); 1408236131e25705a809d496672a3819e1741166c4bzhanyong.wan // Comparing two pointers of which only one is NULL is undefined. 1418236131e25705a809d496672a3819e1741166c4bzhanyong.wan if (last_alt_sep != NULL && 1428236131e25705a809d496672a3819e1741166c4bzhanyong.wan (last_sep == NULL || last_alt_sep > last_sep)) { 1438236131e25705a809d496672a3819e1741166c4bzhanyong.wan return last_alt_sep; 1448236131e25705a809d496672a3819e1741166c4bzhanyong.wan } 1458236131e25705a809d496672a3819e1741166c4bzhanyong.wan#endif 1468236131e25705a809d496672a3819e1741166c4bzhanyong.wan return last_sep; 1478236131e25705a809d496672a3819e1741166c4bzhanyong.wan} 1488236131e25705a809d496672a3819e1741166c4bzhanyong.wan 1494b6829f0d28990dd645e16386eb226d0f10c8731shiqian// Returns a copy of the FilePath with the directory part removed. 1504b6829f0d28990dd645e16386eb226d0f10c8731shiqian// Example: FilePath("path/to/file").RemoveDirectoryName() returns 1514b6829f0d28990dd645e16386eb226d0f10c8731shiqian// FilePath("file"). If there is no directory part ("just_a_file"), it returns 1524b6829f0d28990dd645e16386eb226d0f10c8731shiqian// the FilePath unmodified. If there is no file part ("just_a_dir/") it 1534b6829f0d28990dd645e16386eb226d0f10c8731shiqian// returns an empty FilePath (""). 1544b6829f0d28990dd645e16386eb226d0f10c8731shiqian// On Windows platform, '\' is the path separator, otherwise it is '/'. 1554b6829f0d28990dd645e16386eb226d0f10c8731shiqianFilePath FilePath::RemoveDirectoryName() const { 1568236131e25705a809d496672a3819e1741166c4bzhanyong.wan const char* const last_sep = FindLastPathSeparator(); 15703c314931649a999b0cf5deb0a434a1009157416jgm@google.com return last_sep ? FilePath(last_sep + 1) : *this; 1584b6829f0d28990dd645e16386eb226d0f10c8731shiqian} 1594b6829f0d28990dd645e16386eb226d0f10c8731shiqian 1604b6829f0d28990dd645e16386eb226d0f10c8731shiqian// RemoveFileName returns the directory path with the filename removed. 1614b6829f0d28990dd645e16386eb226d0f10c8731shiqian// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". 1624b6829f0d28990dd645e16386eb226d0f10c8731shiqian// If the FilePath is "a_file" or "/a_file", RemoveFileName returns 1634b6829f0d28990dd645e16386eb226d0f10c8731shiqian// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does 1644b6829f0d28990dd645e16386eb226d0f10c8731shiqian// not have a file, like "just/a/dir/", it returns the FilePath unmodified. 1654b6829f0d28990dd645e16386eb226d0f10c8731shiqian// On Windows platform, '\' is the path separator, otherwise it is '/'. 1664b6829f0d28990dd645e16386eb226d0f10c8731shiqianFilePath FilePath::RemoveFileName() const { 1678236131e25705a809d496672a3819e1741166c4bzhanyong.wan const char* const last_sep = FindLastPathSeparator(); 16803c314931649a999b0cf5deb0a434a1009157416jgm@google.com std::string dir; 16998efcc49448a78cae3af3ed793a3ad6927620fc4zhanyong.wan if (last_sep) { 17003c314931649a999b0cf5deb0a434a1009157416jgm@google.com dir = std::string(c_str(), last_sep + 1 - c_str()); 17198efcc49448a78cae3af3ed793a3ad6927620fc4zhanyong.wan } else { 17298efcc49448a78cae3af3ed793a3ad6927620fc4zhanyong.wan dir = kCurrentDirectoryString; 17398efcc49448a78cae3af3ed793a3ad6927620fc4zhanyong.wan } 17498efcc49448a78cae3af3ed793a3ad6927620fc4zhanyong.wan return FilePath(dir); 1754b6829f0d28990dd645e16386eb226d0f10c8731shiqian} 1764b6829f0d28990dd645e16386eb226d0f10c8731shiqian 1774b6829f0d28990dd645e16386eb226d0f10c8731shiqian// Helper functions for naming files in a directory for xml output. 1784b6829f0d28990dd645e16386eb226d0f10c8731shiqian 1794b6829f0d28990dd645e16386eb226d0f10c8731shiqian// Given directory = "dir", base_name = "test", number = 0, 1804b6829f0d28990dd645e16386eb226d0f10c8731shiqian// extension = "xml", returns "dir/test.xml". If number is greater 1814b6829f0d28990dd645e16386eb226d0f10c8731shiqian// than zero (e.g., 12), returns "dir/test_12.xml". 1824b6829f0d28990dd645e16386eb226d0f10c8731shiqian// On Windows platform, uses \ as the separator rather than /. 1834b6829f0d28990dd645e16386eb226d0f10c8731shiqianFilePath FilePath::MakeFileName(const FilePath& directory, 1844b6829f0d28990dd645e16386eb226d0f10c8731shiqian const FilePath& base_name, 1854b6829f0d28990dd645e16386eb226d0f10c8731shiqian int number, 1864b6829f0d28990dd645e16386eb226d0f10c8731shiqian const char* extension) { 18703c314931649a999b0cf5deb0a434a1009157416jgm@google.com std::string file; 18898efcc49448a78cae3af3ed793a3ad6927620fc4zhanyong.wan if (number == 0) { 18903c314931649a999b0cf5deb0a434a1009157416jgm@google.com file = base_name.string() + "." + extension; 19098efcc49448a78cae3af3ed793a3ad6927620fc4zhanyong.wan } else { 1913b8388d9490a64a47ed8cbdab2021935b1b2c76ckosak@google.com file = base_name.string() + "_" + StreamableToString(number) 19203c314931649a999b0cf5deb0a434a1009157416jgm@google.com + "." + extension; 19398efcc49448a78cae3af3ed793a3ad6927620fc4zhanyong.wan } 19498efcc49448a78cae3af3ed793a3ad6927620fc4zhanyong.wan return ConcatPaths(directory, FilePath(file)); 195e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wan} 196e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wan 197e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wan// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml". 198e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wan// On Windows, uses \ as the separator rather than /. 199e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wanFilePath FilePath::ConcatPaths(const FilePath& directory, 200e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wan const FilePath& relative_path) { 201e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wan if (directory.IsEmpty()) 202e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wan return relative_path; 203e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wan const FilePath dir(directory.RemoveTrailingPathSeparator()); 20403c314931649a999b0cf5deb0a434a1009157416jgm@google.com return FilePath(dir.string() + kPathSeparator + relative_path.string()); 2054b6829f0d28990dd645e16386eb226d0f10c8731shiqian} 2064b6829f0d28990dd645e16386eb226d0f10c8731shiqian 2074b6829f0d28990dd645e16386eb226d0f10c8731shiqian// Returns true if pathname describes something findable in the file-system, 2084b6829f0d28990dd645e16386eb226d0f10c8731shiqian// either a file, directory, or whatever. 2094b6829f0d28990dd645e16386eb226d0f10c8731shiqianbool FilePath::FileOrDirectoryExists() const { 210fff033497b70e96a5dcadb6ba9570c12b5921d74zhanyong.wan#if GTEST_OS_WINDOWS_MOBILE 211dd4a17bc20377d250ed116b1083d851adbe45f25shiqian LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str()); 212dd4a17bc20377d250ed116b1083d851adbe45f25shiqian const DWORD attributes = GetFileAttributes(unicode); 213dd4a17bc20377d250ed116b1083d851adbe45f25shiqian delete [] unicode; 214dd4a17bc20377d250ed116b1083d851adbe45f25shiqian return attributes != kInvalidFileAttributes; 2154b6829f0d28990dd645e16386eb226d0f10c8731shiqian#else 216c7f60f1514013d57a624c3a2966709998678f24bzhanyong.wan posix::StatStruct file_stat; 217c7f60f1514013d57a624c3a2966709998678f24bzhanyong.wan return posix::Stat(pathname_.c_str(), &file_stat) == 0; 218fff033497b70e96a5dcadb6ba9570c12b5921d74zhanyong.wan#endif // GTEST_OS_WINDOWS_MOBILE 2194b6829f0d28990dd645e16386eb226d0f10c8731shiqian} 2204b6829f0d28990dd645e16386eb226d0f10c8731shiqian 2214b6829f0d28990dd645e16386eb226d0f10c8731shiqian// Returns true if pathname describes a directory in the file-system 2224b6829f0d28990dd645e16386eb226d0f10c8731shiqian// that exists. 2234b6829f0d28990dd645e16386eb226d0f10c8731shiqianbool FilePath::DirectoryExists() const { 2244b6829f0d28990dd645e16386eb226d0f10c8731shiqian bool result = false; 2254cd62602913a032a7aec091d4c8055ff9af95e37zhanyong.wan#if GTEST_OS_WINDOWS 226f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian // Don't strip off trailing separator if path is a root directory on 227f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian // Windows (like "C:\\"). 228f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian const FilePath& path(IsRootDirectory() ? *this : 229f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian RemoveTrailingPathSeparator()); 230a49bf25b24dd239a9da88e783f037d817a6287b0zhanyong.wan#else 231a49bf25b24dd239a9da88e783f037d817a6287b0zhanyong.wan const FilePath& path(*this); 232a49bf25b24dd239a9da88e783f037d817a6287b0zhanyong.wan#endif 233a49bf25b24dd239a9da88e783f037d817a6287b0zhanyong.wan 234fff033497b70e96a5dcadb6ba9570c12b5921d74zhanyong.wan#if GTEST_OS_WINDOWS_MOBILE 235f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian LPCWSTR unicode = String::AnsiToUtf16(path.c_str()); 236dd4a17bc20377d250ed116b1083d851adbe45f25shiqian const DWORD attributes = GetFileAttributes(unicode); 237dd4a17bc20377d250ed116b1083d851adbe45f25shiqian delete [] unicode; 238dd4a17bc20377d250ed116b1083d851adbe45f25shiqian if ((attributes != kInvalidFileAttributes) && 239dd4a17bc20377d250ed116b1083d851adbe45f25shiqian (attributes & FILE_ATTRIBUTE_DIRECTORY)) { 240dd4a17bc20377d250ed116b1083d851adbe45f25shiqian result = true; 241dd4a17bc20377d250ed116b1083d851adbe45f25shiqian } 242dd4a17bc20377d250ed116b1083d851adbe45f25shiqian#else 243c7f60f1514013d57a624c3a2966709998678f24bzhanyong.wan posix::StatStruct file_stat; 244c7f60f1514013d57a624c3a2966709998678f24bzhanyong.wan result = posix::Stat(path.c_str(), &file_stat) == 0 && 245a49bf25b24dd239a9da88e783f037d817a6287b0zhanyong.wan posix::IsDir(file_stat); 246fff033497b70e96a5dcadb6ba9570c12b5921d74zhanyong.wan#endif // GTEST_OS_WINDOWS_MOBILE 247a49bf25b24dd239a9da88e783f037d817a6287b0zhanyong.wan 2484b6829f0d28990dd645e16386eb226d0f10c8731shiqian return result; 2494b6829f0d28990dd645e16386eb226d0f10c8731shiqian} 2504b6829f0d28990dd645e16386eb226d0f10c8731shiqian 251f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian// Returns true if pathname describes a root directory. (Windows has one 252f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian// root directory per disk drive.) 253f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqianbool FilePath::IsRootDirectory() const { 2544cd62602913a032a7aec091d4c8055ff9af95e37zhanyong.wan#if GTEST_OS_WINDOWS 255e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wan // TODO(wan@google.com): on Windows a network share like 256e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wan // \\server\share can be a root directory, although it cannot be the 257e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wan // current directory. Handle this properly. 25889be5763249cbab785abfa310fb1cd6b5e9c4adfzhanyong.wan return pathname_.length() == 3 && IsAbsolutePath(); 259e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wan#else 2608236131e25705a809d496672a3819e1741166c4bzhanyong.wan return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); 261e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wan#endif 262e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wan} 263e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wan 264e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wan// Returns true if pathname describes an absolute path. 265e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wanbool FilePath::IsAbsolutePath() const { 266e5722bdcf1680483a80d97707dd8b97a7c346759zhanyong.wan const char* const name = pathname_.c_str(); 2674cd62602913a032a7aec091d4c8055ff9af95e37zhanyong.wan#if GTEST_OS_WINDOWS 26889be5763249cbab785abfa310fb1cd6b5e9c4adfzhanyong.wan return pathname_.length() >= 3 && 269f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian ((name[0] >= 'a' && name[0] <= 'z') || 270f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian (name[0] >= 'A' && name[0] <= 'Z')) && 271f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian name[1] == ':' && 2728236131e25705a809d496672a3819e1741166c4bzhanyong.wan IsPathSeparator(name[2]); 273f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian#else 2748236131e25705a809d496672a3819e1741166c4bzhanyong.wan return IsPathSeparator(name[0]); 275f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian#endif 276f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian} 277f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian 2784b6829f0d28990dd645e16386eb226d0f10c8731shiqian// Returns a pathname for a file that does not currently exist. The pathname 2794b6829f0d28990dd645e16386eb226d0f10c8731shiqian// will be directory/base_name.extension or 2804b6829f0d28990dd645e16386eb226d0f10c8731shiqian// directory/base_name_<number>.extension if directory/base_name.extension 2814b6829f0d28990dd645e16386eb226d0f10c8731shiqian// already exists. The number will be incremented until a pathname is found 2824b6829f0d28990dd645e16386eb226d0f10c8731shiqian// that does not already exist. 2834b6829f0d28990dd645e16386eb226d0f10c8731shiqian// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. 2844b6829f0d28990dd645e16386eb226d0f10c8731shiqian// There could be a race condition if two or more processes are calling this 2854b6829f0d28990dd645e16386eb226d0f10c8731shiqian// function at the same time -- they could both pick the same filename. 2864b6829f0d28990dd645e16386eb226d0f10c8731shiqianFilePath FilePath::GenerateUniqueFileName(const FilePath& directory, 2874b6829f0d28990dd645e16386eb226d0f10c8731shiqian const FilePath& base_name, 2884b6829f0d28990dd645e16386eb226d0f10c8731shiqian const char* extension) { 2894b6829f0d28990dd645e16386eb226d0f10c8731shiqian FilePath full_pathname; 2904b6829f0d28990dd645e16386eb226d0f10c8731shiqian int number = 0; 2914b6829f0d28990dd645e16386eb226d0f10c8731shiqian do { 2924b6829f0d28990dd645e16386eb226d0f10c8731shiqian full_pathname.Set(MakeFileName(directory, base_name, number++, extension)); 2934b6829f0d28990dd645e16386eb226d0f10c8731shiqian } while (full_pathname.FileOrDirectoryExists()); 2944b6829f0d28990dd645e16386eb226d0f10c8731shiqian return full_pathname; 2954b6829f0d28990dd645e16386eb226d0f10c8731shiqian} 2964b6829f0d28990dd645e16386eb226d0f10c8731shiqian 2974b6829f0d28990dd645e16386eb226d0f10c8731shiqian// Returns true if FilePath ends with a path separator, which indicates that 2984b6829f0d28990dd645e16386eb226d0f10c8731shiqian// it is intended to represent a directory. Returns false otherwise. 2994b6829f0d28990dd645e16386eb226d0f10c8731shiqian// This does NOT check that a directory (or file) actually exists. 3004b6829f0d28990dd645e16386eb226d0f10c8731shiqianbool FilePath::IsDirectory() const { 3018236131e25705a809d496672a3819e1741166c4bzhanyong.wan return !pathname_.empty() && 3028236131e25705a809d496672a3819e1741166c4bzhanyong.wan IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]); 3034b6829f0d28990dd645e16386eb226d0f10c8731shiqian} 3044b6829f0d28990dd645e16386eb226d0f10c8731shiqian 3054b6829f0d28990dd645e16386eb226d0f10c8731shiqian// Create directories so that path exists. Returns true if successful or if 3064b6829f0d28990dd645e16386eb226d0f10c8731shiqian// the directories already exist; returns false if unable to create directories 3074b6829f0d28990dd645e16386eb226d0f10c8731shiqian// for any reason. 3084b6829f0d28990dd645e16386eb226d0f10c8731shiqianbool FilePath::CreateDirectoriesRecursively() const { 3094b6829f0d28990dd645e16386eb226d0f10c8731shiqian if (!this->IsDirectory()) { 3104b6829f0d28990dd645e16386eb226d0f10c8731shiqian return false; 3114b6829f0d28990dd645e16386eb226d0f10c8731shiqian } 3124b6829f0d28990dd645e16386eb226d0f10c8731shiqian 31389be5763249cbab785abfa310fb1cd6b5e9c4adfzhanyong.wan if (pathname_.length() == 0 || this->DirectoryExists()) { 3144b6829f0d28990dd645e16386eb226d0f10c8731shiqian return true; 3154b6829f0d28990dd645e16386eb226d0f10c8731shiqian } 3164b6829f0d28990dd645e16386eb226d0f10c8731shiqian 3174b6829f0d28990dd645e16386eb226d0f10c8731shiqian const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName()); 3184b6829f0d28990dd645e16386eb226d0f10c8731shiqian return parent.CreateDirectoriesRecursively() && this->CreateFolder(); 3194b6829f0d28990dd645e16386eb226d0f10c8731shiqian} 3204b6829f0d28990dd645e16386eb226d0f10c8731shiqian 3214b6829f0d28990dd645e16386eb226d0f10c8731shiqian// Create the directory so that path exists. Returns true if successful or 3224b6829f0d28990dd645e16386eb226d0f10c8731shiqian// if the directory already exists; returns false if unable to create the 3234b6829f0d28990dd645e16386eb226d0f10c8731shiqian// directory for any reason, including if the parent directory does not 3244b6829f0d28990dd645e16386eb226d0f10c8731shiqian// exist. Not named "CreateDirectory" because that's a macro on Windows. 3254b6829f0d28990dd645e16386eb226d0f10c8731shiqianbool FilePath::CreateFolder() const { 326fff033497b70e96a5dcadb6ba9570c12b5921d74zhanyong.wan#if GTEST_OS_WINDOWS_MOBILE 327dd4a17bc20377d250ed116b1083d851adbe45f25shiqian FilePath removed_sep(this->RemoveTrailingPathSeparator()); 328dd4a17bc20377d250ed116b1083d851adbe45f25shiqian LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str()); 329dd4a17bc20377d250ed116b1083d851adbe45f25shiqian int result = CreateDirectory(unicode, NULL) ? 0 : -1; 330dd4a17bc20377d250ed116b1083d851adbe45f25shiqian delete [] unicode; 331fff033497b70e96a5dcadb6ba9570c12b5921d74zhanyong.wan#elif GTEST_OS_WINDOWS 3324b6829f0d28990dd645e16386eb226d0f10c8731shiqian int result = _mkdir(pathname_.c_str()); 3334b6829f0d28990dd645e16386eb226d0f10c8731shiqian#else 3344b6829f0d28990dd645e16386eb226d0f10c8731shiqian int result = mkdir(pathname_.c_str(), 0777); 335fff033497b70e96a5dcadb6ba9570c12b5921d74zhanyong.wan#endif // GTEST_OS_WINDOWS_MOBILE 336fff033497b70e96a5dcadb6ba9570c12b5921d74zhanyong.wan 3374b6829f0d28990dd645e16386eb226d0f10c8731shiqian if (result == -1) { 3384b6829f0d28990dd645e16386eb226d0f10c8731shiqian return this->DirectoryExists(); // An error is OK if the directory exists. 3394b6829f0d28990dd645e16386eb226d0f10c8731shiqian } 3404b6829f0d28990dd645e16386eb226d0f10c8731shiqian return true; // No error. 3414b6829f0d28990dd645e16386eb226d0f10c8731shiqian} 3424b6829f0d28990dd645e16386eb226d0f10c8731shiqian 3434b6829f0d28990dd645e16386eb226d0f10c8731shiqian// If input name has a trailing separator character, remove it and return the 3444b6829f0d28990dd645e16386eb226d0f10c8731shiqian// name, otherwise return the name string unmodified. 3454b6829f0d28990dd645e16386eb226d0f10c8731shiqian// On Windows platform, uses \ as the separator, other platforms use /. 3464b6829f0d28990dd645e16386eb226d0f10c8731shiqianFilePath FilePath::RemoveTrailingPathSeparator() const { 3478236131e25705a809d496672a3819e1741166c4bzhanyong.wan return IsDirectory() 34803c314931649a999b0cf5deb0a434a1009157416jgm@google.com ? FilePath(pathname_.substr(0, pathname_.length() - 1)) 3494b6829f0d28990dd645e16386eb226d0f10c8731shiqian : *this; 3504b6829f0d28990dd645e16386eb226d0f10c8731shiqian} 3514b6829f0d28990dd645e16386eb226d0f10c8731shiqian 352673a0cb9079f8f37bd61588a3160e12daf70ec44vladlosev// Removes any redundant separators that might be in the pathname. 353f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian// For example, "bar///foo" becomes "bar/foo". Does not eliminate other 354f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian// redundancies that might be in a pathname involving "." or "..". 355673a0cb9079f8f37bd61588a3160e12daf70ec44vladlosev// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share). 356f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqianvoid FilePath::Normalize() { 357f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian if (pathname_.c_str() == NULL) { 358f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian pathname_ = ""; 359f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian return; 360f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian } 361f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian const char* src = pathname_.c_str(); 36289be5763249cbab785abfa310fb1cd6b5e9c4adfzhanyong.wan char* const dest = new char[pathname_.length() + 1]; 363f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian char* dest_ptr = dest; 36489be5763249cbab785abfa310fb1cd6b5e9c4adfzhanyong.wan memset(dest_ptr, 0, pathname_.length() + 1); 365f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian 366f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian while (*src != '\0') { 3678236131e25705a809d496672a3819e1741166c4bzhanyong.wan *dest_ptr = *src; 3688236131e25705a809d496672a3819e1741166c4bzhanyong.wan if (!IsPathSeparator(*src)) { 369f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian src++; 3708236131e25705a809d496672a3819e1741166c4bzhanyong.wan } else { 3718236131e25705a809d496672a3819e1741166c4bzhanyong.wan#if GTEST_HAS_ALT_PATH_SEP_ 3728236131e25705a809d496672a3819e1741166c4bzhanyong.wan if (*dest_ptr == kAlternatePathSeparator) { 3738236131e25705a809d496672a3819e1741166c4bzhanyong.wan *dest_ptr = kPathSeparator; 3748236131e25705a809d496672a3819e1741166c4bzhanyong.wan } 3758236131e25705a809d496672a3819e1741166c4bzhanyong.wan#endif 3768236131e25705a809d496672a3819e1741166c4bzhanyong.wan while (IsPathSeparator(*src)) 377f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian src++; 3788236131e25705a809d496672a3819e1741166c4bzhanyong.wan } 3798236131e25705a809d496672a3819e1741166c4bzhanyong.wan dest_ptr++; 380f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian } 381f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian *dest_ptr = '\0'; 382f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian pathname_ = dest; 383f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian delete[] dest; 384f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian} 385f0e809a3c9946e99595d4faeb0a16bdc2ca9ffd5shiqian 3864b6829f0d28990dd645e16386eb226d0f10c8731shiqian} // namespace internal 3874b6829f0d28990dd645e16386eb226d0f10c8731shiqian} // namespace testing 388