diff options
author | Adam Midvidy <amidvidy@gmail.com> | 2016-02-05 15:19:18 -0500 |
---|---|---|
committer | Adam Midvidy <amidvidy@gmail.com> | 2016-02-05 15:20:26 -0500 |
commit | 77191d85a8a42d28cd32ce37365defae23556069 (patch) | |
tree | 3a830c8e9644d76808aba3e5209902f65f254de0 | |
parent | 22c3c3d13f8d2557c4be9c2060bcd8026023ebf8 (diff) | |
download | mongo-77191d85a8a42d28cd32ce37365defae23556069.tar.gz |
SERVER-22352 lockFile changes for readOnly
modify StorageEngineLockFile::open() to return a different status if it
fails due to the dbpath having read-only permissions
3 files changed, 94 insertions, 0 deletions
diff --git a/src/mongo/db/storage/storage_engine_lock_file_posix.cpp b/src/mongo/db/storage/storage_engine_lock_file_posix.cpp index fd4d987f6c2..cb78d518e15 100644 --- a/src/mongo/db/storage/storage_engine_lock_file_posix.cpp +++ b/src/mongo/db/storage/storage_engine_lock_file_posix.cpp @@ -101,6 +101,12 @@ Status StorageEngineLockFile::open() { ::open(_filespec.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (lockFile < 0) { int errorcode = errno; + if (errorcode == EACCES) { + return Status(ErrorCodes::IllegalOperation, + str::stream() + << "Attempted to create a lock file on a read-only directory: " + << _dbpath << " - did you mean to start with --readOnly?"); + } return Status(ErrorCodes::DBPathInUse, str::stream() << "Unable to create/open lock file: " << _filespec << ' ' << errnoWithDescription(errorcode) diff --git a/src/mongo/db/storage/storage_engine_lock_file_test.cpp b/src/mongo/db/storage/storage_engine_lock_file_test.cpp index 9312b7f7c3a..cd3f1a1ef80 100644 --- a/src/mongo/db/storage/storage_engine_lock_file_test.cpp +++ b/src/mongo/db/storage/storage_engine_lock_file_test.cpp @@ -37,6 +37,10 @@ #include "mongo/unittest/temp_dir.h" #include "mongo/unittest/unittest.h" +#ifndef _WIN32 +#include <sys/stat.h> +#endif + namespace { using std::string; @@ -169,4 +173,82 @@ TEST(StorageEngineLockFileTest, ClearPidAndUnlock) { ASSERT_EQUALS(0U, boost::filesystem::file_size(lockFile.getFilespec())); } +class ScopedReadOnlyDirectory { +public: + ScopedReadOnlyDirectory(const std::string& path) : _path(std::move(path)) { + _applyToPathRecursive(_path, makePathReadOnly); + } + + ~ScopedReadOnlyDirectory() { + _applyToPathRecursive(_path, makePathWritable); + } + +private: + const std::string& _path; + + static void makePathReadOnly(const boost::filesystem::path& path) { +#ifdef _WIN32 + ::SetFileAttributes(path.c_str(), FILE_ATTRIBUTE_READONLY); +#else + ::chmod(path.c_str(), 0544); +#endif + } + + static void makePathWritable(const boost::filesystem::path& path) { +#ifdef _WIN32 + ::SetFileAttributes(path.c_str(), FILE_ATTRIBUTE_NORMAL); +#else + ::chmod(path.c_str(), 0777); +#endif + } + + template <typename Func> + static void _applyToPathRecursive(const boost::filesystem::path& path, Func func) { + func(path); + + using rdi = boost::filesystem::recursive_directory_iterator; + for (auto iter = rdi{path}; iter != rdi(); ++iter) { + func(*iter); + } + } +}; + +#ifndef _WIN32 + +// Windows has no concept of read only directories - only read only files. +TEST(StorageEngineLockFileTest, ReadOnlyDirectory) { + TempDir tempDir("StorageEngineLockFileTest_ReadOnlyDirectory"); + + // Make tempDir read-only. + ScopedReadOnlyDirectory srod(tempDir.path()); + + StorageEngineLockFile lockFile(tempDir.path()); + + auto openStatus = lockFile.open(); + + ASSERT_NOT_OK(openStatus); + ASSERT_EQ(openStatus, ErrorCodes::IllegalOperation); +} + +#endif + +TEST(StorageEngineLockFileTest, ReadOnlyDirectoryWithLockFile) { + TempDir tempDir("StorageEngineLockFileTest_ReadOnlyDirectoryWithLockFile"); + + StorageEngineLockFile lockFile(tempDir.path()); + ASSERT_OK(lockFile.open()); + ASSERT_OK(lockFile.writePid()); + + // Make tempDir read-only. + ScopedReadOnlyDirectory srod(tempDir.path()); + + // Try to create a new lock file. + StorageEngineLockFile lockFile2(tempDir.path()); + + auto openStatus = lockFile2.open(); + + ASSERT_NOT_OK(openStatus); + ASSERT_EQ(openStatus, ErrorCodes::IllegalOperation); +} + } // namespace diff --git a/src/mongo/db/storage/storage_engine_lock_file_windows.cpp b/src/mongo/db/storage/storage_engine_lock_file_windows.cpp index 6a3d69a3e2a..e38b2752bad 100644 --- a/src/mongo/db/storage/storage_engine_lock_file_windows.cpp +++ b/src/mongo/db/storage/storage_engine_lock_file_windows.cpp @@ -122,6 +122,12 @@ Status StorageEngineLockFile::open() { if (lockFileHandle == INVALID_HANDLE_VALUE) { int errorcode = GetLastError(); + if (errorcode == ERROR_ACCESS_DENIED) { + return Status(ErrorCodes::IllegalOperation, + str::stream() + << "Attempted to create a lock file on a read-only directory: " + << _dbpath << " - did you mean to start with --readOnly?"); + } return Status(ErrorCodes::DBPathInUse, str::stream() << "Unable to create/open lock file: " << _filespec << ' ' << errnoWithDescription(errorcode) |