mirror of
https://github.com/NixOS/nix.git
synced 2025-11-20 17:29:36 +01:00
libstore: Make uploads with filetransfer.cc consume a RestartableSource
Make uploads run in constant memory. Also change the callbacks to be noexcept, since we really don't want to be unwinding the stack in the curl thread. That will definitely corrupt that stack and make nix/curl crash in very bad ways.
This commit is contained in:
parent
b8d7f551e4
commit
cf75079bd8
9 changed files with 87 additions and 42 deletions
|
|
@ -295,20 +295,17 @@ struct curlFileTransfer : public FileTransfer
|
|||
return 0;
|
||||
}
|
||||
|
||||
size_t readOffset = 0;
|
||||
|
||||
size_t readCallback(char * buffer, size_t size, size_t nitems)
|
||||
{
|
||||
if (readOffset == request.data->length())
|
||||
return 0;
|
||||
auto count = std::min(size * nitems, request.data->length() - readOffset);
|
||||
assert(count);
|
||||
memcpy(buffer, request.data->data() + readOffset, count);
|
||||
readOffset += count;
|
||||
return count;
|
||||
size_t readCallback(char * buffer, size_t size, size_t nitems) noexcept
|
||||
try {
|
||||
auto data = request.data;
|
||||
return data->source->read(buffer, nitems * size);
|
||||
} catch (EndOfFile &) {
|
||||
return 0;
|
||||
} catch (...) {
|
||||
return CURL_READFUNC_ABORT;
|
||||
}
|
||||
|
||||
static size_t readCallbackWrapper(char * buffer, size_t size, size_t nitems, void * userp)
|
||||
static size_t readCallbackWrapper(char * buffer, size_t size, size_t nitems, void * userp) noexcept
|
||||
{
|
||||
return ((TransferItem *) userp)->readCallback(buffer, size, nitems);
|
||||
}
|
||||
|
|
@ -322,19 +319,24 @@ struct curlFileTransfer : public FileTransfer
|
|||
}
|
||||
#endif
|
||||
|
||||
size_t seekCallback(curl_off_t offset, int origin)
|
||||
{
|
||||
size_t seekCallback(curl_off_t offset, int origin) noexcept
|
||||
try {
|
||||
auto source = request.data->source;
|
||||
if (origin == SEEK_SET) {
|
||||
readOffset = offset;
|
||||
source->restart();
|
||||
source->skip(offset);
|
||||
} else if (origin == SEEK_CUR) {
|
||||
readOffset += offset;
|
||||
source->skip(offset);
|
||||
} else if (origin == SEEK_END) {
|
||||
readOffset = request.data->length() + offset;
|
||||
NullSink sink{};
|
||||
source->drainInto(sink);
|
||||
}
|
||||
return CURL_SEEKFUNC_OK;
|
||||
} catch (...) {
|
||||
return CURL_SEEKFUNC_FAIL;
|
||||
}
|
||||
|
||||
static size_t seekCallbackWrapper(void * clientp, curl_off_t offset, int origin)
|
||||
static size_t seekCallbackWrapper(void * clientp, curl_off_t offset, int origin) noexcept
|
||||
{
|
||||
return ((TransferItem *) clientp)->seekCallback(offset, origin);
|
||||
}
|
||||
|
|
@ -393,10 +395,10 @@ struct curlFileTransfer : public FileTransfer
|
|||
if (request.data) {
|
||||
if (request.method == HttpMethod::POST) {
|
||||
curl_easy_setopt(req, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(req, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t) request.data->length());
|
||||
curl_easy_setopt(req, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t) request.data->sizeHint);
|
||||
} else if (request.method == HttpMethod::PUT) {
|
||||
curl_easy_setopt(req, CURLOPT_UPLOAD, 1L);
|
||||
curl_easy_setopt(req, CURLOPT_INFILESIZE_LARGE, (curl_off_t) request.data->length());
|
||||
curl_easy_setopt(req, CURLOPT_INFILESIZE_LARGE, (curl_off_t) request.data->sizeHint);
|
||||
} else {
|
||||
unreachable();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue