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