license.bot | f003cfe | 2008-08-24 09:55:55 +0900 | [diff] [blame^] | 1 | // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 4 | |
| 5 | // This file contains utility functions for dealing with the local |
| 6 | // filesystem. |
| 7 | |
brettw@google.com | e3c034a | 2008-08-08 03:31:40 +0900 | [diff] [blame] | 8 | #ifndef BASE_FILE_UTIL_H_ |
| 9 | #define BASE_FILE_UTIL_H_ |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 10 | |
erikkay@google.com | 1d4507f | 2008-08-07 01:29:44 +0900 | [diff] [blame] | 11 | #include "build/build_config.h" |
| 12 | |
brettw@google.com | e3c034a | 2008-08-08 03:31:40 +0900 | [diff] [blame] | 13 | #if defined(OS_WIN) |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 14 | #include <windows.h> |
erikkay@google.com | dfb51b2 | 2008-08-16 02:32:10 +0900 | [diff] [blame] | 15 | #elif defined(OS_POSIX) |
| 16 | #include <fts.h> |
erikkay@google.com | 1d4507f | 2008-08-07 01:29:44 +0900 | [diff] [blame] | 17 | #endif |
brettw@google.com | e3c034a | 2008-08-08 03:31:40 +0900 | [diff] [blame] | 18 | |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 19 | #include <stack> |
| 20 | #include <string> |
erikkay@google.com | dfb51b2 | 2008-08-16 02:32:10 +0900 | [diff] [blame] | 21 | #include <vector> |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 22 | |
| 23 | #include "base/basictypes.h" |
| 24 | |
| 25 | namespace file_util { |
| 26 | |
| 27 | //----------------------------------------------------------------------------- |
| 28 | // Constants |
| 29 | |
| 30 | extern const wchar_t kPathSeparator; |
| 31 | |
| 32 | |
| 33 | //----------------------------------------------------------------------------- |
| 34 | // Functions that operate purely on a path string w/o touching the filesystem: |
| 35 | |
erikkay@google.com | dfb51b2 | 2008-08-16 02:32:10 +0900 | [diff] [blame] | 36 | // Returns a vector of all of the components of the provided path. |
| 37 | void PathComponents(const std::wstring& path, |
| 38 | std::vector<std::wstring>* components); |
| 39 | |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 40 | // Returns true if the given path ends with a path separator character. |
erikkay@google.com | dfb51b2 | 2008-08-16 02:32:10 +0900 | [diff] [blame] | 41 | // TODO(erikkay): remove this pointer version |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 42 | bool EndsWithSeparator(std::wstring* path); |
erikkay@google.com | dfb51b2 | 2008-08-16 02:32:10 +0900 | [diff] [blame] | 43 | bool EndsWithSeparator(const std::wstring& path); |
| 44 | |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 45 | // Modifies a string by trimming all trailing separators from the end. |
| 46 | void TrimTrailingSeparator(std::wstring* dir); |
| 47 | |
| 48 | // Strips the topmost directory from the end of 'dir'. Assumes 'dir' does not |
| 49 | // refer to a file. |
| 50 | // If 'dir' is a root directory, return without change. |
| 51 | void UpOneDirectory(std::wstring* dir); |
| 52 | |
| 53 | // Strips the topmost directory from the end of 'dir'. Assumes 'dir' does not |
| 54 | // refer to a file. |
| 55 | // If 'dir' is a root directory, the result becomes empty string. |
| 56 | void UpOneDirectoryOrEmpty(std::wstring* dir); |
| 57 | |
| 58 | // Strips the filename component from the end of 'path'. |
| 59 | void TrimFilename(std::wstring* path); |
| 60 | |
| 61 | // Returns the filename portion of 'path', without any leading \'s or /'s. |
| 62 | std::wstring GetFilenameFromPath(const std::wstring& path); |
| 63 | |
| 64 | // Returns "jpg" for path "C:\pics\jojo.jpg", or an empty string if |
| 65 | // the file has no extension. |
| 66 | std::wstring GetFileExtensionFromPath(const std::wstring& path); |
| 67 | |
| 68 | // Returns the directory component of a path, without the trailing |
| 69 | // path separator, or an empty string on error. The function does not |
| 70 | // check for the existence of the path, so if it is passed a directory |
| 71 | // without the trailing \, it will interpret the last component of the |
| 72 | // path as a file and chomp it. This does not support relative paths. |
| 73 | // Examples: |
| 74 | // path == "C:\pics\jojo.jpg", returns "C:\pics" |
| 75 | // path == "C:\Windows\system32\", returns "C:\Windows\system32" |
| 76 | // path == "C:\Windows\system32", returns "C:\Windows" |
| 77 | std::wstring GetDirectoryFromPath(const std::wstring& path); |
| 78 | |
| 79 | // Appends new_ending to path, adding a separator between the two if necessary. |
| 80 | void AppendToPath(std::wstring* path, const std::wstring& new_ending); |
| 81 | |
erikkay@google.com | a3ff275 | 2008-08-13 02:33:52 +0900 | [diff] [blame] | 82 | // Convert provided relative path into an absolute path. Returns false on |
| 83 | // error. |
| 84 | bool AbsolutePath(std::wstring* path); |
| 85 | |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 86 | // Inserts |suffix| after the file name portion of |path| but before the |
| 87 | // extension. |
| 88 | // Examples: |
| 89 | // path == "C:\pics\jojo.jpg" suffix == " (1)", returns "C:\pics\jojo (1).jpg" |
| 90 | // path == "jojo.jpg" suffix == " (1)", returns "jojo (1).jpg" |
| 91 | // path == "C:\pics\jojo" suffix == " (1)", returns "C:\pics\jojo (1)" |
| 92 | // path == "C:\pics.old\jojo" suffix == " (1)", returns "C:\pics.old\jojo (1)" |
| 93 | void InsertBeforeExtension(std::wstring* path, const std::wstring& suffix); |
| 94 | |
| 95 | // Replaces characters in 'file_name' that are illegal for file names with |
| 96 | // 'replace_char'. 'file_name' must not be a full or relative path, but just the |
| 97 | // file name component. Any leading or trailing whitespace in 'file_name' is |
| 98 | // removed. |
| 99 | // Example: |
| 100 | // file_name == "bad:file*name?.txt", changed to: "bad-file-name-.txt" when |
| 101 | // 'replace_char' is '-'. |
| 102 | void ReplaceIllegalCharacters(std::wstring* file_name, int replace_char); |
| 103 | |
| 104 | // Replaces the extension of |file_name| with |extension|. If |file_name| |
| 105 | // does not have an extension, them |extension| is added. If |extention| is |
| 106 | // empty, then the extension is removed from |file_name|. |
| 107 | void ReplaceExtension(std::wstring* file_name, const std::wstring& extension); |
| 108 | |
| 109 | //----------------------------------------------------------------------------- |
| 110 | // Functions that involve filesystem access or modification: |
| 111 | |
brettw@google.com | e3c034a | 2008-08-08 03:31:40 +0900 | [diff] [blame] | 112 | #if defined(OS_WIN) |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 113 | // Returns the number of files matching the current path that were |
| 114 | // created on or after the given FILETIME. Doesn't count ".." or ".". |
| 115 | // Filetime is UTC filetime, not LocalFiletime. |
| 116 | int CountFilesCreatedAfter(const std::wstring& path, |
| 117 | const FILETIME& file_time); |
brettw@google.com | e3c034a | 2008-08-08 03:31:40 +0900 | [diff] [blame] | 118 | #endif // defined(OS_WIN) |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 119 | |
| 120 | // Deletes the given path, whether it's a file or a directory. |
| 121 | // If it's a directory, it's perfectly happy to delete all of the |
| 122 | // directory's contents. Passing true to recursive deletes |
| 123 | // subdirectories and their contents as well. |
| 124 | // Returns true if successful, false otherwise. |
| 125 | // |
| 126 | // WARNING: USING THIS WITH recursive==true IS EQUIVALENT |
| 127 | // TO "rm -rf", SO USE WITH CAUTION. |
| 128 | bool Delete(const std::wstring& path, bool recursive); |
| 129 | |
| 130 | // Moves the given path, whether it's a file or a directory. |
| 131 | // Returns true if successful, false otherwise. |
| 132 | bool Move(const std::wstring& from_path, const std::wstring& to_path); |
| 133 | |
| 134 | // Copies a single file. Use CopyDirectory to copy directories. |
| 135 | bool CopyFile(const std::wstring& from_path, const std::wstring& to_path); |
| 136 | |
| 137 | // Copies the given path, and optionally all subdirectories and their contents |
| 138 | // as well. |
| 139 | // If there are files existing under to_path, always overwrite. |
| 140 | // Returns true if successful, false otherwise. |
| 141 | // Dont't use wildcards on the names, it may stop working without notice. |
| 142 | // |
| 143 | // If you only need to copy a file use CopyFile, it's faster. |
| 144 | bool CopyDirectory(const std::wstring& from_path, const std::wstring& to_path, |
| 145 | bool recursive); |
| 146 | |
| 147 | // Returns true if the given path exists on the local filesystem, |
| 148 | // false otherwise. |
| 149 | bool PathExists(const std::wstring& path); |
| 150 | |
| 151 | // Returns true if the given path is writable by the user, false otherwise. |
| 152 | bool PathIsWritable(const std::wstring& path); |
| 153 | |
brettw@google.com | e3c034a | 2008-08-08 03:31:40 +0900 | [diff] [blame] | 154 | #if defined(OS_WIN) |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 155 | // Gets the creation time of the given file (expressed in the local timezone), |
| 156 | // and returns it via the creation_time parameter. Returns true if successful, |
| 157 | // false otherwise. |
| 158 | bool GetFileCreationLocalTime(const std::wstring& filename, |
| 159 | LPSYSTEMTIME creation_time); |
| 160 | |
| 161 | // Same as above, but takes a previously-opened file handle instead of a name. |
| 162 | bool GetFileCreationLocalTimeFromHandle(HANDLE file_handle, |
| 163 | LPSYSTEMTIME creation_time); |
brettw@google.com | e3c034a | 2008-08-08 03:31:40 +0900 | [diff] [blame] | 164 | #endif // defined(OS_WIN) |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 165 | |
| 166 | // Returns true if the contents of the two files given are equal, false |
| 167 | // otherwise. If either file can't be read, returns false. |
| 168 | bool ContentsEqual(const std::wstring& filename1, |
| 169 | const std::wstring& filename2); |
| 170 | |
| 171 | // Read the file at |path| into |contents|, returning true on success. |
| 172 | // Useful for unit tests. |
| 173 | bool ReadFileToString(const std::wstring& path, std::string* contents); |
| 174 | |
erikkay@google.com | 014161d | 2008-08-16 02:45:13 +0900 | [diff] [blame] | 175 | #if defined(OS_WIN) |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 176 | // Resolve Windows shortcut (.LNK file) |
| 177 | // Argument path specifies a valid LNK file. On success, return true and put |
| 178 | // the URL into path. If path is a invalid .LNK file, return false. |
| 179 | bool ResolveShortcut(std::wstring* path); |
| 180 | |
| 181 | // Create a Windows shortcut (.LNK file) |
| 182 | // This method creates a shortcut link using the information given. Ensure |
| 183 | // you have initialized COM before calling into this function. 'source' |
| 184 | // and 'destination' parameters are required, everything else can be NULL. |
| 185 | // 'source' is the existing file, 'destination' is the new link file to be |
ericroman@google.com | dbff4f5 | 2008-08-19 01:00:38 +0900 | [diff] [blame] | 186 | // created; for best results pass the filename with the .lnk extension. |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 187 | // The 'icon' can specify a dll or exe in which case the icon index is the |
| 188 | // resource id. |
| 189 | // Note that if the shortcut exists it will overwrite it. |
| 190 | bool CreateShortcutLink(const wchar_t *source, const wchar_t *destination, |
| 191 | const wchar_t *working_dir, const wchar_t *arguments, |
| 192 | const wchar_t *description, const wchar_t *icon, |
| 193 | int icon_index); |
| 194 | |
| 195 | // Update a Windows shortcut (.LNK file). This method assumes the shortcut |
| 196 | // link already exists (otherwise false is returned). Ensure you have |
| 197 | // initialized COM before calling into this function. Only 'destination' |
ericroman@google.com | dbff4f5 | 2008-08-19 01:00:38 +0900 | [diff] [blame] | 198 | // parameter is required, everything else can be NULL (but if everything else |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 199 | // is NULL no changes are made to the shortcut). 'destination' is the link |
| 200 | // file to be updated. For best results pass the filename with the .lnk |
| 201 | // extension. |
| 202 | bool UpdateShortcutLink(const wchar_t *source, const wchar_t *destination, |
| 203 | const wchar_t *working_dir, const wchar_t *arguments, |
| 204 | const wchar_t *description, const wchar_t *icon, |
| 205 | int icon_index); |
erikkay@google.com | dfb51b2 | 2008-08-16 02:32:10 +0900 | [diff] [blame] | 206 | #endif |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 207 | |
erikkay@google.com | dfb51b2 | 2008-08-16 02:32:10 +0900 | [diff] [blame] | 208 | |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 209 | // Get the temporary directory provided by the system. |
| 210 | bool GetTempDir(std::wstring* path); |
| 211 | |
erikkay@google.com | dfb51b2 | 2008-08-16 02:32:10 +0900 | [diff] [blame] | 212 | // Creates a temporary file. The full path is placed in 'temp_file', and the |
| 213 | // function returns true if was successful in creating the file. The file will |
| 214 | // be empty and all handles closed after this function returns. |
| 215 | // TODO(erikkay): rename this function and track down all of the callers. |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 216 | bool CreateTemporaryFileName(std::wstring* temp_file); |
| 217 | |
| 218 | // Create a new directory under TempPath. If prefix is provided, the new |
| 219 | // directory name is in the format of prefixyyyy. |
| 220 | // If success, return true and output the full path of the directory created. |
| 221 | bool CreateNewTempDirectory(const std::wstring& prefix, |
| 222 | std::wstring* new_temp_path); |
| 223 | |
| 224 | // Creates a directory, as well as creating any parent directories, if they |
| 225 | // don't exist. Returns 'true' on successful creation. |
| 226 | bool CreateDirectory(const std::wstring& full_path); |
| 227 | |
| 228 | // Returns the file size. Returns true on success. |
| 229 | bool GetFileSize(const std::wstring& file_path, int64* file_size); |
| 230 | |
| 231 | // Reads the given number of bytes from the file into the buffer. Returns |
| 232 | // the number of read bytes, or -1 on error. |
| 233 | int ReadFile(const std::wstring& filename, char* data, int size); |
| 234 | |
| 235 | // Writes the given buffer into the file, overwriting any data that was |
| 236 | // previously there. Returns the number of bytes written, or -1 on error. |
| 237 | int WriteFile(const std::wstring& filename, const char* data, int size); |
| 238 | |
erikkay@google.com | 1d4507f | 2008-08-07 01:29:44 +0900 | [diff] [blame] | 239 | // Gets the current working directory for the process. |
| 240 | bool GetCurrentDirectory(std::wstring* path); |
| 241 | |
| 242 | // Sets the current working directory for the process. |
| 243 | bool SetCurrentDirectory(const std::wstring& current_directory); |
| 244 | |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 245 | // A class for enumerating the files in a provided path. The order of the |
| 246 | // results is not guaranteed. |
| 247 | // |
| 248 | // DO NOT USE FROM THE MAIN THREAD of your application unless it is a test |
| 249 | // program where latency does not matter. This class is blocking. |
| 250 | class FileEnumerator { |
| 251 | public: |
| 252 | enum FILE_TYPE { |
| 253 | FILES = 0x1, |
| 254 | DIRECTORIES = 0x2, |
| 255 | FILES_AND_DIRECTORIES = 0x3 |
| 256 | }; |
| 257 | |
| 258 | // |root_path| is the starting directory to search for. It may or may not end |
| 259 | // in a slash. |
| 260 | // |
| 261 | // If |recursive| is true, this will enumerate all matches in any |
| 262 | // subdirectories matched as well. It does a breadth-first search, so all |
| 263 | // files in one directory will be returned before any files in a |
| 264 | // subdirectory. |
| 265 | // |
erikkay@google.com | dfb51b2 | 2008-08-16 02:32:10 +0900 | [diff] [blame] | 266 | // |file_type| specifies whether the enumerator should match files, |
| 267 | // directories, or both. |
| 268 | // |
| 269 | // |pattern| is an optional pattern for which files to match. This |
| 270 | // works like shell globbing. For example, "*.txt" or "Foo???.doc". |
| 271 | // However, be careful in specifying patterns that aren't cross platform |
| 272 | // since the underlying code uses OS-specific matching routines. In general, |
| 273 | // Windows matching is less featureful than others, so test there first. |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 274 | // If unspecified, this will match all files. |
erikkay@google.com | dfb51b2 | 2008-08-16 02:32:10 +0900 | [diff] [blame] | 275 | // NOTE: the pattern only matches the contents of root_path, not files in |
| 276 | // recursive subdirectories. |
| 277 | // TODO(erikkay): Fix the pattern matching to work at all levels. |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 278 | FileEnumerator(const std::wstring& root_path, |
| 279 | bool recursive, |
| 280 | FileEnumerator::FILE_TYPE file_type); |
| 281 | FileEnumerator(const std::wstring& root_path, |
| 282 | bool recursive, |
| 283 | FileEnumerator::FILE_TYPE file_type, |
| 284 | const std::wstring& pattern); |
| 285 | ~FileEnumerator(); |
| 286 | |
| 287 | // Returns an empty string if there are no more results. |
| 288 | std::wstring Next(); |
| 289 | |
| 290 | private: |
| 291 | std::wstring root_path_; |
| 292 | bool recursive_; |
| 293 | FILE_TYPE file_type_; |
| 294 | std::wstring pattern_; // Empty when we want to find everything. |
| 295 | |
| 296 | // Set to true when there is a find operation open. This way, we can lazily |
| 297 | // start the operations when the caller calls Next(). |
| 298 | bool is_in_find_op_; |
| 299 | |
| 300 | // A stack that keeps track of which subdirectories we still need to |
| 301 | // enumerate in the breadth-first search. |
| 302 | std::stack<std::wstring> pending_paths_; |
| 303 | |
brettw@google.com | e3c034a | 2008-08-08 03:31:40 +0900 | [diff] [blame] | 304 | #if defined(OS_WIN) |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 305 | WIN32_FIND_DATA find_data_; |
| 306 | HANDLE find_handle_; |
erikkay@google.com | dfb51b2 | 2008-08-16 02:32:10 +0900 | [diff] [blame] | 307 | #elif defined(OS_POSIX) |
| 308 | FTS* fts_; |
| 309 | #endif |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 310 | |
| 311 | DISALLOW_EVIL_CONSTRUCTORS(FileEnumerator); |
| 312 | }; |
| 313 | |
| 314 | // Renames a file using the MoveFileEx API and ensures that the target file gets |
| 315 | // the correct security descriptor in the new path. |
| 316 | bool RenameFileAndResetSecurityDescriptor( |
| 317 | const std::wstring& source_file_path, |
| 318 | const std::wstring& target_file_path); |
| 319 | |
| 320 | } // namespace file_util |
| 321 | |
brettw@google.com | e3c034a | 2008-08-08 03:31:40 +0900 | [diff] [blame] | 322 | #endif // BASE_FILE_UTIL_H_ |
license.bot | f003cfe | 2008-08-24 09:55:55 +0900 | [diff] [blame^] | 323 | |