LCOV - code coverage report
Current view: top level - import - curl-util.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 0 216 0.0 %
Date: 2019-08-23 13:36:53 Functions: 0 13 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 178 0.0 %

           Branch data     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