Esempio n. 1
0
osd_file::error osd_file::open(std::string const &orig_path, UINT32 openflags, ptr &file, std::uint64_t &filesize)
{
    std::string path;
    try {
        osd_subst_env(path, orig_path);
    }
    catch (...) {
        return error::OUT_OF_MEMORY;
    }

    if (win_check_socket_path(path))
        return win_open_socket(path, openflags, file, filesize);
    else if (win_check_ptty_path(path))
        return win_open_ptty(path, openflags, file, filesize);

    // convert path to TCHAR
    TCHAR *t_path = tstring_from_utf8(path.c_str());
    osd_disposer<TCHAR> t_path_disposer(t_path);
    if (!t_path)
        return error::OUT_OF_MEMORY;

    // convert the path into something Windows compatible
    for (TCHAR *src = t_path; *src != 0; src++)
        *src = /* ('/' == *src) ? '\\' : */ *src;

    // select the file open modes
    DWORD disposition, access, sharemode;
    if (openflags & OPEN_FLAG_WRITE)
    {
        disposition = (!is_path_to_physical_drive(path.c_str()) && (openflags & OPEN_FLAG_CREATE)) ? CREATE_ALWAYS : OPEN_EXISTING;
        access = (openflags & OPEN_FLAG_READ) ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_WRITE;
        sharemode = FILE_SHARE_READ;
    }
    else if (openflags & OPEN_FLAG_READ)
    {
        disposition = OPEN_EXISTING;
        access = GENERIC_READ;
        sharemode = FILE_SHARE_READ;
    }
    else
    {
        return error::INVALID_ACCESS;
    }

    // attempt to open the file
    HANDLE h = CreateFile(t_path, access, sharemode, nullptr, disposition, 0, nullptr);
    if (INVALID_HANDLE_VALUE == h)
    {
        DWORD err = GetLastError();
        // create the path if necessary
        if ((ERROR_PATH_NOT_FOUND == err) && (openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS))
        {
            TCHAR *pathsep = _tcsrchr(t_path, '\\');
            if (pathsep != nullptr)
            {
                // create the path up to the file
                *pathsep = 0;
                err = create_path_recursive(t_path);
                *pathsep = '\\';

                // attempt to reopen the file
                if (err == NO_ERROR)
                {
                    h = CreateFile(t_path, access, sharemode, nullptr, disposition, 0, nullptr);
                    err = GetLastError();
                }
            }
        }

        // if we still failed, clean up and free
        if (INVALID_HANDLE_VALUE == h)
            return win_error_to_file_error(err);
    }

    // get the file size
    DWORD upper, lower;
    lower = GetFileSize(h, &upper);
    if (INVALID_FILE_SIZE == lower)
    {
        DWORD const err = GetLastError();
        if (NO_ERROR != err)
        {
            CloseHandle(h);
            return win_error_to_file_error(err);
        }
    }

    try
    {
        file = std::make_unique<win_osd_file>(h);
        filesize = (std::uint64_t(upper) << 32) | lower;
        return error::NONE;
    }
    catch (...)
    {
        CloseHandle(h);
        return error::OUT_OF_MEMORY;
    }
}
Esempio n. 2
0
osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, ptr &file, std::uint64_t &filesize)
{
    std::string path;
    try {
        osd_subst_env(path, orig_path);
    }
    catch (...) {
        return error::OUT_OF_MEMORY;
    }

    if (win_check_socket_path(path))
        return win_open_socket(path, openflags, file, filesize);
    else if (win_check_ptty_path(path))
        return win_open_ptty(path, openflags, file, filesize);

    // convert path to TCHAR
    osd::text::tstring t_path = osd::text::to_tstring(path);

    // convert the path into something Windows compatible (the actual interesting part appears
    // to have been commented out???)
    for (auto iter = t_path.begin(); iter != t_path.end(); iter++)
        *iter = /* ('/' == *iter) ? '\\' : */ *iter;

    // select the file open modes
    DWORD disposition, access, sharemode;
    if (openflags & OPEN_FLAG_WRITE)
    {
        disposition = (!is_path_to_physical_drive(path.c_str()) && (openflags & OPEN_FLAG_CREATE)) ? CREATE_ALWAYS : OPEN_EXISTING;
        access = (openflags & OPEN_FLAG_READ) ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_WRITE;
        sharemode = FILE_SHARE_READ;
    }
    else if (openflags & OPEN_FLAG_READ)
    {
        disposition = OPEN_EXISTING;
        access = GENERIC_READ;
        sharemode = FILE_SHARE_READ;
    }
    else
    {
        return error::INVALID_ACCESS;
    }

    // attempt to open the file
    HANDLE h = CreateFile(t_path.c_str(), access, sharemode, nullptr, disposition, 0, nullptr);
    if (INVALID_HANDLE_VALUE == h)
    {
        DWORD err = GetLastError();
        // create the path if necessary
        if ((ERROR_PATH_NOT_FOUND == err) && (openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS))
        {
            auto pathsep = t_path.rfind('\\');
            if (pathsep != decltype(t_path)::npos)
            {
                // create the path up to the file
                t_path[pathsep] = 0;
                err = create_path_recursive(&t_path[0]);
                t_path[pathsep] = '\\';

                // attempt to reopen the file
                if (err == NO_ERROR)
                {
                    h = CreateFile(t_path.c_str(), access, sharemode, nullptr, disposition, 0, nullptr);
                    err = GetLastError();
                }
            }
        }

        // if we still failed, clean up and free
        if (INVALID_HANDLE_VALUE == h)
            return win_error_to_file_error(err);
    }

    // get the file size
    DWORD upper, lower;
    lower = GetFileSize(h, &upper);
    if (INVALID_FILE_SIZE == lower)
    {
        DWORD const err = GetLastError();
        if (NO_ERROR != err)
        {
            CloseHandle(h);
            return win_error_to_file_error(err);
        }
    }

    try
    {
        file = std::make_unique<win_osd_file>(h);
        filesize = (std::uint64_t(upper) << 32) | lower;
        return error::NONE;
    }
    catch (...)
    {
        CloseHandle(h);
        return error::OUT_OF_MEMORY;
    }
}