1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel (at) 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 * HTTP PUT upload with authentiction using "any" method. libcurl picks the 24 * one the server supports/wants. 25 * </DESC> 26 */ 27 #include <stdio.h> 28 #include <fcntl.h> 29 #ifdef WIN32 30 # include <io.h> 31 #else 32 # ifdef __VMS 33 typedef int intptr_t; 34 # endif 35 # if !defined(_AIX) && !defined(__sgi) && !defined(__osf__) 36 # include <stdint.h> 37 # endif 38 # include <unistd.h> 39 #endif 40 #include <sys/types.h> 41 #include <sys/stat.h> 42 43 #ifdef _MSC_VER 44 # ifdef _WIN64 45 typedef __int64 intptr_t; 46 # else 47 typedef int intptr_t; 48 # endif 49 #endif 50 51 #include <curl/curl.h> 52 53 #if LIBCURL_VERSION_NUM < 0x070c03 54 #error "upgrade your libcurl to no less than 7.12.3" 55 #endif 56 57 #ifndef TRUE 58 #define TRUE 1 59 #endif 60 61 #if defined(_AIX) || defined(__sgi) || defined(__osf__) 62 #ifndef intptr_t 63 #define intptr_t long 64 #endif 65 #endif 66 67 /* 68 * This example shows a HTTP PUT operation with authentiction using "any" 69 * type. It PUTs a file given as a command line argument to the URL also given 70 * on the command line. 71 * 72 * Since libcurl 7.12.3, using "any" auth and POST/PUT requires a set ioctl 73 * function. 74 * 75 * This example also uses its own read callback. 76 */ 77 78 /* ioctl callback function */ 79 static curlioerr my_ioctl(CURL *handle, curliocmd cmd, void *userp) 80 { 81 int *fdp = (int *)userp; 82 int fd = *fdp; 83 84 (void)handle; /* not used in here */ 85 86 switch(cmd) { 87 case CURLIOCMD_RESTARTREAD: 88 /* mr libcurl kindly asks as to rewind the read data stream to start */ 89 if(-1 == lseek(fd, 0, SEEK_SET)) 90 /* couldn't rewind */ 91 return CURLIOE_FAILRESTART; 92 93 break; 94 95 default: /* ignore unknown commands */ 96 return CURLIOE_UNKNOWNCMD; 97 } 98 return CURLIOE_OK; /* success! */ 99 } 100 101 /* read callback function, fread() look alike */ 102 static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream) 103 { 104 ssize_t retcode; 105 curl_off_t nread; 106 107 int *fdp = (int *)stream; 108 int fd = *fdp; 109 110 retcode = read(fd, ptr, size * nmemb); 111 112 nread = (curl_off_t)retcode; 113 114 fprintf(stderr, "*** We read %" CURL_FORMAT_CURL_OFF_T 115 " bytes from file\n", nread); 116 117 return retcode; 118 } 119 120 int main(int argc, char **argv) 121 { 122 CURL *curl; 123 CURLcode res; 124 int hd; 125 struct stat file_info; 126 127 char *file; 128 char *url; 129 130 if(argc < 3) 131 return 1; 132 133 file= argv[1]; 134 url = argv[2]; 135 136 /* get the file size of the local file */ 137 hd = open(file, O_RDONLY); 138 fstat(hd, &file_info); 139 140 /* In windows, this will init the winsock stuff */ 141 curl_global_init(CURL_GLOBAL_ALL); 142 143 /* get a curl handle */ 144 curl = curl_easy_init(); 145 if(curl) { 146 /* we want to use our own read function */ 147 curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); 148 149 /* which file to upload */ 150 curl_easy_setopt(curl, CURLOPT_READDATA, (void *)&hd); 151 152 /* set the ioctl function */ 153 curl_easy_setopt(curl, CURLOPT_IOCTLFUNCTION, my_ioctl); 154 155 /* pass the file descriptor to the ioctl callback as well */ 156 curl_easy_setopt(curl, CURLOPT_IOCTLDATA, (void *)&hd); 157 158 /* enable "uploading" (which means PUT when doing HTTP) */ 159 curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); 160 161 /* specify target URL, and note that this URL should also include a file 162 name, not only a directory (as you can do with GTP uploads) */ 163 curl_easy_setopt(curl, CURLOPT_URL, url); 164 165 /* and give the size of the upload, this supports large file sizes 166 on systems that have general support for it */ 167 curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, 168 (curl_off_t)file_info.st_size); 169 170 /* tell libcurl we can use "any" auth, which lets the lib pick one, but it 171 also costs one extra round-trip and possibly sending of all the PUT 172 data twice!!! */ 173 curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_ANY); 174 175 /* set user name and password for the authentication */ 176 curl_easy_setopt(curl, CURLOPT_USERPWD, "user:password"); 177 178 /* Now run off and do what you've been told! */ 179 res = curl_easy_perform(curl); 180 /* Check for errors */ 181 if(res != CURLE_OK) 182 fprintf(stderr, "curl_easy_perform() failed: %s\n", 183 curl_easy_strerror(res)); 184 185 /* always cleanup */ 186 curl_easy_cleanup(curl); 187 } 188 close(hd); /* close the local file */ 189 190 curl_global_cleanup(); 191 return 0; 192 } 193