summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Midvidy <amidvidy@gmail.com>2016-02-05 15:19:18 -0500
committerAdam Midvidy <amidvidy@gmail.com>2016-02-05 15:20:26 -0500
commit77191d85a8a42d28cd32ce37365defae23556069 (patch)
tree3a830c8e9644d76808aba3e5209902f65f254de0
parent22c3c3d13f8d2557c4be9c2060bcd8026023ebf8 (diff)
downloadmongo-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
-rw-r--r--src/mongo/db/storage/storage_engine_lock_file_posix.cpp6
-rw-r--r--src/mongo/db/storage/storage_engine_lock_file_test.cpp82
-rw-r--r--src/mongo/db/storage/storage_engine_lock_file_windows.cpp6
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)