1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE file.
6
7 #include "base/file_util.h"
8
9 #if defined(OS_WIN)
10 #include <io.h>
11 #endif
12 #include <stdio.h>
13 #if defined(ANDROID) || defined(OS_POSIX)
14 #include <unistd.h>
15 #endif
16
17 #include <fstream>
18
19 #include "base/file_path.h"
20 #include "base/logging.h"
21 #include "base/string_util.h"
22
23 #include "base/string_piece.h"
24 #include "base/sys_string_conversions.h"
25
26 namespace {
27
28 const FilePath::CharType kExtensionSeparator = FILE_PATH_LITERAL('.');
29
30 } // namespace
31
32 namespace file_util {
33
EndsWithSeparator(const FilePath & path)34 bool EndsWithSeparator(const FilePath& path) {
35 FilePath::StringType value = path.value();
36 if (value.empty()) return false;
37
38 return FilePath::IsSeparator(value[value.size() - 1]);
39 }
40
TrimTrailingSeparator(std::wstring * dir)41 void TrimTrailingSeparator(std::wstring* dir) {
42 while (dir->length() > 1 && EndsWithSeparator(dir))
43 dir->resize(dir->length() - 1);
44 }
45
GetFileExtensionFromPath(const FilePath & path)46 FilePath::StringType GetFileExtensionFromPath(const FilePath& path) {
47 FilePath::StringType file_name = path.BaseName().value();
48 const FilePath::StringType::size_type last_dot =
49 file_name.rfind(kExtensionSeparator);
50 return FilePath::StringType(last_dot == FilePath::StringType::npos
51 ? FILE_PATH_LITERAL("")
52 : file_name,
53 last_dot + 1);
54 }
55
InsertBeforeExtension(FilePath * path,const FilePath::StringType & suffix)56 void InsertBeforeExtension(FilePath* path, const FilePath::StringType& suffix) {
57 FilePath::StringType& value =
58 const_cast<FilePath::StringType&>(path->value());
59
60 const FilePath::StringType::size_type last_dot =
61 value.rfind(kExtensionSeparator);
62 const FilePath::StringType::size_type last_separator =
63 value.find_last_of(FilePath::StringType(FilePath::kSeparators));
64
65 if (last_dot == FilePath::StringType::npos ||
66 (last_separator != std::wstring::npos && last_dot < last_separator)) {
67 // The path looks something like "C:\pics.old\jojo" or "C:\pics\jojo".
68 // We should just append the suffix to the entire path.
69 value.append(suffix);
70 return;
71 }
72
73 value.insert(last_dot, suffix);
74 }
75
ReplaceExtension(FilePath * path,const FilePath::StringType & extension)76 void ReplaceExtension(FilePath* path, const FilePath::StringType& extension) {
77 FilePath::StringType clean_extension;
78 // If the new extension is "" or ".", then we will just remove the current
79 // extension.
80 if (!extension.empty() &&
81 extension != FilePath::StringType(&kExtensionSeparator, 1)) {
82 if (extension[0] != kExtensionSeparator)
83 clean_extension.append(&kExtensionSeparator, 1);
84 clean_extension.append(extension);
85 }
86
87 FilePath::StringType& value =
88 const_cast<FilePath::StringType&>(path->value());
89 const FilePath::StringType::size_type last_dot =
90 value.rfind(kExtensionSeparator);
91 const FilePath::StringType::size_type last_separator =
92 value.find_last_of(FilePath::StringType(FilePath::kSeparators));
93
94 // Erase the current extension, if any.
95 if ((last_dot > last_separator ||
96 last_separator == FilePath::StringType::npos) &&
97 last_dot != FilePath::StringType::npos)
98 value.erase(last_dot);
99
100 value.append(clean_extension);
101 }
102
CreateAndOpenTemporaryFile(FilePath * path)103 FILE* CreateAndOpenTemporaryFile(FilePath* path) {
104 FilePath directory;
105 if (!GetTempDir(&directory)) return NULL;
106
107 return CreateAndOpenTemporaryFileInDir(directory, path);
108 }
109
GetFileSize(const FilePath & file_path,int64_t * file_size)110 bool GetFileSize(const FilePath& file_path, int64_t* file_size) {
111 FileInfo info;
112 if (!GetFileInfo(file_path, &info)) return false;
113 *file_size = info.size;
114 return true;
115 }
116
CloseFile(FILE * file)117 bool CloseFile(FILE* file) {
118 if (file == NULL) return true;
119 return fclose(file) == 0;
120 }
121
122 // Deprecated functions ----------------------------------------------------
123
AbsolutePath(std::wstring * path_str)124 bool AbsolutePath(std::wstring* path_str) {
125 FilePath path(FilePath::FromWStringHack(*path_str));
126 if (!AbsolutePath(&path)) return false;
127 *path_str = path.ToWStringHack();
128 return true;
129 }
AppendToPath(std::wstring * path,const std::wstring & new_ending)130 void AppendToPath(std::wstring* path, const std::wstring& new_ending) {
131 if (!path) {
132 NOTREACHED();
133 return; // Don't crash in this function in release builds.
134 }
135
136 if (!EndsWithSeparator(path)) path->push_back(FilePath::kSeparators[0]);
137 path->append(new_ending);
138 }
CopyFile(const std::wstring & from_path,const std::wstring & to_path)139 bool CopyFile(const std::wstring& from_path, const std::wstring& to_path) {
140 return CopyFile(FilePath::FromWStringHack(from_path),
141 FilePath::FromWStringHack(to_path));
142 }
CreateDirectory(const std::wstring & full_path)143 bool CreateDirectory(const std::wstring& full_path) {
144 return CreateDirectory(FilePath::FromWStringHack(full_path));
145 }
CreateNewTempDirectory(const std::wstring & prefix,std::wstring * new_temp_path)146 bool CreateNewTempDirectory(const std::wstring& prefix,
147 std::wstring* new_temp_path) {
148 #if defined(OS_WIN)
149 FilePath::StringType dir_prefix(prefix);
150 #elif defined(OS_POSIX)
151 FilePath::StringType dir_prefix = WideToUTF8(prefix);
152 #endif
153 FilePath temp_path;
154 if (!CreateNewTempDirectory(dir_prefix, &temp_path)) return false;
155 *new_temp_path = temp_path.ToWStringHack();
156 return true;
157 }
CreateTemporaryFileName(std::wstring * temp_file)158 bool CreateTemporaryFileName(std::wstring* temp_file) {
159 FilePath temp_file_path;
160 if (!CreateTemporaryFileName(&temp_file_path)) return false;
161 *temp_file = temp_file_path.ToWStringHack();
162 return true;
163 }
Delete(const std::wstring & path)164 bool Delete(const std::wstring& path) {
165 return Delete(FilePath::FromWStringHack(path));
166 }
DirectoryExists(const std::wstring & path)167 bool DirectoryExists(const std::wstring& path) {
168 return DirectoryExists(FilePath::FromWStringHack(path));
169 }
EndsWithSeparator(std::wstring * path)170 bool EndsWithSeparator(std::wstring* path) {
171 return EndsWithSeparator(FilePath::FromWStringHack(*path));
172 }
EndsWithSeparator(const std::wstring & path)173 bool EndsWithSeparator(const std::wstring& path) {
174 return EndsWithSeparator(FilePath::FromWStringHack(path));
175 }
GetCurrentDirectory(std::wstring * path_str)176 bool GetCurrentDirectory(std::wstring* path_str) {
177 FilePath path;
178 if (!GetCurrentDirectory(&path)) return false;
179 *path_str = path.ToWStringHack();
180 return true;
181 }
GetFileExtensionFromPath(const std::wstring & path)182 std::wstring GetFileExtensionFromPath(const std::wstring& path) {
183 FilePath::StringType extension =
184 GetFileExtensionFromPath(FilePath::FromWStringHack(path));
185 #if defined(OS_WIN)
186 return extension;
187 #elif defined(OS_POSIX)
188 return UTF8ToWide(extension);
189 #endif
190 }
GetFileInfo(const std::wstring & file_path,FileInfo * results)191 bool GetFileInfo(const std::wstring& file_path, FileInfo* results) {
192 return GetFileInfo(FilePath::FromWStringHack(file_path), results);
193 }
GetFilenameFromPath(const std::wstring & path)194 std::wstring GetFilenameFromPath(const std::wstring& path) {
195 if (path.empty() || EndsWithSeparator(path)) return std::wstring();
196
197 return FilePath::FromWStringHack(path).BaseName().ToWStringHack();
198 }
GetFileSize(const std::wstring & file_path,int64_t * file_size)199 bool GetFileSize(const std::wstring& file_path, int64_t* file_size) {
200 return GetFileSize(FilePath::FromWStringHack(file_path), file_size);
201 }
GetTempDir(std::wstring * path_str)202 bool GetTempDir(std::wstring* path_str) {
203 FilePath path;
204 if (!GetTempDir(&path)) return false;
205 *path_str = path.ToWStringHack();
206 return true;
207 }
OpenFile(const std::wstring & filename,const char * mode)208 FILE* OpenFile(const std::wstring& filename, const char* mode) {
209 return OpenFile(FilePath::FromWStringHack(filename), mode);
210 }
PathExists(const std::wstring & path)211 bool PathExists(const std::wstring& path) {
212 return PathExists(FilePath::FromWStringHack(path));
213 }
PathIsWritable(const std::wstring & path)214 bool PathIsWritable(const std::wstring& path) {
215 return PathIsWritable(FilePath::FromWStringHack(path));
216 }
ReadFile(const std::wstring & filename,char * data,int size)217 int ReadFile(const std::wstring& filename, char* data, int size) {
218 return ReadFile(FilePath::FromWStringHack(filename), data, size);
219 }
SetCurrentDirectory(const std::wstring & directory)220 bool SetCurrentDirectory(const std::wstring& directory) {
221 return SetCurrentDirectory(FilePath::FromWStringHack(directory));
222 }
UpOneDirectory(std::wstring * dir)223 void UpOneDirectory(std::wstring* dir) {
224 FilePath path = FilePath::FromWStringHack(*dir);
225 FilePath directory = path.DirName();
226 // If there is no separator, we will get back kCurrentDirectory.
227 // In this case don't change |dir|.
228 if (directory.value() != FilePath::kCurrentDirectory)
229 *dir = directory.ToWStringHack();
230 }
WriteFile(const std::wstring & filename,const char * data,int size)231 int WriteFile(const std::wstring& filename, const char* data, int size) {
232 return WriteFile(FilePath::FromWStringHack(filename), data, size);
233 }
234 } // namespace file_util
235