diff --git a/3party/Alohalytics/src/file_manager.h b/3party/Alohalytics/src/file_manager.h index bfd19ff6c1..27d0242742 100644 --- a/3party/Alohalytics/src/file_manager.h +++ b/3party/Alohalytics/src/file_manager.h @@ -25,6 +25,7 @@ SOFTWARE. #ifndef FILE_MANAGER_H #define FILE_MANAGER_H +#include #include #include #include @@ -85,9 +86,32 @@ struct FileManager { fi.read(&buffer[0], static_cast(size)); return buffer; } + + // Returns true if we can write to the specified directory. + static bool IsDirectoryWritable(std::string directory) { + AppendDirectorySlash(directory); + std::string temporary_file = directory; + // For a pseudo-random file we turn directory path into a file name. + std::replace(temporary_file.begin(), temporary_file.end(), kDirectorySeparator, 'Z'); + // Make sure it does not exist first. + while (true) { + try { + (void)GetFileSize(directory + temporary_file); + temporary_file += 'Z'; + } catch (const std::exception &) { + break; } } - return std::string(); + const ScopedRemoveFile remover(directory + temporary_file); + bool is_writable = false; + try { + (void)FileManager::AppendStringToFile(temporary_file, remover.file); + if (FileManager::ReadFileAsString(remover.file) == temporary_file) { + is_writable = true; + } + } catch (const std::exception &) { + } + return is_writable; } // Executes lambda for each regular file in the directory and stops immediately if lambda returns false. diff --git a/3party/Alohalytics/tests/test_messages_queue.cc b/3party/Alohalytics/tests/test_messages_queue.cc index c7c1f5773c..1366a77f66 100644 --- a/3party/Alohalytics/tests/test_messages_queue.cc +++ b/3party/Alohalytics/tests/test_messages_queue.cc @@ -212,6 +212,21 @@ void Test_GetFileSize() { // It should also fail for directories. TEST_EXCEPTION(std::ios_base::failure, FileManager::GetFileSize(FileManager::GetDirectoryFromFilePath(file))); } + +void Test_IsDirectoryWritable() { + const std::string file = GenerateTemporaryFileName(); + const ScopedRemoveFile remover(file); + TEST_EQUAL(true, FileManager::IsDirectoryWritable(FileManager::GetDirectoryFromFilePath(file))); + TEST_EQUAL(false, FileManager::IsDirectoryWritable(file)); + + const std::string not_writable_system_directory = +#ifdef _MSC_VER + "C:\"; +#else + "/Users"; +#endif + // Suppose you do not run tests as root/Administrator. + TEST_EQUAL(false, FileManager::IsDirectoryWritable(not_writable_system_directory)); } // ******************* Message Queue tests ****************** @@ -490,6 +505,7 @@ int main(int, char * []) { Test_AppendStringToFile(); Test_ForEachFileInDir(); Test_GetFileSize(); + Test_IsDirectoryWritable(); Test_EndsWith(); Test_MessagesQueue_InMemory_Empty();