#include "setup.h"
#include <curl/curl.h>
#define ENABLE_CURLX_PRINTF
#include "curlx.h"
#include "tool_cfgable.h"
#include "tool_msgs.h"
#include "tool_cb_wrt.h"
#include "memdebug.h"
size_t tool_write_cb(void *buffer, size_t sz, size_t nmemb, void *userdata)
{
size_t rc;
struct OutStruct *outs = userdata;
struct Configurable *config = outs->config;
const size_t failure = (sz * nmemb) ? 0 : 1;
if(!config)
return failure;
#ifdef DEBUGBUILD
if(config->include_headers) {
if(sz * nmemb > (size_t)CURL_MAX_HTTP_HEADER) {
warnf(config, "Header data size exceeds single call write limit!\n");
return failure;
}
}
else {
if(sz * nmemb > (size_t)CURL_MAX_WRITE_SIZE) {
warnf(config, "Data size exceeds single call write limit!\n");
return failure;
}
}
{
bool check_fails = FALSE;
if(outs->filename) {
if(!*outs->filename)
check_fails = TRUE;
if(!outs->s_isreg)
check_fails = TRUE;
if(outs->fopened && !outs->stream)
check_fails = TRUE;
if(!outs->fopened && outs->stream)
check_fails = TRUE;
if(!outs->fopened && outs->bytes)
check_fails = TRUE;
}
else {
if(!outs->stream || outs->s_isreg || outs->fopened)
check_fails = TRUE;
if(outs->alloc_filename || outs->init)
check_fails = TRUE;
}
if(check_fails) {
warnf(config, "Invalid output struct data for write callback\n");
return failure;
}
}
#endif
if(!outs->stream) {
FILE *file;
if(!outs->filename || !*outs->filename) {
warnf(config, "Remote filename has no length!\n");
return failure;
}
if(config->content_disposition) {
file = fopen(outs->filename, "rb");
if(file) {
fclose(file);
warnf(config, "Refusing to overwrite %s: %s\n", outs->filename,
strerror(EEXIST));
return failure;
}
}
file = fopen(outs->filename, "wb");
if(!file) {
warnf(config, "Failed to create the file %s: %s\n", outs->filename,
strerror(errno));
return failure;
}
outs->s_isreg = TRUE;
outs->fopened = TRUE;
outs->stream = file;
outs->bytes = 0;
outs->init = 0;
}
rc = fwrite(buffer, sz, nmemb, outs->stream);
if((sz * nmemb) == rc)
outs->bytes += (sz * nmemb);
if(config->readbusy) {
config->readbusy = FALSE;
curl_easy_pause(config->easy, CURLPAUSE_CONT);
}
if(config->nobuffer) {
int res = fflush(outs->stream);
if(res)
return failure;
}
return rc;
}