PageRenderTime 44ms CodeModel.GetById 34ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

/mordor/streams/file.cpp

http://github.com/mozy/mordor
C++ | 107 lines | 97 code | 9 blank | 1 comment | 23 complexity | b04c4361b503368574cc885766777213 MD5 | raw file
  1// Copyright (c) 2009 - Mozy, Inc.
  2
  3#include "file.h"
  4
  5#include "mordor/assert.h"
  6#include "mordor/string.h"
  7
  8namespace Mordor {
  9
 10static Logger::ptr g_log = Log::lookup("mordor:streams:file");
 11
 12FileStream::FileStream()
 13: m_supportsRead(false),
 14  m_supportsWrite(false),
 15  m_supportsSeek(false)
 16{}
 17
 18void
 19FileStream::init(const std::string &path, AccessFlags accessFlags,
 20    CreateFlags createFlags, IOManager *ioManager, Scheduler *scheduler)
 21{
 22    NativeHandle handle;
 23#ifdef WINDOWS
 24    DWORD access = 0;
 25    if (accessFlags & READ)
 26        access |= GENERIC_READ;
 27    if (accessFlags & WRITE)
 28        access |= GENERIC_WRITE;
 29    if (accessFlags == APPEND)
 30        access = FILE_APPEND_DATA | SYNCHRONIZE;
 31    DWORD flags = 0;
 32    if (createFlags & DELETE_ON_CLOSE) {
 33        flags |= FILE_FLAG_DELETE_ON_CLOSE;
 34        createFlags = (CreateFlags)(createFlags & ~DELETE_ON_CLOSE);
 35    }
 36    if (ioManager)
 37        flags |= FILE_FLAG_OVERLAPPED;
 38    MORDOR_ASSERT(createFlags >= CREATE_NEW && createFlags <= TRUNCATE_EXISTING);
 39    unsigned long  shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
 40    handle = ::CreateFileW(Mordor::toUtf16(path).c_str(), access, shareMode, NULL, createFlags, flags, NULL);
 41    error_t error = lastError();
 42    MORDOR_LOG_VERBOSE(g_log) << "CreateFileW(" << path << ", "
 43        << access << ", " << createFlags << ", " << flags << "): " << handle
 44        << " (" << error << ")";
 45    if (handle == INVALID_HANDLE_VALUE) {
 46        try {
 47            MORDOR_THROW_EXCEPTION_FROM_ERROR_API(error, "CreateFileW");
 48        } catch (boost::exception &ex) {
 49            ex << boost::errinfo_file_name(path);
 50            throw;
 51        }
 52    }
 53#else
 54    int oflags = (int)accessFlags;
 55    switch (createFlags & ~DELETE_ON_CLOSE) {
 56        case OPEN:
 57            break;
 58        case CREATE:
 59            oflags |= O_CREAT | O_EXCL;
 60            break;
 61        case OPEN_OR_CREATE:
 62            oflags |= O_CREAT;
 63            break;
 64        case OVERWRITE:
 65            oflags |= O_TRUNC;
 66            break;
 67        case OVERWRITE_OR_CREATE:
 68            oflags |= O_CREAT | O_TRUNC;
 69            break;
 70        default:
 71            MORDOR_NOTREACHED();
 72    }
 73    handle = open(path.c_str(), oflags, 0777);
 74    error_t error = lastError();
 75    MORDOR_LOG_VERBOSE(g_log) << "open(" << path << ", " << oflags << "): "
 76        << handle << " (" << error << ")";
 77    if (handle < 0) {
 78        try {
 79            MORDOR_THROW_EXCEPTION_FROM_ERROR_API(error, "open");
 80        } catch (boost::exception &ex) {
 81            ex << boost::errinfo_file_name(path);
 82            throw;
 83        }
 84    }
 85    if (createFlags & DELETE_ON_CLOSE) {
 86        int rc = unlink(path.c_str());
 87        if (rc != 0) {
 88            error_t error = lastError();
 89            ::close(handle);
 90            MORDOR_THROW_EXCEPTION_FROM_ERROR_API(error, "unlink");
 91        }
 92    }
 93#endif
 94
 95    NativeStream::init(handle, ioManager, scheduler);
 96    setSupportFlags(accessFlags);
 97    m_path = path;
 98}
 99
100void FileStream::setSupportFlags(AccessFlags accessFlags)
101{
102    m_supportsRead = accessFlags == READ || accessFlags == READWRITE;
103    m_supportsWrite = accessFlags == WRITE || accessFlags == READWRITE || accessFlags == APPEND;
104    m_supportsSeek = accessFlags != APPEND;
105}
106
107}