file_util.h revision 731df977c0511bca2206b5f333555b1205ff1f43
1// Copyright (c) 2010 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. 4 5// This file contains utility functions for dealing with the local 6// filesystem. 7 8#ifndef BASE_FILE_UTIL_H_ 9#define BASE_FILE_UTIL_H_ 10#pragma once 11 12#include "build/build_config.h" 13 14#if defined(OS_WIN) 15#include <windows.h> 16#if defined(UNIT_TEST) 17#include <aclapi.h> 18#endif 19#elif defined(OS_POSIX) 20#include <sys/stat.h> 21#endif 22 23#include <stdio.h> 24 25#include <stack> 26#include <string> 27#include <vector> 28 29#include "base/basictypes.h" 30#include "base/file_path.h" 31#include "base/platform_file.h" 32#include "base/scoped_ptr.h" 33#include "base/string16.h" 34 35#if defined(OS_POSIX) 36#include "base/eintr_wrapper.h" 37#include "base/file_descriptor_posix.h" 38#include "base/logging.h" 39#endif 40 41namespace base { 42class Time; 43} 44 45namespace file_util { 46 47//----------------------------------------------------------------------------- 48// Functions that operate purely on a path string w/o touching the filesystem: 49 50// Returns true if the given path ends with a path separator character. 51bool EndsWithSeparator(const FilePath& path); 52 53// Makes sure that |path| ends with a separator IFF path is a directory that 54// exists. Returns true if |path| is an existing directory, false otherwise. 55bool EnsureEndsWithSeparator(FilePath* path); 56 57// Convert provided relative path into an absolute path. Returns false on 58// error. On POSIX, this function fails if the path does not exist. 59bool AbsolutePath(FilePath* path); 60 61// Returns true if |parent| contains |child|. Both paths are converted to 62// absolute paths before doing the comparison. 63bool ContainsPath(const FilePath& parent, const FilePath& child); 64 65//----------------------------------------------------------------------------- 66// Functions that involve filesystem access or modification: 67 68// Returns the number of files matching the current path that were 69// created on or after the given |file_time|. Doesn't count ".." or ".". 70// 71// Note for POSIX environments: a file created before |file_time| 72// can be mis-detected as a newer file due to low precision of 73// timestmap of file creation time. If you need to avoid such 74// mis-detection perfectly, you should wait one second before 75// obtaining |file_time|. 76int CountFilesCreatedAfter(const FilePath& path, 77 const base::Time& file_time); 78 79// Returns the total number of bytes used by all the files under |root_path|. 80// If the path does not exist the function returns 0. 81// 82// This function is implemented using the FileEnumerator class so it is not 83// particularly speedy in any platform. 84int64 ComputeDirectorySize(const FilePath& root_path); 85 86// Returns the total number of bytes used by all files matching the provided 87// |pattern|, on this |directory| (without recursion). If the path does not 88// exist the function returns 0. 89// 90// This function is implemented using the FileEnumerator class so it is not 91// particularly speedy in any platform. 92int64 ComputeFilesSize(const FilePath& directory, 93 const FilePath::StringType& pattern); 94 95// Deletes the given path, whether it's a file or a directory. 96// If it's a directory, it's perfectly happy to delete all of the 97// directory's contents. Passing true to recursive deletes 98// subdirectories and their contents as well. 99// Returns true if successful, false otherwise. 100// 101// WARNING: USING THIS WITH recursive==true IS EQUIVALENT 102// TO "rm -rf", SO USE WITH CAUTION. 103bool Delete(const FilePath& path, bool recursive); 104 105#if defined(OS_WIN) 106// Schedules to delete the given path, whether it's a file or a directory, until 107// the operating system is restarted. 108// Note: 109// 1) The file/directory to be deleted should exist in a temp folder. 110// 2) The directory to be deleted must be empty. 111bool DeleteAfterReboot(const FilePath& path); 112#endif 113 114// Moves the given path, whether it's a file or a directory. 115// If a simple rename is not possible, such as in the case where the paths are 116// on different volumes, this will attempt to copy and delete. Returns 117// true for success. 118bool Move(const FilePath& from_path, const FilePath& to_path); 119 120// Renames file |from_path| to |to_path|. Both paths must be on the same 121// volume, or the function will fail. Destination file will be created 122// if it doesn't exist. Prefer this function over Move when dealing with 123// temporary files. On Windows it preserves attributes of the target file. 124// Returns true on success. 125bool ReplaceFile(const FilePath& from_path, const FilePath& to_path); 126 127// Copies a single file. Use CopyDirectory to copy directories. 128bool CopyFile(const FilePath& from_path, const FilePath& to_path); 129 130// Copies the given path, and optionally all subdirectories and their contents 131// as well. 132// If there are files existing under to_path, always overwrite. 133// Returns true if successful, false otherwise. 134// Don't use wildcards on the names, it may stop working without notice. 135// 136// If you only need to copy a file use CopyFile, it's faster. 137bool CopyDirectory(const FilePath& from_path, const FilePath& to_path, 138 bool recursive); 139 140// Returns true if the given path exists on the local filesystem, 141// false otherwise. 142bool PathExists(const FilePath& path); 143 144// Returns true if the given path is writable by the user, false otherwise. 145bool PathIsWritable(const FilePath& path); 146 147// Returns true if the given path exists and is a directory, false otherwise. 148bool DirectoryExists(const FilePath& path); 149 150#if defined(OS_WIN) 151// Gets the creation time of the given file (expressed in the local timezone), 152// and returns it via the creation_time parameter. Returns true if successful, 153// false otherwise. 154bool GetFileCreationLocalTime(const std::wstring& filename, 155 LPSYSTEMTIME creation_time); 156 157// Same as above, but takes a previously-opened file handle instead of a name. 158bool GetFileCreationLocalTimeFromHandle(HANDLE file_handle, 159 LPSYSTEMTIME creation_time); 160#endif // defined(OS_WIN) 161 162// Returns true if the contents of the two files given are equal, false 163// otherwise. If either file can't be read, returns false. 164bool ContentsEqual(const FilePath& filename1, 165 const FilePath& filename2); 166 167// Returns true if the contents of the two text files given are equal, false 168// otherwise. This routine treats "\r\n" and "\n" as equivalent. 169bool TextContentsEqual(const FilePath& filename1, const FilePath& filename2); 170 171// Read the file at |path| into |contents|, returning true on success. 172// |contents| may be NULL, in which case this function is useful for its 173// side effect of priming the disk cache. 174// Useful for unit tests. 175bool ReadFileToString(const FilePath& path, std::string* contents); 176 177#if defined(OS_POSIX) 178// Read exactly |bytes| bytes from file descriptor |fd|, storing the result 179// in |buffer|. This function is protected against EINTR and partial reads. 180// Returns true iff |bytes| bytes have been successfuly read from |fd|. 181bool ReadFromFD(int fd, char* buffer, size_t bytes); 182#endif // defined(OS_POSIX) 183 184#if defined(OS_WIN) 185// Resolve Windows shortcut (.LNK file) 186// This methods tries to resolve a shortcut .LNK file. If the |path| is valid 187// returns true and puts the target into the |path|, otherwise returns 188// false leaving the path as it is. 189bool ResolveShortcut(FilePath* path); 190 191// Create a Windows shortcut (.LNK file) 192// This method creates a shortcut link using the information given. Ensure 193// you have initialized COM before calling into this function. 'source' 194// and 'destination' parameters are required, everything else can be NULL. 195// 'source' is the existing file, 'destination' is the new link file to be 196// created; for best results pass the filename with the .lnk extension. 197// The 'icon' can specify a dll or exe in which case the icon index is the 198// resource id. 'app_id' is the app model id for the shortcut on Win7. 199// Note that if the shortcut exists it will overwrite it. 200bool CreateShortcutLink(const wchar_t *source, const wchar_t *destination, 201 const wchar_t *working_dir, const wchar_t *arguments, 202 const wchar_t *description, const wchar_t *icon, 203 int icon_index, const wchar_t* app_id); 204 205// Update a Windows shortcut (.LNK file). This method assumes the shortcut 206// link already exists (otherwise false is returned). Ensure you have 207// initialized COM before calling into this function. Only 'destination' 208// parameter is required, everything else can be NULL (but if everything else 209// is NULL no changes are made to the shortcut). 'destination' is the link 210// file to be updated. 'app_id' is the app model id for the shortcut on Win7. 211// For best results pass the filename with the .lnk extension. 212bool UpdateShortcutLink(const wchar_t *source, const wchar_t *destination, 213 const wchar_t *working_dir, const wchar_t *arguments, 214 const wchar_t *description, const wchar_t *icon, 215 int icon_index, const wchar_t* app_id); 216 217// Pins a shortcut to the Windows 7 taskbar. The shortcut file must already 218// exist and be a shortcut that points to an executable. 219bool TaskbarPinShortcutLink(const wchar_t* shortcut); 220 221// Unpins a shortcut from the Windows 7 taskbar. The shortcut must exist and 222// already be pinned to the taskbar. 223bool TaskbarUnpinShortcutLink(const wchar_t* shortcut); 224 225// Copy from_path to to_path recursively and then delete from_path recursively. 226// Returns true if all operations succeed. 227// This function simulates Move(), but unlike Move() it works across volumes. 228// This fuction is not transactional. 229bool CopyAndDeleteDirectory(const FilePath& from_path, 230 const FilePath& to_path); 231#endif // defined(OS_WIN) 232 233// Return true if the given directory is empty 234bool IsDirectoryEmpty(const FilePath& dir_path); 235 236// Get the temporary directory provided by the system. 237// WARNING: DON'T USE THIS. If you want to create a temporary file, use one of 238// the functions below. 239bool GetTempDir(FilePath* path); 240// Get a temporary directory for shared memory files. 241// Only useful on POSIX; redirects to GetTempDir() on Windows. 242bool GetShmemTempDir(FilePath* path); 243 244// Get the home directory. This is more complicated than just getenv("HOME") 245// as it knows to fall back on getpwent() etc. 246FilePath GetHomeDir(); 247 248// Creates a temporary file. The full path is placed in |path|, and the 249// function returns true if was successful in creating the file. The file will 250// be empty and all handles closed after this function returns. 251bool CreateTemporaryFile(FilePath* path); 252 253// Same as CreateTemporaryFile but the file is created in |dir|. 254bool CreateTemporaryFileInDir(const FilePath& dir, FilePath* temp_file); 255 256// Create and open a temporary file. File is opened for read/write. 257// The full path is placed in |path|. 258// Returns a handle to the opened file or NULL if an error occured. 259FILE* CreateAndOpenTemporaryFile(FilePath* path); 260// Like above but for shmem files. Only useful for POSIX. 261FILE* CreateAndOpenTemporaryShmemFile(FilePath* path); 262// Similar to CreateAndOpenTemporaryFile, but the file is created in |dir|. 263FILE* CreateAndOpenTemporaryFileInDir(const FilePath& dir, FilePath* path); 264 265// Create a new directory. If prefix is provided, the new directory name is in 266// the format of prefixyyyy. 267// NOTE: prefix is ignored in the POSIX implementation. 268// If success, return true and output the full path of the directory created. 269bool CreateNewTempDirectory(const FilePath::StringType& prefix, 270 FilePath* new_temp_path); 271 272// Create a directory within another directory. 273// Extra characters will be appended to |prefix| to ensure that the 274// new directory does not have the same name as an existing directory. 275bool CreateTemporaryDirInDir(const FilePath& base_dir, 276 const FilePath::StringType& prefix, 277 FilePath* new_dir); 278 279// Creates a directory, as well as creating any parent directories, if they 280// don't exist. Returns 'true' on successful creation, or if the directory 281// already exists. The directory is only readable by the current user. 282bool CreateDirectory(const FilePath& full_path); 283 284// Returns the file size. Returns true on success. 285bool GetFileSize(const FilePath& file_path, int64* file_size); 286 287// Returns true if the given path's base name is ".". 288bool IsDot(const FilePath& path); 289 290// Returns true if the given path's base name is "..". 291bool IsDotDot(const FilePath& path); 292 293// Sets |real_path| to |path| with symbolic links and junctions expanded. 294// On windows, make sure the path starts with a lettered drive. 295// |path| must reference a file. Function will fail if |path| points to 296// a directory or to a nonexistent path. On windows, this function will 297// fail if |path| is a junction or symlink that points to an empty file, 298// or if |real_path| would be longer than MAX_PATH characters. 299bool NormalizeFilePath(const FilePath& path, FilePath* real_path); 300 301#if defined(OS_WIN) 302// Given an existing file in |path|, it returns in |real_path| the path 303// in the native NT format, of the form "\Device\HarddiskVolumeXX\..". 304// Returns false it it fails. Empty files cannot be resolved with this 305// function. 306bool NormalizeToNativeFilePath(const FilePath& path, FilePath* nt_path); 307#endif 308 309// Returns information about the given file path. 310bool GetFileInfo(const FilePath& file_path, base::PlatformFileInfo* info); 311 312// Sets the time of the last access and the time of the last modification. 313bool TouchFile(const FilePath& path, 314 const base::Time& last_accessed, 315 const base::Time& last_modified); 316 317// Set the time of the last modification. Useful for unit tests. 318bool SetLastModifiedTime(const FilePath& path, 319 const base::Time& last_modified); 320 321#if defined(OS_POSIX) 322// Store inode number of |path| in |inode|. Return true on success. 323bool GetInode(const FilePath& path, ino_t* inode); 324#endif 325 326// Wrapper for fopen-like calls. Returns non-NULL FILE* on success. 327FILE* OpenFile(const FilePath& filename, const char* mode); 328 329// Closes file opened by OpenFile. Returns true on success. 330bool CloseFile(FILE* file); 331 332// Truncates an open file to end at the location of the current file pointer. 333// This is a cross-platform analog to Windows' SetEndOfFile() function. 334bool TruncateFile(FILE* file); 335 336// Reads the given number of bytes from the file into the buffer. Returns 337// the number of read bytes, or -1 on error. 338int ReadFile(const FilePath& filename, char* data, int size); 339 340// Writes the given buffer into the file, overwriting any data that was 341// previously there. Returns the number of bytes written, or -1 on error. 342int WriteFile(const FilePath& filename, const char* data, int size); 343#if defined(OS_POSIX) 344// Append the data to |fd|. Does not close |fd| when done. 345int WriteFileDescriptor(const int fd, const char* data, int size); 346#endif 347 348// Gets the current working directory for the process. 349bool GetCurrentDirectory(FilePath* path); 350 351// Sets the current working directory for the process. 352bool SetCurrentDirectory(const FilePath& path); 353 354// A class to handle auto-closing of FILE*'s. 355class ScopedFILEClose { 356 public: 357 inline void operator()(FILE* x) const { 358 if (x) { 359 fclose(x); 360 } 361 } 362}; 363 364typedef scoped_ptr_malloc<FILE, ScopedFILEClose> ScopedFILE; 365 366#if defined(OS_POSIX) 367// A class to handle auto-closing of FDs. 368class ScopedFDClose { 369 public: 370 inline void operator()(int* x) const { 371 if (x && *x >= 0) { 372 if (HANDLE_EINTR(close(*x)) < 0) 373 PLOG(ERROR) << "close"; 374 } 375 } 376}; 377 378typedef scoped_ptr_malloc<int, ScopedFDClose> ScopedFD; 379#endif // OS_POSIX 380 381// A class for enumerating the files in a provided path. The order of the 382// results is not guaranteed. 383// 384// DO NOT USE FROM THE MAIN THREAD of your application unless it is a test 385// program where latency does not matter. This class is blocking. 386class FileEnumerator { 387 public: 388#if defined(OS_WIN) 389 typedef WIN32_FIND_DATA FindInfo; 390#elif defined(OS_POSIX) 391 typedef struct { 392 struct stat stat; 393 std::string filename; 394 } FindInfo; 395#endif 396 397 enum FILE_TYPE { 398 FILES = 1 << 0, 399 DIRECTORIES = 1 << 1, 400 INCLUDE_DOT_DOT = 1 << 2, 401#if defined(OS_POSIX) 402 SHOW_SYM_LINKS = 1 << 4, 403#endif 404 }; 405 406 // |root_path| is the starting directory to search for. It may or may not end 407 // in a slash. 408 // 409 // If |recursive| is true, this will enumerate all matches in any 410 // subdirectories matched as well. It does a breadth-first search, so all 411 // files in one directory will be returned before any files in a 412 // subdirectory. 413 // 414 // |file_type| specifies whether the enumerator should match files, 415 // directories, or both. 416 // 417 // |pattern| is an optional pattern for which files to match. This 418 // works like shell globbing. For example, "*.txt" or "Foo???.doc". 419 // However, be careful in specifying patterns that aren't cross platform 420 // since the underlying code uses OS-specific matching routines. In general, 421 // Windows matching is less featureful than others, so test there first. 422 // If unspecified, this will match all files. 423 // NOTE: the pattern only matches the contents of root_path, not files in 424 // recursive subdirectories. 425 // TODO(erikkay): Fix the pattern matching to work at all levels. 426 FileEnumerator(const FilePath& root_path, 427 bool recursive, 428 FileEnumerator::FILE_TYPE file_type); 429 FileEnumerator(const FilePath& root_path, 430 bool recursive, 431 FileEnumerator::FILE_TYPE file_type, 432 const FilePath::StringType& pattern); 433 ~FileEnumerator(); 434 435 // Returns an empty string if there are no more results. 436 FilePath Next(); 437 438 // Write the file info into |info|. 439 void GetFindInfo(FindInfo* info); 440 441 // Looks inside a FindInfo and determines if it's a directory. 442 static bool IsDirectory(const FindInfo& info); 443 444 static FilePath GetFilename(const FindInfo& find_info); 445 446 private: 447 // Returns true if the given path should be skipped in enumeration. 448 bool ShouldSkip(const FilePath& path); 449 450 451#if defined(OS_WIN) 452 // True when find_data_ is valid. 453 bool has_find_data_; 454 WIN32_FIND_DATA find_data_; 455 HANDLE find_handle_; 456#elif defined(OS_POSIX) 457 typedef struct { 458 FilePath filename; 459 struct stat stat; 460 } DirectoryEntryInfo; 461 462 // Read the filenames in source into the vector of DirectoryEntryInfo's 463 static bool ReadDirectory(std::vector<DirectoryEntryInfo>* entries, 464 const FilePath& source, bool show_links); 465 466 // The files in the current directory 467 std::vector<DirectoryEntryInfo> directory_entries_; 468 469 // The next entry to use from the directory_entries_ vector 470 size_t current_directory_entry_; 471#endif 472 473 FilePath root_path_; 474 bool recursive_; 475 FILE_TYPE file_type_; 476 FilePath::StringType pattern_; // Empty when we want to find everything. 477 478 // A stack that keeps track of which subdirectories we still need to 479 // enumerate in the breadth-first search. 480 std::stack<FilePath> pending_paths_; 481 482 DISALLOW_COPY_AND_ASSIGN(FileEnumerator); 483}; 484 485class MemoryMappedFile { 486 public: 487 // The default constructor sets all members to invalid/null values. 488 MemoryMappedFile(); 489 ~MemoryMappedFile(); 490 491 // Opens an existing file and maps it into memory. Access is restricted to 492 // read only. If this object already points to a valid memory mapped file 493 // then this method will fail and return false. If it cannot open the file, 494 // the file does not exist, or the memory mapping fails, it will return false. 495 // Later we may want to allow the user to specify access. 496 bool Initialize(const FilePath& file_name); 497 // As above, but works with an already-opened file. MemoryMappedFile will take 498 // ownership of |file| and close it when done. 499 bool Initialize(base::PlatformFile file); 500 501 const uint8* data() const { return data_; } 502 size_t length() const { return length_; } 503 504 // Is file_ a valid file handle that points to an open, memory mapped file? 505 bool IsValid(); 506 507 private: 508 // Open the given file and pass it to MapFileToMemoryInternal(). 509 bool MapFileToMemory(const FilePath& file_name); 510 511 // Map the file to memory, set data_ to that memory address. Return true on 512 // success, false on any kind of failure. This is a helper for Initialize(). 513 bool MapFileToMemoryInternal(); 514 515 // Closes all open handles. Later we may want to make this public. 516 void CloseHandles(); 517 518 base::PlatformFile file_; 519#if defined(OS_WIN) 520 HANDLE file_mapping_; 521#endif 522 uint8* data_; 523 size_t length_; 524 525 DISALLOW_COPY_AND_ASSIGN(MemoryMappedFile); 526}; 527 528// Renames a file using the SHFileOperation API to ensure that the target file 529// gets the correct default security descriptor in the new path. 530bool RenameFileAndResetSecurityDescriptor( 531 const FilePath& source_file_path, 532 const FilePath& target_file_path); 533 534// Returns whether the file has been modified since a particular date. 535bool HasFileBeenModifiedSince(const FileEnumerator::FindInfo& find_info, 536 const base::Time& cutoff_time); 537 538#ifdef UNIT_TEST 539 540inline bool MakeFileUnreadable(const FilePath& path) { 541#if defined(OS_POSIX) 542 struct stat stat_buf; 543 if (stat(path.value().c_str(), &stat_buf) != 0) 544 return false; 545 stat_buf.st_mode &= ~(S_IRUSR | S_IRGRP | S_IROTH); 546 547 return chmod(path.value().c_str(), stat_buf.st_mode) == 0; 548 549#elif defined(OS_WIN) 550 PACL old_dacl; 551 PSECURITY_DESCRIPTOR security_descriptor; 552 if (GetNamedSecurityInfo(const_cast<wchar_t*>(path.value().c_str()), 553 SE_FILE_OBJECT, 554 DACL_SECURITY_INFORMATION, NULL, NULL, &old_dacl, 555 NULL, &security_descriptor) != ERROR_SUCCESS) 556 return false; 557 558 // Deny Read access for the current user. 559 EXPLICIT_ACCESS change; 560 change.grfAccessPermissions = GENERIC_READ; 561 change.grfAccessMode = DENY_ACCESS; 562 change.grfInheritance = 0; 563 change.Trustee.pMultipleTrustee = NULL; 564 change.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 565 change.Trustee.TrusteeForm = TRUSTEE_IS_NAME; 566 change.Trustee.TrusteeType = TRUSTEE_IS_USER; 567 change.Trustee.ptstrName = L"CURRENT_USER"; 568 569 PACL new_dacl; 570 if (SetEntriesInAcl(1, &change, old_dacl, &new_dacl) != ERROR_SUCCESS) { 571 LocalFree(security_descriptor); 572 return false; 573 } 574 575 DWORD rc = SetNamedSecurityInfo(const_cast<wchar_t*>(path.value().c_str()), 576 SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, 577 NULL, NULL, new_dacl, NULL); 578 LocalFree(security_descriptor); 579 LocalFree(new_dacl); 580 581 return rc == ERROR_SUCCESS; 582#else 583 NOTIMPLEMENTED(); 584 return false; 585#endif 586} 587 588#endif // UNIT_TEST 589 590#if defined(OS_WIN) 591 // Loads the file passed in as an image section and touches pages to avoid 592 // subsequent hard page faults during LoadLibrary. The size to be pre read 593 // is passed in. If it is 0 then the whole file is paged in. The step size 594 // which indicates the number of bytes to skip after every page touched is 595 // also passed in. 596bool PreReadImage(const wchar_t* file_path, size_t size_to_read, 597 size_t step_size); 598#endif // OS_WIN 599 600#if defined(OS_LINUX) 601// Broad categories of file systems as returned by statfs() on Linux. 602enum FileSystemType { 603 FILE_SYSTEM_UNKNOWN, // statfs failed. 604 FILE_SYSTEM_0, // statfs.f_type == 0 means unknown, may indicate AFS. 605 FILE_SYSTEM_ORDINARY, // on-disk filesystem like ext2 606 FILE_SYSTEM_NFS, 607 FILE_SYSTEM_SMB, 608 FILE_SYSTEM_CODA, 609 FILE_SYSTEM_MEMORY, // in-memory file system 610 FILE_SYSTEM_OTHER, // any other value. 611 FILE_SYSTEM_TYPE_COUNT 612}; 613 614// Attempts determine the FileSystemType for |path|. 615// Returns false if |path| doesn't exist. 616bool GetFileSystemType(const FilePath& path, FileSystemType* type); 617#endif 618 619} // namespace file_util 620 621// Deprecated functions have been moved to this separate header file, 622// which must be included last after all the above definitions. 623#include "base/file_util_deprecated.h" 624 625#endif // BASE_FILE_UTIL_H_ 626