/* Curl_client_chop_write() writes chunks of data not larger than * CURL_MAX_WRITE_SIZE via client write callback(s) and * takes care of pause requests from the callbacks. */ CURLcode Curl_client_chop_write(struct connectdata *conn, int type, char * ptr, size_t len) { struct SessionHandle *data = conn->data; curl_write_callback writeheader = NULL; curl_write_callback writebody = NULL; if(!len) return CURLE_OK; /* If reading is actually paused, we're forced to append this chunk of data to the already held data, but only if it is the same type as otherwise it can't work and it'll return error instead. */ if(data->req.keepon & KEEP_RECV_PAUSE) { size_t newlen; char *newptr; if(type != data->state.tempwritetype) /* major internal confusion */ return CURLE_RECV_ERROR; DEBUGASSERT(data->state.tempwrite); /* figure out the new size of the data to save */ newlen = len + data->state.tempwritesize; /* allocate the new memory area */ newptr = realloc(data->state.tempwrite, newlen); if(!newptr) return CURLE_OUT_OF_MEMORY; /* copy the new data to the end of the new area */ memcpy(newptr + data->state.tempwritesize, ptr, len); /* update the pointer and the size */ data->state.tempwrite = newptr; data->state.tempwritesize = newlen; return CURLE_OK; } /* Determine the callback(s) to use. */ if(type & CLIENTWRITE_BODY) writebody = data->set.fwrite_func; if((type & CLIENTWRITE_HEADER) && (data->set.fwrite_header || data->set.writeheader)) { /* * Write headers to the same callback or to the especially setup * header callback function (added after version 7.7.1). */ writeheader = data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func; } /* Chop data, write chunks. */ while(len) { size_t chunklen = len <= CURL_MAX_WRITE_SIZE? len: CURL_MAX_WRITE_SIZE; if(writebody) { size_t wrote = writebody(ptr, 1, chunklen, data->set.out); 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 return pausewrite(data, type, ptr, len); } else if(wrote != chunklen) { failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen); return CURLE_WRITE_ERROR; } } if(writeheader) { size_t wrote = writeheader(ptr, 1, chunklen, data->set.writeheader); if(CURL_WRITEFUNC_PAUSE == wrote) /* here we pass in the HEADER bit only since if this was body as well then it was passed already and clearly that didn't trigger the pause, so this is saved for later with the HEADER bit only */ return pausewrite(data, CLIENTWRITE_HEADER, ptr, len); if(wrote != chunklen) { failf (data, "Failed writing header"); return CURLE_WRITE_ERROR; } } ptr += chunklen; len -= chunklen; } return CURLE_OK; }
/* chop_write() writes chunks of data not larger than CURL_MAX_WRITE_SIZE via * client write callback(s) and takes care of pause requests from the * callbacks. */ static CURLcode chop_write(struct connectdata *conn, int type, char *optr, size_t olen) { struct Curl_easy *data = conn->data; curl_write_callback writeheader = NULL; curl_write_callback writebody = NULL; char *ptr = optr; size_t len = olen; if(!len) return CURLE_OK; /* If reading is paused, append this data to the already held data for this type. */ if(data->req.keepon & KEEP_RECV_PAUSE) return pausewrite(data, type, ptr, len); /* Determine the callback(s) to use. */ if(type & CLIENTWRITE_BODY) writebody = data->set.fwrite_func; if((type & CLIENTWRITE_HEADER) && (data->set.fwrite_header || data->set.writeheader)) { /* * Write headers to the same callback or to the especially setup * header callback function (added after version 7.7.1). */ writeheader = data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func; } /* Chop data, write chunks. */ while(len) { size_t chunklen = len <= CURL_MAX_WRITE_SIZE? len: CURL_MAX_WRITE_SIZE; if(writebody) { size_t wrote = writebody(ptr, 1, chunklen, data->set.out); 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; } return pausewrite(data, type, ptr, len); } if(wrote != chunklen) { failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen); return CURLE_WRITE_ERROR; } } ptr += chunklen; len -= chunklen; } if(writeheader) { size_t wrote; ptr = optr; len = olen; Curl_set_in_callback(data, true); wrote = writeheader(ptr, 1, len, data->set.writeheader); Curl_set_in_callback(data, false); if(CURL_WRITEFUNC_PAUSE == wrote) /* here we pass in the HEADER bit only since if this was body as well then it was passed already and clearly that didn't trigger the pause, so this is saved for later with the HEADER bit only */ return pausewrite(data, CLIENTWRITE_HEADER, ptr, len); if(wrote != len) { failf(data, "Failed writing header"); return CURLE_WRITE_ERROR; } } return CURLE_OK; }
int main (int argc, char *argv[]) { int use_stdin = 0; FILE *newsfile; FILE *newsfile_copy; char *bodyfile_name = NULL; FILE *bodyfile_r; FILE *bodyfile_w; char *mergefile_name = NULL; FILE *mergefile; #if defined(MAINLOOP) volatile int w = 1; while (w); #endif parse_commandline (argc, argv); if (printversion) { printf ("%s (" PACKAGE ") " VERSION "\n", Name); return 0; } if (!strcmp (newsfile_name, "-")) { use_stdin = 1; newsfile_name = nb_tmpnam (); newsfile_copy = open_write (newsfile_name); newsfile = stdin; mergefile = stdout; } else { newsfile_copy = NULL; newsfile = open_read (newsfile_name); mergefile_name = nb_tmpnam (); mergefile = open_write (mergefile_name); } if (filter) { expand_argv (new_argv, "-"); exec_filter (new_argv, &bodyfile_w, &bodyfile_r); writebody (newsfile, newsfile_copy, bodyfile_w, remove_header, remove_quote, remove_sig, keep); newsfile = open_read (newsfile_name); readbody (newsfile, bodyfile_r, mergefile, remove_header, remove_quote, remove_sig, keep); check_child (); } else { bodyfile_name = nb_tmpnam (); bodyfile_w = open_write (bodyfile_name); expand_argv (new_argv, bodyfile_name); writebody (newsfile, newsfile_copy, bodyfile_w, remove_header, remove_quote, remove_sig, keep); exec_program (new_argv); check_child (); newsfile = open_read (newsfile_name); bodyfile_r = open_read (bodyfile_name); readbody (newsfile, bodyfile_r, mergefile, remove_header, remove_quote, remove_sig, keep); } if (use_stdin) nb_unlink (newsfile_name); else nb_rename (mergefile_name, newsfile_name); if (!filter) nb_unlink (bodyfile_name); return 0; }