tool_cb_wrt.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
00009  *
00010  * This software is licensed as described in the file COPYING, which
00011  * you should have received as part of this distribution. The terms
00012  * are also available at https://curl.haxx.se/docs/copyright.html.
00013  *
00014  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00015  * copies of the Software, and permit persons to whom the Software is
00016  * furnished to do so, under the terms of the COPYING file.
00017  *
00018  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00019  * KIND, either express or implied.
00020  *
00021  ***************************************************************************/
00022 #include "tool_setup.h"
00023 
00024 #define ENABLE_CURLX_PRINTF
00025 /* use our own printf() functions */
00026 #include "curlx.h"
00027 
00028 #include "tool_cfgable.h"
00029 #include "tool_msgs.h"
00030 #include "tool_cb_wrt.h"
00031 
00032 #include "memdebug.h" /* keep this as LAST include */
00033 
00034 /* create a local file for writing, return TRUE on success */
00035 bool tool_create_output_file(struct OutStruct *outs)
00036 {
00037   struct GlobalConfig *global = outs->config->global;
00038   FILE *file;
00039 
00040   if(!outs->filename || !*outs->filename) {
00041     warnf(global, "Remote filename has no length!\n");
00042     return FALSE;
00043   }
00044 
00045   if(outs->is_cd_filename) {
00046     /* don't overwrite existing files */
00047     file = fopen(outs->filename, "rb");
00048     if(file) {
00049       fclose(file);
00050       warnf(global, "Refusing to overwrite %s: %s\n", outs->filename,
00051             strerror(EEXIST));
00052       return FALSE;
00053     }
00054   }
00055 
00056   /* open file for writing */
00057   file = fopen(outs->filename, "wb");
00058   if(!file) {
00059     warnf(global, "Failed to create the file %s: %s\n", outs->filename,
00060           strerror(errno));
00061     return FALSE;
00062   }
00063   outs->s_isreg = TRUE;
00064   outs->fopened = TRUE;
00065   outs->stream = file;
00066   outs->bytes = 0;
00067   outs->init = 0;
00068   return TRUE;
00069 }
00070 
00071 /*
00072 ** callback for CURLOPT_WRITEFUNCTION
00073 */
00074 
00075 size_t tool_write_cb(void *buffer, size_t sz, size_t nmemb, void *userdata)
00076 {
00077   size_t rc;
00078   struct OutStruct *outs = userdata;
00079   struct OperationConfig *config = outs->config;
00080 
00081   /*
00082    * Once that libcurl has called back tool_write_cb() the returned value
00083    * is checked against the amount that was intended to be written, if
00084    * it does not match then it fails with CURLE_WRITE_ERROR. So at this
00085    * point returning a value different from sz*nmemb indicates failure.
00086    */
00087   const size_t failure = (sz * nmemb) ? 0 : 1;
00088 
00089   if(!config)
00090     return failure;
00091 
00092 #ifdef DEBUGBUILD
00093   if(config->include_headers) {
00094     if(sz * nmemb > (size_t)CURL_MAX_HTTP_HEADER) {
00095       warnf(config->global, "Header data size exceeds single call write "
00096             "limit!\n");
00097       return failure;
00098     }
00099   }
00100   else {
00101     if(sz * nmemb > (size_t)CURL_MAX_WRITE_SIZE) {
00102       warnf(config->global, "Data size exceeds single call write limit!\n");
00103       return failure;
00104     }
00105   }
00106 
00107   {
00108     /* Some internal congruency checks on received OutStruct */
00109     bool check_fails = FALSE;
00110     if(outs->filename) {
00111       /* regular file */
00112       if(!*outs->filename)
00113         check_fails = TRUE;
00114       if(!outs->s_isreg)
00115         check_fails = TRUE;
00116       if(outs->fopened && !outs->stream)
00117         check_fails = TRUE;
00118       if(!outs->fopened && outs->stream)
00119         check_fails = TRUE;
00120       if(!outs->fopened && outs->bytes)
00121         check_fails = TRUE;
00122     }
00123     else {
00124       /* standard stream */
00125       if(!outs->stream || outs->s_isreg || outs->fopened)
00126         check_fails = TRUE;
00127       if(outs->alloc_filename || outs->is_cd_filename || outs->init)
00128         check_fails = TRUE;
00129     }
00130     if(check_fails) {
00131       warnf(config->global, "Invalid output struct data for write callback\n");
00132       return failure;
00133     }
00134   }
00135 #endif
00136 
00137   if(!outs->stream && !tool_create_output_file(outs))
00138     return failure;
00139 
00140   rc = fwrite(buffer, sz, nmemb, outs->stream);
00141 
00142   if((sz * nmemb) == rc)
00143     /* we added this amount of data to the output */
00144     outs->bytes += (sz * nmemb);
00145 
00146   if(config->readbusy) {
00147     config->readbusy = FALSE;
00148     curl_easy_pause(config->easy, CURLPAUSE_CONT);
00149   }
00150 
00151   if(config->nobuffer) {
00152     /* output buffering disabled */
00153     int res = fflush(outs->stream);
00154     if(res)
00155       return failure;
00156   }
00157 
00158   return rc;
00159 }


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:06