1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/system/file_wrapper.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <cerrno>
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
16*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/safe_conversions.h"
17*d9f75844SAndroid Build Coastguard Worker
18*d9f75844SAndroid Build Coastguard Worker #ifdef _WIN32
19*d9f75844SAndroid Build Coastguard Worker #include <Windows.h>
20*d9f75844SAndroid Build Coastguard Worker #else
21*d9f75844SAndroid Build Coastguard Worker #include <string.h>
22*d9f75844SAndroid Build Coastguard Worker #endif
23*d9f75844SAndroid Build Coastguard Worker
24*d9f75844SAndroid Build Coastguard Worker #include <utility>
25*d9f75844SAndroid Build Coastguard Worker
26*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
27*d9f75844SAndroid Build Coastguard Worker namespace {
FileOpen(absl::string_view file_name_utf8,bool read_only,int * error)28*d9f75844SAndroid Build Coastguard Worker FILE* FileOpen(absl::string_view file_name_utf8, bool read_only, int* error) {
29*d9f75844SAndroid Build Coastguard Worker RTC_CHECK_EQ(file_name_utf8.find_first_of('\0'), absl::string_view::npos)
30*d9f75844SAndroid Build Coastguard Worker << "Invalid filename, containing NUL character";
31*d9f75844SAndroid Build Coastguard Worker std::string file_name(file_name_utf8);
32*d9f75844SAndroid Build Coastguard Worker #if defined(_WIN32)
33*d9f75844SAndroid Build Coastguard Worker int len = MultiByteToWideChar(CP_UTF8, 0, file_name.c_str(), -1, nullptr, 0);
34*d9f75844SAndroid Build Coastguard Worker std::wstring wstr(len, 0);
35*d9f75844SAndroid Build Coastguard Worker MultiByteToWideChar(CP_UTF8, 0, file_name.c_str(), -1, &wstr[0], len);
36*d9f75844SAndroid Build Coastguard Worker FILE* file = _wfopen(wstr.c_str(), read_only ? L"rb" : L"wb");
37*d9f75844SAndroid Build Coastguard Worker #else
38*d9f75844SAndroid Build Coastguard Worker FILE* file = fopen(file_name.c_str(), read_only ? "rb" : "wb");
39*d9f75844SAndroid Build Coastguard Worker #endif
40*d9f75844SAndroid Build Coastguard Worker if (!file && error) {
41*d9f75844SAndroid Build Coastguard Worker *error = errno;
42*d9f75844SAndroid Build Coastguard Worker }
43*d9f75844SAndroid Build Coastguard Worker return file;
44*d9f75844SAndroid Build Coastguard Worker }
45*d9f75844SAndroid Build Coastguard Worker
46*d9f75844SAndroid Build Coastguard Worker } // namespace
47*d9f75844SAndroid Build Coastguard Worker
48*d9f75844SAndroid Build Coastguard Worker // static
OpenReadOnly(absl::string_view file_name_utf8)49*d9f75844SAndroid Build Coastguard Worker FileWrapper FileWrapper::OpenReadOnly(absl::string_view file_name_utf8) {
50*d9f75844SAndroid Build Coastguard Worker return FileWrapper(FileOpen(file_name_utf8, true, nullptr));
51*d9f75844SAndroid Build Coastguard Worker }
52*d9f75844SAndroid Build Coastguard Worker
53*d9f75844SAndroid Build Coastguard Worker // static
OpenWriteOnly(absl::string_view file_name_utf8,int * error)54*d9f75844SAndroid Build Coastguard Worker FileWrapper FileWrapper::OpenWriteOnly(absl::string_view file_name_utf8,
55*d9f75844SAndroid Build Coastguard Worker int* error /*=nullptr*/) {
56*d9f75844SAndroid Build Coastguard Worker return FileWrapper(FileOpen(file_name_utf8, false, error));
57*d9f75844SAndroid Build Coastguard Worker }
58*d9f75844SAndroid Build Coastguard Worker
FileWrapper(FileWrapper && other)59*d9f75844SAndroid Build Coastguard Worker FileWrapper::FileWrapper(FileWrapper&& other) {
60*d9f75844SAndroid Build Coastguard Worker operator=(std::move(other));
61*d9f75844SAndroid Build Coastguard Worker }
62*d9f75844SAndroid Build Coastguard Worker
operator =(FileWrapper && other)63*d9f75844SAndroid Build Coastguard Worker FileWrapper& FileWrapper::operator=(FileWrapper&& other) {
64*d9f75844SAndroid Build Coastguard Worker Close();
65*d9f75844SAndroid Build Coastguard Worker file_ = other.file_;
66*d9f75844SAndroid Build Coastguard Worker other.file_ = nullptr;
67*d9f75844SAndroid Build Coastguard Worker return *this;
68*d9f75844SAndroid Build Coastguard Worker }
69*d9f75844SAndroid Build Coastguard Worker
SeekRelative(int64_t offset)70*d9f75844SAndroid Build Coastguard Worker bool FileWrapper::SeekRelative(int64_t offset) {
71*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(file_);
72*d9f75844SAndroid Build Coastguard Worker return fseek(file_, rtc::checked_cast<long>(offset), SEEK_CUR) == 0;
73*d9f75844SAndroid Build Coastguard Worker }
74*d9f75844SAndroid Build Coastguard Worker
SeekTo(int64_t position)75*d9f75844SAndroid Build Coastguard Worker bool FileWrapper::SeekTo(int64_t position) {
76*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(file_);
77*d9f75844SAndroid Build Coastguard Worker return fseek(file_, rtc::checked_cast<long>(position), SEEK_SET) == 0;
78*d9f75844SAndroid Build Coastguard Worker }
79*d9f75844SAndroid Build Coastguard Worker
FileSize()80*d9f75844SAndroid Build Coastguard Worker long FileWrapper::FileSize() {
81*d9f75844SAndroid Build Coastguard Worker if (file_ == nullptr)
82*d9f75844SAndroid Build Coastguard Worker return -1;
83*d9f75844SAndroid Build Coastguard Worker long original_position = ftell(file_);
84*d9f75844SAndroid Build Coastguard Worker if (original_position < 0)
85*d9f75844SAndroid Build Coastguard Worker return -1;
86*d9f75844SAndroid Build Coastguard Worker int seek_error = fseek(file_, 0, SEEK_END);
87*d9f75844SAndroid Build Coastguard Worker if (seek_error)
88*d9f75844SAndroid Build Coastguard Worker return -1;
89*d9f75844SAndroid Build Coastguard Worker long file_size = ftell(file_);
90*d9f75844SAndroid Build Coastguard Worker seek_error = fseek(file_, original_position, SEEK_SET);
91*d9f75844SAndroid Build Coastguard Worker if (seek_error)
92*d9f75844SAndroid Build Coastguard Worker return -1;
93*d9f75844SAndroid Build Coastguard Worker return file_size;
94*d9f75844SAndroid Build Coastguard Worker }
95*d9f75844SAndroid Build Coastguard Worker
Flush()96*d9f75844SAndroid Build Coastguard Worker bool FileWrapper::Flush() {
97*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(file_);
98*d9f75844SAndroid Build Coastguard Worker return fflush(file_) == 0;
99*d9f75844SAndroid Build Coastguard Worker }
100*d9f75844SAndroid Build Coastguard Worker
Read(void * buf,size_t length)101*d9f75844SAndroid Build Coastguard Worker size_t FileWrapper::Read(void* buf, size_t length) {
102*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(file_);
103*d9f75844SAndroid Build Coastguard Worker return fread(buf, 1, length, file_);
104*d9f75844SAndroid Build Coastguard Worker }
105*d9f75844SAndroid Build Coastguard Worker
ReadEof() const106*d9f75844SAndroid Build Coastguard Worker bool FileWrapper::ReadEof() const {
107*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(file_);
108*d9f75844SAndroid Build Coastguard Worker return feof(file_);
109*d9f75844SAndroid Build Coastguard Worker }
110*d9f75844SAndroid Build Coastguard Worker
Write(const void * buf,size_t length)111*d9f75844SAndroid Build Coastguard Worker bool FileWrapper::Write(const void* buf, size_t length) {
112*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(file_);
113*d9f75844SAndroid Build Coastguard Worker return fwrite(buf, 1, length, file_) == length;
114*d9f75844SAndroid Build Coastguard Worker }
115*d9f75844SAndroid Build Coastguard Worker
Close()116*d9f75844SAndroid Build Coastguard Worker bool FileWrapper::Close() {
117*d9f75844SAndroid Build Coastguard Worker if (file_ == nullptr)
118*d9f75844SAndroid Build Coastguard Worker return true;
119*d9f75844SAndroid Build Coastguard Worker
120*d9f75844SAndroid Build Coastguard Worker bool success = fclose(file_) == 0;
121*d9f75844SAndroid Build Coastguard Worker file_ = nullptr;
122*d9f75844SAndroid Build Coastguard Worker return success;
123*d9f75844SAndroid Build Coastguard Worker }
124*d9f75844SAndroid Build Coastguard Worker
Release()125*d9f75844SAndroid Build Coastguard Worker FILE* FileWrapper::Release() {
126*d9f75844SAndroid Build Coastguard Worker FILE* file = file_;
127*d9f75844SAndroid Build Coastguard Worker file_ = nullptr;
128*d9f75844SAndroid Build Coastguard Worker return file;
129*d9f75844SAndroid Build Coastguard Worker }
130*d9f75844SAndroid Build Coastguard Worker
131*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
132