v31.1-roots.1 · Commit 7: [PATCH 07/17] feat(rpc): preserve Roots operator interfaces on v31
src/util/fs_helpers.cpp
Before: src/util/fs_helpers.cpp · After: src/util/fs_helpers.cpp
File metadata
index a4d5e40d5f6660a656edc06148e80a154866664c..346b94b320c2f6f40f579d11b94234eae7e813cc 100644
Download original patch · Release notes
Diff rows 1–130 of 130. Line numbers refer to the original before/after files.
+ Added− RemovedUnmarked lines are context.
Scroll the code area horizontally to read long lines. The two line-number columns refer to before and after.
src/util/fs_helpers.cpp
CHANGED
|
@@ -10,12 +10,16 @@
|
|
|
10
10
|
#include <random.h>
|
|
11
11
|
#include <sync.h>
|
|
12
12
|
#include <tinyformat.h>
|
|
13
|
+
#include <util/check.h>
|
|
13
14
|
#include <util/fs.h>
|
|
14
15
|
#include <util/log.h>
|
|
15
16
|
#include <util/syserror.h>
|
|
16
17
|
|
|
17
18
|
#include <cerrno>
|
|
19
|
+
#include <cstdint>
|
|
20
|
+
#include <cstring>
|
|
18
21
|
#include <fstream>
|
|
22
|
+
#include <limits>
|
|
19
23
|
#include <map>
|
|
20
24
|
#include <memory>
|
|
21
25
|
#include <optional>
|
|
@@ -158,19 +162,35 @@ bool TruncateFile(FILE* file, unsigned int length)
|
|
|
158
162
|
*/
|
|
159
163
|
int RaiseFileDescriptorLimit(int nMinFD)
|
|
160
164
|
{
|
|
165
|
+
Assert(nMinFD >= 0);
|
|
161
166
|
#if defined(WIN32)
|
|
162
167
|
return 2048;
|
|
163
168
|
#else
|
|
164
169
|
struct rlimit limitFD;
|
|
165
170
|
if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) {
|
|
166
|
-
if (limitFD.rlim_cur < (rlim_t)nMinFD) {
|
|
167
|
-
limitFD.rlim_cur = nMinFD;
|
|
168
|
-
if (limitFD.rlim_cur > limitFD.rlim_max)
|
|
171
|
+
// If the current soft limit is already higher, don't raise it
|
|
172
|
+
if (limitFD.rlim_cur != RLIM_INFINITY && std::cmp_less(limitFD.rlim_cur, nMinFD)) {
|
|
173
|
+
const auto current_limit{limitFD.rlim_cur};
|
|
174
|
+
limitFD.rlim_cur = std::in_range<rlim_t>(nMinFD) ? static_cast<rlim_t>(nMinFD) : limitFD.rlim_max;
|
|
175
|
+
// Don't raise soft limit beyond hard limit
|
|
176
|
+
if (limitFD.rlim_max != RLIM_INFINITY && limitFD.rlim_cur > limitFD.rlim_max) {
|
|
169
177
|
limitFD.rlim_cur = limitFD.rlim_max;
|
|
170
|
-
setrlimit(RLIMIT_NOFILE, &limitFD);
|
|
171
|
-
getrlimit(RLIMIT_NOFILE, &limitFD);
|
|
178
|
+
}
|
|
179
|
+
if (current_limit != limitFD.rlim_cur) {
|
|
180
|
+
setrlimit(RLIMIT_NOFILE, &limitFD);
|
|
181
|
+
getrlimit(RLIMIT_NOFILE, &limitFD);
|
|
182
|
+
}
|
|
172
183
|
}
|
|
173
|
-
return limitFD.rlim_cur;
|
|
184
|
+
// Check the (possibly raised) current soft limit against the special
|
|
185
|
+
// value of RLIM_INFINITY. Some platforms implement this as the maximum
|
|
186
|
+
// uint64, others as int64 (-1). Avoid casting even if the return type
|
|
187
|
+
// is changed to uint64_t. We also cap unlikely but possible values
|
|
188
|
+
// that would overflow int.
|
|
189
|
+
if (limitFD.rlim_cur == RLIM_INFINITY ||
|
|
190
|
+
std::cmp_greater_equal(limitFD.rlim_cur, std::numeric_limits<int>::max())) {
|
|
191
|
+
return std::numeric_limits<int>::max();
|
|
192
|
+
}
|
|
193
|
+
return static_cast<int>(limitFD.rlim_cur);
|
|
174
194
|
}
|
|
175
195
|
return nMinFD; // getrlimit failed, assume it's fine
|
|
176
196
|
#endif
|
|
@@ -178,7 +198,7 @@ int RaiseFileDescriptorLimit(int nMinFD)
|
|
|
178
198
|
|
|
179
199
|
/**
|
|
180
200
|
* this function tries to make a particular range of a file allocated (corresponding to disk space)
|
|
181
|
-
* it is advisory, and the range specified in the arguments will never contain live data
|
|
201
|
+
* It is advisory and must preserve existing bytes in the requested range.
|
|
182
202
|
*/
|
|
183
203
|
void AllocateFileRange(FILE* file, unsigned int offset, unsigned int length)
|
|
184
204
|
{
|
|
@@ -187,42 +207,43 @@ void AllocateFileRange(FILE* file, unsigned int offset, unsigned int length)
|
|
|
187
207
|
HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
|
|
188
208
|
LARGE_INTEGER nFileSize;
|
|
189
209
|
int64_t nEndPos = (int64_t)offset + length;
|
|
190
|
-
nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF;
|
|
191
|
-
nFileSize.u.HighPart = nEndPos >> 32;
|
|
192
|
-
SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN);
|
|
193
|
-
SetEndOfFile(hFile);
|
|
194
|
-
#elif defined(__APPLE__)
|
|
195
|
-
// OSX specific version
|
|
196
|
-
// NOTE: Contrary to other OS versions, the OSX version assumes that
|
|
197
|
-
// NOTE: offset is the size of the file.
|
|
198
|
-
fstore_t fst;
|
|
199
|
-
fst.fst_flags = F_ALLOCATECONTIG;
|
|
200
|
-
fst.fst_posmode = F_PEOFPOSMODE;
|
|
201
|
-
fst.fst_offset = 0;
|
|
202
|
-
fst.fst_length = length; // mac os fst_length takes the # of free bytes to allocate, not desired file size
|
|
203
|
-
fst.fst_bytesalloc = 0;
|
|
204
|
-
if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) {
|
|
205
|
-
fst.fst_flags = F_ALLOCATEALL;
|
|
206
|
-
fcntl(fileno(file), F_PREALLOCATE, &fst);
|
|
210
|
+
if (GetFileSizeEx(hFile, &nFileSize) && nFileSize.QuadPart < nEndPos) {
|
|
211
|
+
nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF;
|
|
212
|
+
nFileSize.u.HighPart = nEndPos >> 32;
|
|
213
|
+
if (SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN)) {
|
|
214
|
+
SetEndOfFile(hFile);
|
|
215
|
+
}
|
|
207
216
|
}
|
|
208
|
-
ftruncate(fileno(file), static_cast<off_t>(offset) + length);
|
|
209
217
|
#else
|
|
210
218
|
#if defined(HAVE_POSIX_FALLOCATE)
|
|
211
219
|
// Version using posix_fallocate
|
|
212
|
-
off_t nEndPos = (off_t)offset + length;
|
|
213
|
-
if (0 == posix_fallocate(fileno(file), 0, nEndPos)) return;
|
|
220
|
+
if (0 == posix_fallocate(fileno(file), offset, length)) return;
|
|
214
221
|
#endif
|
|
215
222
|
// Fallback version
|
|
216
223
|
// TODO: just write one byte per block
|
|
217
|
-
static const char buf[65536] = {};
|
|
224
|
+
uint8_t buf[65536];
|
|
218
225
|
if (fseek(file, offset, SEEK_SET)) {
|
|
219
226
|
return;
|
|
220
227
|
}
|
|
228
|
+
clearerr(file);
|
|
221
229
|
while (length > 0) {
|
|
222
230
|
unsigned int now = 65536;
|
|
223
231
|
if (length < now)
|
|
224
232
|
now = length;
|
|
225
|
-
fwrite(buf, 1, now, file); // allowed to fail; this function is advisory anyway
|
|
233
|
+
const size_t rlen = fread(buf, 1, now, file);
|
|
234
|
+
if (rlen < now) {
|
|
235
|
+
if (ferror(file)) {
|
|
236
|
+
// Don't clobber anything, just give up
|
|
237
|
+
clearerr(file);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
memset(&buf[rlen], 0, now - rlen);
|
|
241
|
+
}
|
|
242
|
+
// Rewind after every read so allocation preserves existing bytes.
|
|
243
|
+
if (fseek(file, -static_cast<long>(rlen), SEEK_CUR)) return;
|
|
244
|
+
if (fwrite(buf, 1, now, file) != now) return; // Advisory allocation may fail.
|
|
245
|
+
// An update stream needs a positioning operation between writing and reading.
|
|
246
|
+
if (fseek(file, 0, SEEK_CUR)) return;
|
|
226
247
|
length -= now;
|
|
227
248
|
}
|
|
228
249
|
#endif
|