react-native-mmkv 3.2.0 → 4.0.0-beta.0
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/android/CMakeLists.txt +18 -9
- package/android/build.gradle +6 -2
- package/cpp/{MMKVManagedBuffer.h → ManagedMMBuffer.h} +6 -6
- package/cpp/MmkvHostObject.cpp +22 -17
- package/cpp/MmkvHostObject.h +1 -2
- package/cpp/MmkvTypes.h +50 -0
- package/cpp/NativeMmkvModule.cpp +3 -3
- package/cpp/NativeMmkvModule.h +1 -8
- package/lib/commonjs/MMKV.js.map +1 -1
- package/lib/commonjs/Types.js.map +1 -1
- package/lib/commonjs/createMMKV.web.js +1 -1
- package/lib/commonjs/createMMKV.web.js.map +1 -1
- package/lib/module/MMKV.js.map +1 -1
- package/lib/module/Types.js.map +1 -1
- package/lib/module/createMMKV.web.js +1 -1
- package/lib/module/createMMKV.web.js.map +1 -1
- package/lib/typescript/src/MMKV.d.ts +1 -1
- package/lib/typescript/src/MMKV.d.ts.map +1 -1
- package/lib/typescript/src/Types.d.ts +7 -1
- package/lib/typescript/src/Types.d.ts.map +1 -1
- package/lib/typescript/src/hooks.d.ts +1 -1
- package/lib/typescript/src/hooks.d.ts.map +1 -1
- package/package.json +22 -27
- package/react-native-mmkv.podspec +4 -10
- package/react-native.config.js +9 -0
- package/src/MMKV.ts +1 -1
- package/src/Types.ts +7 -1
- package/src/createMMKV.web.ts +1 -1
- package/src/hooks.ts +1 -1
- package/MMKV/Core/CMakeLists.txt +0 -172
- package/MMKV/Core/CodedInputData.cpp +0 -252
- package/MMKV/Core/CodedInputData.h +0 -87
- package/MMKV/Core/CodedInputDataCrypt.cpp +0 -280
- package/MMKV/Core/CodedInputDataCrypt.h +0 -87
- package/MMKV/Core/CodedInputDataCrypt_OSX.cpp +0 -62
- package/MMKV/Core/CodedInputData_OSX.cpp +0 -92
- package/MMKV/Core/CodedOutputData.cpp +0 -186
- package/MMKV/Core/CodedOutputData.h +0 -88
- package/MMKV/Core/Core.xcodeproj/project.pbxproj +0 -707
- package/MMKV/Core/Core.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- package/MMKV/Core/Core.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- package/MMKV/Core/Core.xcodeproj/xcshareddata/xcschemes/Core.xcscheme +0 -67
- package/MMKV/Core/Core.xcodeproj/xcshareddata/xcschemes/MMKVWatchCore.xcscheme +0 -67
- package/MMKV/Core/InterProcessLock.cpp +0 -186
- package/MMKV/Core/InterProcessLock.h +0 -119
- package/MMKV/Core/InterProcessLock_Android.cpp +0 -103
- package/MMKV/Core/InterProcessLock_Win32.cpp +0 -108
- package/MMKV/Core/KeyValueHolder.cpp +0 -236
- package/MMKV/Core/KeyValueHolder.h +0 -122
- package/MMKV/Core/MMBuffer.cpp +0 -210
- package/MMKV/Core/MMBuffer.h +0 -111
- package/MMKV/Core/MMKV.cpp +0 -1702
- package/MMKV/Core/MMKV.h +0 -595
- package/MMKV/Core/MMKVLog.cpp +0 -127
- package/MMKV/Core/MMKVLog.h +0 -86
- package/MMKV/Core/MMKVLog_Android.cpp +0 -134
- package/MMKV/Core/MMKVMetaInfo.hpp +0 -99
- package/MMKV/Core/MMKVPredef.h +0 -293
- package/MMKV/Core/MMKV_Android.cpp +0 -261
- package/MMKV/Core/MMKV_IO.cpp +0 -1905
- package/MMKV/Core/MMKV_IO.h +0 -57
- package/MMKV/Core/MMKV_OSX.cpp +0 -423
- package/MMKV/Core/MMKV_OSX.h +0 -57
- package/MMKV/Core/MemoryFile.cpp +0 -603
- package/MMKV/Core/MemoryFile.h +0 -194
- package/MMKV/Core/MemoryFile_Android.cpp +0 -236
- package/MMKV/Core/MemoryFile_Linux.cpp +0 -125
- package/MMKV/Core/MemoryFile_OSX.cpp +0 -142
- package/MMKV/Core/MemoryFile_Win32.cpp +0 -554
- package/MMKV/Core/MiniPBCoder.cpp +0 -672
- package/MMKV/Core/MiniPBCoder.h +0 -151
- package/MMKV/Core/MiniPBCoder_OSX.cpp +0 -237
- package/MMKV/Core/PBEncodeItem.hpp +0 -104
- package/MMKV/Core/PBUtility.cpp +0 -61
- package/MMKV/Core/PBUtility.h +0 -148
- package/MMKV/Core/ScopedLock.hpp +0 -69
- package/MMKV/Core/ThreadLock.cpp +0 -75
- package/MMKV/Core/ThreadLock.h +0 -81
- package/MMKV/Core/ThreadLock_Win32.cpp +0 -89
- package/MMKV/Core/aes/AESCrypt.cpp +0 -273
- package/MMKV/Core/aes/AESCrypt.h +0 -112
- package/MMKV/Core/aes/openssl/openssl_aes-armv4.S +0 -1243
- package/MMKV/Core/aes/openssl/openssl_aes.h +0 -130
- package/MMKV/Core/aes/openssl/openssl_aes_core.cpp +0 -1044
- package/MMKV/Core/aes/openssl/openssl_aes_locl.h +0 -38
- package/MMKV/Core/aes/openssl/openssl_aesv8-armx.S +0 -308
- package/MMKV/Core/aes/openssl/openssl_arm_arch.h +0 -84
- package/MMKV/Core/aes/openssl/openssl_cfb128.cpp +0 -97
- package/MMKV/Core/aes/openssl/openssl_md32_common.h +0 -254
- package/MMKV/Core/aes/openssl/openssl_md5.h +0 -49
- package/MMKV/Core/aes/openssl/openssl_md5_dgst.cpp +0 -166
- package/MMKV/Core/aes/openssl/openssl_md5_locl.h +0 -75
- package/MMKV/Core/aes/openssl/openssl_md5_one.cpp +0 -30
- package/MMKV/Core/aes/openssl/openssl_opensslconf.h +0 -271
- package/MMKV/Core/core.vcxproj +0 -288
- package/MMKV/Core/core.vcxproj.filters +0 -150
- package/MMKV/Core/crc32/Checksum.h +0 -75
- package/MMKV/Core/crc32/crc32_armv8.cpp +0 -134
- package/MMKV/Core/crc32/zlib/CMakeLists.txt +0 -60
- package/MMKV/Core/crc32/zlib/crc32.cpp +0 -55
- package/MMKV/Core/crc32/zlib/crc32.h +0 -48
- package/MMKV/Core/crc32/zlib/zconf.h +0 -380
- package/MMKV/Core/crc32/zlib/zutil.h +0 -25
- package/MMKV/README.md +0 -354
package/MMKV/Core/MemoryFile.cpp
DELETED
|
@@ -1,603 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Tencent is pleased to support the open source community by making
|
|
3
|
-
* MMKV available.
|
|
4
|
-
*
|
|
5
|
-
* Copyright (C) 2018 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
|
-
#ifndef MMKV_WIN32
|
|
24
|
-
|
|
25
|
-
# include "InterProcessLock.h"
|
|
26
|
-
# include "MMBuffer.h"
|
|
27
|
-
# include "MMKVLog.h"
|
|
28
|
-
# include "ScopedLock.hpp"
|
|
29
|
-
# include <cerrno>
|
|
30
|
-
# include <utility>
|
|
31
|
-
# include <fcntl.h>
|
|
32
|
-
# include <sys/mman.h>
|
|
33
|
-
# include <sys/stat.h>
|
|
34
|
-
# include <unistd.h>
|
|
35
|
-
# include <sys/file.h>
|
|
36
|
-
# include <dirent.h>
|
|
37
|
-
# include <cstring>
|
|
38
|
-
# include <unistd.h>
|
|
39
|
-
|
|
40
|
-
using namespace std;
|
|
41
|
-
|
|
42
|
-
namespace mmkv {
|
|
43
|
-
|
|
44
|
-
extern bool getFileSize(int fd, size_t &size);
|
|
45
|
-
|
|
46
|
-
# ifdef MMKV_ANDROID
|
|
47
|
-
extern size_t ASharedMemory_getSize(int fd);
|
|
48
|
-
# else
|
|
49
|
-
File::File(MMKVPath_t path, OpenFlag flag) : m_path(std::move(path)), m_fd(-1), m_flag(flag) {
|
|
50
|
-
open();
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
MemoryFile::MemoryFile(MMKVPath_t path, size_t expectedCapacity, bool readOnly)
|
|
54
|
-
: m_diskFile(std::move(path), readOnly ? OpenFlag::ReadOnly : (OpenFlag::ReadWrite | OpenFlag::Create))
|
|
55
|
-
, m_ptr(nullptr), m_size(0), m_readOnly(readOnly)
|
|
56
|
-
{
|
|
57
|
-
reloadFromFile(expectedCapacity);
|
|
58
|
-
}
|
|
59
|
-
# endif // !defined(MMKV_ANDROID)
|
|
60
|
-
|
|
61
|
-
# ifdef MMKV_IOS
|
|
62
|
-
void tryResetFileProtection(const string &path);
|
|
63
|
-
# endif
|
|
64
|
-
|
|
65
|
-
static int OpenFlag2NativeFlag(OpenFlag flag) {
|
|
66
|
-
int native = O_CLOEXEC;
|
|
67
|
-
if ((flag & OpenFlagRWMask) == OpenFlag::ReadWrite) {
|
|
68
|
-
native |= O_RDWR;
|
|
69
|
-
} else if (flag & OpenFlag::ReadOnly) {
|
|
70
|
-
native |= O_RDONLY;
|
|
71
|
-
} else if (flag & OpenFlag::WriteOnly) {
|
|
72
|
-
native |= O_WRONLY;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (flag & OpenFlag::Create) {
|
|
76
|
-
native |= O_CREAT;
|
|
77
|
-
}
|
|
78
|
-
if (flag & OpenFlag::Excel) {
|
|
79
|
-
native |= O_EXCL;
|
|
80
|
-
}
|
|
81
|
-
if (flag & OpenFlag::Truncate) {
|
|
82
|
-
native |= O_TRUNC;
|
|
83
|
-
}
|
|
84
|
-
return native;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
bool File::open() {
|
|
88
|
-
# ifdef MMKV_ANDROID
|
|
89
|
-
if (m_fileType == MMFILE_TYPE_ASHMEM) {
|
|
90
|
-
return isFileValid();
|
|
91
|
-
}
|
|
92
|
-
# endif
|
|
93
|
-
if (isFileValid()) {
|
|
94
|
-
return true;
|
|
95
|
-
}
|
|
96
|
-
m_fd = ::open(m_path.c_str(), OpenFlag2NativeFlag(m_flag), S_IRWXU);
|
|
97
|
-
if (!isFileValid()) {
|
|
98
|
-
MMKVError("fail to open [%s], flag %x, %d(%s)", m_path.c_str(), m_flag, errno, strerror(errno));
|
|
99
|
-
return false;
|
|
100
|
-
}
|
|
101
|
-
MMKVInfo("open fd[%p], flag %x, %s", m_fd, m_flag, m_path.c_str());
|
|
102
|
-
return true;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
void File::close() {
|
|
106
|
-
if (isFileValid()) {
|
|
107
|
-
MMKVInfo("closing fd[%p], %s", m_fd, m_path.c_str());
|
|
108
|
-
if (::close(m_fd) == 0) {
|
|
109
|
-
m_fd = -1;
|
|
110
|
-
} else {
|
|
111
|
-
MMKVError("fail to close [%s], %d(%s)", m_path.c_str(), errno, strerror(errno));
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
size_t File::getActualFileSize() const {
|
|
117
|
-
# ifdef MMKV_ANDROID
|
|
118
|
-
if (m_fileType == MMFILE_TYPE_ASHMEM) {
|
|
119
|
-
return ASharedMemory_getSize(m_fd);
|
|
120
|
-
}
|
|
121
|
-
# endif
|
|
122
|
-
size_t size = 0;
|
|
123
|
-
mmkv::getFileSize(m_fd, size);
|
|
124
|
-
return size;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
bool MemoryFile::truncate(size_t size) {
|
|
128
|
-
if (!m_diskFile.isFileValid()) {
|
|
129
|
-
return false;
|
|
130
|
-
}
|
|
131
|
-
if (size == m_size) {
|
|
132
|
-
return true;
|
|
133
|
-
}
|
|
134
|
-
if (m_readOnly) {
|
|
135
|
-
// truncate readonly file not allow
|
|
136
|
-
return false;
|
|
137
|
-
}
|
|
138
|
-
# ifdef MMKV_ANDROID
|
|
139
|
-
if (m_diskFile.m_fileType == MMFILE_TYPE_ASHMEM) {
|
|
140
|
-
if (size > m_size) {
|
|
141
|
-
MMKVError("ashmem %s reach size limit:%zu, consider configure with larger size", m_diskFile.m_path.c_str(), m_size);
|
|
142
|
-
} else {
|
|
143
|
-
MMKVInfo("no way to trim ashmem %s from %zu to smaller size %zu", m_diskFile.m_path.c_str(), m_size, size);
|
|
144
|
-
}
|
|
145
|
-
return false;
|
|
146
|
-
}
|
|
147
|
-
# endif // MMKV_ANDROID
|
|
148
|
-
|
|
149
|
-
auto oldSize = m_size;
|
|
150
|
-
m_size = size;
|
|
151
|
-
// round up to (n * pagesize)
|
|
152
|
-
if (m_size < DEFAULT_MMAP_SIZE || (m_size % DEFAULT_MMAP_SIZE != 0)) {
|
|
153
|
-
m_size = ((m_size / DEFAULT_MMAP_SIZE) + 1) * DEFAULT_MMAP_SIZE;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (::ftruncate(m_diskFile.m_fd, static_cast<off_t>(m_size)) != 0) {
|
|
157
|
-
MMKVError("fail to truncate [%s] to size %zu, %s", m_diskFile.m_path.c_str(), m_size, strerror(errno));
|
|
158
|
-
m_size = oldSize;
|
|
159
|
-
return false;
|
|
160
|
-
}
|
|
161
|
-
if (m_size > oldSize) {
|
|
162
|
-
if (!zeroFillFile(m_diskFile.m_fd, oldSize, m_size - oldSize)) {
|
|
163
|
-
MMKVError("fail to zeroFile [%s] to size %zu, %s", m_diskFile.m_path.c_str(), m_size, strerror(errno));
|
|
164
|
-
m_size = oldSize;
|
|
165
|
-
|
|
166
|
-
// redo ftruncate to its previous size
|
|
167
|
-
int status = ::ftruncate(m_diskFile.m_fd, static_cast<off_t>(m_size));
|
|
168
|
-
if (status != 0) {
|
|
169
|
-
MMKVError("failed to truncate back [%s] to size %zu, %s", m_diskFile.m_path.c_str(), m_size, strerror(errno));
|
|
170
|
-
} else {
|
|
171
|
-
MMKVError("success to truncate [%s] back to size %zu", m_diskFile.m_path.c_str(), m_size);
|
|
172
|
-
MMKVError("after truncate, file size = %zu", getActualFileSize());
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return false;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (m_ptr) {
|
|
180
|
-
if (munmap(m_ptr, oldSize) != 0) {
|
|
181
|
-
MMKVError("fail to munmap [%s], %s", m_diskFile.m_path.c_str(), strerror(errno));
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
auto ret = mmap();
|
|
185
|
-
if (!ret) {
|
|
186
|
-
doCleanMemoryCache(true);
|
|
187
|
-
}
|
|
188
|
-
return ret;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
bool MemoryFile::msync(SyncFlag syncFlag) {
|
|
192
|
-
if (m_readOnly) {
|
|
193
|
-
// there's no point in msync() readonly memory
|
|
194
|
-
return true;
|
|
195
|
-
}
|
|
196
|
-
if (m_ptr) {
|
|
197
|
-
auto ret = ::msync(m_ptr, m_size, syncFlag ? MS_SYNC : MS_ASYNC);
|
|
198
|
-
if (ret == 0) {
|
|
199
|
-
return true;
|
|
200
|
-
}
|
|
201
|
-
MMKVError("fail to msync [%s], %s", m_diskFile.m_path.c_str(), strerror(errno));
|
|
202
|
-
}
|
|
203
|
-
return false;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
bool MemoryFile::mmap() {
|
|
207
|
-
auto oldPtr = m_ptr;
|
|
208
|
-
auto mode = m_readOnly ? PROT_READ : (PROT_READ | PROT_WRITE);
|
|
209
|
-
m_ptr = (char *) ::mmap(m_ptr, m_size, mode, MAP_SHARED, m_diskFile.m_fd, 0);
|
|
210
|
-
if (m_ptr == MAP_FAILED) {
|
|
211
|
-
MMKVError("fail to mmap [%s], mode %x, %s", m_diskFile.m_path.c_str(), mode, strerror(errno));
|
|
212
|
-
m_ptr = nullptr;
|
|
213
|
-
return false;
|
|
214
|
-
}
|
|
215
|
-
MMKVInfo("mmap to address [%p], oldPtr [%p], [%s]", m_ptr, oldPtr, m_diskFile.m_path.c_str());
|
|
216
|
-
return true;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
void MemoryFile::reloadFromFile(size_t expectedCapacity) {
|
|
220
|
-
# ifdef MMKV_ANDROID
|
|
221
|
-
if (m_fileType == MMFILE_TYPE_ASHMEM) {
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
# endif
|
|
225
|
-
if (isFileValid()) {
|
|
226
|
-
MMKVWarning("calling reloadFromFile while the cache [%s] is still valid", m_diskFile.m_path.c_str());
|
|
227
|
-
MMKV_ASSERT(0);
|
|
228
|
-
doCleanMemoryCache(false);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
if (!m_diskFile.open()) {
|
|
232
|
-
MMKVError("fail to open:%s, %s", m_diskFile.m_path.c_str(), strerror(errno));
|
|
233
|
-
} else {
|
|
234
|
-
FileLock fileLock(m_diskFile.m_fd);
|
|
235
|
-
InterProcessLock lock(&fileLock, SharedLockType);
|
|
236
|
-
SCOPED_LOCK(&lock);
|
|
237
|
-
|
|
238
|
-
mmkv::getFileSize(m_diskFile.m_fd, m_size);
|
|
239
|
-
size_t expectedSize = std::max<size_t>(DEFAULT_MMAP_SIZE, roundUp<size_t>(expectedCapacity, DEFAULT_MMAP_SIZE));
|
|
240
|
-
// round up to (n * pagesize)
|
|
241
|
-
if (!m_readOnly && (m_size < expectedSize || (m_size % DEFAULT_MMAP_SIZE != 0))) {
|
|
242
|
-
InterProcessLock exclusiveLock(&fileLock, ExclusiveLockType);
|
|
243
|
-
SCOPED_LOCK(&exclusiveLock);
|
|
244
|
-
|
|
245
|
-
size_t roundSize = ((m_size / DEFAULT_MMAP_SIZE) + 1) * DEFAULT_MMAP_SIZE;;
|
|
246
|
-
roundSize = std::max<size_t>(expectedSize, roundSize);
|
|
247
|
-
truncate(roundSize);
|
|
248
|
-
} else {
|
|
249
|
-
auto ret = mmap();
|
|
250
|
-
if (!ret) {
|
|
251
|
-
doCleanMemoryCache(true);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
# ifdef MMKV_IOS
|
|
255
|
-
if (!m_readOnly) {
|
|
256
|
-
tryResetFileProtection(m_diskFile.m_path);
|
|
257
|
-
}
|
|
258
|
-
# endif
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
void MemoryFile::doCleanMemoryCache(bool forceClean) {
|
|
263
|
-
# ifdef MMKV_ANDROID
|
|
264
|
-
if (m_diskFile.m_fileType == MMFILE_TYPE_ASHMEM && !forceClean) {
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
# endif
|
|
268
|
-
if (m_ptr && m_ptr != MAP_FAILED) {
|
|
269
|
-
if (munmap(m_ptr, m_size) != 0) {
|
|
270
|
-
MMKVError("fail to munmap [%s], %s", m_diskFile.m_path.c_str(), strerror(errno));
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
m_ptr = nullptr;
|
|
274
|
-
|
|
275
|
-
m_diskFile.close();
|
|
276
|
-
m_size = 0;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
bool isFileExist(const string &nsFilePath) {
|
|
280
|
-
if (nsFilePath.empty()) {
|
|
281
|
-
return false;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
return access(nsFilePath.c_str(), F_OK) == 0;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
#ifndef MMKV_APPLE
|
|
288
|
-
extern bool mkPath(const MMKVPath_t &str) {
|
|
289
|
-
char *path = strdup(str.c_str());
|
|
290
|
-
|
|
291
|
-
struct stat sb = {};
|
|
292
|
-
bool done = false;
|
|
293
|
-
char *slash = path;
|
|
294
|
-
|
|
295
|
-
while (!done) {
|
|
296
|
-
slash += strspn(slash, "/");
|
|
297
|
-
slash += strcspn(slash, "/");
|
|
298
|
-
|
|
299
|
-
done = (*slash == '\0');
|
|
300
|
-
*slash = '\0';
|
|
301
|
-
|
|
302
|
-
if (stat(path, &sb) != 0) {
|
|
303
|
-
if (errno != ENOENT || mkdir(path, 0777) != 0) {
|
|
304
|
-
MMKVWarning("%s : %s", path, strerror(errno));
|
|
305
|
-
// there's report that some Android devices might not have access permission on parent dir
|
|
306
|
-
if (done) {
|
|
307
|
-
free(path);
|
|
308
|
-
return false;
|
|
309
|
-
}
|
|
310
|
-
goto LContinue;
|
|
311
|
-
}
|
|
312
|
-
} else if (!S_ISDIR(sb.st_mode)) {
|
|
313
|
-
MMKVWarning("%s: %s", path, strerror(ENOTDIR));
|
|
314
|
-
free(path);
|
|
315
|
-
return false;
|
|
316
|
-
}
|
|
317
|
-
LContinue:
|
|
318
|
-
*slash = '/';
|
|
319
|
-
}
|
|
320
|
-
free(path);
|
|
321
|
-
|
|
322
|
-
return true;
|
|
323
|
-
}
|
|
324
|
-
#else
|
|
325
|
-
// avoid using so-called privacy API
|
|
326
|
-
extern bool mkPath(const MMKVPath_t &str) {
|
|
327
|
-
auto path = [NSString stringWithUTF8String:str.c_str()];
|
|
328
|
-
NSError *error = nil;
|
|
329
|
-
auto ret = [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error];
|
|
330
|
-
if (!ret) {
|
|
331
|
-
MMKVWarning("%s", error.localizedDescription.UTF8String);
|
|
332
|
-
return false;
|
|
333
|
-
}
|
|
334
|
-
return true;
|
|
335
|
-
}
|
|
336
|
-
#endif
|
|
337
|
-
|
|
338
|
-
MMBuffer *readWholeFile(const MMKVPath_t &path) {
|
|
339
|
-
MMBuffer *buffer = nullptr;
|
|
340
|
-
int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
|
|
341
|
-
if (fd >= 0) {
|
|
342
|
-
auto fileLength = lseek(fd, 0, SEEK_END);
|
|
343
|
-
if (fileLength > 0) {
|
|
344
|
-
buffer = new MMBuffer(static_cast<size_t>(fileLength));
|
|
345
|
-
lseek(fd, 0, SEEK_SET);
|
|
346
|
-
auto readSize = read(fd, buffer->getPtr(), static_cast<size_t>(fileLength));
|
|
347
|
-
if (readSize != -1) {
|
|
348
|
-
//fileSize = readSize;
|
|
349
|
-
} else {
|
|
350
|
-
MMKVWarning("fail to read %s: %s", path.c_str(), strerror(errno));
|
|
351
|
-
|
|
352
|
-
delete buffer;
|
|
353
|
-
buffer = nullptr;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
close(fd);
|
|
357
|
-
} else {
|
|
358
|
-
MMKVWarning("fail to open %s: %s", path.c_str(), strerror(errno));
|
|
359
|
-
}
|
|
360
|
-
return buffer;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
bool zeroFillFile(int fd, size_t startPos, size_t size) {
|
|
364
|
-
if (fd < 0) {
|
|
365
|
-
return false;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
if (lseek(fd, static_cast<off_t>(startPos), SEEK_SET) < 0) {
|
|
369
|
-
MMKVError("fail to lseek fd[%d], error:%s", fd, strerror(errno));
|
|
370
|
-
return false;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
static const char zeros[4096] = {};
|
|
374
|
-
while (size >= sizeof(zeros)) {
|
|
375
|
-
if (write(fd, zeros, sizeof(zeros)) < 0) {
|
|
376
|
-
MMKVError("fail to write fd[%d], error:%s", fd, strerror(errno));
|
|
377
|
-
return false;
|
|
378
|
-
}
|
|
379
|
-
size -= sizeof(zeros);
|
|
380
|
-
}
|
|
381
|
-
if (size > 0) {
|
|
382
|
-
if (write(fd, zeros, size) < 0) {
|
|
383
|
-
MMKVError("fail to write fd[%d], error:%s", fd, strerror(errno));
|
|
384
|
-
return false;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
return true;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
#ifndef MMKV_APPLE
|
|
391
|
-
bool getFileSize(int fd, size_t &size) {
|
|
392
|
-
struct stat st = {};
|
|
393
|
-
if (fstat(fd, &st) != -1) {
|
|
394
|
-
size = (size_t) st.st_size;
|
|
395
|
-
return true;
|
|
396
|
-
}
|
|
397
|
-
return false;
|
|
398
|
-
}
|
|
399
|
-
#else
|
|
400
|
-
// avoid using so-called privacy API
|
|
401
|
-
bool getFileSize(int fd, size_t &size) {
|
|
402
|
-
auto cur = lseek(fd, 0, SEEK_CUR);
|
|
403
|
-
if (cur == -1) {
|
|
404
|
-
return false;
|
|
405
|
-
}
|
|
406
|
-
auto end = lseek(fd, 0, SEEK_END);
|
|
407
|
-
if (end == -1) {
|
|
408
|
-
return false;
|
|
409
|
-
}
|
|
410
|
-
size = (size_t) end;
|
|
411
|
-
|
|
412
|
-
lseek(fd, cur, SEEK_SET);
|
|
413
|
-
return true;
|
|
414
|
-
}
|
|
415
|
-
#endif
|
|
416
|
-
|
|
417
|
-
size_t getPageSize() {
|
|
418
|
-
return static_cast<size_t>(getpagesize());
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
#ifndef MMKV_APPLE
|
|
422
|
-
|
|
423
|
-
static pair<MMKVPath_t, int> createUniqueTempFile(const char *prefix) {
|
|
424
|
-
char path[PATH_MAX];
|
|
425
|
-
#ifdef MMKV_ANDROID
|
|
426
|
-
snprintf(path, PATH_MAX, "%s/%s.XXXXXX", g_android_tmpDir.c_str(), prefix);
|
|
427
|
-
#else
|
|
428
|
-
snprintf(path, PATH_MAX, "%s/%s.XXXXXX", P_tmpdir, prefix);
|
|
429
|
-
#endif
|
|
430
|
-
|
|
431
|
-
auto fd = mkstemp(path);
|
|
432
|
-
if (fd < 0) {
|
|
433
|
-
MMKVError("fail to create unique temp file [%s], %d(%s)", path, errno, strerror(errno));
|
|
434
|
-
return {"", fd};
|
|
435
|
-
}
|
|
436
|
-
MMKVDebug("create unique temp file [%s] with fd[%d]", path, fd);
|
|
437
|
-
return {MMKVPath_t(path), fd};
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
#if !defined(MMKV_ANDROID) && !defined(MMKV_LINUX)
|
|
441
|
-
|
|
442
|
-
bool tryAtomicRename(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
|
|
443
|
-
if (::rename(srcPath.c_str(), dstPath.c_str()) != 0) {
|
|
444
|
-
MMKVError("fail to rename [%s] to [%s], %d(%s)", srcPath.c_str(), dstPath.c_str(), errno, strerror(errno));
|
|
445
|
-
return false;
|
|
446
|
-
}
|
|
447
|
-
return true;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD, bool needTruncate) {
|
|
451
|
-
if (dstFD < 0) {
|
|
452
|
-
return false;
|
|
453
|
-
}
|
|
454
|
-
bool ret = false;
|
|
455
|
-
File srcFile(srcPath, OpenFlag::ReadOnly);
|
|
456
|
-
if (!srcFile.isFileValid()) {
|
|
457
|
-
return false;
|
|
458
|
-
}
|
|
459
|
-
auto bufferSize = getPageSize();
|
|
460
|
-
auto buffer = (char *) malloc(bufferSize);
|
|
461
|
-
if (!buffer) {
|
|
462
|
-
MMKVError("fail to malloc size %zu, %d(%s)", bufferSize, errno, strerror(errno));
|
|
463
|
-
goto errorOut;
|
|
464
|
-
}
|
|
465
|
-
lseek(dstFD, 0, SEEK_SET);
|
|
466
|
-
|
|
467
|
-
// the POSIX standard don't have sendfile()/fcopyfile() equivalent, do it the hard way
|
|
468
|
-
while (true) {
|
|
469
|
-
auto sizeRead = read(srcFile.getFd(), buffer, bufferSize);
|
|
470
|
-
if (sizeRead < 0) {
|
|
471
|
-
MMKVError("fail to read file [%s], %d(%s)", srcPath.c_str(), errno, strerror(errno));
|
|
472
|
-
goto errorOut;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
size_t totalWrite = 0;
|
|
476
|
-
do {
|
|
477
|
-
auto sizeWrite = write(dstFD, buffer + totalWrite, sizeRead - totalWrite);
|
|
478
|
-
if (sizeWrite < 0) {
|
|
479
|
-
MMKVError("fail to write fd [%d], %d(%s)", dstFD, errno, strerror(errno));
|
|
480
|
-
goto errorOut;
|
|
481
|
-
}
|
|
482
|
-
totalWrite += sizeWrite;
|
|
483
|
-
} while (totalWrite < sizeRead);
|
|
484
|
-
|
|
485
|
-
if (sizeRead < bufferSize) {
|
|
486
|
-
break;
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
if (needTruncate) {
|
|
490
|
-
size_t dstFileSize = 0;
|
|
491
|
-
getFileSize(dstFD, dstFileSize);
|
|
492
|
-
auto srcFileSize = srcFile.getActualFileSize();
|
|
493
|
-
if ((dstFileSize != srcFileSize) && (::ftruncate(dstFD, static_cast<off_t>(srcFileSize)) != 0)) {
|
|
494
|
-
MMKVError("fail to truncate [%d] to size [%zu], %d(%s)", dstFD, srcFileSize, errno, strerror(errno));
|
|
495
|
-
goto errorOut;
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
ret = true;
|
|
500
|
-
MMKVInfo("copy content from %s to fd[%d] finish", srcPath.c_str(), dstFD);
|
|
501
|
-
|
|
502
|
-
errorOut:
|
|
503
|
-
free(buffer);
|
|
504
|
-
return ret;
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
#endif // !defined(MMKV_ANDROID) && !defined(MMKV_LINUX)
|
|
508
|
-
|
|
509
|
-
// copy to a temp file then rename it
|
|
510
|
-
// this is the best we can do under the POSIX standard
|
|
511
|
-
bool copyFile(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
|
|
512
|
-
auto pair = createUniqueTempFile("MMKV");
|
|
513
|
-
auto tmpFD = pair.second;
|
|
514
|
-
auto &tmpPath = pair.first;
|
|
515
|
-
if (tmpFD < 0) {
|
|
516
|
-
return false;
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
bool renamed = false;
|
|
520
|
-
if (copyFileContent(srcPath, tmpFD, false)) {
|
|
521
|
-
MMKVInfo("copyfile [%s] to [%s]", srcPath.c_str(), tmpPath.c_str());
|
|
522
|
-
renamed = tryAtomicRename(tmpPath, dstPath);
|
|
523
|
-
if (renamed) {
|
|
524
|
-
MMKVInfo("copyfile [%s] to [%s] finish.", srcPath.c_str(), dstPath.c_str());
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
::close(tmpFD);
|
|
529
|
-
if (!renamed) {
|
|
530
|
-
::unlink(tmpPath.c_str());
|
|
531
|
-
}
|
|
532
|
-
return renamed;
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
bool copyFileContent(const MMKVPath_t &srcPath, const MMKVPath_t &dstPath) {
|
|
536
|
-
File dstFile(dstPath, OpenFlag::WriteOnly | OpenFlag::Create | OpenFlag::Truncate);
|
|
537
|
-
if (!dstFile.isFileValid()) {
|
|
538
|
-
return false;
|
|
539
|
-
}
|
|
540
|
-
auto ret = copyFileContent(srcPath, dstFile.getFd(), false);
|
|
541
|
-
if (!ret) {
|
|
542
|
-
MMKVError("fail to copyfile(): target file %s", dstPath.c_str());
|
|
543
|
-
} else {
|
|
544
|
-
MMKVInfo("copy content from %s to [%s] finish", srcPath.c_str(), dstPath.c_str());
|
|
545
|
-
}
|
|
546
|
-
return ret;
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
bool copyFileContent(const MMKVPath_t &srcPath, MMKVFileHandle_t dstFD) {
|
|
550
|
-
return copyFileContent(srcPath, dstFD, true);
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
#endif // !defined(MMKV_APPLE)
|
|
554
|
-
|
|
555
|
-
void walkInDir(const MMKVPath_t &dirPath, WalkType type, const function<void(const MMKVPath_t&, WalkType)> &walker) {
|
|
556
|
-
auto folderPathStr = dirPath.data();
|
|
557
|
-
DIR *dir = opendir(folderPathStr);
|
|
558
|
-
if (!dir) {
|
|
559
|
-
MMKVError("opendir failed: %d(%s), %s", errno, strerror(errno), dirPath.c_str());
|
|
560
|
-
return;
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
char childPath[PATH_MAX];
|
|
564
|
-
size_t folderPathLength = dirPath.size();
|
|
565
|
-
strncpy(childPath, folderPathStr, folderPathLength + 1);
|
|
566
|
-
if (folderPathStr[folderPathLength - 1] != '/') {
|
|
567
|
-
childPath[folderPathLength] = '/';
|
|
568
|
-
folderPathLength++;
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
while (auto child = readdir(dir)) {
|
|
572
|
-
if ((child->d_type & DT_REG) && (type & WalkFile)) {
|
|
573
|
-
#if defined(_DIRENT_HAVE_D_NAMLEN) || defined(__APPLE__)
|
|
574
|
-
stpcpy(childPath + folderPathLength, child->d_name);
|
|
575
|
-
childPath[folderPathLength + child->d_namlen] = 0;
|
|
576
|
-
#else
|
|
577
|
-
strcpy(childPath + folderPathLength, child->d_name);
|
|
578
|
-
#endif
|
|
579
|
-
walker(childPath, WalkFile);
|
|
580
|
-
} else if ((child->d_type & DT_DIR) && (type & WalkFolder)) {
|
|
581
|
-
#if defined(_DIRENT_HAVE_D_NAMLEN) || defined(__APPLE__)
|
|
582
|
-
if ((child->d_namlen == 1 && child->d_name[0] == '.') ||
|
|
583
|
-
(child->d_namlen == 2 && child->d_name[0] == '.' && child->d_name[1] == '.')) {
|
|
584
|
-
continue;
|
|
585
|
-
}
|
|
586
|
-
stpcpy(childPath + folderPathLength, child->d_name);
|
|
587
|
-
childPath[folderPathLength + child->d_namlen] = 0;
|
|
588
|
-
#else
|
|
589
|
-
if (strcmp(child->d_name, ".") == 0 || strcmp(child->d_name, "..") == 0) {
|
|
590
|
-
continue;
|
|
591
|
-
}
|
|
592
|
-
strcpy(childPath + folderPathLength, child->d_name);
|
|
593
|
-
#endif
|
|
594
|
-
walker(childPath, WalkFolder);
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
closedir(dir);
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
} // namespace mmkv
|
|
602
|
-
|
|
603
|
-
#endif // !defined(MMKV_WIN32)
|