1*da0073e9SAndroid Build Coastguard Worker #include "caffe2/serialize/file_adapter.h"
2*da0073e9SAndroid Build Coastguard Worker #include <c10/util/Exception.h>
3*da0073e9SAndroid Build Coastguard Worker #include <cerrno>
4*da0073e9SAndroid Build Coastguard Worker #include <cstdio>
5*da0073e9SAndroid Build Coastguard Worker #include <string>
6*da0073e9SAndroid Build Coastguard Worker #include "caffe2/core/common.h"
7*da0073e9SAndroid Build Coastguard Worker
8*da0073e9SAndroid Build Coastguard Worker namespace caffe2 {
9*da0073e9SAndroid Build Coastguard Worker namespace serialize {
10*da0073e9SAndroid Build Coastguard Worker
RAIIFile(const std::string & file_name)11*da0073e9SAndroid Build Coastguard Worker FileAdapter::RAIIFile::RAIIFile(const std::string& file_name) {
12*da0073e9SAndroid Build Coastguard Worker fp_ = fopen(file_name.c_str(), "rb");
13*da0073e9SAndroid Build Coastguard Worker if (fp_ == nullptr) {
14*da0073e9SAndroid Build Coastguard Worker auto old_errno = errno;
15*da0073e9SAndroid Build Coastguard Worker #if defined(_WIN32) && (defined(__MINGW32__) || defined(_MSC_VER))
16*da0073e9SAndroid Build Coastguard Worker char buf[1024];
17*da0073e9SAndroid Build Coastguard Worker buf[0] = '\0';
18*da0073e9SAndroid Build Coastguard Worker char* error_msg = buf;
19*da0073e9SAndroid Build Coastguard Worker strerror_s(buf, sizeof(buf), old_errno);
20*da0073e9SAndroid Build Coastguard Worker #else
21*da0073e9SAndroid Build Coastguard Worker auto error_msg =
22*da0073e9SAndroid Build Coastguard Worker std::system_category().default_error_condition(old_errno).message();
23*da0073e9SAndroid Build Coastguard Worker #endif
24*da0073e9SAndroid Build Coastguard Worker AT_ERROR(
25*da0073e9SAndroid Build Coastguard Worker "open file failed because of errno ",
26*da0073e9SAndroid Build Coastguard Worker old_errno,
27*da0073e9SAndroid Build Coastguard Worker " on fopen: ",
28*da0073e9SAndroid Build Coastguard Worker error_msg,
29*da0073e9SAndroid Build Coastguard Worker ", file path: ",
30*da0073e9SAndroid Build Coastguard Worker file_name);
31*da0073e9SAndroid Build Coastguard Worker }
32*da0073e9SAndroid Build Coastguard Worker }
33*da0073e9SAndroid Build Coastguard Worker
~RAIIFile()34*da0073e9SAndroid Build Coastguard Worker FileAdapter::RAIIFile::~RAIIFile() {
35*da0073e9SAndroid Build Coastguard Worker if (fp_ != nullptr) {
36*da0073e9SAndroid Build Coastguard Worker fclose(fp_);
37*da0073e9SAndroid Build Coastguard Worker }
38*da0073e9SAndroid Build Coastguard Worker }
39*da0073e9SAndroid Build Coastguard Worker
40*da0073e9SAndroid Build Coastguard Worker // FileAdapter directly calls C file API.
FileAdapter(const std::string & file_name)41*da0073e9SAndroid Build Coastguard Worker FileAdapter::FileAdapter(const std::string& file_name) : file_(file_name) {
42*da0073e9SAndroid Build Coastguard Worker const int fseek_ret = fseek(file_.fp_, 0L, SEEK_END);
43*da0073e9SAndroid Build Coastguard Worker TORCH_CHECK(fseek_ret == 0, "fseek returned ", fseek_ret);
44*da0073e9SAndroid Build Coastguard Worker #if defined(_MSC_VER)
45*da0073e9SAndroid Build Coastguard Worker const int64_t ftell_ret = _ftelli64(file_.fp_);
46*da0073e9SAndroid Build Coastguard Worker #else
47*da0073e9SAndroid Build Coastguard Worker const off_t ftell_ret = ftello(file_.fp_);
48*da0073e9SAndroid Build Coastguard Worker #endif
49*da0073e9SAndroid Build Coastguard Worker TORCH_CHECK(ftell_ret != -1L, "ftell returned ", ftell_ret);
50*da0073e9SAndroid Build Coastguard Worker size_ = ftell_ret;
51*da0073e9SAndroid Build Coastguard Worker rewind(file_.fp_);
52*da0073e9SAndroid Build Coastguard Worker }
53*da0073e9SAndroid Build Coastguard Worker
size() const54*da0073e9SAndroid Build Coastguard Worker size_t FileAdapter::size() const {
55*da0073e9SAndroid Build Coastguard Worker return size_;
56*da0073e9SAndroid Build Coastguard Worker }
57*da0073e9SAndroid Build Coastguard Worker
read(uint64_t pos,void * buf,size_t n,const char * what) const58*da0073e9SAndroid Build Coastguard Worker size_t FileAdapter::read(uint64_t pos, void* buf, size_t n, const char* what)
59*da0073e9SAndroid Build Coastguard Worker const {
60*da0073e9SAndroid Build Coastguard Worker // Ensure that pos doesn't exceed size_.
61*da0073e9SAndroid Build Coastguard Worker pos = std::min(pos, size_);
62*da0073e9SAndroid Build Coastguard Worker // If pos doesn't exceed size_, then size_ - pos can never be negative (in
63*da0073e9SAndroid Build Coastguard Worker // signed math) or since these are unsigned values, a very large value.
64*da0073e9SAndroid Build Coastguard Worker // Clamp 'n' to the smaller of 'size_ - pos' and 'n' itself. i.e. if the
65*da0073e9SAndroid Build Coastguard Worker // user requested to read beyond the end of the file, we clamp to just the
66*da0073e9SAndroid Build Coastguard Worker // end of the file.
67*da0073e9SAndroid Build Coastguard Worker n = std::min(static_cast<size_t>(size_ - pos), n);
68*da0073e9SAndroid Build Coastguard Worker #if defined(_MSC_VER)
69*da0073e9SAndroid Build Coastguard Worker const int fseek_ret = _fseeki64(file_.fp_, pos, SEEK_SET);
70*da0073e9SAndroid Build Coastguard Worker #else
71*da0073e9SAndroid Build Coastguard Worker const int fseek_ret = fseeko(file_.fp_, pos, SEEK_SET);
72*da0073e9SAndroid Build Coastguard Worker #endif
73*da0073e9SAndroid Build Coastguard Worker TORCH_CHECK(
74*da0073e9SAndroid Build Coastguard Worker fseek_ret == 0, "fseek returned ", fseek_ret, ", context: ", what);
75*da0073e9SAndroid Build Coastguard Worker return fread(buf, 1, n, file_.fp_);
76*da0073e9SAndroid Build Coastguard Worker }
77*da0073e9SAndroid Build Coastguard Worker
78*da0073e9SAndroid Build Coastguard Worker FileAdapter::~FileAdapter() = default;
79*da0073e9SAndroid Build Coastguard Worker
80*da0073e9SAndroid Build Coastguard Worker } // namespace serialize
81*da0073e9SAndroid Build Coastguard Worker } // namespace caffe2
82