UNPKG

2.48 kBtext/x-cView Raw
1/*
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the LICENSE
5 * file in the root directory of this source tree.
6 */
7#ifndef _WINDOWS
8
9#include <fcntl.h>
10#include <sys/mman.h>
11#include <sys/stat.h>
12#include <sys/types.h>
13#include <unistd.h>
14#include <cerrno>
15#include <stdexcept>
16
17#include <jsi/jsilib.h>
18
19#if __APPLE__
20#include <mach/vm_statistics.h>
21#define MAP_TAG VM_MAKE_TAG(VM_MEMORY_APPLICATION_SPECIFIC_16)
22#endif // __APPLE__
23
24#ifndef MAP_TAG
25#define MAP_TAG 0
26#endif
27
28namespace facebook {
29namespace jsi {
30
31namespace {
32
33constexpr size_t kErrorBufferSize = 512;
34
35__attribute__((format(printf, 1, 2))) void throwFormattedError(
36 const char* fmt,
37 ...) {
38 char logBuffer[kErrorBufferSize];
39
40 va_list va_args;
41 va_start(va_args, fmt);
42 int result = vsnprintf(logBuffer, sizeof(logBuffer), fmt, va_args);
43 va_end(va_args);
44
45 if (result < 0) {
46 throw JSINativeException(
47 std::string("Failed to format error message: ") + fmt);
48 }
49
50 throw JSINativeException(logBuffer);
51}
52
53class ScopedFile {
54 public:
55 ScopedFile(const std::string& path)
56 : path_(path), fd_(::open(path.c_str(), O_RDONLY)) {
57 if (fd_ == -1) {
58 throwFormattedError(
59 "Could not open %s: %s", path.c_str(), strerror(errno));
60 }
61 }
62
63 ~ScopedFile() {
64 ::close(fd_);
65 }
66
67 size_t size() {
68 struct stat fileInfo;
69 if (::fstat(fd_, &fileInfo) == -1) {
70 throwFormattedError(
71 "Could not stat %s: %s", path_.c_str(), strerror(errno));
72 }
73 return fileInfo.st_size;
74 }
75
76 uint8_t* mmap(size_t size) {
77 void* result =
78 ::mmap(nullptr, size, PROT_READ, MAP_PRIVATE | MAP_TAG, fd_, 0);
79 if (result == MAP_FAILED) {
80 throwFormattedError(
81 "Could not mmap %s: %s", path_.c_str(), strerror(errno));
82 }
83 return reinterpret_cast<uint8_t*>(result);
84 }
85
86 const std::string& path_;
87 const int fd_;
88};
89
90} // namespace
91
92FileBuffer::FileBuffer(const std::string& path) {
93 ScopedFile file(path);
94 size_ = file.size();
95 data_ = file.mmap(size_);
96}
97
98FileBuffer::~FileBuffer() {
99 if (::munmap(data_, size_)) {
100 // terminate the program with pending exception
101 try {
102 throwFormattedError(
103 "Could not unmap memory (%p, %zu bytes): %s",
104 data_,
105 size_,
106 strerror(errno));
107 } catch (...) {
108 std::terminate();
109 }
110 }
111}
112
113} // namespace jsi
114} // namespace facebook
115
116#endif // !defined(_WINDOWS)