xref: /aosp_15_r20/external/curl/src/tool_operate.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker  *                                  _   _ ____  _
3*6236dae4SAndroid Build Coastguard Worker  *  Project                     ___| | | |  _ \| |
4*6236dae4SAndroid Build Coastguard Worker  *                             / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker  *                            | (__| |_| |  _ <| |___
6*6236dae4SAndroid Build Coastguard Worker  *                             \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker  *
8*6236dae4SAndroid Build Coastguard Worker  * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker  *
10*6236dae4SAndroid Build Coastguard Worker  * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker  * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker  * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker  *
14*6236dae4SAndroid Build Coastguard Worker  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker  * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker  * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker  *
18*6236dae4SAndroid Build Coastguard Worker  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker  * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker  *
21*6236dae4SAndroid Build Coastguard Worker  * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker  *
23*6236dae4SAndroid Build Coastguard Worker  ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker #include "tool_setup.h"
25*6236dae4SAndroid Build Coastguard Worker 
26*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_FCNTL_H
27*6236dae4SAndroid Build Coastguard Worker #  include <fcntl.h>
28*6236dae4SAndroid Build Coastguard Worker #endif
29*6236dae4SAndroid Build Coastguard Worker 
30*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_LOCALE_H
31*6236dae4SAndroid Build Coastguard Worker #  include <locale.h>
32*6236dae4SAndroid Build Coastguard Worker #endif
33*6236dae4SAndroid Build Coastguard Worker 
34*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SYS_SELECT_H
35*6236dae4SAndroid Build Coastguard Worker #  include <sys/select.h>
36*6236dae4SAndroid Build Coastguard Worker #elif defined(HAVE_UNISTD_H)
37*6236dae4SAndroid Build Coastguard Worker #  include <unistd.h>
38*6236dae4SAndroid Build Coastguard Worker #endif
39*6236dae4SAndroid Build Coastguard Worker 
40*6236dae4SAndroid Build Coastguard Worker #ifdef __VMS
41*6236dae4SAndroid Build Coastguard Worker #  include <fabdef.h>
42*6236dae4SAndroid Build Coastguard Worker #endif
43*6236dae4SAndroid Build Coastguard Worker 
44*6236dae4SAndroid Build Coastguard Worker #ifdef __AMIGA__
45*6236dae4SAndroid Build Coastguard Worker #  include <proto/dos.h>
46*6236dae4SAndroid Build Coastguard Worker #endif
47*6236dae4SAndroid Build Coastguard Worker 
48*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN_H
49*6236dae4SAndroid Build Coastguard Worker #  include <netinet/in.h>
50*6236dae4SAndroid Build Coastguard Worker #endif
51*6236dae4SAndroid Build Coastguard Worker 
52*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_UV_H
53*6236dae4SAndroid Build Coastguard Worker /* Hack for Unity mode */
54*6236dae4SAndroid Build Coastguard Worker #ifdef HEADER_CURL_MEMDEBUG_H
55*6236dae4SAndroid Build Coastguard Worker #undef HEADER_CURL_MEMDEBUG_H
56*6236dae4SAndroid Build Coastguard Worker #undef freeaddrinfo
57*6236dae4SAndroid Build Coastguard Worker #undef getaddrinfo
58*6236dae4SAndroid Build Coastguard Worker #endif
59*6236dae4SAndroid Build Coastguard Worker /* this is for libuv-enabled debug builds only */
60*6236dae4SAndroid Build Coastguard Worker #include <uv.h>
61*6236dae4SAndroid Build Coastguard Worker #endif
62*6236dae4SAndroid Build Coastguard Worker 
63*6236dae4SAndroid Build Coastguard Worker #include "curlx.h"
64*6236dae4SAndroid Build Coastguard Worker 
65*6236dae4SAndroid Build Coastguard Worker #include "tool_binmode.h"
66*6236dae4SAndroid Build Coastguard Worker #include "tool_cfgable.h"
67*6236dae4SAndroid Build Coastguard Worker #include "tool_cb_dbg.h"
68*6236dae4SAndroid Build Coastguard Worker #include "tool_cb_hdr.h"
69*6236dae4SAndroid Build Coastguard Worker #include "tool_cb_prg.h"
70*6236dae4SAndroid Build Coastguard Worker #include "tool_cb_rea.h"
71*6236dae4SAndroid Build Coastguard Worker #include "tool_cb_see.h"
72*6236dae4SAndroid Build Coastguard Worker #include "tool_cb_soc.h"
73*6236dae4SAndroid Build Coastguard Worker #include "tool_cb_wrt.h"
74*6236dae4SAndroid Build Coastguard Worker #include "tool_dirhie.h"
75*6236dae4SAndroid Build Coastguard Worker #include "tool_doswin.h"
76*6236dae4SAndroid Build Coastguard Worker #include "tool_easysrc.h"
77*6236dae4SAndroid Build Coastguard Worker #include "tool_filetime.h"
78*6236dae4SAndroid Build Coastguard Worker #include "tool_getparam.h"
79*6236dae4SAndroid Build Coastguard Worker #include "tool_helpers.h"
80*6236dae4SAndroid Build Coastguard Worker #include "tool_findfile.h"
81*6236dae4SAndroid Build Coastguard Worker #include "tool_libinfo.h"
82*6236dae4SAndroid Build Coastguard Worker #include "tool_main.h"
83*6236dae4SAndroid Build Coastguard Worker #include "tool_msgs.h"
84*6236dae4SAndroid Build Coastguard Worker #include "tool_operate.h"
85*6236dae4SAndroid Build Coastguard Worker #include "tool_operhlp.h"
86*6236dae4SAndroid Build Coastguard Worker #include "tool_paramhlp.h"
87*6236dae4SAndroid Build Coastguard Worker #include "tool_parsecfg.h"
88*6236dae4SAndroid Build Coastguard Worker #include "tool_setopt.h"
89*6236dae4SAndroid Build Coastguard Worker #include "tool_sleep.h"
90*6236dae4SAndroid Build Coastguard Worker #include "tool_urlglob.h"
91*6236dae4SAndroid Build Coastguard Worker #include "tool_util.h"
92*6236dae4SAndroid Build Coastguard Worker #include "tool_writeout.h"
93*6236dae4SAndroid Build Coastguard Worker #include "tool_xattr.h"
94*6236dae4SAndroid Build Coastguard Worker #include "tool_vms.h"
95*6236dae4SAndroid Build Coastguard Worker #include "tool_help.h"
96*6236dae4SAndroid Build Coastguard Worker #include "tool_hugehelp.h"
97*6236dae4SAndroid Build Coastguard Worker #include "tool_progress.h"
98*6236dae4SAndroid Build Coastguard Worker #include "tool_ipfs.h"
99*6236dae4SAndroid Build Coastguard Worker #include "dynbuf.h"
100*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUGBUILD
101*6236dae4SAndroid Build Coastguard Worker /* libcurl's debug-only curl_easy_perform_ev() */
102*6236dae4SAndroid Build Coastguard Worker CURL_EXTERN CURLcode curl_easy_perform_ev(CURL *easy);
103*6236dae4SAndroid Build Coastguard Worker #endif
104*6236dae4SAndroid Build Coastguard Worker 
105*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h" /* keep this as LAST include */
106*6236dae4SAndroid Build Coastguard Worker 
107*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_CA_EMBED
108*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DECLARED_CURL_CA_EMBED
109*6236dae4SAndroid Build Coastguard Worker #define CURL_DECLARED_CURL_CA_EMBED
110*6236dae4SAndroid Build Coastguard Worker extern const unsigned char curl_ca_embed[];
111*6236dae4SAndroid Build Coastguard Worker #endif
112*6236dae4SAndroid Build Coastguard Worker #endif
113*6236dae4SAndroid Build Coastguard Worker 
114*6236dae4SAndroid Build Coastguard Worker #ifndef O_BINARY
115*6236dae4SAndroid Build Coastguard Worker /* since O_BINARY as used in bitmasks, setting it to zero makes it usable in
116*6236dae4SAndroid Build Coastguard Worker    source code but yet it does not ruin anything */
117*6236dae4SAndroid Build Coastguard Worker #  define O_BINARY 0
118*6236dae4SAndroid Build Coastguard Worker #endif
119*6236dae4SAndroid Build Coastguard Worker 
120*6236dae4SAndroid Build Coastguard Worker #ifndef SOL_IP
121*6236dae4SAndroid Build Coastguard Worker #  define SOL_IP IPPROTO_IP
122*6236dae4SAndroid Build Coastguard Worker #endif
123*6236dae4SAndroid Build Coastguard Worker 
124*6236dae4SAndroid Build Coastguard Worker #define CURL_CA_CERT_ERRORMSG                                              \
125*6236dae4SAndroid Build Coastguard Worker   "More details here: https://curl.se/docs/sslcerts.html\n\n"              \
126*6236dae4SAndroid Build Coastguard Worker   "curl failed to verify the legitimacy of the server and therefore "      \
127*6236dae4SAndroid Build Coastguard Worker   "could not\nestablish a secure connection to it. To learn more about "   \
128*6236dae4SAndroid Build Coastguard Worker   "this situation and\nhow to fix it, please visit the webpage mentioned " \
129*6236dae4SAndroid Build Coastguard Worker   "above.\n"
130*6236dae4SAndroid Build Coastguard Worker 
131*6236dae4SAndroid Build Coastguard Worker static CURLcode single_transfer(struct GlobalConfig *global,
132*6236dae4SAndroid Build Coastguard Worker                                 struct OperationConfig *config,
133*6236dae4SAndroid Build Coastguard Worker                                 CURLSH *share,
134*6236dae4SAndroid Build Coastguard Worker                                 bool capath_from_env,
135*6236dae4SAndroid Build Coastguard Worker                                 bool *added,
136*6236dae4SAndroid Build Coastguard Worker                                 bool *skipped);
137*6236dae4SAndroid Build Coastguard Worker static CURLcode create_transfer(struct GlobalConfig *global,
138*6236dae4SAndroid Build Coastguard Worker                                 CURLSH *share,
139*6236dae4SAndroid Build Coastguard Worker                                 bool *added,
140*6236dae4SAndroid Build Coastguard Worker                                 bool *skipped);
141*6236dae4SAndroid Build Coastguard Worker 
is_fatal_error(CURLcode code)142*6236dae4SAndroid Build Coastguard Worker static bool is_fatal_error(CURLcode code)
143*6236dae4SAndroid Build Coastguard Worker {
144*6236dae4SAndroid Build Coastguard Worker   switch(code) {
145*6236dae4SAndroid Build Coastguard Worker   case CURLE_FAILED_INIT:
146*6236dae4SAndroid Build Coastguard Worker   case CURLE_OUT_OF_MEMORY:
147*6236dae4SAndroid Build Coastguard Worker   case CURLE_UNKNOWN_OPTION:
148*6236dae4SAndroid Build Coastguard Worker   case CURLE_FUNCTION_NOT_FOUND:
149*6236dae4SAndroid Build Coastguard Worker   case CURLE_BAD_FUNCTION_ARGUMENT:
150*6236dae4SAndroid Build Coastguard Worker     /* critical error */
151*6236dae4SAndroid Build Coastguard Worker     return TRUE;
152*6236dae4SAndroid Build Coastguard Worker   default:
153*6236dae4SAndroid Build Coastguard Worker     break;
154*6236dae4SAndroid Build Coastguard Worker   }
155*6236dae4SAndroid Build Coastguard Worker 
156*6236dae4SAndroid Build Coastguard Worker   /* no error or not critical */
157*6236dae4SAndroid Build Coastguard Worker   return FALSE;
158*6236dae4SAndroid Build Coastguard Worker }
159*6236dae4SAndroid Build Coastguard Worker 
160*6236dae4SAndroid Build Coastguard Worker /*
161*6236dae4SAndroid Build Coastguard Worker  * Check if a given string is a PKCS#11 URI
162*6236dae4SAndroid Build Coastguard Worker  */
is_pkcs11_uri(const char * string)163*6236dae4SAndroid Build Coastguard Worker static bool is_pkcs11_uri(const char *string)
164*6236dae4SAndroid Build Coastguard Worker {
165*6236dae4SAndroid Build Coastguard Worker   if(curl_strnequal(string, "pkcs11:", 7)) {
166*6236dae4SAndroid Build Coastguard Worker     return TRUE;
167*6236dae4SAndroid Build Coastguard Worker   }
168*6236dae4SAndroid Build Coastguard Worker   else {
169*6236dae4SAndroid Build Coastguard Worker     return FALSE;
170*6236dae4SAndroid Build Coastguard Worker   }
171*6236dae4SAndroid Build Coastguard Worker }
172*6236dae4SAndroid Build Coastguard Worker 
173*6236dae4SAndroid Build Coastguard Worker #ifdef IP_TOS
get_address_family(curl_socket_t sockfd)174*6236dae4SAndroid Build Coastguard Worker static int get_address_family(curl_socket_t sockfd)
175*6236dae4SAndroid Build Coastguard Worker {
176*6236dae4SAndroid Build Coastguard Worker   struct sockaddr addr;
177*6236dae4SAndroid Build Coastguard Worker   curl_socklen_t addrlen = sizeof(addr);
178*6236dae4SAndroid Build Coastguard Worker   memset(&addr, 0, sizeof(addr));
179*6236dae4SAndroid Build Coastguard Worker   if(getsockname(sockfd, (struct sockaddr *)&addr, &addrlen) == 0)
180*6236dae4SAndroid Build Coastguard Worker     return addr.sa_family;
181*6236dae4SAndroid Build Coastguard Worker   return AF_UNSPEC;
182*6236dae4SAndroid Build Coastguard Worker }
183*6236dae4SAndroid Build Coastguard Worker #endif
184*6236dae4SAndroid Build Coastguard Worker 
185*6236dae4SAndroid Build Coastguard Worker #if defined(IP_TOS) || defined(IPV6_TCLASS) || defined(SO_PRIORITY)
sockopt_callback(void * clientp,curl_socket_t curlfd,curlsocktype purpose)186*6236dae4SAndroid Build Coastguard Worker static int sockopt_callback(void *clientp, curl_socket_t curlfd,
187*6236dae4SAndroid Build Coastguard Worker                             curlsocktype purpose)
188*6236dae4SAndroid Build Coastguard Worker {
189*6236dae4SAndroid Build Coastguard Worker   struct OperationConfig *config = (struct OperationConfig *)clientp;
190*6236dae4SAndroid Build Coastguard Worker   if(purpose != CURLSOCKTYPE_IPCXN)
191*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKOPT_OK;
192*6236dae4SAndroid Build Coastguard Worker   (void)config;
193*6236dae4SAndroid Build Coastguard Worker   (void)curlfd;
194*6236dae4SAndroid Build Coastguard Worker #if defined(IP_TOS) || defined(IPV6_TCLASS)
195*6236dae4SAndroid Build Coastguard Worker   if(config->ip_tos > 0) {
196*6236dae4SAndroid Build Coastguard Worker     int tos = (int)config->ip_tos;
197*6236dae4SAndroid Build Coastguard Worker     int result = 0;
198*6236dae4SAndroid Build Coastguard Worker     switch(get_address_family(curlfd)) {
199*6236dae4SAndroid Build Coastguard Worker     case AF_INET:
200*6236dae4SAndroid Build Coastguard Worker #ifdef IP_TOS
201*6236dae4SAndroid Build Coastguard Worker       result = setsockopt(curlfd, SOL_IP, IP_TOS, (void *)&tos, sizeof(tos));
202*6236dae4SAndroid Build Coastguard Worker #endif
203*6236dae4SAndroid Build Coastguard Worker       break;
204*6236dae4SAndroid Build Coastguard Worker #if defined(IPV6_TCLASS) && defined(AF_INET6)
205*6236dae4SAndroid Build Coastguard Worker     case AF_INET6:
206*6236dae4SAndroid Build Coastguard Worker       result = setsockopt(curlfd, IPPROTO_IPV6, IPV6_TCLASS,
207*6236dae4SAndroid Build Coastguard Worker                           (void *)&tos, sizeof(tos));
208*6236dae4SAndroid Build Coastguard Worker       break;
209*6236dae4SAndroid Build Coastguard Worker #endif
210*6236dae4SAndroid Build Coastguard Worker     }
211*6236dae4SAndroid Build Coastguard Worker     if(result < 0) {
212*6236dae4SAndroid Build Coastguard Worker       int error = errno;
213*6236dae4SAndroid Build Coastguard Worker       warnf(config->global,
214*6236dae4SAndroid Build Coastguard Worker             "Setting type of service to %d failed with errno %d: %s;\n",
215*6236dae4SAndroid Build Coastguard Worker             tos, error, strerror(error));
216*6236dae4SAndroid Build Coastguard Worker     }
217*6236dae4SAndroid Build Coastguard Worker   }
218*6236dae4SAndroid Build Coastguard Worker #endif
219*6236dae4SAndroid Build Coastguard Worker #ifdef SO_PRIORITY
220*6236dae4SAndroid Build Coastguard Worker   if(config->vlan_priority > 0) {
221*6236dae4SAndroid Build Coastguard Worker     int priority = (int)config->vlan_priority;
222*6236dae4SAndroid Build Coastguard Worker     if(setsockopt(curlfd, SOL_SOCKET, SO_PRIORITY,
223*6236dae4SAndroid Build Coastguard Worker       (void *)&priority, sizeof(priority)) != 0) {
224*6236dae4SAndroid Build Coastguard Worker       int error = errno;
225*6236dae4SAndroid Build Coastguard Worker       warnf(config->global, "VLAN priority %d failed with errno %d: %s;\n",
226*6236dae4SAndroid Build Coastguard Worker             priority, error, strerror(error));
227*6236dae4SAndroid Build Coastguard Worker     }
228*6236dae4SAndroid Build Coastguard Worker   }
229*6236dae4SAndroid Build Coastguard Worker #endif
230*6236dae4SAndroid Build Coastguard Worker   return CURL_SOCKOPT_OK;
231*6236dae4SAndroid Build Coastguard Worker }
232*6236dae4SAndroid Build Coastguard Worker #endif
233*6236dae4SAndroid Build Coastguard Worker 
234*6236dae4SAndroid Build Coastguard Worker 
235*6236dae4SAndroid Build Coastguard Worker #ifdef __VMS
236*6236dae4SAndroid Build Coastguard Worker /*
237*6236dae4SAndroid Build Coastguard Worker  * get_vms_file_size does what it takes to get the real size of the file
238*6236dae4SAndroid Build Coastguard Worker  *
239*6236dae4SAndroid Build Coastguard Worker  * For fixed files, find out the size of the EOF block and adjust.
240*6236dae4SAndroid Build Coastguard Worker  *
241*6236dae4SAndroid Build Coastguard Worker  * For all others, have to read the entire file in, discarding the contents.
242*6236dae4SAndroid Build Coastguard Worker  * Most posted text files will be small, and binary files like zlib archives
243*6236dae4SAndroid Build Coastguard Worker  * and CD/DVD images should be either a STREAM_LF format or a fixed format.
244*6236dae4SAndroid Build Coastguard Worker  *
245*6236dae4SAndroid Build Coastguard Worker  */
vms_realfilesize(const char * name,const struct_stat * stat_buf)246*6236dae4SAndroid Build Coastguard Worker static curl_off_t vms_realfilesize(const char *name,
247*6236dae4SAndroid Build Coastguard Worker                                    const struct_stat *stat_buf)
248*6236dae4SAndroid Build Coastguard Worker {
249*6236dae4SAndroid Build Coastguard Worker   char buffer[8192];
250*6236dae4SAndroid Build Coastguard Worker   curl_off_t count;
251*6236dae4SAndroid Build Coastguard Worker   int ret_stat;
252*6236dae4SAndroid Build Coastguard Worker   FILE * file;
253*6236dae4SAndroid Build Coastguard Worker 
254*6236dae4SAndroid Build Coastguard Worker   /* !checksrc! disable FOPENMODE 1 */
255*6236dae4SAndroid Build Coastguard Worker   file = fopen(name, "r"); /* VMS */
256*6236dae4SAndroid Build Coastguard Worker   if(!file) {
257*6236dae4SAndroid Build Coastguard Worker     return 0;
258*6236dae4SAndroid Build Coastguard Worker   }
259*6236dae4SAndroid Build Coastguard Worker   count = 0;
260*6236dae4SAndroid Build Coastguard Worker   ret_stat = 1;
261*6236dae4SAndroid Build Coastguard Worker   while(ret_stat > 0) {
262*6236dae4SAndroid Build Coastguard Worker     ret_stat = fread(buffer, 1, sizeof(buffer), file);
263*6236dae4SAndroid Build Coastguard Worker     if(ret_stat)
264*6236dae4SAndroid Build Coastguard Worker       count += ret_stat;
265*6236dae4SAndroid Build Coastguard Worker   }
266*6236dae4SAndroid Build Coastguard Worker   fclose(file);
267*6236dae4SAndroid Build Coastguard Worker 
268*6236dae4SAndroid Build Coastguard Worker   return count;
269*6236dae4SAndroid Build Coastguard Worker }
270*6236dae4SAndroid Build Coastguard Worker 
271*6236dae4SAndroid Build Coastguard Worker /*
272*6236dae4SAndroid Build Coastguard Worker  *
273*6236dae4SAndroid Build Coastguard Worker  *  VmsSpecialSize checks to see if the stat st_size can be trusted and
274*6236dae4SAndroid Build Coastguard Worker  *  if not to call a routine to get the correct size.
275*6236dae4SAndroid Build Coastguard Worker  *
276*6236dae4SAndroid Build Coastguard Worker  */
VmsSpecialSize(const char * name,const struct_stat * stat_buf)277*6236dae4SAndroid Build Coastguard Worker static curl_off_t VmsSpecialSize(const char *name,
278*6236dae4SAndroid Build Coastguard Worker                                  const struct_stat *stat_buf)
279*6236dae4SAndroid Build Coastguard Worker {
280*6236dae4SAndroid Build Coastguard Worker   switch(stat_buf->st_fab_rfm) {
281*6236dae4SAndroid Build Coastguard Worker   case FAB$C_VAR:
282*6236dae4SAndroid Build Coastguard Worker   case FAB$C_VFC:
283*6236dae4SAndroid Build Coastguard Worker     return vms_realfilesize(name, stat_buf);
284*6236dae4SAndroid Build Coastguard Worker     break;
285*6236dae4SAndroid Build Coastguard Worker   default:
286*6236dae4SAndroid Build Coastguard Worker     return stat_buf->st_size;
287*6236dae4SAndroid Build Coastguard Worker   }
288*6236dae4SAndroid Build Coastguard Worker }
289*6236dae4SAndroid Build Coastguard Worker #endif /* __VMS */
290*6236dae4SAndroid Build Coastguard Worker 
291*6236dae4SAndroid Build Coastguard Worker #define BUFFER_SIZE (100*1024)
292*6236dae4SAndroid Build Coastguard Worker 
293*6236dae4SAndroid Build Coastguard Worker struct per_transfer *transfers; /* first node */
294*6236dae4SAndroid Build Coastguard Worker static struct per_transfer *transfersl; /* last node */
295*6236dae4SAndroid Build Coastguard Worker static curl_off_t all_pers;
296*6236dae4SAndroid Build Coastguard Worker 
297*6236dae4SAndroid Build Coastguard Worker /* add_per_transfer creates a new 'per_transfer' node in the linked
298*6236dae4SAndroid Build Coastguard Worker    list of transfers */
add_per_transfer(struct per_transfer ** per)299*6236dae4SAndroid Build Coastguard Worker static CURLcode add_per_transfer(struct per_transfer **per)
300*6236dae4SAndroid Build Coastguard Worker {
301*6236dae4SAndroid Build Coastguard Worker   struct per_transfer *p;
302*6236dae4SAndroid Build Coastguard Worker   p = calloc(1, sizeof(struct per_transfer));
303*6236dae4SAndroid Build Coastguard Worker   if(!p)
304*6236dae4SAndroid Build Coastguard Worker     return CURLE_OUT_OF_MEMORY;
305*6236dae4SAndroid Build Coastguard Worker   if(!transfers)
306*6236dae4SAndroid Build Coastguard Worker     /* first entry */
307*6236dae4SAndroid Build Coastguard Worker     transfersl = transfers = p;
308*6236dae4SAndroid Build Coastguard Worker   else {
309*6236dae4SAndroid Build Coastguard Worker     /* make the last node point to the new node */
310*6236dae4SAndroid Build Coastguard Worker     transfersl->next = p;
311*6236dae4SAndroid Build Coastguard Worker     /* make the new node point back to the formerly last node */
312*6236dae4SAndroid Build Coastguard Worker     p->prev = transfersl;
313*6236dae4SAndroid Build Coastguard Worker     /* move the last node pointer to the new entry */
314*6236dae4SAndroid Build Coastguard Worker     transfersl = p;
315*6236dae4SAndroid Build Coastguard Worker   }
316*6236dae4SAndroid Build Coastguard Worker   *per = p;
317*6236dae4SAndroid Build Coastguard Worker   all_xfers++; /* count total number of transfers added */
318*6236dae4SAndroid Build Coastguard Worker   all_pers++;
319*6236dae4SAndroid Build Coastguard Worker 
320*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
321*6236dae4SAndroid Build Coastguard Worker }
322*6236dae4SAndroid Build Coastguard Worker 
323*6236dae4SAndroid Build Coastguard Worker /* Remove the specified transfer from the list (and free it), return the next
324*6236dae4SAndroid Build Coastguard Worker    in line */
del_per_transfer(struct per_transfer * per)325*6236dae4SAndroid Build Coastguard Worker static struct per_transfer *del_per_transfer(struct per_transfer *per)
326*6236dae4SAndroid Build Coastguard Worker {
327*6236dae4SAndroid Build Coastguard Worker   struct per_transfer *n;
328*6236dae4SAndroid Build Coastguard Worker   struct per_transfer *p;
329*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(transfers);
330*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(transfersl);
331*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(per);
332*6236dae4SAndroid Build Coastguard Worker 
333*6236dae4SAndroid Build Coastguard Worker   n = per->next;
334*6236dae4SAndroid Build Coastguard Worker   p = per->prev;
335*6236dae4SAndroid Build Coastguard Worker 
336*6236dae4SAndroid Build Coastguard Worker   if(p)
337*6236dae4SAndroid Build Coastguard Worker     p->next = n;
338*6236dae4SAndroid Build Coastguard Worker   else
339*6236dae4SAndroid Build Coastguard Worker     transfers = n;
340*6236dae4SAndroid Build Coastguard Worker 
341*6236dae4SAndroid Build Coastguard Worker   if(n)
342*6236dae4SAndroid Build Coastguard Worker     n->prev = p;
343*6236dae4SAndroid Build Coastguard Worker   else
344*6236dae4SAndroid Build Coastguard Worker     transfersl = p;
345*6236dae4SAndroid Build Coastguard Worker 
346*6236dae4SAndroid Build Coastguard Worker   free(per);
347*6236dae4SAndroid Build Coastguard Worker   all_pers--;
348*6236dae4SAndroid Build Coastguard Worker 
349*6236dae4SAndroid Build Coastguard Worker   return n;
350*6236dae4SAndroid Build Coastguard Worker }
351*6236dae4SAndroid Build Coastguard Worker 
pre_transfer(struct GlobalConfig * global,struct per_transfer * per)352*6236dae4SAndroid Build Coastguard Worker static CURLcode pre_transfer(struct GlobalConfig *global,
353*6236dae4SAndroid Build Coastguard Worker                              struct per_transfer *per)
354*6236dae4SAndroid Build Coastguard Worker {
355*6236dae4SAndroid Build Coastguard Worker   curl_off_t uploadfilesize = -1;
356*6236dae4SAndroid Build Coastguard Worker   struct_stat fileinfo;
357*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
358*6236dae4SAndroid Build Coastguard Worker 
359*6236dae4SAndroid Build Coastguard Worker   if(per->uploadfile && !stdin_upload(per->uploadfile)) {
360*6236dae4SAndroid Build Coastguard Worker     /* VMS Note:
361*6236dae4SAndroid Build Coastguard Worker      *
362*6236dae4SAndroid Build Coastguard Worker      * Reading binary from files can be a problem... Only FIXED, VAR
363*6236dae4SAndroid Build Coastguard Worker      * etc WITHOUT implied CC will work. Others need a \n appended to
364*6236dae4SAndroid Build Coastguard Worker      * a line
365*6236dae4SAndroid Build Coastguard Worker      *
366*6236dae4SAndroid Build Coastguard Worker      * - Stat gives a size but this is UNRELIABLE in VMS. E.g.
367*6236dae4SAndroid Build Coastguard Worker      * a fixed file with implied CC needs to have a byte added for every
368*6236dae4SAndroid Build Coastguard Worker      * record processed, this can be derived from Filesize & recordsize
369*6236dae4SAndroid Build Coastguard Worker      * for VARiable record files the records need to be counted!  for
370*6236dae4SAndroid Build Coastguard Worker      * every record add 1 for linefeed and subtract 2 for the record
371*6236dae4SAndroid Build Coastguard Worker      * header for VARIABLE header files only the bare record data needs
372*6236dae4SAndroid Build Coastguard Worker      * to be considered with one appended if implied CC
373*6236dae4SAndroid Build Coastguard Worker      */
374*6236dae4SAndroid Build Coastguard Worker #ifdef __VMS
375*6236dae4SAndroid Build Coastguard Worker     /* Calculate the real upload size for VMS */
376*6236dae4SAndroid Build Coastguard Worker     per->infd = -1;
377*6236dae4SAndroid Build Coastguard Worker     if(stat(per->uploadfile, &fileinfo) == 0) {
378*6236dae4SAndroid Build Coastguard Worker       fileinfo.st_size = VmsSpecialSize(uploadfile, &fileinfo);
379*6236dae4SAndroid Build Coastguard Worker       switch(fileinfo.st_fab_rfm) {
380*6236dae4SAndroid Build Coastguard Worker       case FAB$C_VAR:
381*6236dae4SAndroid Build Coastguard Worker       case FAB$C_VFC:
382*6236dae4SAndroid Build Coastguard Worker       case FAB$C_STMCR:
383*6236dae4SAndroid Build Coastguard Worker         per->infd = open(per->uploadfile, O_RDONLY | O_BINARY);
384*6236dae4SAndroid Build Coastguard Worker         break;
385*6236dae4SAndroid Build Coastguard Worker       default:
386*6236dae4SAndroid Build Coastguard Worker         per->infd = open(per->uploadfile, O_RDONLY | O_BINARY,
387*6236dae4SAndroid Build Coastguard Worker                          "rfm=stmlf", "ctx=stm");
388*6236dae4SAndroid Build Coastguard Worker       }
389*6236dae4SAndroid Build Coastguard Worker     }
390*6236dae4SAndroid Build Coastguard Worker     if(per->infd == -1)
391*6236dae4SAndroid Build Coastguard Worker #else
392*6236dae4SAndroid Build Coastguard Worker       per->infd = open(per->uploadfile, O_RDONLY | O_BINARY);
393*6236dae4SAndroid Build Coastguard Worker     if((per->infd == -1) || fstat(per->infd, &fileinfo))
394*6236dae4SAndroid Build Coastguard Worker #endif
395*6236dae4SAndroid Build Coastguard Worker     {
396*6236dae4SAndroid Build Coastguard Worker       helpf(tool_stderr, "cannot open '%s'", per->uploadfile);
397*6236dae4SAndroid Build Coastguard Worker       if(per->infd != -1) {
398*6236dae4SAndroid Build Coastguard Worker         close(per->infd);
399*6236dae4SAndroid Build Coastguard Worker         per->infd = STDIN_FILENO;
400*6236dae4SAndroid Build Coastguard Worker       }
401*6236dae4SAndroid Build Coastguard Worker       return CURLE_READ_ERROR;
402*6236dae4SAndroid Build Coastguard Worker     }
403*6236dae4SAndroid Build Coastguard Worker     per->infdopen = TRUE;
404*6236dae4SAndroid Build Coastguard Worker 
405*6236dae4SAndroid Build Coastguard Worker     /* we ignore file size for char/block devices, sockets, etc. */
406*6236dae4SAndroid Build Coastguard Worker     if(S_ISREG(fileinfo.st_mode))
407*6236dae4SAndroid Build Coastguard Worker       uploadfilesize = fileinfo.st_size;
408*6236dae4SAndroid Build Coastguard Worker 
409*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUGBUILD
410*6236dae4SAndroid Build Coastguard Worker     /* allow dedicated test cases to override */
411*6236dae4SAndroid Build Coastguard Worker     {
412*6236dae4SAndroid Build Coastguard Worker       char *ev = getenv("CURL_UPLOAD_SIZE");
413*6236dae4SAndroid Build Coastguard Worker       if(ev) {
414*6236dae4SAndroid Build Coastguard Worker         int sz = atoi(ev);
415*6236dae4SAndroid Build Coastguard Worker         uploadfilesize = (curl_off_t)sz;
416*6236dae4SAndroid Build Coastguard Worker       }
417*6236dae4SAndroid Build Coastguard Worker     }
418*6236dae4SAndroid Build Coastguard Worker #endif
419*6236dae4SAndroid Build Coastguard Worker 
420*6236dae4SAndroid Build Coastguard Worker     if(uploadfilesize != -1) {
421*6236dae4SAndroid Build Coastguard Worker       struct OperationConfig *config = per->config; /* for the macro below */
422*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_DISABLE_LIBCURL_OPTION
423*6236dae4SAndroid Build Coastguard Worker       (void)config;
424*6236dae4SAndroid Build Coastguard Worker       (void)global;
425*6236dae4SAndroid Build Coastguard Worker #endif
426*6236dae4SAndroid Build Coastguard Worker       my_setopt(per->curl, CURLOPT_INFILESIZE_LARGE, uploadfilesize);
427*6236dae4SAndroid Build Coastguard Worker     }
428*6236dae4SAndroid Build Coastguard Worker   }
429*6236dae4SAndroid Build Coastguard Worker   per->uploadfilesize = uploadfilesize;
430*6236dae4SAndroid Build Coastguard Worker   per->start = tvnow();
431*6236dae4SAndroid Build Coastguard Worker   return result;
432*6236dae4SAndroid Build Coastguard Worker }
433*6236dae4SAndroid Build Coastguard Worker 
434*6236dae4SAndroid Build Coastguard Worker /* When doing serial transfers, we use a single fixed error area */
435*6236dae4SAndroid Build Coastguard Worker static char global_errorbuffer[CURL_ERROR_SIZE];
436*6236dae4SAndroid Build Coastguard Worker 
single_transfer_cleanup(struct OperationConfig * config)437*6236dae4SAndroid Build Coastguard Worker void single_transfer_cleanup(struct OperationConfig *config)
438*6236dae4SAndroid Build Coastguard Worker {
439*6236dae4SAndroid Build Coastguard Worker   if(config) {
440*6236dae4SAndroid Build Coastguard Worker     struct State *state = &config->state;
441*6236dae4SAndroid Build Coastguard Worker     /* Free list of remaining URLs */
442*6236dae4SAndroid Build Coastguard Worker     glob_cleanup(&state->urls);
443*6236dae4SAndroid Build Coastguard Worker     Curl_safefree(state->outfiles);
444*6236dae4SAndroid Build Coastguard Worker     Curl_safefree(state->uploadfile);
445*6236dae4SAndroid Build Coastguard Worker     /* Free list of globbed upload files */
446*6236dae4SAndroid Build Coastguard Worker     glob_cleanup(&state->inglob);
447*6236dae4SAndroid Build Coastguard Worker   }
448*6236dae4SAndroid Build Coastguard Worker }
449*6236dae4SAndroid Build Coastguard Worker 
450*6236dae4SAndroid Build Coastguard Worker /*
451*6236dae4SAndroid Build Coastguard Worker  * Call this after a transfer has completed.
452*6236dae4SAndroid Build Coastguard Worker  */
post_per_transfer(struct GlobalConfig * global,struct per_transfer * per,CURLcode result,bool * retryp,long * delay)453*6236dae4SAndroid Build Coastguard Worker static CURLcode post_per_transfer(struct GlobalConfig *global,
454*6236dae4SAndroid Build Coastguard Worker                                   struct per_transfer *per,
455*6236dae4SAndroid Build Coastguard Worker                                   CURLcode result,
456*6236dae4SAndroid Build Coastguard Worker                                   bool *retryp,
457*6236dae4SAndroid Build Coastguard Worker                                   long *delay) /* milliseconds! */
458*6236dae4SAndroid Build Coastguard Worker {
459*6236dae4SAndroid Build Coastguard Worker   struct OutStruct *outs = &per->outs;
460*6236dae4SAndroid Build Coastguard Worker   CURL *curl = per->curl;
461*6236dae4SAndroid Build Coastguard Worker   struct OperationConfig *config = per->config;
462*6236dae4SAndroid Build Coastguard Worker   int rc;
463*6236dae4SAndroid Build Coastguard Worker 
464*6236dae4SAndroid Build Coastguard Worker   *retryp = FALSE;
465*6236dae4SAndroid Build Coastguard Worker   *delay = 0; /* for no retry, keep it zero */
466*6236dae4SAndroid Build Coastguard Worker 
467*6236dae4SAndroid Build Coastguard Worker   if(!curl || !config)
468*6236dae4SAndroid Build Coastguard Worker     return result;
469*6236dae4SAndroid Build Coastguard Worker 
470*6236dae4SAndroid Build Coastguard Worker   if(per->infdopen)
471*6236dae4SAndroid Build Coastguard Worker     close(per->infd);
472*6236dae4SAndroid Build Coastguard Worker 
473*6236dae4SAndroid Build Coastguard Worker   if(per->skip)
474*6236dae4SAndroid Build Coastguard Worker     goto skip;
475*6236dae4SAndroid Build Coastguard Worker 
476*6236dae4SAndroid Build Coastguard Worker #ifdef __VMS
477*6236dae4SAndroid Build Coastguard Worker   if(is_vms_shell()) {
478*6236dae4SAndroid Build Coastguard Worker     /* VMS DCL shell behavior */
479*6236dae4SAndroid Build Coastguard Worker     if(global->silent && !global->showerror)
480*6236dae4SAndroid Build Coastguard Worker       vms_show = VMSSTS_HIDE;
481*6236dae4SAndroid Build Coastguard Worker   }
482*6236dae4SAndroid Build Coastguard Worker   else
483*6236dae4SAndroid Build Coastguard Worker #endif
484*6236dae4SAndroid Build Coastguard Worker     if(!config->synthetic_error && result &&
485*6236dae4SAndroid Build Coastguard Worker        (!global->silent || global->showerror)) {
486*6236dae4SAndroid Build Coastguard Worker       const char *msg = per->errorbuffer;
487*6236dae4SAndroid Build Coastguard Worker       fprintf(tool_stderr, "curl: (%d) %s\n", result,
488*6236dae4SAndroid Build Coastguard Worker               (msg && msg[0]) ? msg : curl_easy_strerror(result));
489*6236dae4SAndroid Build Coastguard Worker       if(result == CURLE_PEER_FAILED_VERIFICATION)
490*6236dae4SAndroid Build Coastguard Worker         fputs(CURL_CA_CERT_ERRORMSG, tool_stderr);
491*6236dae4SAndroid Build Coastguard Worker     }
492*6236dae4SAndroid Build Coastguard Worker     else if(config->failwithbody) {
493*6236dae4SAndroid Build Coastguard Worker       /* if HTTP response >= 400, return error */
494*6236dae4SAndroid Build Coastguard Worker       long code = 0;
495*6236dae4SAndroid Build Coastguard Worker       curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
496*6236dae4SAndroid Build Coastguard Worker       if(code >= 400) {
497*6236dae4SAndroid Build Coastguard Worker         if(!global->silent || global->showerror)
498*6236dae4SAndroid Build Coastguard Worker           fprintf(tool_stderr,
499*6236dae4SAndroid Build Coastguard Worker                   "curl: (%d) The requested URL returned error: %ld\n",
500*6236dae4SAndroid Build Coastguard Worker                   CURLE_HTTP_RETURNED_ERROR, code);
501*6236dae4SAndroid Build Coastguard Worker         result = CURLE_HTTP_RETURNED_ERROR;
502*6236dae4SAndroid Build Coastguard Worker       }
503*6236dae4SAndroid Build Coastguard Worker     }
504*6236dae4SAndroid Build Coastguard Worker   /* Set file extended attributes */
505*6236dae4SAndroid Build Coastguard Worker   if(!result && config->xattr && outs->fopened && outs->stream) {
506*6236dae4SAndroid Build Coastguard Worker     rc = fwrite_xattr(curl, per->url, fileno(outs->stream));
507*6236dae4SAndroid Build Coastguard Worker     if(rc)
508*6236dae4SAndroid Build Coastguard Worker       warnf(config->global, "Error setting extended attributes on '%s': %s",
509*6236dae4SAndroid Build Coastguard Worker             outs->filename, strerror(errno));
510*6236dae4SAndroid Build Coastguard Worker   }
511*6236dae4SAndroid Build Coastguard Worker 
512*6236dae4SAndroid Build Coastguard Worker   if(!result && !outs->stream && !outs->bytes) {
513*6236dae4SAndroid Build Coastguard Worker     /* we have received no data despite the transfer was successful
514*6236dae4SAndroid Build Coastguard Worker        ==> force creation of an empty output file (if an output file
515*6236dae4SAndroid Build Coastguard Worker        was specified) */
516*6236dae4SAndroid Build Coastguard Worker     long cond_unmet = 0L;
517*6236dae4SAndroid Build Coastguard Worker     /* do not create (or even overwrite) the file in case we get no
518*6236dae4SAndroid Build Coastguard Worker        data because of unmet condition */
519*6236dae4SAndroid Build Coastguard Worker     curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &cond_unmet);
520*6236dae4SAndroid Build Coastguard Worker     if(!cond_unmet && !tool_create_output_file(outs, config))
521*6236dae4SAndroid Build Coastguard Worker       result = CURLE_WRITE_ERROR;
522*6236dae4SAndroid Build Coastguard Worker   }
523*6236dae4SAndroid Build Coastguard Worker 
524*6236dae4SAndroid Build Coastguard Worker   if(!outs->s_isreg && outs->stream) {
525*6236dae4SAndroid Build Coastguard Worker     /* Dump standard stream buffered data */
526*6236dae4SAndroid Build Coastguard Worker     rc = fflush(outs->stream);
527*6236dae4SAndroid Build Coastguard Worker     if(!result && rc) {
528*6236dae4SAndroid Build Coastguard Worker       /* something went wrong in the writing process */
529*6236dae4SAndroid Build Coastguard Worker       result = CURLE_WRITE_ERROR;
530*6236dae4SAndroid Build Coastguard Worker       errorf(global, "Failed writing body");
531*6236dae4SAndroid Build Coastguard Worker     }
532*6236dae4SAndroid Build Coastguard Worker   }
533*6236dae4SAndroid Build Coastguard Worker 
534*6236dae4SAndroid Build Coastguard Worker #ifdef _WIN32
535*6236dae4SAndroid Build Coastguard Worker   /* Discard incomplete UTF-8 sequence buffered from body */
536*6236dae4SAndroid Build Coastguard Worker   if(outs->utf8seq[0])
537*6236dae4SAndroid Build Coastguard Worker     memset(outs->utf8seq, 0, sizeof(outs->utf8seq));
538*6236dae4SAndroid Build Coastguard Worker #endif
539*6236dae4SAndroid Build Coastguard Worker 
540*6236dae4SAndroid Build Coastguard Worker   /* if retry-max-time is non-zero, make sure we have not exceeded the
541*6236dae4SAndroid Build Coastguard Worker      time */
542*6236dae4SAndroid Build Coastguard Worker   if(per->retry_remaining &&
543*6236dae4SAndroid Build Coastguard Worker      (!config->retry_maxtime ||
544*6236dae4SAndroid Build Coastguard Worker       (tvdiff(tvnow(), per->retrystart) <
545*6236dae4SAndroid Build Coastguard Worker        config->retry_maxtime*1000L)) ) {
546*6236dae4SAndroid Build Coastguard Worker     enum {
547*6236dae4SAndroid Build Coastguard Worker       RETRY_NO,
548*6236dae4SAndroid Build Coastguard Worker       RETRY_ALL_ERRORS,
549*6236dae4SAndroid Build Coastguard Worker       RETRY_TIMEOUT,
550*6236dae4SAndroid Build Coastguard Worker       RETRY_CONNREFUSED,
551*6236dae4SAndroid Build Coastguard Worker       RETRY_HTTP,
552*6236dae4SAndroid Build Coastguard Worker       RETRY_FTP,
553*6236dae4SAndroid Build Coastguard Worker       RETRY_LAST /* not used */
554*6236dae4SAndroid Build Coastguard Worker     } retry = RETRY_NO;
555*6236dae4SAndroid Build Coastguard Worker     long response = 0;
556*6236dae4SAndroid Build Coastguard Worker     if((CURLE_OPERATION_TIMEDOUT == result) ||
557*6236dae4SAndroid Build Coastguard Worker        (CURLE_COULDNT_RESOLVE_HOST == result) ||
558*6236dae4SAndroid Build Coastguard Worker        (CURLE_COULDNT_RESOLVE_PROXY == result) ||
559*6236dae4SAndroid Build Coastguard Worker        (CURLE_FTP_ACCEPT_TIMEOUT == result))
560*6236dae4SAndroid Build Coastguard Worker       /* retry timeout always */
561*6236dae4SAndroid Build Coastguard Worker       retry = RETRY_TIMEOUT;
562*6236dae4SAndroid Build Coastguard Worker     else if(config->retry_connrefused &&
563*6236dae4SAndroid Build Coastguard Worker             (CURLE_COULDNT_CONNECT == result)) {
564*6236dae4SAndroid Build Coastguard Worker       long oserrno = 0;
565*6236dae4SAndroid Build Coastguard Worker       curl_easy_getinfo(curl, CURLINFO_OS_ERRNO, &oserrno);
566*6236dae4SAndroid Build Coastguard Worker       if(ECONNREFUSED == oserrno)
567*6236dae4SAndroid Build Coastguard Worker         retry = RETRY_CONNREFUSED;
568*6236dae4SAndroid Build Coastguard Worker     }
569*6236dae4SAndroid Build Coastguard Worker     else if((CURLE_OK == result) ||
570*6236dae4SAndroid Build Coastguard Worker             ((config->failonerror || config->failwithbody) &&
571*6236dae4SAndroid Build Coastguard Worker              (CURLE_HTTP_RETURNED_ERROR == result))) {
572*6236dae4SAndroid Build Coastguard Worker       /* If it returned OK. _or_ failonerror was enabled and it
573*6236dae4SAndroid Build Coastguard Worker          returned due to such an error, check for HTTP transient
574*6236dae4SAndroid Build Coastguard Worker          errors to retry on. */
575*6236dae4SAndroid Build Coastguard Worker       const char *scheme;
576*6236dae4SAndroid Build Coastguard Worker       curl_easy_getinfo(curl, CURLINFO_SCHEME, &scheme);
577*6236dae4SAndroid Build Coastguard Worker       scheme = proto_token(scheme);
578*6236dae4SAndroid Build Coastguard Worker       if(scheme == proto_http || scheme == proto_https) {
579*6236dae4SAndroid Build Coastguard Worker         /* This was HTTP(S) */
580*6236dae4SAndroid Build Coastguard Worker         curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
581*6236dae4SAndroid Build Coastguard Worker 
582*6236dae4SAndroid Build Coastguard Worker         switch(response) {
583*6236dae4SAndroid Build Coastguard Worker         case 408: /* Request Timeout */
584*6236dae4SAndroid Build Coastguard Worker         case 429: /* Too Many Requests (RFC6585) */
585*6236dae4SAndroid Build Coastguard Worker         case 500: /* Internal Server Error */
586*6236dae4SAndroid Build Coastguard Worker         case 502: /* Bad Gateway */
587*6236dae4SAndroid Build Coastguard Worker         case 503: /* Service Unavailable */
588*6236dae4SAndroid Build Coastguard Worker         case 504: /* Gateway Timeout */
589*6236dae4SAndroid Build Coastguard Worker           retry = RETRY_HTTP;
590*6236dae4SAndroid Build Coastguard Worker           /*
591*6236dae4SAndroid Build Coastguard Worker            * At this point, we have already written data to the output
592*6236dae4SAndroid Build Coastguard Worker            * file (or terminal). If we write to a file, we must rewind
593*6236dae4SAndroid Build Coastguard Worker            * or close/re-open the file so that the next attempt starts
594*6236dae4SAndroid Build Coastguard Worker            * over from the beginning.
595*6236dae4SAndroid Build Coastguard Worker            *
596*6236dae4SAndroid Build Coastguard Worker            * TODO: similar action for the upload case. We might need
597*6236dae4SAndroid Build Coastguard Worker            * to start over reading from a previous point if we have
598*6236dae4SAndroid Build Coastguard Worker            * uploaded something when this was returned.
599*6236dae4SAndroid Build Coastguard Worker            */
600*6236dae4SAndroid Build Coastguard Worker           break;
601*6236dae4SAndroid Build Coastguard Worker         }
602*6236dae4SAndroid Build Coastguard Worker       }
603*6236dae4SAndroid Build Coastguard Worker     } /* if CURLE_OK */
604*6236dae4SAndroid Build Coastguard Worker     else if(result) {
605*6236dae4SAndroid Build Coastguard Worker       const char *scheme;
606*6236dae4SAndroid Build Coastguard Worker 
607*6236dae4SAndroid Build Coastguard Worker       curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
608*6236dae4SAndroid Build Coastguard Worker       curl_easy_getinfo(curl, CURLINFO_SCHEME, &scheme);
609*6236dae4SAndroid Build Coastguard Worker       scheme = proto_token(scheme);
610*6236dae4SAndroid Build Coastguard Worker 
611*6236dae4SAndroid Build Coastguard Worker       if((scheme == proto_ftp || scheme == proto_ftps) && response / 100 == 4)
612*6236dae4SAndroid Build Coastguard Worker         /*
613*6236dae4SAndroid Build Coastguard Worker          * This is typically when the FTP server only allows a certain
614*6236dae4SAndroid Build Coastguard Worker          * amount of users and we are not one of them. All 4xx codes
615*6236dae4SAndroid Build Coastguard Worker          * are transient.
616*6236dae4SAndroid Build Coastguard Worker          */
617*6236dae4SAndroid Build Coastguard Worker         retry = RETRY_FTP;
618*6236dae4SAndroid Build Coastguard Worker     }
619*6236dae4SAndroid Build Coastguard Worker 
620*6236dae4SAndroid Build Coastguard Worker     if(result && !retry && config->retry_all_errors)
621*6236dae4SAndroid Build Coastguard Worker       retry = RETRY_ALL_ERRORS;
622*6236dae4SAndroid Build Coastguard Worker 
623*6236dae4SAndroid Build Coastguard Worker     if(retry) {
624*6236dae4SAndroid Build Coastguard Worker       long sleeptime = 0;
625*6236dae4SAndroid Build Coastguard Worker       curl_off_t retry_after = 0;
626*6236dae4SAndroid Build Coastguard Worker       static const char * const m[]={
627*6236dae4SAndroid Build Coastguard Worker         NULL,
628*6236dae4SAndroid Build Coastguard Worker         "(retrying all errors)",
629*6236dae4SAndroid Build Coastguard Worker         ": timeout",
630*6236dae4SAndroid Build Coastguard Worker         ": connection refused",
631*6236dae4SAndroid Build Coastguard Worker         ": HTTP error",
632*6236dae4SAndroid Build Coastguard Worker         ": FTP error"
633*6236dae4SAndroid Build Coastguard Worker       };
634*6236dae4SAndroid Build Coastguard Worker 
635*6236dae4SAndroid Build Coastguard Worker       sleeptime = per->retry_sleep;
636*6236dae4SAndroid Build Coastguard Worker       if(RETRY_HTTP == retry) {
637*6236dae4SAndroid Build Coastguard Worker         curl_easy_getinfo(curl, CURLINFO_RETRY_AFTER, &retry_after);
638*6236dae4SAndroid Build Coastguard Worker         if(retry_after) {
639*6236dae4SAndroid Build Coastguard Worker           /* store in a 'long', make sure it does not overflow */
640*6236dae4SAndroid Build Coastguard Worker           if(retry_after > LONG_MAX/1000)
641*6236dae4SAndroid Build Coastguard Worker             sleeptime = LONG_MAX;
642*6236dae4SAndroid Build Coastguard Worker           else if((retry_after * 1000) > sleeptime)
643*6236dae4SAndroid Build Coastguard Worker             sleeptime = (long)retry_after * 1000; /* milliseconds */
644*6236dae4SAndroid Build Coastguard Worker 
645*6236dae4SAndroid Build Coastguard Worker           /* if adding retry_after seconds to the process would exceed the
646*6236dae4SAndroid Build Coastguard Worker              maximum time allowed for retrying, then exit the retries right
647*6236dae4SAndroid Build Coastguard Worker              away */
648*6236dae4SAndroid Build Coastguard Worker           if(config->retry_maxtime) {
649*6236dae4SAndroid Build Coastguard Worker             curl_off_t seconds = tvdiff(tvnow(), per->retrystart)/1000;
650*6236dae4SAndroid Build Coastguard Worker 
651*6236dae4SAndroid Build Coastguard Worker             if((CURL_OFF_T_MAX - retry_after < seconds) ||
652*6236dae4SAndroid Build Coastguard Worker                (seconds + retry_after > config->retry_maxtime)) {
653*6236dae4SAndroid Build Coastguard Worker               warnf(config->global, "The Retry-After: time would "
654*6236dae4SAndroid Build Coastguard Worker                     "make this command line exceed the maximum allowed time "
655*6236dae4SAndroid Build Coastguard Worker                     "for retries.");
656*6236dae4SAndroid Build Coastguard Worker               goto noretry;
657*6236dae4SAndroid Build Coastguard Worker             }
658*6236dae4SAndroid Build Coastguard Worker           }
659*6236dae4SAndroid Build Coastguard Worker         }
660*6236dae4SAndroid Build Coastguard Worker       }
661*6236dae4SAndroid Build Coastguard Worker       warnf(config->global, "Problem %s. "
662*6236dae4SAndroid Build Coastguard Worker             "Will retry in %ld seconds. "
663*6236dae4SAndroid Build Coastguard Worker             "%ld retries left.",
664*6236dae4SAndroid Build Coastguard Worker             m[retry], sleeptime/1000L, per->retry_remaining);
665*6236dae4SAndroid Build Coastguard Worker 
666*6236dae4SAndroid Build Coastguard Worker       per->retry_remaining--;
667*6236dae4SAndroid Build Coastguard Worker       if(!config->retry_delay) {
668*6236dae4SAndroid Build Coastguard Worker         per->retry_sleep *= 2;
669*6236dae4SAndroid Build Coastguard Worker         if(per->retry_sleep > RETRY_SLEEP_MAX)
670*6236dae4SAndroid Build Coastguard Worker           per->retry_sleep = RETRY_SLEEP_MAX;
671*6236dae4SAndroid Build Coastguard Worker       }
672*6236dae4SAndroid Build Coastguard Worker       if(outs->bytes && outs->filename && outs->stream) {
673*6236dae4SAndroid Build Coastguard Worker         /* We have written data to an output file, we truncate file
674*6236dae4SAndroid Build Coastguard Worker          */
675*6236dae4SAndroid Build Coastguard Worker         notef(config->global,
676*6236dae4SAndroid Build Coastguard Worker               "Throwing away %"  CURL_FORMAT_CURL_OFF_T " bytes",
677*6236dae4SAndroid Build Coastguard Worker               outs->bytes);
678*6236dae4SAndroid Build Coastguard Worker         fflush(outs->stream);
679*6236dae4SAndroid Build Coastguard Worker         /* truncate file at the position where we started appending */
680*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_FTRUNCATE
681*6236dae4SAndroid Build Coastguard Worker         if(ftruncate(fileno(outs->stream), outs->init)) {
682*6236dae4SAndroid Build Coastguard Worker           /* when truncate fails, we cannot just append as then we will
683*6236dae4SAndroid Build Coastguard Worker              create something strange, bail out */
684*6236dae4SAndroid Build Coastguard Worker           errorf(config->global, "Failed to truncate file");
685*6236dae4SAndroid Build Coastguard Worker           return CURLE_WRITE_ERROR;
686*6236dae4SAndroid Build Coastguard Worker         }
687*6236dae4SAndroid Build Coastguard Worker         /* now seek to the end of the file, the position where we
688*6236dae4SAndroid Build Coastguard Worker            just truncated the file in a large file-safe way */
689*6236dae4SAndroid Build Coastguard Worker         rc = fseek(outs->stream, 0, SEEK_END);
690*6236dae4SAndroid Build Coastguard Worker #else
691*6236dae4SAndroid Build Coastguard Worker         /* ftruncate is not available, so just reposition the file
692*6236dae4SAndroid Build Coastguard Worker            to the location we would have truncated it. This will not
693*6236dae4SAndroid Build Coastguard Worker            work properly with large files on 32-bit systems, but
694*6236dae4SAndroid Build Coastguard Worker            most of those will have ftruncate. */
695*6236dae4SAndroid Build Coastguard Worker         rc = fseek(outs->stream, (long)outs->init, SEEK_SET);
696*6236dae4SAndroid Build Coastguard Worker #endif
697*6236dae4SAndroid Build Coastguard Worker         if(rc) {
698*6236dae4SAndroid Build Coastguard Worker           errorf(config->global, "Failed seeking to end of file");
699*6236dae4SAndroid Build Coastguard Worker           return CURLE_WRITE_ERROR;
700*6236dae4SAndroid Build Coastguard Worker         }
701*6236dae4SAndroid Build Coastguard Worker         outs->bytes = 0; /* clear for next round */
702*6236dae4SAndroid Build Coastguard Worker       }
703*6236dae4SAndroid Build Coastguard Worker       *retryp = TRUE;
704*6236dae4SAndroid Build Coastguard Worker       per->num_retries++;
705*6236dae4SAndroid Build Coastguard Worker       *delay = sleeptime;
706*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
707*6236dae4SAndroid Build Coastguard Worker     }
708*6236dae4SAndroid Build Coastguard Worker   } /* if retry_remaining */
709*6236dae4SAndroid Build Coastguard Worker noretry:
710*6236dae4SAndroid Build Coastguard Worker 
711*6236dae4SAndroid Build Coastguard Worker   if((global->progressmode == CURL_PROGRESS_BAR) &&
712*6236dae4SAndroid Build Coastguard Worker      per->progressbar.calls)
713*6236dae4SAndroid Build Coastguard Worker     /* if the custom progress bar has been displayed, we output a
714*6236dae4SAndroid Build Coastguard Worker        newline here */
715*6236dae4SAndroid Build Coastguard Worker     fputs("\n", per->progressbar.out);
716*6236dae4SAndroid Build Coastguard Worker 
717*6236dae4SAndroid Build Coastguard Worker   /* Close the outs file */
718*6236dae4SAndroid Build Coastguard Worker   if(outs->fopened && outs->stream) {
719*6236dae4SAndroid Build Coastguard Worker     rc = fclose(outs->stream);
720*6236dae4SAndroid Build Coastguard Worker     if(!result && rc) {
721*6236dae4SAndroid Build Coastguard Worker       /* something went wrong in the writing process */
722*6236dae4SAndroid Build Coastguard Worker       result = CURLE_WRITE_ERROR;
723*6236dae4SAndroid Build Coastguard Worker       errorf(config->global, "curl: (%d) Failed writing body", result);
724*6236dae4SAndroid Build Coastguard Worker     }
725*6236dae4SAndroid Build Coastguard Worker     if(result && config->rm_partial) {
726*6236dae4SAndroid Build Coastguard Worker       struct_stat st;
727*6236dae4SAndroid Build Coastguard Worker       if(!stat(outs->filename, &st) &&
728*6236dae4SAndroid Build Coastguard Worker          S_ISREG(st.st_mode)) {
729*6236dae4SAndroid Build Coastguard Worker         if(!unlink(outs->filename))
730*6236dae4SAndroid Build Coastguard Worker           notef(global, "Removed output file: %s", outs->filename);
731*6236dae4SAndroid Build Coastguard Worker         else
732*6236dae4SAndroid Build Coastguard Worker           warnf(global, "Failed removing: %s", outs->filename);
733*6236dae4SAndroid Build Coastguard Worker       }
734*6236dae4SAndroid Build Coastguard Worker       else
735*6236dae4SAndroid Build Coastguard Worker         warnf(global, "Skipping removal; not a regular file: %s",
736*6236dae4SAndroid Build Coastguard Worker               outs->filename);
737*6236dae4SAndroid Build Coastguard Worker     }
738*6236dae4SAndroid Build Coastguard Worker   }
739*6236dae4SAndroid Build Coastguard Worker 
740*6236dae4SAndroid Build Coastguard Worker   /* File time can only be set _after_ the file has been closed */
741*6236dae4SAndroid Build Coastguard Worker   if(!result && config->remote_time && outs->s_isreg && outs->filename) {
742*6236dae4SAndroid Build Coastguard Worker     /* Ask libcurl if we got a remote file time */
743*6236dae4SAndroid Build Coastguard Worker     curl_off_t filetime = -1;
744*6236dae4SAndroid Build Coastguard Worker     curl_easy_getinfo(curl, CURLINFO_FILETIME_T, &filetime);
745*6236dae4SAndroid Build Coastguard Worker     setfiletime(filetime, outs->filename, global);
746*6236dae4SAndroid Build Coastguard Worker   }
747*6236dae4SAndroid Build Coastguard Worker skip:
748*6236dae4SAndroid Build Coastguard Worker   /* Write the --write-out data before cleanup but after result is final */
749*6236dae4SAndroid Build Coastguard Worker   if(config->writeout)
750*6236dae4SAndroid Build Coastguard Worker     ourWriteOut(config, per, result);
751*6236dae4SAndroid Build Coastguard Worker 
752*6236dae4SAndroid Build Coastguard Worker   /* Close function-local opened file descriptors */
753*6236dae4SAndroid Build Coastguard Worker   if(per->heads.fopened && per->heads.stream)
754*6236dae4SAndroid Build Coastguard Worker     fclose(per->heads.stream);
755*6236dae4SAndroid Build Coastguard Worker 
756*6236dae4SAndroid Build Coastguard Worker   if(per->heads.alloc_filename)
757*6236dae4SAndroid Build Coastguard Worker     Curl_safefree(per->heads.filename);
758*6236dae4SAndroid Build Coastguard Worker 
759*6236dae4SAndroid Build Coastguard Worker   if(per->etag_save.fopened && per->etag_save.stream)
760*6236dae4SAndroid Build Coastguard Worker     fclose(per->etag_save.stream);
761*6236dae4SAndroid Build Coastguard Worker 
762*6236dae4SAndroid Build Coastguard Worker   if(per->etag_save.alloc_filename)
763*6236dae4SAndroid Build Coastguard Worker     Curl_safefree(per->etag_save.filename);
764*6236dae4SAndroid Build Coastguard Worker 
765*6236dae4SAndroid Build Coastguard Worker   curl_easy_cleanup(per->curl);
766*6236dae4SAndroid Build Coastguard Worker   if(outs->alloc_filename)
767*6236dae4SAndroid Build Coastguard Worker     free(outs->filename);
768*6236dae4SAndroid Build Coastguard Worker   free(per->url);
769*6236dae4SAndroid Build Coastguard Worker   free(per->outfile);
770*6236dae4SAndroid Build Coastguard Worker   free(per->uploadfile);
771*6236dae4SAndroid Build Coastguard Worker   if(global->parallel)
772*6236dae4SAndroid Build Coastguard Worker     free(per->errorbuffer);
773*6236dae4SAndroid Build Coastguard Worker   curl_slist_free_all(per->hdrcbdata.headlist);
774*6236dae4SAndroid Build Coastguard Worker   per->hdrcbdata.headlist = NULL;
775*6236dae4SAndroid Build Coastguard Worker   return result;
776*6236dae4SAndroid Build Coastguard Worker }
777*6236dae4SAndroid Build Coastguard Worker 
778*6236dae4SAndroid Build Coastguard Worker /*
779*6236dae4SAndroid Build Coastguard Worker  * Possibly rewrite the URL for IPFS and return the protocol token for the
780*6236dae4SAndroid Build Coastguard Worker  * scheme used in the given URL.
781*6236dae4SAndroid Build Coastguard Worker  */
url_proto_and_rewrite(char ** url,struct OperationConfig * config,const char ** scheme)782*6236dae4SAndroid Build Coastguard Worker static CURLcode url_proto_and_rewrite(char **url,
783*6236dae4SAndroid Build Coastguard Worker                                       struct OperationConfig *config,
784*6236dae4SAndroid Build Coastguard Worker                                       const char **scheme)
785*6236dae4SAndroid Build Coastguard Worker {
786*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
787*6236dae4SAndroid Build Coastguard Worker   CURLU *uh = curl_url();
788*6236dae4SAndroid Build Coastguard Worker   const char *proto = NULL;
789*6236dae4SAndroid Build Coastguard Worker   *scheme = NULL;
790*6236dae4SAndroid Build Coastguard Worker 
791*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(url && *url);
792*6236dae4SAndroid Build Coastguard Worker   if(uh) {
793*6236dae4SAndroid Build Coastguard Worker     char *schemep = NULL;
794*6236dae4SAndroid Build Coastguard Worker     if(!curl_url_set(uh, CURLUPART_URL, *url,
795*6236dae4SAndroid Build Coastguard Worker                      CURLU_GUESS_SCHEME | CURLU_NON_SUPPORT_SCHEME) &&
796*6236dae4SAndroid Build Coastguard Worker        !curl_url_get(uh, CURLUPART_SCHEME, &schemep,
797*6236dae4SAndroid Build Coastguard Worker                      CURLU_DEFAULT_SCHEME)) {
798*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_DISABLE_IPFS
799*6236dae4SAndroid Build Coastguard Worker       (void)config;
800*6236dae4SAndroid Build Coastguard Worker #else
801*6236dae4SAndroid Build Coastguard Worker       if(curl_strequal(schemep, proto_ipfs) ||
802*6236dae4SAndroid Build Coastguard Worker          curl_strequal(schemep, proto_ipns)) {
803*6236dae4SAndroid Build Coastguard Worker         result = ipfs_url_rewrite(uh, schemep, url, config);
804*6236dae4SAndroid Build Coastguard Worker         /* short-circuit proto_token, we know it is ipfs or ipns */
805*6236dae4SAndroid Build Coastguard Worker         if(curl_strequal(schemep, proto_ipfs))
806*6236dae4SAndroid Build Coastguard Worker           proto = proto_ipfs;
807*6236dae4SAndroid Build Coastguard Worker         else if(curl_strequal(schemep, proto_ipns))
808*6236dae4SAndroid Build Coastguard Worker           proto = proto_ipns;
809*6236dae4SAndroid Build Coastguard Worker         if(result)
810*6236dae4SAndroid Build Coastguard Worker           config->synthetic_error = TRUE;
811*6236dae4SAndroid Build Coastguard Worker       }
812*6236dae4SAndroid Build Coastguard Worker       else
813*6236dae4SAndroid Build Coastguard Worker #endif /* !CURL_DISABLE_IPFS */
814*6236dae4SAndroid Build Coastguard Worker         proto = proto_token(schemep);
815*6236dae4SAndroid Build Coastguard Worker 
816*6236dae4SAndroid Build Coastguard Worker       curl_free(schemep);
817*6236dae4SAndroid Build Coastguard Worker     }
818*6236dae4SAndroid Build Coastguard Worker     curl_url_cleanup(uh);
819*6236dae4SAndroid Build Coastguard Worker   }
820*6236dae4SAndroid Build Coastguard Worker   else
821*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OUT_OF_MEMORY;
822*6236dae4SAndroid Build Coastguard Worker 
823*6236dae4SAndroid Build Coastguard Worker   *scheme = proto ? proto : "?"; /* Never match if not found. */
824*6236dae4SAndroid Build Coastguard Worker   return result;
825*6236dae4SAndroid Build Coastguard Worker }
826*6236dae4SAndroid Build Coastguard Worker 
827*6236dae4SAndroid Build Coastguard Worker /* return current SSL backend name, chop off multissl */
ssl_backend(void)828*6236dae4SAndroid Build Coastguard Worker static char *ssl_backend(void)
829*6236dae4SAndroid Build Coastguard Worker {
830*6236dae4SAndroid Build Coastguard Worker   static char ssl_ver[80] = "no ssl";
831*6236dae4SAndroid Build Coastguard Worker   static bool already = FALSE;
832*6236dae4SAndroid Build Coastguard Worker   if(!already) { /* if there is no existing version */
833*6236dae4SAndroid Build Coastguard Worker     const char *v = curl_version_info(CURLVERSION_NOW)->ssl_version;
834*6236dae4SAndroid Build Coastguard Worker     if(v)
835*6236dae4SAndroid Build Coastguard Worker       msnprintf(ssl_ver, sizeof(ssl_ver), "%.*s", (int) strcspn(v, " "), v);
836*6236dae4SAndroid Build Coastguard Worker     already = TRUE;
837*6236dae4SAndroid Build Coastguard Worker   }
838*6236dae4SAndroid Build Coastguard Worker   return ssl_ver;
839*6236dae4SAndroid Build Coastguard Worker }
840*6236dae4SAndroid Build Coastguard Worker 
set_cert_types(struct OperationConfig * config)841*6236dae4SAndroid Build Coastguard Worker static CURLcode set_cert_types(struct OperationConfig *config)
842*6236dae4SAndroid Build Coastguard Worker {
843*6236dae4SAndroid Build Coastguard Worker   if(feature_ssl) {
844*6236dae4SAndroid Build Coastguard Worker     /* Check if config->cert is a PKCS#11 URI and set the config->cert_type if
845*6236dae4SAndroid Build Coastguard Worker      * necessary */
846*6236dae4SAndroid Build Coastguard Worker     if(config->cert && !config->cert_type && is_pkcs11_uri(config->cert)) {
847*6236dae4SAndroid Build Coastguard Worker       config->cert_type = strdup("ENG");
848*6236dae4SAndroid Build Coastguard Worker       if(!config->cert_type)
849*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
850*6236dae4SAndroid Build Coastguard Worker     }
851*6236dae4SAndroid Build Coastguard Worker 
852*6236dae4SAndroid Build Coastguard Worker     /* Check if config->key is a PKCS#11 URI and set the config->key_type if
853*6236dae4SAndroid Build Coastguard Worker      * necessary */
854*6236dae4SAndroid Build Coastguard Worker     if(config->key && !config->key_type && is_pkcs11_uri(config->key)) {
855*6236dae4SAndroid Build Coastguard Worker       config->key_type = strdup("ENG");
856*6236dae4SAndroid Build Coastguard Worker       if(!config->key_type)
857*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
858*6236dae4SAndroid Build Coastguard Worker     }
859*6236dae4SAndroid Build Coastguard Worker 
860*6236dae4SAndroid Build Coastguard Worker     /* Check if config->proxy_cert is a PKCS#11 URI and set the
861*6236dae4SAndroid Build Coastguard Worker      * config->proxy_type if necessary */
862*6236dae4SAndroid Build Coastguard Worker     if(config->proxy_cert && !config->proxy_cert_type &&
863*6236dae4SAndroid Build Coastguard Worker        is_pkcs11_uri(config->proxy_cert)) {
864*6236dae4SAndroid Build Coastguard Worker       config->proxy_cert_type = strdup("ENG");
865*6236dae4SAndroid Build Coastguard Worker       if(!config->proxy_cert_type)
866*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
867*6236dae4SAndroid Build Coastguard Worker     }
868*6236dae4SAndroid Build Coastguard Worker 
869*6236dae4SAndroid Build Coastguard Worker     /* Check if config->proxy_key is a PKCS#11 URI and set the
870*6236dae4SAndroid Build Coastguard Worker      * config->proxy_key_type if necessary */
871*6236dae4SAndroid Build Coastguard Worker     if(config->proxy_key && !config->proxy_key_type &&
872*6236dae4SAndroid Build Coastguard Worker        is_pkcs11_uri(config->proxy_key)) {
873*6236dae4SAndroid Build Coastguard Worker       config->proxy_key_type = strdup("ENG");
874*6236dae4SAndroid Build Coastguard Worker       if(!config->proxy_key_type)
875*6236dae4SAndroid Build Coastguard Worker         return CURLE_OUT_OF_MEMORY;
876*6236dae4SAndroid Build Coastguard Worker     }
877*6236dae4SAndroid Build Coastguard Worker   }
878*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
879*6236dae4SAndroid Build Coastguard Worker }
880*6236dae4SAndroid Build Coastguard Worker 
config2setopts(struct GlobalConfig * global,struct OperationConfig * config,struct per_transfer * per,bool capath_from_env,CURL * curl,CURLSH * share)881*6236dae4SAndroid Build Coastguard Worker static CURLcode config2setopts(struct GlobalConfig *global,
882*6236dae4SAndroid Build Coastguard Worker                                struct OperationConfig *config,
883*6236dae4SAndroid Build Coastguard Worker                                struct per_transfer *per,
884*6236dae4SAndroid Build Coastguard Worker                                bool capath_from_env,
885*6236dae4SAndroid Build Coastguard Worker                                CURL *curl,
886*6236dae4SAndroid Build Coastguard Worker                                CURLSH *share)
887*6236dae4SAndroid Build Coastguard Worker {
888*6236dae4SAndroid Build Coastguard Worker   const char *use_proto;
889*6236dae4SAndroid Build Coastguard Worker   CURLcode result = url_proto_and_rewrite(&per->url, config, &use_proto);
890*6236dae4SAndroid Build Coastguard Worker 
891*6236dae4SAndroid Build Coastguard Worker   /* Avoid having this setopt added to the --libcurl source output. */
892*6236dae4SAndroid Build Coastguard Worker   if(!result)
893*6236dae4SAndroid Build Coastguard Worker     result = curl_easy_setopt(curl, CURLOPT_SHARE, share);
894*6236dae4SAndroid Build Coastguard Worker   if(result)
895*6236dae4SAndroid Build Coastguard Worker     return result;
896*6236dae4SAndroid Build Coastguard Worker 
897*6236dae4SAndroid Build Coastguard Worker #ifndef DEBUGBUILD
898*6236dae4SAndroid Build Coastguard Worker   /* On most modern OSes, exiting works thoroughly,
899*6236dae4SAndroid Build Coastguard Worker      we will clean everything up via exit(), so do not bother with
900*6236dae4SAndroid Build Coastguard Worker      slow cleanups. Crappy ones might need to skip this.
901*6236dae4SAndroid Build Coastguard Worker      Note: avoid having this setopt added to the --libcurl source
902*6236dae4SAndroid Build Coastguard Worker      output. */
903*6236dae4SAndroid Build Coastguard Worker   result = curl_easy_setopt(curl, CURLOPT_QUICK_EXIT, 1L);
904*6236dae4SAndroid Build Coastguard Worker   if(result)
905*6236dae4SAndroid Build Coastguard Worker     return result;
906*6236dae4SAndroid Build Coastguard Worker #endif
907*6236dae4SAndroid Build Coastguard Worker 
908*6236dae4SAndroid Build Coastguard Worker   if(!config->tcp_nodelay)
909*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_TCP_NODELAY, 0L);
910*6236dae4SAndroid Build Coastguard Worker 
911*6236dae4SAndroid Build Coastguard Worker   if(config->tcp_fastopen)
912*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_TCP_FASTOPEN, 1L);
913*6236dae4SAndroid Build Coastguard Worker 
914*6236dae4SAndroid Build Coastguard Worker   if(config->mptcp)
915*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_OPENSOCKETFUNCTION,
916*6236dae4SAndroid Build Coastguard Worker               tool_socket_open_mptcp_cb);
917*6236dae4SAndroid Build Coastguard Worker 
918*6236dae4SAndroid Build Coastguard Worker   /* where to store */
919*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_WRITEDATA, per);
920*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_INTERLEAVEDATA, per);
921*6236dae4SAndroid Build Coastguard Worker 
922*6236dae4SAndroid Build Coastguard Worker   /* what call to write */
923*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb);
924*6236dae4SAndroid Build Coastguard Worker 
925*6236dae4SAndroid Build Coastguard Worker   /* Note that if CURLOPT_READFUNCTION is fread (the default), then
926*6236dae4SAndroid Build Coastguard Worker    * lib/telnet.c will Curl_poll() on the input file descriptor
927*6236dae4SAndroid Build Coastguard Worker    * rather than calling the READFUNCTION at regular intervals.
928*6236dae4SAndroid Build Coastguard Worker    * The circumstances in which it is preferable to enable this
929*6236dae4SAndroid Build Coastguard Worker    * behavior, by omitting to set the READFUNCTION & READDATA options,
930*6236dae4SAndroid Build Coastguard Worker    * have not been determined.
931*6236dae4SAndroid Build Coastguard Worker    */
932*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_READDATA, per);
933*6236dae4SAndroid Build Coastguard Worker   /* what call to read */
934*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_READFUNCTION, tool_read_cb);
935*6236dae4SAndroid Build Coastguard Worker 
936*6236dae4SAndroid Build Coastguard Worker   /* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what
937*6236dae4SAndroid Build Coastguard Worker      CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */
938*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_SEEKDATA, per);
939*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb);
940*6236dae4SAndroid Build Coastguard Worker 
941*6236dae4SAndroid Build Coastguard Worker   {
942*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUGBUILD
943*6236dae4SAndroid Build Coastguard Worker     char *env = getenv("CURL_BUFFERSIZE");
944*6236dae4SAndroid Build Coastguard Worker     if(env) {
945*6236dae4SAndroid Build Coastguard Worker       long size = strtol(env, NULL, 10);
946*6236dae4SAndroid Build Coastguard Worker       if(size)
947*6236dae4SAndroid Build Coastguard Worker         my_setopt(curl, CURLOPT_BUFFERSIZE, size);
948*6236dae4SAndroid Build Coastguard Worker     }
949*6236dae4SAndroid Build Coastguard Worker     else
950*6236dae4SAndroid Build Coastguard Worker #endif
951*6236dae4SAndroid Build Coastguard Worker       if(config->recvpersecond &&
952*6236dae4SAndroid Build Coastguard Worker          (config->recvpersecond < BUFFER_SIZE))
953*6236dae4SAndroid Build Coastguard Worker         /* use a smaller sized buffer for better sleeps */
954*6236dae4SAndroid Build Coastguard Worker         my_setopt(curl, CURLOPT_BUFFERSIZE, (long)config->recvpersecond);
955*6236dae4SAndroid Build Coastguard Worker       else
956*6236dae4SAndroid Build Coastguard Worker         my_setopt(curl, CURLOPT_BUFFERSIZE, (long)BUFFER_SIZE);
957*6236dae4SAndroid Build Coastguard Worker   }
958*6236dae4SAndroid Build Coastguard Worker 
959*6236dae4SAndroid Build Coastguard Worker   my_setopt_str(curl, CURLOPT_URL, per->url);
960*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_NOPROGRESS,
961*6236dae4SAndroid Build Coastguard Worker             global->noprogress || global->silent ? 1L : 0L);
962*6236dae4SAndroid Build Coastguard Worker   if(config->no_body)
963*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_NOBODY, 1L);
964*6236dae4SAndroid Build Coastguard Worker 
965*6236dae4SAndroid Build Coastguard Worker   if(config->oauth_bearer)
966*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_XOAUTH2_BEARER, config->oauth_bearer);
967*6236dae4SAndroid Build Coastguard Worker 
968*6236dae4SAndroid Build Coastguard Worker   my_setopt_str(curl, CURLOPT_PROXY, config->proxy);
969*6236dae4SAndroid Build Coastguard Worker 
970*6236dae4SAndroid Build Coastguard Worker   if(config->proxy && result) {
971*6236dae4SAndroid Build Coastguard Worker     errorf(global, "proxy support is disabled in this libcurl");
972*6236dae4SAndroid Build Coastguard Worker     config->synthetic_error = TRUE;
973*6236dae4SAndroid Build Coastguard Worker     return CURLE_NOT_BUILT_IN;
974*6236dae4SAndroid Build Coastguard Worker   }
975*6236dae4SAndroid Build Coastguard Worker 
976*6236dae4SAndroid Build Coastguard Worker   /* new in libcurl 7.5 */
977*6236dae4SAndroid Build Coastguard Worker   if(config->proxy)
978*6236dae4SAndroid Build Coastguard Worker     my_setopt_enum(curl, CURLOPT_PROXYTYPE, config->proxyver);
979*6236dae4SAndroid Build Coastguard Worker 
980*6236dae4SAndroid Build Coastguard Worker   my_setopt_str(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
981*6236dae4SAndroid Build Coastguard Worker 
982*6236dae4SAndroid Build Coastguard Worker   /* new in libcurl 7.3 */
983*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel ?
984*6236dae4SAndroid Build Coastguard Worker             1L : 0L);
985*6236dae4SAndroid Build Coastguard Worker 
986*6236dae4SAndroid Build Coastguard Worker   /* new in libcurl 7.52.0 */
987*6236dae4SAndroid Build Coastguard Worker   if(config->preproxy)
988*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_PRE_PROXY, config->preproxy);
989*6236dae4SAndroid Build Coastguard Worker 
990*6236dae4SAndroid Build Coastguard Worker   /* new in libcurl 7.10.6 */
991*6236dae4SAndroid Build Coastguard Worker   if(config->proxyanyauth)
992*6236dae4SAndroid Build Coastguard Worker     my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, (long)CURLAUTH_ANY);
993*6236dae4SAndroid Build Coastguard Worker   else if(config->proxynegotiate)
994*6236dae4SAndroid Build Coastguard Worker     my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_GSSNEGOTIATE);
995*6236dae4SAndroid Build Coastguard Worker   else if(config->proxyntlm)
996*6236dae4SAndroid Build Coastguard Worker     my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
997*6236dae4SAndroid Build Coastguard Worker   else if(config->proxydigest)
998*6236dae4SAndroid Build Coastguard Worker     my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);
999*6236dae4SAndroid Build Coastguard Worker   else if(config->proxybasic)
1000*6236dae4SAndroid Build Coastguard Worker     my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
1001*6236dae4SAndroid Build Coastguard Worker 
1002*6236dae4SAndroid Build Coastguard Worker   /* new in libcurl 7.19.4 */
1003*6236dae4SAndroid Build Coastguard Worker   my_setopt_str(curl, CURLOPT_NOPROXY, config->noproxy);
1004*6236dae4SAndroid Build Coastguard Worker 
1005*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_SUPPRESS_CONNECT_HEADERS,
1006*6236dae4SAndroid Build Coastguard Worker             config->suppress_connect_headers ? 1L : 0L);
1007*6236dae4SAndroid Build Coastguard Worker 
1008*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_FAILONERROR, config->failonerror ? 1L : 0L);
1009*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_REQUEST_TARGET, config->request_target);
1010*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_UPLOAD, per->uploadfile ? 1L : 0L);
1011*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_DIRLISTONLY, config->dirlistonly ? 1L : 0L);
1012*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_APPEND, config->ftp_append ? 1L : 0L);
1013*6236dae4SAndroid Build Coastguard Worker 
1014*6236dae4SAndroid Build Coastguard Worker   if(config->netrc_opt)
1015*6236dae4SAndroid Build Coastguard Worker     my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_OPTIONAL);
1016*6236dae4SAndroid Build Coastguard Worker   else if(config->netrc || config->netrc_file)
1017*6236dae4SAndroid Build Coastguard Worker     my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_REQUIRED);
1018*6236dae4SAndroid Build Coastguard Worker   else
1019*6236dae4SAndroid Build Coastguard Worker     my_setopt_enum(curl, CURLOPT_NETRC, (long)CURL_NETRC_IGNORED);
1020*6236dae4SAndroid Build Coastguard Worker 
1021*6236dae4SAndroid Build Coastguard Worker   if(config->netrc_file)
1022*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_NETRC_FILE, config->netrc_file);
1023*6236dae4SAndroid Build Coastguard Worker 
1024*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_TRANSFERTEXT, config->use_ascii ? 1L : 0L);
1025*6236dae4SAndroid Build Coastguard Worker   if(config->login_options)
1026*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_LOGIN_OPTIONS, config->login_options);
1027*6236dae4SAndroid Build Coastguard Worker   my_setopt_str(curl, CURLOPT_USERPWD, config->userpwd);
1028*6236dae4SAndroid Build Coastguard Worker   my_setopt_str(curl, CURLOPT_RANGE, config->range);
1029*6236dae4SAndroid Build Coastguard Worker   if(!global->parallel) {
1030*6236dae4SAndroid Build Coastguard Worker     per->errorbuffer = global_errorbuffer;
1031*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_ERRORBUFFER, global_errorbuffer);
1032*6236dae4SAndroid Build Coastguard Worker   }
1033*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_TIMEOUT_MS, config->timeout_ms);
1034*6236dae4SAndroid Build Coastguard Worker 
1035*6236dae4SAndroid Build Coastguard Worker   switch(config->httpreq) {
1036*6236dae4SAndroid Build Coastguard Worker   case TOOL_HTTPREQ_SIMPLEPOST:
1037*6236dae4SAndroid Build Coastguard Worker     if(config->resume_from) {
1038*6236dae4SAndroid Build Coastguard Worker       errorf(global, "cannot mix --continue-at with --data");
1039*6236dae4SAndroid Build Coastguard Worker       result = CURLE_FAILED_INIT;
1040*6236dae4SAndroid Build Coastguard Worker     }
1041*6236dae4SAndroid Build Coastguard Worker     else {
1042*6236dae4SAndroid Build Coastguard Worker       my_setopt_str(curl, CURLOPT_POSTFIELDS,
1043*6236dae4SAndroid Build Coastguard Worker                     curlx_dyn_ptr(&config->postdata));
1044*6236dae4SAndroid Build Coastguard Worker       my_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
1045*6236dae4SAndroid Build Coastguard Worker                 (curl_off_t)curlx_dyn_len(&config->postdata));
1046*6236dae4SAndroid Build Coastguard Worker     }
1047*6236dae4SAndroid Build Coastguard Worker     break;
1048*6236dae4SAndroid Build Coastguard Worker   case TOOL_HTTPREQ_MIMEPOST:
1049*6236dae4SAndroid Build Coastguard Worker     /* free previous remainders */
1050*6236dae4SAndroid Build Coastguard Worker     curl_mime_free(config->mimepost);
1051*6236dae4SAndroid Build Coastguard Worker     config->mimepost = NULL;
1052*6236dae4SAndroid Build Coastguard Worker     if(config->resume_from) {
1053*6236dae4SAndroid Build Coastguard Worker       errorf(global, "cannot mix --continue-at with --form");
1054*6236dae4SAndroid Build Coastguard Worker       result = CURLE_FAILED_INIT;
1055*6236dae4SAndroid Build Coastguard Worker     }
1056*6236dae4SAndroid Build Coastguard Worker     else {
1057*6236dae4SAndroid Build Coastguard Worker       result = tool2curlmime(curl, config->mimeroot, &config->mimepost);
1058*6236dae4SAndroid Build Coastguard Worker       if(!result)
1059*6236dae4SAndroid Build Coastguard Worker         my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost);
1060*6236dae4SAndroid Build Coastguard Worker     }
1061*6236dae4SAndroid Build Coastguard Worker     break;
1062*6236dae4SAndroid Build Coastguard Worker   default:
1063*6236dae4SAndroid Build Coastguard Worker     break;
1064*6236dae4SAndroid Build Coastguard Worker   }
1065*6236dae4SAndroid Build Coastguard Worker   if(result)
1066*6236dae4SAndroid Build Coastguard Worker     return result;
1067*6236dae4SAndroid Build Coastguard Worker 
1068*6236dae4SAndroid Build Coastguard Worker   /* new in libcurl 7.81.0 */
1069*6236dae4SAndroid Build Coastguard Worker   if(config->mime_options)
1070*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_MIME_OPTIONS, config->mime_options);
1071*6236dae4SAndroid Build Coastguard Worker 
1072*6236dae4SAndroid Build Coastguard Worker   /* new in libcurl 7.10.6 (default is Basic) */
1073*6236dae4SAndroid Build Coastguard Worker   if(config->authtype)
1074*6236dae4SAndroid Build Coastguard Worker     my_setopt_bitmask(curl, CURLOPT_HTTPAUTH, (long)config->authtype);
1075*6236dae4SAndroid Build Coastguard Worker 
1076*6236dae4SAndroid Build Coastguard Worker   my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers);
1077*6236dae4SAndroid Build Coastguard Worker 
1078*6236dae4SAndroid Build Coastguard Worker   if(proto_http || proto_rtsp) {
1079*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_REFERER, config->referer);
1080*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent);
1081*6236dae4SAndroid Build Coastguard Worker   }
1082*6236dae4SAndroid Build Coastguard Worker 
1083*6236dae4SAndroid Build Coastguard Worker   if(proto_http) {
1084*6236dae4SAndroid Build Coastguard Worker     long postRedir = 0;
1085*6236dae4SAndroid Build Coastguard Worker 
1086*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_FOLLOWLOCATION,
1087*6236dae4SAndroid Build Coastguard Worker               config->followlocation ? 1L : 0L);
1088*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_UNRESTRICTED_AUTH,
1089*6236dae4SAndroid Build Coastguard Worker               config->unrestricted_auth ? 1L : 0L);
1090*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_AWS_SIGV4, config->aws_sigv4);
1091*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_AUTOREFERER, config->autoreferer ? 1L : 0L);
1092*6236dae4SAndroid Build Coastguard Worker 
1093*6236dae4SAndroid Build Coastguard Worker     /* new in libcurl 7.36.0 */
1094*6236dae4SAndroid Build Coastguard Worker     if(config->proxyheaders) {
1095*6236dae4SAndroid Build Coastguard Worker       my_setopt_slist(curl, CURLOPT_PROXYHEADER, config->proxyheaders);
1096*6236dae4SAndroid Build Coastguard Worker       my_setopt(curl, CURLOPT_HEADEROPT, (long)CURLHEADER_SEPARATE);
1097*6236dae4SAndroid Build Coastguard Worker     }
1098*6236dae4SAndroid Build Coastguard Worker 
1099*6236dae4SAndroid Build Coastguard Worker     /* new in libcurl 7.5 */
1100*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_MAXREDIRS, config->maxredirs);
1101*6236dae4SAndroid Build Coastguard Worker 
1102*6236dae4SAndroid Build Coastguard Worker     if(config->httpversion)
1103*6236dae4SAndroid Build Coastguard Worker       my_setopt_enum(curl, CURLOPT_HTTP_VERSION, config->httpversion);
1104*6236dae4SAndroid Build Coastguard Worker     else if(feature_http2)
1105*6236dae4SAndroid Build Coastguard Worker       my_setopt_enum(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
1106*6236dae4SAndroid Build Coastguard Worker 
1107*6236dae4SAndroid Build Coastguard Worker     /* curl 7.19.1 (the 301 version existed in 7.18.2),
1108*6236dae4SAndroid Build Coastguard Worker        303 was added in 7.26.0 */
1109*6236dae4SAndroid Build Coastguard Worker     if(config->post301)
1110*6236dae4SAndroid Build Coastguard Worker       postRedir |= CURL_REDIR_POST_301;
1111*6236dae4SAndroid Build Coastguard Worker     if(config->post302)
1112*6236dae4SAndroid Build Coastguard Worker       postRedir |= CURL_REDIR_POST_302;
1113*6236dae4SAndroid Build Coastguard Worker     if(config->post303)
1114*6236dae4SAndroid Build Coastguard Worker       postRedir |= CURL_REDIR_POST_303;
1115*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_POSTREDIR, postRedir);
1116*6236dae4SAndroid Build Coastguard Worker 
1117*6236dae4SAndroid Build Coastguard Worker     /* new in libcurl 7.21.6 */
1118*6236dae4SAndroid Build Coastguard Worker     if(config->encoding)
1119*6236dae4SAndroid Build Coastguard Worker       my_setopt_str(curl, CURLOPT_ACCEPT_ENCODING, "");
1120*6236dae4SAndroid Build Coastguard Worker 
1121*6236dae4SAndroid Build Coastguard Worker     /* new in libcurl 7.21.6 */
1122*6236dae4SAndroid Build Coastguard Worker     if(config->tr_encoding)
1123*6236dae4SAndroid Build Coastguard Worker       my_setopt(curl, CURLOPT_TRANSFER_ENCODING, 1L);
1124*6236dae4SAndroid Build Coastguard Worker     /* new in libcurl 7.64.0 */
1125*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_HTTP09_ALLOWED,
1126*6236dae4SAndroid Build Coastguard Worker               config->http09_allowed ? 1L : 0L);
1127*6236dae4SAndroid Build Coastguard Worker     if(result) {
1128*6236dae4SAndroid Build Coastguard Worker       errorf(global, "HTTP/0.9 is not supported in this build");
1129*6236dae4SAndroid Build Coastguard Worker       return result;
1130*6236dae4SAndroid Build Coastguard Worker     }
1131*6236dae4SAndroid Build Coastguard Worker 
1132*6236dae4SAndroid Build Coastguard Worker   } /* (proto_http) */
1133*6236dae4SAndroid Build Coastguard Worker 
1134*6236dae4SAndroid Build Coastguard Worker   if(proto_ftp)
1135*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_FTPPORT, config->ftpport);
1136*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_LOW_SPEED_LIMIT,
1137*6236dae4SAndroid Build Coastguard Worker             config->low_speed_limit);
1138*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time);
1139*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_MAX_SEND_SPEED_LARGE,
1140*6236dae4SAndroid Build Coastguard Worker             config->sendpersecond);
1141*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE,
1142*6236dae4SAndroid Build Coastguard Worker             config->recvpersecond);
1143*6236dae4SAndroid Build Coastguard Worker 
1144*6236dae4SAndroid Build Coastguard Worker   if(config->use_resume)
1145*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_RESUME_FROM_LARGE, config->resume_from);
1146*6236dae4SAndroid Build Coastguard Worker   else
1147*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_RESUME_FROM_LARGE, CURL_OFF_T_C(0));
1148*6236dae4SAndroid Build Coastguard Worker 
1149*6236dae4SAndroid Build Coastguard Worker   my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd);
1150*6236dae4SAndroid Build Coastguard Worker   my_setopt_str(curl, CURLOPT_PROXY_KEYPASSWD, config->proxy_key_passwd);
1151*6236dae4SAndroid Build Coastguard Worker 
1152*6236dae4SAndroid Build Coastguard Worker   if(use_proto == proto_scp || use_proto == proto_sftp) {
1153*6236dae4SAndroid Build Coastguard Worker     /* SSH and SSL private key uses same command-line option */
1154*6236dae4SAndroid Build Coastguard Worker     /* new in libcurl 7.16.1 */
1155*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key);
1156*6236dae4SAndroid Build Coastguard Worker     /* new in libcurl 7.16.1 */
1157*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey);
1158*6236dae4SAndroid Build Coastguard Worker 
1159*6236dae4SAndroid Build Coastguard Worker     /* new in libcurl 7.17.1: SSH host key md5 checking allows us
1160*6236dae4SAndroid Build Coastguard Worker        to fail if we are not talking to who we think we should */
1161*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
1162*6236dae4SAndroid Build Coastguard Worker                   config->hostpubmd5);
1163*6236dae4SAndroid Build Coastguard Worker 
1164*6236dae4SAndroid Build Coastguard Worker     /* new in libcurl 7.80.0: SSH host key sha256 checking allows us
1165*6236dae4SAndroid Build Coastguard Worker        to fail if we are not talking to who we think we should */
1166*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256,
1167*6236dae4SAndroid Build Coastguard Worker                   config->hostpubsha256);
1168*6236dae4SAndroid Build Coastguard Worker 
1169*6236dae4SAndroid Build Coastguard Worker     /* new in libcurl 7.56.0 */
1170*6236dae4SAndroid Build Coastguard Worker     if(config->ssh_compression)
1171*6236dae4SAndroid Build Coastguard Worker       my_setopt(curl, CURLOPT_SSH_COMPRESSION, 1L);
1172*6236dae4SAndroid Build Coastguard Worker 
1173*6236dae4SAndroid Build Coastguard Worker     if(!config->insecure_ok) {
1174*6236dae4SAndroid Build Coastguard Worker       char *known = findfile(".ssh/known_hosts", FALSE);
1175*6236dae4SAndroid Build Coastguard Worker       if(known) {
1176*6236dae4SAndroid Build Coastguard Worker         /* new in curl 7.19.6 */
1177*6236dae4SAndroid Build Coastguard Worker         result = res_setopt_str(curl, CURLOPT_SSH_KNOWNHOSTS, known);
1178*6236dae4SAndroid Build Coastguard Worker         curl_free(known);
1179*6236dae4SAndroid Build Coastguard Worker         if(result == CURLE_UNKNOWN_OPTION)
1180*6236dae4SAndroid Build Coastguard Worker           /* libssh2 version older than 1.1.1 */
1181*6236dae4SAndroid Build Coastguard Worker           result = CURLE_OK;
1182*6236dae4SAndroid Build Coastguard Worker         if(result)
1183*6236dae4SAndroid Build Coastguard Worker           return result;
1184*6236dae4SAndroid Build Coastguard Worker       }
1185*6236dae4SAndroid Build Coastguard Worker       else
1186*6236dae4SAndroid Build Coastguard Worker         warnf(global, "Couldn't find a known_hosts file");
1187*6236dae4SAndroid Build Coastguard Worker     }
1188*6236dae4SAndroid Build Coastguard Worker   }
1189*6236dae4SAndroid Build Coastguard Worker 
1190*6236dae4SAndroid Build Coastguard Worker   if(config->cacert)
1191*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_CAINFO, config->cacert);
1192*6236dae4SAndroid Build Coastguard Worker   if(config->proxy_cacert)
1193*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_PROXY_CAINFO, config->proxy_cacert);
1194*6236dae4SAndroid Build Coastguard Worker 
1195*6236dae4SAndroid Build Coastguard Worker   if(config->capath) {
1196*6236dae4SAndroid Build Coastguard Worker     result = res_setopt_str(curl, CURLOPT_CAPATH, config->capath);
1197*6236dae4SAndroid Build Coastguard Worker     if(result == CURLE_NOT_BUILT_IN) {
1198*6236dae4SAndroid Build Coastguard Worker       warnf(global, "ignoring %s, not supported by libcurl with %s",
1199*6236dae4SAndroid Build Coastguard Worker             capath_from_env ?
1200*6236dae4SAndroid Build Coastguard Worker             "SSL_CERT_DIR environment variable" : "--capath",
1201*6236dae4SAndroid Build Coastguard Worker             ssl_backend());
1202*6236dae4SAndroid Build Coastguard Worker     }
1203*6236dae4SAndroid Build Coastguard Worker     else if(result)
1204*6236dae4SAndroid Build Coastguard Worker       return result;
1205*6236dae4SAndroid Build Coastguard Worker   }
1206*6236dae4SAndroid Build Coastguard Worker   /* For the time being if --proxy-capath is not set then we use the
1207*6236dae4SAndroid Build Coastguard Worker      --capath value for it, if any. See #1257 */
1208*6236dae4SAndroid Build Coastguard Worker   if(config->proxy_capath || config->capath) {
1209*6236dae4SAndroid Build Coastguard Worker     result = res_setopt_str(curl, CURLOPT_PROXY_CAPATH,
1210*6236dae4SAndroid Build Coastguard Worker                             (config->proxy_capath ?
1211*6236dae4SAndroid Build Coastguard Worker                              config->proxy_capath :
1212*6236dae4SAndroid Build Coastguard Worker                              config->capath));
1213*6236dae4SAndroid Build Coastguard Worker     if((result == CURLE_NOT_BUILT_IN) ||
1214*6236dae4SAndroid Build Coastguard Worker        (result == CURLE_UNKNOWN_OPTION)) {
1215*6236dae4SAndroid Build Coastguard Worker       if(config->proxy_capath) {
1216*6236dae4SAndroid Build Coastguard Worker         warnf(global, "ignoring %s, not supported by libcurl with %s",
1217*6236dae4SAndroid Build Coastguard Worker               config->proxy_capath ? "--proxy-capath" : "--capath",
1218*6236dae4SAndroid Build Coastguard Worker               ssl_backend());
1219*6236dae4SAndroid Build Coastguard Worker       }
1220*6236dae4SAndroid Build Coastguard Worker     }
1221*6236dae4SAndroid Build Coastguard Worker     else if(result)
1222*6236dae4SAndroid Build Coastguard Worker       return result;
1223*6236dae4SAndroid Build Coastguard Worker   }
1224*6236dae4SAndroid Build Coastguard Worker 
1225*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_CA_EMBED
1226*6236dae4SAndroid Build Coastguard Worker   if(!config->cacert && !config->capath) {
1227*6236dae4SAndroid Build Coastguard Worker     struct curl_blob blob;
1228*6236dae4SAndroid Build Coastguard Worker     blob.data = (void *)curl_ca_embed;
1229*6236dae4SAndroid Build Coastguard Worker     blob.len = strlen((const char *)curl_ca_embed);
1230*6236dae4SAndroid Build Coastguard Worker     blob.flags = CURL_BLOB_NOCOPY;
1231*6236dae4SAndroid Build Coastguard Worker     notef(config->global,
1232*6236dae4SAndroid Build Coastguard Worker           "Using embedded CA bundle (%zu bytes)",
1233*6236dae4SAndroid Build Coastguard Worker           blob.len);
1234*6236dae4SAndroid Build Coastguard Worker     result = curl_easy_setopt(curl, CURLOPT_CAINFO_BLOB, &blob);
1235*6236dae4SAndroid Build Coastguard Worker     if(result == CURLE_NOT_BUILT_IN) {
1236*6236dae4SAndroid Build Coastguard Worker       warnf(global, "ignoring %s, not supported by libcurl with %s",
1237*6236dae4SAndroid Build Coastguard Worker             "embedded CA bundle", ssl_backend());
1238*6236dae4SAndroid Build Coastguard Worker     }
1239*6236dae4SAndroid Build Coastguard Worker   }
1240*6236dae4SAndroid Build Coastguard Worker   if(!config->proxy_cacert && !config->proxy_capath) {
1241*6236dae4SAndroid Build Coastguard Worker     struct curl_blob blob;
1242*6236dae4SAndroid Build Coastguard Worker     blob.data = (void *)curl_ca_embed;
1243*6236dae4SAndroid Build Coastguard Worker     blob.len = strlen((const char *)curl_ca_embed);
1244*6236dae4SAndroid Build Coastguard Worker     blob.flags = CURL_BLOB_NOCOPY;
1245*6236dae4SAndroid Build Coastguard Worker     notef(config->global,
1246*6236dae4SAndroid Build Coastguard Worker           "Using embedded CA bundle, for proxies (%zu bytes)",
1247*6236dae4SAndroid Build Coastguard Worker           blob.len);
1248*6236dae4SAndroid Build Coastguard Worker     result = curl_easy_setopt(curl, CURLOPT_PROXY_CAINFO_BLOB, &blob);
1249*6236dae4SAndroid Build Coastguard Worker     if(result == CURLE_NOT_BUILT_IN) {
1250*6236dae4SAndroid Build Coastguard Worker       warnf(global, "ignoring %s, not supported by libcurl with %s",
1251*6236dae4SAndroid Build Coastguard Worker             "embedded CA bundle", ssl_backend());
1252*6236dae4SAndroid Build Coastguard Worker     }
1253*6236dae4SAndroid Build Coastguard Worker   }
1254*6236dae4SAndroid Build Coastguard Worker #endif
1255*6236dae4SAndroid Build Coastguard Worker 
1256*6236dae4SAndroid Build Coastguard Worker   if(config->crlfile)
1257*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_CRLFILE, config->crlfile);
1258*6236dae4SAndroid Build Coastguard Worker   if(config->proxy_crlfile)
1259*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->proxy_crlfile);
1260*6236dae4SAndroid Build Coastguard Worker   else if(config->crlfile) /* CURLOPT_PROXY_CRLFILE default is crlfile */
1261*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->crlfile);
1262*6236dae4SAndroid Build Coastguard Worker 
1263*6236dae4SAndroid Build Coastguard Worker   if(config->pinnedpubkey) {
1264*6236dae4SAndroid Build Coastguard Worker     result = res_setopt_str(curl, CURLOPT_PINNEDPUBLICKEY,
1265*6236dae4SAndroid Build Coastguard Worker                             config->pinnedpubkey);
1266*6236dae4SAndroid Build Coastguard Worker     if(result == CURLE_NOT_BUILT_IN)
1267*6236dae4SAndroid Build Coastguard Worker       warnf(global, "ignoring %s, not supported by libcurl with %s",
1268*6236dae4SAndroid Build Coastguard Worker             "--pinnedpubkey", ssl_backend());
1269*6236dae4SAndroid Build Coastguard Worker   }
1270*6236dae4SAndroid Build Coastguard Worker   if(config->proxy_pinnedpubkey) {
1271*6236dae4SAndroid Build Coastguard Worker     result = res_setopt_str(curl, CURLOPT_PROXY_PINNEDPUBLICKEY,
1272*6236dae4SAndroid Build Coastguard Worker                             config->proxy_pinnedpubkey);
1273*6236dae4SAndroid Build Coastguard Worker     if(result == CURLE_NOT_BUILT_IN)
1274*6236dae4SAndroid Build Coastguard Worker       warnf(global, "ignoring %s, not supported by libcurl with %s",
1275*6236dae4SAndroid Build Coastguard Worker             "--proxy-pinnedpubkey", ssl_backend());
1276*6236dae4SAndroid Build Coastguard Worker   }
1277*6236dae4SAndroid Build Coastguard Worker 
1278*6236dae4SAndroid Build Coastguard Worker   if(config->ssl_ec_curves)
1279*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_SSL_EC_CURVES, config->ssl_ec_curves);
1280*6236dae4SAndroid Build Coastguard Worker 
1281*6236dae4SAndroid Build Coastguard Worker   if(config->writeout)
1282*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_CERTINFO, 1L);
1283*6236dae4SAndroid Build Coastguard Worker 
1284*6236dae4SAndroid Build Coastguard Worker   if(feature_ssl) {
1285*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_SSLCERT, config->cert);
1286*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_PROXY_SSLCERT, config->proxy_cert);
1287*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
1288*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_PROXY_SSLCERTTYPE,
1289*6236dae4SAndroid Build Coastguard Worker                   config->proxy_cert_type);
1290*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_SSLKEY, config->key);
1291*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_PROXY_SSLKEY, config->proxy_key);
1292*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
1293*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_PROXY_SSLKEYTYPE,
1294*6236dae4SAndroid Build Coastguard Worker                   config->proxy_key_type);
1295*6236dae4SAndroid Build Coastguard Worker 
1296*6236dae4SAndroid Build Coastguard Worker     /* libcurl default is strict verifyhost -> 1L, verifypeer -> 1L */
1297*6236dae4SAndroid Build Coastguard Worker     if(config->insecure_ok) {
1298*6236dae4SAndroid Build Coastguard Worker       my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
1299*6236dae4SAndroid Build Coastguard Worker       my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
1300*6236dae4SAndroid Build Coastguard Worker     }
1301*6236dae4SAndroid Build Coastguard Worker 
1302*6236dae4SAndroid Build Coastguard Worker     if(config->doh_insecure_ok) {
1303*6236dae4SAndroid Build Coastguard Worker       my_setopt(curl, CURLOPT_DOH_SSL_VERIFYPEER, 0L);
1304*6236dae4SAndroid Build Coastguard Worker       my_setopt(curl, CURLOPT_DOH_SSL_VERIFYHOST, 0L);
1305*6236dae4SAndroid Build Coastguard Worker     }
1306*6236dae4SAndroid Build Coastguard Worker 
1307*6236dae4SAndroid Build Coastguard Worker     if(config->proxy_insecure_ok) {
1308*6236dae4SAndroid Build Coastguard Worker       my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 0L);
1309*6236dae4SAndroid Build Coastguard Worker       my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 0L);
1310*6236dae4SAndroid Build Coastguard Worker     }
1311*6236dae4SAndroid Build Coastguard Worker 
1312*6236dae4SAndroid Build Coastguard Worker     if(config->verifystatus)
1313*6236dae4SAndroid Build Coastguard Worker       my_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 1L);
1314*6236dae4SAndroid Build Coastguard Worker 
1315*6236dae4SAndroid Build Coastguard Worker     if(config->doh_verifystatus)
1316*6236dae4SAndroid Build Coastguard Worker       my_setopt(curl, CURLOPT_DOH_SSL_VERIFYSTATUS, 1L);
1317*6236dae4SAndroid Build Coastguard Worker 
1318*6236dae4SAndroid Build Coastguard Worker     if(config->falsestart)
1319*6236dae4SAndroid Build Coastguard Worker       my_setopt(curl, CURLOPT_SSL_FALSESTART, 1L);
1320*6236dae4SAndroid Build Coastguard Worker 
1321*6236dae4SAndroid Build Coastguard Worker     my_setopt_SSLVERSION(curl, CURLOPT_SSLVERSION,
1322*6236dae4SAndroid Build Coastguard Worker                          config->ssl_version | config->ssl_version_max);
1323*6236dae4SAndroid Build Coastguard Worker     if(config->proxy)
1324*6236dae4SAndroid Build Coastguard Worker       my_setopt_SSLVERSION(curl, CURLOPT_PROXY_SSLVERSION,
1325*6236dae4SAndroid Build Coastguard Worker                            config->proxy_ssl_version);
1326*6236dae4SAndroid Build Coastguard Worker 
1327*6236dae4SAndroid Build Coastguard Worker     {
1328*6236dae4SAndroid Build Coastguard Worker       long mask =
1329*6236dae4SAndroid Build Coastguard Worker         (config->ssl_allow_beast ?
1330*6236dae4SAndroid Build Coastguard Worker          CURLSSLOPT_ALLOW_BEAST : 0) |
1331*6236dae4SAndroid Build Coastguard Worker         (config->ssl_allow_earlydata ?
1332*6236dae4SAndroid Build Coastguard Worker          CURLSSLOPT_EARLYDATA : 0) |
1333*6236dae4SAndroid Build Coastguard Worker         (config->ssl_no_revoke ?
1334*6236dae4SAndroid Build Coastguard Worker          CURLSSLOPT_NO_REVOKE : 0) |
1335*6236dae4SAndroid Build Coastguard Worker         (config->ssl_revoke_best_effort ?
1336*6236dae4SAndroid Build Coastguard Worker          CURLSSLOPT_REVOKE_BEST_EFFORT : 0) |
1337*6236dae4SAndroid Build Coastguard Worker         (config->native_ca_store ?
1338*6236dae4SAndroid Build Coastguard Worker          CURLSSLOPT_NATIVE_CA : 0) |
1339*6236dae4SAndroid Build Coastguard Worker         (config->ssl_auto_client_cert ?
1340*6236dae4SAndroid Build Coastguard Worker          CURLSSLOPT_AUTO_CLIENT_CERT : 0);
1341*6236dae4SAndroid Build Coastguard Worker 
1342*6236dae4SAndroid Build Coastguard Worker       if(mask)
1343*6236dae4SAndroid Build Coastguard Worker         my_setopt_bitmask(curl, CURLOPT_SSL_OPTIONS, mask);
1344*6236dae4SAndroid Build Coastguard Worker     }
1345*6236dae4SAndroid Build Coastguard Worker 
1346*6236dae4SAndroid Build Coastguard Worker     {
1347*6236dae4SAndroid Build Coastguard Worker       long mask =
1348*6236dae4SAndroid Build Coastguard Worker         (config->proxy_ssl_allow_beast ?
1349*6236dae4SAndroid Build Coastguard Worker          CURLSSLOPT_ALLOW_BEAST : 0) |
1350*6236dae4SAndroid Build Coastguard Worker         (config->proxy_ssl_auto_client_cert ?
1351*6236dae4SAndroid Build Coastguard Worker          CURLSSLOPT_AUTO_CLIENT_CERT : 0) |
1352*6236dae4SAndroid Build Coastguard Worker         (config->proxy_native_ca_store ?
1353*6236dae4SAndroid Build Coastguard Worker          CURLSSLOPT_NATIVE_CA : 0);
1354*6236dae4SAndroid Build Coastguard Worker 
1355*6236dae4SAndroid Build Coastguard Worker       if(mask)
1356*6236dae4SAndroid Build Coastguard Worker         my_setopt_bitmask(curl, CURLOPT_PROXY_SSL_OPTIONS, mask);
1357*6236dae4SAndroid Build Coastguard Worker     }
1358*6236dae4SAndroid Build Coastguard Worker   }
1359*6236dae4SAndroid Build Coastguard Worker 
1360*6236dae4SAndroid Build Coastguard Worker   if(config->path_as_is)
1361*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_PATH_AS_IS, 1L);
1362*6236dae4SAndroid Build Coastguard Worker 
1363*6236dae4SAndroid Build Coastguard Worker   if(config->no_body || config->remote_time) {
1364*6236dae4SAndroid Build Coastguard Worker     /* no body or use remote time */
1365*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_FILETIME, 1L);
1366*6236dae4SAndroid Build Coastguard Worker   }
1367*6236dae4SAndroid Build Coastguard Worker 
1368*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_CRLF, config->crlf ? 1L : 0L);
1369*6236dae4SAndroid Build Coastguard Worker   my_setopt_slist(curl, CURLOPT_QUOTE, config->quote);
1370*6236dae4SAndroid Build Coastguard Worker   my_setopt_slist(curl, CURLOPT_POSTQUOTE, config->postquote);
1371*6236dae4SAndroid Build Coastguard Worker   my_setopt_slist(curl, CURLOPT_PREQUOTE, config->prequote);
1372*6236dae4SAndroid Build Coastguard Worker 
1373*6236dae4SAndroid Build Coastguard Worker   if(config->cookies) {
1374*6236dae4SAndroid Build Coastguard Worker     struct curlx_dynbuf cookies;
1375*6236dae4SAndroid Build Coastguard Worker     struct curl_slist *cl;
1376*6236dae4SAndroid Build Coastguard Worker 
1377*6236dae4SAndroid Build Coastguard Worker     /* The maximum size needs to match MAX_NAME in cookie.h */
1378*6236dae4SAndroid Build Coastguard Worker #define MAX_COOKIE_LINE 8200
1379*6236dae4SAndroid Build Coastguard Worker     curlx_dyn_init(&cookies, MAX_COOKIE_LINE);
1380*6236dae4SAndroid Build Coastguard Worker     for(cl = config->cookies; cl; cl = cl->next) {
1381*6236dae4SAndroid Build Coastguard Worker       if(cl == config->cookies)
1382*6236dae4SAndroid Build Coastguard Worker         result = curlx_dyn_addf(&cookies, "%s", cl->data);
1383*6236dae4SAndroid Build Coastguard Worker       else
1384*6236dae4SAndroid Build Coastguard Worker         result = curlx_dyn_addf(&cookies, ";%s", cl->data);
1385*6236dae4SAndroid Build Coastguard Worker 
1386*6236dae4SAndroid Build Coastguard Worker       if(result) {
1387*6236dae4SAndroid Build Coastguard Worker         warnf(global,
1388*6236dae4SAndroid Build Coastguard Worker               "skipped provided cookie, the cookie header "
1389*6236dae4SAndroid Build Coastguard Worker               "would go over %u bytes", MAX_COOKIE_LINE);
1390*6236dae4SAndroid Build Coastguard Worker         return result;
1391*6236dae4SAndroid Build Coastguard Worker       }
1392*6236dae4SAndroid Build Coastguard Worker     }
1393*6236dae4SAndroid Build Coastguard Worker 
1394*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_COOKIE, curlx_dyn_ptr(&cookies));
1395*6236dae4SAndroid Build Coastguard Worker     curlx_dyn_free(&cookies);
1396*6236dae4SAndroid Build Coastguard Worker   }
1397*6236dae4SAndroid Build Coastguard Worker 
1398*6236dae4SAndroid Build Coastguard Worker   if(config->cookiefiles) {
1399*6236dae4SAndroid Build Coastguard Worker     struct curl_slist *cfl;
1400*6236dae4SAndroid Build Coastguard Worker 
1401*6236dae4SAndroid Build Coastguard Worker     for(cfl = config->cookiefiles; cfl; cfl = cfl->next)
1402*6236dae4SAndroid Build Coastguard Worker       my_setopt_str(curl, CURLOPT_COOKIEFILE, cfl->data);
1403*6236dae4SAndroid Build Coastguard Worker   }
1404*6236dae4SAndroid Build Coastguard Worker 
1405*6236dae4SAndroid Build Coastguard Worker   /* new in libcurl 7.9 */
1406*6236dae4SAndroid Build Coastguard Worker   if(config->cookiejar)
1407*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_COOKIEJAR, config->cookiejar);
1408*6236dae4SAndroid Build Coastguard Worker 
1409*6236dae4SAndroid Build Coastguard Worker   /* new in libcurl 7.9.7 */
1410*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_COOKIESESSION, config->cookiesession ?
1411*6236dae4SAndroid Build Coastguard Worker             1L : 0L);
1412*6236dae4SAndroid Build Coastguard Worker 
1413*6236dae4SAndroid Build Coastguard Worker   my_setopt_enum(curl, CURLOPT_TIMECONDITION, (long)config->timecond);
1414*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_TIMEVALUE_LARGE, config->condtime);
1415*6236dae4SAndroid Build Coastguard Worker   my_setopt_str(curl, CURLOPT_CUSTOMREQUEST, config->customrequest);
1416*6236dae4SAndroid Build Coastguard Worker   customrequest_helper(config, config->httpreq, config->customrequest);
1417*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_STDERR, tool_stderr);
1418*6236dae4SAndroid Build Coastguard Worker 
1419*6236dae4SAndroid Build Coastguard Worker   /* three new ones in libcurl 7.3: */
1420*6236dae4SAndroid Build Coastguard Worker   my_setopt_str(curl, CURLOPT_INTERFACE, config->iface);
1421*6236dae4SAndroid Build Coastguard Worker   my_setopt_str(curl, CURLOPT_KRBLEVEL, config->krblevel);
1422*6236dae4SAndroid Build Coastguard Worker   progressbarinit(&per->progressbar, config);
1423*6236dae4SAndroid Build Coastguard Worker 
1424*6236dae4SAndroid Build Coastguard Worker   if((global->progressmode == CURL_PROGRESS_BAR) &&
1425*6236dae4SAndroid Build Coastguard Worker      !global->noprogress && !global->silent) {
1426*6236dae4SAndroid Build Coastguard Worker     /* we want the alternative style, then we have to implement it
1427*6236dae4SAndroid Build Coastguard Worker        ourselves! */
1428*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_progress_cb);
1429*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_XFERINFODATA, per);
1430*6236dae4SAndroid Build Coastguard Worker   }
1431*6236dae4SAndroid Build Coastguard Worker   else if(per->uploadfile && !strcmp(per->uploadfile, ".")) {
1432*6236dae4SAndroid Build Coastguard Worker     /* when reading from stdin in non-blocking mode, we use the progress
1433*6236dae4SAndroid Build Coastguard Worker        function to unpause a busy read */
1434*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_NOPROGRESS, 0L);
1435*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_readbusy_cb);
1436*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_XFERINFODATA, per);
1437*6236dae4SAndroid Build Coastguard Worker   }
1438*6236dae4SAndroid Build Coastguard Worker 
1439*6236dae4SAndroid Build Coastguard Worker   /* new in libcurl 7.24.0: */
1440*6236dae4SAndroid Build Coastguard Worker   if(config->dns_servers)
1441*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_DNS_SERVERS, config->dns_servers);
1442*6236dae4SAndroid Build Coastguard Worker 
1443*6236dae4SAndroid Build Coastguard Worker   /* new in libcurl 7.33.0: */
1444*6236dae4SAndroid Build Coastguard Worker   if(config->dns_interface)
1445*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_DNS_INTERFACE, config->dns_interface);
1446*6236dae4SAndroid Build Coastguard Worker   if(config->dns_ipv4_addr)
1447*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP4, config->dns_ipv4_addr);
1448*6236dae4SAndroid Build Coastguard Worker   if(config->dns_ipv6_addr)
1449*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP6, config->dns_ipv6_addr);
1450*6236dae4SAndroid Build Coastguard Worker 
1451*6236dae4SAndroid Build Coastguard Worker   /* new in libcurl 7.6.2: */
1452*6236dae4SAndroid Build Coastguard Worker   my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
1453*6236dae4SAndroid Build Coastguard Worker 
1454*6236dae4SAndroid Build Coastguard Worker   /* new in libcurl 7.7: */
1455*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, config->connecttimeout_ms);
1456*6236dae4SAndroid Build Coastguard Worker 
1457*6236dae4SAndroid Build Coastguard Worker   if(config->doh_url)
1458*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_DOH_URL, config->doh_url);
1459*6236dae4SAndroid Build Coastguard Worker 
1460*6236dae4SAndroid Build Coastguard Worker   if(config->cipher_list) {
1461*6236dae4SAndroid Build Coastguard Worker     result = res_setopt_str(curl, CURLOPT_SSL_CIPHER_LIST,
1462*6236dae4SAndroid Build Coastguard Worker                             config->cipher_list);
1463*6236dae4SAndroid Build Coastguard Worker     if(result == CURLE_NOT_BUILT_IN)
1464*6236dae4SAndroid Build Coastguard Worker       warnf(global, "ignoring %s, not supported by libcurl with %s",
1465*6236dae4SAndroid Build Coastguard Worker             "--ciphers", ssl_backend());
1466*6236dae4SAndroid Build Coastguard Worker   }
1467*6236dae4SAndroid Build Coastguard Worker   if(config->proxy_cipher_list) {
1468*6236dae4SAndroid Build Coastguard Worker     result = res_setopt_str(curl, CURLOPT_PROXY_SSL_CIPHER_LIST,
1469*6236dae4SAndroid Build Coastguard Worker                             config->proxy_cipher_list);
1470*6236dae4SAndroid Build Coastguard Worker     if(result == CURLE_NOT_BUILT_IN)
1471*6236dae4SAndroid Build Coastguard Worker       warnf(global, "ignoring %s, not supported by libcurl with %s",
1472*6236dae4SAndroid Build Coastguard Worker             "--proxy-ciphers", ssl_backend());
1473*6236dae4SAndroid Build Coastguard Worker   }
1474*6236dae4SAndroid Build Coastguard Worker   if(config->cipher13_list) {
1475*6236dae4SAndroid Build Coastguard Worker     result = res_setopt_str(curl, CURLOPT_TLS13_CIPHERS,
1476*6236dae4SAndroid Build Coastguard Worker                             config->cipher13_list);
1477*6236dae4SAndroid Build Coastguard Worker     if(result == CURLE_NOT_BUILT_IN)
1478*6236dae4SAndroid Build Coastguard Worker       warnf(global, "ignoring %s, not supported by libcurl with %s",
1479*6236dae4SAndroid Build Coastguard Worker             "--tls13-ciphers", ssl_backend());
1480*6236dae4SAndroid Build Coastguard Worker   }
1481*6236dae4SAndroid Build Coastguard Worker   if(config->proxy_cipher13_list) {
1482*6236dae4SAndroid Build Coastguard Worker     result = res_setopt_str(curl, CURLOPT_PROXY_TLS13_CIPHERS,
1483*6236dae4SAndroid Build Coastguard Worker                             config->proxy_cipher13_list);
1484*6236dae4SAndroid Build Coastguard Worker     if(result == CURLE_NOT_BUILT_IN)
1485*6236dae4SAndroid Build Coastguard Worker       warnf(global, "ignoring %s, not supported by libcurl with %s",
1486*6236dae4SAndroid Build Coastguard Worker             "--proxy-tls13-ciphers", ssl_backend());
1487*6236dae4SAndroid Build Coastguard Worker   }
1488*6236dae4SAndroid Build Coastguard Worker 
1489*6236dae4SAndroid Build Coastguard Worker   /* new in libcurl 7.9.2: */
1490*6236dae4SAndroid Build Coastguard Worker   if(config->disable_epsv)
1491*6236dae4SAndroid Build Coastguard Worker     /* disable it */
1492*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_FTP_USE_EPSV, 0L);
1493*6236dae4SAndroid Build Coastguard Worker 
1494*6236dae4SAndroid Build Coastguard Worker   /* new in libcurl 7.10.5 */
1495*6236dae4SAndroid Build Coastguard Worker   if(config->disable_eprt)
1496*6236dae4SAndroid Build Coastguard Worker     /* disable it */
1497*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_FTP_USE_EPRT, 0L);
1498*6236dae4SAndroid Build Coastguard Worker 
1499*6236dae4SAndroid Build Coastguard Worker   if(global->tracetype != TRACE_NONE) {
1500*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb);
1501*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_DEBUGDATA, config);
1502*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_VERBOSE, 1L);
1503*6236dae4SAndroid Build Coastguard Worker   }
1504*6236dae4SAndroid Build Coastguard Worker 
1505*6236dae4SAndroid Build Coastguard Worker   /* new in curl 7.9.3 */
1506*6236dae4SAndroid Build Coastguard Worker   if(config->engine) {
1507*6236dae4SAndroid Build Coastguard Worker     result = res_setopt_str(curl, CURLOPT_SSLENGINE, config->engine);
1508*6236dae4SAndroid Build Coastguard Worker     if(result)
1509*6236dae4SAndroid Build Coastguard Worker       return result;
1510*6236dae4SAndroid Build Coastguard Worker   }
1511*6236dae4SAndroid Build Coastguard Worker 
1512*6236dae4SAndroid Build Coastguard Worker   /* new in curl 7.10.7, extended in 7.19.4. Modified to use
1513*6236dae4SAndroid Build Coastguard Worker      CREATE_DIR_RETRY in 7.49.0 */
1514*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS,
1515*6236dae4SAndroid Build Coastguard Worker             (long)(config->ftp_create_dirs ?
1516*6236dae4SAndroid Build Coastguard Worker                    CURLFTP_CREATE_DIR_RETRY : CURLFTP_CREATE_DIR_NONE));
1517*6236dae4SAndroid Build Coastguard Worker 
1518*6236dae4SAndroid Build Coastguard Worker   /* new in curl 7.10.8 */
1519*6236dae4SAndroid Build Coastguard Worker   if(config->max_filesize)
1520*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_MAXFILESIZE_LARGE,
1521*6236dae4SAndroid Build Coastguard Worker               config->max_filesize);
1522*6236dae4SAndroid Build Coastguard Worker 
1523*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_IPRESOLVE, config->ip_version);
1524*6236dae4SAndroid Build Coastguard Worker 
1525*6236dae4SAndroid Build Coastguard Worker   /* new in curl 7.15.5 */
1526*6236dae4SAndroid Build Coastguard Worker   if(config->ftp_ssl_reqd)
1527*6236dae4SAndroid Build Coastguard Worker     my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
1528*6236dae4SAndroid Build Coastguard Worker 
1529*6236dae4SAndroid Build Coastguard Worker   /* new in curl 7.11.0 */
1530*6236dae4SAndroid Build Coastguard Worker   else if(config->ftp_ssl)
1531*6236dae4SAndroid Build Coastguard Worker     my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY);
1532*6236dae4SAndroid Build Coastguard Worker 
1533*6236dae4SAndroid Build Coastguard Worker   /* new in curl 7.16.0 */
1534*6236dae4SAndroid Build Coastguard Worker   else if(config->ftp_ssl_control)
1535*6236dae4SAndroid Build Coastguard Worker     my_setopt_enum(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_CONTROL);
1536*6236dae4SAndroid Build Coastguard Worker 
1537*6236dae4SAndroid Build Coastguard Worker   /* new in curl 7.16.1 */
1538*6236dae4SAndroid Build Coastguard Worker   if(config->ftp_ssl_ccc)
1539*6236dae4SAndroid Build Coastguard Worker     my_setopt_enum(curl, CURLOPT_FTP_SSL_CCC,
1540*6236dae4SAndroid Build Coastguard Worker                    (long)config->ftp_ssl_ccc_mode);
1541*6236dae4SAndroid Build Coastguard Worker 
1542*6236dae4SAndroid Build Coastguard Worker   /* new in curl 7.19.4 */
1543*6236dae4SAndroid Build Coastguard Worker   if(config->socks5_gssapi_nec)
1544*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_NEC, 1L);
1545*6236dae4SAndroid Build Coastguard Worker 
1546*6236dae4SAndroid Build Coastguard Worker   /* new in curl 7.55.0 */
1547*6236dae4SAndroid Build Coastguard Worker   if(config->socks5_auth)
1548*6236dae4SAndroid Build Coastguard Worker     my_setopt_bitmask(curl, CURLOPT_SOCKS5_AUTH,
1549*6236dae4SAndroid Build Coastguard Worker                       (long)config->socks5_auth);
1550*6236dae4SAndroid Build Coastguard Worker 
1551*6236dae4SAndroid Build Coastguard Worker   /* new in curl 7.43.0 */
1552*6236dae4SAndroid Build Coastguard Worker   if(config->proxy_service_name)
1553*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_PROXY_SERVICE_NAME,
1554*6236dae4SAndroid Build Coastguard Worker                   config->proxy_service_name);
1555*6236dae4SAndroid Build Coastguard Worker 
1556*6236dae4SAndroid Build Coastguard Worker   /* new in curl 7.43.0 */
1557*6236dae4SAndroid Build Coastguard Worker   if(config->service_name)
1558*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_SERVICE_NAME,
1559*6236dae4SAndroid Build Coastguard Worker                   config->service_name);
1560*6236dae4SAndroid Build Coastguard Worker 
1561*6236dae4SAndroid Build Coastguard Worker   /* curl 7.13.0 */
1562*6236dae4SAndroid Build Coastguard Worker   my_setopt_str(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account);
1563*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl ?
1564*6236dae4SAndroid Build Coastguard Worker             1L : 0L);
1565*6236dae4SAndroid Build Coastguard Worker 
1566*6236dae4SAndroid Build Coastguard Worker   /* curl 7.14.2 */
1567*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip ?
1568*6236dae4SAndroid Build Coastguard Worker             1L : 0L);
1569*6236dae4SAndroid Build Coastguard Worker 
1570*6236dae4SAndroid Build Coastguard Worker   /* curl 7.15.1 */
1571*6236dae4SAndroid Build Coastguard Worker   if(proto_ftp)
1572*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_FTP_FILEMETHOD,
1573*6236dae4SAndroid Build Coastguard Worker               (long)config->ftp_filemethod);
1574*6236dae4SAndroid Build Coastguard Worker 
1575*6236dae4SAndroid Build Coastguard Worker   /* curl 7.15.2 */
1576*6236dae4SAndroid Build Coastguard Worker   if(config->localport) {
1577*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_LOCALPORT, config->localport);
1578*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_LOCALPORTRANGE, config->localportrange);
1579*6236dae4SAndroid Build Coastguard Worker   }
1580*6236dae4SAndroid Build Coastguard Worker 
1581*6236dae4SAndroid Build Coastguard Worker   /* curl 7.15.5 */
1582*6236dae4SAndroid Build Coastguard Worker   my_setopt_str(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER,
1583*6236dae4SAndroid Build Coastguard Worker                 config->ftp_alternative_to_user);
1584*6236dae4SAndroid Build Coastguard Worker 
1585*6236dae4SAndroid Build Coastguard Worker   /* curl 7.16.0 */
1586*6236dae4SAndroid Build Coastguard Worker   if(config->disable_sessionid)
1587*6236dae4SAndroid Build Coastguard Worker     /* disable it */
1588*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 0L);
1589*6236dae4SAndroid Build Coastguard Worker 
1590*6236dae4SAndroid Build Coastguard Worker   /* curl 7.16.2 */
1591*6236dae4SAndroid Build Coastguard Worker   if(config->raw) {
1592*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, 0L);
1593*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_HTTP_TRANSFER_DECODING, 0L);
1594*6236dae4SAndroid Build Coastguard Worker   }
1595*6236dae4SAndroid Build Coastguard Worker 
1596*6236dae4SAndroid Build Coastguard Worker   /* curl 7.17.1 */
1597*6236dae4SAndroid Build Coastguard Worker   if(!config->nokeepalive) {
1598*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
1599*6236dae4SAndroid Build Coastguard Worker     if(config->alivetime) {
1600*6236dae4SAndroid Build Coastguard Worker       my_setopt(curl, CURLOPT_TCP_KEEPIDLE, config->alivetime);
1601*6236dae4SAndroid Build Coastguard Worker       my_setopt(curl, CURLOPT_TCP_KEEPINTVL, config->alivetime);
1602*6236dae4SAndroid Build Coastguard Worker     }
1603*6236dae4SAndroid Build Coastguard Worker     if(config->alivecnt)
1604*6236dae4SAndroid Build Coastguard Worker       my_setopt(curl, CURLOPT_TCP_KEEPCNT, config->alivecnt);
1605*6236dae4SAndroid Build Coastguard Worker   }
1606*6236dae4SAndroid Build Coastguard Worker   else
1607*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_TCP_KEEPALIVE, 0L);
1608*6236dae4SAndroid Build Coastguard Worker 
1609*6236dae4SAndroid Build Coastguard Worker   /* curl 7.20.0 */
1610*6236dae4SAndroid Build Coastguard Worker   if(config->tftp_blksize && proto_tftp)
1611*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_TFTP_BLKSIZE, config->tftp_blksize);
1612*6236dae4SAndroid Build Coastguard Worker 
1613*6236dae4SAndroid Build Coastguard Worker   if(config->mail_from)
1614*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_MAIL_FROM, config->mail_from);
1615*6236dae4SAndroid Build Coastguard Worker 
1616*6236dae4SAndroid Build Coastguard Worker   if(config->mail_rcpt)
1617*6236dae4SAndroid Build Coastguard Worker     my_setopt_slist(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt);
1618*6236dae4SAndroid Build Coastguard Worker 
1619*6236dae4SAndroid Build Coastguard Worker   /* curl 7.69.x */
1620*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_MAIL_RCPT_ALLOWFAILS,
1621*6236dae4SAndroid Build Coastguard Worker             config->mail_rcpt_allowfails ? 1L : 0L);
1622*6236dae4SAndroid Build Coastguard Worker 
1623*6236dae4SAndroid Build Coastguard Worker   /* curl 7.20.x */
1624*6236dae4SAndroid Build Coastguard Worker   if(config->ftp_pret)
1625*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_FTP_USE_PRET, 1L);
1626*6236dae4SAndroid Build Coastguard Worker 
1627*6236dae4SAndroid Build Coastguard Worker   if(config->create_file_mode)
1628*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_NEW_FILE_PERMS, config->create_file_mode);
1629*6236dae4SAndroid Build Coastguard Worker 
1630*6236dae4SAndroid Build Coastguard Worker   if(config->proto_present)
1631*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_PROTOCOLS_STR, config->proto_str);
1632*6236dae4SAndroid Build Coastguard Worker   if(config->proto_redir_present)
1633*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_REDIR_PROTOCOLS_STR,
1634*6236dae4SAndroid Build Coastguard Worker                   config->proto_redir_str);
1635*6236dae4SAndroid Build Coastguard Worker 
1636*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_HEADERFUNCTION, tool_header_cb);
1637*6236dae4SAndroid Build Coastguard Worker   my_setopt(curl, CURLOPT_HEADERDATA, per);
1638*6236dae4SAndroid Build Coastguard Worker 
1639*6236dae4SAndroid Build Coastguard Worker   if(config->resolve)
1640*6236dae4SAndroid Build Coastguard Worker     /* new in 7.21.3 */
1641*6236dae4SAndroid Build Coastguard Worker     my_setopt_slist(curl, CURLOPT_RESOLVE, config->resolve);
1642*6236dae4SAndroid Build Coastguard Worker 
1643*6236dae4SAndroid Build Coastguard Worker   if(config->connect_to)
1644*6236dae4SAndroid Build Coastguard Worker     /* new in 7.49.0 */
1645*6236dae4SAndroid Build Coastguard Worker     my_setopt_slist(curl, CURLOPT_CONNECT_TO, config->connect_to);
1646*6236dae4SAndroid Build Coastguard Worker 
1647*6236dae4SAndroid Build Coastguard Worker   /* new in 7.21.4 */
1648*6236dae4SAndroid Build Coastguard Worker   if(feature_tls_srp) {
1649*6236dae4SAndroid Build Coastguard Worker     if(config->tls_username)
1650*6236dae4SAndroid Build Coastguard Worker       my_setopt_str(curl, CURLOPT_TLSAUTH_USERNAME,
1651*6236dae4SAndroid Build Coastguard Worker                     config->tls_username);
1652*6236dae4SAndroid Build Coastguard Worker     if(config->tls_password)
1653*6236dae4SAndroid Build Coastguard Worker       my_setopt_str(curl, CURLOPT_TLSAUTH_PASSWORD,
1654*6236dae4SAndroid Build Coastguard Worker                     config->tls_password);
1655*6236dae4SAndroid Build Coastguard Worker     if(config->tls_authtype)
1656*6236dae4SAndroid Build Coastguard Worker       my_setopt_str(curl, CURLOPT_TLSAUTH_TYPE,
1657*6236dae4SAndroid Build Coastguard Worker                     config->tls_authtype);
1658*6236dae4SAndroid Build Coastguard Worker     if(config->proxy_tls_username)
1659*6236dae4SAndroid Build Coastguard Worker       my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_USERNAME,
1660*6236dae4SAndroid Build Coastguard Worker                     config->proxy_tls_username);
1661*6236dae4SAndroid Build Coastguard Worker     if(config->proxy_tls_password)
1662*6236dae4SAndroid Build Coastguard Worker       my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD,
1663*6236dae4SAndroid Build Coastguard Worker                     config->proxy_tls_password);
1664*6236dae4SAndroid Build Coastguard Worker     if(config->proxy_tls_authtype)
1665*6236dae4SAndroid Build Coastguard Worker       my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_TYPE,
1666*6236dae4SAndroid Build Coastguard Worker                     config->proxy_tls_authtype);
1667*6236dae4SAndroid Build Coastguard Worker   }
1668*6236dae4SAndroid Build Coastguard Worker 
1669*6236dae4SAndroid Build Coastguard Worker   /* new in 7.22.0 */
1670*6236dae4SAndroid Build Coastguard Worker   if(config->gssapi_delegation)
1671*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_GSSAPI_DELEGATION,
1672*6236dae4SAndroid Build Coastguard Worker                   config->gssapi_delegation);
1673*6236dae4SAndroid Build Coastguard Worker 
1674*6236dae4SAndroid Build Coastguard Worker   if(config->mail_auth)
1675*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
1676*6236dae4SAndroid Build Coastguard Worker 
1677*6236dae4SAndroid Build Coastguard Worker   /* new in 7.66.0 */
1678*6236dae4SAndroid Build Coastguard Worker   if(config->sasl_authzid)
1679*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_SASL_AUTHZID, config->sasl_authzid);
1680*6236dae4SAndroid Build Coastguard Worker 
1681*6236dae4SAndroid Build Coastguard Worker   /* new in 7.31.0 */
1682*6236dae4SAndroid Build Coastguard Worker   if(config->sasl_ir)
1683*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_SASL_IR, 1L);
1684*6236dae4SAndroid Build Coastguard Worker 
1685*6236dae4SAndroid Build Coastguard Worker   if(config->noalpn) {
1686*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L);
1687*6236dae4SAndroid Build Coastguard Worker   }
1688*6236dae4SAndroid Build Coastguard Worker 
1689*6236dae4SAndroid Build Coastguard Worker   /* new in 7.40.0, abstract support added in 7.53.0 */
1690*6236dae4SAndroid Build Coastguard Worker   if(config->unix_socket_path) {
1691*6236dae4SAndroid Build Coastguard Worker     if(config->abstract_unix_socket) {
1692*6236dae4SAndroid Build Coastguard Worker       my_setopt_str(curl, CURLOPT_ABSTRACT_UNIX_SOCKET,
1693*6236dae4SAndroid Build Coastguard Worker                     config->unix_socket_path);
1694*6236dae4SAndroid Build Coastguard Worker     }
1695*6236dae4SAndroid Build Coastguard Worker     else {
1696*6236dae4SAndroid Build Coastguard Worker       my_setopt_str(curl, CURLOPT_UNIX_SOCKET_PATH,
1697*6236dae4SAndroid Build Coastguard Worker                     config->unix_socket_path);
1698*6236dae4SAndroid Build Coastguard Worker     }
1699*6236dae4SAndroid Build Coastguard Worker   }
1700*6236dae4SAndroid Build Coastguard Worker 
1701*6236dae4SAndroid Build Coastguard Worker   /* new in 7.45.0 */
1702*6236dae4SAndroid Build Coastguard Worker   if(config->proto_default)
1703*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_DEFAULT_PROTOCOL, config->proto_default);
1704*6236dae4SAndroid Build Coastguard Worker 
1705*6236dae4SAndroid Build Coastguard Worker   /* new in 7.47.0 */
1706*6236dae4SAndroid Build Coastguard Worker   if(config->expect100timeout_ms > 0)
1707*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_EXPECT_100_TIMEOUT_MS,
1708*6236dae4SAndroid Build Coastguard Worker                   config->expect100timeout_ms);
1709*6236dae4SAndroid Build Coastguard Worker 
1710*6236dae4SAndroid Build Coastguard Worker   /* new in 7.48.0 */
1711*6236dae4SAndroid Build Coastguard Worker   if(config->tftp_no_options && proto_tftp)
1712*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_TFTP_NO_OPTIONS, 1L);
1713*6236dae4SAndroid Build Coastguard Worker 
1714*6236dae4SAndroid Build Coastguard Worker   /* new in 7.59.0 */
1715*6236dae4SAndroid Build Coastguard Worker   if(config->happy_eyeballs_timeout_ms != CURL_HET_DEFAULT)
1716*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS,
1717*6236dae4SAndroid Build Coastguard Worker               config->happy_eyeballs_timeout_ms);
1718*6236dae4SAndroid Build Coastguard Worker 
1719*6236dae4SAndroid Build Coastguard Worker   /* new in 7.60.0 */
1720*6236dae4SAndroid Build Coastguard Worker   if(config->haproxy_protocol)
1721*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L);
1722*6236dae4SAndroid Build Coastguard Worker 
1723*6236dae4SAndroid Build Coastguard Worker   /* new in 8.2.0 */
1724*6236dae4SAndroid Build Coastguard Worker   if(config->haproxy_clientip)
1725*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_HAPROXY_CLIENT_IP,
1726*6236dae4SAndroid Build Coastguard Worker                   config->haproxy_clientip);
1727*6236dae4SAndroid Build Coastguard Worker 
1728*6236dae4SAndroid Build Coastguard Worker   if(config->disallow_username_in_url)
1729*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_DISALLOW_USERNAME_IN_URL, 1L);
1730*6236dae4SAndroid Build Coastguard Worker 
1731*6236dae4SAndroid Build Coastguard Worker   if(config->altsvc)
1732*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_ALTSVC, config->altsvc);
1733*6236dae4SAndroid Build Coastguard Worker 
1734*6236dae4SAndroid Build Coastguard Worker   if(config->hsts)
1735*6236dae4SAndroid Build Coastguard Worker     my_setopt_str(curl, CURLOPT_HSTS, config->hsts);
1736*6236dae4SAndroid Build Coastguard Worker 
1737*6236dae4SAndroid Build Coastguard Worker   if(feature_ech) {
1738*6236dae4SAndroid Build Coastguard Worker     /* only if enabled in libcurl */
1739*6236dae4SAndroid Build Coastguard Worker     if(config->ech) /* only if set (optional) */
1740*6236dae4SAndroid Build Coastguard Worker       my_setopt_str(curl, CURLOPT_ECH, config->ech);
1741*6236dae4SAndroid Build Coastguard Worker     if(config->ech_public) /* only if set (optional) */
1742*6236dae4SAndroid Build Coastguard Worker       my_setopt_str(curl, CURLOPT_ECH, config->ech_public);
1743*6236dae4SAndroid Build Coastguard Worker     if(config->ech_config) /* only if set (optional) */
1744*6236dae4SAndroid Build Coastguard Worker       my_setopt_str(curl, CURLOPT_ECH, config->ech_config);
1745*6236dae4SAndroid Build Coastguard Worker   }
1746*6236dae4SAndroid Build Coastguard Worker 
1747*6236dae4SAndroid Build Coastguard Worker   /* new in 8.9.0 */
1748*6236dae4SAndroid Build Coastguard Worker   if(config->ip_tos > 0 || config->vlan_priority > 0) {
1749*6236dae4SAndroid Build Coastguard Worker #if defined(IP_TOS) || defined(IPV6_TCLASS) || defined(SO_PRIORITY)
1750*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
1751*6236dae4SAndroid Build Coastguard Worker     my_setopt(curl, CURLOPT_SOCKOPTDATA, config);
1752*6236dae4SAndroid Build Coastguard Worker #else
1753*6236dae4SAndroid Build Coastguard Worker     if(config->ip_tos > 0) {
1754*6236dae4SAndroid Build Coastguard Worker       errorf(config->global,
1755*6236dae4SAndroid Build Coastguard Worker              "Type of service is not supported in this build.");
1756*6236dae4SAndroid Build Coastguard Worker       result = CURLE_NOT_BUILT_IN;
1757*6236dae4SAndroid Build Coastguard Worker     }
1758*6236dae4SAndroid Build Coastguard Worker     if(config->vlan_priority > 0) {
1759*6236dae4SAndroid Build Coastguard Worker       errorf(config->global,
1760*6236dae4SAndroid Build Coastguard Worker              "VLAN priority is not supported in this build.");
1761*6236dae4SAndroid Build Coastguard Worker       result = CURLE_NOT_BUILT_IN;
1762*6236dae4SAndroid Build Coastguard Worker     }
1763*6236dae4SAndroid Build Coastguard Worker #endif
1764*6236dae4SAndroid Build Coastguard Worker   }
1765*6236dae4SAndroid Build Coastguard Worker   return result;
1766*6236dae4SAndroid Build Coastguard Worker }
1767*6236dae4SAndroid Build Coastguard Worker 
append2query(struct GlobalConfig * global,struct OperationConfig * config,struct per_transfer * per,const char * q)1768*6236dae4SAndroid Build Coastguard Worker static CURLcode append2query(struct GlobalConfig *global,
1769*6236dae4SAndroid Build Coastguard Worker                              struct OperationConfig *config,
1770*6236dae4SAndroid Build Coastguard Worker                              struct per_transfer *per,
1771*6236dae4SAndroid Build Coastguard Worker                              const char *q)
1772*6236dae4SAndroid Build Coastguard Worker {
1773*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
1774*6236dae4SAndroid Build Coastguard Worker   CURLU *uh = curl_url();
1775*6236dae4SAndroid Build Coastguard Worker   if(uh) {
1776*6236dae4SAndroid Build Coastguard Worker     CURLUcode uerr;
1777*6236dae4SAndroid Build Coastguard Worker     uerr = curl_url_set(uh, CURLUPART_URL, per->url,
1778*6236dae4SAndroid Build Coastguard Worker                         CURLU_GUESS_SCHEME);
1779*6236dae4SAndroid Build Coastguard Worker     if(uerr) {
1780*6236dae4SAndroid Build Coastguard Worker       result = urlerr_cvt(uerr);
1781*6236dae4SAndroid Build Coastguard Worker       errorf(global, "(%d) Could not parse the URL, "
1782*6236dae4SAndroid Build Coastguard Worker              "failed to set query", result);
1783*6236dae4SAndroid Build Coastguard Worker       config->synthetic_error = TRUE;
1784*6236dae4SAndroid Build Coastguard Worker     }
1785*6236dae4SAndroid Build Coastguard Worker     else {
1786*6236dae4SAndroid Build Coastguard Worker       char *updated = NULL;
1787*6236dae4SAndroid Build Coastguard Worker       uerr = curl_url_set(uh, CURLUPART_QUERY, q, CURLU_APPENDQUERY);
1788*6236dae4SAndroid Build Coastguard Worker       if(!uerr)
1789*6236dae4SAndroid Build Coastguard Worker         uerr = curl_url_get(uh, CURLUPART_URL, &updated,
1790*6236dae4SAndroid Build Coastguard Worker                             CURLU_GUESS_SCHEME);
1791*6236dae4SAndroid Build Coastguard Worker       if(uerr)
1792*6236dae4SAndroid Build Coastguard Worker         result = urlerr_cvt(uerr);
1793*6236dae4SAndroid Build Coastguard Worker       else {
1794*6236dae4SAndroid Build Coastguard Worker         Curl_safefree(per->url); /* free previous URL */
1795*6236dae4SAndroid Build Coastguard Worker         per->url = updated; /* use our new URL instead! */
1796*6236dae4SAndroid Build Coastguard Worker       }
1797*6236dae4SAndroid Build Coastguard Worker     }
1798*6236dae4SAndroid Build Coastguard Worker     curl_url_cleanup(uh);
1799*6236dae4SAndroid Build Coastguard Worker   }
1800*6236dae4SAndroid Build Coastguard Worker   return result;
1801*6236dae4SAndroid Build Coastguard Worker }
1802*6236dae4SAndroid Build Coastguard Worker 
1803*6236dae4SAndroid Build Coastguard Worker /* create the next (singular) transfer */
single_transfer(struct GlobalConfig * global,struct OperationConfig * config,CURLSH * share,bool capath_from_env,bool * added,bool * skipped)1804*6236dae4SAndroid Build Coastguard Worker static CURLcode single_transfer(struct GlobalConfig *global,
1805*6236dae4SAndroid Build Coastguard Worker                                 struct OperationConfig *config,
1806*6236dae4SAndroid Build Coastguard Worker                                 CURLSH *share,
1807*6236dae4SAndroid Build Coastguard Worker                                 bool capath_from_env,
1808*6236dae4SAndroid Build Coastguard Worker                                 bool *added,
1809*6236dae4SAndroid Build Coastguard Worker                                 bool *skipped)
1810*6236dae4SAndroid Build Coastguard Worker {
1811*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
1812*6236dae4SAndroid Build Coastguard Worker   struct getout *urlnode;
1813*6236dae4SAndroid Build Coastguard Worker   bool orig_noprogress = global->noprogress;
1814*6236dae4SAndroid Build Coastguard Worker   bool orig_isatty = global->isatty;
1815*6236dae4SAndroid Build Coastguard Worker   struct State *state = &config->state;
1816*6236dae4SAndroid Build Coastguard Worker   char *httpgetfields = state->httpgetfields;
1817*6236dae4SAndroid Build Coastguard Worker 
1818*6236dae4SAndroid Build Coastguard Worker   *skipped = *added = FALSE; /* not yet */
1819*6236dae4SAndroid Build Coastguard Worker 
1820*6236dae4SAndroid Build Coastguard Worker   if(config->postfields) {
1821*6236dae4SAndroid Build Coastguard Worker     if(config->use_httpget) {
1822*6236dae4SAndroid Build Coastguard Worker       if(!httpgetfields) {
1823*6236dae4SAndroid Build Coastguard Worker         /* Use the postfields data for an HTTP get */
1824*6236dae4SAndroid Build Coastguard Worker         httpgetfields = state->httpgetfields = config->postfields;
1825*6236dae4SAndroid Build Coastguard Worker         config->postfields = NULL;
1826*6236dae4SAndroid Build Coastguard Worker         if(SetHTTPrequest(config, (config->no_body ? TOOL_HTTPREQ_HEAD :
1827*6236dae4SAndroid Build Coastguard Worker                                    TOOL_HTTPREQ_GET), &config->httpreq)) {
1828*6236dae4SAndroid Build Coastguard Worker           result = CURLE_FAILED_INIT;
1829*6236dae4SAndroid Build Coastguard Worker         }
1830*6236dae4SAndroid Build Coastguard Worker       }
1831*6236dae4SAndroid Build Coastguard Worker     }
1832*6236dae4SAndroid Build Coastguard Worker     else {
1833*6236dae4SAndroid Build Coastguard Worker       if(SetHTTPrequest(config, TOOL_HTTPREQ_SIMPLEPOST, &config->httpreq))
1834*6236dae4SAndroid Build Coastguard Worker         result = CURLE_FAILED_INIT;
1835*6236dae4SAndroid Build Coastguard Worker     }
1836*6236dae4SAndroid Build Coastguard Worker     if(result)
1837*6236dae4SAndroid Build Coastguard Worker       goto fail;
1838*6236dae4SAndroid Build Coastguard Worker   }
1839*6236dae4SAndroid Build Coastguard Worker   if(!state->urlnode) {
1840*6236dae4SAndroid Build Coastguard Worker     /* first time caller, setup things */
1841*6236dae4SAndroid Build Coastguard Worker     state->urlnode = config->url_list;
1842*6236dae4SAndroid Build Coastguard Worker     state->infilenum = 1;
1843*6236dae4SAndroid Build Coastguard Worker   }
1844*6236dae4SAndroid Build Coastguard Worker 
1845*6236dae4SAndroid Build Coastguard Worker   result = set_cert_types(config);
1846*6236dae4SAndroid Build Coastguard Worker   if(result)
1847*6236dae4SAndroid Build Coastguard Worker     goto fail;
1848*6236dae4SAndroid Build Coastguard Worker 
1849*6236dae4SAndroid Build Coastguard Worker   for(; state->urlnode; state->urlnode = urlnode->next) {
1850*6236dae4SAndroid Build Coastguard Worker     static bool warn_more_options = FALSE;
1851*6236dae4SAndroid Build Coastguard Worker     curl_off_t urlnum;
1852*6236dae4SAndroid Build Coastguard Worker 
1853*6236dae4SAndroid Build Coastguard Worker     urlnode = state->urlnode;
1854*6236dae4SAndroid Build Coastguard Worker     /* urlnode->url is the full URL or NULL */
1855*6236dae4SAndroid Build Coastguard Worker     if(!urlnode->url) {
1856*6236dae4SAndroid Build Coastguard Worker       /* This node has no URL. Free node data without destroying the
1857*6236dae4SAndroid Build Coastguard Worker          node itself nor modifying next pointer and continue to next */
1858*6236dae4SAndroid Build Coastguard Worker       urlnode->flags = 0;
1859*6236dae4SAndroid Build Coastguard Worker       state->up = 0;
1860*6236dae4SAndroid Build Coastguard Worker       if(!warn_more_options) {
1861*6236dae4SAndroid Build Coastguard Worker         /* only show this once */
1862*6236dae4SAndroid Build Coastguard Worker         warnf(config->global, "Got more output options than URLs");
1863*6236dae4SAndroid Build Coastguard Worker         warn_more_options = TRUE;
1864*6236dae4SAndroid Build Coastguard Worker       }
1865*6236dae4SAndroid Build Coastguard Worker       continue; /* next URL please */
1866*6236dae4SAndroid Build Coastguard Worker     }
1867*6236dae4SAndroid Build Coastguard Worker 
1868*6236dae4SAndroid Build Coastguard Worker     /* save outfile pattern before expansion */
1869*6236dae4SAndroid Build Coastguard Worker     if(urlnode->outfile && !state->outfiles) {
1870*6236dae4SAndroid Build Coastguard Worker       state->outfiles = strdup(urlnode->outfile);
1871*6236dae4SAndroid Build Coastguard Worker       if(!state->outfiles) {
1872*6236dae4SAndroid Build Coastguard Worker         errorf(global, "out of memory");
1873*6236dae4SAndroid Build Coastguard Worker         result = CURLE_OUT_OF_MEMORY;
1874*6236dae4SAndroid Build Coastguard Worker         break;
1875*6236dae4SAndroid Build Coastguard Worker       }
1876*6236dae4SAndroid Build Coastguard Worker     }
1877*6236dae4SAndroid Build Coastguard Worker 
1878*6236dae4SAndroid Build Coastguard Worker     if(!config->globoff && urlnode->infile && !state->inglob) {
1879*6236dae4SAndroid Build Coastguard Worker       /* Unless explicitly shut off */
1880*6236dae4SAndroid Build Coastguard Worker       result = glob_url(&state->inglob, urlnode->infile, &state->infilenum,
1881*6236dae4SAndroid Build Coastguard Worker                         (!global->silent || global->showerror) ?
1882*6236dae4SAndroid Build Coastguard Worker                         tool_stderr : NULL);
1883*6236dae4SAndroid Build Coastguard Worker       if(result)
1884*6236dae4SAndroid Build Coastguard Worker         break;
1885*6236dae4SAndroid Build Coastguard Worker     }
1886*6236dae4SAndroid Build Coastguard Worker 
1887*6236dae4SAndroid Build Coastguard Worker 
1888*6236dae4SAndroid Build Coastguard Worker     if(state->up || urlnode->infile) {
1889*6236dae4SAndroid Build Coastguard Worker       if(!state->uploadfile) {
1890*6236dae4SAndroid Build Coastguard Worker         if(state->inglob) {
1891*6236dae4SAndroid Build Coastguard Worker           result = glob_next_url(&state->uploadfile, state->inglob);
1892*6236dae4SAndroid Build Coastguard Worker           if(result == CURLE_OUT_OF_MEMORY)
1893*6236dae4SAndroid Build Coastguard Worker             errorf(global, "out of memory");
1894*6236dae4SAndroid Build Coastguard Worker         }
1895*6236dae4SAndroid Build Coastguard Worker         else if(!state->up) {
1896*6236dae4SAndroid Build Coastguard Worker           /* copy the allocated string */
1897*6236dae4SAndroid Build Coastguard Worker           state->uploadfile = urlnode->infile;
1898*6236dae4SAndroid Build Coastguard Worker           urlnode->infile = NULL;
1899*6236dae4SAndroid Build Coastguard Worker         }
1900*6236dae4SAndroid Build Coastguard Worker       }
1901*6236dae4SAndroid Build Coastguard Worker       if(result)
1902*6236dae4SAndroid Build Coastguard Worker         break;
1903*6236dae4SAndroid Build Coastguard Worker     }
1904*6236dae4SAndroid Build Coastguard Worker 
1905*6236dae4SAndroid Build Coastguard Worker     if(!state->urlnum) {
1906*6236dae4SAndroid Build Coastguard Worker       if(!config->globoff) {
1907*6236dae4SAndroid Build Coastguard Worker         /* Unless explicitly shut off, we expand '{...}' and '[...]'
1908*6236dae4SAndroid Build Coastguard Worker            expressions and return total number of URLs in pattern set */
1909*6236dae4SAndroid Build Coastguard Worker         result = glob_url(&state->urls, urlnode->url, &state->urlnum,
1910*6236dae4SAndroid Build Coastguard Worker                           (!global->silent || global->showerror) ?
1911*6236dae4SAndroid Build Coastguard Worker                           tool_stderr : NULL);
1912*6236dae4SAndroid Build Coastguard Worker         if(result)
1913*6236dae4SAndroid Build Coastguard Worker           break;
1914*6236dae4SAndroid Build Coastguard Worker         urlnum = state->urlnum;
1915*6236dae4SAndroid Build Coastguard Worker       }
1916*6236dae4SAndroid Build Coastguard Worker       else
1917*6236dae4SAndroid Build Coastguard Worker         urlnum = 1; /* without globbing, this is a single URL */
1918*6236dae4SAndroid Build Coastguard Worker     }
1919*6236dae4SAndroid Build Coastguard Worker     else
1920*6236dae4SAndroid Build Coastguard Worker       urlnum = state->urlnum;
1921*6236dae4SAndroid Build Coastguard Worker 
1922*6236dae4SAndroid Build Coastguard Worker     if(state->up < state->infilenum) {
1923*6236dae4SAndroid Build Coastguard Worker       struct per_transfer *per = NULL;
1924*6236dae4SAndroid Build Coastguard Worker       struct OutStruct *outs;
1925*6236dae4SAndroid Build Coastguard Worker       struct OutStruct *heads;
1926*6236dae4SAndroid Build Coastguard Worker       struct OutStruct *etag_save;
1927*6236dae4SAndroid Build Coastguard Worker       struct HdrCbData *hdrcbdata = NULL;
1928*6236dae4SAndroid Build Coastguard Worker       struct OutStruct etag_first;
1929*6236dae4SAndroid Build Coastguard Worker       CURL *curl;
1930*6236dae4SAndroid Build Coastguard Worker 
1931*6236dae4SAndroid Build Coastguard Worker       /* --etag-save */
1932*6236dae4SAndroid Build Coastguard Worker       memset(&etag_first, 0, sizeof(etag_first));
1933*6236dae4SAndroid Build Coastguard Worker       etag_save = &etag_first;
1934*6236dae4SAndroid Build Coastguard Worker       etag_save->stream = stdout;
1935*6236dae4SAndroid Build Coastguard Worker 
1936*6236dae4SAndroid Build Coastguard Worker       /* --etag-compare */
1937*6236dae4SAndroid Build Coastguard Worker       if(config->etag_compare_file) {
1938*6236dae4SAndroid Build Coastguard Worker         char *etag_from_file = NULL;
1939*6236dae4SAndroid Build Coastguard Worker         char *header = NULL;
1940*6236dae4SAndroid Build Coastguard Worker         ParameterError pe;
1941*6236dae4SAndroid Build Coastguard Worker 
1942*6236dae4SAndroid Build Coastguard Worker         /* open file for reading: */
1943*6236dae4SAndroid Build Coastguard Worker         FILE *file = fopen(config->etag_compare_file, FOPEN_READTEXT);
1944*6236dae4SAndroid Build Coastguard Worker         if(!file && !config->etag_save_file) {
1945*6236dae4SAndroid Build Coastguard Worker           errorf(global,
1946*6236dae4SAndroid Build Coastguard Worker                  "Failed to open %s", config->etag_compare_file);
1947*6236dae4SAndroid Build Coastguard Worker           result = CURLE_READ_ERROR;
1948*6236dae4SAndroid Build Coastguard Worker           break;
1949*6236dae4SAndroid Build Coastguard Worker         }
1950*6236dae4SAndroid Build Coastguard Worker 
1951*6236dae4SAndroid Build Coastguard Worker         if((PARAM_OK == file2string(&etag_from_file, file)) &&
1952*6236dae4SAndroid Build Coastguard Worker            etag_from_file) {
1953*6236dae4SAndroid Build Coastguard Worker           header = aprintf("If-None-Match: %s", etag_from_file);
1954*6236dae4SAndroid Build Coastguard Worker           Curl_safefree(etag_from_file);
1955*6236dae4SAndroid Build Coastguard Worker         }
1956*6236dae4SAndroid Build Coastguard Worker         else
1957*6236dae4SAndroid Build Coastguard Worker           header = aprintf("If-None-Match: \"\"");
1958*6236dae4SAndroid Build Coastguard Worker 
1959*6236dae4SAndroid Build Coastguard Worker         if(!header) {
1960*6236dae4SAndroid Build Coastguard Worker           if(file)
1961*6236dae4SAndroid Build Coastguard Worker             fclose(file);
1962*6236dae4SAndroid Build Coastguard Worker           errorf(global,
1963*6236dae4SAndroid Build Coastguard Worker                  "Failed to allocate memory for custom etag header");
1964*6236dae4SAndroid Build Coastguard Worker           result = CURLE_OUT_OF_MEMORY;
1965*6236dae4SAndroid Build Coastguard Worker           break;
1966*6236dae4SAndroid Build Coastguard Worker         }
1967*6236dae4SAndroid Build Coastguard Worker 
1968*6236dae4SAndroid Build Coastguard Worker         /* add Etag from file to list of custom headers */
1969*6236dae4SAndroid Build Coastguard Worker         pe = add2list(&config->headers, header);
1970*6236dae4SAndroid Build Coastguard Worker         Curl_safefree(header);
1971*6236dae4SAndroid Build Coastguard Worker 
1972*6236dae4SAndroid Build Coastguard Worker         if(file)
1973*6236dae4SAndroid Build Coastguard Worker           fclose(file);
1974*6236dae4SAndroid Build Coastguard Worker         if(pe != PARAM_OK) {
1975*6236dae4SAndroid Build Coastguard Worker           result = CURLE_OUT_OF_MEMORY;
1976*6236dae4SAndroid Build Coastguard Worker           break;
1977*6236dae4SAndroid Build Coastguard Worker         }
1978*6236dae4SAndroid Build Coastguard Worker       }
1979*6236dae4SAndroid Build Coastguard Worker 
1980*6236dae4SAndroid Build Coastguard Worker       if(config->etag_save_file) {
1981*6236dae4SAndroid Build Coastguard Worker         /* open file for output: */
1982*6236dae4SAndroid Build Coastguard Worker         if(strcmp(config->etag_save_file, "-")) {
1983*6236dae4SAndroid Build Coastguard Worker           FILE *newfile = fopen(config->etag_save_file, "ab");
1984*6236dae4SAndroid Build Coastguard Worker           if(!newfile) {
1985*6236dae4SAndroid Build Coastguard Worker             warnf(global, "Failed creating file for saving etags: \"%s\". "
1986*6236dae4SAndroid Build Coastguard Worker                   "Skip this transfer", config->etag_save_file);
1987*6236dae4SAndroid Build Coastguard Worker             Curl_safefree(state->outfiles);
1988*6236dae4SAndroid Build Coastguard Worker             glob_cleanup(&state->urls);
1989*6236dae4SAndroid Build Coastguard Worker             return CURLE_OK;
1990*6236dae4SAndroid Build Coastguard Worker           }
1991*6236dae4SAndroid Build Coastguard Worker           else {
1992*6236dae4SAndroid Build Coastguard Worker             etag_save->filename = config->etag_save_file;
1993*6236dae4SAndroid Build Coastguard Worker             etag_save->s_isreg = TRUE;
1994*6236dae4SAndroid Build Coastguard Worker             etag_save->fopened = TRUE;
1995*6236dae4SAndroid Build Coastguard Worker             etag_save->stream = newfile;
1996*6236dae4SAndroid Build Coastguard Worker           }
1997*6236dae4SAndroid Build Coastguard Worker         }
1998*6236dae4SAndroid Build Coastguard Worker         else {
1999*6236dae4SAndroid Build Coastguard Worker           /* always use binary mode for protocol header output */
2000*6236dae4SAndroid Build Coastguard Worker           set_binmode(etag_save->stream);
2001*6236dae4SAndroid Build Coastguard Worker         }
2002*6236dae4SAndroid Build Coastguard Worker       }
2003*6236dae4SAndroid Build Coastguard Worker 
2004*6236dae4SAndroid Build Coastguard Worker       curl = curl_easy_init();
2005*6236dae4SAndroid Build Coastguard Worker       if(curl)
2006*6236dae4SAndroid Build Coastguard Worker         result = add_per_transfer(&per);
2007*6236dae4SAndroid Build Coastguard Worker       else
2008*6236dae4SAndroid Build Coastguard Worker         result = CURLE_OUT_OF_MEMORY;
2009*6236dae4SAndroid Build Coastguard Worker       if(result) {
2010*6236dae4SAndroid Build Coastguard Worker         curl_easy_cleanup(curl);
2011*6236dae4SAndroid Build Coastguard Worker         if(etag_save->fopened)
2012*6236dae4SAndroid Build Coastguard Worker           fclose(etag_save->stream);
2013*6236dae4SAndroid Build Coastguard Worker         break;
2014*6236dae4SAndroid Build Coastguard Worker       }
2015*6236dae4SAndroid Build Coastguard Worker       per->etag_save = etag_first; /* copy the whole struct */
2016*6236dae4SAndroid Build Coastguard Worker       if(state->uploadfile) {
2017*6236dae4SAndroid Build Coastguard Worker         per->uploadfile = strdup(state->uploadfile);
2018*6236dae4SAndroid Build Coastguard Worker         if(!per->uploadfile) {
2019*6236dae4SAndroid Build Coastguard Worker           curl_easy_cleanup(curl);
2020*6236dae4SAndroid Build Coastguard Worker           result = CURLE_OUT_OF_MEMORY;
2021*6236dae4SAndroid Build Coastguard Worker           break;
2022*6236dae4SAndroid Build Coastguard Worker         }
2023*6236dae4SAndroid Build Coastguard Worker         if(SetHTTPrequest(config, TOOL_HTTPREQ_PUT, &config->httpreq)) {
2024*6236dae4SAndroid Build Coastguard Worker           Curl_safefree(per->uploadfile);
2025*6236dae4SAndroid Build Coastguard Worker           curl_easy_cleanup(curl);
2026*6236dae4SAndroid Build Coastguard Worker           result = CURLE_FAILED_INIT;
2027*6236dae4SAndroid Build Coastguard Worker           break;
2028*6236dae4SAndroid Build Coastguard Worker         }
2029*6236dae4SAndroid Build Coastguard Worker       }
2030*6236dae4SAndroid Build Coastguard Worker       *added = TRUE;
2031*6236dae4SAndroid Build Coastguard Worker       per->config = config;
2032*6236dae4SAndroid Build Coastguard Worker       per->curl = curl;
2033*6236dae4SAndroid Build Coastguard Worker       per->urlnum = (unsigned int)urlnode->num;
2034*6236dae4SAndroid Build Coastguard Worker 
2035*6236dae4SAndroid Build Coastguard Worker       /* default headers output stream is stdout */
2036*6236dae4SAndroid Build Coastguard Worker       heads = &per->heads;
2037*6236dae4SAndroid Build Coastguard Worker       heads->stream = stdout;
2038*6236dae4SAndroid Build Coastguard Worker 
2039*6236dae4SAndroid Build Coastguard Worker       /* Single header file for all URLs */
2040*6236dae4SAndroid Build Coastguard Worker       if(config->headerfile) {
2041*6236dae4SAndroid Build Coastguard Worker         /* open file for output: */
2042*6236dae4SAndroid Build Coastguard Worker         if(!strcmp(config->headerfile, "%")) {
2043*6236dae4SAndroid Build Coastguard Worker           heads->stream = stderr;
2044*6236dae4SAndroid Build Coastguard Worker           /* use binary mode for protocol header output */
2045*6236dae4SAndroid Build Coastguard Worker           set_binmode(heads->stream);
2046*6236dae4SAndroid Build Coastguard Worker         }
2047*6236dae4SAndroid Build Coastguard Worker         else if(strcmp(config->headerfile, "-")) {
2048*6236dae4SAndroid Build Coastguard Worker           FILE *newfile;
2049*6236dae4SAndroid Build Coastguard Worker 
2050*6236dae4SAndroid Build Coastguard Worker           /*
2051*6236dae4SAndroid Build Coastguard Worker            * Since every transfer has its own file handle for dumping
2052*6236dae4SAndroid Build Coastguard Worker            * the headers, we need to open it in append mode, since transfers
2053*6236dae4SAndroid Build Coastguard Worker            * might finish in any order.
2054*6236dae4SAndroid Build Coastguard Worker            * The first transfer just clears the file.
2055*6236dae4SAndroid Build Coastguard Worker            * TODO: Consider placing the file handle inside the
2056*6236dae4SAndroid Build Coastguard Worker            * OperationConfig, so that it does not need to be opened/closed
2057*6236dae4SAndroid Build Coastguard Worker            * for every transfer.
2058*6236dae4SAndroid Build Coastguard Worker            */
2059*6236dae4SAndroid Build Coastguard Worker           if(config->create_dirs) {
2060*6236dae4SAndroid Build Coastguard Worker             result = create_dir_hierarchy(config->headerfile, global);
2061*6236dae4SAndroid Build Coastguard Worker             /* create_dir_hierarchy shows error upon CURLE_WRITE_ERROR */
2062*6236dae4SAndroid Build Coastguard Worker             if(result)
2063*6236dae4SAndroid Build Coastguard Worker               break;
2064*6236dae4SAndroid Build Coastguard Worker           }
2065*6236dae4SAndroid Build Coastguard Worker           if(!per->prev || per->prev->config != config) {
2066*6236dae4SAndroid Build Coastguard Worker             newfile = fopen(config->headerfile, "wb");
2067*6236dae4SAndroid Build Coastguard Worker             if(newfile)
2068*6236dae4SAndroid Build Coastguard Worker               fclose(newfile);
2069*6236dae4SAndroid Build Coastguard Worker           }
2070*6236dae4SAndroid Build Coastguard Worker           newfile = fopen(config->headerfile, "ab");
2071*6236dae4SAndroid Build Coastguard Worker 
2072*6236dae4SAndroid Build Coastguard Worker           if(!newfile) {
2073*6236dae4SAndroid Build Coastguard Worker             errorf(global, "Failed to open %s", config->headerfile);
2074*6236dae4SAndroid Build Coastguard Worker             result = CURLE_WRITE_ERROR;
2075*6236dae4SAndroid Build Coastguard Worker             break;
2076*6236dae4SAndroid Build Coastguard Worker           }
2077*6236dae4SAndroid Build Coastguard Worker           else {
2078*6236dae4SAndroid Build Coastguard Worker             heads->filename = config->headerfile;
2079*6236dae4SAndroid Build Coastguard Worker             heads->s_isreg = TRUE;
2080*6236dae4SAndroid Build Coastguard Worker             heads->fopened = TRUE;
2081*6236dae4SAndroid Build Coastguard Worker             heads->stream = newfile;
2082*6236dae4SAndroid Build Coastguard Worker           }
2083*6236dae4SAndroid Build Coastguard Worker         }
2084*6236dae4SAndroid Build Coastguard Worker         else {
2085*6236dae4SAndroid Build Coastguard Worker           /* always use binary mode for protocol header output */
2086*6236dae4SAndroid Build Coastguard Worker           set_binmode(heads->stream);
2087*6236dae4SAndroid Build Coastguard Worker         }
2088*6236dae4SAndroid Build Coastguard Worker       }
2089*6236dae4SAndroid Build Coastguard Worker 
2090*6236dae4SAndroid Build Coastguard Worker       hdrcbdata = &per->hdrcbdata;
2091*6236dae4SAndroid Build Coastguard Worker 
2092*6236dae4SAndroid Build Coastguard Worker       outs = &per->outs;
2093*6236dae4SAndroid Build Coastguard Worker 
2094*6236dae4SAndroid Build Coastguard Worker       per->outfile = NULL;
2095*6236dae4SAndroid Build Coastguard Worker       per->infdopen = FALSE;
2096*6236dae4SAndroid Build Coastguard Worker       per->infd = STDIN_FILENO;
2097*6236dae4SAndroid Build Coastguard Worker 
2098*6236dae4SAndroid Build Coastguard Worker       /* default output stream is stdout */
2099*6236dae4SAndroid Build Coastguard Worker       outs->stream = stdout;
2100*6236dae4SAndroid Build Coastguard Worker 
2101*6236dae4SAndroid Build Coastguard Worker       if(state->urls) {
2102*6236dae4SAndroid Build Coastguard Worker         result = glob_next_url(&per->url, state->urls);
2103*6236dae4SAndroid Build Coastguard Worker         if(result)
2104*6236dae4SAndroid Build Coastguard Worker           break;
2105*6236dae4SAndroid Build Coastguard Worker       }
2106*6236dae4SAndroid Build Coastguard Worker       else if(!state->li) {
2107*6236dae4SAndroid Build Coastguard Worker         per->url = strdup(urlnode->url);
2108*6236dae4SAndroid Build Coastguard Worker         if(!per->url) {
2109*6236dae4SAndroid Build Coastguard Worker           result = CURLE_OUT_OF_MEMORY;
2110*6236dae4SAndroid Build Coastguard Worker           break;
2111*6236dae4SAndroid Build Coastguard Worker         }
2112*6236dae4SAndroid Build Coastguard Worker       }
2113*6236dae4SAndroid Build Coastguard Worker       else
2114*6236dae4SAndroid Build Coastguard Worker         per->url = NULL;
2115*6236dae4SAndroid Build Coastguard Worker       if(!per->url)
2116*6236dae4SAndroid Build Coastguard Worker         break;
2117*6236dae4SAndroid Build Coastguard Worker 
2118*6236dae4SAndroid Build Coastguard Worker       if(state->outfiles) {
2119*6236dae4SAndroid Build Coastguard Worker         per->outfile = strdup(state->outfiles);
2120*6236dae4SAndroid Build Coastguard Worker         if(!per->outfile) {
2121*6236dae4SAndroid Build Coastguard Worker           result = CURLE_OUT_OF_MEMORY;
2122*6236dae4SAndroid Build Coastguard Worker           break;
2123*6236dae4SAndroid Build Coastguard Worker         }
2124*6236dae4SAndroid Build Coastguard Worker       }
2125*6236dae4SAndroid Build Coastguard Worker 
2126*6236dae4SAndroid Build Coastguard Worker       if(((urlnode->flags&GETOUT_USEREMOTE) ||
2127*6236dae4SAndroid Build Coastguard Worker           (per->outfile && strcmp("-", per->outfile)))) {
2128*6236dae4SAndroid Build Coastguard Worker 
2129*6236dae4SAndroid Build Coastguard Worker         /*
2130*6236dae4SAndroid Build Coastguard Worker          * We have specified a filename to store the result in, or we have
2131*6236dae4SAndroid Build Coastguard Worker          * decided we want to use the remote filename.
2132*6236dae4SAndroid Build Coastguard Worker          */
2133*6236dae4SAndroid Build Coastguard Worker 
2134*6236dae4SAndroid Build Coastguard Worker         if(!per->outfile) {
2135*6236dae4SAndroid Build Coastguard Worker           /* extract the filename from the URL */
2136*6236dae4SAndroid Build Coastguard Worker           result = get_url_file_name(global, &per->outfile, per->url);
2137*6236dae4SAndroid Build Coastguard Worker           if(result) {
2138*6236dae4SAndroid Build Coastguard Worker             errorf(global, "Failed to extract a filename"
2139*6236dae4SAndroid Build Coastguard Worker                    " from the URL to use for storage");
2140*6236dae4SAndroid Build Coastguard Worker             break;
2141*6236dae4SAndroid Build Coastguard Worker           }
2142*6236dae4SAndroid Build Coastguard Worker         }
2143*6236dae4SAndroid Build Coastguard Worker         else if(state->urls) {
2144*6236dae4SAndroid Build Coastguard Worker           /* fill '#1' ... '#9' terms from URL pattern */
2145*6236dae4SAndroid Build Coastguard Worker           char *storefile = per->outfile;
2146*6236dae4SAndroid Build Coastguard Worker           result = glob_match_url(&per->outfile, storefile, state->urls);
2147*6236dae4SAndroid Build Coastguard Worker           Curl_safefree(storefile);
2148*6236dae4SAndroid Build Coastguard Worker           if(result) {
2149*6236dae4SAndroid Build Coastguard Worker             /* bad globbing */
2150*6236dae4SAndroid Build Coastguard Worker             warnf(global, "bad output glob");
2151*6236dae4SAndroid Build Coastguard Worker             break;
2152*6236dae4SAndroid Build Coastguard Worker           }
2153*6236dae4SAndroid Build Coastguard Worker           if(!*per->outfile) {
2154*6236dae4SAndroid Build Coastguard Worker             warnf(global, "output glob produces empty string");
2155*6236dae4SAndroid Build Coastguard Worker             result = CURLE_WRITE_ERROR;
2156*6236dae4SAndroid Build Coastguard Worker             break;
2157*6236dae4SAndroid Build Coastguard Worker           }
2158*6236dae4SAndroid Build Coastguard Worker         }
2159*6236dae4SAndroid Build Coastguard Worker         DEBUGASSERT(per->outfile);
2160*6236dae4SAndroid Build Coastguard Worker 
2161*6236dae4SAndroid Build Coastguard Worker         if(config->output_dir && *config->output_dir) {
2162*6236dae4SAndroid Build Coastguard Worker           char *d = aprintf("%s/%s", config->output_dir, per->outfile);
2163*6236dae4SAndroid Build Coastguard Worker           if(!d) {
2164*6236dae4SAndroid Build Coastguard Worker             result = CURLE_WRITE_ERROR;
2165*6236dae4SAndroid Build Coastguard Worker             break;
2166*6236dae4SAndroid Build Coastguard Worker           }
2167*6236dae4SAndroid Build Coastguard Worker           free(per->outfile);
2168*6236dae4SAndroid Build Coastguard Worker           per->outfile = d;
2169*6236dae4SAndroid Build Coastguard Worker         }
2170*6236dae4SAndroid Build Coastguard Worker         /* Create the directory hierarchy, if not pre-existent to a multiple
2171*6236dae4SAndroid Build Coastguard Worker            file output call */
2172*6236dae4SAndroid Build Coastguard Worker 
2173*6236dae4SAndroid Build Coastguard Worker         if(config->create_dirs) {
2174*6236dae4SAndroid Build Coastguard Worker           result = create_dir_hierarchy(per->outfile, global);
2175*6236dae4SAndroid Build Coastguard Worker           /* create_dir_hierarchy shows error upon CURLE_WRITE_ERROR */
2176*6236dae4SAndroid Build Coastguard Worker           if(result)
2177*6236dae4SAndroid Build Coastguard Worker             break;
2178*6236dae4SAndroid Build Coastguard Worker         }
2179*6236dae4SAndroid Build Coastguard Worker 
2180*6236dae4SAndroid Build Coastguard Worker         if(config->skip_existing) {
2181*6236dae4SAndroid Build Coastguard Worker           struct_stat fileinfo;
2182*6236dae4SAndroid Build Coastguard Worker           if(!stat(per->outfile, &fileinfo)) {
2183*6236dae4SAndroid Build Coastguard Worker             /* file is present */
2184*6236dae4SAndroid Build Coastguard Worker             notef(global, "skips transfer, \"%s\" exists locally",
2185*6236dae4SAndroid Build Coastguard Worker                   per->outfile);
2186*6236dae4SAndroid Build Coastguard Worker             per->skip = TRUE;
2187*6236dae4SAndroid Build Coastguard Worker             *skipped = TRUE;
2188*6236dae4SAndroid Build Coastguard Worker           }
2189*6236dae4SAndroid Build Coastguard Worker         }
2190*6236dae4SAndroid Build Coastguard Worker         if((urlnode->flags & GETOUT_USEREMOTE)
2191*6236dae4SAndroid Build Coastguard Worker            && config->content_disposition) {
2192*6236dae4SAndroid Build Coastguard Worker           /* Our header callback MIGHT set the filename */
2193*6236dae4SAndroid Build Coastguard Worker           DEBUGASSERT(!outs->filename);
2194*6236dae4SAndroid Build Coastguard Worker         }
2195*6236dae4SAndroid Build Coastguard Worker 
2196*6236dae4SAndroid Build Coastguard Worker         if(config->resume_from_current) {
2197*6236dae4SAndroid Build Coastguard Worker           /* We are told to continue from where we are now. Get the size
2198*6236dae4SAndroid Build Coastguard Worker              of the file as it is now and open it for append instead */
2199*6236dae4SAndroid Build Coastguard Worker           struct_stat fileinfo;
2200*6236dae4SAndroid Build Coastguard Worker           /* VMS -- Danger, the filesize is only valid for stream files */
2201*6236dae4SAndroid Build Coastguard Worker           if(0 == stat(per->outfile, &fileinfo))
2202*6236dae4SAndroid Build Coastguard Worker             /* set offset to current file size: */
2203*6236dae4SAndroid Build Coastguard Worker             config->resume_from = fileinfo.st_size;
2204*6236dae4SAndroid Build Coastguard Worker           else
2205*6236dae4SAndroid Build Coastguard Worker             /* let offset be 0 */
2206*6236dae4SAndroid Build Coastguard Worker             config->resume_from = 0;
2207*6236dae4SAndroid Build Coastguard Worker         }
2208*6236dae4SAndroid Build Coastguard Worker 
2209*6236dae4SAndroid Build Coastguard Worker         if(config->resume_from) {
2210*6236dae4SAndroid Build Coastguard Worker #ifdef __VMS
2211*6236dae4SAndroid Build Coastguard Worker           /* open file for output, forcing VMS output format into stream
2212*6236dae4SAndroid Build Coastguard Worker              mode which is needed for stat() call above to always work. */
2213*6236dae4SAndroid Build Coastguard Worker           FILE *file = fopen(outfile, "ab",
2214*6236dae4SAndroid Build Coastguard Worker                              "ctx=stm", "rfm=stmlf", "rat=cr", "mrs=0");
2215*6236dae4SAndroid Build Coastguard Worker #else
2216*6236dae4SAndroid Build Coastguard Worker           /* open file for output: */
2217*6236dae4SAndroid Build Coastguard Worker           FILE *file = fopen(per->outfile, "ab");
2218*6236dae4SAndroid Build Coastguard Worker #endif
2219*6236dae4SAndroid Build Coastguard Worker           if(!file) {
2220*6236dae4SAndroid Build Coastguard Worker             errorf(global, "cannot open '%s'", per->outfile);
2221*6236dae4SAndroid Build Coastguard Worker             result = CURLE_WRITE_ERROR;
2222*6236dae4SAndroid Build Coastguard Worker             break;
2223*6236dae4SAndroid Build Coastguard Worker           }
2224*6236dae4SAndroid Build Coastguard Worker           outs->fopened = TRUE;
2225*6236dae4SAndroid Build Coastguard Worker           outs->stream = file;
2226*6236dae4SAndroid Build Coastguard Worker           outs->init = config->resume_from;
2227*6236dae4SAndroid Build Coastguard Worker         }
2228*6236dae4SAndroid Build Coastguard Worker         else {
2229*6236dae4SAndroid Build Coastguard Worker           outs->stream = NULL; /* open when needed */
2230*6236dae4SAndroid Build Coastguard Worker         }
2231*6236dae4SAndroid Build Coastguard Worker         outs->filename = per->outfile;
2232*6236dae4SAndroid Build Coastguard Worker         outs->s_isreg = TRUE;
2233*6236dae4SAndroid Build Coastguard Worker       }
2234*6236dae4SAndroid Build Coastguard Worker 
2235*6236dae4SAndroid Build Coastguard Worker       if(per->uploadfile && !stdin_upload(per->uploadfile)) {
2236*6236dae4SAndroid Build Coastguard Worker         /*
2237*6236dae4SAndroid Build Coastguard Worker          * We have specified a file to upload and it is not "-".
2238*6236dae4SAndroid Build Coastguard Worker          */
2239*6236dae4SAndroid Build Coastguard Worker         result = add_file_name_to_url(per->curl, &per->url,
2240*6236dae4SAndroid Build Coastguard Worker                                       per->uploadfile);
2241*6236dae4SAndroid Build Coastguard Worker         if(result)
2242*6236dae4SAndroid Build Coastguard Worker           break;
2243*6236dae4SAndroid Build Coastguard Worker       }
2244*6236dae4SAndroid Build Coastguard Worker       else if(per->uploadfile && stdin_upload(per->uploadfile)) {
2245*6236dae4SAndroid Build Coastguard Worker         /* count to see if there are more than one auth bit set
2246*6236dae4SAndroid Build Coastguard Worker            in the authtype field */
2247*6236dae4SAndroid Build Coastguard Worker         int authbits = 0;
2248*6236dae4SAndroid Build Coastguard Worker         int bitcheck = 0;
2249*6236dae4SAndroid Build Coastguard Worker         while(bitcheck < 32) {
2250*6236dae4SAndroid Build Coastguard Worker           if(config->authtype & (1UL << bitcheck++)) {
2251*6236dae4SAndroid Build Coastguard Worker             authbits++;
2252*6236dae4SAndroid Build Coastguard Worker             if(authbits > 1) {
2253*6236dae4SAndroid Build Coastguard Worker               /* more than one, we are done! */
2254*6236dae4SAndroid Build Coastguard Worker               break;
2255*6236dae4SAndroid Build Coastguard Worker             }
2256*6236dae4SAndroid Build Coastguard Worker           }
2257*6236dae4SAndroid Build Coastguard Worker         }
2258*6236dae4SAndroid Build Coastguard Worker 
2259*6236dae4SAndroid Build Coastguard Worker         /*
2260*6236dae4SAndroid Build Coastguard Worker          * If the user has also selected --anyauth or --proxy-anyauth
2261*6236dae4SAndroid Build Coastguard Worker          * we should warn them.
2262*6236dae4SAndroid Build Coastguard Worker          */
2263*6236dae4SAndroid Build Coastguard Worker         if(config->proxyanyauth || (authbits > 1)) {
2264*6236dae4SAndroid Build Coastguard Worker           warnf(global,
2265*6236dae4SAndroid Build Coastguard Worker                 "Using --anyauth or --proxy-anyauth with upload from stdin"
2266*6236dae4SAndroid Build Coastguard Worker                 " involves a big risk of it not working. Use a temporary"
2267*6236dae4SAndroid Build Coastguard Worker                 " file or a fixed auth type instead");
2268*6236dae4SAndroid Build Coastguard Worker         }
2269*6236dae4SAndroid Build Coastguard Worker 
2270*6236dae4SAndroid Build Coastguard Worker         DEBUGASSERT(per->infdopen == FALSE);
2271*6236dae4SAndroid Build Coastguard Worker         DEBUGASSERT(per->infd == STDIN_FILENO);
2272*6236dae4SAndroid Build Coastguard Worker 
2273*6236dae4SAndroid Build Coastguard Worker         set_binmode(stdin);
2274*6236dae4SAndroid Build Coastguard Worker         if(!strcmp(per->uploadfile, ".")) {
2275*6236dae4SAndroid Build Coastguard Worker           if(curlx_nonblock((curl_socket_t)per->infd, TRUE) < 0)
2276*6236dae4SAndroid Build Coastguard Worker             warnf(global,
2277*6236dae4SAndroid Build Coastguard Worker                   "fcntl failed on fd=%d: %s", per->infd, strerror(errno));
2278*6236dae4SAndroid Build Coastguard Worker         }
2279*6236dae4SAndroid Build Coastguard Worker       }
2280*6236dae4SAndroid Build Coastguard Worker 
2281*6236dae4SAndroid Build Coastguard Worker       if(per->uploadfile && config->resume_from_current)
2282*6236dae4SAndroid Build Coastguard Worker         config->resume_from = -1; /* -1 will then force get-it-yourself */
2283*6236dae4SAndroid Build Coastguard Worker 
2284*6236dae4SAndroid Build Coastguard Worker       if(output_expected(per->url, per->uploadfile) && outs->stream &&
2285*6236dae4SAndroid Build Coastguard Worker          isatty(fileno(outs->stream)))
2286*6236dae4SAndroid Build Coastguard Worker         /* we send the output to a tty, therefore we switch off the progress
2287*6236dae4SAndroid Build Coastguard Worker            meter */
2288*6236dae4SAndroid Build Coastguard Worker         per->noprogress = global->noprogress = global->isatty = TRUE;
2289*6236dae4SAndroid Build Coastguard Worker       else {
2290*6236dae4SAndroid Build Coastguard Worker         /* progress meter is per download, so restore config
2291*6236dae4SAndroid Build Coastguard Worker            values */
2292*6236dae4SAndroid Build Coastguard Worker         per->noprogress = global->noprogress = orig_noprogress;
2293*6236dae4SAndroid Build Coastguard Worker         global->isatty = orig_isatty;
2294*6236dae4SAndroid Build Coastguard Worker       }
2295*6236dae4SAndroid Build Coastguard Worker 
2296*6236dae4SAndroid Build Coastguard Worker       if(httpgetfields || config->query) {
2297*6236dae4SAndroid Build Coastguard Worker         result = append2query(global, config, per,
2298*6236dae4SAndroid Build Coastguard Worker                               httpgetfields ? httpgetfields : config->query);
2299*6236dae4SAndroid Build Coastguard Worker         if(result)
2300*6236dae4SAndroid Build Coastguard Worker           break;
2301*6236dae4SAndroid Build Coastguard Worker       }
2302*6236dae4SAndroid Build Coastguard Worker 
2303*6236dae4SAndroid Build Coastguard Worker       if((!per->outfile || !strcmp(per->outfile, "-")) &&
2304*6236dae4SAndroid Build Coastguard Worker          !config->use_ascii) {
2305*6236dae4SAndroid Build Coastguard Worker         /* We get the output to stdout and we have not got the ASCII/text
2306*6236dae4SAndroid Build Coastguard Worker            flag, then set stdout to be binary */
2307*6236dae4SAndroid Build Coastguard Worker         set_binmode(stdout);
2308*6236dae4SAndroid Build Coastguard Worker       }
2309*6236dae4SAndroid Build Coastguard Worker 
2310*6236dae4SAndroid Build Coastguard Worker       /* explicitly passed to stdout means okaying binary gunk */
2311*6236dae4SAndroid Build Coastguard Worker       config->terminal_binary_ok =
2312*6236dae4SAndroid Build Coastguard Worker         (per->outfile && !strcmp(per->outfile, "-"));
2313*6236dae4SAndroid Build Coastguard Worker 
2314*6236dae4SAndroid Build Coastguard Worker       if(config->content_disposition && (urlnode->flags & GETOUT_USEREMOTE))
2315*6236dae4SAndroid Build Coastguard Worker         hdrcbdata->honor_cd_filename = TRUE;
2316*6236dae4SAndroid Build Coastguard Worker       else
2317*6236dae4SAndroid Build Coastguard Worker         hdrcbdata->honor_cd_filename = FALSE;
2318*6236dae4SAndroid Build Coastguard Worker 
2319*6236dae4SAndroid Build Coastguard Worker       hdrcbdata->outs = outs;
2320*6236dae4SAndroid Build Coastguard Worker       hdrcbdata->heads = heads;
2321*6236dae4SAndroid Build Coastguard Worker       hdrcbdata->etag_save = etag_save;
2322*6236dae4SAndroid Build Coastguard Worker       hdrcbdata->global = global;
2323*6236dae4SAndroid Build Coastguard Worker       hdrcbdata->config = config;
2324*6236dae4SAndroid Build Coastguard Worker 
2325*6236dae4SAndroid Build Coastguard Worker       result = config2setopts(global, config, per, capath_from_env,
2326*6236dae4SAndroid Build Coastguard Worker                               curl, share);
2327*6236dae4SAndroid Build Coastguard Worker       if(result)
2328*6236dae4SAndroid Build Coastguard Worker         break;
2329*6236dae4SAndroid Build Coastguard Worker 
2330*6236dae4SAndroid Build Coastguard Worker       /* initialize retry vars for loop below */
2331*6236dae4SAndroid Build Coastguard Worker       per->retry_sleep_default = (config->retry_delay) ?
2332*6236dae4SAndroid Build Coastguard Worker         config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
2333*6236dae4SAndroid Build Coastguard Worker       per->retry_remaining = config->req_retry;
2334*6236dae4SAndroid Build Coastguard Worker       per->retry_sleep = per->retry_sleep_default; /* ms */
2335*6236dae4SAndroid Build Coastguard Worker       per->retrystart = tvnow();
2336*6236dae4SAndroid Build Coastguard Worker 
2337*6236dae4SAndroid Build Coastguard Worker       state->li++;
2338*6236dae4SAndroid Build Coastguard Worker       /* Here's looping around each globbed URL */
2339*6236dae4SAndroid Build Coastguard Worker       if(state->li >= urlnum) {
2340*6236dae4SAndroid Build Coastguard Worker         state->li = 0;
2341*6236dae4SAndroid Build Coastguard Worker         state->urlnum = 0; /* forced reglob of URLs */
2342*6236dae4SAndroid Build Coastguard Worker         glob_cleanup(&state->urls);
2343*6236dae4SAndroid Build Coastguard Worker         state->up++;
2344*6236dae4SAndroid Build Coastguard Worker         Curl_safefree(state->uploadfile); /* clear it to get the next */
2345*6236dae4SAndroid Build Coastguard Worker       }
2346*6236dae4SAndroid Build Coastguard Worker     }
2347*6236dae4SAndroid Build Coastguard Worker     else {
2348*6236dae4SAndroid Build Coastguard Worker       /* Free this URL node data without destroying the
2349*6236dae4SAndroid Build Coastguard Worker          node itself nor modifying next pointer. */
2350*6236dae4SAndroid Build Coastguard Worker       urlnode->flags = 0;
2351*6236dae4SAndroid Build Coastguard Worker       glob_cleanup(&state->urls);
2352*6236dae4SAndroid Build Coastguard Worker       state->urlnum = 0;
2353*6236dae4SAndroid Build Coastguard Worker 
2354*6236dae4SAndroid Build Coastguard Worker       Curl_safefree(state->outfiles);
2355*6236dae4SAndroid Build Coastguard Worker       Curl_safefree(state->uploadfile);
2356*6236dae4SAndroid Build Coastguard Worker       /* Free list of globbed upload files */
2357*6236dae4SAndroid Build Coastguard Worker       glob_cleanup(&state->inglob);
2358*6236dae4SAndroid Build Coastguard Worker       state->up = 0;
2359*6236dae4SAndroid Build Coastguard Worker       continue;
2360*6236dae4SAndroid Build Coastguard Worker     }
2361*6236dae4SAndroid Build Coastguard Worker     break;
2362*6236dae4SAndroid Build Coastguard Worker   }
2363*6236dae4SAndroid Build Coastguard Worker   Curl_safefree(state->outfiles);
2364*6236dae4SAndroid Build Coastguard Worker fail:
2365*6236dae4SAndroid Build Coastguard Worker   if(!*added || result) {
2366*6236dae4SAndroid Build Coastguard Worker     *added = FALSE;
2367*6236dae4SAndroid Build Coastguard Worker     single_transfer_cleanup(config);
2368*6236dae4SAndroid Build Coastguard Worker   }
2369*6236dae4SAndroid Build Coastguard Worker   return result;
2370*6236dae4SAndroid Build Coastguard Worker }
2371*6236dae4SAndroid Build Coastguard Worker 
2372*6236dae4SAndroid Build Coastguard Worker static long all_added; /* number of easy handles currently added */
2373*6236dae4SAndroid Build Coastguard Worker 
2374*6236dae4SAndroid Build Coastguard Worker /*
2375*6236dae4SAndroid Build Coastguard Worker  * add_parallel_transfers() sets 'morep' to TRUE if there are more transfers
2376*6236dae4SAndroid Build Coastguard Worker  * to add even after this call returns. sets 'addedp' to TRUE if one or more
2377*6236dae4SAndroid Build Coastguard Worker  * transfers were added.
2378*6236dae4SAndroid Build Coastguard Worker  */
add_parallel_transfers(struct GlobalConfig * global,CURLM * multi,CURLSH * share,bool * morep,bool * addedp)2379*6236dae4SAndroid Build Coastguard Worker static CURLcode add_parallel_transfers(struct GlobalConfig *global,
2380*6236dae4SAndroid Build Coastguard Worker                                        CURLM *multi,
2381*6236dae4SAndroid Build Coastguard Worker                                        CURLSH *share,
2382*6236dae4SAndroid Build Coastguard Worker                                        bool *morep,
2383*6236dae4SAndroid Build Coastguard Worker                                        bool *addedp)
2384*6236dae4SAndroid Build Coastguard Worker {
2385*6236dae4SAndroid Build Coastguard Worker   struct per_transfer *per;
2386*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
2387*6236dae4SAndroid Build Coastguard Worker   CURLMcode mcode;
2388*6236dae4SAndroid Build Coastguard Worker   bool sleeping = FALSE;
2389*6236dae4SAndroid Build Coastguard Worker   char *errorbuf;
2390*6236dae4SAndroid Build Coastguard Worker   *addedp = FALSE;
2391*6236dae4SAndroid Build Coastguard Worker   *morep = FALSE;
2392*6236dae4SAndroid Build Coastguard Worker   if(all_pers < (global->parallel_max*2)) {
2393*6236dae4SAndroid Build Coastguard Worker     bool skipped = FALSE;
2394*6236dae4SAndroid Build Coastguard Worker     do {
2395*6236dae4SAndroid Build Coastguard Worker       result = create_transfer(global, share, addedp, &skipped);
2396*6236dae4SAndroid Build Coastguard Worker       if(result)
2397*6236dae4SAndroid Build Coastguard Worker         return result;
2398*6236dae4SAndroid Build Coastguard Worker     } while(skipped);
2399*6236dae4SAndroid Build Coastguard Worker   }
2400*6236dae4SAndroid Build Coastguard Worker   for(per = transfers; per && (all_added < global->parallel_max);
2401*6236dae4SAndroid Build Coastguard Worker       per = per->next) {
2402*6236dae4SAndroid Build Coastguard Worker     if(per->added || per->skip)
2403*6236dae4SAndroid Build Coastguard Worker       /* already added or to be skipped */
2404*6236dae4SAndroid Build Coastguard Worker       continue;
2405*6236dae4SAndroid Build Coastguard Worker     if(per->startat && (time(NULL) < per->startat)) {
2406*6236dae4SAndroid Build Coastguard Worker       /* this is still delaying */
2407*6236dae4SAndroid Build Coastguard Worker       sleeping = TRUE;
2408*6236dae4SAndroid Build Coastguard Worker       continue;
2409*6236dae4SAndroid Build Coastguard Worker     }
2410*6236dae4SAndroid Build Coastguard Worker     per->added = TRUE;
2411*6236dae4SAndroid Build Coastguard Worker 
2412*6236dae4SAndroid Build Coastguard Worker     result = pre_transfer(global, per);
2413*6236dae4SAndroid Build Coastguard Worker     if(result)
2414*6236dae4SAndroid Build Coastguard Worker       return result;
2415*6236dae4SAndroid Build Coastguard Worker 
2416*6236dae4SAndroid Build Coastguard Worker     errorbuf = malloc(CURL_ERROR_SIZE);
2417*6236dae4SAndroid Build Coastguard Worker     if(!errorbuf)
2418*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
2419*6236dae4SAndroid Build Coastguard Worker 
2420*6236dae4SAndroid Build Coastguard Worker     /* parallel connect means that we do not set PIPEWAIT since pipewait
2421*6236dae4SAndroid Build Coastguard Worker        will make libcurl prefer multiplexing */
2422*6236dae4SAndroid Build Coastguard Worker     (void)curl_easy_setopt(per->curl, CURLOPT_PIPEWAIT,
2423*6236dae4SAndroid Build Coastguard Worker                            global->parallel_connect ? 0L : 1L);
2424*6236dae4SAndroid Build Coastguard Worker     (void)curl_easy_setopt(per->curl, CURLOPT_PRIVATE, per);
2425*6236dae4SAndroid Build Coastguard Worker     (void)curl_easy_setopt(per->curl, CURLOPT_XFERINFOFUNCTION, xferinfo_cb);
2426*6236dae4SAndroid Build Coastguard Worker     (void)curl_easy_setopt(per->curl, CURLOPT_XFERINFODATA, per);
2427*6236dae4SAndroid Build Coastguard Worker     (void)curl_easy_setopt(per->curl, CURLOPT_NOPROGRESS, 0L);
2428*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUGBUILD
2429*6236dae4SAndroid Build Coastguard Worker     if(getenv("CURL_FORBID_REUSE"))
2430*6236dae4SAndroid Build Coastguard Worker       (void)curl_easy_setopt(per->curl, CURLOPT_FORBID_REUSE, 1L);
2431*6236dae4SAndroid Build Coastguard Worker #endif
2432*6236dae4SAndroid Build Coastguard Worker 
2433*6236dae4SAndroid Build Coastguard Worker     mcode = curl_multi_add_handle(multi, per->curl);
2434*6236dae4SAndroid Build Coastguard Worker     if(mcode) {
2435*6236dae4SAndroid Build Coastguard Worker       DEBUGASSERT(mcode == CURLM_OUT_OF_MEMORY);
2436*6236dae4SAndroid Build Coastguard Worker       result = CURLE_OUT_OF_MEMORY;
2437*6236dae4SAndroid Build Coastguard Worker     }
2438*6236dae4SAndroid Build Coastguard Worker 
2439*6236dae4SAndroid Build Coastguard Worker     if(!result) {
2440*6236dae4SAndroid Build Coastguard Worker       bool getadded = FALSE;
2441*6236dae4SAndroid Build Coastguard Worker       bool skipped = FALSE;
2442*6236dae4SAndroid Build Coastguard Worker       do {
2443*6236dae4SAndroid Build Coastguard Worker         result = create_transfer(global, share, &getadded, &skipped);
2444*6236dae4SAndroid Build Coastguard Worker         if(result)
2445*6236dae4SAndroid Build Coastguard Worker           break;
2446*6236dae4SAndroid Build Coastguard Worker       } while(skipped);
2447*6236dae4SAndroid Build Coastguard Worker     }
2448*6236dae4SAndroid Build Coastguard Worker     if(result) {
2449*6236dae4SAndroid Build Coastguard Worker       free(errorbuf);
2450*6236dae4SAndroid Build Coastguard Worker       return result;
2451*6236dae4SAndroid Build Coastguard Worker     }
2452*6236dae4SAndroid Build Coastguard Worker     errorbuf[0] = 0;
2453*6236dae4SAndroid Build Coastguard Worker     (void)curl_easy_setopt(per->curl, CURLOPT_ERRORBUFFER, errorbuf);
2454*6236dae4SAndroid Build Coastguard Worker     per->errorbuffer = errorbuf;
2455*6236dae4SAndroid Build Coastguard Worker     per->added = TRUE;
2456*6236dae4SAndroid Build Coastguard Worker     all_added++;
2457*6236dae4SAndroid Build Coastguard Worker     *addedp = TRUE;
2458*6236dae4SAndroid Build Coastguard Worker   }
2459*6236dae4SAndroid Build Coastguard Worker   *morep = (per || sleeping);
2460*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
2461*6236dae4SAndroid Build Coastguard Worker }
2462*6236dae4SAndroid Build Coastguard Worker 
2463*6236dae4SAndroid Build Coastguard Worker struct parastate {
2464*6236dae4SAndroid Build Coastguard Worker   struct GlobalConfig *global;
2465*6236dae4SAndroid Build Coastguard Worker   CURLM *multi;
2466*6236dae4SAndroid Build Coastguard Worker   CURLSH *share;
2467*6236dae4SAndroid Build Coastguard Worker   CURLMcode mcode;
2468*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
2469*6236dae4SAndroid Build Coastguard Worker   int still_running;
2470*6236dae4SAndroid Build Coastguard Worker   struct timeval start;
2471*6236dae4SAndroid Build Coastguard Worker   bool more_transfers;
2472*6236dae4SAndroid Build Coastguard Worker   bool added_transfers;
2473*6236dae4SAndroid Build Coastguard Worker   /* wrapitup is set TRUE after a critical error occurs to end all transfers */
2474*6236dae4SAndroid Build Coastguard Worker   bool wrapitup;
2475*6236dae4SAndroid Build Coastguard Worker   /* wrapitup_processed is set TRUE after the per transfer abort flag is set */
2476*6236dae4SAndroid Build Coastguard Worker   bool wrapitup_processed;
2477*6236dae4SAndroid Build Coastguard Worker   time_t tick;
2478*6236dae4SAndroid Build Coastguard Worker };
2479*6236dae4SAndroid Build Coastguard Worker 
2480*6236dae4SAndroid Build Coastguard Worker #if defined(DEBUGBUILD) && defined(USE_LIBUV)
2481*6236dae4SAndroid Build Coastguard Worker 
2482*6236dae4SAndroid Build Coastguard Worker #define DEBUG_UV    0
2483*6236dae4SAndroid Build Coastguard Worker 
2484*6236dae4SAndroid Build Coastguard Worker /* object to pass to the callbacks */
2485*6236dae4SAndroid Build Coastguard Worker struct datauv {
2486*6236dae4SAndroid Build Coastguard Worker   uv_timer_t timeout;
2487*6236dae4SAndroid Build Coastguard Worker   uv_loop_t *loop;
2488*6236dae4SAndroid Build Coastguard Worker   struct parastate *s;
2489*6236dae4SAndroid Build Coastguard Worker };
2490*6236dae4SAndroid Build Coastguard Worker 
2491*6236dae4SAndroid Build Coastguard Worker struct contextuv {
2492*6236dae4SAndroid Build Coastguard Worker   uv_poll_t poll_handle;
2493*6236dae4SAndroid Build Coastguard Worker   curl_socket_t sockfd;
2494*6236dae4SAndroid Build Coastguard Worker   struct datauv *uv;
2495*6236dae4SAndroid Build Coastguard Worker };
2496*6236dae4SAndroid Build Coastguard Worker 
2497*6236dae4SAndroid Build Coastguard Worker static CURLcode check_finished(struct parastate *s);
2498*6236dae4SAndroid Build Coastguard Worker 
check_multi_info(struct datauv * uv)2499*6236dae4SAndroid Build Coastguard Worker static void check_multi_info(struct datauv *uv)
2500*6236dae4SAndroid Build Coastguard Worker {
2501*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
2502*6236dae4SAndroid Build Coastguard Worker 
2503*6236dae4SAndroid Build Coastguard Worker   result = check_finished(uv->s);
2504*6236dae4SAndroid Build Coastguard Worker   if(result && !uv->s->result)
2505*6236dae4SAndroid Build Coastguard Worker     uv->s->result = result;
2506*6236dae4SAndroid Build Coastguard Worker 
2507*6236dae4SAndroid Build Coastguard Worker   if(uv->s->more_transfers) {
2508*6236dae4SAndroid Build Coastguard Worker     result = add_parallel_transfers(uv->s->global, uv->s->multi,
2509*6236dae4SAndroid Build Coastguard Worker                                     uv->s->share,
2510*6236dae4SAndroid Build Coastguard Worker                                     &uv->s->more_transfers,
2511*6236dae4SAndroid Build Coastguard Worker                                     &uv->s->added_transfers);
2512*6236dae4SAndroid Build Coastguard Worker     if(result && !uv->s->result)
2513*6236dae4SAndroid Build Coastguard Worker       uv->s->result = result;
2514*6236dae4SAndroid Build Coastguard Worker     if(result)
2515*6236dae4SAndroid Build Coastguard Worker       uv_stop(uv->loop);
2516*6236dae4SAndroid Build Coastguard Worker   }
2517*6236dae4SAndroid Build Coastguard Worker }
2518*6236dae4SAndroid Build Coastguard Worker 
2519*6236dae4SAndroid Build Coastguard Worker /* callback from libuv on socket activity */
on_uv_socket(uv_poll_t * req,int status,int events)2520*6236dae4SAndroid Build Coastguard Worker static void on_uv_socket(uv_poll_t *req, int status, int events)
2521*6236dae4SAndroid Build Coastguard Worker {
2522*6236dae4SAndroid Build Coastguard Worker   int flags = 0;
2523*6236dae4SAndroid Build Coastguard Worker   struct contextuv *c = (struct contextuv *) req->data;
2524*6236dae4SAndroid Build Coastguard Worker   (void)status;
2525*6236dae4SAndroid Build Coastguard Worker   if(events & UV_READABLE)
2526*6236dae4SAndroid Build Coastguard Worker     flags |= CURL_CSELECT_IN;
2527*6236dae4SAndroid Build Coastguard Worker   if(events & UV_WRITABLE)
2528*6236dae4SAndroid Build Coastguard Worker     flags |= CURL_CSELECT_OUT;
2529*6236dae4SAndroid Build Coastguard Worker 
2530*6236dae4SAndroid Build Coastguard Worker   curl_multi_socket_action(c->uv->s->multi, c->sockfd, flags,
2531*6236dae4SAndroid Build Coastguard Worker                            &c->uv->s->still_running);
2532*6236dae4SAndroid Build Coastguard Worker }
2533*6236dae4SAndroid Build Coastguard Worker 
2534*6236dae4SAndroid Build Coastguard Worker /* callback from libuv when timeout expires */
on_uv_timeout(uv_timer_t * req)2535*6236dae4SAndroid Build Coastguard Worker static void on_uv_timeout(uv_timer_t *req)
2536*6236dae4SAndroid Build Coastguard Worker {
2537*6236dae4SAndroid Build Coastguard Worker   struct datauv *uv = (struct datauv *) req->data;
2538*6236dae4SAndroid Build Coastguard Worker #if DEBUG_UV
2539*6236dae4SAndroid Build Coastguard Worker   fprintf(tool_stderr, "parallel_event: on_uv_timeout\n");
2540*6236dae4SAndroid Build Coastguard Worker #endif
2541*6236dae4SAndroid Build Coastguard Worker   if(uv && uv->s) {
2542*6236dae4SAndroid Build Coastguard Worker     curl_multi_socket_action(uv->s->multi, CURL_SOCKET_TIMEOUT, 0,
2543*6236dae4SAndroid Build Coastguard Worker                              &uv->s->still_running);
2544*6236dae4SAndroid Build Coastguard Worker     check_multi_info(uv);
2545*6236dae4SAndroid Build Coastguard Worker   }
2546*6236dae4SAndroid Build Coastguard Worker }
2547*6236dae4SAndroid Build Coastguard Worker 
2548*6236dae4SAndroid Build Coastguard Worker /* callback from libcurl to update the timeout expiry */
cb_timeout(CURLM * multi,long timeout_ms,struct datauv * uv)2549*6236dae4SAndroid Build Coastguard Worker static int cb_timeout(CURLM *multi, long timeout_ms,
2550*6236dae4SAndroid Build Coastguard Worker                       struct datauv *uv)
2551*6236dae4SAndroid Build Coastguard Worker {
2552*6236dae4SAndroid Build Coastguard Worker   (void)multi;
2553*6236dae4SAndroid Build Coastguard Worker #if DEBUG_UV
2554*6236dae4SAndroid Build Coastguard Worker   fprintf(tool_stderr, "parallel_event: cb_timeout=%ld\n", timeout_ms);
2555*6236dae4SAndroid Build Coastguard Worker #endif
2556*6236dae4SAndroid Build Coastguard Worker   if(timeout_ms < 0)
2557*6236dae4SAndroid Build Coastguard Worker     uv_timer_stop(&uv->timeout);
2558*6236dae4SAndroid Build Coastguard Worker   else {
2559*6236dae4SAndroid Build Coastguard Worker     if(timeout_ms == 0)
2560*6236dae4SAndroid Build Coastguard Worker       timeout_ms = 1; /* 0 means call curl_multi_socket_action asap but NOT
2561*6236dae4SAndroid Build Coastguard Worker                          within the callback itself */
2562*6236dae4SAndroid Build Coastguard Worker     uv_timer_start(&uv->timeout, on_uv_timeout, timeout_ms,
2563*6236dae4SAndroid Build Coastguard Worker                    0); /* do not repeat */
2564*6236dae4SAndroid Build Coastguard Worker   }
2565*6236dae4SAndroid Build Coastguard Worker   return 0;
2566*6236dae4SAndroid Build Coastguard Worker }
2567*6236dae4SAndroid Build Coastguard Worker 
create_context(curl_socket_t sockfd,struct datauv * uv)2568*6236dae4SAndroid Build Coastguard Worker static struct contextuv *create_context(curl_socket_t sockfd,
2569*6236dae4SAndroid Build Coastguard Worker                                         struct datauv *uv)
2570*6236dae4SAndroid Build Coastguard Worker {
2571*6236dae4SAndroid Build Coastguard Worker   struct contextuv *c;
2572*6236dae4SAndroid Build Coastguard Worker 
2573*6236dae4SAndroid Build Coastguard Worker   c = (struct contextuv *) malloc(sizeof(*c));
2574*6236dae4SAndroid Build Coastguard Worker 
2575*6236dae4SAndroid Build Coastguard Worker   c->sockfd = sockfd;
2576*6236dae4SAndroid Build Coastguard Worker   c->uv = uv;
2577*6236dae4SAndroid Build Coastguard Worker 
2578*6236dae4SAndroid Build Coastguard Worker   uv_poll_init_socket(uv->loop, &c->poll_handle, sockfd);
2579*6236dae4SAndroid Build Coastguard Worker   c->poll_handle.data = c;
2580*6236dae4SAndroid Build Coastguard Worker 
2581*6236dae4SAndroid Build Coastguard Worker   return c;
2582*6236dae4SAndroid Build Coastguard Worker }
2583*6236dae4SAndroid Build Coastguard Worker 
close_cb(uv_handle_t * handle)2584*6236dae4SAndroid Build Coastguard Worker static void close_cb(uv_handle_t *handle)
2585*6236dae4SAndroid Build Coastguard Worker {
2586*6236dae4SAndroid Build Coastguard Worker   struct contextuv *c = (struct contextuv *) handle->data;
2587*6236dae4SAndroid Build Coastguard Worker   free(c);
2588*6236dae4SAndroid Build Coastguard Worker }
2589*6236dae4SAndroid Build Coastguard Worker 
destroy_context(struct contextuv * c)2590*6236dae4SAndroid Build Coastguard Worker static void destroy_context(struct contextuv *c)
2591*6236dae4SAndroid Build Coastguard Worker {
2592*6236dae4SAndroid Build Coastguard Worker   uv_close((uv_handle_t *) &c->poll_handle, close_cb);
2593*6236dae4SAndroid Build Coastguard Worker }
2594*6236dae4SAndroid Build Coastguard Worker 
2595*6236dae4SAndroid Build Coastguard Worker /* callback from libcurl to update socket activity to wait for */
cb_socket(CURL * easy,curl_socket_t s,int action,struct datauv * uv,void * socketp)2596*6236dae4SAndroid Build Coastguard Worker static int cb_socket(CURL *easy, curl_socket_t s, int action,
2597*6236dae4SAndroid Build Coastguard Worker                      struct datauv *uv,
2598*6236dae4SAndroid Build Coastguard Worker                      void *socketp)
2599*6236dae4SAndroid Build Coastguard Worker {
2600*6236dae4SAndroid Build Coastguard Worker   struct contextuv *c;
2601*6236dae4SAndroid Build Coastguard Worker   int events = 0;
2602*6236dae4SAndroid Build Coastguard Worker   (void)easy;
2603*6236dae4SAndroid Build Coastguard Worker 
2604*6236dae4SAndroid Build Coastguard Worker   switch(action) {
2605*6236dae4SAndroid Build Coastguard Worker   case CURL_POLL_IN:
2606*6236dae4SAndroid Build Coastguard Worker   case CURL_POLL_OUT:
2607*6236dae4SAndroid Build Coastguard Worker   case CURL_POLL_INOUT:
2608*6236dae4SAndroid Build Coastguard Worker     c = socketp ?
2609*6236dae4SAndroid Build Coastguard Worker       (struct contextuv *) socketp : create_context(s, uv);
2610*6236dae4SAndroid Build Coastguard Worker 
2611*6236dae4SAndroid Build Coastguard Worker     curl_multi_assign(uv->s->multi, s, c);
2612*6236dae4SAndroid Build Coastguard Worker 
2613*6236dae4SAndroid Build Coastguard Worker     if(action != CURL_POLL_IN)
2614*6236dae4SAndroid Build Coastguard Worker       events |= UV_WRITABLE;
2615*6236dae4SAndroid Build Coastguard Worker     if(action != CURL_POLL_OUT)
2616*6236dae4SAndroid Build Coastguard Worker       events |= UV_READABLE;
2617*6236dae4SAndroid Build Coastguard Worker 
2618*6236dae4SAndroid Build Coastguard Worker     uv_poll_start(&c->poll_handle, events, on_uv_socket);
2619*6236dae4SAndroid Build Coastguard Worker     break;
2620*6236dae4SAndroid Build Coastguard Worker   case CURL_POLL_REMOVE:
2621*6236dae4SAndroid Build Coastguard Worker     if(socketp) {
2622*6236dae4SAndroid Build Coastguard Worker       c = (struct contextuv *)socketp;
2623*6236dae4SAndroid Build Coastguard Worker       uv_poll_stop(&c->poll_handle);
2624*6236dae4SAndroid Build Coastguard Worker       destroy_context(c);
2625*6236dae4SAndroid Build Coastguard Worker       curl_multi_assign(uv->s->multi, s, NULL);
2626*6236dae4SAndroid Build Coastguard Worker       /* check if we can do more now */
2627*6236dae4SAndroid Build Coastguard Worker       check_multi_info(uv);
2628*6236dae4SAndroid Build Coastguard Worker     }
2629*6236dae4SAndroid Build Coastguard Worker     break;
2630*6236dae4SAndroid Build Coastguard Worker   default:
2631*6236dae4SAndroid Build Coastguard Worker     abort();
2632*6236dae4SAndroid Build Coastguard Worker   }
2633*6236dae4SAndroid Build Coastguard Worker 
2634*6236dae4SAndroid Build Coastguard Worker   return 0;
2635*6236dae4SAndroid Build Coastguard Worker }
2636*6236dae4SAndroid Build Coastguard Worker 
parallel_event(struct parastate * s)2637*6236dae4SAndroid Build Coastguard Worker static CURLcode parallel_event(struct parastate *s)
2638*6236dae4SAndroid Build Coastguard Worker {
2639*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
2640*6236dae4SAndroid Build Coastguard Worker   struct datauv uv = { 0 };
2641*6236dae4SAndroid Build Coastguard Worker 
2642*6236dae4SAndroid Build Coastguard Worker   s->result = CURLE_OK;
2643*6236dae4SAndroid Build Coastguard Worker   uv.s = s;
2644*6236dae4SAndroid Build Coastguard Worker   uv.loop = uv_default_loop();
2645*6236dae4SAndroid Build Coastguard Worker   uv_timer_init(uv.loop, &uv.timeout);
2646*6236dae4SAndroid Build Coastguard Worker   uv.timeout.data = &uv;
2647*6236dae4SAndroid Build Coastguard Worker 
2648*6236dae4SAndroid Build Coastguard Worker   /* setup event callbacks */
2649*6236dae4SAndroid Build Coastguard Worker   curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, cb_socket);
2650*6236dae4SAndroid Build Coastguard Worker   curl_multi_setopt(s->multi, CURLMOPT_SOCKETDATA, &uv);
2651*6236dae4SAndroid Build Coastguard Worker   curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, cb_timeout);
2652*6236dae4SAndroid Build Coastguard Worker   curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, &uv);
2653*6236dae4SAndroid Build Coastguard Worker 
2654*6236dae4SAndroid Build Coastguard Worker   /* kickstart the thing */
2655*6236dae4SAndroid Build Coastguard Worker   curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0,
2656*6236dae4SAndroid Build Coastguard Worker                            &s->still_running);
2657*6236dae4SAndroid Build Coastguard Worker 
2658*6236dae4SAndroid Build Coastguard Worker   while(!s->mcode && (s->still_running || s->more_transfers)) {
2659*6236dae4SAndroid Build Coastguard Worker #if DEBUG_UV
2660*6236dae4SAndroid Build Coastguard Worker     fprintf(tool_stderr, "parallel_event: uv_run(), mcode=%d, %d running, "
2661*6236dae4SAndroid Build Coastguard Worker             "%d more\n", s->mcode, uv.s->still_running, s->more_transfers);
2662*6236dae4SAndroid Build Coastguard Worker #endif
2663*6236dae4SAndroid Build Coastguard Worker     uv_run(uv.loop, UV_RUN_DEFAULT);
2664*6236dae4SAndroid Build Coastguard Worker #if DEBUG_UV
2665*6236dae4SAndroid Build Coastguard Worker     fprintf(tool_stderr, "parallel_event: uv_run() returned\n");
2666*6236dae4SAndroid Build Coastguard Worker #endif
2667*6236dae4SAndroid Build Coastguard Worker 
2668*6236dae4SAndroid Build Coastguard Worker     result = check_finished(s);
2669*6236dae4SAndroid Build Coastguard Worker     if(result && !s->result)
2670*6236dae4SAndroid Build Coastguard Worker       s->result = result;
2671*6236dae4SAndroid Build Coastguard Worker 
2672*6236dae4SAndroid Build Coastguard Worker     /* early exit called */
2673*6236dae4SAndroid Build Coastguard Worker     if(s->wrapitup) {
2674*6236dae4SAndroid Build Coastguard Worker       if(s->still_running && !s->wrapitup_processed) {
2675*6236dae4SAndroid Build Coastguard Worker         struct per_transfer *per;
2676*6236dae4SAndroid Build Coastguard Worker         for(per = transfers; per; per = per->next) {
2677*6236dae4SAndroid Build Coastguard Worker           if(per->added)
2678*6236dae4SAndroid Build Coastguard Worker             per->abort = TRUE;
2679*6236dae4SAndroid Build Coastguard Worker         }
2680*6236dae4SAndroid Build Coastguard Worker         s->wrapitup_processed = TRUE;
2681*6236dae4SAndroid Build Coastguard Worker       }
2682*6236dae4SAndroid Build Coastguard Worker       break;
2683*6236dae4SAndroid Build Coastguard Worker     }
2684*6236dae4SAndroid Build Coastguard Worker 
2685*6236dae4SAndroid Build Coastguard Worker     if(s->more_transfers) {
2686*6236dae4SAndroid Build Coastguard Worker       result = add_parallel_transfers(s->global, s->multi, s->share,
2687*6236dae4SAndroid Build Coastguard Worker                                       &s->more_transfers, &s->added_transfers);
2688*6236dae4SAndroid Build Coastguard Worker       if(result && !s->result)
2689*6236dae4SAndroid Build Coastguard Worker         s->result = result;
2690*6236dae4SAndroid Build Coastguard Worker     }
2691*6236dae4SAndroid Build Coastguard Worker   }
2692*6236dae4SAndroid Build Coastguard Worker 
2693*6236dae4SAndroid Build Coastguard Worker #if DEBUG_UV
2694*6236dae4SAndroid Build Coastguard Worker   fprintf(tool_stderr, "DONE parallel_event -> %d, mcode=%d, %d running, "
2695*6236dae4SAndroid Build Coastguard Worker           "%d more\n",
2696*6236dae4SAndroid Build Coastguard Worker           s->result, s->mcode, uv.s->still_running, s->more_transfers);
2697*6236dae4SAndroid Build Coastguard Worker #endif
2698*6236dae4SAndroid Build Coastguard Worker   return s->result;
2699*6236dae4SAndroid Build Coastguard Worker }
2700*6236dae4SAndroid Build Coastguard Worker 
2701*6236dae4SAndroid Build Coastguard Worker #endif
2702*6236dae4SAndroid Build Coastguard Worker 
check_finished(struct parastate * s)2703*6236dae4SAndroid Build Coastguard Worker static CURLcode check_finished(struct parastate *s)
2704*6236dae4SAndroid Build Coastguard Worker {
2705*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
2706*6236dae4SAndroid Build Coastguard Worker   int rc;
2707*6236dae4SAndroid Build Coastguard Worker   CURLMsg *msg;
2708*6236dae4SAndroid Build Coastguard Worker   bool checkmore = FALSE;
2709*6236dae4SAndroid Build Coastguard Worker   struct GlobalConfig *global = s->global;
2710*6236dae4SAndroid Build Coastguard Worker   progress_meter(global, &s->start, FALSE);
2711*6236dae4SAndroid Build Coastguard Worker   do {
2712*6236dae4SAndroid Build Coastguard Worker     msg = curl_multi_info_read(s->multi, &rc);
2713*6236dae4SAndroid Build Coastguard Worker     if(msg) {
2714*6236dae4SAndroid Build Coastguard Worker       bool retry;
2715*6236dae4SAndroid Build Coastguard Worker       long delay;
2716*6236dae4SAndroid Build Coastguard Worker       struct per_transfer *ended;
2717*6236dae4SAndroid Build Coastguard Worker       CURL *easy = msg->easy_handle;
2718*6236dae4SAndroid Build Coastguard Worker       CURLcode tres = msg->data.result;
2719*6236dae4SAndroid Build Coastguard Worker       curl_easy_getinfo(easy, CURLINFO_PRIVATE, (void *)&ended);
2720*6236dae4SAndroid Build Coastguard Worker       curl_multi_remove_handle(s->multi, easy);
2721*6236dae4SAndroid Build Coastguard Worker 
2722*6236dae4SAndroid Build Coastguard Worker       if(ended->abort && (tres == CURLE_ABORTED_BY_CALLBACK) &&
2723*6236dae4SAndroid Build Coastguard Worker          ended->errorbuffer) {
2724*6236dae4SAndroid Build Coastguard Worker         msnprintf(ended->errorbuffer, CURL_ERROR_SIZE,
2725*6236dae4SAndroid Build Coastguard Worker                   "Transfer aborted due to critical error "
2726*6236dae4SAndroid Build Coastguard Worker                   "in another transfer");
2727*6236dae4SAndroid Build Coastguard Worker       }
2728*6236dae4SAndroid Build Coastguard Worker       tres = post_per_transfer(global, ended, tres, &retry, &delay);
2729*6236dae4SAndroid Build Coastguard Worker       progress_finalize(ended); /* before it goes away */
2730*6236dae4SAndroid Build Coastguard Worker       all_added--; /* one fewer added */
2731*6236dae4SAndroid Build Coastguard Worker       checkmore = TRUE;
2732*6236dae4SAndroid Build Coastguard Worker       if(retry) {
2733*6236dae4SAndroid Build Coastguard Worker         ended->added = FALSE; /* add it again */
2734*6236dae4SAndroid Build Coastguard Worker         /* we delay retries in full integer seconds only */
2735*6236dae4SAndroid Build Coastguard Worker         ended->startat = delay ? time(NULL) + delay/1000 : 0;
2736*6236dae4SAndroid Build Coastguard Worker       }
2737*6236dae4SAndroid Build Coastguard Worker       else {
2738*6236dae4SAndroid Build Coastguard Worker         /* result receives this transfer's error unless the transfer was
2739*6236dae4SAndroid Build Coastguard Worker            marked for abort due to a critical error in another transfer */
2740*6236dae4SAndroid Build Coastguard Worker         if(tres && (!ended->abort || !result))
2741*6236dae4SAndroid Build Coastguard Worker           result = tres;
2742*6236dae4SAndroid Build Coastguard Worker         if(is_fatal_error(result) || (result && global->fail_early))
2743*6236dae4SAndroid Build Coastguard Worker           s->wrapitup = TRUE;
2744*6236dae4SAndroid Build Coastguard Worker         (void)del_per_transfer(ended);
2745*6236dae4SAndroid Build Coastguard Worker       }
2746*6236dae4SAndroid Build Coastguard Worker     }
2747*6236dae4SAndroid Build Coastguard Worker   } while(msg);
2748*6236dae4SAndroid Build Coastguard Worker   if(!s->wrapitup) {
2749*6236dae4SAndroid Build Coastguard Worker     if(!checkmore) {
2750*6236dae4SAndroid Build Coastguard Worker       time_t tock = time(NULL);
2751*6236dae4SAndroid Build Coastguard Worker       if(s->tick != tock) {
2752*6236dae4SAndroid Build Coastguard Worker         checkmore = TRUE;
2753*6236dae4SAndroid Build Coastguard Worker         s->tick = tock;
2754*6236dae4SAndroid Build Coastguard Worker       }
2755*6236dae4SAndroid Build Coastguard Worker     }
2756*6236dae4SAndroid Build Coastguard Worker     if(checkmore) {
2757*6236dae4SAndroid Build Coastguard Worker       /* one or more transfers completed, add more! */
2758*6236dae4SAndroid Build Coastguard Worker       CURLcode tres = add_parallel_transfers(global, s->multi, s->share,
2759*6236dae4SAndroid Build Coastguard Worker                                              &s->more_transfers,
2760*6236dae4SAndroid Build Coastguard Worker                                              &s->added_transfers);
2761*6236dae4SAndroid Build Coastguard Worker       if(tres)
2762*6236dae4SAndroid Build Coastguard Worker         result = tres;
2763*6236dae4SAndroid Build Coastguard Worker       if(s->added_transfers)
2764*6236dae4SAndroid Build Coastguard Worker         /* we added new ones, make sure the loop does not exit yet */
2765*6236dae4SAndroid Build Coastguard Worker         s->still_running = 1;
2766*6236dae4SAndroid Build Coastguard Worker     }
2767*6236dae4SAndroid Build Coastguard Worker     if(is_fatal_error(result) || (result && global->fail_early))
2768*6236dae4SAndroid Build Coastguard Worker       s->wrapitup = TRUE;
2769*6236dae4SAndroid Build Coastguard Worker   }
2770*6236dae4SAndroid Build Coastguard Worker   return result;
2771*6236dae4SAndroid Build Coastguard Worker }
2772*6236dae4SAndroid Build Coastguard Worker 
parallel_transfers(struct GlobalConfig * global,CURLSH * share)2773*6236dae4SAndroid Build Coastguard Worker static CURLcode parallel_transfers(struct GlobalConfig *global,
2774*6236dae4SAndroid Build Coastguard Worker                                    CURLSH *share)
2775*6236dae4SAndroid Build Coastguard Worker {
2776*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
2777*6236dae4SAndroid Build Coastguard Worker   struct parastate p;
2778*6236dae4SAndroid Build Coastguard Worker   struct parastate *s = &p;
2779*6236dae4SAndroid Build Coastguard Worker   s->share = share;
2780*6236dae4SAndroid Build Coastguard Worker   s->mcode = CURLM_OK;
2781*6236dae4SAndroid Build Coastguard Worker   s->result = CURLE_OK;
2782*6236dae4SAndroid Build Coastguard Worker   s->still_running = 1;
2783*6236dae4SAndroid Build Coastguard Worker   s->start = tvnow();
2784*6236dae4SAndroid Build Coastguard Worker   s->wrapitup = FALSE;
2785*6236dae4SAndroid Build Coastguard Worker   s->wrapitup_processed = FALSE;
2786*6236dae4SAndroid Build Coastguard Worker   s->tick = time(NULL);
2787*6236dae4SAndroid Build Coastguard Worker   s->global = global;
2788*6236dae4SAndroid Build Coastguard Worker   s->multi = curl_multi_init();
2789*6236dae4SAndroid Build Coastguard Worker   if(!s->multi)
2790*6236dae4SAndroid Build Coastguard Worker     return CURLE_OUT_OF_MEMORY;
2791*6236dae4SAndroid Build Coastguard Worker 
2792*6236dae4SAndroid Build Coastguard Worker   result = add_parallel_transfers(global, s->multi, s->share,
2793*6236dae4SAndroid Build Coastguard Worker                                   &s->more_transfers, &s->added_transfers);
2794*6236dae4SAndroid Build Coastguard Worker   if(result) {
2795*6236dae4SAndroid Build Coastguard Worker     curl_multi_cleanup(s->multi);
2796*6236dae4SAndroid Build Coastguard Worker     return result;
2797*6236dae4SAndroid Build Coastguard Worker   }
2798*6236dae4SAndroid Build Coastguard Worker 
2799*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUGBUILD
2800*6236dae4SAndroid Build Coastguard Worker   if(global->test_event_based)
2801*6236dae4SAndroid Build Coastguard Worker #ifdef USE_LIBUV
2802*6236dae4SAndroid Build Coastguard Worker     result = parallel_event(s);
2803*6236dae4SAndroid Build Coastguard Worker #else
2804*6236dae4SAndroid Build Coastguard Worker     errorf(global, "Testing --parallel event-based requires libuv");
2805*6236dae4SAndroid Build Coastguard Worker #endif
2806*6236dae4SAndroid Build Coastguard Worker   else
2807*6236dae4SAndroid Build Coastguard Worker #endif
2808*6236dae4SAndroid Build Coastguard Worker 
2809*6236dae4SAndroid Build Coastguard Worker   if(all_added) {
2810*6236dae4SAndroid Build Coastguard Worker     while(!s->mcode && (s->still_running || s->more_transfers)) {
2811*6236dae4SAndroid Build Coastguard Worker       /* If stopping prematurely (eg due to a --fail-early condition) then
2812*6236dae4SAndroid Build Coastguard Worker          signal that any transfers in the multi should abort (via progress
2813*6236dae4SAndroid Build Coastguard Worker          callback). */
2814*6236dae4SAndroid Build Coastguard Worker       if(s->wrapitup) {
2815*6236dae4SAndroid Build Coastguard Worker         if(!s->still_running)
2816*6236dae4SAndroid Build Coastguard Worker           break;
2817*6236dae4SAndroid Build Coastguard Worker         if(!s->wrapitup_processed) {
2818*6236dae4SAndroid Build Coastguard Worker           struct per_transfer *per;
2819*6236dae4SAndroid Build Coastguard Worker           for(per = transfers; per; per = per->next) {
2820*6236dae4SAndroid Build Coastguard Worker             if(per->added)
2821*6236dae4SAndroid Build Coastguard Worker               per->abort = TRUE;
2822*6236dae4SAndroid Build Coastguard Worker           }
2823*6236dae4SAndroid Build Coastguard Worker           s->wrapitup_processed = TRUE;
2824*6236dae4SAndroid Build Coastguard Worker         }
2825*6236dae4SAndroid Build Coastguard Worker       }
2826*6236dae4SAndroid Build Coastguard Worker 
2827*6236dae4SAndroid Build Coastguard Worker       s->mcode = curl_multi_poll(s->multi, NULL, 0, 1000, NULL);
2828*6236dae4SAndroid Build Coastguard Worker       if(!s->mcode)
2829*6236dae4SAndroid Build Coastguard Worker         s->mcode = curl_multi_perform(s->multi, &s->still_running);
2830*6236dae4SAndroid Build Coastguard Worker       if(!s->mcode)
2831*6236dae4SAndroid Build Coastguard Worker         result = check_finished(s);
2832*6236dae4SAndroid Build Coastguard Worker     }
2833*6236dae4SAndroid Build Coastguard Worker 
2834*6236dae4SAndroid Build Coastguard Worker     (void)progress_meter(global, &s->start, TRUE);
2835*6236dae4SAndroid Build Coastguard Worker   }
2836*6236dae4SAndroid Build Coastguard Worker 
2837*6236dae4SAndroid Build Coastguard Worker   /* Make sure to return some kind of error if there was a multi problem */
2838*6236dae4SAndroid Build Coastguard Worker   if(s->mcode) {
2839*6236dae4SAndroid Build Coastguard Worker     result = (s->mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY :
2840*6236dae4SAndroid Build Coastguard Worker       /* The other multi errors should never happen, so return
2841*6236dae4SAndroid Build Coastguard Worker          something suitably generic */
2842*6236dae4SAndroid Build Coastguard Worker       CURLE_BAD_FUNCTION_ARGUMENT;
2843*6236dae4SAndroid Build Coastguard Worker   }
2844*6236dae4SAndroid Build Coastguard Worker 
2845*6236dae4SAndroid Build Coastguard Worker   curl_multi_cleanup(s->multi);
2846*6236dae4SAndroid Build Coastguard Worker 
2847*6236dae4SAndroid Build Coastguard Worker   return result;
2848*6236dae4SAndroid Build Coastguard Worker }
2849*6236dae4SAndroid Build Coastguard Worker 
serial_transfers(struct GlobalConfig * global,CURLSH * share)2850*6236dae4SAndroid Build Coastguard Worker static CURLcode serial_transfers(struct GlobalConfig *global,
2851*6236dae4SAndroid Build Coastguard Worker                                  CURLSH *share)
2852*6236dae4SAndroid Build Coastguard Worker {
2853*6236dae4SAndroid Build Coastguard Worker   CURLcode returncode = CURLE_OK;
2854*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
2855*6236dae4SAndroid Build Coastguard Worker   struct per_transfer *per;
2856*6236dae4SAndroid Build Coastguard Worker   bool added = FALSE;
2857*6236dae4SAndroid Build Coastguard Worker   bool skipped = FALSE;
2858*6236dae4SAndroid Build Coastguard Worker 
2859*6236dae4SAndroid Build Coastguard Worker   result = create_transfer(global, share, &added, &skipped);
2860*6236dae4SAndroid Build Coastguard Worker   if(result)
2861*6236dae4SAndroid Build Coastguard Worker     return result;
2862*6236dae4SAndroid Build Coastguard Worker   if(!added) {
2863*6236dae4SAndroid Build Coastguard Worker     errorf(global, "no transfer performed");
2864*6236dae4SAndroid Build Coastguard Worker     return CURLE_READ_ERROR;
2865*6236dae4SAndroid Build Coastguard Worker   }
2866*6236dae4SAndroid Build Coastguard Worker   for(per = transfers; per;) {
2867*6236dae4SAndroid Build Coastguard Worker     bool retry;
2868*6236dae4SAndroid Build Coastguard Worker     long delay_ms;
2869*6236dae4SAndroid Build Coastguard Worker     bool bailout = FALSE;
2870*6236dae4SAndroid Build Coastguard Worker     struct timeval start;
2871*6236dae4SAndroid Build Coastguard Worker 
2872*6236dae4SAndroid Build Coastguard Worker     start = tvnow();
2873*6236dae4SAndroid Build Coastguard Worker     if(!per->skip) {
2874*6236dae4SAndroid Build Coastguard Worker       result = pre_transfer(global, per);
2875*6236dae4SAndroid Build Coastguard Worker       if(result)
2876*6236dae4SAndroid Build Coastguard Worker         break;
2877*6236dae4SAndroid Build Coastguard Worker 
2878*6236dae4SAndroid Build Coastguard Worker       if(global->libcurl) {
2879*6236dae4SAndroid Build Coastguard Worker         result = easysrc_perform();
2880*6236dae4SAndroid Build Coastguard Worker         if(result)
2881*6236dae4SAndroid Build Coastguard Worker           break;
2882*6236dae4SAndroid Build Coastguard Worker       }
2883*6236dae4SAndroid Build Coastguard Worker 
2884*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUGBUILD
2885*6236dae4SAndroid Build Coastguard Worker       if(getenv("CURL_FORBID_REUSE"))
2886*6236dae4SAndroid Build Coastguard Worker         (void)curl_easy_setopt(per->curl, CURLOPT_FORBID_REUSE, 1L);
2887*6236dae4SAndroid Build Coastguard Worker 
2888*6236dae4SAndroid Build Coastguard Worker       if(global->test_event_based)
2889*6236dae4SAndroid Build Coastguard Worker         result = curl_easy_perform_ev(per->curl);
2890*6236dae4SAndroid Build Coastguard Worker       else
2891*6236dae4SAndroid Build Coastguard Worker #endif
2892*6236dae4SAndroid Build Coastguard Worker         result = curl_easy_perform(per->curl);
2893*6236dae4SAndroid Build Coastguard Worker     }
2894*6236dae4SAndroid Build Coastguard Worker 
2895*6236dae4SAndroid Build Coastguard Worker     returncode = post_per_transfer(global, per, result, &retry, &delay_ms);
2896*6236dae4SAndroid Build Coastguard Worker     if(retry) {
2897*6236dae4SAndroid Build Coastguard Worker       tool_go_sleep(delay_ms);
2898*6236dae4SAndroid Build Coastguard Worker       continue;
2899*6236dae4SAndroid Build Coastguard Worker     }
2900*6236dae4SAndroid Build Coastguard Worker 
2901*6236dae4SAndroid Build Coastguard Worker     /* Bail out upon critical errors or --fail-early */
2902*6236dae4SAndroid Build Coastguard Worker     if(is_fatal_error(returncode) || (returncode && global->fail_early))
2903*6236dae4SAndroid Build Coastguard Worker       bailout = TRUE;
2904*6236dae4SAndroid Build Coastguard Worker     else {
2905*6236dae4SAndroid Build Coastguard Worker       do {
2906*6236dae4SAndroid Build Coastguard Worker         /* setup the next one just before we delete this */
2907*6236dae4SAndroid Build Coastguard Worker         result = create_transfer(global, share, &added, &skipped);
2908*6236dae4SAndroid Build Coastguard Worker         if(result) {
2909*6236dae4SAndroid Build Coastguard Worker           returncode = result;
2910*6236dae4SAndroid Build Coastguard Worker           bailout = TRUE;
2911*6236dae4SAndroid Build Coastguard Worker           break;
2912*6236dae4SAndroid Build Coastguard Worker         }
2913*6236dae4SAndroid Build Coastguard Worker       } while(skipped);
2914*6236dae4SAndroid Build Coastguard Worker     }
2915*6236dae4SAndroid Build Coastguard Worker 
2916*6236dae4SAndroid Build Coastguard Worker     per = del_per_transfer(per);
2917*6236dae4SAndroid Build Coastguard Worker 
2918*6236dae4SAndroid Build Coastguard Worker     if(bailout)
2919*6236dae4SAndroid Build Coastguard Worker       break;
2920*6236dae4SAndroid Build Coastguard Worker 
2921*6236dae4SAndroid Build Coastguard Worker     if(per && global->ms_per_transfer) {
2922*6236dae4SAndroid Build Coastguard Worker       /* how long time did the most recent transfer take in number of
2923*6236dae4SAndroid Build Coastguard Worker          milliseconds */
2924*6236dae4SAndroid Build Coastguard Worker       long milli = tvdiff(tvnow(), start);
2925*6236dae4SAndroid Build Coastguard Worker       if(milli < global->ms_per_transfer) {
2926*6236dae4SAndroid Build Coastguard Worker         notef(global, "Transfer took %ld ms, waits %ldms as set by --rate",
2927*6236dae4SAndroid Build Coastguard Worker               milli, global->ms_per_transfer - milli);
2928*6236dae4SAndroid Build Coastguard Worker         /* The transfer took less time than wanted. Wait a little. */
2929*6236dae4SAndroid Build Coastguard Worker         tool_go_sleep(global->ms_per_transfer - milli);
2930*6236dae4SAndroid Build Coastguard Worker       }
2931*6236dae4SAndroid Build Coastguard Worker     }
2932*6236dae4SAndroid Build Coastguard Worker   }
2933*6236dae4SAndroid Build Coastguard Worker   if(returncode)
2934*6236dae4SAndroid Build Coastguard Worker     /* returncode errors have priority */
2935*6236dae4SAndroid Build Coastguard Worker     result = returncode;
2936*6236dae4SAndroid Build Coastguard Worker 
2937*6236dae4SAndroid Build Coastguard Worker   if(result)
2938*6236dae4SAndroid Build Coastguard Worker     single_transfer_cleanup(global->current);
2939*6236dae4SAndroid Build Coastguard Worker 
2940*6236dae4SAndroid Build Coastguard Worker   return result;
2941*6236dae4SAndroid Build Coastguard Worker }
2942*6236dae4SAndroid Build Coastguard Worker 
is_using_schannel(int * using)2943*6236dae4SAndroid Build Coastguard Worker static CURLcode is_using_schannel(int *using)
2944*6236dae4SAndroid Build Coastguard Worker {
2945*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
2946*6236dae4SAndroid Build Coastguard Worker   static int using_schannel = -1; /* -1 = not checked
2947*6236dae4SAndroid Build Coastguard Worker                                      0 = nope
2948*6236dae4SAndroid Build Coastguard Worker                                      1 = yes */
2949*6236dae4SAndroid Build Coastguard Worker   if(using_schannel == -1) {
2950*6236dae4SAndroid Build Coastguard Worker     CURL *curltls = curl_easy_init();
2951*6236dae4SAndroid Build Coastguard Worker     /* The TLS backend remains, so keep the info */
2952*6236dae4SAndroid Build Coastguard Worker     struct curl_tlssessioninfo *tls_backend_info = NULL;
2953*6236dae4SAndroid Build Coastguard Worker 
2954*6236dae4SAndroid Build Coastguard Worker     if(!curltls)
2955*6236dae4SAndroid Build Coastguard Worker       result = CURLE_OUT_OF_MEMORY;
2956*6236dae4SAndroid Build Coastguard Worker     else {
2957*6236dae4SAndroid Build Coastguard Worker       result = curl_easy_getinfo(curltls, CURLINFO_TLS_SSL_PTR,
2958*6236dae4SAndroid Build Coastguard Worker                                  &tls_backend_info);
2959*6236dae4SAndroid Build Coastguard Worker       if(!result)
2960*6236dae4SAndroid Build Coastguard Worker         using_schannel =
2961*6236dae4SAndroid Build Coastguard Worker           (tls_backend_info->backend == CURLSSLBACKEND_SCHANNEL);
2962*6236dae4SAndroid Build Coastguard Worker     }
2963*6236dae4SAndroid Build Coastguard Worker     curl_easy_cleanup(curltls);
2964*6236dae4SAndroid Build Coastguard Worker     if(result)
2965*6236dae4SAndroid Build Coastguard Worker       return result;
2966*6236dae4SAndroid Build Coastguard Worker   }
2967*6236dae4SAndroid Build Coastguard Worker   *using = using_schannel;
2968*6236dae4SAndroid Build Coastguard Worker   return result;
2969*6236dae4SAndroid Build Coastguard Worker }
2970*6236dae4SAndroid Build Coastguard Worker 
2971*6236dae4SAndroid Build Coastguard Worker /* Set the CA cert locations specified in the environment. For Windows if no
2972*6236dae4SAndroid Build Coastguard Worker  * environment-specified filename is found then check for CA bundle default
2973*6236dae4SAndroid Build Coastguard Worker  * filename curl-ca-bundle.crt in the user's PATH.
2974*6236dae4SAndroid Build Coastguard Worker  *
2975*6236dae4SAndroid Build Coastguard Worker  * If Schannel is the selected SSL backend then these locations are ignored.
2976*6236dae4SAndroid Build Coastguard Worker  * We allow setting CA location for Schannel only when explicitly specified by
2977*6236dae4SAndroid Build Coastguard Worker  * the user via CURLOPT_CAINFO / --cacert.
2978*6236dae4SAndroid Build Coastguard Worker  */
2979*6236dae4SAndroid Build Coastguard Worker 
cacertpaths(struct OperationConfig * config)2980*6236dae4SAndroid Build Coastguard Worker static CURLcode cacertpaths(struct OperationConfig *config)
2981*6236dae4SAndroid Build Coastguard Worker {
2982*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OUT_OF_MEMORY;
2983*6236dae4SAndroid Build Coastguard Worker   char *env = curl_getenv("CURL_CA_BUNDLE");
2984*6236dae4SAndroid Build Coastguard Worker   if(env) {
2985*6236dae4SAndroid Build Coastguard Worker     config->cacert = strdup(env);
2986*6236dae4SAndroid Build Coastguard Worker     curl_free(env);
2987*6236dae4SAndroid Build Coastguard Worker     if(!config->cacert)
2988*6236dae4SAndroid Build Coastguard Worker       goto fail;
2989*6236dae4SAndroid Build Coastguard Worker   }
2990*6236dae4SAndroid Build Coastguard Worker   else {
2991*6236dae4SAndroid Build Coastguard Worker     env = curl_getenv("SSL_CERT_DIR");
2992*6236dae4SAndroid Build Coastguard Worker     if(env) {
2993*6236dae4SAndroid Build Coastguard Worker       config->capath = strdup(env);
2994*6236dae4SAndroid Build Coastguard Worker       curl_free(env);
2995*6236dae4SAndroid Build Coastguard Worker       if(!config->capath)
2996*6236dae4SAndroid Build Coastguard Worker         goto fail;
2997*6236dae4SAndroid Build Coastguard Worker     }
2998*6236dae4SAndroid Build Coastguard Worker     env = curl_getenv("SSL_CERT_FILE");
2999*6236dae4SAndroid Build Coastguard Worker     if(env) {
3000*6236dae4SAndroid Build Coastguard Worker       config->cacert = strdup(env);
3001*6236dae4SAndroid Build Coastguard Worker       curl_free(env);
3002*6236dae4SAndroid Build Coastguard Worker       if(!config->cacert)
3003*6236dae4SAndroid Build Coastguard Worker         goto fail;
3004*6236dae4SAndroid Build Coastguard Worker     }
3005*6236dae4SAndroid Build Coastguard Worker   }
3006*6236dae4SAndroid Build Coastguard Worker 
3007*6236dae4SAndroid Build Coastguard Worker #ifdef _WIN32
3008*6236dae4SAndroid Build Coastguard Worker   if(!env) {
3009*6236dae4SAndroid Build Coastguard Worker #if defined(CURL_CA_SEARCH_SAFE)
3010*6236dae4SAndroid Build Coastguard Worker     char *cacert = NULL;
3011*6236dae4SAndroid Build Coastguard Worker     FILE *cafile = Curl_execpath("curl-ca-bundle.crt", &cacert);
3012*6236dae4SAndroid Build Coastguard Worker     if(cafile) {
3013*6236dae4SAndroid Build Coastguard Worker       fclose(cafile);
3014*6236dae4SAndroid Build Coastguard Worker       config->cacert = strdup(cacert);
3015*6236dae4SAndroid Build Coastguard Worker     }
3016*6236dae4SAndroid Build Coastguard Worker #elif !defined(CURL_WINDOWS_UWP) && !defined(CURL_DISABLE_CA_SEARCH)
3017*6236dae4SAndroid Build Coastguard Worker     result = FindWin32CACert(config, TEXT("curl-ca-bundle.crt"));
3018*6236dae4SAndroid Build Coastguard Worker     if(result)
3019*6236dae4SAndroid Build Coastguard Worker       goto fail;
3020*6236dae4SAndroid Build Coastguard Worker #endif
3021*6236dae4SAndroid Build Coastguard Worker   }
3022*6236dae4SAndroid Build Coastguard Worker #endif
3023*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
3024*6236dae4SAndroid Build Coastguard Worker fail:
3025*6236dae4SAndroid Build Coastguard Worker   free(config->capath);
3026*6236dae4SAndroid Build Coastguard Worker   return result;
3027*6236dae4SAndroid Build Coastguard Worker }
3028*6236dae4SAndroid Build Coastguard Worker 
3029*6236dae4SAndroid Build Coastguard Worker /* setup a transfer for the given config */
transfer_per_config(struct GlobalConfig * global,struct OperationConfig * config,CURLSH * share,bool * added,bool * skipped)3030*6236dae4SAndroid Build Coastguard Worker static CURLcode transfer_per_config(struct GlobalConfig *global,
3031*6236dae4SAndroid Build Coastguard Worker                                     struct OperationConfig *config,
3032*6236dae4SAndroid Build Coastguard Worker                                     CURLSH *share,
3033*6236dae4SAndroid Build Coastguard Worker                                     bool *added,
3034*6236dae4SAndroid Build Coastguard Worker                                     bool *skipped)
3035*6236dae4SAndroid Build Coastguard Worker {
3036*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
3037*6236dae4SAndroid Build Coastguard Worker   bool capath_from_env;
3038*6236dae4SAndroid Build Coastguard Worker   *added = FALSE;
3039*6236dae4SAndroid Build Coastguard Worker 
3040*6236dae4SAndroid Build Coastguard Worker   /* Check we have a url */
3041*6236dae4SAndroid Build Coastguard Worker   if(!config->url_list || !config->url_list->url) {
3042*6236dae4SAndroid Build Coastguard Worker     helpf(tool_stderr, "(%d) no URL specified", CURLE_FAILED_INIT);
3043*6236dae4SAndroid Build Coastguard Worker     return CURLE_FAILED_INIT;
3044*6236dae4SAndroid Build Coastguard Worker   }
3045*6236dae4SAndroid Build Coastguard Worker 
3046*6236dae4SAndroid Build Coastguard Worker   /* On Windows we cannot set the path to curl-ca-bundle.crt at compile time.
3047*6236dae4SAndroid Build Coastguard Worker    * We look for the file in two ways:
3048*6236dae4SAndroid Build Coastguard Worker    * 1: look at the environment variable CURL_CA_BUNDLE for a path
3049*6236dae4SAndroid Build Coastguard Worker    * 2: if #1 is not found, use the Windows API function SearchPath()
3050*6236dae4SAndroid Build Coastguard Worker    *    to find it along the app's path (includes app's dir and CWD)
3051*6236dae4SAndroid Build Coastguard Worker    *
3052*6236dae4SAndroid Build Coastguard Worker    * We support the environment variable thing for non-Windows platforms
3053*6236dae4SAndroid Build Coastguard Worker    * too. Just for the sake of it.
3054*6236dae4SAndroid Build Coastguard Worker    */
3055*6236dae4SAndroid Build Coastguard Worker   capath_from_env = false;
3056*6236dae4SAndroid Build Coastguard Worker   if(feature_ssl &&
3057*6236dae4SAndroid Build Coastguard Worker      !config->cacert &&
3058*6236dae4SAndroid Build Coastguard Worker      !config->capath &&
3059*6236dae4SAndroid Build Coastguard Worker      (!config->insecure_ok || (config->doh_url && !config->doh_insecure_ok))) {
3060*6236dae4SAndroid Build Coastguard Worker     int using_schannel = -1;
3061*6236dae4SAndroid Build Coastguard Worker 
3062*6236dae4SAndroid Build Coastguard Worker     result = is_using_schannel(&using_schannel);
3063*6236dae4SAndroid Build Coastguard Worker 
3064*6236dae4SAndroid Build Coastguard Worker     /* With the addition of CAINFO support for Schannel, this search could
3065*6236dae4SAndroid Build Coastguard Worker      * find a certificate bundle that was previously ignored. To maintain
3066*6236dae4SAndroid Build Coastguard Worker      * backward compatibility, only perform this search if not using Schannel.
3067*6236dae4SAndroid Build Coastguard Worker      */
3068*6236dae4SAndroid Build Coastguard Worker     if(!result && !using_schannel)
3069*6236dae4SAndroid Build Coastguard Worker       result = cacertpaths(config);
3070*6236dae4SAndroid Build Coastguard Worker   }
3071*6236dae4SAndroid Build Coastguard Worker 
3072*6236dae4SAndroid Build Coastguard Worker   if(!result)
3073*6236dae4SAndroid Build Coastguard Worker     result = single_transfer(global, config, share, capath_from_env, added,
3074*6236dae4SAndroid Build Coastguard Worker                              skipped);
3075*6236dae4SAndroid Build Coastguard Worker 
3076*6236dae4SAndroid Build Coastguard Worker   return result;
3077*6236dae4SAndroid Build Coastguard Worker }
3078*6236dae4SAndroid Build Coastguard Worker 
3079*6236dae4SAndroid Build Coastguard Worker /*
3080*6236dae4SAndroid Build Coastguard Worker  * 'create_transfer' gets the details and sets up a new transfer if 'added'
3081*6236dae4SAndroid Build Coastguard Worker  * returns TRUE.
3082*6236dae4SAndroid Build Coastguard Worker  */
create_transfer(struct GlobalConfig * global,CURLSH * share,bool * added,bool * skipped)3083*6236dae4SAndroid Build Coastguard Worker static CURLcode create_transfer(struct GlobalConfig *global,
3084*6236dae4SAndroid Build Coastguard Worker                                 CURLSH *share,
3085*6236dae4SAndroid Build Coastguard Worker                                 bool *added,
3086*6236dae4SAndroid Build Coastguard Worker                                 bool *skipped)
3087*6236dae4SAndroid Build Coastguard Worker {
3088*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
3089*6236dae4SAndroid Build Coastguard Worker   *added = FALSE;
3090*6236dae4SAndroid Build Coastguard Worker   while(global->current) {
3091*6236dae4SAndroid Build Coastguard Worker     result = transfer_per_config(global, global->current, share, added,
3092*6236dae4SAndroid Build Coastguard Worker                                  skipped);
3093*6236dae4SAndroid Build Coastguard Worker     if(!result && !*added) {
3094*6236dae4SAndroid Build Coastguard Worker       /* when one set is drained, continue to next */
3095*6236dae4SAndroid Build Coastguard Worker       global->current = global->current->next;
3096*6236dae4SAndroid Build Coastguard Worker       continue;
3097*6236dae4SAndroid Build Coastguard Worker     }
3098*6236dae4SAndroid Build Coastguard Worker     break;
3099*6236dae4SAndroid Build Coastguard Worker   }
3100*6236dae4SAndroid Build Coastguard Worker   return result;
3101*6236dae4SAndroid Build Coastguard Worker }
3102*6236dae4SAndroid Build Coastguard Worker 
run_all_transfers(struct GlobalConfig * global,CURLSH * share,CURLcode result)3103*6236dae4SAndroid Build Coastguard Worker static CURLcode run_all_transfers(struct GlobalConfig *global,
3104*6236dae4SAndroid Build Coastguard Worker                                   CURLSH *share,
3105*6236dae4SAndroid Build Coastguard Worker                                   CURLcode result)
3106*6236dae4SAndroid Build Coastguard Worker {
3107*6236dae4SAndroid Build Coastguard Worker   /* Save the values of noprogress and isatty to restore them later on */
3108*6236dae4SAndroid Build Coastguard Worker   bool orig_noprogress = global->noprogress;
3109*6236dae4SAndroid Build Coastguard Worker   bool orig_isatty = global->isatty;
3110*6236dae4SAndroid Build Coastguard Worker   struct per_transfer *per;
3111*6236dae4SAndroid Build Coastguard Worker 
3112*6236dae4SAndroid Build Coastguard Worker   /* Time to actually do the transfers */
3113*6236dae4SAndroid Build Coastguard Worker   if(!result) {
3114*6236dae4SAndroid Build Coastguard Worker     if(global->parallel)
3115*6236dae4SAndroid Build Coastguard Worker       result = parallel_transfers(global, share);
3116*6236dae4SAndroid Build Coastguard Worker     else
3117*6236dae4SAndroid Build Coastguard Worker       result = serial_transfers(global, share);
3118*6236dae4SAndroid Build Coastguard Worker   }
3119*6236dae4SAndroid Build Coastguard Worker 
3120*6236dae4SAndroid Build Coastguard Worker   /* cleanup if there are any left */
3121*6236dae4SAndroid Build Coastguard Worker   for(per = transfers; per;) {
3122*6236dae4SAndroid Build Coastguard Worker     bool retry;
3123*6236dae4SAndroid Build Coastguard Worker     long delay;
3124*6236dae4SAndroid Build Coastguard Worker     CURLcode result2 = post_per_transfer(global, per, result, &retry, &delay);
3125*6236dae4SAndroid Build Coastguard Worker     if(!result)
3126*6236dae4SAndroid Build Coastguard Worker       /* do not overwrite the original error */
3127*6236dae4SAndroid Build Coastguard Worker       result = result2;
3128*6236dae4SAndroid Build Coastguard Worker 
3129*6236dae4SAndroid Build Coastguard Worker     /* Free list of given URLs */
3130*6236dae4SAndroid Build Coastguard Worker     clean_getout(per->config);
3131*6236dae4SAndroid Build Coastguard Worker 
3132*6236dae4SAndroid Build Coastguard Worker     per = del_per_transfer(per);
3133*6236dae4SAndroid Build Coastguard Worker   }
3134*6236dae4SAndroid Build Coastguard Worker 
3135*6236dae4SAndroid Build Coastguard Worker   /* Reset the global config variables */
3136*6236dae4SAndroid Build Coastguard Worker   global->noprogress = orig_noprogress;
3137*6236dae4SAndroid Build Coastguard Worker   global->isatty = orig_isatty;
3138*6236dae4SAndroid Build Coastguard Worker 
3139*6236dae4SAndroid Build Coastguard Worker 
3140*6236dae4SAndroid Build Coastguard Worker   return result;
3141*6236dae4SAndroid Build Coastguard Worker }
3142*6236dae4SAndroid Build Coastguard Worker 
operate(struct GlobalConfig * global,int argc,argv_item_t argv[])3143*6236dae4SAndroid Build Coastguard Worker CURLcode operate(struct GlobalConfig *global, int argc, argv_item_t argv[])
3144*6236dae4SAndroid Build Coastguard Worker {
3145*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
3146*6236dae4SAndroid Build Coastguard Worker   char *first_arg = argc > 1 ? curlx_convert_tchar_to_UTF8(argv[1]) : NULL;
3147*6236dae4SAndroid Build Coastguard Worker 
3148*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SETLOCALE
3149*6236dae4SAndroid Build Coastguard Worker   /* Override locale for number parsing (only) */
3150*6236dae4SAndroid Build Coastguard Worker   setlocale(LC_ALL, "");
3151*6236dae4SAndroid Build Coastguard Worker   setlocale(LC_NUMERIC, "C");
3152*6236dae4SAndroid Build Coastguard Worker #endif
3153*6236dae4SAndroid Build Coastguard Worker 
3154*6236dae4SAndroid Build Coastguard Worker   /* Parse .curlrc if necessary */
3155*6236dae4SAndroid Build Coastguard Worker   if((argc == 1) ||
3156*6236dae4SAndroid Build Coastguard Worker      (first_arg && strncmp(first_arg, "-q", 2) &&
3157*6236dae4SAndroid Build Coastguard Worker       strcmp(first_arg, "--disable"))) {
3158*6236dae4SAndroid Build Coastguard Worker     parseconfig(NULL, global); /* ignore possible failure */
3159*6236dae4SAndroid Build Coastguard Worker 
3160*6236dae4SAndroid Build Coastguard Worker     /* If we had no arguments then make sure a url was specified in .curlrc */
3161*6236dae4SAndroid Build Coastguard Worker     if((argc < 2) && (!global->first->url_list)) {
3162*6236dae4SAndroid Build Coastguard Worker       helpf(tool_stderr, NULL);
3163*6236dae4SAndroid Build Coastguard Worker       result = CURLE_FAILED_INIT;
3164*6236dae4SAndroid Build Coastguard Worker     }
3165*6236dae4SAndroid Build Coastguard Worker   }
3166*6236dae4SAndroid Build Coastguard Worker 
3167*6236dae4SAndroid Build Coastguard Worker   curlx_unicodefree(first_arg);
3168*6236dae4SAndroid Build Coastguard Worker 
3169*6236dae4SAndroid Build Coastguard Worker   if(!result) {
3170*6236dae4SAndroid Build Coastguard Worker     /* Parse the command line arguments */
3171*6236dae4SAndroid Build Coastguard Worker     ParameterError res = parse_args(global, argc, argv);
3172*6236dae4SAndroid Build Coastguard Worker     if(res) {
3173*6236dae4SAndroid Build Coastguard Worker       result = CURLE_OK;
3174*6236dae4SAndroid Build Coastguard Worker 
3175*6236dae4SAndroid Build Coastguard Worker       /* Check if we were asked for the help */
3176*6236dae4SAndroid Build Coastguard Worker       if(res == PARAM_HELP_REQUESTED)
3177*6236dae4SAndroid Build Coastguard Worker         tool_help(global->help_category);
3178*6236dae4SAndroid Build Coastguard Worker       /* Check if we were asked for the manual */
3179*6236dae4SAndroid Build Coastguard Worker       else if(res == PARAM_MANUAL_REQUESTED)
3180*6236dae4SAndroid Build Coastguard Worker         hugehelp();
3181*6236dae4SAndroid Build Coastguard Worker       /* Check if we were asked for the version information */
3182*6236dae4SAndroid Build Coastguard Worker       else if(res == PARAM_VERSION_INFO_REQUESTED)
3183*6236dae4SAndroid Build Coastguard Worker         tool_version_info();
3184*6236dae4SAndroid Build Coastguard Worker       /* Check if we were asked to list the SSL engines */
3185*6236dae4SAndroid Build Coastguard Worker       else if(res == PARAM_ENGINES_REQUESTED)
3186*6236dae4SAndroid Build Coastguard Worker         tool_list_engines();
3187*6236dae4SAndroid Build Coastguard Worker       /* Check if we were asked to dump the embedded CA bundle */
3188*6236dae4SAndroid Build Coastguard Worker       else if(res == PARAM_CA_EMBED_REQUESTED) {
3189*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_CA_EMBED
3190*6236dae4SAndroid Build Coastguard Worker         printf("%s", curl_ca_embed);
3191*6236dae4SAndroid Build Coastguard Worker #endif
3192*6236dae4SAndroid Build Coastguard Worker       }
3193*6236dae4SAndroid Build Coastguard Worker       else if(res == PARAM_LIBCURL_UNSUPPORTED_PROTOCOL)
3194*6236dae4SAndroid Build Coastguard Worker         result = CURLE_UNSUPPORTED_PROTOCOL;
3195*6236dae4SAndroid Build Coastguard Worker       else if(res == PARAM_READ_ERROR)
3196*6236dae4SAndroid Build Coastguard Worker         result = CURLE_READ_ERROR;
3197*6236dae4SAndroid Build Coastguard Worker       else
3198*6236dae4SAndroid Build Coastguard Worker         result = CURLE_FAILED_INIT;
3199*6236dae4SAndroid Build Coastguard Worker     }
3200*6236dae4SAndroid Build Coastguard Worker     else {
3201*6236dae4SAndroid Build Coastguard Worker       if(global->libcurl) {
3202*6236dae4SAndroid Build Coastguard Worker         /* Initialise the libcurl source output */
3203*6236dae4SAndroid Build Coastguard Worker         result = easysrc_init();
3204*6236dae4SAndroid Build Coastguard Worker       }
3205*6236dae4SAndroid Build Coastguard Worker 
3206*6236dae4SAndroid Build Coastguard Worker       /* Perform the main operations */
3207*6236dae4SAndroid Build Coastguard Worker       if(!result) {
3208*6236dae4SAndroid Build Coastguard Worker         size_t count = 0;
3209*6236dae4SAndroid Build Coastguard Worker         struct OperationConfig *operation = global->first;
3210*6236dae4SAndroid Build Coastguard Worker         CURLSH *share = curl_share_init();
3211*6236dae4SAndroid Build Coastguard Worker         if(!share) {
3212*6236dae4SAndroid Build Coastguard Worker           if(global->libcurl) {
3213*6236dae4SAndroid Build Coastguard Worker             /* Cleanup the libcurl source output */
3214*6236dae4SAndroid Build Coastguard Worker             easysrc_cleanup();
3215*6236dae4SAndroid Build Coastguard Worker           }
3216*6236dae4SAndroid Build Coastguard Worker           result = CURLE_OUT_OF_MEMORY;
3217*6236dae4SAndroid Build Coastguard Worker         }
3218*6236dae4SAndroid Build Coastguard Worker 
3219*6236dae4SAndroid Build Coastguard Worker         if(!result) {
3220*6236dae4SAndroid Build Coastguard Worker           curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
3221*6236dae4SAndroid Build Coastguard Worker           curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
3222*6236dae4SAndroid Build Coastguard Worker           curl_share_setopt(share, CURLSHOPT_SHARE,
3223*6236dae4SAndroid Build Coastguard Worker                             CURL_LOCK_DATA_SSL_SESSION);
3224*6236dae4SAndroid Build Coastguard Worker           curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
3225*6236dae4SAndroid Build Coastguard Worker           curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_PSL);
3226*6236dae4SAndroid Build Coastguard Worker           curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_HSTS);
3227*6236dae4SAndroid Build Coastguard Worker 
3228*6236dae4SAndroid Build Coastguard Worker           /* Get the required arguments for each operation */
3229*6236dae4SAndroid Build Coastguard Worker           do {
3230*6236dae4SAndroid Build Coastguard Worker             result = get_args(operation, count++);
3231*6236dae4SAndroid Build Coastguard Worker 
3232*6236dae4SAndroid Build Coastguard Worker             operation = operation->next;
3233*6236dae4SAndroid Build Coastguard Worker           } while(!result && operation);
3234*6236dae4SAndroid Build Coastguard Worker 
3235*6236dae4SAndroid Build Coastguard Worker           /* Set the current operation pointer */
3236*6236dae4SAndroid Build Coastguard Worker           global->current = global->first;
3237*6236dae4SAndroid Build Coastguard Worker 
3238*6236dae4SAndroid Build Coastguard Worker           /* now run! */
3239*6236dae4SAndroid Build Coastguard Worker           result = run_all_transfers(global, share, result);
3240*6236dae4SAndroid Build Coastguard Worker 
3241*6236dae4SAndroid Build Coastguard Worker           curl_share_cleanup(share);
3242*6236dae4SAndroid Build Coastguard Worker           if(global->libcurl) {
3243*6236dae4SAndroid Build Coastguard Worker             /* Cleanup the libcurl source output */
3244*6236dae4SAndroid Build Coastguard Worker             easysrc_cleanup();
3245*6236dae4SAndroid Build Coastguard Worker 
3246*6236dae4SAndroid Build Coastguard Worker             /* Dump the libcurl code if previously enabled */
3247*6236dae4SAndroid Build Coastguard Worker             dumpeasysrc(global);
3248*6236dae4SAndroid Build Coastguard Worker           }
3249*6236dae4SAndroid Build Coastguard Worker         }
3250*6236dae4SAndroid Build Coastguard Worker       }
3251*6236dae4SAndroid Build Coastguard Worker       else
3252*6236dae4SAndroid Build Coastguard Worker         errorf(global, "out of memory");
3253*6236dae4SAndroid Build Coastguard Worker     }
3254*6236dae4SAndroid Build Coastguard Worker   }
3255*6236dae4SAndroid Build Coastguard Worker 
3256*6236dae4SAndroid Build Coastguard Worker   varcleanup(global);
3257*6236dae4SAndroid Build Coastguard Worker 
3258*6236dae4SAndroid Build Coastguard Worker   return result;
3259*6236dae4SAndroid Build Coastguard Worker }
3260