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