From 2a4ee0d221555686b4a8eae87e54a19e128f7271 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 26 Dec 2013 23:50:34 +0100 Subject: [PATCH] FILE: we don't support paused transfers using this protocol Make sure that we detect such attempts and return a proper error code instead of silently handling this in problematic ways. Updated the documentation to mention this limitation. Bug: http://curl.haxx.se/bug/view.cgi?id=1286 --- docs/libcurl/curl_easy_pause.3 | 8 ++++++-- lib/sendf.c | 12 ++++++++++-- lib/transfer.c | 24 +++++++++++++++++------- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/docs/libcurl/curl_easy_pause.3 b/docs/libcurl/curl_easy_pause.3 index 402bb0546..1e53477f7 100644 --- a/docs/libcurl/curl_easy_pause.3 +++ b/docs/libcurl/curl_easy_pause.3 @@ -31,8 +31,8 @@ curl_easy_pause - pause and unpause a connection Using this function, you can explicitly mark a running connection to get paused, and you can unpause a connection that was previously paused. -A connection can be paused by using this function or by letting the read -or the write callbacks return the proper magic return code +A connection can be paused by using this function or by letting the read or +the write callbacks return the proper magic return code (\fICURL_READFUNC_PAUSE\fP and \fICURL_WRITEFUNC_PAUSE\fP). A write callback that returns pause signals to the library that it couldn't take care of any data at all, and that data will then be delivered again to the callback when @@ -68,6 +68,10 @@ Convenience define that unpauses both directions CURLE_OK (zero) means that the option was set properly, and a non-zero return code means something wrong occurred after the new state was set. See the \fIlibcurl-errors(3)\fP man page for the full list with descriptions. +.SH LIMITATIONS +The pausing of transfers does not work with protocols that work without +network connectivity, like FILE://. Trying to pause such a transfer, in any +direction, will cause problems in the worst case or an error in the best case. .SH AVAILABILITY This function was added in libcurl 7.18.0. Before this version, there was no explicit support for pausing transfers. diff --git a/lib/sendf.c b/lib/sendf.c index c274203bf..8ffd43f47 100644 --- a/lib/sendf.c +++ b/lib/sendf.c @@ -444,10 +444,18 @@ CURLcode Curl_client_write(struct connectdata *conn, wrote = len; } - if(CURL_WRITEFUNC_PAUSE == wrote) + if(conn->handler->flags & PROTOPT_NONETWORK) { + /* protocols that work without network cannot be paused. This is + actually only FILE:// just now, and it can't pause since the transfer + isn't done using the "normal" procedure. */ + failf(data, "Write callback asked for PAUSE when not supported!"); + return CURLE_WRITE_ERROR; + } + + else if(CURL_WRITEFUNC_PAUSE == wrote) return pausewrite(data, type, ptr, len); - if(wrote != len) { + else if(wrote != len) { failf(data, "Failed writing body (%zu != %zu)", wrote, len); return CURLE_WRITE_ERROR; } diff --git a/lib/transfer.c b/lib/transfer.c index 2ce6597c3..4dbc4e1b7 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -128,14 +128,24 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp) return CURLE_ABORTED_BY_CALLBACK; } else if(nread == CURL_READFUNC_PAUSE) { - struct SingleRequest *k = &data->req; - /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */ - k->keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */ - if(data->req.upload_chunky) { - /* Back out the preallocation done above */ - data->req.upload_fromhere -= (8 + 2); + + if(conn->handler->flags & PROTOPT_NONETWORK) { + /* protocols that work without network cannot be paused. This is + actually only FILE:// just now, and it can't pause since the transfer + isn't done using the "normal" procedure. */ + failf(data, "Read callback asked for PAUSE when not supported!"); + return CURLE_READ_ERROR; + } + else { + struct SingleRequest *k = &data->req; + /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */ + k->keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */ + if(data->req.upload_chunky) { + /* Back out the preallocation done above */ + data->req.upload_fromhere -= (8 + 2); + } + *nreadp = 0; } - *nreadp = 0; return CURLE_OK; /* nothing was read */ } else if((size_t)nread > buffersize) {