Home | History | Annotate | Download | only in examples
      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