diff --git a/src/db.cpp b/src/db.cpp index 521562fe6..05cd657f1 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -72,7 +72,7 @@ bool CDBEnv::Open(const boost::filesystem::path& pathIn) path = pathIn; filesystem::path pathLogDir = path / "database"; - filesystem::create_directory(pathLogDir); + TryCreateDirectory(pathLogDir); filesystem::path pathErrorFile = path / "db.log"; LogPrintf("dbenv.open LogDir=%s ErrorFile=%s\n", pathLogDir.string(), pathErrorFile.string()); diff --git a/src/leveldbwrapper.cpp b/src/leveldbwrapper.cpp index 43c737a59..5b4a9c147 100644 --- a/src/leveldbwrapper.cpp +++ b/src/leveldbwrapper.cpp @@ -51,7 +51,7 @@ CLevelDBWrapper::CLevelDBWrapper(const boost::filesystem::path &path, size_t nCa LogPrintf("Wiping LevelDB in %s\n", path.string()); leveldb::DestroyDB(path.string(), options); } - boost::filesystem::create_directory(path); + TryCreateDirectory(path); LogPrintf("Opening LevelDB in %s\n", path.string()); } leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb); diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index f34260649..3e99e941a 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -178,7 +178,7 @@ void Intro::pickDataDirectory() } dataDir = intro.getDataDirectory(); try { - fs::create_directory(GUIUtil::qstringToBoostPath(dataDir)); + TryCreateDirectory(GUIUtil::qstringToBoostPath(dataDir)); break; } catch(fs::filesystem_error &e) { QMessageBox::critical(0, tr("Bitcoin"), diff --git a/src/util.cpp b/src/util.cpp index b90921ab8..a919b4b85 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -976,7 +976,7 @@ boost::filesystem::path GetDefaultDataDir() #ifdef MAC_OSX // Mac pathRet /= "Library/Application Support"; - fs::create_directory(pathRet); + TryCreateDirectory(pathRet); return pathRet / "Bitcoin"; #else // Unix @@ -1090,6 +1090,23 @@ bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest) #endif /* WIN32 */ } + +// Ignores exceptions thrown by boost's create_directory if the requested directory exists. +// Specifically handles case where path p exists, but it wasn't possible for the user to write to the parent directory. +bool TryCreateDirectory(const boost::filesystem::path& p) +{ + try + { + return boost::filesystem::create_directory(p); + } catch (boost::filesystem::filesystem_error) { + if (!boost::filesystem::exists(p) || !boost::filesystem::is_directory(p)) + throw; + } + + // create_directory didn't create the directory, it had to have existed already + return false; +} + void FileCommit(FILE *fileout) { fflush(fileout); // harmless if redundantly called diff --git a/src/util.h b/src/util.h index b0dabd2f6..fbd841f7a 100644 --- a/src/util.h +++ b/src/util.h @@ -189,6 +189,7 @@ bool TruncateFile(FILE *file, unsigned int length); int RaiseFileDescriptorLimit(int nMinFD); void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); +bool TryCreateDirectory(const boost::filesystem::path& p); boost::filesystem::path GetDefaultDataDir(); const boost::filesystem::path &GetDataDir(bool fNetSpecific = true); boost::filesystem::path GetConfigFile();