1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright 2008, Google Inc. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// All rights reserved. 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Redistribution and use in source and binary forms, with or without 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// modification, are permitted provided that the following conditions are 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// met: 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * Redistributions of source code must retain the above copyright 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// notice, this list of conditions and the following disclaimer. 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * Redistributions in binary form must reproduce the above 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// copyright notice, this list of conditions and the following disclaimer 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// in the documentation and/or other materials provided with the 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// distribution. 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * Neither the name of Google Inc. nor the names of its 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// contributors may be used to endorse or promote products derived from 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// this software without specific prior written permission. 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Authors: keith.ray@gmail.com (Keith Ray) 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <gtest/internal/gtest-filepath.h> 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <gtest/internal/gtest-port.h> 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef _WIN32 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <direct.h> 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <io.h> 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif // _WIN32 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/stat.h> 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <gtest/internal/gtest-string.h> 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace testing { 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace internal { 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef GTEST_OS_WINDOWS 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char kPathSeparator = '\\'; 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char kPathSeparatorString[] = "\\"; 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char kCurrentDirectoryString[] = ".\\"; 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char kPathSeparator = '/'; 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char kPathSeparatorString[] = "/"; 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char kCurrentDirectoryString[] = "./"; 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif // GTEST_OS_WINDOWS 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Returns a copy of the FilePath with the case-insensitive extension removed. 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// FilePath("dir/file"). If a case-insensitive extension is not 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found, returns a copy of the original FilePath. 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFilePath FilePath::RemoveExtension(const char* extension) const { 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott String dot_extension(String::Format(".%s", extension)); 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (pathname_.EndsWithCaseInsensitive(dot_extension.c_str())) { 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return FilePath(String(pathname_.c_str(), pathname_.GetLength() - 4)); 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return *this; 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Returns a copy of the FilePath with the directory part removed. 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Example: FilePath("path/to/file").RemoveDirectoryName() returns 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// FilePath("file"). If there is no directory part ("just_a_file"), it returns 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the FilePath unmodified. If there is no file part ("just_a_dir/") it 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// returns an empty FilePath (""). 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// On Windows platform, '\' is the path separator, otherwise it is '/'. 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFilePath FilePath::RemoveDirectoryName() const { 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* const last_sep = strrchr(c_str(), kPathSeparator); 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return last_sep ? FilePath(String(last_sep + 1)) : *this; 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// RemoveFileName returns the directory path with the filename removed. 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// If the FilePath is "a_file" or "/a_file", RemoveFileName returns 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// not have a file, like "just/a/dir/", it returns the FilePath unmodified. 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// On Windows platform, '\' is the path separator, otherwise it is '/'. 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFilePath FilePath::RemoveFileName() const { 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* const last_sep = strrchr(c_str(), kPathSeparator); 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return FilePath(last_sep ? String(c_str(), last_sep + 1 - c_str()) 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : String(kCurrentDirectoryString)); 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Helper functions for naming files in a directory for xml output. 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Given directory = "dir", base_name = "test", number = 0, 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// extension = "xml", returns "dir/test.xml". If number is greater 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// than zero (e.g., 12), returns "dir/test_12.xml". 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// On Windows platform, uses \ as the separator rather than /. 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFilePath FilePath::MakeFileName(const FilePath& directory, 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const FilePath& base_name, 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int number, 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* extension) { 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FilePath dir(directory.RemoveTrailingPathSeparator()); 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (number == 0) { 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return FilePath(String::Format("%s%c%s.%s", dir.c_str(), kPathSeparator, 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott base_name.c_str(), extension)); 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return FilePath(String::Format("%s%c%s_%d.%s", dir.c_str(), kPathSeparator, 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott base_name.c_str(), number, extension)); 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Returns true if pathname describes something findable in the file-system, 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// either a file, directory, or whatever. 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FilePath::FileOrDirectoryExists() const { 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef GTEST_OS_WINDOWS 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct _stat file_stat; 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return _stat(pathname_.c_str(), &file_stat) == 0; 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct stat file_stat; 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return stat(pathname_.c_str(), &file_stat) == 0; 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif // GTEST_OS_WINDOWS 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Returns true if pathname describes a directory in the file-system 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// that exists. 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FilePath::DirectoryExists() const { 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool result = false; 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef _WIN32 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FilePath removed_sep(this->RemoveTrailingPathSeparator()); 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct _stat file_stat; 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott file_stat.st_mode = 0; 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = _stat(removed_sep.c_str(), &file_stat) == 0 && 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (_S_IFDIR & file_stat.st_mode) != 0; 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct stat file_stat; 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott file_stat.st_mode = 0; 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = stat(pathname_.c_str(), &file_stat) == 0 && 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott S_ISDIR(file_stat.st_mode); 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif // _WIN32 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Returns a pathname for a file that does not currently exist. The pathname 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// will be directory/base_name.extension or 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// directory/base_name_<number>.extension if directory/base_name.extension 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// already exists. The number will be incremented until a pathname is found 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// that does not already exist. 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// There could be a race condition if two or more processes are calling this 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// function at the same time -- they could both pick the same filename. 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFilePath FilePath::GenerateUniqueFileName(const FilePath& directory, 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const FilePath& base_name, 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* extension) { 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FilePath full_pathname; 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int number = 0; 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott full_pathname.Set(MakeFileName(directory, base_name, number++, extension)); 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while (full_pathname.FileOrDirectoryExists()); 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return full_pathname; 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Returns true if FilePath ends with a path separator, which indicates that 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// it is intended to represent a directory. Returns false otherwise. 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This does NOT check that a directory (or file) actually exists. 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FilePath::IsDirectory() const { 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return pathname_.EndsWith(kPathSeparatorString); 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Create directories so that path exists. Returns true if successful or if 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the directories already exist; returns false if unable to create directories 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// for any reason. 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FilePath::CreateDirectoriesRecursively() const { 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!this->IsDirectory()) { 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (pathname_.GetLength() == 0 || this->DirectoryExists()) { 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName()); 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return parent.CreateDirectoriesRecursively() && this->CreateFolder(); 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Create the directory so that path exists. Returns true if successful or 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// if the directory already exists; returns false if unable to create the 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// directory for any reason, including if the parent directory does not 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// exist. Not named "CreateDirectory" because that's a macro on Windows. 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FilePath::CreateFolder() const { 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef _WIN32 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int result = _mkdir(pathname_.c_str()); 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int result = mkdir(pathname_.c_str(), 0777); 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif // _WIN32 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == -1) { 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return this->DirectoryExists(); // An error is OK if the directory exists. 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; // No error. 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// If input name has a trailing separator character, remove it and return the 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// name, otherwise return the name string unmodified. 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// On Windows platform, uses \ as the separator, other platforms use /. 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFilePath FilePath::RemoveTrailingPathSeparator() const { 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return pathname_.EndsWith(kPathSeparatorString) 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ? FilePath(String(pathname_.c_str(), pathname_.GetLength() - 1)) 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : *this; 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace internal 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace testing 211