curl tool: reviewed code moved to tool_*.[ch] files

This commit is contained in:
Yang Tse 2011-09-24 17:38:16 +02:00
parent 8bab6700d9
commit c6702c7d3f
19 changed files with 1218 additions and 632 deletions

View File

@ -11,6 +11,13 @@ SOURCE \
main.c hugehelp.c urlglob.c writeout.c writeenv.c \
getpass.c homedir.c curlutil.c xattr.c \
tool_bname.c \
tool_cb_dbg.c \
tool_cb_hdr.c \
tool_cb_prg.c \
tool_cb_rea.c \
tool_cb_see.c \
tool_cb_skt.c \
tool_cb_wrt.c \
tool_cfgable.c \
tool_convert.c \
tool_dirhie.c \
@ -20,7 +27,6 @@ SOURCE \
tool_mfiles.c \
tool_msgs.c \
tool_myfunc.c \
tool_progress.c \
tool_setopt.c \
tool_vms.c

View File

@ -17,6 +17,13 @@ CURLX_ONES = $(top_srcdir)/lib/strtoofft.c \
CURL_CFILES = main.c hugehelp.c urlglob.c writeout.c writeenv.c \
getpass.c homedir.c curlutil.c xattr.c \
tool_bname.c \
tool_cb_dbg.c \
tool_cb_hdr.c \
tool_cb_prg.c \
tool_cb_rea.c \
tool_cb_see.c \
tool_cb_skt.c \
tool_cb_wrt.c \
tool_cfgable.c \
tool_convert.c \
tool_dirhie.c \
@ -26,7 +33,6 @@ CURL_CFILES = main.c hugehelp.c urlglob.c writeout.c writeenv.c \
tool_mfiles.c \
tool_msgs.c \
tool_myfunc.c \
tool_progress.c \
tool_setopt.c \
tool_vms.c
@ -34,6 +40,13 @@ CURL_HFILES = hugehelp.h setup.h config-win32.h config-mac.h \
config-riscos.h urlglob.h version.h xattr.h \
writeout.h writeenv.h getpass.h homedir.h curlutil.h \
tool_bname.h \
tool_cb_dbg.h \
tool_cb_hdr.h \
tool_cb_prg.h \
tool_cb_rea.h \
tool_cb_see.h \
tool_cb_skt.h \
tool_cb_wrt.h \
tool_cfgable.h \
tool_convert.h \
tool_dirhie.h \
@ -43,7 +56,6 @@ CURL_HFILES = hugehelp.h setup.h config-win32.h config-mac.h \
tool_mfiles.h \
tool_msgs.h \
tool_myfunc.h \
tool_progress.h \
tool_sdecls.h \
tool_setopt.h \
tool_vms.h

View File

@ -142,6 +142,13 @@ RELEASE_OBJS= \
rawstrr.obj \
strtoofftr.obj \
tool_bnamer.obj \
tool_cb_dbgr.obj \
tool_cb_hdrr.obj \
tool_cb_prgr.obj \
tool_cb_rear.obj \
tool_cb_seer.obj \
tool_cb_sktr.obj \
tool_cb_wrtr.obj \
tool_cfgabler.obj \
tool_convertr.obj \
tool_dirhier.obj \
@ -151,7 +158,6 @@ RELEASE_OBJS= \
tool_mfilesr.obj \
tool_msgsr.obj \
tool_myfuncr.obj \
tool_progressr.obj \
tool_setoptr.obj \
tool_vmsr.obj \
urlglobr.obj \
@ -169,6 +175,13 @@ DEBUG_OBJS= \
rawstrd.obj \
strtoofftd.obj \
tool_bnamed.obj \
tool_cb_dbgd.obj \
tool_cb_hdrd.obj \
tool_cb_prgd.obj \
tool_cb_read.obj \
tool_cb_seed.obj \
tool_cb_sktd.obj \
tool_cb_wrtd.obj \
tool_cfgabled.obj \
tool_convertd.obj \
tool_dirhied.obj \
@ -178,7 +191,6 @@ DEBUG_OBJS= \
tool_mfilesd.obj \
tool_msgsd.obj \
tool_myfuncd.obj \
tool_progressd.obj \
tool_setoptd.obj \
tool_vmsd.obj \
urlglobd.obj \
@ -326,6 +338,20 @@ strtoofftr.obj: ../lib/strtoofft.c
$(CCR) $(CFLAGS) /Fo"$@" ../lib/strtoofft.c
tool_bnamer.obj: tool_bname.c
$(CCR) $(CFLAGS) /Fo"$@" tool_bname.c
tool_cb_dbgr.obj: tool_cb_dbg.c
$(CCR) $(CFLAGS) /Fo"$@" tool_cb_dbg.c
tool_cb_hdrr.obj: tool_cb_hdr.c
$(CCR) $(CFLAGS) /Fo"$@" tool_cb_hdr.c
tool_cb_prgr.obj: tool_cb_prg.c
$(CCR) $(CFLAGS) /Fo"$@" tool_cb_prg.c
tool_cb_rear.obj: tool_cb_rea.c
$(CCR) $(CFLAGS) /Fo"$@" tool_cb_rea.c
tool_cb_seer.obj: tool_cb_see.c
$(CCR) $(CFLAGS) /Fo"$@" tool_cb_see.c
tool_cb_sktr.obj: tool_cb_skt.c
$(CCR) $(CFLAGS) /Fo"$@" tool_cb_skt.c
tool_cb_wrtr.obj: tool_cb_wrt.c
$(CCR) $(CFLAGS) /Fo"$@" tool_cb_wrt.c
tool_cfgabler.obj: tool_cfgable.c
$(CCR) $(CFLAGS) /Fo"$@" tool_cfgable.c
tool_convertr.obj: tool_convert.c
@ -344,8 +370,6 @@ tool_msgsr.obj: tool_msgs.c
$(CCR) $(CFLAGS) /Fo"$@" tool_msgs.c
tool_myfuncr.obj: tool_myfunc.c
$(CCR) $(CFLAGS) /Fo"$@" tool_myfunc.c
tool_progressr.obj: tool_progress.c
$(CCR) $(CFLAGS) /Fo"$@" tool_progress.c
tool_setoptr.obj: tool_setopt.c
$(CCR) $(CFLAGS) /Fo"$@" tool_setopt.c
tool_vmsr.obj: tool_vms.c
@ -378,6 +402,20 @@ strtoofftd.obj: ../lib/strtoofft.c
$(CCD) $(CFLAGS) /Fo"$@" ../lib/strtoofft.c
tool_bnamed.obj: tool_bname.c
$(CCD) $(CFLAGS) /Fo"$@" tool_bname.c
tool_cb_dbgd.obj: tool_cb_dbg.c
$(CCD) $(CFLAGS) /Fo"$@" tool_cb_dbg.c
tool_cb_hdrd.obj: tool_cb_hdr.c
$(CCD) $(CFLAGS) /Fo"$@" tool_cb_hdr.c
tool_cb_prgd.obj: tool_cb_prg.c
$(CCD) $(CFLAGS) /Fo"$@" tool_cb_prg.c
tool_cb_read.obj: tool_cb_rea.c
$(CCD) $(CFLAGS) /Fo"$@" tool_cb_rea.c
tool_cb_seed.obj: tool_cb_see.c
$(CCD) $(CFLAGS) /Fo"$@" tool_cb_see.c
tool_cb_sktd.obj: tool_cb_skt.c
$(CCD) $(CFLAGS) /Fo"$@" tool_cb_skt.c
tool_cb_wrtd.obj: tool_cb_wrt.c
$(CCD) $(CFLAGS) /Fo"$@" tool_cb_wrt.c
tool_cfgabled.obj: tool_cfgable.c
$(CCD) $(CFLAGS) /Fo"$@" tool_cfgable.c
tool_convertd.obj: tool_convert.c
@ -396,8 +434,6 @@ tool_msgsd.obj: tool_msgs.c
$(CCD) $(CFLAGS) /Fo"$@" tool_msgs.c
tool_myfuncd.obj: tool_myfunc.c
$(CCD) $(CFLAGS) /Fo"$@" tool_myfunc.c
tool_progressd.obj: tool_progress.c
$(CCD) $(CFLAGS) /Fo"$@" tool_progress.c
tool_setoptd.obj: tool_setopt.c
$(CCD) $(CFLAGS) /Fo"$@" tool_setopt.c
tool_vmsd.obj: tool_vms.c

View File

@ -102,9 +102,17 @@
#include "tool_mfiles.h"
#include "tool_msgs.h"
#include "tool_myfunc.h"
#include "tool_progress.h"
#include "tool_cb_prg.h"
#include "tool_setopt.h"
#include "tool_vms.h"
#include "tool_cb_rea.h"
#include "tool_cb_wrt.h"
#include "tool_cb_see.h"
#include "tool_cb_skt.h"
#include "tool_cb_hdr.h"
#include "tool_cb_dbg.h"
#ifdef USE_MANUAL
# include "hugehelp.h"
#endif
@ -230,44 +238,6 @@ char **__crt0_glob_function (char *arg)
"If you'd like to turn off curl's verification of the certificate, use\n" \
" the -k (or --insecure) option.\n"
#if defined(WIN32) && !defined(__MINGW64__)
#ifdef __BORLANDC__
/* 64-bit lseek-like function unavailable */
# define _lseeki64(hnd,ofs,whence) lseek(hnd,ofs,whence)
#endif
#ifdef __POCC__
# if(__POCC__ < 450)
/* 64-bit lseek-like function unavailable */
# define _lseeki64(hnd,ofs,whence) _lseek(hnd,ofs,whence)
# else
# define _lseeki64(hnd,ofs,whence) _lseek64(hnd,ofs,whence)
# endif
#endif
#ifndef HAVE_FTRUNCATE
#define HAVE_FTRUNCATE 1
#endif
/*
* Truncate a file handle at a 64-bit position 'where'.
*/
static int ftruncate64(int fd, curl_off_t where)
{
if(_lseeki64(fd, where, SEEK_SET) < 0)
return -1;
if(!SetEndOfFile((HANDLE)_get_osfhandle(fd)))
return -1;
return 0;
}
#define ftruncate(fd,where) ftruncate64(fd,where)
#endif /* WIN32 */
/*
* This is the main global constructor for the app. Call this before
* _any_ libcurl usage. If this fails, *NO* libcurl functions may be
@ -1210,60 +1180,6 @@ static int ftpcccmethod(struct Configurable *config, const char *str)
return CURLFTPSSL_CCC_PASSIVE;
}
static int sockoptcallback(void *clientp, curl_socket_t curlfd,
curlsocktype purpose)
{
struct Configurable *config = (struct Configurable *)clientp;
int onoff = 1; /* this callback is only used if we ask for keepalives on the
connection */
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPINTVL)
int keepidle = (int)config->alivetime;
#endif
switch(purpose) {
case CURLSOCKTYPE_IPCXN:
if(setsockopt(curlfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&onoff,
sizeof(onoff)) < 0) {
/* don't abort operation, just issue a warning */
SET_SOCKERRNO(0);
warnf(clientp, "Could not set SO_KEEPALIVE!\n");
return 0;
}
else {
if(config->alivetime) {
#ifdef TCP_KEEPIDLE
if(setsockopt(curlfd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&keepidle,
sizeof(keepidle)) < 0) {
/* don't abort operation, just issue a warning */
SET_SOCKERRNO(0);
warnf(clientp, "Could not set TCP_KEEPIDLE!\n");
return 0;
}
#endif
#ifdef TCP_KEEPINTVL
if(setsockopt(curlfd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&keepidle,
sizeof(keepidle)) < 0) {
/* don't abort operation, just issue a warning */
SET_SOCKERRNO(0);
warnf(clientp, "Could not set TCP_KEEPINTVL!\n");
return 0;
}
#endif
#if !defined(TCP_KEEPIDLE) || !defined(TCP_KEEPINTVL)
warnf(clientp, "Keep-alive functionality somewhat crippled due to "
"missing support in your operating system!\n");
#endif
}
}
break;
default:
break;
}
return 0;
}
static long delegation(struct Configurable *config,
char *str)
{
@ -3045,369 +2961,6 @@ static void go_sleep(long ms)
#endif
}
static size_t my_fwrite(void *buffer, size_t sz, size_t nmemb, void *stream)
{
size_t rc;
struct OutStruct *out=(struct OutStruct *)stream;
struct Configurable *config = out->config;
/*
* Once that libcurl has called back my_fwrite() the returned value
* is checked against the amount that was intended to be written, if
* it does not match then it fails with CURLE_WRITE_ERROR. So at this
* point returning a value different from sz*nmemb indicates failure.
*/
const size_t err_rc = (sz * nmemb) ? 0 : 1;
if(!out->stream) {
out->bytes = 0; /* nothing written yet */
if(!out->filename) {
warnf(config, "Remote filename has no length!\n");
return err_rc; /* Failure */
}
if(config->content_disposition) {
/* don't overwrite existing files */
FILE* f = fopen(out->filename, "r");
if(f) {
fclose(f);
warnf(config, "Refusing to overwrite %s: %s\n", out->filename,
strerror(EEXIST));
return err_rc; /* Failure */
}
}
/* open file for writing */
out->stream=fopen(out->filename, "wb");
if(!out->stream) {
warnf(config, "Failed to create the file %s: %s\n", out->filename,
strerror(errno));
return err_rc; /* failure */
}
}
rc = fwrite(buffer, sz, nmemb, out->stream);
if((sz * nmemb) == rc)
/* we added this amount of data to the output */
out->bytes += (sz * nmemb);
if(config->readbusy) {
config->readbusy = FALSE;
curl_easy_pause(config->easy, CURLPAUSE_CONT);
}
if(config->nobuffer) {
/* disable output buffering */
int res = fflush(out->stream);
if(res) {
/* return a value that isn't the same as sz * nmemb */
return err_rc; /* failure */
}
}
return rc;
}
#define MAX_SEEK 2147483647
/*
* my_seek() is the CURLOPT_SEEKFUNCTION we use
*/
static int my_seek(void *stream, curl_off_t offset, int whence)
{
struct InStruct *in=(struct InStruct *)stream;
#if(CURL_SIZEOF_CURL_OFF_T > SIZEOF_OFF_T) && !defined(USE_WIN32_LARGE_FILES)
/* The offset check following here is only interesting if curl_off_t is
larger than off_t and we are not using the WIN32 large file support
macros that provide the support to do 64bit seeks correctly */
if(offset > MAX_SEEK) {
/* Some precaution code to work around problems with different data sizes
to allow seeking >32bit even if off_t is 32bit. Should be very rare and
is really valid on weirdo-systems. */
curl_off_t left = offset;
if(whence != SEEK_SET)
/* this code path doesn't support other types */
return 1;
if(LSEEK_ERROR == lseek(in->fd, 0, SEEK_SET))
/* couldn't rewind to beginning */
return 1;
while(left) {
long step = (left>MAX_SEEK ? MAX_SEEK : (long)left);
if(LSEEK_ERROR == lseek(in->fd, step, SEEK_CUR))
/* couldn't seek forwards the desired amount */
return 1;
left -= step;
}
return 0;
}
#endif
if(LSEEK_ERROR == lseek(in->fd, offset, whence))
/* couldn't rewind, the reason is in errno but errno is just not portable
enough and we don't actually care that much why we failed. We'll let
libcurl know that it may try other means if it wants to. */
return CURL_SEEKFUNC_CANTSEEK;
return 0;
}
static size_t my_fread(void *buffer, size_t sz, size_t nmemb, void *userp)
{
ssize_t rc;
struct InStruct *in=(struct InStruct *)userp;
rc = read(in->fd, buffer, sz*nmemb);
if(rc < 0) {
if(errno == EAGAIN) {
errno = 0;
in->config->readbusy = TRUE;
return CURL_READFUNC_PAUSE;
}
/* since size_t is unsigned we can't return negative values fine */
rc = 0;
}
in->config->readbusy = FALSE;
return (size_t)rc;
}
static
void dump(const char *timebuf, const char *text,
FILE *stream, const unsigned char *ptr, size_t size,
trace tracetype, curl_infotype infotype)
{
size_t i;
size_t c;
unsigned int width=0x10;
if(tracetype == TRACE_ASCII)
/* without the hex output, we can fit more on screen */
width = 0x40;
fprintf(stream, "%s%s, %zd bytes (0x%zx)\n", timebuf, text, size, size);
for(i=0; i<size; i+= width) {
fprintf(stream, "%04zx: ", i);
if(tracetype == TRACE_BIN) {
/* hex not disabled, show it */
for(c = 0; c < width; c++)
if(i+c < size)
fprintf(stream, "%02x ", ptr[i+c]);
else
fputs(" ", stream);
}
for(c = 0; (c < width) && (i+c < size); c++) {
/* check for 0D0A; if found, skip past and start a new line of output */
if((tracetype == TRACE_ASCII) &&
(i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
i+=(c+2-width);
break;
}
#ifdef CURL_DOES_CONVERSIONS
/* repeat the 0D0A check above but use the host encoding for CRLF */
if((tracetype == TRACE_ASCII) &&
(i+c+1 < size) && ptr[i+c]=='\r' && ptr[i+c+1]=='\n') {
i+=(c+2-width);
break;
}
/* convert to host encoding and print this character */
fprintf(stream, "%c", convert_char(infotype, ptr[i+c]));
#else
(void)infotype;
fprintf(stream, "%c",
(ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:UNPRINTABLE_CHAR);
#endif /* CURL_DOES_CONVERSIONS */
/* check again for 0D0A, to avoid an extra \n if it's at width */
if((tracetype == TRACE_ASCII) &&
(i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
i+=(c+3-width);
break;
}
}
fputc('\n', stream); /* newline */
}
fflush(stream);
}
static
int my_trace(CURL *handle, curl_infotype type,
unsigned char *data, size_t size,
void *userp)
{
struct Configurable *config = (struct Configurable *)userp;
FILE *output=config->errors;
const char *text;
struct timeval tv;
struct tm *now;
char timebuf[20];
time_t secs;
static time_t epoch_offset;
static int known_offset;
(void)handle; /* prevent compiler warning */
if(config->tracetime) {
tv = cutil_tvnow();
if(!known_offset) {
epoch_offset = time(NULL) - tv.tv_sec;
known_offset = 1;
}
secs = epoch_offset + tv.tv_sec;
now = localtime(&secs); /* not thread safe but we don't care */
snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld ",
now->tm_hour, now->tm_min, now->tm_sec, (long)tv.tv_usec);
}
else
timebuf[0]=0;
if(!config->trace_stream) {
/* open for append */
if(curlx_strequal("-", config->trace_dump))
config->trace_stream = stdout;
else if(curlx_strequal("%", config->trace_dump))
/* Ok, this is somewhat hackish but we do it undocumented for now */
config->trace_stream = config->errors; /* aka stderr */
else {
config->trace_stream = fopen(config->trace_dump, "w");
config->trace_fopened = TRUE;
}
}
if(config->trace_stream)
output = config->trace_stream;
if(!output) {
warnf(config, "Failed to create/open output");
return 0;
}
if(config->tracetype == TRACE_PLAIN) {
/*
* This is the trace look that is similar to what libcurl makes on its
* own.
*/
static const char * const s_infotype[] = {
"*", "<", ">", "{", "}", "{", "}"
};
size_t i;
size_t st=0;
static bool newl = FALSE;
static bool traced_data = FALSE;
switch(type) {
case CURLINFO_HEADER_OUT:
for(i=0; i<size-1; i++) {
if(data[i] == '\n') { /* LF */
if(!newl) {
fprintf(output, "%s%s ", timebuf, s_infotype[type]);
}
(void)fwrite(data+st, i-st+1, 1, output);
st = i+1;
newl = FALSE;
}
}
if(!newl)
fprintf(output, "%s%s ", timebuf, s_infotype[type]);
(void)fwrite(data+st, i-st+1, 1, output);
newl = (size && (data[size-1] != '\n'))?TRUE:FALSE;
traced_data = FALSE;
break;
case CURLINFO_TEXT:
case CURLINFO_HEADER_IN:
if(!newl)
fprintf(output, "%s%s ", timebuf, s_infotype[type]);
(void)fwrite(data, size, 1, output);
newl = (size && (data[size-1] != '\n'))?TRUE:FALSE;
traced_data = FALSE;
break;
case CURLINFO_DATA_OUT:
case CURLINFO_DATA_IN:
case CURLINFO_SSL_DATA_IN:
case CURLINFO_SSL_DATA_OUT:
if(!traced_data) {
/* if the data is output to a tty and we're sending this debug trace
to stderr or stdout, we don't display the alert about the data not
being shown as the data _is_ shown then just not via this
function */
if(!config->isatty ||
((output != stderr) && (output != stdout))) {
if(!newl)
fprintf(output, "%s%s ", timebuf, s_infotype[type]);
fprintf(output, "[data not shown]\n");
newl = FALSE;
traced_data = TRUE;
}
}
break;
default: /* nada */
newl = FALSE;
traced_data = FALSE;
break;
}
return 0;
}
#ifdef CURL_DOES_CONVERSIONS
/* Special processing is needed for CURLINFO_HEADER_OUT blocks
* if they contain both headers and data (separated by CRLFCRLF).
* We dump the header text and then switch type to CURLINFO_DATA_OUT.
*/
if((type == CURLINFO_HEADER_OUT) && (size > 4)) {
size_t i;
for(i = 0; i < size - 4; i++) {
if(memcmp(&data[i], "\r\n\r\n", 4) == 0) {
/* dump everything through the CRLFCRLF as a sent header */
text = "=> Send header";
dump(timebuf, text, output, data, i+4, config->tracetype, type);
data += i + 3;
size -= i + 4;
type = CURLINFO_DATA_OUT;
data += 1;
break;
}
}
}
#endif /* CURL_DOES_CONVERSIONS */
switch (type) {
case CURLINFO_TEXT:
fprintf(output, "%s== Info: %s", timebuf, data);
default: /* in case a new one is introduced to shock us */
return 0;
case CURLINFO_HEADER_OUT:
text = "=> Send header";
break;
case CURLINFO_DATA_OUT:
text = "=> Send data";
break;
case CURLINFO_HEADER_IN:
text = "<= Recv header";
break;
case CURLINFO_DATA_IN:
text = "<= Recv data";
break;
case CURLINFO_SSL_DATA_IN:
text = "<= Recv SSL data";
break;
case CURLINFO_SSL_DATA_OUT:
text = "=> Send SSL data";
break;
}
dump(timebuf, text, output, data, size, config->tracetype, type);
return 0;
}
#define RETRY_SLEEP_DEFAULT 1000L /* ms */
#define RETRY_SLEEP_MAX 600000L /* ms == 10 minutes */
@ -3505,147 +3058,6 @@ static char *get_url_file_name(const char *url)
return fn;
}
/*
* Copies a file name part and returns an ALLOCATED data buffer.
*/
static char*
parse_filename(char *ptr, size_t len)
{
char* copy;
char* p;
char* q;
char stop = 0;
/* simple implementation of strndup() */
copy = malloc(len+1);
if(!copy)
return NULL;
memcpy(copy, ptr, len);
copy[len] = 0;
p = copy;
if(*p == '\'' || *p == '"') {
/* store the starting quote */
stop = *p;
p++;
}
else
stop = ';';
/* if the filename contains a path, only use filename portion */
q = strrchr(copy, '/');
if(q) {
p=q+1;
if(!*p) {
Curl_safefree(copy);
return NULL;
}
}
/* If the filename contains a backslash, only use filename portion. The idea
is that even systems that don't handle backslashes as path separators
probably want the path removed for convenience. */
q = strrchr(p, '\\');
if(q) {
p = q+1;
if(!*p) {
Curl_safefree(copy);
return NULL;
}
}
/* scan for the end letter and stop there */
q = p;
while(*q) {
if(q[1] && q[0]=='\\')
q++;
else if(q[0] == stop)
break;
q++;
}
*q = 0;
/* make sure the file name doesn't end in \r or \n */
q = strchr(p, '\r');
if(q)
*q = 0;
q = strchr(p, '\n');
if(q)
*q = 0;
if(copy!=p)
memmove(copy, p, strlen(p)+1);
/* in case we built curl debug enabled, we allow an evironment variable
* named CURL_TESTDIR to prefix the given file name to put it into a
* specific directory
*/
#ifdef CURLDEBUG
{
char *tdir = curlx_getenv("CURL_TESTDIR");
if(tdir) {
char buffer[512]; /* suitably large */
snprintf(buffer, sizeof(buffer), "%s/%s", tdir, copy);
Curl_safefree(copy);
copy = strdup(buffer); /* clone the buffer, we don't use the libcurl
aprintf() or similar since we want to use the
same memory code as the "real" parse_filename
function */
curl_free(tdir);
}
}
#endif
return copy;
}
static size_t
header_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
struct OutStruct* outs = (struct OutStruct*)stream;
const char* str = (char*)ptr;
const size_t cb = size*nmemb;
const char* end = (char*)ptr + cb;
if(cb > 20 && checkprefix("Content-disposition:", str)) {
char *p = (char*)str + 20;
/* look for the 'filename=' parameter
(encoded filenames (*=) are not supported) */
for(;;) {
char *filename;
size_t len;
while(*p && (p < end) && !ISALPHA(*p))
p++;
if(p > end-9)
break;
if(memcmp(p, "filename=", 9)) {
/* no match, find next parameter */
while((p < end) && (*p != ';'))
p++;
continue;
}
p+=9;
/* this expression below typecasts 'cb' only to avoid
warning: signed and unsigned type in conditional expression
*/
len = (ssize_t)cb - (p - str);
filename = parse_filename(p, len);
if(filename) {
outs->filename = filename;
outs->alloc_filename = TRUE;
break;
}
}
}
return cb;
}
#ifdef CURLDEBUG
static void memory_tracking_init(void)
{
@ -4322,7 +3734,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
/* where to store */
my_setopt(curl, CURLOPT_WRITEDATA, &outs);
/* what call to write */
my_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb);
/* for uploads */
input.fd = infd;
@ -4331,12 +3743,12 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
/* what call to read */
if((outfile && !curlx_strequal("-", outfile)) ||
!checkprefix("telnet:", this_url))
my_setopt(curl, CURLOPT_READFUNCTION, my_fread);
my_setopt(curl, CURLOPT_READFUNCTION, tool_read_cb);
/* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what
CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */
my_setopt(curl, CURLOPT_SEEKDATA, &input);
my_setopt(curl, CURLOPT_SEEKFUNCTION, my_seek);
my_setopt(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb);
if(config->recvpersecond)
/* tell libcurl to use a smaller sized buffer as it allows us to
@ -4581,7 +3993,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
!config->noprogress && !config->mute) {
/* we want the alternative style, then we have to implement it
ourselves! */
my_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress);
my_setopt(curl, CURLOPT_PROGRESSFUNCTION, tool_progress_cb);
my_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar);
}
@ -4607,7 +4019,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
my_setopt(curl, CURLOPT_FTP_USE_EPRT, FALSE);
if(config->tracetype != TRACE_NONE) {
my_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
my_setopt(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb);
my_setopt(curl, CURLOPT_DEBUGDATA, config);
my_setopt(curl, CURLOPT_VERBOSE, TRUE);
}
@ -4702,7 +4114,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
/* curl 7.17.1 */
if(!config->nokeepalive) {
my_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockoptcallback);
my_setopt(curl, CURLOPT_SOCKOPTFUNCTION, tool_sockopt_cb);
my_setopt(curl, CURLOPT_SOCKOPTDATA, config);
}
@ -4727,7 +4139,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
if((urlnode->flags & GETOUT_USEREMOTE)
&& config->content_disposition) {
my_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);
my_setopt(curl, CURLOPT_HEADERFUNCTION, tool_header_cb);
my_setopt(curl, CURLOPT_HEADERDATA, &outs);
}
else {
@ -5045,6 +4457,8 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
Curl_safefree(urlnode->infile);
urlnode->flags = 0;
/* TODO: Should CURLE_SSL_CACERT be included as critical error ? */
/*
** Bail out upon critical errors
*/

276
src/tool_cb_dbg.c Normal file
View File

@ -0,0 +1,276 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "setup.h"
#include <curl/curl.h>
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
#include "curlx.h"
#include "curlutil.h"
#include "tool_cfgable.h"
#include "tool_msgs.h"
#include "tool_cb_dbg.h"
#include "memdebug.h" /* keep this as LAST include */
static void dump(const char *timebuf, const char *text,
FILE *stream, const unsigned char *ptr, size_t size,
trace tracetype, curl_infotype infotype);
/*
** callback for CURLOPT_DEBUGFUNCTION
*/
int tool_debug_cb(CURL *handle, curl_infotype type,
unsigned char *data, size_t size,
void *userdata)
{
struct Configurable *config = userdata;
FILE *output = config->errors;
const char *text;
struct timeval tv;
struct tm *now;
char timebuf[20];
time_t secs;
static time_t epoch_offset;
static int known_offset;
(void)handle; /* not used */
if(config->tracetime) {
tv = cutil_tvnow();
if(!known_offset) {
epoch_offset = time(NULL) - tv.tv_sec;
known_offset = 1;
}
secs = epoch_offset + tv.tv_sec;
now = localtime(&secs); /* not thread safe but we don't care */
snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld ",
now->tm_hour, now->tm_min, now->tm_sec, (long)tv.tv_usec);
}
else
timebuf[0] = 0;
if(!config->trace_stream) {
/* open for append */
if(curlx_strequal("-", config->trace_dump))
config->trace_stream = stdout;
else if(curlx_strequal("%", config->trace_dump))
/* Ok, this is somewhat hackish but we do it undocumented for now */
config->trace_stream = config->errors; /* aka stderr */
else {
config->trace_stream = fopen(config->trace_dump, "w");
config->trace_fopened = TRUE;
}
}
if(config->trace_stream)
output = config->trace_stream;
if(!output) {
warnf(config, "Failed to create/open output");
return 0;
}
if(config->tracetype == TRACE_PLAIN) {
/*
* This is the trace look that is similar to what libcurl makes on its
* own.
*/
static const char * const s_infotype[] = {
"*", "<", ">", "{", "}", "{", "}"
};
size_t i;
size_t st = 0;
static bool newl = FALSE;
static bool traced_data = FALSE;
switch(type) {
case CURLINFO_HEADER_OUT:
for(i = 0; i < size - 1; i++) {
if(data[i] == '\n') { /* LF */
if(!newl) {
fprintf(output, "%s%s ", timebuf, s_infotype[type]);
}
(void)fwrite(data + st, i - st + 1, 1, output);
st = i + 1;
newl = FALSE;
}
}
if(!newl)
fprintf(output, "%s%s ", timebuf, s_infotype[type]);
(void)fwrite(data + st, i - st + 1, 1, output);
newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE;
traced_data = FALSE;
break;
case CURLINFO_TEXT:
case CURLINFO_HEADER_IN:
if(!newl)
fprintf(output, "%s%s ", timebuf, s_infotype[type]);
(void)fwrite(data, size, 1, output);
newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE;
traced_data = FALSE;
break;
case CURLINFO_DATA_OUT:
case CURLINFO_DATA_IN:
case CURLINFO_SSL_DATA_IN:
case CURLINFO_SSL_DATA_OUT:
if(!traced_data) {
/* if the data is output to a tty and we're sending this debug trace
to stderr or stdout, we don't display the alert about the data not
being shown as the data _is_ shown then just not via this
function */
if(!config->isatty ||
((output != stderr) && (output != stdout))) {
if(!newl)
fprintf(output, "%s%s ", timebuf, s_infotype[type]);
fprintf(output, "[data not shown]\n");
newl = FALSE;
traced_data = TRUE;
}
}
break;
default: /* nada */
newl = FALSE;
traced_data = FALSE;
break;
}
return 0;
}
#ifdef CURL_DOES_CONVERSIONS
/* Special processing is needed for CURLINFO_HEADER_OUT blocks
* if they contain both headers and data (separated by CRLFCRLF).
* We dump the header text and then switch type to CURLINFO_DATA_OUT.
*/
if((type == CURLINFO_HEADER_OUT) && (size > 4)) {
size_t i;
for(i = 0; i < size - 4; i++) {
if(memcmp(&data[i], "\r\n\r\n", 4) == 0) {
/* dump everything through the CRLFCRLF as a sent header */
text = "=> Send header";
dump(timebuf, text, output, data, i + 4, config->tracetype, type);
data += i + 3;
size -= i + 4;
type = CURLINFO_DATA_OUT;
data += 1;
break;
}
}
}
#endif /* CURL_DOES_CONVERSIONS */
switch (type) {
case CURLINFO_TEXT:
fprintf(output, "%s== Info: %s", timebuf, data);
default: /* in case a new one is introduced to shock us */
return 0;
case CURLINFO_HEADER_OUT:
text = "=> Send header";
break;
case CURLINFO_DATA_OUT:
text = "=> Send data";
break;
case CURLINFO_HEADER_IN:
text = "<= Recv header";
break;
case CURLINFO_DATA_IN:
text = "<= Recv data";
break;
case CURLINFO_SSL_DATA_IN:
text = "<= Recv SSL data";
break;
case CURLINFO_SSL_DATA_OUT:
text = "=> Send SSL data";
break;
}
dump(timebuf, text, output, data, size, config->tracetype, type);
return 0;
}
static void dump(const char *timebuf, const char *text,
FILE *stream, const unsigned char *ptr, size_t size,
trace tracetype, curl_infotype infotype)
{
size_t i;
size_t c;
unsigned int width = 0x10;
if(tracetype == TRACE_ASCII)
/* without the hex output, we can fit more on screen */
width = 0x40;
fprintf(stream, "%s%s, %zd bytes (0x%zx)\n", timebuf, text, size, size);
for(i = 0; i < size; i += width) {
fprintf(stream, "%04zx: ", i);
if(tracetype == TRACE_BIN) {
/* hex not disabled, show it */
for(c = 0; c < width; c++)
if(i+c < size)
fprintf(stream, "%02x ", ptr[i+c]);
else
fputs(" ", stream);
}
for(c = 0; (c < width) && (i+c < size); c++) {
/* check for 0D0A; if found, skip past and start a new line of output */
if((tracetype == TRACE_ASCII) &&
(i+c+1 < size) && (ptr[i+c] == 0x0D) && (ptr[i+c+1] == 0x0A)) {
i += (c+2-width);
break;
}
#ifdef CURL_DOES_CONVERSIONS
/* repeat the 0D0A check above but use the host encoding for CRLF */
if((tracetype == TRACE_ASCII) &&
(i+c+1 < size) && (ptr[i+c] == '\r') && (ptr[i+c+1] == '\n')) {
i += (c+2-width);
break;
}
/* convert to host encoding and print this character */
fprintf(stream, "%c", convert_char(infotype, ptr[i+c]));
#else
(void)infotype;
fprintf(stream, "%c", ((ptr[i+c] >= 0x20) && (ptr[i+c] < 0x80)) ?
ptr[i+c] : UNPRINTABLE_CHAR);
#endif /* CURL_DOES_CONVERSIONS */
/* check again for 0D0A, to avoid an extra \n if it's at width */
if((tracetype == TRACE_ASCII) &&
(i+c+2 < size) && (ptr[i+c+1] == 0x0D) && (ptr[i+c+2] == 0x0A)) {
i += (c+3-width);
break;
}
}
fputc('\n', stream); /* newline */
}
fflush(stream);
}

35
src/tool_cb_dbg.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef HEADER_CURL_TOOL_CB_DBG_H
#define HEADER_CURL_TOOL_CB_DBG_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "setup.h"
/*
** callback for CURLOPT_DEBUGFUNCTION
*/
int tool_debug_cb(CURL *handle, curl_infotype type,
unsigned char *data, size_t size,
void *userdata);
#endif /* HEADER_CURL_TOOL_CB_DBG_H */

182
src/tool_cb_hdr.c Normal file
View File

@ -0,0 +1,182 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "setup.h"
#include <curl/curl.h>
#include "rawstr.h"
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
#include "curlx.h"
#include "tool_cfgable.h"
#include "tool_cb_hdr.h"
#include "memdebug.h" /* keep this as LAST include */
static char *parse_filename(const char *ptr, size_t len);
/*
** callback for CURLOPT_HEADERFUNCTION
*/
size_t tool_header_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
{
struct OutStruct *outs = userdata;
const char *str = ptr;
const size_t cb = size * nmemb;
const char *end = (char*)ptr + cb;
if(cb > 20 && checkprefix("Content-disposition:", str)) {
const char *p = str + 20;
/* look for the 'filename=' parameter
(encoded filenames (*=) are not supported) */
for(;;) {
char *filename;
size_t len;
while(*p && (p < end) && !ISALPHA(*p))
p++;
if(p > end - 9)
break;
if(memcmp(p, "filename=", 9)) {
/* no match, find next parameter */
while((p < end) && (*p != ';'))
p++;
continue;
}
p += 9;
/* this expression below typecasts 'cb' only to avoid
warning: signed and unsigned type in conditional expression
*/
len = (ssize_t)cb - (p - str);
filename = parse_filename(p, len);
/* TODO: OOM handling - return (size_t)-1 ? */
if(filename) {
outs->filename = filename;
outs->alloc_filename = TRUE;
break;
}
}
}
return cb;
}
/*
* Copies a file name part and returns an ALLOCATED data buffer.
*/
static char *parse_filename(const char *ptr, size_t len)
{
char *copy;
char *p;
char *q;
char stop = '\0';
/* simple implementation of strndup() */
copy = malloc(len+1);
if(!copy)
return NULL;
memcpy(copy, ptr, len);
copy[len] = '\0';
p = copy;
if(*p == '\'' || *p == '"') {
/* store the starting quote */
stop = *p;
p++;
}
else
stop = ';';
/* if the filename contains a path, only use filename portion */
q = strrchr(copy, '/');
if(q) {
p = q + 1;
if(!*p) {
Curl_safefree(copy);
return NULL;
}
}
/* If the filename contains a backslash, only use filename portion. The idea
is that even systems that don't handle backslashes as path separators
probably want the path removed for convenience. */
q = strrchr(p, '\\');
if(q) {
p = q + 1;
if(!*p) {
Curl_safefree(copy);
return NULL;
}
}
/* scan for the end letter and stop there */
q = p;
while(*q) {
if(q[1] && (q[0] == '\\'))
q++;
else if(q[0] == stop)
break;
q++;
}
*q = '\0';
/* make sure the file name doesn't end in \r or \n */
q = strchr(p, '\r');
if(q)
*q = '\0';
q = strchr(p, '\n');
if(q)
*q = '\0';
if(copy != p)
memmove(copy, p, strlen(p) + 1);
/* in case we built curl debug enabled, we allow an evironment variable
* named CURL_TESTDIR to prefix the given file name to put it into a
* specific directory
*/
#ifdef CURLDEBUG
{
char *tdir = curlx_getenv("CURL_TESTDIR");
if(tdir) {
char buffer[512]; /* suitably large */
snprintf(buffer, sizeof(buffer), "%s/%s", tdir, copy);
Curl_safefree(copy);
copy = strdup(buffer); /* clone the buffer, we don't use the libcurl
aprintf() or similar since we want to use the
same memory code as the "real" parse_filename
function */
curl_free(tdir);
}
}
#endif
return copy;
}

33
src/tool_cb_hdr.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef HEADER_CURL_TOOL_CB_HDR_H
#define HEADER_CURL_TOOL_CB_HDR_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "setup.h"
/*
** callback for CURLOPT_HEADERFUNCTION
*/
size_t tool_header_cb(void *ptr, size_t size, size_t nmemb, void *userdata);
#endif /* HEADER_CURL_TOOL_CB_HDR_H */

View File

@ -28,13 +28,17 @@
#include "curlx.h"
#include "tool_cfgable.h"
#include "tool_progress.h"
#include "tool_cb_prg.h"
#include "memdebug.h" /* keep this as LAST include */
int my_progress(void *clientp,
double dltotal, double dlnow,
double ultotal, double ulnow)
/*
** callback for CURLOPT_PROGRESSFUNCTION
*/
int tool_progress_cb(void *clientp,
double dltotal, double dlnow,
double ultotal, double ulnow)
{
/* The original progress-bar source code was written for curl by Lars Aas,
and this new edition inherits some of his concepts. */

View File

@ -1,5 +1,5 @@
#ifndef HEADER_CURL_TOOL_PROGRESS_H
#define HEADER_CURL_TOOL_PROGRESS_H
#ifndef HEADER_CURL_TOOL_CB_PRG_H
#define HEADER_CURL_TOOL_CB_PRG_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@ -34,12 +34,16 @@ struct ProgressData {
curl_off_t initial_size;
};
int my_progress(void *clientp,
double dltotal, double dlnow,
double ultotal, double ulnow);
void progressbarinit(struct ProgressData *bar,
struct Configurable *config);
#endif /* HEADER_CURL_TOOL_PROGRESS_H */
/*
** callback for CURLOPT_PROGRESSFUNCTION
*/
int tool_progress_cb(void *clientp,
double dltotal, double dlnow,
double ultotal, double ulnow);
#endif /* HEADER_CURL_TOOL_CB_PRG_H */

61
src/tool_cb_rea.c Normal file
View File

@ -0,0 +1,61 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "setup.h"
#include <curl/curl.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
#include "curlx.h"
#include "tool_cfgable.h"
#include "tool_cb_rea.h"
#include "memdebug.h" /* keep this as LAST include */
/*
** callback for CURLOPT_READFUNCTION
*/
size_t tool_read_cb(void *buffer, size_t sz, size_t nmemb, void *userdata)
{
ssize_t rc;
struct InStruct *in = userdata;
rc = read(in->fd, buffer, sz*nmemb);
if(rc < 0) {
if(errno == EAGAIN) {
errno = 0;
in->config->readbusy = TRUE;
return CURL_READFUNC_PAUSE;
}
/* since size_t is unsigned we can't return negative values fine */
rc = 0;
}
in->config->readbusy = FALSE;
return (size_t)rc;
}

33
src/tool_cb_rea.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef HEADER_CURL_TOOL_CB_REA_H
#define HEADER_CURL_TOOL_CB_REA_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "setup.h"
/*
** callback for CURLOPT_READFUNCTION
*/
size_t tool_read_cb(void *buffer, size_t sz, size_t nmemb, void *userdata);
#endif /* HEADER_CURL_TOOL_CB_REA_H */

129
src/tool_cb_see.c Normal file
View File

@ -0,0 +1,129 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "setup.h"
#include <curl/curl.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
#include "curlx.h"
#include "tool_cfgable.h"
#include "tool_cb_see.h"
#include "memdebug.h" /* keep this as LAST include */
/* OUR_MAX_SEEK_L has 'long' data type, OUR_MAX_SEEK_O has 'curl_off_t,
both represent the same value. Maximum offset used here when we lseek
using a 'long' data type offset */
#define OUR_MAX_SEEK_L 2147483647L - 1L
#define OUR_MAX_SEEK_O CURL_OFF_T_C(0x7FFFFFFF) - CURL_OFF_T_C(0x1)
/*
** callback for CURLOPT_SEEKFUNCTION
**
** Notice that this is not supposed to return the resulting offset. This
** shall only return CURL_SEEKFUNC_* return codes.
*/
int tool_seek_cb(void *userdata, curl_off_t offset, int whence)
{
struct InStruct *in = userdata;
#if(CURL_SIZEOF_CURL_OFF_T > SIZEOF_OFF_T) && !defined(USE_WIN32_LARGE_FILES)
/* The offset check following here is only interesting if curl_off_t is
larger than off_t and we are not using the WIN32 large file support
macros that provide the support to do 64bit seeks correctly */
if(offset > OUR_MAX_SEEK_O) {
/* Some precaution code to work around problems with different data sizes
to allow seeking >32bit even if off_t is 32bit. Should be very rare and
is really valid on weirdo-systems. */
curl_off_t left = offset;
if(whence != SEEK_SET)
/* this code path doesn't support other types */
return CURL_SEEKFUNC_FAIL;
if(LSEEK_ERROR == lseek(in->fd, 0, SEEK_SET))
/* couldn't rewind to beginning */
return CURL_SEEKFUNC_FAIL;
while(left) {
long step = (left > OUR_MAX_SEEK_O) ? OUR_MAX_SEEK_L : (long)left;
if(LSEEK_ERROR == lseek(in->fd, step, SEEK_CUR))
/* couldn't seek forwards the desired amount */
return CURL_SEEKFUNC_FAIL;
left -= step;
}
return CURL_SEEKFUNC_OK;
}
#endif
if(LSEEK_ERROR == lseek(in->fd, offset, whence))
/* couldn't rewind, the reason is in errno but errno is just not portable
enough and we don't actually care that much why we failed. We'll let
libcurl know that it may try other means if it wants to. */
return CURL_SEEKFUNC_CANTSEEK;
return CURL_SEEKFUNC_OK;
}
#if defined(WIN32) && !defined(__MINGW64__)
#ifdef __BORLANDC__
/* 64-bit lseek-like function unavailable */
# define _lseeki64(hnd,ofs,whence) lseek(hnd,ofs,whence)
#endif
#ifdef __POCC__
# if(__POCC__ < 450)
/* 64-bit lseek-like function unavailable */
# define _lseeki64(hnd,ofs,whence) _lseek(hnd,ofs,whence)
# else
# define _lseeki64(hnd,ofs,whence) _lseek64(hnd,ofs,whence)
# endif
#endif
/*
* Truncate a file handle at a 64-bit position 'where'.
*/
int tool_ftruncate64(int fd, curl_off_t where)
{
if(_lseeki64(fd, where, SEEK_SET) < 0)
return -1;
if(!SetEndOfFile((HANDLE)_get_osfhandle(fd)))
return -1;
return 0;
}
#endif /* WIN32 && ! __MINGW64__ */

45
src/tool_cb_see.h Normal file
View File

@ -0,0 +1,45 @@
#ifndef HEADER_CURL_TOOL_CB_SEE_H
#define HEADER_CURL_TOOL_CB_SEE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "setup.h"
#if defined(WIN32) && !defined(__MINGW64__)
int tool_ftruncate64(int fd, curl_off_t where);
#define ftruncate(fd,where) tool_ftruncate64(fd,where)
#ifndef HAVE_FTRUNCATE
# define HAVE_FTRUNCATE 1
#endif
#endif /* WIN32 && ! __MINGW64__ */
/*
** callback for CURLOPT_SEEKFUNCTION
*/
int tool_seek_cb(void *userdata, curl_off_t offset, int whence);
#endif /* HEADER_CURL_TOOL_CB_SEE_H */

97
src/tool_cb_skt.c Normal file
View File

@ -0,0 +1,97 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "setup.h"
#include <curl/curl.h>
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
#include "curlx.h"
#include "tool_cfgable.h"
#include "tool_msgs.h"
#include "tool_cb_skt.h"
#include "memdebug.h" /* keep this as LAST include */
/*
** callback for CURLOPT_SOCKOPTFUNCTION
*/
int tool_sockopt_cb(void *userdata, curl_socket_t curlfd, curlsocktype purpose)
{
struct Configurable *config = userdata;
int onoff = 1; /* this callback is only used if we ask for keepalives on the
connection */
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPINTVL)
int keepidle = (int)config->alivetime;
#endif
switch(purpose) {
case CURLSOCKTYPE_IPCXN:
if(setsockopt(curlfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&onoff,
sizeof(onoff)) < 0) {
/* don't abort operation, just issue a warning */
SET_SOCKERRNO(0);
warnf(config, "Could not set SO_KEEPALIVE!\n");
return 0;
}
else {
if(config->alivetime) {
#ifdef TCP_KEEPIDLE
if(setsockopt(curlfd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&keepidle,
sizeof(keepidle)) < 0) {
/* don't abort operation, just issue a warning */
SET_SOCKERRNO(0);
warnf(config, "Could not set TCP_KEEPIDLE!\n");
return 0;
}
#endif
#ifdef TCP_KEEPINTVL
if(setsockopt(curlfd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&keepidle,
sizeof(keepidle)) < 0) {
/* don't abort operation, just issue a warning */
SET_SOCKERRNO(0);
warnf(config, "Could not set TCP_KEEPINTVL!\n");
return 0;
}
#endif
#if !defined(TCP_KEEPIDLE) || !defined(TCP_KEEPINTVL)
warnf(config, "Keep-alive functionality somewhat crippled due to "
"missing support in your operating system!\n");
#endif
}
}
break;
default:
break;
}
return 0;
}

35
src/tool_cb_skt.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef HEADER_CURL_TOOL_CB_SKT_H
#define HEADER_CURL_TOOL_CB_SKT_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "setup.h"
/*
** callback for CURLOPT_SOCKOPTFUNCTION
*/
int tool_sockopt_cb(void *userdata,
curl_socket_t curlfd,
curlsocktype purpose);
#endif /* HEADER_CURL_TOOL_CB_SKT_H */

103
src/tool_cb_wrt.c Normal file
View File

@ -0,0 +1,103 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "setup.h"
#include <curl/curl.h>
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
#include "curlx.h"
#include "tool_cfgable.h"
#include "tool_msgs.h"
#include "tool_cb_wrt.h"
#include "memdebug.h" /* keep this as LAST include */
/*
** callback for CURLOPT_WRITEFUNCTION
*/
size_t tool_write_cb(void *buffer, size_t sz, size_t nmemb, void *userdata)
{
size_t rc;
struct OutStruct *out = userdata;
struct Configurable *config = out->config;
/*
* Once that libcurl has called back tool_write_cb() the returned value
* is checked against the amount that was intended to be written, if
* it does not match then it fails with CURLE_WRITE_ERROR. So at this
* point returning a value different from sz*nmemb indicates failure.
*/
const size_t err_rc = (sz * nmemb) ? 0 : 1;
if(!out->stream) {
out->bytes = 0; /* nothing written yet */
if(!out->filename) {
warnf(config, "Remote filename has no length!\n");
return err_rc; /* Failure */
}
if(config->content_disposition) {
/* don't overwrite existing files */
FILE* f = fopen(out->filename, "r");
if(f) {
fclose(f);
warnf(config, "Refusing to overwrite %s: %s\n", out->filename,
strerror(EEXIST));
return err_rc; /* Failure */
}
}
/* open file for writing */
out->stream = fopen(out->filename, "wb");
if(!out->stream) {
warnf(config, "Failed to create the file %s: %s\n", out->filename,
strerror(errno));
return err_rc; /* failure */
}
}
rc = fwrite(buffer, sz, nmemb, out->stream);
if((sz * nmemb) == rc)
/* we added this amount of data to the output */
out->bytes += (sz * nmemb);
if(config->readbusy) {
config->readbusy = FALSE;
curl_easy_pause(config->easy, CURLPAUSE_CONT);
}
if(config->nobuffer) {
/* disable output buffering */
int res = fflush(out->stream);
if(res) {
/* return a value that isn't the same as sz * nmemb */
return err_rc; /* failure */
}
}
return rc;
}

33
src/tool_cb_wrt.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef HEADER_CURL_TOOL_CB_WRT_H
#define HEADER_CURL_TOOL_CB_WRT_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "setup.h"
/*
** callback for CURLOPT_WRITEFUNCTION
*/
size_t tool_write_cb(void *buffer, size_t sz, size_t nmemb, void *userdata);
#endif /* HEADER_CURL_TOOL_CB_WRT_H */

View File

@ -175,6 +175,34 @@ SOURCE=.\tool_bname.c
# End Source File
# Begin Source File
SOURCE=.\tool_cb_dbg.c
# End Source File
# Begin Source File
SOURCE=.\tool_cb_hdr.c
# End Source File
# Begin Source File
SOURCE=.\tool_cb_prg.c
# End Source File
# Begin Source File
SOURCE=.\tool_cb_rea.c
# End Source File
# Begin Source File
SOURCE=.\tool_cb_see.c
# End Source File
# Begin Source File
SOURCE=.\tool_cb_skt.c
# End Source File
# Begin Source File
SOURCE=.\tool_cb_wrt.c
# End Source File
# Begin Source File
SOURCE=.\tool_cfgable.c
# End Source File
# Begin Source File
@ -211,10 +239,6 @@ SOURCE=.\tool_myfunc.c
# End Source File
# Begin Source File
SOURCE=.\tool_progress.c
# End Source File
# Begin Source File
SOURCE=.\tool_setopt.c
# End Source File
# Begin Source File
@ -283,6 +307,34 @@ SOURCE=.\tool_bname.h
# End Source File
# Begin Source File
SOURCE=.\tool_cb_dbg.h
# End Source File
# Begin Source File
SOURCE=.\tool_cb_hdr.h
# End Source File
# Begin Source File
SOURCE=.\tool_cb_prg.h
# End Source File
# Begin Source File
SOURCE=.\tool_cb_rea.h
# End Source File
# Begin Source File
SOURCE=.\tool_cb_see.h
# End Source File
# Begin Source File
SOURCE=.\tool_cb_skt.h
# End Source File
# Begin Source File
SOURCE=.\tool_cb_wrt.h
# End Source File
# Begin Source File
SOURCE=.\tool_cfgable.h
# End Source File
# Begin Source File
@ -319,10 +371,6 @@ SOURCE=.\tool_myfunc.h
# End Source File
# Begin Source File
SOURCE=.\tool_progress.h
# End Source File
# Begin Source File
SOURCE=.\tool_sdecls.h
# End Source File
# Begin Source File