ftpuploadresume.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 /* <DESC>
23  * Upload to FTP, resuming failed transfers.
24  * </DESC>
25  */
26 
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <curl/curl.h>
30 
31 /* parse headers for Content-Length */
32 static size_t getcontentlengthfunc(void *ptr, size_t size, size_t nmemb,
33  void *stream)
34 {
35  int r;
36  long len = 0;
37 
38  r = sscanf(ptr, "Content-Length: %ld\n", &len);
39  if(r)
40  *((long *) stream) = len;
41 
42  return size * nmemb;
43 }
44 
45 /* discard downloaded data */
46 static size_t discardfunc(void *ptr, size_t size, size_t nmemb, void *stream)
47 {
48  (void)ptr;
49  (void)stream;
50  return size * nmemb;
51 }
52 
53 /* read data to upload */
54 static size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream)
55 {
56  FILE *f = stream;
57  size_t n;
58 
59  if(ferror(f))
60  return CURL_READFUNC_ABORT;
61 
62  n = fread(ptr, size, nmemb, f) * size;
63 
64  return n;
65 }
66 
67 
68 static int upload(CURL *curlhandle, const char *remotepath,
69  const char *localpath, long timeout, long tries)
70 {
71  FILE *f;
72  long uploaded_len = 0;
74  int c;
75 
76  f = fopen(localpath, "rb");
77  if(!f) {
78  perror(NULL);
79  return 0;
80  }
81 
82  curl_easy_setopt(curlhandle, CURLOPT_UPLOAD, 1L);
83 
84  curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath);
85 
86  if(timeout)
87  curl_easy_setopt(curlhandle, CURLOPT_FTP_RESPONSE_TIMEOUT, timeout);
88 
89  curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, getcontentlengthfunc);
90  curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &uploaded_len);
91 
92  curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, discardfunc);
93 
94  curl_easy_setopt(curlhandle, CURLOPT_READFUNCTION, readfunc);
95  curl_easy_setopt(curlhandle, CURLOPT_READDATA, f);
96 
97  /* disable passive mode */
98  curl_easy_setopt(curlhandle, CURLOPT_FTPPORT, "-");
99  curl_easy_setopt(curlhandle, CURLOPT_FTP_CREATE_MISSING_DIRS, 1L);
100 
101  curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L);
102 
103  for(c = 0; (r != CURLE_OK) && (c < tries); c++) {
104  /* are we resuming? */
105  if(c) { /* yes */
106  /* determine the length of the file already written */
107 
108  /*
109  * With NOBODY and NOHEADER, libcurl will issue a SIZE
110  * command, but the only way to retrieve the result is
111  * to parse the returned Content-Length header. Thus,
112  * getcontentlengthfunc(). We need discardfunc() above
113  * because HEADER will dump the headers to stdout
114  * without it.
115  */
116  curl_easy_setopt(curlhandle, CURLOPT_NOBODY, 1L);
117  curl_easy_setopt(curlhandle, CURLOPT_HEADER, 1L);
118 
119  r = curl_easy_perform(curlhandle);
120  if(r != CURLE_OK)
121  continue;
122 
123  curl_easy_setopt(curlhandle, CURLOPT_NOBODY, 0L);
124  curl_easy_setopt(curlhandle, CURLOPT_HEADER, 0L);
125 
126  fseek(f, uploaded_len, SEEK_SET);
127 
128  curl_easy_setopt(curlhandle, CURLOPT_APPEND, 1L);
129  }
130  else { /* no */
131  curl_easy_setopt(curlhandle, CURLOPT_APPEND, 0L);
132  }
133 
134  r = curl_easy_perform(curlhandle);
135  }
136 
137  fclose(f);
138 
139  if(r == CURLE_OK)
140  return 1;
141  else {
142  fprintf(stderr, "%s\n", curl_easy_strerror(r));
143  return 0;
144  }
145 }
146 
147 int main(void)
148 {
149  CURL *curlhandle = NULL;
150 
152  curlhandle = curl_easy_init();
153 
154  upload(curlhandle, "ftp://user:pass@example.com/path/file", "C:\\file",
155  0, 3);
156 
157  curl_easy_cleanup(curlhandle);
159 
160  return 0;
161 }
f
uv_timer_t timeout
Definition: multi-uv.c:42
UNITTEST_START char * ptr
Definition: unit1330.c:38
CURLcode
Definition: curl.h:454
static size_t discardfunc(void *ptr, size_t size, size_t nmemb, void *stream)
static size_t getcontentlengthfunc(void *ptr, size_t size, size_t nmemb, void *stream)
#define curl_easy_setopt(handle, option, value)
Definition: typecheck-gcc.h:41
size_t len
Definition: curl_sasl.c:55
static int upload(CURL *curlhandle, const char *remotepath, const char *localpath, long timeout, long tries)
int main(void)
CURL_EXTERN CURL * curl_easy_init(void)
Definition: easy.c:343
CURL_EXTERN void curl_easy_cleanup(CURL *curl)
Definition: curl.h:455
#define CURL_READFUNC_ABORT
Definition: curl.h:350
size_t fread(void *, size_t, size_t, FILE *)
CURL_EXTERN CURLcode curl_global_init(long flags)
curl_global_init() globally initializes curl given a bitwise set of the different features of what to...
Definition: easy.c:271
void CURL
Definition: curl.h:102
size_t size
Definition: unit1302.c:52
#define fprintf
Definition: curl_printf.h:41
CURL_EXTERN void curl_global_cleanup(void)
curl_global_cleanup() globally cleanups curl, uses the value of "init_flags" to determine what needs ...
Definition: easy.c:312
#define CURL_GLOBAL_ALL
Definition: curl.h:2519
static size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream)
CURL_EXTERN const char * curl_easy_strerror(CURLcode)
Definition: strerror.c:57
CURL_EXTERN CURLcode curl_easy_perform(CURL *curl)


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:09