| /* | |
| * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | |
| * | |
| * Use of this source code is governed by a BSD-style license | |
| * that can be found in the LICENSE file in the root of the source | |
| * tree. An additional intellectual property rights grant can be found | |
| * in the file PATENTS. All contributing project authors may | |
| * be found in the AUTHORS file in the root of the source tree. | |
| */ | |
| #include "rtc_base/system/file_wrapper.h" | |
| #include <cerrno> | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <cstdio> | |
| #include <optional> | |
| #include <string> | |
| #include <utility> | |
| #include "absl/strings/string_view.h" | |
| #include "rtc_base/checks.h" | |
| #include "rtc_base/numerics/safe_conversions.h" | |
| #ifdef _WIN32 | |
| #include <Windows.h> | |
| #else | |
| #endif | |
| namespace webrtc { | |
| namespace { | |
| FILE* FileOpen(absl::string_view file_name_utf8, bool read_only, int* error) { | |
| RTC_CHECK_EQ(file_name_utf8.find_first_of('\0'), absl::string_view::npos) | |
| << "Invalid filename, containing NUL character"; | |
| std::string file_name(file_name_utf8); | |
| #if defined(_WIN32) | |
| int len = MultiByteToWideChar(CP_UTF8, 0, file_name.c_str(), -1, nullptr, 0); | |
| std::wstring wstr(len, 0); | |
| MultiByteToWideChar(CP_UTF8, 0, file_name.c_str(), -1, &wstr[0], len); | |
| FILE* file = _wfopen(wstr.c_str(), read_only ? L"rb" : L"wb"); | |
| #else | |
| FILE* file = fopen(file_name.c_str(), read_only ? "rb" : "wb"); | |
| #endif | |
| if (!file && error) { | |
| *error = errno; | |
| } | |
| return file; | |
| } | |
| } // namespace | |
| // static | |
| FileWrapper FileWrapper::OpenReadOnly(absl::string_view file_name_utf8) { | |
| return FileWrapper(FileOpen(file_name_utf8, true, nullptr)); | |
| } | |
| // static | |
| FileWrapper FileWrapper::OpenWriteOnly(absl::string_view file_name_utf8, | |
| int* error /*=nullptr*/) { | |
| return FileWrapper(FileOpen(file_name_utf8, false, error)); | |
| } | |
| FileWrapper::FileWrapper(FileWrapper&& other) { | |
| operator=(std::move(other)); | |
| } | |
| FileWrapper& FileWrapper::operator=(FileWrapper&& other) { | |
| Close(); | |
| file_ = other.file_; | |
| other.file_ = nullptr; | |
| return *this; | |
| } | |
| bool FileWrapper::SeekRelative(int64_t offset) { | |
| RTC_DCHECK(file_); | |
| return fseek(file_, checked_cast<long>(offset), SEEK_CUR) == 0; | |
| } | |
| bool FileWrapper::SeekTo(int64_t position) { | |
| RTC_DCHECK(file_); | |
| return fseek(file_, checked_cast<long>(position), SEEK_SET) == 0; | |
| } | |
| std::optional<size_t> FileWrapper::FileSize() { | |
| if (file_ == nullptr) | |
| return std::nullopt; | |
| long original_position = ftell(file_); | |
| if (original_position < 0) | |
| return std::nullopt; | |
| int seek_error = fseek(file_, 0, SEEK_END); | |
| if (seek_error) | |
| return std::nullopt; | |
| long file_size = ftell(file_); | |
| seek_error = fseek(file_, original_position, SEEK_SET); | |
| if (seek_error) | |
| return std::nullopt; | |
| return checked_cast<size_t>(file_size); | |
| } | |
| bool FileWrapper::Flush() { | |
| RTC_DCHECK(file_); | |
| return fflush(file_) == 0; | |
| } | |
| size_t FileWrapper::Read(void* buf, size_t length) { | |
| RTC_DCHECK(file_); | |
| return fread(buf, 1, length, file_); | |
| } | |
| bool FileWrapper::ReadEof() const { | |
| RTC_DCHECK(file_); | |
| return feof(file_); | |
| } | |
| bool FileWrapper::Write(const void* buf, size_t length) { | |
| RTC_DCHECK(file_); | |
| return fwrite(buf, 1, length, file_) == length; | |
| } | |
| bool FileWrapper::Close() { | |
| if (file_ == nullptr) | |
| return true; | |
| bool success = fclose(file_) == 0; | |
| file_ = nullptr; | |
| return success; | |
| } | |
| FILE* FileWrapper::Release() { | |
| FILE* file = file_; | |
| file_ = nullptr; | |
| return file; | |
| } | |
| } // namespace webrtc |