LCOV - code coverage report
Current view: top level - home/snorch/criu - protobuf.c (source / functions) Hit Total Coverage
Test: coverage3.info Lines: 56 278 20.1 %
Date: 2014-04-22 Functions: 3 27 11.1 %
Branches: 38 203 18.7 %

           Branch data     Line data    Source code
       1                 :            : #include <unistd.h>
       2                 :            : #include <sys/types.h>
       3                 :            : #include <sys/stat.h>
       4                 :            : #include <fcntl.h>
       5                 :            : #include <stdlib.h>
       6                 :            : #include <arpa/inet.h>
       7                 :            : #include <ctype.h>
       8                 :            : 
       9                 :            : #include <google/protobuf-c/protobuf-c.h>
      10                 :            : 
      11                 :            : #include "image.h"
      12                 :            : #include "servicefd.h"
      13                 :            : #include "compiler.h"
      14                 :            : #include "asm/types.h"
      15                 :            : #include "log.h"
      16                 :            : #include "util.h"
      17                 :            : #include "string.h"
      18                 :            : #include "sockets.h"
      19                 :            : #include "cr_options.h"
      20                 :            : 
      21                 :            : #include "protobuf.h"
      22                 :            : 
      23                 :            : /*
      24                 :            :  * To speed up reading of packed objects
      25                 :            :  * by providing space on stack, this should
      26                 :            :  * be more than enough for most objects.
      27                 :            :  */
      28                 :            : #define PB_PKOBJ_LOCAL_SIZE     1024
      29                 :            : 
      30                 :            : #define INET_ADDR_LEN           40
      31                 :            : 
      32                 :            : struct pb_pr_field_s {
      33                 :            :         void *data;
      34                 :            :         int number;
      35                 :            :         int depth;
      36                 :            :         int count;
      37                 :            :         char fmt[32];
      38                 :            : };
      39                 :            : 
      40                 :            : typedef struct pb_pr_field_s pb_pr_field_t;
      41                 :            : 
      42                 :            : struct pb_pr_ctrl_s {
      43                 :            :         void *arg;
      44                 :            :         int single_entry;
      45                 :            :         const char *pretty_fmt;
      46                 :            :         pb_pr_field_t cur;
      47                 :            : };
      48                 :            : 
      49                 :            : typedef struct pb_pr_ctrl_s pb_pr_ctl_t;
      50                 :            : typedef int (*pb_pr_show_t)(pb_pr_field_t *field);
      51                 :            : 
      52                 :          0 : static int pb_msg_int32x(pb_pr_field_t *field)
      53                 :            : {
      54                 :          0 :         pr_msg("%#x", *(int *)field->data);
      55                 :          0 :         return 0;
      56                 :            : }
      57                 :            : 
      58                 :          0 : static int pb_msg_int64x(pb_pr_field_t *field)
      59                 :            : {
      60                 :          0 :         pr_msg("%#016lx", *(long *)field->data);
      61                 :          0 :         return 0;
      62                 :            : }
      63                 :            : 
      64                 :          0 : static int pb_msg_int64x_r(pb_pr_field_t *field)
      65                 :            : {
      66                 :          0 :         long val = *(long *)field->data;
      67         [ #  # ]:          0 :         if (val)
      68                 :          0 :                 pr_msg("%#016lx", val);
      69                 :            :         else
      70                 :          0 :                 pr_msg("0");
      71                 :          0 :         return 0;
      72                 :            : }
      73                 :            : 
      74                 :          0 : static int pb_msg_string(pb_pr_field_t *field)
      75                 :            : {
      76                 :          0 :         pr_msg("\"%s\"",    *(char **)field->data);
      77                 :          0 :         return 0;
      78                 :            : }
      79                 :            : 
      80                 :          0 : static int pb_msg_unk(pb_pr_field_t *field)
      81                 :            : {
      82                 :          0 :         pr_msg("unknown object %p", field->data);
      83                 :          0 :         return 0;
      84                 :            : }
      85                 :            : 
      86                 :            : static inline void print_tabs(pb_pr_ctl_t *ctl)
      87                 :            : {
      88                 :            :         int counter = ctl->cur.depth;
      89                 :            : 
      90 [ #  # ][ #  # ]:          0 :         if (!ctl->single_entry)
      91                 :            :                 return;
      92                 :            : 
      93 [ #  # ][ #  # ]:          0 :         while (counter--)
      94                 :          0 :                 pr_msg("\t");
      95                 :            : }
      96                 :            : 
      97                 :          0 : static void print_nested_message_braces(pb_pr_ctl_t *ctl, int right_brace)
      98                 :            : {
      99         [ #  # ]:          0 :         if (right_brace)
     100                 :            :                 print_tabs(ctl);
     101 [ #  # ][ #  # ]:          0 :         pr_msg("%s%s", (right_brace) ? "}" : "{", (ctl->single_entry) ? "\n" : " ");
     102                 :          0 : }
     103                 :            : 
     104                 :            : static void pb_show_msg(const void *msg, pb_pr_ctl_t *ctl);
     105                 :            : 
     106                 :          0 : static int show_nested_message(pb_pr_field_t *field)
     107                 :            : {
     108                 :          0 :         pb_pr_ctl_t *ctl = container_of(field, pb_pr_ctl_t, cur);
     109                 :            : 
     110                 :          0 :         print_nested_message_braces(ctl, 0);
     111                 :          0 :         field->depth++;
     112                 :          0 :         pb_show_msg(field->data, ctl);
     113                 :          0 :         field->depth--;
     114                 :          0 :         print_nested_message_braces(ctl, 1);
     115                 :          0 :         return 0;
     116                 :            : }
     117                 :            : 
     118                 :          0 : static int show_enum(pb_pr_field_t *field)
     119                 :            : {
     120                 :            :         pb_pr_ctl_t *ctl = container_of(field, pb_pr_ctl_t, cur);
     121                 :          0 :         ProtobufCEnumDescriptor *d = ctl->arg;
     122                 :            :         const char *val_name = NULL;
     123                 :            :         int val, i;
     124                 :            : 
     125                 :          0 :         val = *(int *)field->data;
     126         [ #  # ]:          0 :         for (i = 0; i < d->n_values; i++)
     127         [ #  # ]:          0 :                 if (d->values[i].value == val) {
     128                 :          0 :                         val_name = d->values[i].name;
     129                 :          0 :                         break;
     130                 :            :                 }
     131                 :            : 
     132         [ #  # ]:          0 :         if (val_name != NULL)
     133                 :          0 :                 pr_msg("%s", val_name);
     134                 :            :         else
     135                 :          0 :                 pr_msg("%d", val);
     136                 :          0 :         return 0;
     137                 :            : }
     138                 :            : 
     139                 :          0 : static int show_bool(pb_pr_field_t *field)
     140                 :            : {
     141                 :          0 :         protobuf_c_boolean val = *(protobuf_c_boolean *)field->data;
     142                 :            : 
     143         [ #  # ]:          0 :         if (val)
     144                 :          0 :                 pr_msg("True");
     145                 :            :         else
     146                 :          0 :                 pr_msg("False");
     147                 :          0 :         return 0;
     148                 :            : }
     149                 :            : 
     150                 :          0 : static int show_bytes(pb_pr_field_t *field)
     151                 :            : {
     152                 :          0 :         ProtobufCBinaryData *bytes = (ProtobufCBinaryData *)field->data;
     153                 :            :         int i = 0;
     154                 :            : 
     155         [ #  # ]:          0 :         while (i < bytes->len)
     156                 :          0 :                 pr_msg("%02x ", bytes->data[i++]);
     157                 :          0 :         return 0;
     158                 :            : }
     159                 :            : 
     160                 :          0 : static size_t pb_show_prepare_field_context(const ProtobufCFieldDescriptor *fd,
     161                 :            :                                           pb_pr_ctl_t *ctl)
     162                 :            : {
     163                 :            :         size_t fsize = 0;
     164                 :            : 
     165   [ #  #  #  #  :          0 :         switch (fd->type) {
             #  #  #  # ]
     166                 :            :         case PROTOBUF_C_TYPE_ENUM:
     167                 :          0 :                 ctl->arg = (void *)fd->descriptor;
     168                 :            :         case PROTOBUF_C_TYPE_INT32:
     169                 :            :         case PROTOBUF_C_TYPE_SINT32:
     170                 :            :         case PROTOBUF_C_TYPE_UINT32:
     171                 :            :         case PROTOBUF_C_TYPE_SFIXED32:
     172                 :            :         case PROTOBUF_C_TYPE_FLOAT:
     173                 :            :                 fsize = 4;
     174                 :            :                 break;
     175                 :            :         case PROTOBUF_C_TYPE_INT64:
     176                 :            :         case PROTOBUF_C_TYPE_SINT64:
     177                 :            :         case PROTOBUF_C_TYPE_SFIXED64:
     178                 :            :         case PROTOBUF_C_TYPE_FIXED32:
     179                 :            :         case PROTOBUF_C_TYPE_UINT64:
     180                 :            :         case PROTOBUF_C_TYPE_FIXED64:
     181                 :            :         case PROTOBUF_C_TYPE_DOUBLE:
     182                 :            :                 fsize = 8;
     183                 :            :                 break;
     184                 :            :         case PROTOBUF_C_TYPE_MESSAGE:
     185                 :          0 :                 ctl->arg = (void *)fd->descriptor;
     186                 :            :         case PROTOBUF_C_TYPE_STRING:
     187                 :            :                 fsize = sizeof (void *);
     188                 :            :                 break;
     189                 :            :         case PROTOBUF_C_TYPE_BOOL:
     190                 :            :                 fsize = sizeof (protobuf_c_boolean);
     191                 :            :                 break;
     192                 :            :         case PROTOBUF_C_TYPE_BYTES:
     193                 :            :                 fsize = sizeof (ProtobufCBinaryData);
     194                 :            :                 break;
     195                 :            :         default:
     196                 :          0 :                 BUG();
     197                 :            :         }
     198                 :          0 :         return fsize;
     199                 :            : }
     200                 :            : 
     201                 :          0 : static int pb_show_pretty(pb_pr_field_t *field)
     202                 :            : {
     203   [ #  #  #  # ]:          0 :         switch (field->fmt[0]) {
     204                 :            :         case '%':
     205                 :          0 :                 pr_msg(field->fmt, *(long *)field->data);
     206                 :          0 :                 break;
     207                 :            :         case 'S':
     208                 :            :                 {
     209                 :          0 :                         ProtobufCBinaryData *name = (ProtobufCBinaryData *)field->data;
     210                 :            :                         int i;
     211                 :            : 
     212         [ #  # ]:          0 :                         for (i = 0; i < name->len; i++) {
     213                 :          0 :                                 char c = (char)name->data[i];
     214                 :            : 
     215         [ #  # ]:          0 :                                 if (isprint(c))
     216                 :          0 :                                         pr_msg("%c", c);
     217         [ #  # ]:          0 :                                 else if (c != 0)
     218                 :          0 :                                         pr_msg(".");
     219                 :            :                         }
     220                 :            :                         break;
     221                 :            :                 }
     222                 :            :         case 'A':
     223                 :            :                 {
     224                 :          0 :                         char addr[INET_ADDR_LEN] = "<unknown>";
     225         [ #  # ]:          0 :                         int family = (field->count == 1) ? AF_INET : AF_INET6;
     226                 :            : 
     227         [ #  # ]:          0 :                         if (inet_ntop(family, (void *)field->data, addr,
     228                 :            :                                       INET_ADDR_LEN) == NULL)
     229                 :          0 :                                 pr_msg("failed to translate");
     230                 :            :                         else
     231                 :          0 :                                 pr_msg("%s", addr);
     232                 :            :                 }
     233                 :          0 :                 return 1;
     234                 :            :         }
     235                 :            :         return 0;
     236                 :            : }
     237                 :            : 
     238                 :            : static void pb_copy_fmt(const char *fmt, char *to)
     239                 :            : {
     240         [ #  # ]:          0 :         while (*fmt != ' ' && *fmt != '\0') {
     241                 :          0 :                 *to = *fmt;
     242                 :          0 :                 to++;
     243                 :          0 :                 fmt++;
     244                 :            :         }
     245                 :            : 
     246                 :          0 :         *to = '\0';
     247                 :            : }
     248                 :            : 
     249                 :          0 : static const char *pb_next_pretty(const char *pfmt)
     250                 :            : {
     251                 :          0 :         pfmt = strchr(pfmt, ' ');
     252         [ #  # ]:          0 :         if (pfmt) {
     253         [ #  # ]:          0 :                 while (*pfmt == ' ')
     254                 :          0 :                         pfmt++;
     255                 :            : 
     256         [ #  # ]:          0 :                 if (*pfmt == '\0')
     257                 :            :                         pfmt = NULL;
     258                 :            :         }
     259                 :            : 
     260                 :          0 :         return pfmt;
     261                 :            : }
     262                 :            : 
     263                 :          0 : static int pb_find_fmt(char *what, pb_pr_ctl_t *ctl)
     264                 :            : {
     265                 :            :         int len;
     266                 :          0 :         const char *pretty = ctl->pretty_fmt;
     267                 :            : 
     268                 :          0 :         len = strlen(what);
     269                 :            :         while (1) {
     270         [ #  # ]:          0 :                 if (!strncmp(pretty, what, len)) {
     271                 :          0 :                         pb_copy_fmt(pretty + len, ctl->cur.fmt);
     272                 :          0 :                         return 1;
     273                 :            :                 }
     274                 :            : 
     275                 :          0 :                 pretty = pb_next_pretty(pretty + len);
     276         [ #  # ]:          0 :                 if (!pretty)
     277                 :            :                         return 0;
     278                 :            :         }
     279                 :            : }
     280                 :            : 
     281                 :          0 : static int pb_field_show_pretty(const ProtobufCFieldDescriptor *fd, pb_pr_ctl_t *ctl)
     282                 :            : {
     283                 :            :         char cookie[32];
     284                 :            : 
     285         [ #  # ]:          0 :         if (!ctl->pretty_fmt)
     286                 :            :                 return 0;
     287                 :            : 
     288                 :          0 :         sprintf(cookie, "%s:", fd->name);
     289         [ #  # ]:          0 :         if (pb_find_fmt(cookie, ctl))
     290                 :            :                 return 1;
     291                 :            : 
     292         [ #  # ]:          0 :         if (!ctl->cur.depth)
     293                 :          0 :                 sprintf(cookie, "%d:", ctl->cur.number);
     294                 :            :         else
     295                 :          0 :                 sprintf(cookie, "%d.%d:", ctl->cur.depth, ctl->cur.number);
     296                 :            : 
     297         [ #  # ]:          0 :         if (pb_find_fmt(cookie, ctl))
     298                 :            :                 return 1;
     299                 :            : 
     300                 :            :         sprintf(cookie, "*:");
     301         [ #  # ]:          0 :         if (pb_find_fmt(cookie, ctl))
     302                 :            :                 return 1;
     303                 :            : 
     304                 :            :         return 0;
     305                 :            : }
     306                 :            : 
     307                 :          0 : static pb_pr_show_t get_pb_show_function(int type, int label)
     308                 :            : {
     309   [ #  #  #  #  :          0 :         switch (type) {
             #  #  #  #  
                      # ]
     310                 :            :         case PROTOBUF_C_TYPE_INT32:
     311                 :            :         case PROTOBUF_C_TYPE_SINT32:
     312                 :            :         case PROTOBUF_C_TYPE_UINT32:
     313                 :            :         case PROTOBUF_C_TYPE_SFIXED32:
     314                 :            :                 return pb_msg_int32x;
     315                 :            :         case PROTOBUF_C_TYPE_INT64:
     316                 :            :         case PROTOBUF_C_TYPE_SINT64:
     317                 :            :         case PROTOBUF_C_TYPE_SFIXED64:
     318                 :            :         case PROTOBUF_C_TYPE_FIXED32:
     319                 :            :         case PROTOBUF_C_TYPE_UINT64:
     320                 :            :         case PROTOBUF_C_TYPE_FIXED64:
     321         [ #  # ]:          0 :                 return (label == PROTOBUF_C_LABEL_REPEATED ?
     322                 :            :                                 pb_msg_int64x_r : pb_msg_int64x);
     323                 :            :         case PROTOBUF_C_TYPE_STRING:
     324                 :          0 :                 return pb_msg_string;
     325                 :            :         case PROTOBUF_C_TYPE_MESSAGE:
     326                 :          0 :                 return show_nested_message;
     327                 :            :         case PROTOBUF_C_TYPE_ENUM:
     328                 :          0 :                 return show_enum;
     329                 :            :         case PROTOBUF_C_TYPE_BOOL:
     330                 :          0 :                 return show_bool;
     331                 :            :         case PROTOBUF_C_TYPE_BYTES:
     332                 :          0 :                 return show_bytes;
     333                 :            :         case PROTOBUF_C_TYPE_FLOAT:
     334                 :            :         case PROTOBUF_C_TYPE_DOUBLE:
     335                 :            :                 break;
     336                 :            :         default:
     337                 :          0 :                 BUG();
     338                 :            :         }
     339                 :            :         return pb_msg_unk;
     340                 :            : }
     341                 :            : 
     342                 :          0 : static pb_pr_show_t get_show_function(const ProtobufCFieldDescriptor *fd, pb_pr_ctl_t *ctl)
     343                 :            : {
     344         [ #  # ]:          0 :         if (pb_field_show_pretty(fd, ctl))
     345                 :            :                 return pb_show_pretty;
     346                 :          0 :         return get_pb_show_function(fd->type, fd->label);
     347                 :            : }
     348                 :            : 
     349                 :          0 : static void pb_show_repeated(const ProtobufCFieldDescriptor *fd, pb_pr_ctl_t *ctl, int nr_fields, pb_pr_show_t show,
     350                 :            :                           size_t fsize)
     351                 :            : {
     352                 :          0 :         pb_pr_field_t *field = &ctl->cur;
     353                 :            :         unsigned long counter;
     354                 :            :         int done;
     355                 :            : 
     356         [ #  # ]:          0 :         if (nr_fields == 0) {
     357                 :          0 :                 pr_msg("<empty>");
     358                 :            :                 return;
     359                 :            :         }
     360                 :            : 
     361         [ #  # ]:          0 :         if (fd->type == PROTOBUF_C_TYPE_MESSAGE) {
     362                 :          0 :                 void *p = field->data;
     363                 :            : 
     364                 :          0 :                 field->count = nr_fields;
     365                 :          0 :                 field->data = (void *)(*(long *)p);
     366                 :          0 :                 done = show(field);
     367         [ #  # ]:          0 :                 if (done)
     368                 :            :                         return;
     369                 :            : 
     370         [ #  # ]:          0 :                 for (p += fsize, counter = 0; counter < nr_fields - 1; counter++, p += fsize) {
     371                 :          0 :                         pr_msg(":");
     372                 :          0 :                         field->data = (void *)(*(long *)p);
     373                 :          0 :                         show(field);
     374                 :            :                 }
     375                 :            :                 return;
     376                 :            :         }
     377                 :            : 
     378                 :          0 :         field->count = nr_fields;
     379                 :          0 :         done = show(field);
     380         [ #  # ]:          0 :         if (done)
     381                 :            :                 return;
     382                 :            : 
     383                 :          0 :         field->data += fsize;
     384                 :            : 
     385         [ #  # ]:          0 :         for (counter = 0; counter < nr_fields - 1; counter++, field->data += fsize) {
     386                 :          0 :                 pr_msg(":");
     387                 :          0 :                 show(field);
     388                 :            :         }
     389                 :            : }
     390                 :            : 
     391                 :          0 : static void pb_show_field(const ProtobufCFieldDescriptor *fd,
     392                 :          0 :                           int nr_fields, pb_pr_ctl_t *ctl)
     393                 :            : {
     394                 :            :         pb_pr_show_t show;
     395                 :            : 
     396                 :            :         print_tabs(ctl);
     397                 :          0 :         pr_msg("%s: ", fd->name);
     398                 :            : 
     399                 :          0 :         show = get_show_function(fd, ctl);
     400                 :            : 
     401                 :          0 :         pb_show_repeated(fd, ctl, nr_fields, show, pb_show_prepare_field_context(fd, ctl));
     402                 :            : 
     403         [ #  # ]:          0 :         if (ctl->single_entry)
     404                 :          0 :                 pr_msg("\n");
     405                 :            :         else
     406                 :          0 :                 pr_msg(" ");
     407                 :          0 : }
     408                 :            : 
     409                 :          0 : static int pb_optional_field_present(const ProtobufCFieldDescriptor *field,
     410                 :            :                 const void *msg)
     411                 :            : {
     412         [ #  # ]:          0 :         if ((field->type == PROTOBUF_C_TYPE_MESSAGE) ||
     413                 :            :                 (field->type == PROTOBUF_C_TYPE_STRING)) {
     414                 :          0 :                 const void *opt_flag = * (const void * const *)(msg + field->offset);
     415                 :            : 
     416 [ #  # ][ #  # ]:          0 :                 if ((opt_flag == NULL) || (opt_flag == field->default_value))
     417                 :            :                         return 0;
     418                 :            :         } else {
     419                 :          0 :                 const protobuf_c_boolean *has = msg + field->quantifier_offset;
     420                 :            : 
     421         [ #  # ]:          0 :                 if (!*has)
     422                 :            :                         return 0;
     423                 :            :         }
     424                 :          0 :         return 1;
     425                 :            : }
     426                 :            : 
     427                 :          0 : static bool should_show_field(const char *name)
     428                 :            : {
     429                 :            :         char *s, *e;
     430                 :            :         int len;
     431                 :            : 
     432         [ #  # ]:          0 :         if (!opts.show_fmt)
     433                 :            :                 return true;
     434                 :            : 
     435                 :          0 :         len = strlen(name);
     436                 :            :         s = opts.show_fmt;
     437                 :            : 
     438                 :            :         while (1) {
     439                 :          0 :                 e = strchrnul(s, ',');
     440         [ #  # ]:          0 :                 if (e - s == len) {
     441         [ #  # ]:          0 :                         if (!strncmp(name, s, len))
     442                 :            :                                 return true;
     443                 :            :                 }
     444         [ #  # ]:          0 :                 if (*e == '\0')
     445                 :            :                         return false;
     446                 :          0 :                 s = e + 1;
     447                 :          0 :         }
     448                 :            : }
     449                 :            : 
     450                 :          0 : static void pb_show_msg(const void *msg, pb_pr_ctl_t *ctl)
     451                 :            : {
     452                 :            :         int i;
     453                 :          0 :         const ProtobufCMessageDescriptor *md = ctl->arg;
     454                 :            : 
     455         [ #  # ]:          0 :         BUG_ON(md == NULL);
     456                 :            : 
     457         [ #  # ]:          0 :         for (i = 0; i < md->n_fields; i++) {
     458                 :          0 :                 const ProtobufCFieldDescriptor fd = md->fields[i];
     459                 :            :                 unsigned long *data;
     460                 :            :                 size_t nr_fields;
     461                 :            : 
     462                 :            :                 nr_fields = 1;
     463                 :          0 :                 data = (unsigned long *)(msg + fd.offset);
     464                 :            : 
     465         [ #  # ]:          0 :                 if (fd.label == PROTOBUF_C_LABEL_OPTIONAL) {
     466         [ #  # ]:          0 :                         if (!pb_optional_field_present(&fd, msg))
     467                 :          0 :                                 continue;
     468                 :            :                 }
     469                 :            : 
     470         [ #  # ]:          0 :                 if (!should_show_field(fd.name))
     471                 :          0 :                         continue;
     472                 :            : 
     473         [ #  # ]:          0 :                 if (fd.label == PROTOBUF_C_LABEL_REPEATED) {
     474                 :          0 :                         nr_fields = *(size_t *)(msg + fd.quantifier_offset);
     475                 :          0 :                         data = (unsigned long *)*data;
     476                 :            :                 }
     477                 :            : 
     478                 :          0 :                 ctl->cur.data = data;
     479                 :          0 :                 ctl->cur.number = i + 1;
     480                 :            : 
     481                 :          0 :                 pb_show_field(&fd, nr_fields, ctl);
     482                 :            :         }
     483                 :          0 : }
     484                 :            : 
     485                 :          0 : static inline void pb_no_payload(int fd, void *obj) { }
     486                 :            : 
     487                 :          0 : void do_pb_show_plain(int fd, int type, int single_entry,
     488                 :            :                 void (*payload_hadler)(int fd, void *obj),
     489                 :            :                 const char *pretty_fmt)
     490                 :            : {
     491                 :          0 :         pb_pr_ctl_t ctl = {NULL, single_entry, pretty_fmt};
     492                 :            :         void (*handle_payload)(int fd, void *obj);
     493                 :            : 
     494         [ #  # ]:          0 :         if (!cr_pb_descs[type].pb_desc) {
     495                 :          0 :                 pr_err("Wrong object requested %d\n", type);
     496                 :          0 :                 return;
     497                 :            :         }
     498                 :            : 
     499         [ #  # ]:          0 :         handle_payload = (payload_hadler) ? : pb_no_payload;
     500                 :            : 
     501                 :            :         while (1) {
     502                 :            :                 void *obj;
     503                 :            : 
     504         [ #  # ]:          0 :                 if (pb_read_one_eof(fd, &obj, type) <= 0)
     505                 :            :                         break;
     506                 :            : 
     507                 :          0 :                 ctl.arg = (void *)cr_pb_descs[type].pb_desc;
     508                 :          0 :                 pb_show_msg(obj, &ctl);
     509                 :          0 :                 handle_payload(fd, obj);
     510                 :          0 :                 cr_pb_descs[type].free(obj, NULL);
     511         [ #  # ]:          0 :                 if (single_entry)
     512                 :            :                         break;
     513                 :          0 :                 pr_msg("\n");
     514                 :          0 :         }
     515                 :            : }
     516                 :            : 
     517                 :            : static char *image_name(int fd)
     518                 :            : {
     519                 :            :         static char image_path[PATH_MAX];
     520                 :            : 
     521 [ #  # ][ #  # ]:          0 :         if (read_fd_link(fd, image_path, sizeof(image_path)) > 0)
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     522                 :            :                 return image_path;
     523                 :            :         return NULL;
     524                 :            : }
     525                 :            : 
     526                 :            : /*
     527                 :            :  * Reads PB record (header + packed object) from file @fd and unpack
     528                 :            :  * it with @unpack procedure to the pointer @pobj
     529                 :            :  *
     530                 :            :  *  1 on success
     531                 :            :  * -1 on error (or EOF met and @eof set to false)
     532                 :            :  *  0 on EOF and @eof set to true
     533                 :            :  *
     534                 :            :  * Don't forget to free memory granted to unpacked object in calling code if needed
     535                 :            :  */
     536                 :            : 
     537                 :     387878 : int do_pb_read_one(int fd, void **pobj, int type, bool eof)
     538                 :            : {
     539                 :            :         u8 local[PB_PKOBJ_LOCAL_SIZE];
     540                 :            :         void *buf = (void *)&local;
     541                 :            :         u32 size;
     542                 :            :         int ret;
     543                 :            : 
     544         [ -  + ]:     387878 :         if (!cr_pb_descs[type].pb_desc) {
     545                 :          0 :                 pr_err("Wrong object requested %d on %s\n",
     546                 :            :                         type, image_name(fd));
     547                 :          0 :                 return -1;
     548                 :            :         }
     549                 :            : 
     550                 :     387878 :         *pobj = NULL;
     551                 :            : 
     552                 :     387878 :         ret = read(fd, &size, sizeof(size));
     553         [ +  + ]:     387878 :         if (ret == 0) {
     554         [ -  + ]:      14531 :                 if (eof) {
     555                 :            :                         return 0;
     556                 :            :                 } else {
     557                 :          0 :                         pr_err("Unexpected EOF on %s\n",
     558                 :            :                                image_name(fd));
     559                 :          0 :                         return -1;
     560                 :            :                 }
     561         [ -  + ]:     373347 :         } else if (ret < sizeof(size)) {
     562                 :          0 :                 pr_perror("Read %d bytes while %d expected on %s",
     563                 :            :                           ret, (int)sizeof(size),
     564                 :            :                           image_name(fd));
     565                 :          0 :                 return -1;
     566                 :            :         }
     567                 :            : 
     568         [ +  + ]:     373347 :         if (size > sizeof(local)) {
     569                 :            :                 ret = -1;
     570         [ -  + ]:         88 :                 buf = xmalloc(size);
     571         [ +  - ]:         88 :                 if (!buf)
     572                 :            :                         goto err;
     573                 :            :         }
     574                 :            : 
     575                 :     746694 :         ret = read(fd, buf, size);
     576         [ -  + ]:     373347 :         if (ret < 0) {
     577                 :          0 :                 pr_perror("Can't read %d bytes from file %s",
     578                 :            :                           size, image_name(fd));
     579                 :          0 :                 goto err;
     580         [ -  + ]:     373347 :         } else if (ret != size) {
     581                 :          0 :                 pr_perror("Read %d bytes while %d expected from %s",
     582                 :            :                           ret, size, image_name(fd));
     583                 :            :                 ret = -1;
     584                 :          0 :                 goto err;
     585                 :            :         }
     586                 :            : 
     587                 :     373347 :         *pobj = cr_pb_descs[type].unpack(NULL, size, buf);
     588         [ -  + ]:     373347 :         if (!*pobj) {
     589                 :            :                 ret = -1;
     590                 :          0 :                 pr_err("Failed unpacking object %p from %s\n",
     591                 :            :                        pobj, image_name(fd));
     592                 :          0 :                 goto err;
     593                 :            :         }
     594                 :            : 
     595                 :            :         ret = 1;
     596                 :            : err:
     597         [ +  + ]:     373347 :         if (buf != (void *)&local)
     598         [ +  - ]:         88 :                 xfree(buf);
     599                 :            : 
     600                 :     373347 :         return ret;
     601                 :            : }
     602                 :            : 
     603                 :            : /*
     604                 :            :  * Writes PB record (header + packed object pointed by @obj)
     605                 :            :  * to file @fd, using @getpksize to get packed size and @pack
     606                 :            :  * to implement packing
     607                 :            :  *
     608                 :            :  *  0 on success
     609                 :            :  * -1 on error
     610                 :            :  */
     611                 :     233447 : int pb_write_one(int fd, void *obj, int type)
     612                 :            : {
     613                 :            :         u8 local[PB_PKOBJ_LOCAL_SIZE];
     614                 :            :         void *buf = (void *)&local;
     615                 :            :         u32 size, packed;
     616                 :            :         int ret = -1;
     617                 :            :         struct iovec iov[2];
     618                 :            : 
     619         [ -  + ]:     233447 :         if (!cr_pb_descs[type].pb_desc) {
     620                 :          0 :                 pr_err("Wrong object requested %d\n", type);
     621                 :          0 :                 return -1;
     622                 :            :         }
     623                 :            : 
     624                 :     233447 :         size = cr_pb_descs[type].getpksize(obj);
     625         [ +  + ]:     233447 :         if (size > (u32)sizeof(local)) {
     626         [ -  + ]:         78 :                 buf = xmalloc(size);
     627         [ +  - ]:         78 :                 if (!buf)
     628                 :            :                         goto err;
     629                 :            :         }
     630                 :            : 
     631                 :     233447 :         packed = cr_pb_descs[type].pack(obj, buf);
     632         [ -  + ]:     233447 :         if (packed != size) {
     633                 :          0 :                 pr_err("Failed packing PB object %p\n", obj);
     634                 :          0 :                 goto err;
     635                 :            :         }
     636                 :            : 
     637                 :     233447 :         iov[0].iov_base = &size;
     638                 :     233447 :         iov[0].iov_len = sizeof(size);
     639                 :     233447 :         iov[1].iov_base = buf;
     640                 :     233447 :         iov[1].iov_len = size;
     641                 :            : 
     642                 :     233447 :         ret = writev(fd, iov, 2);
     643         [ -  + ]:     233447 :         if (ret != size + sizeof(size)) {
     644                 :          0 :                 pr_perror("Can't write %d bytes", (int)(size + sizeof(size)));
     645                 :          0 :                 goto err;
     646                 :            :         }
     647                 :            : 
     648                 :            :         ret = 0;
     649                 :            : err:
     650         [ +  + ]:     233447 :         if (buf != (void *)&local)
     651         [ +  - ]:         78 :                 xfree(buf);
     652                 :     233447 :         return ret;
     653                 :            : }
     654                 :            : 
     655                 :       8113 : int collect_image(struct collect_image_info *cinfo)
     656                 :            : {
     657                 :       8113 :         bool optional = !!(cinfo->flags & COLLECT_OPTIONAL);
     658                 :            :         int fd, ret;
     659                 :            :         void *(*o_alloc)(size_t size) = malloc;
     660                 :            :         void (*o_free)(void *ptr) = free;
     661                 :            : 
     662                 :       8113 :         pr_info("Collecting %d/%d (flags %x)\n",
     663                 :            :                         cinfo->fd_type, cinfo->pb_type, cinfo->flags);
     664                 :            : 
     665         [ +  + ]:       8113 :         fd = open_image(cinfo->fd_type, O_RSTR | (optional ? O_OPT : 0));
     666         [ -  + ]:       8113 :         if (fd < 0) {
     667         [ #  # ]:          0 :                 if (optional && fd == -ENOENT)
     668                 :            :                         return 0;
     669                 :            :                 else
     670                 :          0 :                         return -1;
     671                 :            :         }
     672                 :            : 
     673         [ +  + ]:       8113 :         if (cinfo->flags & COLLECT_SHARED) {
     674                 :            :                 o_alloc = shmalloc;
     675                 :            :                 o_free = shfree_last;
     676                 :            :         }
     677                 :            : 
     678                 :            :         while (1) {
     679                 :            :                 void *obj;
     680                 :            :                 ProtobufCMessage *msg;
     681                 :            : 
     682         [ +  + ]:      11910 :                 if (cinfo->priv_size) {
     683                 :            :                         ret = -1;
     684                 :      11529 :                         obj = o_alloc(cinfo->priv_size);
     685         [ +  - ]:      11529 :                         if (!obj)
     686                 :            :                                 break;
     687                 :            :                 } else
     688                 :            :                         obj = NULL;
     689                 :            : 
     690                 :      11910 :                 ret = pb_read_one_eof(fd, &msg, cinfo->pb_type);
     691         [ +  + ]:      11910 :                 if (ret <= 0) {
     692                 :       8113 :                         o_free(obj);
     693                 :       8113 :                         break;
     694                 :            :                 }
     695                 :            : 
     696                 :       3797 :                 ret = cinfo->collect(obj, msg);
     697         [ -  + ]:       3797 :                 if (ret < 0) {
     698                 :          0 :                         o_free(obj);
     699                 :          0 :                         cr_pb_descs[cinfo->pb_type].free(msg, NULL);
     700                 :          0 :                         break;
     701                 :            :                 }
     702                 :            : 
     703         [ +  + ]:       3797 :                 if (!cinfo->priv_size)
     704                 :         26 :                         cr_pb_descs[cinfo->pb_type].free(msg, NULL);
     705                 :       3797 :         }
     706                 :            : 
     707                 :       8113 :         close(fd);
     708                 :       8113 :         pr_debug(" `- ... done\n");
     709                 :       8113 :         return ret;
     710                 :            : }

Generated by: LCOV version 1.9