gtest-filepath.cc revision fbaaef999ba563838ebd00874ed8a1c01fbf286d
1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Copyright 2008, Google Inc. 2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// All rights reserved. 3fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 4fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Redistribution and use in source and binary forms, with or without 5fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// modification, are permitted provided that the following conditions are 6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// met: 7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Redistributions of source code must retain the above copyright 9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// notice, this list of conditions and the following disclaimer. 10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Redistributions in binary form must reproduce the above 11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// copyright notice, this list of conditions and the following disclaimer 12fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// in the documentation and/or other materials provided with the 13fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// distribution. 14fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Neither the name of Google Inc. nor the names of its 15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// contributors may be used to endorse or promote products derived from 16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// this software without specific prior written permission. 17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Authors: keith.ray@gmail.com (Keith Ray) 31fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <gtest/internal/gtest-filepath.h> 33fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <gtest/internal/gtest-port.h> 34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 35fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <stdlib.h> 36fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32_WCE 38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <windows.h> 39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#elif GTEST_OS_WINDOWS 40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <direct.h> 41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <io.h> 42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#elif GTEST_OS_SYMBIAN 43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Symbian OpenC has PATH_MAX in sys/syslimits.h 44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <sys/syslimits.h> 45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <limits.h> 47fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <climits> // Some Linux distributions define PATH_MAX here. 48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif // _WIN32_WCE or _WIN32 49fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 50fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if GTEST_OS_WINDOWS 51fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define GTEST_PATH_MAX_ _MAX_PATH 52fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#elif defined(PATH_MAX) 53fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define GTEST_PATH_MAX_ PATH_MAX 54fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#elif defined(_XOPEN_PATH_MAX) 55fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define GTEST_PATH_MAX_ _XOPEN_PATH_MAX 56fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 57fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define GTEST_PATH_MAX_ _POSIX_PATH_MAX 58fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif // GTEST_OS_WINDOWS 59fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 60fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <gtest/internal/gtest-string.h> 61fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace testing { 63fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace internal { 64fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if GTEST_OS_WINDOWS 66fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleconst char kPathSeparator = '\\'; 67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleconst char kPathSeparatorString[] = "\\"; 68fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32_WCE 69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Windows CE doesn't have a current directory. You should not use 70fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// the current directory in tests on Windows CE, but this at least 71fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// provides a reasonable fallback. 72fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleconst char kCurrentDirectoryString[] = "\\"; 73fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Windows CE doesn't define INVALID_FILE_ATTRIBUTES 74fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleconst DWORD kInvalidFileAttributes = 0xffffffff; 75fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 76fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleconst char kCurrentDirectoryString[] = ".\\"; 77fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif // _WIN32_WCE 78fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 79fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleconst char kPathSeparator = '/'; 80fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleconst char kPathSeparatorString[] = "/"; 81fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleconst char kCurrentDirectoryString[] = "./"; 82fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif // GTEST_OS_WINDOWS 83fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 84fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Returns the current working directory, or "" if unsuccessful. 85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleFilePath FilePath::GetCurrentDir() { 86fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32_WCE 87fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Windows CE doesn't have a current directory, so we just return 88fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// something reasonable. 89fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return FilePath(kCurrentDirectoryString); 90fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#elif GTEST_OS_WINDOWS 91fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; 92fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); 93fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 94fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; 95fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); 96fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 97fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 98fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 99fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Returns a copy of the FilePath with the case-insensitive extension removed. 100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns 101fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// FilePath("dir/file"). If a case-insensitive extension is not 102fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// found, returns a copy of the original FilePath. 103fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleFilePath FilePath::RemoveExtension(const char* extension) const { 104fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville String dot_extension(String::Format(".%s", extension)); 105fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (pathname_.EndsWithCaseInsensitive(dot_extension.c_str())) { 106fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return FilePath(String(pathname_.c_str(), pathname_.GetLength() - 4)); 107fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return *this; 109fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Returns a copy of the FilePath with the directory part removed. 112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Example: FilePath("path/to/file").RemoveDirectoryName() returns 113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// FilePath("file"). If there is no directory part ("just_a_file"), it returns 114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// the FilePath unmodified. If there is no file part ("just_a_dir/") it 115fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// returns an empty FilePath (""). 116fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// On Windows platform, '\' is the path separator, otherwise it is '/'. 117fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleFilePath FilePath::RemoveDirectoryName() const { 118fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const char* const last_sep = strrchr(c_str(), kPathSeparator); 119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return last_sep ? FilePath(String(last_sep + 1)) : *this; 120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 122fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// RemoveFileName returns the directory path with the filename removed. 123fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". 124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// If the FilePath is "a_file" or "/a_file", RemoveFileName returns 125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does 126fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// not have a file, like "just/a/dir/", it returns the FilePath unmodified. 127fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// On Windows platform, '\' is the path separator, otherwise it is '/'. 128fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleFilePath FilePath::RemoveFileName() const { 129fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const char* const last_sep = strrchr(c_str(), kPathSeparator); 130fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville String dir; 131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (last_sep) { 132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville dir = String(c_str(), last_sep + 1 - c_str()); 133fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville dir = kCurrentDirectoryString; 135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return FilePath(dir); 137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Helper functions for naming files in a directory for xml output. 140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Given directory = "dir", base_name = "test", number = 0, 142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// extension = "xml", returns "dir/test.xml". If number is greater 143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// than zero (e.g., 12), returns "dir/test_12.xml". 144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// On Windows platform, uses \ as the separator rather than /. 145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleFilePath FilePath::MakeFileName(const FilePath& directory, 146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const FilePath& base_name, 147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int number, 148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const char* extension) { 149fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville String file; 150fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (number == 0) { 151fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file = String::Format("%s.%s", base_name.c_str(), extension); 152fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 153fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file = String::Format("%s_%d.%s", base_name.c_str(), number, extension); 154fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 155fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return ConcatPaths(directory, FilePath(file)); 156fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 157fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 158fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml". 159fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// On Windows, uses \ as the separator rather than /. 160fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleFilePath FilePath::ConcatPaths(const FilePath& directory, 161fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const FilePath& relative_path) { 162fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (directory.IsEmpty()) 163fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return relative_path; 164fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const FilePath dir(directory.RemoveTrailingPathSeparator()); 165fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return FilePath(String::Format("%s%c%s", dir.c_str(), kPathSeparator, 166fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville relative_path.c_str())); 167fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 168fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 169fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Returns true if pathname describes something findable in the file-system, 170fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// either a file, directory, or whatever. 171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool FilePath::FileOrDirectoryExists() const { 172fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32_WCE 173fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str()); 174fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const DWORD attributes = GetFileAttributes(unicode); 175fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville delete [] unicode; 176fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return attributes != kInvalidFileAttributes; 177fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 178fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville posix::StatStruct file_stat; 179fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return posix::Stat(pathname_.c_str(), &file_stat) == 0; 180fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif // _WIN32_WCE 181fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Returns true if pathname describes a directory in the file-system 184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// that exists. 185fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool FilePath::DirectoryExists() const { 186fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville bool result = false; 187fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if GTEST_OS_WINDOWS 188fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Don't strip off trailing separator if path is a root directory on 189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Windows (like "C:\\"). 190fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const FilePath& path(IsRootDirectory() ? *this : 191fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville RemoveTrailingPathSeparator()); 192fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const FilePath& path(*this); 194fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 195fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32_WCE 197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville LPCWSTR unicode = String::AnsiToUtf16(path.c_str()); 198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const DWORD attributes = GetFileAttributes(unicode); 199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville delete [] unicode; 200fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if ((attributes != kInvalidFileAttributes) && 201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville (attributes & FILE_ATTRIBUTE_DIRECTORY)) { 202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville result = true; 203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 205fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville posix::StatStruct file_stat; 206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville result = posix::Stat(path.c_str(), &file_stat) == 0 && 207fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville posix::IsDir(file_stat); 208fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif // _WIN32_WCE 209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return result; 211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Returns true if pathname describes a root directory. (Windows has one 214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// root directory per disk drive.) 215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool FilePath::IsRootDirectory() const { 216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if GTEST_OS_WINDOWS 217fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // TODO(wan@google.com): on Windows a network share like 218fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // \\server\share can be a root directory, although it cannot be the 219fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // current directory. Handle this properly. 220fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return pathname_.GetLength() == 3 && IsAbsolutePath(); 221fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 222fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return pathname_ == kPathSeparatorString; 223fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 224fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 225fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 226fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Returns true if pathname describes an absolute path. 227fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool FilePath::IsAbsolutePath() const { 228fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const char* const name = pathname_.c_str(); 229fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if GTEST_OS_WINDOWS 230fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return pathname_.GetLength() >= 3 && 231fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ((name[0] >= 'a' && name[0] <= 'z') || 232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville (name[0] >= 'A' && name[0] <= 'Z')) && 233fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name[1] == ':' && 234fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name[2] == kPathSeparator; 235fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return name[0] == kPathSeparator; 237fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 238fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 239fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 240fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Returns a pathname for a file that does not currently exist. The pathname 241fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// will be directory/base_name.extension or 242fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// directory/base_name_<number>.extension if directory/base_name.extension 243fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// already exists. The number will be incremented until a pathname is found 244fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// that does not already exist. 245fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. 246fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// There could be a race condition if two or more processes are calling this 247fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// function at the same time -- they could both pick the same filename. 248fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleFilePath FilePath::GenerateUniqueFileName(const FilePath& directory, 249fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const FilePath& base_name, 250fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const char* extension) { 251fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville FilePath full_pathname; 252fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int number = 0; 253fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville do { 254fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville full_pathname.Set(MakeFileName(directory, base_name, number++, extension)); 255fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } while (full_pathname.FileOrDirectoryExists()); 256fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return full_pathname; 257fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 258fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 259fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Returns true if FilePath ends with a path separator, which indicates that 260fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// it is intended to represent a directory. Returns false otherwise. 261fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// This does NOT check that a directory (or file) actually exists. 262fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool FilePath::IsDirectory() const { 263fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return pathname_.EndsWith(kPathSeparatorString); 264fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 265fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 266fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Create directories so that path exists. Returns true if successful or if 267fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// the directories already exist; returns false if unable to create directories 268fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// for any reason. 269fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool FilePath::CreateDirectoriesRecursively() const { 270fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!this->IsDirectory()) { 271fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 272fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 273fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 274fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (pathname_.GetLength() == 0 || this->DirectoryExists()) { 275fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return true; 276fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 277fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 278fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName()); 279fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return parent.CreateDirectoriesRecursively() && this->CreateFolder(); 280fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 281fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 282fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Create the directory so that path exists. Returns true if successful or 283fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// if the directory already exists; returns false if unable to create the 284fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// directory for any reason, including if the parent directory does not 285fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// exist. Not named "CreateDirectory" because that's a macro on Windows. 286fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool FilePath::CreateFolder() const { 287fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if GTEST_OS_WINDOWS 288fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32_WCE 289fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville FilePath removed_sep(this->RemoveTrailingPathSeparator()); 290fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str()); 291fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int result = CreateDirectory(unicode, NULL) ? 0 : -1; 292fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville delete [] unicode; 293fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 294fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int result = _mkdir(pathname_.c_str()); 295fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif // !WIN32_WCE 296fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 297fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int result = mkdir(pathname_.c_str(), 0777); 298fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif // _WIN32 299fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (result == -1) { 300fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return this->DirectoryExists(); // An error is OK if the directory exists. 301fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 302fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return true; // No error. 303fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 304fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 305fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// If input name has a trailing separator character, remove it and return the 306fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// name, otherwise return the name string unmodified. 307fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// On Windows platform, uses \ as the separator, other platforms use /. 308fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleFilePath FilePath::RemoveTrailingPathSeparator() const { 309fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return pathname_.EndsWith(kPathSeparatorString) 310fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ? FilePath(String(pathname_.c_str(), pathname_.GetLength() - 1)) 311fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville : *this; 312fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 313fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 314fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Normalize removes any redundant separators that might be in the pathname. 315fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// For example, "bar///foo" becomes "bar/foo". Does not eliminate other 316fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// redundancies that might be in a pathname involving "." or "..". 317fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid FilePath::Normalize() { 318fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (pathname_.c_str() == NULL) { 319fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville pathname_ = ""; 320fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return; 321fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 322fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const char* src = pathname_.c_str(); 323fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville char* const dest = new char[pathname_.GetLength() + 1]; 324fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville char* dest_ptr = dest; 325fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville memset(dest_ptr, 0, pathname_.GetLength() + 1); 326fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 327fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville while (*src != '\0') { 328fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville *dest_ptr++ = *src; 329fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (*src != kPathSeparator) 330fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville src++; 331fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville else 332fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville while (*src == kPathSeparator) 333fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville src++; 334fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 335fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville *dest_ptr = '\0'; 336fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville pathname_ = dest; 337fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville delete[] dest; 338fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 339fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 340fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // namespace internal 341fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // namespace testing 342