LCOV - code coverage report
Current view: top level - lib/util - tevent_req_profile.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 0 243 0.0 %
Date: 2024-06-13 04:01:37 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Unix SMB/CIFS implementation.
       3             :  *
       4             :  * Helpers around tevent_req_profile
       5             :  *
       6             :  * Copyright (C) Volker Lendecke 2018
       7             :  *
       8             :  *   ** NOTE! The following LGPL license applies to the tevent
       9             :  *   ** library. This does NOT imply that all of Samba is released
      10             :  *   ** under the LGPL
      11             :  *
      12             :  * This library is free software; you can redistribute it and/or
      13             :  * modify it under the terms of the GNU Lesser General Public
      14             :  * License as published by the Free Software Foundation; either
      15             :  * version 3 of the License, or (at your option) any later version.
      16             :  *
      17             :  * This library is distributed in the hope that it will be useful,
      18             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      19             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      20             :  * Lesser General Public License for more details.
      21             :  *
      22             :  * You should have received a copy of the GNU Lesser General Public
      23             :  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
      24             :  */
      25             : 
      26             : #include "replace.h"
      27             : #include <tevent.h>
      28             : #include "lib/util/tevent_req_profile.h"
      29             : #include "lib/util/time_basic.h"
      30             : #include "lib/util/memory.h"
      31             : 
      32           0 : static bool tevent_req_profile_string_internal(
      33             :         const struct tevent_req_profile *profile,
      34             :         unsigned indent,
      35             :         unsigned max_indent,
      36             :         char **string)
      37             : {
      38             :         struct timeval start, stop, diff;
      39             :         struct timeval_buf start_buf, stop_buf;
      40           0 :         const char *req_name = NULL;
      41           0 :         const char *start_location = NULL;
      42           0 :         const char *stop_location = NULL;
      43             :         pid_t pid;
      44             :         enum tevent_req_state state;
      45           0 :         const char *state_buf = NULL;
      46             :         uint64_t user_error;
      47           0 :         const struct tevent_req_profile *sub = NULL;
      48             :         char *result;
      49             : 
      50           0 :         tevent_req_profile_get_name(profile, &req_name);
      51             : 
      52           0 :         tevent_req_profile_get_start(profile, &start_location, &start);
      53           0 :         timeval_str_buf(&start, false, true, &start_buf);
      54             : 
      55           0 :         tevent_req_profile_get_stop(profile, &stop_location, &stop);
      56           0 :         timeval_str_buf(&stop, false, true, &stop_buf);
      57             : 
      58           0 :         diff = tevent_timeval_until(&start, &stop);
      59             : 
      60           0 :         tevent_req_profile_get_status(profile, &pid, &state, &user_error);
      61             : 
      62           0 :         switch(state) {
      63           0 :         case TEVENT_REQ_INIT:
      64           0 :                 state_buf = "TEVENT_REQ_INIT";
      65           0 :                 break;
      66           0 :         case TEVENT_REQ_IN_PROGRESS:
      67           0 :                 state_buf = "TEVENT_REQ_IN_PROGRESS";
      68           0 :                 break;
      69           0 :         case TEVENT_REQ_DONE:
      70           0 :                 state_buf = "TEVENT_REQ_DONE";
      71           0 :                 break;
      72           0 :         case TEVENT_REQ_USER_ERROR:
      73           0 :                 state_buf = "TEVENT_REQ_USER_ERROR";
      74           0 :                 break;
      75           0 :         case TEVENT_REQ_TIMED_OUT:
      76           0 :                 state_buf = "TEVENT_REQ_TIMED_OUT";
      77           0 :                 break;
      78           0 :         case TEVENT_REQ_NO_MEMORY:
      79           0 :                 state_buf = "TEVENT_REQ_NO_MEMORY";
      80           0 :                 break;
      81           0 :         case TEVENT_REQ_RECEIVED:
      82           0 :                 state_buf = "TEVENT_REQ_RECEIVED";
      83           0 :                 break;
      84           0 :         default:
      85           0 :                 state_buf = "unknown";
      86           0 :                 break;
      87             :         }
      88             : 
      89           0 :         result = talloc_asprintf_append_buffer(
      90             :                 *string,
      91             :                 "%*s[%s] %s [%s] %s [%s] [%ju.%.6ju] -> %s (%d %"PRIu64"))\n",
      92             :                 indent,
      93             :                 "",
      94             :                 req_name,
      95             :                 start_location,
      96             :                 start_buf.buf,
      97             :                 stop_location,
      98             :                 stop_buf.buf,
      99           0 :                 (uintmax_t)diff.tv_sec,
     100           0 :                 (uintmax_t)diff.tv_usec,
     101             :                 state_buf,
     102             :                 (int)state,
     103             :                 user_error);
     104           0 :         if (result == NULL) {
     105           0 :                 return false;
     106             :         }
     107           0 :         *string = result;
     108             : 
     109           0 :         indent += 1;
     110             : 
     111           0 :         if (indent >= max_indent) {
     112           0 :                 return true;
     113             :         }
     114             : 
     115           0 :         for (sub = tevent_req_profile_get_subprofiles(profile);
     116           0 :              sub != NULL;
     117           0 :              sub = tevent_req_profile_next(sub)) {
     118             :                 bool ret;
     119             : 
     120           0 :                 ret = tevent_req_profile_string_internal(
     121             :                         sub,
     122             :                         indent,
     123             :                         max_indent,
     124             :                         string);
     125           0 :                 if (!ret) {
     126           0 :                         return false;
     127             :                 }
     128             :         }
     129             : 
     130           0 :         return true;
     131             : }
     132             : 
     133           0 : char *tevent_req_profile_string(TALLOC_CTX *mem_ctx,
     134             :                                 const struct tevent_req_profile *profile,
     135             :                                 unsigned indent,
     136             :                                 unsigned max_indent)
     137             : {
     138             :         char *result;
     139             :         bool ret;
     140             : 
     141           0 :         result = talloc_strdup(mem_ctx, "");
     142           0 :         if (result == NULL) {
     143           0 :                 return NULL;
     144             :         }
     145             : 
     146           0 :         ret = tevent_req_profile_string_internal(
     147             :                 profile,
     148             :                 indent,
     149             :                 max_indent,
     150             :                 &result);
     151           0 :         if (!ret) {
     152           0 :                 TALLOC_FREE(result);
     153           0 :                 return NULL;
     154             :         }
     155             : 
     156           0 :         return result;
     157             : }
     158             : 
     159           0 : static ssize_t tevent_req_profile_pack_one(
     160             :         const struct tevent_req_profile *profile,
     161             :         uint8_t *buf,
     162             :         size_t buflen)
     163             : {
     164           0 :         const char *req_name = NULL;
     165           0 :         const char *start_location = NULL;
     166           0 :         const char *stop_location = NULL;
     167             :         struct timeval start_time, stop_time;
     168             :         pid_t pid;
     169             :         enum tevent_req_state state;
     170             :         uint64_t user_error;
     171             :         size_t pack_len, len;
     172             :         int ret;
     173             : 
     174           0 :         tevent_req_profile_get_name(profile, &req_name);
     175           0 :         tevent_req_profile_get_start(profile, &start_location, &start_time);
     176           0 :         tevent_req_profile_get_stop(profile, &stop_location, &stop_time);
     177           0 :         tevent_req_profile_get_status(profile, &pid, &state, &user_error);
     178             : 
     179           0 :         len = strlen(req_name)+1;
     180           0 :         if (buflen >= len) {
     181           0 :                 memcpy(buf, req_name, len);
     182           0 :                 buf += len;
     183           0 :                 buflen -= len;
     184             :         }
     185             : 
     186           0 :         pack_len = len;
     187             : 
     188           0 :         len = strlen(start_location)+1;
     189           0 :         pack_len += len;
     190           0 :         if (pack_len < len) {
     191           0 :                 return -1;      /* overflow */
     192             :         }
     193             : 
     194           0 :         if (buflen >= len) {
     195           0 :                 memcpy(buf, start_location, len);
     196           0 :                 buf += len;
     197           0 :                 buflen -= len;
     198             :         }
     199             : 
     200           0 :         len = strlen(stop_location)+1;
     201           0 :         pack_len += len;
     202           0 :         if (pack_len < len) {
     203           0 :                 return -1;      /* overflow */
     204             :         }
     205             : 
     206           0 :         if (buflen >= len) {
     207           0 :                 memcpy(buf, stop_location, len);
     208           0 :                 buf += len;
     209           0 :                 buflen -= len;
     210             :         }
     211             : 
     212           0 :         ret = snprintf((char *)buf,
     213             :                        buflen,
     214             :                        "%ju %ju %ju %ju %d %d %"PRIu64"",
     215           0 :                        (uintmax_t)start_time.tv_sec,
     216           0 :                        (uintmax_t)start_time.tv_usec,
     217           0 :                        (uintmax_t)stop_time.tv_sec,
     218           0 :                        (uintmax_t)stop_time.tv_usec,
     219             :                        (int)pid,
     220             :                        (int)state,
     221             :                        user_error);
     222           0 :         if (ret < 0) {
     223           0 :                 return -1;
     224             :         }
     225             : 
     226             :         /*
     227             :          * Take care of the trailing 0. No overflow check, this would
     228             :          * be a VERY small number of bits for "int".
     229             :          */
     230           0 :         ret += 1;
     231             : 
     232           0 :         pack_len += ret;
     233             : 
     234           0 :         return pack_len;
     235             : }
     236             : 
     237           0 : ssize_t tevent_req_profile_pack(
     238             :         const struct tevent_req_profile *profile,
     239             :         uint8_t *buf,
     240             :         size_t buflen)
     241             : {
     242           0 :         const struct tevent_req_profile *sub = NULL;
     243             :         size_t num_sub;
     244             :         ssize_t pack_len, profile_len;
     245             :         int ret;
     246             : 
     247           0 :         num_sub = 0;
     248           0 :         pack_len = 0;
     249             : 
     250           0 :         for (sub = tevent_req_profile_get_subprofiles(profile);
     251           0 :              sub != NULL;
     252           0 :              sub = tevent_req_profile_next(sub)) {
     253           0 :                 num_sub += 1;
     254             :         }
     255             : 
     256           0 :         ret = snprintf((char *)buf, buflen, "%zu ", num_sub);
     257           0 :         if (ret < 0) {
     258           0 :                 return -1;
     259             :         }
     260             : 
     261           0 :         if (buflen > (size_t)ret) {
     262           0 :                 buf += ret;
     263           0 :                 buflen -= ret;
     264             :         }
     265             : 
     266           0 :         pack_len = ret;
     267             : 
     268           0 :         profile_len = tevent_req_profile_pack_one(profile, buf, buflen);
     269           0 :         if (profile_len == -1) {
     270           0 :                 return -1;
     271             :         }
     272             : 
     273           0 :         if (buflen >= (size_t)profile_len) {
     274           0 :                 buf += profile_len;
     275           0 :                 buflen -= profile_len;
     276             :         }
     277             : 
     278           0 :         pack_len += profile_len;
     279           0 :         if (pack_len < profile_len) {
     280           0 :                 return -1;      /* overflow */
     281             :         }
     282             : 
     283           0 :         for (sub = tevent_req_profile_get_subprofiles(profile);
     284           0 :              sub != NULL;
     285           0 :              sub = tevent_req_profile_next(sub)) {
     286             : 
     287           0 :                 profile_len = tevent_req_profile_pack(sub, buf, buflen);
     288           0 :                 if (profile_len == -1) {
     289           0 :                         return -1;
     290             :                 }
     291             : 
     292           0 :                 if (buflen >= (size_t)profile_len) {
     293           0 :                         buf += profile_len;
     294           0 :                         buflen -= profile_len;
     295             :                 }
     296             : 
     297           0 :                 pack_len += profile_len;
     298           0 :                 if (pack_len < profile_len) {
     299           0 :                         return -1;      /* overflow */
     300             :                 }
     301             :         }
     302             : 
     303           0 :         return pack_len;
     304             : }
     305             : 
     306           0 : static bool parse_uintmax(const char *buf,
     307             :                           char delimiter,
     308             :                           uintmax_t *presult,
     309             :                           char **p_endptr)
     310             : {
     311             :         uintmax_t result;
     312             :         char *endptr;
     313             : 
     314           0 :         result = strtoumax(buf, &endptr, 10);
     315           0 :         if ((result == UINTMAX_MAX) && (errno == ERANGE)) {
     316           0 :                 return false;
     317             :         }
     318           0 :         if (*endptr != delimiter) {
     319           0 :                 return false;
     320             :         }
     321             : 
     322           0 :         *presult = result;
     323           0 :         *p_endptr = endptr+1;
     324             : 
     325           0 :         return true;
     326             : }
     327             : 
     328           0 : static ssize_t tevent_req_profile_unpack_one(
     329             :         const uint8_t *buf,
     330             :         size_t buflen,
     331             :         struct tevent_req_profile *profile)
     332             : {
     333           0 :         const char *orig_buf = (const char *)buf;
     334           0 :         const char *req_name = NULL;
     335           0 :         const char *start_location = NULL;
     336           0 :         const char *stop_location = NULL;
     337             :         uintmax_t start_sec, start_usec, stop_sec, stop_usec, pid, state;
     338             :         uintmax_t user_error;
     339           0 :         char *next = NULL;
     340             :         size_t len;
     341             :         bool ok;
     342             : 
     343           0 :         if (buflen == 0) {
     344           0 :                 return -1;
     345             :         }
     346           0 :         if (buf[buflen-1] != '\0') {
     347           0 :                 return -1;
     348             :         }
     349             : 
     350           0 :         req_name = (const char *)buf;
     351           0 :         len = strlen(req_name)+1;
     352             : 
     353           0 :         buf += len;
     354           0 :         buflen -= len;
     355           0 :         if (buflen == 0) {
     356           0 :                 return -1;
     357             :         }
     358             : 
     359           0 :         start_location = (const char *)buf;
     360           0 :         len = strlen(start_location)+1;
     361             : 
     362           0 :         buf += len;
     363           0 :         buflen -= len;
     364           0 :         if (buflen == 0) {
     365           0 :                 return -1;
     366             :         }
     367             : 
     368           0 :         stop_location = (const char *)buf;
     369           0 :         len = strlen(stop_location)+1;
     370             : 
     371           0 :         buf += len;
     372           0 :         buflen -= len;
     373           0 :         if (buflen == 0) {
     374           0 :                 return -1;
     375             :         }
     376             : 
     377           0 :         ok = parse_uintmax((const char *)buf, ' ', &start_sec, &next);
     378           0 :         if (!ok) {
     379           0 :                 return -1;
     380             :         }
     381             : 
     382           0 :         ok = parse_uintmax(next, ' ', &start_usec, &next);
     383           0 :         if (!ok) {
     384           0 :                 return -1;
     385             :         }
     386             : 
     387           0 :         ok = parse_uintmax(next, ' ', &stop_sec, &next);
     388           0 :         if (!ok) {
     389           0 :                 return -1;
     390             :         }
     391             : 
     392           0 :         ok = parse_uintmax(next, ' ', &stop_usec, &next);
     393           0 :         if (!ok) {
     394           0 :                 return -1;
     395             :         }
     396             : 
     397           0 :         ok = parse_uintmax(next, ' ', &pid, &next);
     398           0 :         if (!ok) {
     399           0 :                 return -1;
     400             :         }
     401             : 
     402           0 :         ok = parse_uintmax(next, ' ', &state, &next);
     403           0 :         if (!ok) {
     404           0 :                 return -1;
     405             :         }
     406             : 
     407           0 :         ok = parse_uintmax(next, '\0', &user_error, &next);
     408           0 :         if (!ok) {
     409           0 :                 return -1;
     410             :         }
     411             : 
     412           0 :         ok = tevent_req_profile_set_name(profile, req_name);
     413           0 :         if (!ok) {
     414           0 :                 return -1;
     415             :         }
     416             : 
     417           0 :         ok = tevent_req_profile_set_start(
     418             :                 profile,
     419             :                 start_location,
     420           0 :                 (struct timeval){ .tv_sec=start_sec, .tv_usec=start_usec });
     421           0 :         if (!ok) {
     422           0 :                 return -1;
     423             :         }
     424             : 
     425           0 :         ok = tevent_req_profile_set_stop(
     426             :                 profile,
     427             :                 stop_location,
     428           0 :                 (struct timeval){ .tv_sec=stop_sec, .tv_usec=stop_usec });
     429           0 :         if (!ok) {
     430           0 :                 return -1;
     431             :         }
     432             : 
     433           0 :         tevent_req_profile_set_status(
     434             :                 profile,
     435             :                 pid,
     436             :                 (enum tevent_req_state)state,
     437             :                 user_error);
     438             : 
     439           0 :         return next - orig_buf;
     440             : }
     441             : 
     442           0 : ssize_t tevent_req_profile_unpack(
     443             :         const uint8_t *buf,
     444             :         size_t buflen,
     445             :         TALLOC_CTX *mem_ctx,
     446             :         struct tevent_req_profile **p_profile)
     447             : {
     448           0 :         const uint8_t *orig_buf = buf;
     449           0 :         struct tevent_req_profile *profile = NULL;
     450             :         uintmax_t i, num_subprofiles;
     451           0 :         char *next = NULL;
     452             :         bool ok;
     453             :         ssize_t len;
     454             : 
     455           0 :         errno = 0;
     456             : 
     457           0 :         if (buf[buflen-1] != '\0') {
     458           0 :                 return -1;
     459             :         }
     460             : 
     461           0 :         ok = parse_uintmax((const char *)buf, ' ', &num_subprofiles, &next);
     462           0 :         if (!ok) {
     463           0 :                 return -1;
     464             :         }
     465             : 
     466           0 :         len = (next - (const char *)buf);
     467             : 
     468           0 :         buf += len;
     469           0 :         buflen -= len;
     470             : 
     471           0 :         profile = tevent_req_profile_create(mem_ctx);
     472           0 :         if (profile == NULL) {
     473           0 :                 return -1;
     474             :         }
     475             : 
     476           0 :         len = tevent_req_profile_unpack_one(buf, buflen, profile);
     477           0 :         if (len == -1) {
     478           0 :                 TALLOC_FREE(profile);
     479           0 :                 return -1;
     480             :         }
     481             : 
     482           0 :         buf += len;
     483           0 :         buflen -= len;
     484             : 
     485           0 :         for (i=0; i<num_subprofiles; i++) {
     486             :                 struct tevent_req_profile *subprofile;
     487             : 
     488           0 :                 len = tevent_req_profile_unpack(
     489             :                         buf,
     490             :                         buflen,
     491             :                         profile,
     492             :                         &subprofile);
     493           0 :                 if (len == -1) {
     494           0 :                         TALLOC_FREE(profile);
     495           0 :                         return -1;
     496             :                 }
     497           0 :                 buf += len;
     498           0 :                 buflen -= len;
     499             : 
     500           0 :                 tevent_req_profile_append_sub(profile, &subprofile);
     501             :         }
     502             : 
     503           0 :         *p_profile = profile;
     504             : 
     505           0 :         return buf - orig_buf;
     506             : }

Generated by: LCOV version 1.13