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