PageRenderTime 13ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/mordor/streams/temp.cpp

http://github.com/mozy/mordor
C++ | 130 lines | 120 code | 8 blank | 2 comment | 47 complexity | 0292430c44aace5ecbc2ca10916ea65a MD5 | raw file
Possible License(s): BSD-3-Clause
  1. // Copyright (c) 2009 - Mozy, Inc.
  2. #include "temp.h"
  3. #include "mordor/config.h"
  4. #include "mordor/string.h"
  5. #include "mordor/log.h"
  6. namespace Mordor {
  7. static ConfigVar<std::string>::ptr g_tempDir = Config::lookup(
  8. "mordor.tempdir",
  9. std::string(""),
  10. "Temporary directory (blank for system default)");
  11. static Logger::ptr g_log = Log::lookup("mordor:streams");
  12. #ifdef WINDOWS
  13. static bool EnsureFolderExist(const std::wstring & wtempdir)
  14. {
  15. size_t backslash = 1;
  16. error_t error;
  17. std::wstring currentFolder;
  18. while ((backslash = wtempdir.find_first_of(L'\\', backslash + 1)) != std::wstring::npos) {
  19. currentFolder = wtempdir.substr(0, backslash);
  20. CreateDirectoryW(currentFolder.c_str(), NULL);
  21. error = lastError();
  22. if (error != ERROR_ALREADY_EXISTS && error != ERROR_SUCCESS) {
  23. MORDOR_LOG_ERROR(g_log) << "Fail to create folder (" << wtempdir.c_str() << "), LastError:" << error;
  24. return false;
  25. }
  26. }
  27. CreateDirectoryW(&wtempdir[0], NULL);
  28. error = lastError();
  29. if (error == ERROR_ALREADY_EXISTS || error == ERROR_SUCCESS) {
  30. return true;
  31. } else {
  32. MORDOR_LOG_ERROR(g_log) << "Fail to create folder (" << wtempdir.c_str() << "), LastError:" << error;
  33. return false;
  34. }
  35. }
  36. #endif
  37. TempStream::TempStream(const std::string &prefix, bool deleteOnClose,
  38. IOManager *ioManager, Scheduler *scheduler)
  39. {
  40. std::string tempdir;
  41. bool absolutePath =
  42. #ifdef WINDOWS
  43. (prefix.size() >= 2 && (prefix[1] == ':' || prefix[1] == '\\')) ||
  44. (!prefix.empty() && prefix[0] == '\\');
  45. #else
  46. !prefix.empty() && prefix[0] == '/';
  47. #endif
  48. if (!absolutePath)
  49. tempdir = g_tempDir->val();
  50. #ifdef WINDOWS
  51. std::wstring wtempdir = toUtf16(tempdir);
  52. if (!absolutePath && wtempdir.empty()) {
  53. wtempdir.resize(MAX_PATH);
  54. DWORD len = GetTempPathW(MAX_PATH, &wtempdir[0]);
  55. if (len == 0)
  56. wtempdir = L".";
  57. else
  58. wtempdir.resize(len);
  59. }
  60. std::wstring prefixW = toUtf16(prefix);
  61. size_t backslash = prefixW.rfind(L'\\');
  62. if (backslash != std::wstring::npos) {
  63. wtempdir += prefixW.substr(0, backslash);
  64. prefixW = prefixW.substr(backslash + 1);
  65. }
  66. std::wstring tempfile;
  67. tempfile.resize(MAX_PATH);
  68. UINT ret = GetTempFileNameW(wtempdir.c_str(),
  69. prefixW.c_str(),
  70. 0,
  71. &tempfile[0]);
  72. error_t error;
  73. if (ret == 0) {
  74. //corner case, so call logic here only when GetTempFileNameW fails.
  75. error = lastError();
  76. if (GetFileAttributesW(wtempdir.c_str()) == INVALID_FILE_ATTRIBUTES && EnsureFolderExist(wtempdir)) {
  77. MORDOR_LOG_INFO(g_log) << "try one more time of GetTempFileNameW";
  78. ret = GetTempFileNameW(wtempdir.c_str(),
  79. prefixW.c_str(),
  80. 0,
  81. &tempfile[0]);
  82. error = lastError();
  83. }
  84. if (ret == 0) {
  85. MORDOR_LOG_ERROR(g_log) << "GetTempFileNameW(" << wtempdir.c_str() << "," << prefixW.c_str() << ") fails with LastError:" << error;
  86. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("GetTempFileNameW");
  87. }
  88. }
  89. tempfile.resize(wcslen(tempfile.c_str()));
  90. init(Mordor::toUtf8(tempfile), FileStream::READWRITE,
  91. (FileStream::CreateFlags)(FileStream::OPEN |
  92. (deleteOnClose ? FileStream::DELETE_ON_CLOSE : 0)),
  93. ioManager, scheduler);
  94. #else
  95. if (!absolutePath && tempdir.empty()) {
  96. const char* tmpdirenv = getenv("TMPDIR");
  97. if (tmpdirenv != NULL) {
  98. tempdir = tmpdirenv;
  99. }
  100. }
  101. if (!absolutePath && tempdir.empty())
  102. tempdir = "/tmp/" + prefix + "XXXXXX";
  103. else if (!absolutePath) {
  104. if (tempdir[tempdir.length()-1] != '/')
  105. tempdir += "/";
  106. tempdir += prefix + "XXXXXX";
  107. }
  108. else
  109. tempdir = prefix + "XXXXXX";
  110. int fd = mkstemp(&tempdir[0]);
  111. if (fd < 0)
  112. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("mkstemp");
  113. init(fd, ioManager, scheduler);
  114. if (deleteOnClose) {
  115. int rc = unlink(tempdir.c_str());
  116. if (rc != 0)
  117. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("unlink");
  118. }
  119. m_path = tempdir;
  120. #endif
  121. }
  122. }