summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/file_util.cc4
-rw-r--r--base/file_util.h6
-rw-r--r--base/file_util_posix.cc9
-rw-r--r--base/file_util_win.cc7
-rw-r--r--third_party/leveldatabase/env_chromium.cc12
-rw-r--r--tools/metrics/histograms/histograms.xml1
6 files changed, 31 insertions, 8 deletions
diff --git a/base/file_util.cc b/base/file_util.cc
index 1479836..0d53162 100644
--- a/base/file_util.cc
+++ b/base/file_util.cc
@@ -185,6 +185,10 @@ FILE* CreateAndOpenTemporaryFile(FilePath* path) {
return CreateAndOpenTemporaryFileInDir(directory, path);
}
+bool CreateDirectory(const base::FilePath& full_path) {
+ return CreateDirectoryAndGetError(full_path, NULL);
+}
+
bool GetFileSize(const FilePath& file_path, int64* file_size) {
base::PlatformFileInfo info;
if (!GetFileInfo(file_path, &info))
diff --git a/base/file_util.h b/base/file_util.h
index 13190dc..b75a18d 100644
--- a/base/file_util.h
+++ b/base/file_util.h
@@ -269,6 +269,12 @@ BASE_EXPORT bool CreateTemporaryDirInDir(
// Creates a directory, as well as creating any parent directories, if they
// don't exist. Returns 'true' on successful creation, or if the directory
// already exists. The directory is only readable by the current user.
+// Returns true on success, leaving *error unchanged.
+// Returns false on failure and sets *error appropriately, if it is non-NULL.
+BASE_EXPORT bool CreateDirectoryAndGetError(const base::FilePath& full_path,
+ base::PlatformFileError* error);
+
+// Backward-compatible convenience method for the above.
BASE_EXPORT bool CreateDirectory(const base::FilePath& full_path);
// Returns the file size. Returns true on success.
diff --git a/base/file_util_posix.cc b/base/file_util_posix.cc
index 8723333..5d037bf 100644
--- a/base/file_util_posix.cc
+++ b/base/file_util_posix.cc
@@ -518,7 +518,8 @@ bool CreateNewTempDirectory(const FilePath::StringType& prefix,
return CreateTemporaryDirInDirImpl(tmpdir, TempFileName(), new_temp_path);
}
-bool CreateDirectory(const FilePath& full_path) {
+bool CreateDirectoryAndGetError(const FilePath& full_path,
+ base::PlatformFileError* error) {
base::ThreadRestrictions::AssertIOAllowed(); // For call to mkdir().
std::vector<FilePath> subpaths;
@@ -542,8 +543,12 @@ bool CreateDirectory(const FilePath& full_path) {
// due to the the directory appearing out of thin air. This can occur if
// two processes are trying to create the same file system tree at the same
// time. Check to see if it exists and make sure it is a directory.
- if (!DirectoryExists(*i))
+ int saved_errno = errno;
+ if (!DirectoryExists(*i)) {
+ if (error)
+ *error = base::ErrnoToPlatformFileError(saved_errno);
return false;
+ }
}
return true;
}
diff --git a/base/file_util_win.cc b/base/file_util_win.cc
index 0566247..43af529 100644
--- a/base/file_util_win.cc
+++ b/base/file_util_win.cc
@@ -403,7 +403,8 @@ bool CreateNewTempDirectory(const FilePath::StringType& prefix,
return CreateTemporaryDirInDir(system_temp_dir, prefix, new_temp_path);
}
-bool CreateDirectory(const FilePath& full_path) {
+bool CreateDirectoryAndGetError(const FilePath& full_path,
+ base::PlatformFileError* error) {
base::ThreadRestrictions::AssertIOAllowed();
// If the path exists, we've succeeded if it's a directory, failed otherwise.
@@ -429,7 +430,7 @@ bool CreateDirectory(const FilePath& full_path) {
if (parent_path.value() == full_path.value()) {
return false;
}
- if (!CreateDirectory(parent_path)) {
+ if (!CreateDirectoryAndGetError(parent_path, error)) {
DLOG(WARNING) << "Failed to create one of the parent directories.";
return false;
}
@@ -443,6 +444,8 @@ bool CreateDirectory(const FilePath& full_path) {
// race to create the same directory.
return true;
} else {
+ if (error)
+ *error = base::LastErrorToPlatformFileError(error_code);
DLOG(WARNING) << "Failed to create directory " << full_path_str
<< ", last error is " << error_code << ".";
return false;
diff --git a/third_party/leveldatabase/env_chromium.cc b/third_party/leveldatabase/env_chromium.cc
index 1d2a74e..71a5c88 100644
--- a/third_party/leveldatabase/env_chromium.cc
+++ b/third_party/leveldatabase/env_chromium.cc
@@ -616,10 +616,14 @@ Status ChromiumEnv::DeleteFile(const std::string& fname) {
Status ChromiumEnv::CreateDir(const std::string& name) {
Status result;
- if (!::file_util::CreateDirectory(CreateFilePath(name))) {
- result = MakeIOError(name, "Could not create directory.", kCreateDir);
- RecordErrorAt(kCreateDir);
- }
+ base::PlatformFileError error = base::PLATFORM_FILE_OK;
+ Retrier retrier(kCreateDir, this);
+ do {
+ if (::file_util::CreateDirectoryAndGetError(CreateFilePath(name), &error))
+ return result;
+ } while (retrier.ShouldKeepTrying(error));
+ result = MakeIOError(name, "Could not create directory.", kCreateDir);
+ RecordErrorAt(kCreateDir);
return result;
}
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index ea83436..8d29061 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -17089,6 +17089,7 @@ other types of suffix sets.
<fieldtrial name="LevelDBEnvRetry" separator="">
<group name="RenameFile" label="RenameFile"/>
<group name="LockFile" label="LockFile"/>
+ <group name="CreateDir" label="CreateDir"/>
<affected-histogram name="LevelDBEnv.IDB.RetryRecoveredFromErrorIn"/>
<affected-histogram name="LevelDBEnv.IDB.TimeUntilSuccessFor"/>
<affected-histogram name="LevelDBEnv.RetryRecoveredFromErrorIn"/>