azure-sdk-for-cpp/sdk/storage/azure-storage-common/src/file_io.cpp
JinmingHu 9c7d4c61e4
move stuff from _details to _internal for storage-common package (#1912)
closes https://github.com/Azure/azure-sdk-for-cpp/issues/1869


# Pull Request Checklist

Please leverage this checklist as a reminder to address commonly occurring feedback when submitting a pull request to make sure your PR can be reviewed quickly:

See the detailed list in the [contributing guide](https://github.com/Azure/azure-sdk-for-cpp/blob/master/CONTRIBUTING.md#pull-requests).

- [x] [C++ Guidelines](https://azure.github.io/azure-sdk/cpp_introduction.html)
- [x] Doxygen docs
- [x] Unit tests
- [x] No unwanted commits/changes
- [x] Descriptive title/description
  - [x] PR is single purpose
  - [x] Related issue listed
- [x] Comments in source
- [x] No typos
- [x] Update changelog
- [x] Not work-in-progress
- [x] External references or docs updated
- [x] Self review of PR done
- [x] Any breaking changes?
2021-03-16 06:55:13 +00:00

154 lines
4.2 KiB
C++

// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#include "azure/storage/common/file_io.hpp"
#include <azure/core/platform.hpp>
#if defined(AZ_PLATFORM_POSIX)
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#endif
#include <codecvt>
#include <limits>
#include <locale>
#include <stdexcept>
namespace Azure { namespace Storage { namespace _internal {
#if defined(AZ_PLATFORM_WINDOWS)
FileReader::FileReader(const std::string& filename)
{
#if !defined(WINAPI_PARTITION_DESKTOP) \
|| WINAPI_PARTITION_DESKTOP // See azure/core/platform.hpp for explanation.
m_handle = CreateFile(
filename.data(),
GENERIC_READ,
FILE_SHARE_READ,
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
#else
m_handle = CreateFile2(
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().from_bytes(filename).c_str(),
GENERIC_READ,
FILE_SHARE_READ,
OPEN_EXISTING,
NULL);
#endif
if (m_handle == INVALID_HANDLE_VALUE)
{
throw std::runtime_error("failed to open file");
}
LARGE_INTEGER fileSize;
BOOL ret = GetFileSizeEx(m_handle, &fileSize);
if (!ret)
{
CloseHandle(m_handle);
throw std::runtime_error("failed to get size of file");
}
m_fileSize = fileSize.QuadPart;
}
FileReader::~FileReader() { CloseHandle(m_handle); }
FileWriter::FileWriter(const std::string& filename)
{
#if !defined(WINAPI_PARTITION_DESKTOP) \
|| WINAPI_PARTITION_DESKTOP // See azure/core/platform.hpp for explanation.
m_handle = CreateFile(
filename.data(),
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
#else
m_handle = CreateFile2(
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().from_bytes(filename).c_str(),
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
CREATE_ALWAYS,
NULL);
#endif
if (m_handle == INVALID_HANDLE_VALUE)
{
throw std::runtime_error("failed to open file");
}
}
FileWriter::~FileWriter() { CloseHandle(m_handle); }
void FileWriter::Write(const uint8_t* buffer, int64_t length, int64_t offset)
{
if (length > std::numeric_limits<DWORD>::max())
{
throw std::runtime_error("failed to write file");
}
OVERLAPPED overlapped;
std::memset(&overlapped, 0, sizeof(overlapped));
overlapped.Offset = static_cast<DWORD>(static_cast<uint64_t>(offset));
overlapped.OffsetHigh = static_cast<DWORD>(static_cast<uint64_t>(offset) >> 32);
DWORD bytesWritten;
BOOL ret = WriteFile(m_handle, buffer, static_cast<DWORD>(length), &bytesWritten, &overlapped);
if (!ret)
{
throw std::runtime_error("failed to write file");
}
}
#elif defined(AZ_PLATFORM_POSIX)
FileReader::FileReader(const std::string& filename)
{
m_handle = open(filename.data(), O_RDONLY);
if (m_handle == -1)
{
throw std::runtime_error("failed to open file");
}
m_fileSize = lseek(m_handle, 0, SEEK_END);
if (m_fileSize == -1)
{
close(m_handle);
throw std::runtime_error("failed to get size of file");
}
}
FileReader::~FileReader() { close(m_handle); }
FileWriter::FileWriter(const std::string& filename)
{
m_handle = open(
filename.data(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (m_handle == -1)
{
throw std::runtime_error("failed to open file");
}
}
FileWriter::~FileWriter() { close(m_handle); }
void FileWriter::Write(const uint8_t* buffer, int64_t length, int64_t offset)
{
if (static_cast<uint64_t>(length) > std::numeric_limits<size_t>::max()
|| offset > static_cast<int64_t>(std::numeric_limits<off_t>::max()))
{
throw std::runtime_error("failed to write file");
}
ssize_t bytesWritten
= pwrite(m_handle, buffer, static_cast<size_t>(length), static_cast<off_t>(offset));
if (bytesWritten != length)
{
throw std::runtime_error("failed to write file");
}
}
#endif
}}} // namespace Azure::Storage::_internal