PageRenderTime 103ms CodeModel.GetById 60ms app.highlight 19ms RepoModel.GetById 21ms app.codeStats 1ms

/mordor/streams/temp.cpp

http://github.com/mozy/mordor
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}