file_util.h revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2012 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
11#include "build/build_config.h"
12
13#if defined(OS_WIN)
14#include <windows.h>
15#elif defined(OS_POSIX)
16#include <sys/stat.h>
17#include <unistd.h>
18#endif
19
20#include <stdio.h>
21
22#include <set>
23#include <stack>
24#include <string>
25#include <vector>
26
27#include "base/base_export.h"
28#include "base/basictypes.h"
29#include "base/files/file_path.h"
30#include "base/memory/scoped_ptr.h"
31#include "base/platform_file.h"
32#include "base/string16.h"
33
34#if defined(OS_POSIX)
35#include "base/file_descriptor_posix.h"
36#include "base/logging.h"
37#include "base/posix/eintr_wrapper.h"
38#endif
39
40namespace base {
41class Time;
42}
43
44namespace file_util {
45
46extern bool g_bug108724_debug;
47
48//-----------------------------------------------------------------------------
49// Functions that operate purely on a path string w/o touching the filesystem:
50
51// Returns true if the given path ends with a path separator character.
52BASE_EXPORT bool EndsWithSeparator(const base::FilePath& path);
53
54// Makes sure that |path| ends with a separator IFF path is a directory that
55// exists. Returns true if |path| is an existing directory, false otherwise.
56BASE_EXPORT bool EnsureEndsWithSeparator(base::FilePath* path);
57
58// Convert provided relative path into an absolute path.  Returns false on
59// error. On POSIX, this function fails if the path does not exist.
60BASE_EXPORT bool AbsolutePath(base::FilePath* path);
61
62// Returns true if |parent| contains |child|. Both paths are converted to
63// absolute paths before doing the comparison.
64BASE_EXPORT bool ContainsPath(const base::FilePath& parent,
65                              const base::FilePath& child);
66
67//-----------------------------------------------------------------------------
68// Functions that involve filesystem access or modification:
69
70// Returns the number of files matching the current path that were
71// created on or after the given |file_time|.  Doesn't count ".." or ".".
72//
73// Note for POSIX environments: a file created before |file_time|
74// can be mis-detected as a newer file due to low precision of
75// timestmap of file creation time. If you need to avoid such
76// mis-detection perfectly, you should wait one second before
77// obtaining |file_time|.
78BASE_EXPORT int CountFilesCreatedAfter(const base::FilePath& path,
79                                       const base::Time& file_time);
80
81// Returns the total number of bytes used by all the files under |root_path|.
82// If the path does not exist the function returns 0.
83//
84// This function is implemented using the FileEnumerator class so it is not
85// particularly speedy in any platform.
86BASE_EXPORT int64 ComputeDirectorySize(const base::FilePath& root_path);
87
88// Returns the total number of bytes used by all files matching the provided
89// |pattern|, on this |directory| (without recursion). If the path does not
90// exist the function returns 0.
91//
92// This function is implemented using the FileEnumerator class so it is not
93// particularly speedy in any platform.
94BASE_EXPORT int64 ComputeFilesSize(const base::FilePath& directory,
95                                   const base::FilePath::StringType& pattern);
96
97// Deletes the given path, whether it's a file or a directory.
98// If it's a directory, it's perfectly happy to delete all of the
99// directory's contents.  Passing true to recursive deletes
100// subdirectories and their contents as well.
101// Returns true if successful, false otherwise.
102//
103// In posix environment and if |path| is a symbolic link, this deletes only
104// the symlink. (even if the symlink points to a non-existent file)
105//
106// WARNING: USING THIS WITH recursive==true IS EQUIVALENT
107//          TO "rm -rf", SO USE WITH CAUTION.
108BASE_EXPORT bool Delete(const base::FilePath& path, bool recursive);
109
110#if defined(OS_WIN)
111// Schedules to delete the given path, whether it's a file or a directory, until
112// the operating system is restarted.
113// Note:
114// 1) The file/directory to be deleted should exist in a temp folder.
115// 2) The directory to be deleted must be empty.
116BASE_EXPORT bool DeleteAfterReboot(const base::FilePath& path);
117#endif
118
119// Moves the given path, whether it's a file or a directory.
120// If a simple rename is not possible, such as in the case where the paths are
121// on different volumes, this will attempt to copy and delete. Returns
122// true for success.
123// This function fails if either path contains traversal components ('..').
124BASE_EXPORT bool Move(const base::FilePath& from_path,
125                      const base::FilePath& to_path);
126
127// Same as Move but allows paths with traversal components.
128// Use only with extreme care.
129BASE_EXPORT bool MoveUnsafe(const base::FilePath& from_path,
130                            const base::FilePath& to_path);
131
132// Renames file |from_path| to |to_path|. Both paths must be on the same
133// volume, or the function will fail. Destination file will be created
134// if it doesn't exist. Prefer this function over Move when dealing with
135// temporary files. On Windows it preserves attributes of the target file.
136// Returns true on success.
137BASE_EXPORT bool ReplaceFile(const base::FilePath& from_path,
138                             const base::FilePath& to_path);
139
140// Copies a single file. Use CopyDirectory to copy directories.
141// This function fails if either path contains traversal components ('..').
142BASE_EXPORT bool CopyFile(const base::FilePath& from_path,
143                          const base::FilePath& to_path);
144
145// Same as CopyFile but allows paths with traversal components.
146// Use only with extreme care.
147BASE_EXPORT bool CopyFileUnsafe(const base::FilePath& from_path,
148                                const base::FilePath& to_path);
149
150// Copies the given path, and optionally all subdirectories and their contents
151// as well.
152// If there are files existing under to_path, always overwrite.
153// Returns true if successful, false otherwise.
154// Don't use wildcards on the names, it may stop working without notice.
155//
156// If you only need to copy a file use CopyFile, it's faster.
157BASE_EXPORT bool CopyDirectory(const base::FilePath& from_path,
158                               const base::FilePath& to_path,
159                               bool recursive);
160
161// Returns true if the given path exists on the local filesystem,
162// false otherwise.
163BASE_EXPORT bool PathExists(const base::FilePath& path);
164
165// Returns true if the given path is writable by the user, false otherwise.
166BASE_EXPORT bool PathIsWritable(const base::FilePath& path);
167
168// Returns true if the given path exists and is a directory, false otherwise.
169BASE_EXPORT bool DirectoryExists(const base::FilePath& path);
170
171// Returns true if the contents of the two files given are equal, false
172// otherwise.  If either file can't be read, returns false.
173BASE_EXPORT bool ContentsEqual(const base::FilePath& filename1,
174                               const base::FilePath& filename2);
175
176// Returns true if the contents of the two text files given are equal, false
177// otherwise.  This routine treats "\r\n" and "\n" as equivalent.
178BASE_EXPORT bool TextContentsEqual(const base::FilePath& filename1,
179                                   const base::FilePath& filename2);
180
181// Read the file at |path| into |contents|, returning true on success.
182// This function fails if the |path| contains path traversal components ('..').
183// |contents| may be NULL, in which case this function is useful for its
184// side effect of priming the disk cache.
185// Useful for unit tests.
186BASE_EXPORT bool ReadFileToString(const base::FilePath& path,
187                                  std::string* contents);
188
189#if defined(OS_POSIX)
190// Read exactly |bytes| bytes from file descriptor |fd|, storing the result
191// in |buffer|. This function is protected against EINTR and partial reads.
192// Returns true iff |bytes| bytes have been successfuly read from |fd|.
193BASE_EXPORT bool ReadFromFD(int fd, char* buffer, size_t bytes);
194
195// Creates a symbolic link at |symlink| pointing to |target|.  Returns
196// false on failure.
197BASE_EXPORT bool CreateSymbolicLink(const base::FilePath& target,
198                                    const base::FilePath& symlink);
199
200// Reads the given |symlink| and returns where it points to in |target|.
201// Returns false upon failure.
202BASE_EXPORT bool ReadSymbolicLink(const base::FilePath& symlink,
203                                  base::FilePath* target);
204
205// Bits ans masks of the file permission.
206enum FilePermissionBits {
207  FILE_PERMISSION_MASK              = S_IRWXU | S_IRWXG | S_IRWXO,
208  FILE_PERMISSION_USER_MASK         = S_IRWXU,
209  FILE_PERMISSION_GROUP_MASK        = S_IRWXG,
210  FILE_PERMISSION_OTHERS_MASK       = S_IRWXO,
211
212  FILE_PERMISSION_READ_BY_USER      = S_IRUSR,
213  FILE_PERMISSION_WRITE_BY_USER     = S_IWUSR,
214  FILE_PERMISSION_EXECUTE_BY_USER   = S_IXUSR,
215  FILE_PERMISSION_READ_BY_GROUP     = S_IRGRP,
216  FILE_PERMISSION_WRITE_BY_GROUP    = S_IWGRP,
217  FILE_PERMISSION_EXECUTE_BY_GROUP  = S_IXGRP,
218  FILE_PERMISSION_READ_BY_OTHERS    = S_IROTH,
219  FILE_PERMISSION_WRITE_BY_OTHERS   = S_IWOTH,
220  FILE_PERMISSION_EXECUTE_BY_OTHERS = S_IXOTH,
221};
222
223// Reads the permission of the given |path|, storing the file permission
224// bits in |mode|. If |path| is symbolic link, |mode| is the permission of
225// a file which the symlink points to.
226BASE_EXPORT bool GetPosixFilePermissions(const base::FilePath& path,
227                                         int* mode);
228// Sets the permission of the given |path|. If |path| is symbolic link, sets
229// the permission of a file which the symlink points to.
230BASE_EXPORT bool SetPosixFilePermissions(const base::FilePath& path,
231                                         int mode);
232#endif  // defined(OS_POSIX)
233
234#if defined(OS_WIN)
235// Copy from_path to to_path recursively and then delete from_path recursively.
236// Returns true if all operations succeed.
237// This function simulates Move(), but unlike Move() it works across volumes.
238// This fuction is not transactional.
239BASE_EXPORT bool CopyAndDeleteDirectory(const base::FilePath& from_path,
240                                        const base::FilePath& to_path);
241#endif  // defined(OS_WIN)
242
243// Return true if the given directory is empty
244BASE_EXPORT bool IsDirectoryEmpty(const base::FilePath& dir_path);
245
246// Get the temporary directory provided by the system.
247// WARNING: DON'T USE THIS. If you want to create a temporary file, use one of
248// the functions below.
249BASE_EXPORT bool GetTempDir(base::FilePath* path);
250// Get a temporary directory for shared memory files.
251// Only useful on POSIX; redirects to GetTempDir() on Windows.
252BASE_EXPORT bool GetShmemTempDir(base::FilePath* path, bool executable);
253
254// Get the home directory.  This is more complicated than just getenv("HOME")
255// as it knows to fall back on getpwent() etc.
256BASE_EXPORT base::FilePath GetHomeDir();
257
258// Creates a temporary file. The full path is placed in |path|, and the
259// function returns true if was successful in creating the file. The file will
260// be empty and all handles closed after this function returns.
261BASE_EXPORT bool CreateTemporaryFile(base::FilePath* path);
262
263// Same as CreateTemporaryFile but the file is created in |dir|.
264BASE_EXPORT bool CreateTemporaryFileInDir(const base::FilePath& dir,
265                                          base::FilePath* temp_file);
266
267// Create and open a temporary file.  File is opened for read/write.
268// The full path is placed in |path|.
269// Returns a handle to the opened file or NULL if an error occured.
270BASE_EXPORT FILE* CreateAndOpenTemporaryFile(base::FilePath* path);
271// Like above but for shmem files.  Only useful for POSIX.
272// The executable flag says the file needs to support using
273// mprotect with PROT_EXEC after mapping.
274BASE_EXPORT FILE* CreateAndOpenTemporaryShmemFile(base::FilePath* path,
275                                                  bool executable);
276// Similar to CreateAndOpenTemporaryFile, but the file is created in |dir|.
277BASE_EXPORT FILE* CreateAndOpenTemporaryFileInDir(const base::FilePath& dir,
278                                                  base::FilePath* path);
279
280// Create a new directory. If prefix is provided, the new directory name is in
281// the format of prefixyyyy.
282// NOTE: prefix is ignored in the POSIX implementation.
283// If success, return true and output the full path of the directory created.
284BASE_EXPORT bool CreateNewTempDirectory(
285    const base::FilePath::StringType& prefix,
286    base::FilePath* new_temp_path);
287
288// Create a directory within another directory.
289// Extra characters will be appended to |prefix| to ensure that the
290// new directory does not have the same name as an existing directory.
291BASE_EXPORT bool CreateTemporaryDirInDir(
292    const base::FilePath& base_dir,
293    const base::FilePath::StringType& prefix,
294    base::FilePath* new_dir);
295
296// Creates a directory, as well as creating any parent directories, if they
297// don't exist. Returns 'true' on successful creation, or if the directory
298// already exists.  The directory is only readable by the current user.
299BASE_EXPORT bool CreateDirectory(const base::FilePath& full_path);
300
301// Returns the file size. Returns true on success.
302BASE_EXPORT bool GetFileSize(const base::FilePath& file_path, int64* file_size);
303
304// Returns true if the given path's base name is ".".
305BASE_EXPORT bool IsDot(const base::FilePath& path);
306
307// Returns true if the given path's base name is "..".
308BASE_EXPORT bool IsDotDot(const base::FilePath& path);
309
310// Sets |real_path| to |path| with symbolic links and junctions expanded.
311// On windows, make sure the path starts with a lettered drive.
312// |path| must reference a file.  Function will fail if |path| points to
313// a directory or to a nonexistent path.  On windows, this function will
314// fail if |path| is a junction or symlink that points to an empty file,
315// or if |real_path| would be longer than MAX_PATH characters.
316BASE_EXPORT bool NormalizeFilePath(const base::FilePath& path,
317                                   base::FilePath* real_path);
318
319#if defined(OS_WIN)
320
321// Given a path in NT native form ("\Device\HarddiskVolumeXX\..."),
322// return in |drive_letter_path| the equivalent path that starts with
323// a drive letter ("C:\...").  Return false if no such path exists.
324BASE_EXPORT bool DevicePathToDriveLetterPath(const base::FilePath& device_path,
325                                             base::FilePath* drive_letter_path);
326
327// Given an existing file in |path|, set |real_path| to the path
328// in native NT format, of the form "\Device\HarddiskVolumeXX\..".
329// Returns false if the path can not be found. Empty files cannot
330// be resolved with this function.
331BASE_EXPORT bool NormalizeToNativeFilePath(const base::FilePath& path,
332                                           base::FilePath* nt_path);
333#endif
334
335// This function will return if the given file is a symlink or not.
336BASE_EXPORT bool IsLink(const base::FilePath& file_path);
337
338// Returns information about the given file path.
339BASE_EXPORT bool GetFileInfo(const base::FilePath& file_path,
340                             base::PlatformFileInfo* info);
341
342// Sets the time of the last access and the time of the last modification.
343BASE_EXPORT bool TouchFile(const base::FilePath& path,
344                           const base::Time& last_accessed,
345                           const base::Time& last_modified);
346
347// Set the time of the last modification. Useful for unit tests.
348BASE_EXPORT bool SetLastModifiedTime(const base::FilePath& path,
349                                     const base::Time& last_modified);
350
351#if defined(OS_POSIX)
352// Store inode number of |path| in |inode|. Return true on success.
353BASE_EXPORT bool GetInode(const base::FilePath& path, ino_t* inode);
354#endif
355
356// Wrapper for fopen-like calls. Returns non-NULL FILE* on success.
357BASE_EXPORT FILE* OpenFile(const base::FilePath& filename, const char* mode);
358
359// Closes file opened by OpenFile. Returns true on success.
360BASE_EXPORT bool CloseFile(FILE* file);
361
362// Truncates an open file to end at the location of the current file pointer.
363// This is a cross-platform analog to Windows' SetEndOfFile() function.
364BASE_EXPORT bool TruncateFile(FILE* file);
365
366// Reads the given number of bytes from the file into the buffer.  Returns
367// the number of read bytes, or -1 on error.
368BASE_EXPORT int ReadFile(const base::FilePath& filename, char* data, int size);
369
370// Writes the given buffer into the file, overwriting any data that was
371// previously there.  Returns the number of bytes written, or -1 on error.
372BASE_EXPORT int WriteFile(const base::FilePath& filename, const char* data,
373                          int size);
374#if defined(OS_POSIX)
375// Append the data to |fd|. Does not close |fd| when done.
376BASE_EXPORT int WriteFileDescriptor(const int fd, const char* data, int size);
377#endif
378// Append the given buffer into the file. Returns the number of bytes written,
379// or -1 on error.
380BASE_EXPORT int AppendToFile(const base::FilePath& filename,
381                             const char* data, int size);
382
383// Gets the current working directory for the process.
384BASE_EXPORT bool GetCurrentDirectory(base::FilePath* path);
385
386// Sets the current working directory for the process.
387BASE_EXPORT bool SetCurrentDirectory(const base::FilePath& path);
388
389// Attempts to find a number that can be appended to the |path| to make it
390// unique. If |path| does not exist, 0 is returned.  If it fails to find such
391// a number, -1 is returned. If |suffix| is not empty, also checks the
392// existence of it with the given suffix.
393BASE_EXPORT int GetUniquePathNumber(const base::FilePath& path,
394                                    const base::FilePath::StringType& suffix);
395
396#if defined(OS_POSIX)
397// Test that |path| can only be changed by a given user and members of
398// a given set of groups.
399// Specifically, test that all parts of |path| under (and including) |base|:
400// * Exist.
401// * Are owned by a specific user.
402// * Are not writable by all users.
403// * Are owned by a memeber of a given set of groups, or are not writable by
404//   their group.
405// * Are not symbolic links.
406// This is useful for checking that a config file is administrator-controlled.
407// |base| must contain |path|.
408BASE_EXPORT bool VerifyPathControlledByUser(const base::FilePath& base,
409                                            const base::FilePath& path,
410                                            uid_t owner_uid,
411                                            const std::set<gid_t>& group_gids);
412#endif  // defined(OS_POSIX)
413
414#if defined(OS_MACOSX) && !defined(OS_IOS)
415// Is |path| writable only by a user with administrator privileges?
416// This function uses Mac OS conventions.  The super user is assumed to have
417// uid 0, and the administrator group is assumed to be named "admin".
418// Testing that |path|, and every parent directory including the root of
419// the filesystem, are owned by the superuser, controlled by the group
420// "admin", are not writable by all users, and contain no symbolic links.
421// Will return false if |path| does not exist.
422BASE_EXPORT bool VerifyPathControlledByAdmin(const base::FilePath& path);
423#endif  // defined(OS_MACOSX) && !defined(OS_IOS)
424
425// Returns the maximum length of path component on the volume containing
426// the directory |path|, in the number of FilePath::CharType, or -1 on failure.
427BASE_EXPORT int GetMaximumPathComponentLength(const base::FilePath& path);
428
429// A class to handle auto-closing of FILE*'s.
430class ScopedFILEClose {
431 public:
432  inline void operator()(FILE* x) const {
433    if (x) {
434      fclose(x);
435    }
436  }
437};
438
439typedef scoped_ptr_malloc<FILE, ScopedFILEClose> ScopedFILE;
440
441#if defined(OS_POSIX)
442// A class to handle auto-closing of FDs.
443class ScopedFDClose {
444 public:
445  inline void operator()(int* x) const {
446    if (x && *x >= 0) {
447      if (HANDLE_EINTR(close(*x)) < 0)
448        DPLOG(ERROR) << "close";
449    }
450  }
451};
452
453typedef scoped_ptr_malloc<int, ScopedFDClose> ScopedFD;
454#endif  // OS_POSIX
455
456// A class for enumerating the files in a provided path. The order of the
457// results is not guaranteed.
458//
459// DO NOT USE FROM THE MAIN THREAD of your application unless it is a test
460// program where latency does not matter. This class is blocking.
461class BASE_EXPORT FileEnumerator {
462 public:
463#if defined(OS_WIN)
464  typedef WIN32_FIND_DATA FindInfo;
465#elif defined(OS_POSIX)
466  typedef struct {
467    struct stat stat;
468    std::string filename;
469  } FindInfo;
470#endif
471
472  enum FileType {
473    FILES                 = 1 << 0,
474    DIRECTORIES           = 1 << 1,
475    INCLUDE_DOT_DOT       = 1 << 2,
476#if defined(OS_POSIX)
477    SHOW_SYM_LINKS        = 1 << 4,
478#endif
479  };
480
481  // |root_path| is the starting directory to search for. It may or may not end
482  // in a slash.
483  //
484  // If |recursive| is true, this will enumerate all matches in any
485  // subdirectories matched as well. It does a breadth-first search, so all
486  // files in one directory will be returned before any files in a
487  // subdirectory.
488  //
489  // |file_type|, a bit mask of FileType, specifies whether the enumerator
490  // should match files, directories, or both.
491  //
492  // |pattern| is an optional pattern for which files to match. This
493  // works like shell globbing. For example, "*.txt" or "Foo???.doc".
494  // However, be careful in specifying patterns that aren't cross platform
495  // since the underlying code uses OS-specific matching routines.  In general,
496  // Windows matching is less featureful than others, so test there first.
497  // If unspecified, this will match all files.
498  // NOTE: the pattern only matches the contents of root_path, not files in
499  // recursive subdirectories.
500  // TODO(erikkay): Fix the pattern matching to work at all levels.
501  FileEnumerator(const base::FilePath& root_path,
502                 bool recursive,
503                 int file_type);
504  FileEnumerator(const base::FilePath& root_path,
505                 bool recursive,
506                 int file_type,
507                 const base::FilePath::StringType& pattern);
508  ~FileEnumerator();
509
510  // Returns an empty string if there are no more results.
511  base::FilePath Next();
512
513  // Write the file info into |info|.
514  void GetFindInfo(FindInfo* info);
515
516  // Looks inside a FindInfo and determines if it's a directory.
517  static bool IsDirectory(const FindInfo& info);
518
519  static base::FilePath GetFilename(const FindInfo& find_info);
520  static int64 GetFilesize(const FindInfo& find_info);
521  static base::Time GetLastModifiedTime(const FindInfo& find_info);
522
523 private:
524  // Returns true if the given path should be skipped in enumeration.
525  bool ShouldSkip(const base::FilePath& path);
526
527
528#if defined(OS_WIN)
529  // True when find_data_ is valid.
530  bool has_find_data_;
531  WIN32_FIND_DATA find_data_;
532  HANDLE find_handle_;
533#elif defined(OS_POSIX)
534  struct DirectoryEntryInfo {
535    base::FilePath filename;
536    struct stat stat;
537  };
538
539  // Read the filenames in source into the vector of DirectoryEntryInfo's
540  static bool ReadDirectory(std::vector<DirectoryEntryInfo>* entries,
541                            const base::FilePath& source, bool show_links);
542
543  // The files in the current directory
544  std::vector<DirectoryEntryInfo> directory_entries_;
545
546  // The next entry to use from the directory_entries_ vector
547  size_t current_directory_entry_;
548#endif
549
550  base::FilePath root_path_;
551  bool recursive_;
552  int file_type_;
553  base::FilePath::StringType pattern_;  // Empty when we want to find
554                                        // everything.
555
556  // A stack that keeps track of which subdirectories we still need to
557  // enumerate in the breadth-first search.
558  std::stack<base::FilePath> pending_paths_;
559
560  DISALLOW_COPY_AND_ASSIGN(FileEnumerator);
561};
562
563// Returns whether the file has been modified since a particular date.
564BASE_EXPORT bool HasFileBeenModifiedSince(
565    const FileEnumerator::FindInfo& find_info,
566    const base::Time& cutoff_time);
567
568#if defined(OS_LINUX)
569// Broad categories of file systems as returned by statfs() on Linux.
570enum FileSystemType {
571  FILE_SYSTEM_UNKNOWN,  // statfs failed.
572  FILE_SYSTEM_0,        // statfs.f_type == 0 means unknown, may indicate AFS.
573  FILE_SYSTEM_ORDINARY,       // on-disk filesystem like ext2
574  FILE_SYSTEM_NFS,
575  FILE_SYSTEM_SMB,
576  FILE_SYSTEM_CODA,
577  FILE_SYSTEM_MEMORY,         // in-memory file system
578  FILE_SYSTEM_CGROUP,         // cgroup control.
579  FILE_SYSTEM_OTHER,          // any other value.
580  FILE_SYSTEM_TYPE_COUNT
581};
582
583// Attempts determine the FileSystemType for |path|.
584// Returns false if |path| doesn't exist.
585BASE_EXPORT bool GetFileSystemType(const base::FilePath& path,
586                                   FileSystemType* type);
587#endif
588
589}  // namespace file_util
590
591#endif  // BASE_FILE_UTIL_H_
592