react-native-mmkv-dz 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +219 -0
- package/MMKV/CHANGELOG.md +553 -0
- package/MMKV/Core/CMakeLists.txt +153 -0
- package/MMKV/Core/CodedInputData.cpp +228 -0
- package/MMKV/Core/CodedInputData.h +83 -0
- package/MMKV/Core/CodedInputDataCrypt.cpp +280 -0
- package/MMKV/Core/CodedInputDataCrypt.h +87 -0
- package/MMKV/Core/CodedInputDataCrypt_OSX.cpp +62 -0
- package/MMKV/Core/CodedInputData_OSX.cpp +92 -0
- package/MMKV/Core/CodedOutputData.cpp +174 -0
- package/MMKV/Core/CodedOutputData.h +82 -0
- package/MMKV/Core/Core.xcodeproj/project.pbxproj +702 -0
- package/MMKV/Core/Core.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/MMKV/Core/Core.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/MMKV/Core/Core.xcodeproj/xcshareddata/xcschemes/Core.xcscheme +67 -0
- package/MMKV/Core/Core.xcodeproj/xcshareddata/xcschemes/MMKVWatchCore.xcscheme +67 -0
- package/MMKV/Core/InterProcessLock.cpp +186 -0
- package/MMKV/Core/InterProcessLock.h +119 -0
- package/MMKV/Core/InterProcessLock_Android.cpp +103 -0
- package/MMKV/Core/InterProcessLock_Win32.cpp +108 -0
- package/MMKV/Core/KeyValueHolder.cpp +236 -0
- package/MMKV/Core/KeyValueHolder.h +118 -0
- package/MMKV/Core/MMBuffer.cpp +185 -0
- package/MMKV/Core/MMBuffer.h +107 -0
- package/MMKV/Core/MMKV.cpp +1418 -0
- package/MMKV/Core/MMKV.h +386 -0
- package/MMKV/Core/MMKVLog.cpp +127 -0
- package/MMKV/Core/MMKVLog.h +86 -0
- package/MMKV/Core/MMKVLog_Android.cpp +79 -0
- package/MMKV/Core/MMKVMetaInfo.hpp +81 -0
- package/MMKV/Core/MMKVPredef.h +245 -0
- package/MMKV/Core/MMKV_Android.cpp +259 -0
- package/MMKV/Core/MMKV_IO.cpp +1119 -0
- package/MMKV/Core/MMKV_IO.h +57 -0
- package/MMKV/Core/MMKV_OSX.cpp +347 -0
- package/MMKV/Core/MMKV_OSX.h +51 -0
- package/MMKV/Core/MemoryFile.cpp +537 -0
- package/MMKV/Core/MemoryFile.h +182 -0
- package/MMKV/Core/MemoryFile_Android.cpp +211 -0
- package/MMKV/Core/MemoryFile_Linux.cpp +120 -0
- package/MMKV/Core/MemoryFile_OSX.cpp +142 -0
- package/MMKV/Core/MemoryFile_Win32.cpp +536 -0
- package/MMKV/Core/MiniPBCoder.cpp +366 -0
- package/MMKV/Core/MiniPBCoder.h +129 -0
- package/MMKV/Core/MiniPBCoder_OSX.cpp +228 -0
- package/MMKV/Core/PBEncodeItem.hpp +86 -0
- package/MMKV/Core/PBUtility.cpp +61 -0
- package/MMKV/Core/PBUtility.h +153 -0
- package/MMKV/Core/ScopedLock.hpp +69 -0
- package/MMKV/Core/ThreadLock.cpp +68 -0
- package/MMKV/Core/ThreadLock.h +78 -0
- package/MMKV/Core/ThreadLock_Win32.cpp +89 -0
- package/MMKV/Core/aes/AESCrypt.cpp +256 -0
- package/MMKV/Core/aes/AESCrypt.h +107 -0
- package/MMKV/Core/aes/openssl/openssl_aes-armv4.S +1231 -0
- package/MMKV/Core/aes/openssl/openssl_aes.h +118 -0
- package/MMKV/Core/aes/openssl/openssl_aes_core.cpp +1044 -0
- package/MMKV/Core/aes/openssl/openssl_aes_locl.h +38 -0
- package/MMKV/Core/aes/openssl/openssl_aesv8-armx.S +308 -0
- package/MMKV/Core/aes/openssl/openssl_arm_arch.h +84 -0
- package/MMKV/Core/aes/openssl/openssl_cfb128.cpp +97 -0
- package/MMKV/Core/aes/openssl/openssl_md32_common.h +254 -0
- package/MMKV/Core/aes/openssl/openssl_md5.h +49 -0
- package/MMKV/Core/aes/openssl/openssl_md5_dgst.cpp +166 -0
- package/MMKV/Core/aes/openssl/openssl_md5_locl.h +75 -0
- package/MMKV/Core/aes/openssl/openssl_md5_one.cpp +30 -0
- package/MMKV/Core/aes/openssl/openssl_opensslconf.h +271 -0
- package/MMKV/Core/core.vcxproj +186 -0
- package/MMKV/Core/core.vcxproj.filters +150 -0
- package/MMKV/Core/crc32/Checksum.h +67 -0
- package/MMKV/Core/crc32/crc32_armv8.cpp +132 -0
- package/MMKV/Core/crc32/zlib/crc32.cpp +55 -0
- package/MMKV/Core/crc32/zlib/crc32.h +48 -0
- package/MMKV/Core/crc32/zlib/zconf.h +380 -0
- package/MMKV/Core/crc32/zlib/zutil.h +25 -0
- package/MMKV/LICENSE.TXT +193 -0
- package/MMKV/README.md +288 -0
- package/README.md +221 -0
- package/android/CMakeLists.txt +71 -0
- package/android/build.gradle +371 -0
- package/android/gradle.properties +4 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/cpp/MmkvHostObject.cpp +302 -0
- package/android/src/main/cpp/MmkvHostObject.h +26 -0
- package/android/src/main/cpp/cpp-adapter.cpp +65 -0
- package/android/src/main/java/com/reactnativemmkv/MmkvModule.java +49 -0
- package/android/src/main/java/com/reactnativemmkv/MmkvPackage.java +26 -0
- package/cpp/TypedArray.cpp +341 -0
- package/cpp/TypedArray.h +175 -0
- package/ios/JSIUtils.h +50 -0
- package/ios/JSIUtils.mm +194 -0
- package/ios/Mmkv.xcodeproj/project.pbxproj +291 -0
- package/ios/MmkvHostObject.h +27 -0
- package/ios/MmkvHostObject.mm +299 -0
- package/ios/MmkvModule.h +5 -0
- package/ios/MmkvModule.mm +73 -0
- package/lib/commonjs/MMKV.js +146 -0
- package/lib/commonjs/MMKV.js.map +1 -0
- package/lib/commonjs/PlatformChecker.js +16 -0
- package/lib/commonjs/PlatformChecker.js.map +1 -0
- package/lib/commonjs/createMMKV.js +66 -0
- package/lib/commonjs/createMMKV.js.map +1 -0
- package/lib/commonjs/createMMKV.mock.js +40 -0
- package/lib/commonjs/createMMKV.mock.js.map +1 -0
- package/lib/commonjs/createMMKV.web.js +77 -0
- package/lib/commonjs/createMMKV.web.js.map +1 -0
- package/lib/commonjs/createTextEncoder.js +24 -0
- package/lib/commonjs/createTextEncoder.js.map +1 -0
- package/lib/commonjs/hooks.js +200 -0
- package/lib/commonjs/hooks.js.map +1 -0
- package/lib/commonjs/index.js +32 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/module/MMKV.js +134 -0
- package/lib/module/MMKV.js.map +1 -0
- package/lib/module/PlatformChecker.js +9 -0
- package/lib/module/PlatformChecker.js.map +1 -0
- package/lib/module/createMMKV.js +55 -0
- package/lib/module/createMMKV.js.map +1 -0
- package/lib/module/createMMKV.mock.js +31 -0
- package/lib/module/createMMKV.mock.js.map +1 -0
- package/lib/module/createMMKV.web.js +67 -0
- package/lib/module/createMMKV.web.js.map +1 -0
- package/lib/module/createTextEncoder.js +17 -0
- package/lib/module/createTextEncoder.js.map +1 -0
- package/lib/module/hooks.js +181 -0
- package/lib/module/hooks.js.map +1 -0
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -0
- package/lib/typescript/MMKV.d.ts +137 -0
- package/lib/typescript/PlatformChecker.d.ts +1 -0
- package/lib/typescript/createMMKV.d.ts +6 -0
- package/lib/typescript/createMMKV.mock.d.ts +2 -0
- package/lib/typescript/createMMKV.web.d.ts +2 -0
- package/lib/typescript/createTextEncoder.d.ts +1 -0
- package/lib/typescript/hooks.d.ts +81 -0
- package/lib/typescript/index.d.ts +2 -0
- package/package.json +168 -0
- package/react-native-mmkv.podspec +32 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tencent is pleased to support the open source community by making
|
|
3
|
+
* MMKV available.
|
|
4
|
+
*
|
|
5
|
+
* Copyright (C) 2019 THL A29 Limited, a Tencent company.
|
|
6
|
+
* All rights reserved.
|
|
7
|
+
*
|
|
8
|
+
* Licensed under the BSD 3-Clause License (the "License"); you may not use
|
|
9
|
+
* this file except in compliance with the License. You may obtain a copy of
|
|
10
|
+
* the License at
|
|
11
|
+
*
|
|
12
|
+
* https://opensource.org/licenses/BSD-3-Clause
|
|
13
|
+
*
|
|
14
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
* See the License for the specific language governing permissions and
|
|
18
|
+
* limitations under the License.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
#include "MemoryFile.h"
|
|
22
|
+
|
|
23
|
+
#ifdef MMKV_ANDROID
|
|
24
|
+
|
|
25
|
+
# include "MMBuffer.h"
|
|
26
|
+
# include "MMKVLog.h"
|
|
27
|
+
# include <cerrno>
|
|
28
|
+
# include <fcntl.h>
|
|
29
|
+
# include <sys/mman.h>
|
|
30
|
+
# include <sys/stat.h>
|
|
31
|
+
# include <unistd.h>
|
|
32
|
+
|
|
33
|
+
using namespace std;
|
|
34
|
+
|
|
35
|
+
constexpr char ASHMEM_NAME_DEF[] = "/dev/ashmem";
|
|
36
|
+
|
|
37
|
+
namespace mmkv {
|
|
38
|
+
|
|
39
|
+
// for Android Q limiting ashmem access
|
|
40
|
+
extern int ASharedMemory_create(const char *name, size_t size);
|
|
41
|
+
extern size_t ASharedMemory_getSize(int fd);
|
|
42
|
+
extern string ASharedMemory_getName(int fd);
|
|
43
|
+
|
|
44
|
+
File::File(MMKVPath_t path, OpenFlag flag, size_t size, FileType fileType)
|
|
45
|
+
: m_path(std::move(path)), m_fd(-1), m_flag(flag), m_size(0), m_fileType(fileType) {
|
|
46
|
+
if (m_fileType == MMFILE_TYPE_FILE) {
|
|
47
|
+
open();
|
|
48
|
+
} else {
|
|
49
|
+
// round up to (n * pagesize)
|
|
50
|
+
if (size < DEFAULT_MMAP_SIZE || (size % DEFAULT_MMAP_SIZE != 0)) {
|
|
51
|
+
size = ((size / DEFAULT_MMAP_SIZE) + 1) * DEFAULT_MMAP_SIZE;
|
|
52
|
+
}
|
|
53
|
+
auto filename = m_path.c_str();
|
|
54
|
+
auto ptr = strstr(filename, ASHMEM_NAME_DEF);
|
|
55
|
+
if (ptr && ptr[sizeof(ASHMEM_NAME_DEF) - 1] == '/') {
|
|
56
|
+
filename = ptr + sizeof(ASHMEM_NAME_DEF);
|
|
57
|
+
}
|
|
58
|
+
m_fd = ASharedMemory_create(filename, size);
|
|
59
|
+
if (isFileValid()) {
|
|
60
|
+
m_size = size;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
File::File(MMKVFileHandle_t ashmemFD)
|
|
66
|
+
: m_path(), m_fd(ashmemFD), m_flag(OpenFlag::ReadWrite), m_size(0), m_fileType(MMFILE_TYPE_ASHMEM) {
|
|
67
|
+
if (isFileValid()) {
|
|
68
|
+
m_path = ASharedMemory_getName(m_fd);
|
|
69
|
+
m_size = ASharedMemory_getSize(m_fd);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
MemoryFile::MemoryFile(string path, size_t size, FileType fileType)
|
|
74
|
+
: m_diskFile(std::move(path), OpenFlag::ReadWrite | OpenFlag::Create, size, fileType), m_ptr(nullptr), m_size(0), m_fileType(fileType) {
|
|
75
|
+
if (m_fileType == MMFILE_TYPE_FILE) {
|
|
76
|
+
reloadFromFile();
|
|
77
|
+
} else {
|
|
78
|
+
if (m_diskFile.isFileValid()) {
|
|
79
|
+
m_size = m_diskFile.m_size;
|
|
80
|
+
auto ret = mmap();
|
|
81
|
+
if (!ret) {
|
|
82
|
+
doCleanMemoryCache(true);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
MemoryFile::MemoryFile(int ashmemFD)
|
|
89
|
+
: m_diskFile(ashmemFD), m_ptr(nullptr), m_size(0), m_fileType(MMFILE_TYPE_ASHMEM) {
|
|
90
|
+
if (!m_diskFile.isFileValid()) {
|
|
91
|
+
MMKVError("fd %d invalid", ashmemFD);
|
|
92
|
+
} else {
|
|
93
|
+
m_size = m_diskFile.m_size;
|
|
94
|
+
MMKVInfo("ashmem name:%s, size:%zu", m_diskFile.m_path.c_str(), m_size);
|
|
95
|
+
auto ret = mmap();
|
|
96
|
+
if (!ret) {
|
|
97
|
+
doCleanMemoryCache(true);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
} // namespace mmkv
|
|
103
|
+
|
|
104
|
+
# pragma mark - ashmem
|
|
105
|
+
# include <dlfcn.h>
|
|
106
|
+
# include <sys/ioctl.h>
|
|
107
|
+
|
|
108
|
+
namespace mmkv {
|
|
109
|
+
|
|
110
|
+
constexpr auto ASHMEM_NAME_LEN = 256;
|
|
111
|
+
constexpr auto ASHMEM_IOC = 0x77;
|
|
112
|
+
# define ASHMEM_SET_NAME _IOW(ASHMEM_IOC, 1, char[ASHMEM_NAME_LEN])
|
|
113
|
+
# define ASHMEM_GET_NAME _IOR(ASHMEM_IOC, 2, char[ASHMEM_NAME_LEN])
|
|
114
|
+
# define ASHMEM_SET_SIZE _IOW(ASHMEM_IOC, 3, size_t)
|
|
115
|
+
# define ASHMEM_GET_SIZE _IO(ASHMEM_IOC, 4)
|
|
116
|
+
|
|
117
|
+
int g_android_api = __ANDROID_API_L__;
|
|
118
|
+
std::string g_android_tmpDir = "/data/local/tmp/";
|
|
119
|
+
|
|
120
|
+
void *loadLibrary() {
|
|
121
|
+
auto name = "libandroid.so";
|
|
122
|
+
static auto handle = dlopen(name, RTLD_LAZY | RTLD_LOCAL);
|
|
123
|
+
if (handle == RTLD_DEFAULT) {
|
|
124
|
+
MMKVError("unable to load library %s", name);
|
|
125
|
+
}
|
|
126
|
+
return handle;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
typedef int (*AShmem_create_t)(const char *name, size_t size);
|
|
130
|
+
|
|
131
|
+
int ASharedMemory_create(const char *name, size_t size) {
|
|
132
|
+
int fd = -1;
|
|
133
|
+
if (g_android_api >= __ANDROID_API_O__) {
|
|
134
|
+
static auto handle = loadLibrary();
|
|
135
|
+
static AShmem_create_t funcPtr =
|
|
136
|
+
(handle != nullptr) ? reinterpret_cast<AShmem_create_t>(dlsym(handle, "ASharedMemory_create")) : nullptr;
|
|
137
|
+
if (funcPtr) {
|
|
138
|
+
fd = funcPtr(name, size);
|
|
139
|
+
if (fd < 0) {
|
|
140
|
+
MMKVError("fail to ASharedMemory_create %s with size %zu, errno:%s", name, size, strerror(errno));
|
|
141
|
+
}
|
|
142
|
+
} else {
|
|
143
|
+
MMKVWarning("fail to locate ASharedMemory_create() from loading libandroid.so");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (fd < 0) {
|
|
147
|
+
fd = open(ASHMEM_NAME_DEF, O_RDWR | O_CLOEXEC);
|
|
148
|
+
if (fd < 0) {
|
|
149
|
+
MMKVError("fail to open ashmem:%s, %s", name, strerror(errno));
|
|
150
|
+
} else {
|
|
151
|
+
if (ioctl(fd, ASHMEM_SET_NAME, name) != 0) {
|
|
152
|
+
MMKVError("fail to set ashmem name:%s, %s", name, strerror(errno));
|
|
153
|
+
} else if (ioctl(fd, ASHMEM_SET_SIZE, size) != 0) {
|
|
154
|
+
MMKVError("fail to set ashmem:%s, size %zu, %s", name, size, strerror(errno));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return fd;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
typedef size_t (*AShmem_getSize_t)(int fd);
|
|
162
|
+
|
|
163
|
+
size_t ASharedMemory_getSize(int fd) {
|
|
164
|
+
size_t size = 0;
|
|
165
|
+
if (g_android_api >= __ANDROID_API_O__) {
|
|
166
|
+
static auto handle = loadLibrary();
|
|
167
|
+
static AShmem_getSize_t funcPtr =
|
|
168
|
+
(handle != nullptr) ? reinterpret_cast<AShmem_getSize_t>(dlsym(handle, "ASharedMemory_getSize")) : nullptr;
|
|
169
|
+
if (funcPtr) {
|
|
170
|
+
size = funcPtr(fd);
|
|
171
|
+
if (size == 0) {
|
|
172
|
+
MMKVError("fail to ASharedMemory_getSize:%d, %s", fd, strerror(errno));
|
|
173
|
+
}
|
|
174
|
+
} else {
|
|
175
|
+
MMKVWarning("fail to locate ASharedMemory_create() from loading libandroid.so");
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (size == 0) {
|
|
179
|
+
int tmp = ioctl(fd, ASHMEM_GET_SIZE, nullptr);
|
|
180
|
+
if (tmp < 0) {
|
|
181
|
+
MMKVError("fail to get ashmem size:%d, %s", fd, strerror(errno));
|
|
182
|
+
} else {
|
|
183
|
+
size = static_cast<size_t>(tmp);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return size;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
string ASharedMemory_getName(int fd) {
|
|
190
|
+
// Android Q doesn't have ASharedMemory_getName()
|
|
191
|
+
// I've make a request to Google, https://issuetracker.google.com/issues/130741665
|
|
192
|
+
// There's nothing we can do before it's supported officially by Google
|
|
193
|
+
if (g_android_api >= __ANDROID_API_Q__) {
|
|
194
|
+
return "";
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
char name[ASHMEM_NAME_LEN] = {0};
|
|
198
|
+
if (ioctl(fd, ASHMEM_GET_NAME, name) != 0) {
|
|
199
|
+
MMKVError("fail to get ashmem name:%d, %s", fd, strerror(errno));
|
|
200
|
+
return "";
|
|
201
|
+
}
|
|
202
|
+
return {name};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
} // namespace mmkv
|
|
206
|
+
|
|
207
|
+
MMKVPath_t ashmemMMKVPathWithID(const MMKVPath_t &mmapID) {
|
|
208
|
+
return MMKVPath_t(ASHMEM_NAME_DEF) + MMKV_PATH_SLASH + mmapID;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
#endif // MMKV_ANDROID
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tencent is pleased to support the open source community by making
|
|
3
|
+
* MMKV available.
|
|
4
|
+
*
|
|
5
|
+
* Copyright (C) 2021 THL A29 Limited, a Tencent company.
|
|
6
|
+
* All rights reserved.
|
|
7
|
+
*
|
|
8
|
+
* Licensed under the BSD 3-Clause License (the "License"); you may not use
|
|
9
|
+
* this file except in compliance with the License. You may obtain a copy of
|
|
10
|
+
* the License at
|
|
11
|
+
*
|
|
12
|
+
* https://opensource.org/licenses/BSD-3-Clause
|
|
13
|
+
*
|
|
14
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
* See the License for the specific language governing permissions and
|
|
18
|
+
* limitations under the License.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
#include "MemoryFile.h"
|
|
22
|
+
|
|
23
|
+
#if defined(MMKV_ANDROID) || defined(MMKV_LINUX)
|
|
24
|
+
# include "InterProcessLock.h"
|
|
25
|
+
# include "MMBuffer.h"
|
|
26
|
+
# include "MMKVLog.h"
|
|
27
|
+
# include "ScopedLock.hpp"
|
|
28
|
+
# include <cerrno>
|
|
29
|
+
# include <utility>
|
|
30
|
+
# include <fcntl.h>
|
|
31
|
+
# include <sys/mman.h>
|
|
32
|
+
# include <sys/stat.h>
|
|
33
|
+
# include <unistd.h>
|
|
34
|
+
# include <sys/file.h>
|
|
35
|
+
# include <dirent.h>
|
|
36
|
+
# include <cstring>
|
|
37
|
+
# include <sys/sendfile.h>
|
|
38
|
+
# include <sys/syscall.h>
|
|
39
|
+
|
|
40
|
+
#ifdef MMKV_ANDROID
|
|
41
|
+
#include <dlfcn.h>
|
|
42
|
+
typedef int (*renameat2_t)(int old_dir_fd, const char* old_path, int new_dir_fd, const char* new_path, unsigned flags);
|
|
43
|
+
#endif
|
|
44
|
+
|
|
45
|
+
#ifndef RENAME_EXCHANGE
|
|
46
|
+
#define RENAME_EXCHANGE (1 << 1) /* Exchange source and dest */
|
|
47
|
+
#endif
|
|
48
|
+
|
|
49
|
+
namespace mmkv {
|
|
50
|
+
|
|
51
|
+
extern bool getFileSize(int fd, size_t &size);
|
|
52
|
+
|
|
53
|
+
bool tryAtomicRename(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
|
|
54
|
+
bool renamed = false;
|
|
55
|
+
|
|
56
|
+
// try renameat2() first
|
|
57
|
+
#ifdef SYS_renameat2
|
|
58
|
+
#ifdef MMKV_ANDROID
|
|
59
|
+
static auto g_renameat2 = (renameat2_t) dlsym(RTLD_DEFAULT, "renameat2");
|
|
60
|
+
if (g_renameat2) {
|
|
61
|
+
renamed = (g_renameat2(AT_FDCWD, srcPath.c_str(), AT_FDCWD, dstPath.c_str(), RENAME_EXCHANGE) == 0);
|
|
62
|
+
}
|
|
63
|
+
#endif
|
|
64
|
+
if (!renamed) {
|
|
65
|
+
renamed = (syscall(SYS_renameat2, AT_FDCWD, srcPath.c_str(), AT_FDCWD, dstPath.c_str(), RENAME_EXCHANGE) == 0);
|
|
66
|
+
}
|
|
67
|
+
if (!renamed && errno != ENOENT) {
|
|
68
|
+
MMKVError("fail on renameat2() [%s] to [%s], %d(%s)", srcPath.c_str(), dstPath.c_str(), errno, strerror(errno));
|
|
69
|
+
}
|
|
70
|
+
#endif // SYS_renameat2
|
|
71
|
+
|
|
72
|
+
if (!renamed) {
|
|
73
|
+
if (::rename(srcPath.c_str(), dstPath.c_str()) != 0) {
|
|
74
|
+
MMKVError("fail to rename [%s] to [%s], %d(%s)", srcPath.c_str(), dstPath.c_str(), errno, strerror(errno));
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
::unlink(srcPath.c_str());
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// do it by sendfile()
|
|
84
|
+
bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD, bool needTruncate) {
|
|
85
|
+
if (dstFD < 0) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
File srcFile(srcPath, OpenFlag::ReadOnly);
|
|
89
|
+
if (!srcFile.isFileValid()) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
auto srcFileSize = srcFile.getActualFileSize();
|
|
93
|
+
|
|
94
|
+
lseek(dstFD, 0, SEEK_SET);
|
|
95
|
+
auto writtenSize = ::sendfile(dstFD, srcFile.getFd(), nullptr, srcFileSize);
|
|
96
|
+
auto ret = (writtenSize == srcFileSize);
|
|
97
|
+
if (!ret) {
|
|
98
|
+
if (writtenSize < 0) {
|
|
99
|
+
MMKVError("fail to sendfile() %s to fd[%d], %d(%s)", srcPath.c_str(), dstFD, errno, strerror(errno));
|
|
100
|
+
} else {
|
|
101
|
+
MMKVError("sendfile() %s to fd[%d], written %lld < %zu", srcPath.c_str(), dstFD, writtenSize, srcFileSize);
|
|
102
|
+
}
|
|
103
|
+
} else if (needTruncate) {
|
|
104
|
+
size_t dstFileSize = 0;
|
|
105
|
+
getFileSize(dstFD, dstFileSize);
|
|
106
|
+
if ((dstFileSize != srcFileSize) && (::ftruncate(dstFD, static_cast<off_t>(srcFileSize)) != 0)) {
|
|
107
|
+
MMKVError("fail to truncate [%d] to size [%zu], %d(%s)", dstFD, srcFileSize, errno, strerror(errno));
|
|
108
|
+
ret = false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (ret) {
|
|
113
|
+
MMKVInfo("copy content from %s to fd[%d] finish", srcPath.c_str(), dstFD);
|
|
114
|
+
}
|
|
115
|
+
return ret;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
} // namespace mmkv
|
|
119
|
+
|
|
120
|
+
#endif // defined(MMKV_ANDROID) || defined(MMKV_LINUX)
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tencent is pleased to support the open source community by making
|
|
3
|
+
* MMKV available.
|
|
4
|
+
*
|
|
5
|
+
* Copyright (C) 2019 THL A29 Limited, a Tencent company.
|
|
6
|
+
* All rights reserved.
|
|
7
|
+
*
|
|
8
|
+
* Licensed under the BSD 3-Clause License (the "License"); you may not use
|
|
9
|
+
* this file except in compliance with the License. You may obtain a copy of
|
|
10
|
+
* the License at
|
|
11
|
+
*
|
|
12
|
+
* https://opensource.org/licenses/BSD-3-Clause
|
|
13
|
+
*
|
|
14
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
* See the License for the specific language governing permissions and
|
|
18
|
+
* limitations under the License.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
#include "MemoryFile.h"
|
|
22
|
+
#include "MMKVLog.h"
|
|
23
|
+
|
|
24
|
+
#ifdef MMKV_IOS
|
|
25
|
+
|
|
26
|
+
using namespace std;
|
|
27
|
+
|
|
28
|
+
namespace mmkv {
|
|
29
|
+
|
|
30
|
+
void tryResetFileProtection(const string &path) {
|
|
31
|
+
@autoreleasepool {
|
|
32
|
+
NSString *nsPath = [NSString stringWithUTF8String:path.c_str()];
|
|
33
|
+
NSDictionary *attr = [[NSFileManager defaultManager] attributesOfItemAtPath:nsPath error:nullptr];
|
|
34
|
+
NSString *protection = [attr valueForKey:NSFileProtectionKey];
|
|
35
|
+
MMKVInfo("protection on [%@] is %@", nsPath, protection);
|
|
36
|
+
if ([protection isEqualToString:NSFileProtectionCompleteUntilFirstUserAuthentication] == NO) {
|
|
37
|
+
NSMutableDictionary *newAttr = [NSMutableDictionary dictionaryWithDictionary:attr];
|
|
38
|
+
[newAttr setObject:NSFileProtectionCompleteUntilFirstUserAuthentication forKey:NSFileProtectionKey];
|
|
39
|
+
NSError *err = nil;
|
|
40
|
+
[[NSFileManager defaultManager] setAttributes:newAttr ofItemAtPath:nsPath error:&err];
|
|
41
|
+
if (err != nil) {
|
|
42
|
+
MMKVError("fail to set attribute %@ on [%@]: %@", NSFileProtectionCompleteUntilFirstUserAuthentication,
|
|
43
|
+
nsPath, err);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
} // namespace mmkv
|
|
50
|
+
|
|
51
|
+
#endif // MMKV_IOS
|
|
52
|
+
|
|
53
|
+
#ifdef MMKV_APPLE
|
|
54
|
+
|
|
55
|
+
#include <copyfile.h>
|
|
56
|
+
#include <mach/mach_time.h>
|
|
57
|
+
|
|
58
|
+
namespace mmkv {
|
|
59
|
+
|
|
60
|
+
bool tryAtomicRename(const char *src, const char *dst) {
|
|
61
|
+
bool renamed = false;
|
|
62
|
+
|
|
63
|
+
// try atomic swap first
|
|
64
|
+
if (@available(iOS 10.0, watchOS 3.0, *)) {
|
|
65
|
+
// renameat2() equivalent
|
|
66
|
+
if (renamex_np(src, dst, RENAME_SWAP) == 0) {
|
|
67
|
+
renamed = true;
|
|
68
|
+
} else if (errno != ENOENT) {
|
|
69
|
+
MMKVError("fail to renamex_np %s to %s, %s", src, dst, strerror(errno));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!renamed) {
|
|
74
|
+
// try old style rename
|
|
75
|
+
if (rename(src, dst) != 0) {
|
|
76
|
+
MMKVError("fail to rename %s to %s, %s", src, dst, strerror(errno));
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
unlink(src);
|
|
82
|
+
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
bool copyFile(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
|
|
87
|
+
// prepare a temp file for atomic rename, avoid data corruption of suddent crash
|
|
88
|
+
NSString *uniqueFileName = [NSString stringWithFormat:@"mmkv_%llu", mach_absolute_time()];
|
|
89
|
+
NSString *tmpFile = [NSTemporaryDirectory() stringByAppendingPathComponent:uniqueFileName];
|
|
90
|
+
if (copyfile(srcPath.c_str(), tmpFile.UTF8String, nullptr, COPYFILE_UNLINK | COPYFILE_CLONE) != 0) {
|
|
91
|
+
MMKVError("fail to copyfile [%s] to [%s], %s", srcPath.c_str(), tmpFile.UTF8String, strerror(errno));
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
MMKVInfo("copyfile [%s] to [%s]", srcPath.c_str(), tmpFile.UTF8String);
|
|
95
|
+
|
|
96
|
+
if (tryAtomicRename(tmpFile.UTF8String, dstPath.c_str())) {
|
|
97
|
+
MMKVInfo("copyfile [%s] to [%s] finish.", srcPath.c_str(), dstPath.c_str());
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
unlink(tmpFile.UTF8String);
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
bool copyFileContent(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
|
|
105
|
+
File dstFile(dstPath, OpenFlag::WriteOnly | OpenFlag::Create | OpenFlag::Truncate);
|
|
106
|
+
if (!dstFile.isFileValid()) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
if (copyFileContent(srcPath, dstFile.getFd())) {
|
|
110
|
+
MMKVInfo("copy content from %s to fd[%s] finish", srcPath.c_str(), dstPath.c_str());
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
MMKVError("fail to copyfile(): target file %s", dstPath.c_str());
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD) {
|
|
118
|
+
if (dstFD < 0) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
File srcFile(srcPath, OpenFlag::ReadOnly);
|
|
123
|
+
if (!srcFile.isFileValid()) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// sendfile() equivalent
|
|
128
|
+
if (::fcopyfile(srcFile.getFd(), dstFD, nullptr, COPYFILE_ACL | COPYFILE_STAT | COPYFILE_XATTR | COPYFILE_DATA) == 0) {
|
|
129
|
+
MMKVInfo("copy content from %s to fd[%d] finish", srcPath.c_str(), dstFD);
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
MMKVError("fail to copyfile(): %d(%s), source file %s", errno, strerror(errno), srcPath.c_str());
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD, bool needTruncate) {
|
|
137
|
+
return copyFileContent(srcPath, dstFD);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
} // namespace mmkv
|
|
141
|
+
|
|
142
|
+
#endif // MMKV_APPLE
|