LCOV - code coverage report
Current view: top level - import - curl-util.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 0 216 0.0 %
Date: 2019-08-22 15:41:25 Functions: 0 13 0.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <fcntl.h>
       4             : 
       5             : #include "alloc-util.h"
       6             : #include "build.h"
       7             : #include "curl-util.h"
       8             : #include "fd-util.h"
       9             : #include "locale-util.h"
      10             : #include "string-util.h"
      11             : 
      12           0 : static void curl_glue_check_finished(CurlGlue *g) {
      13             :         CURLMsg *msg;
      14           0 :         int k = 0;
      15             : 
      16           0 :         assert(g);
      17             : 
      18           0 :         msg = curl_multi_info_read(g->curl, &k);
      19           0 :         if (!msg)
      20           0 :                 return;
      21             : 
      22           0 :         if (msg->msg != CURLMSG_DONE)
      23           0 :                 return;
      24             : 
      25           0 :         if (g->on_finished)
      26           0 :                 g->on_finished(g, msg->easy_handle, msg->data.result);
      27             : }
      28             : 
      29           0 : static int curl_glue_on_io(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
      30           0 :         CurlGlue *g = userdata;
      31           0 :         int action, k = 0;
      32             : 
      33           0 :         assert(s);
      34           0 :         assert(g);
      35             : 
      36           0 :         if (FLAGS_SET(revents, EPOLLIN | EPOLLOUT))
      37           0 :                 action = CURL_POLL_INOUT;
      38           0 :         else if (revents & EPOLLIN)
      39           0 :                 action = CURL_POLL_IN;
      40           0 :         else if (revents & EPOLLOUT)
      41           0 :                 action = CURL_POLL_OUT;
      42             :         else
      43           0 :                 action = 0;
      44             : 
      45           0 :         if (curl_multi_socket_action(g->curl, fd, action, &k) != CURLM_OK)
      46           0 :                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
      47             :                                        "Failed to propagate IO event.");
      48             : 
      49           0 :         curl_glue_check_finished(g);
      50           0 :         return 0;
      51             : }
      52             : 
      53           0 : static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, void *userdata, void *socketp) {
      54           0 :         sd_event_source *io = socketp;
      55           0 :         CurlGlue *g = userdata;
      56           0 :         uint32_t events = 0;
      57             :         int r;
      58             : 
      59           0 :         assert(curl);
      60           0 :         assert(g);
      61             : 
      62           0 :         if (action == CURL_POLL_REMOVE) {
      63           0 :                 if (io) {
      64           0 :                         sd_event_source_disable_unref(io);
      65             : 
      66           0 :                         hashmap_remove(g->ios, FD_TO_PTR(s));
      67             :                 }
      68             : 
      69           0 :                 return 0;
      70             :         }
      71             : 
      72           0 :         r = hashmap_ensure_allocated(&g->ios, &trivial_hash_ops);
      73           0 :         if (r < 0) {
      74           0 :                 log_oom();
      75           0 :                 return -1;
      76             :         }
      77             : 
      78           0 :         if (action == CURL_POLL_IN)
      79           0 :                 events = EPOLLIN;
      80           0 :         else if (action == CURL_POLL_OUT)
      81           0 :                 events = EPOLLOUT;
      82           0 :         else if (action == CURL_POLL_INOUT)
      83           0 :                 events = EPOLLIN|EPOLLOUT;
      84             : 
      85           0 :         if (io) {
      86           0 :                 if (sd_event_source_set_io_events(io, events) < 0)
      87           0 :                         return -1;
      88             : 
      89           0 :                 if (sd_event_source_set_enabled(io, SD_EVENT_ON) < 0)
      90           0 :                         return -1;
      91             :         } else {
      92           0 :                 if (sd_event_add_io(g->event, &io, s, events, curl_glue_on_io, g) < 0)
      93           0 :                         return -1;
      94             : 
      95           0 :                 if (curl_multi_assign(g->curl, s, io) != CURLM_OK)
      96           0 :                         return -1;
      97             : 
      98           0 :                 (void) sd_event_source_set_description(io, "curl-io");
      99             : 
     100           0 :                 r = hashmap_put(g->ios, FD_TO_PTR(s), io);
     101           0 :                 if (r < 0) {
     102           0 :                         log_oom();
     103           0 :                         sd_event_source_unref(io);
     104           0 :                         return -1;
     105             :                 }
     106             :         }
     107             : 
     108           0 :         return 0;
     109             : }
     110             : 
     111           0 : static int curl_glue_on_timer(sd_event_source *s, uint64_t usec, void *userdata) {
     112           0 :         CurlGlue *g = userdata;
     113           0 :         int k = 0;
     114             : 
     115           0 :         assert(s);
     116           0 :         assert(g);
     117             : 
     118           0 :         if (curl_multi_socket_action(g->curl, CURL_SOCKET_TIMEOUT, 0, &k) != CURLM_OK)
     119           0 :                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
     120             :                                        "Failed to propagate timeout.");
     121             : 
     122           0 :         curl_glue_check_finished(g);
     123           0 :         return 0;
     124             : }
     125             : 
     126           0 : static int curl_glue_timer_callback(CURLM *curl, long timeout_ms, void *userdata) {
     127           0 :         CurlGlue *g = userdata;
     128             :         usec_t usec;
     129             : 
     130           0 :         assert(curl);
     131           0 :         assert(g);
     132             : 
     133           0 :         if (timeout_ms < 0) {
     134           0 :                 if (g->timer) {
     135           0 :                         if (sd_event_source_set_enabled(g->timer, SD_EVENT_OFF) < 0)
     136           0 :                                 return -1;
     137             :                 }
     138             : 
     139           0 :                 return 0;
     140             :         }
     141             : 
     142           0 :         usec = now(clock_boottime_or_monotonic()) + (usec_t) timeout_ms * USEC_PER_MSEC + USEC_PER_MSEC - 1;
     143             : 
     144           0 :         if (g->timer) {
     145           0 :                 if (sd_event_source_set_time(g->timer, usec) < 0)
     146           0 :                         return -1;
     147             : 
     148           0 :                 if (sd_event_source_set_enabled(g->timer, SD_EVENT_ONESHOT) < 0)
     149           0 :                         return -1;
     150             :         } else {
     151           0 :                 if (sd_event_add_time(g->event, &g->timer, clock_boottime_or_monotonic(), usec, 0, curl_glue_on_timer, g) < 0)
     152           0 :                         return -1;
     153             : 
     154           0 :                 (void) sd_event_source_set_description(g->timer, "curl-timer");
     155             :         }
     156             : 
     157           0 :         return 0;
     158             : }
     159             : 
     160           0 : CurlGlue *curl_glue_unref(CurlGlue *g) {
     161             :         sd_event_source *io;
     162             : 
     163           0 :         if (!g)
     164           0 :                 return NULL;
     165             : 
     166           0 :         if (g->curl)
     167           0 :                 curl_multi_cleanup(g->curl);
     168             : 
     169           0 :         while ((io = hashmap_steal_first(g->ios))) {
     170           0 :                 sd_event_source_unref(io);
     171             :         }
     172             : 
     173           0 :         hashmap_free(g->ios);
     174             : 
     175           0 :         sd_event_source_unref(g->timer);
     176           0 :         sd_event_unref(g->event);
     177           0 :         return mfree(g);
     178             : }
     179             : 
     180           0 : int curl_glue_new(CurlGlue **glue, sd_event *event) {
     181           0 :         _cleanup_(curl_glue_unrefp) CurlGlue *g = NULL;
     182           0 :         _cleanup_(curl_multi_cleanupp) CURL *c = NULL;
     183           0 :         _cleanup_(sd_event_unrefp) sd_event *e = NULL;
     184             :         int r;
     185             : 
     186           0 :         if (event)
     187           0 :                 e = sd_event_ref(event);
     188             :         else {
     189           0 :                 r = sd_event_default(&e);
     190           0 :                 if (r < 0)
     191           0 :                         return r;
     192             :         }
     193             : 
     194           0 :         c = curl_multi_init();
     195           0 :         if (!c)
     196           0 :                 return -ENOMEM;
     197             : 
     198           0 :         g = new(CurlGlue, 1);
     199           0 :         if (!g)
     200           0 :                 return -ENOMEM;
     201             : 
     202           0 :         *g = (CurlGlue) {
     203           0 :                 .event = TAKE_PTR(e),
     204           0 :                 .curl = TAKE_PTR(c),
     205             :         };
     206             : 
     207           0 :         if (curl_multi_setopt(g->curl, CURLMOPT_SOCKETDATA, g) != CURLM_OK)
     208           0 :                 return -EINVAL;
     209             : 
     210           0 :         if (curl_multi_setopt(g->curl, CURLMOPT_SOCKETFUNCTION, curl_glue_socket_callback) != CURLM_OK)
     211           0 :                 return -EINVAL;
     212             : 
     213           0 :         if (curl_multi_setopt(g->curl, CURLMOPT_TIMERDATA, g) != CURLM_OK)
     214           0 :                 return -EINVAL;
     215             : 
     216           0 :         if (curl_multi_setopt(g->curl, CURLMOPT_TIMERFUNCTION, curl_glue_timer_callback) != CURLM_OK)
     217           0 :                 return -EINVAL;
     218             : 
     219           0 :         *glue = TAKE_PTR(g);
     220             : 
     221           0 :         return 0;
     222             : }
     223             : 
     224           0 : int curl_glue_make(CURL **ret, const char *url, void *userdata) {
     225           0 :         _cleanup_(curl_easy_cleanupp) CURL *c = NULL;
     226             :         const char *useragent;
     227             : 
     228           0 :         assert(ret);
     229           0 :         assert(url);
     230             : 
     231           0 :         c = curl_easy_init();
     232           0 :         if (!c)
     233           0 :                 return -ENOMEM;
     234             : 
     235             :         /* curl_easy_setopt(c, CURLOPT_VERBOSE, 1L); */
     236             : 
     237           0 :         if (curl_easy_setopt(c, CURLOPT_URL, url) != CURLE_OK)
     238           0 :                 return -EIO;
     239             : 
     240           0 :         if (curl_easy_setopt(c, CURLOPT_PRIVATE, userdata) != CURLE_OK)
     241           0 :                 return -EIO;
     242             : 
     243           0 :         useragent = strjoina(program_invocation_short_name, "/" GIT_VERSION);
     244           0 :         if (curl_easy_setopt(c, CURLOPT_USERAGENT, useragent) != CURLE_OK)
     245           0 :                 return -EIO;
     246             : 
     247           0 :         if (curl_easy_setopt(c, CURLOPT_FOLLOWLOCATION, 1L) != CURLE_OK)
     248           0 :                 return -EIO;
     249             : 
     250           0 :         *ret = TAKE_PTR(c);
     251           0 :         return 0;
     252             : }
     253             : 
     254           0 : int curl_glue_add(CurlGlue *g, CURL *c) {
     255           0 :         assert(g);
     256           0 :         assert(c);
     257             : 
     258           0 :         if (curl_multi_add_handle(g->curl, c) != CURLM_OK)
     259           0 :                 return -EIO;
     260             : 
     261           0 :         return 0;
     262             : }
     263             : 
     264           0 : void curl_glue_remove_and_free(CurlGlue *g, CURL *c) {
     265           0 :         assert(g);
     266             : 
     267           0 :         if (!c)
     268           0 :                 return;
     269             : 
     270           0 :         if (g->curl)
     271           0 :                 curl_multi_remove_handle(g->curl, c);
     272             : 
     273           0 :         curl_easy_cleanup(c);
     274             : }
     275             : 
     276           0 : struct curl_slist *curl_slist_new(const char *first, ...) {
     277             :         struct curl_slist *l;
     278             :         va_list ap;
     279             : 
     280           0 :         if (!first)
     281           0 :                 return NULL;
     282             : 
     283           0 :         l = curl_slist_append(NULL, first);
     284           0 :         if (!l)
     285           0 :                 return NULL;
     286             : 
     287           0 :         va_start(ap, first);
     288             : 
     289           0 :         for (;;) {
     290             :                 struct curl_slist *n;
     291             :                 const char *i;
     292             : 
     293           0 :                 i = va_arg(ap, const char*);
     294           0 :                 if (!i)
     295           0 :                         break;
     296             : 
     297           0 :                 n = curl_slist_append(l, i);
     298           0 :                 if (!n) {
     299           0 :                         va_end(ap);
     300           0 :                         curl_slist_free_all(l);
     301           0 :                         return NULL;
     302             :                 }
     303             : 
     304           0 :                 l = n;
     305             :         }
     306             : 
     307           0 :         va_end(ap);
     308           0 :         return l;
     309             : }
     310             : 
     311           0 : int curl_header_strdup(const void *contents, size_t sz, const char *field, char **value) {
     312             :         const char *p;
     313             :         char *s;
     314             : 
     315           0 :         p = memory_startswith_no_case(contents, sz, field);
     316           0 :         if (!p)
     317           0 :                 return 0;
     318             : 
     319           0 :         sz -= p - (const char*) contents;
     320             : 
     321           0 :         if (memchr(p, 0, sz))
     322           0 :                 return 0;
     323             : 
     324             :         /* Skip over preceding whitespace */
     325           0 :         while (sz > 0 && strchr(WHITESPACE, p[0])) {
     326           0 :                 p++;
     327           0 :                 sz--;
     328             :         }
     329             : 
     330             :         /* Truncate trailing whitespace */
     331           0 :         while (sz > 0 && strchr(WHITESPACE, p[sz-1]))
     332           0 :                 sz--;
     333             : 
     334           0 :         s = strndup(p, sz);
     335           0 :         if (!s)
     336           0 :                 return -ENOMEM;
     337             : 
     338           0 :         *value = s;
     339           0 :         return 1;
     340             : }
     341             : 
     342           0 : int curl_parse_http_time(const char *t, usec_t *ret) {
     343           0 :         _cleanup_(freelocalep) locale_t loc = (locale_t) 0;
     344             :         const char *e;
     345             :         struct tm tm;
     346             :         time_t v;
     347             : 
     348           0 :         assert(t);
     349           0 :         assert(ret);
     350             : 
     351           0 :         loc = newlocale(LC_TIME_MASK, "C", (locale_t) 0);
     352           0 :         if (loc == (locale_t) 0)
     353           0 :                 return -errno;
     354             : 
     355             :         /* RFC822 */
     356           0 :         e = strptime_l(t, "%a, %d %b %Y %H:%M:%S %Z", &tm, loc);
     357           0 :         if (!e || *e != 0)
     358             :                 /* RFC 850 */
     359           0 :                 e = strptime_l(t, "%A, %d-%b-%y %H:%M:%S %Z", &tm, loc);
     360           0 :         if (!e || *e != 0)
     361             :                 /* ANSI C */
     362           0 :                 e = strptime_l(t, "%a %b %d %H:%M:%S %Y", &tm, loc);
     363           0 :         if (!e || *e != 0)
     364           0 :                 return -EINVAL;
     365             : 
     366           0 :         v = timegm(&tm);
     367           0 :         if (v == (time_t) -1)
     368           0 :                 return -EINVAL;
     369             : 
     370           0 :         *ret = (usec_t) v * USEC_PER_SEC;
     371           0 :         return 0;
     372             : }

Generated by: LCOV version 1.14