Coverage report for src/sexpr.c.gcov
-: 0:Source:sexpr.c
-: 0:Graph:./libvirt_la-sexpr.gcno
-: 0:Data:./libvirt_la-sexpr.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:/*
-: 2: * sexpr.c : S-Expression routines to communicate with the Xen Daemon
-: 3: *
-: 4: * Copyright (C) 2005
-: 5: *
-: 6: * Anthony Liguori <aliguori@us.ibm.com>
-: 7: *
-: 8: * This file is subject to the terms and conditions of the GNU Lesser General
-: 9: * Public License. See the file COPYING.LIB in the main directory of this
-: 10: * archive for more details.
-: 11: */
-: 12:
-: 13:#define _GNU_SOURCE
-: 14:
-: 15:#include "sexpr.h"
-: 16:#include "internal.h"
-: 17:
-: 18:#include <malloc.h>
-: 19:#include <string.h>
-: 20:#include <stdio.h>
-: 21:#include <ctype.h>
-: 22:#include <errno.h>
-: 23:
-: 24:/**
-: 25: * virSexprError:
-: 26: * @conn: the connection if available
-: 27: * @error: the error noumber
-: 28: * @info: extra information string
-: 29: *
-: 30: * Handle an error in the S-Expression code
-: 31: */
-: 32:static void
-: 33:virSexprError(virErrorNumber error, const char *info)
function virSexprError called 0 returned 0% blocks executed 0%
#####: 34:{
-: 35: const char *errmsg;
-: 36:
#####: 37: if (error == VIR_ERR_OK)
branch 0 never executed
branch 1 never executed
#####: 38: return;
-: 39:
#####: 40: errmsg = __virErrorMsg(error, info);
call 0 never executed
#####: 41: __virRaiseError(NULL, NULL, VIR_FROM_SEXPR, error, VIR_ERR_ERROR,
call 0 never executed
-: 42: errmsg, info, NULL, 0, 0, errmsg, info);
-: 43:}
-: 44:
-: 45:/**
-: 46: * sexpr_new:
-: 47: *
-: 48: * Create a new S-Expression
-: 49: *
-: 50: * Returns the new node or NULL in case of memory allocation error
-: 51: */
-: 52:static struct sexpr *
-: 53:sexpr_new(void)
function sexpr_new called 268 returned 100% blocks executed 67%
268: 54:{
-: 55: struct sexpr *ret;
-: 56:
268: 57: ret = (struct sexpr *) malloc(sizeof(*ret));
call 0 returned 100%
268: 58: if (ret == NULL) {
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 59: virSexprError(VIR_ERR_NO_MEMORY, "failed to allocate a node");
call 0 never executed
#####: 60: return (NULL);
-: 61: }
268: 62: ret->kind = SEXPR_NIL;
268: 63: return ret;
-: 64:}
-: 65:
-: 66:/**
-: 67: * sexpr_free:
-: 68: * @sexpr: the S-Expression pointer
-: 69: *
-: 70: * Free an S-Expression
-: 71: */
-: 72:void
-: 73:sexpr_free(struct sexpr *sexpr)
function sexpr_free called 268 returned 100% blocks executed 92%
268: 74:{
268: 75: int serrno = errno;
call 0 returned 100%
-: 76:
268: 77: if (sexpr == NULL) {
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 78: return;
-: 79: }
-: 80:
268: 81: switch (sexpr->kind) {
branch 0 taken 50%
branch 1 taken 32%
branch 2 taken 18%
-: 82: case SEXPR_CONS:
133: 83: sexpr_free(sexpr->car);
call 0 returned 100%
133: 84: sexpr_free(sexpr->cdr);
call 0 returned 100%
133: 85: break;
-: 86: case SEXPR_VALUE:
86: 87: free(sexpr->value);
call 0 returned 100%
-: 88: break;
-: 89: case SEXPR_NIL:
-: 90: break;
-: 91: }
-: 92:
268: 93: free(sexpr);
call 0 returned 100%
-: 94:
268: 95: errno = serrno;
call 0 returned 100%
-: 96:}
-: 97:
-: 98:/**
-: 99: * sexpr_nil:
-: 100: *
-: 101: * Provide a NIL S-Expression (the pointer is not shared so NIL equality
-: 102: * testing won't work at the pointer level).
-: 103: *
-: 104: * Returns a new NIL S-Expression of NULL in case of error.
-: 105: */
-: 106:struct sexpr *
-: 107:sexpr_nil(void)
function sexpr_nil called 133 returned 100% blocks executed 100%
133: 108:{
133: 109: return sexpr_new();
call 0 returned 100%
-: 110:}
-: 111:
-: 112:/**
-: 113: * sexpr_string:
-: 114: * @str: the input string, assumed to be UTF-8
-: 115: * @len: the length in bytes of the input
-: 116: *
-: 117: * Parse the input S-Expression and return a pointer to the result
-: 118: *
-: 119: * Returns the S-Expression pointer or NULL in case of error
-: 120: */
-: 121:struct sexpr *
-: 122:sexpr_string(const char *str, ssize_t len)
function sexpr_string called 0 returned 0% blocks executed 0%
#####: 123:{
#####: 124: struct sexpr *ret = sexpr_new();
call 0 never executed
-: 125:
#####: 126: if (ret == NULL)
branch 0 never executed
branch 1 never executed
#####: 127: return ret;
#####: 128: ret->kind = SEXPR_VALUE;
#####: 129: if (len > 0) {
branch 0 never executed
branch 1 never executed
#####: 130: ret->value = strndup(str, len);
call 0 never executed
-: 131: } else {
#####: 132: ret->value = strdup(str);
call 0 never executed
-: 133: }
-: 134:
#####: 135: if (ret->value == NULL) {
branch 0 never executed
branch 1 never executed
#####: 136: return NULL;
-: 137: }
-: 138:
#####: 139: return ret;
-: 140:}
-: 141:
-: 142:/**
-: 143: * sexpr_cons:
-: 144: * @car: the left operand
-: 145: * @cdr: the right operand
-: 146: *
-: 147: * Implement the CONS operation assembling 2 existing S-Expressions.
-: 148: * Note that in case of error the input data are not freed.
-: 149: *
-: 150: * Returns the resulting S-Expression pointer or NULL in case of error.
-: 151: */
-: 152:struct sexpr *
-: 153:sexpr_cons(struct sexpr *car, struct sexpr *cdr)
function sexpr_cons called 0 returned 0% blocks executed 0%
#####: 154:{
#####: 155: struct sexpr *ret = sexpr_new();
call 0 never executed
-: 156:
#####: 157: if (ret == NULL)
branch 0 never executed
branch 1 never executed
#####: 158: return ret;
#####: 159: ret->kind = SEXPR_CONS;
#####: 160: ret->car = car;
#####: 161: ret->cdr = cdr;
-: 162:
#####: 163: return ret;
-: 164:}
-: 165:
-: 166:/**
-: 167: * append:
-: 168: * @lst: an existing list
-: 169: * @value: the value
-: 170: *
-: 171: * Internal operation appending a value at the end of an existing list
-: 172: */
-: 173:static void
-: 174:append(struct sexpr *lst, struct sexpr *value)
function append called 133 returned 100% blocks executed 100%
133: 175:{
501: 176: while (lst->kind != SEXPR_NIL) {
branch 0 taken 64%
branch 1 taken 36% (fallthrough)
235: 177: lst = lst->cdr;
-: 178: }
-: 179:
133: 180: lst->kind = SEXPR_CONS;
133: 181: lst->car = value;
133: 182: lst->cdr = sexpr_nil();
call 0 returned 100%
133: 183:}
-: 184:
-: 185:/**
-: 186: * @lst: an existing list
-: 187: * @value: the value
-: 188: *
-: 189: * Append a value at the end of an existing list
-: 190: *
-: 191: * Returns lst or NULL in case of error
-: 192: */
-: 193:struct sexpr *
-: 194:sexpr_append(struct sexpr *lst, struct sexpr *value)
function sexpr_append called 0 returned 0% blocks executed 0%
#####: 195:{
#####: 196: if (lst == NULL)
branch 0 never executed
branch 1 never executed
#####: 197: return (NULL);
#####: 198: if (value == NULL)
branch 0 never executed
branch 1 never executed
#####: 199: return (lst);
#####: 200: append(lst, value);
call 0 never executed
#####: 201: return (lst);
-: 202:}
-: 203:
-: 204:/**
-: 205: * sexpr2string:
-: 206: * @sexpr: an S-Expression pointer
-: 207: * @buffer: the output buffer
-: 208: * @n_buffer: the size of the buffer in bytes
-: 209: *
-: 210: * Serialize the S-Expression in the buffer.
-: 211: * Note that the output may be truncated if @n_buffer is too small
-: 212: * resulting in an unparseable value.
-: 213: *
-: 214: * Returns the number of bytes used by the serialization in the buffer or
-: 215: * 0 in case of error.
-: 216: */
-: 217:size_t
-: 218:sexpr2string(struct sexpr * sexpr, char *buffer, size_t n_buffer)
function sexpr2string called 0 returned 0% blocks executed 0%
#####: 219:{
#####: 220: size_t ret = 0, tmp;
-: 221:
#####: 222: if ((sexpr == NULL) || (buffer == NULL) || (n_buffer <= 0))
branch 0 never executed
branch 1 never executed
branch 2 never executed
branch 3 never executed
#####: 223: return (0);
-: 224:
#####: 225: switch (sexpr->kind) {
branch 0 never executed
branch 1 never executed
branch 2 never executed
branch 3 never executed
-: 226: case SEXPR_CONS:
#####: 227: tmp = snprintf(buffer + ret, n_buffer - ret, "(");
call 0 never executed
#####: 228: if (tmp == 0)
branch 0 never executed
branch 1 never executed
#####: 229: goto error;
#####: 230: ret += tmp;
#####: 231: tmp = sexpr2string(sexpr->car, buffer + ret, n_buffer - ret);
call 0 never executed
#####: 232: if (tmp == 0)
branch 0 never executed
branch 1 never executed
#####: 233: goto error;
#####: 234: ret += tmp;
#####: 235: while (sexpr->cdr->kind != SEXPR_NIL) {
branch 0 never executed
branch 1 never executed
#####: 236: sexpr = sexpr->cdr;
#####: 237: tmp = snprintf(buffer + ret, n_buffer - ret, " ");
call 0 never executed
#####: 238: if (tmp == 0)
branch 0 never executed
branch 1 never executed
#####: 239: goto error;
#####: 240: ret += tmp;
#####: 241: tmp =
call 0 never executed
-: 242: sexpr2string(sexpr->car, buffer + ret, n_buffer - ret);
#####: 243: if (tmp == 0)
branch 0 never executed
branch 1 never executed
#####: 244: goto error;
#####: 245: ret += tmp;
-: 246: }
#####: 247: tmp = snprintf(buffer + ret, n_buffer - ret, ")");
call 0 never executed
#####: 248: if (tmp == 0)
branch 0 never executed
branch 1 never executed
#####: 249: goto error;
#####: 250: ret += tmp;
#####: 251: break;
-: 252: case SEXPR_VALUE:
#####: 253: if (strchr(sexpr->value, ' '))
call 0 never executed
branch 1 never executed
branch 2 never executed
#####: 254: tmp = snprintf(buffer + ret, n_buffer - ret, "'%s'",
call 0 never executed
-: 255: sexpr->value);
-: 256: else
#####: 257: tmp = snprintf(buffer + ret, n_buffer - ret, "%s",
call 0 never executed
-: 258: sexpr->value);
#####: 259: if (tmp == 0)
branch 0 never executed
branch 1 never executed
#####: 260: goto error;
#####: 261: ret += tmp;
#####: 262: break;
-: 263: case SEXPR_NIL:
-: 264: break;
-: 265: default:
-: 266: goto error;
-: 267: }
-: 268:
#####: 269: return (ret);
#####: 270: error:
#####: 271: buffer[n_buffer - 1] = 0;
#####: 272: virSexprError(VIR_ERR_SEXPR_SERIAL, buffer);
call 0 never executed
#####: 273: return (0);
-: 274:}
-: 275:
-: 276:#define IS_SPACE(c) ((c == 0x20) || (c == 0x9) || (c == 0xD) || (c == 0xA))
-: 277:
-: 278:static const char *
-: 279:trim(const char *string)
function trim called 317 returned 100% blocks executed 100%
317: 280:{
683: 281: while (IS_SPACE(*string))
branch 0 taken 13%
branch 1 taken 87% (fallthrough)
branch 2 taken 0%
branch 3 taken 100% (fallthrough)
branch 4 taken 0%
branch 5 taken 100% (fallthrough)
49: 282: string++;
317: 283: return (string);
-: 284:}
-: 285:
-: 286:/**
-: 287: * _string2sexpr:
-: 288: * @buffer: a zero terminated buffer containing an S-Expression in UTF-8
-: 289: * @end: pointer to an index in the buffer for the already parsed bytes
-: 290: *
-: 291: * Internal routine implementing the parse of S-Expression
-: 292: * Note that failure in this function is catrosphic. If it returns
-: 293: * NULL, you've leaked memory and you're currently OOM. It will always
-: 294: * parse an SEXPR given a buffer
-: 295: *
-: 296: * Returns a pointer to the resulting parsed S-Expression, or NULL in case of
-: 297: * hard error.
-: 298: */
-: 299:static struct sexpr *
-: 300:_string2sexpr(const char *buffer, size_t * end)
function _string2sexpr called 135 returned 100% blocks executed 80%
135: 301:{
135: 302: const char *ptr = buffer + *end;
135: 303: struct sexpr *ret = sexpr_new();
call 0 returned 100%
-: 304:
135: 305: if (ret == NULL)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 306: return NULL;
-: 307:
135: 308: ptr = trim(ptr);
call 0 returned 100%
-: 309:
135: 310: if (ptr[0] == '(') {
branch 0 taken 36% (fallthrough)
branch 1 taken 64%
49: 311: ret->kind = SEXPR_NIL;
-: 312:
49: 313: ptr = trim(ptr + 1);
call 0 returned 100%
231: 314: while (*ptr && *ptr != ')') {
branch 0 taken 73%
branch 1 taken 27% (fallthrough)
-: 315: struct sexpr *tmp;
133: 316: size_t tmp_len = 0;
-: 317:
133: 318: tmp = _string2sexpr(ptr, &tmp_len);
call 0 returned 100%
133: 319: if (tmp == NULL)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 320: return NULL;
133: 321: append(ret, tmp);
call 0 returned 100%
-: 322:#if 0
-: 323: if (0) {
-: 324: char buf[4096];
-: 325:
-: 326: sexpr2string(ret, buf, sizeof(buf));
-: 327: printf("%s\n", buffer);
-: 328: }
-: 329:#endif
133: 330: ptr = trim(ptr + tmp_len);
call 0 returned 100%
-: 331: }
-: 332:
49: 333: if (*ptr == ')') {
branch 0 taken 100% (fallthrough)
branch 1 taken 0%
49: 334: ptr++;
-: 335: }
-: 336: } else {
-: 337: const char *start;
-: 338:
86: 339: if (*ptr == '\'') {
branch 0 taken 29% (fallthrough)
branch 1 taken 71%
25: 340: ptr++;
25: 341: start = ptr;
-: 342:
468: 343: while (*ptr && *ptr != '\'') {
branch 0 taken 94%
branch 1 taken 6% (fallthrough)
418: 344: if (*ptr == '\\' && ptr[1])
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
branch 2 never executed
branch 3 never executed
#####: 345: ptr++;
418: 346: ptr++;
-: 347: }
-: 348:
25: 349: ret->value = strndup(start, ptr - start);
call 0 returned 100%
25: 350: if (ret->value == NULL) {
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 351: virSexprError(VIR_ERR_NO_MEMORY,
call 0 never executed
-: 352: "failed to copy a string");
-: 353: }
-: 354:
25: 355: if (*ptr == '\'')
branch 0 taken 100% (fallthrough)
branch 1 taken 0%
25: 356: ptr++;
-: 357: } else {
61: 358: start = ptr;
-: 359:
413: 360: while (*ptr && !isspace(*ptr) && *ptr != ')' && *ptr != '(') {
branch 0 taken 100% (fallthrough)
branch 1 taken 0%
call 2 returned 100%
branch 3 taken 86% (fallthrough)
branch 4 taken 14%
branch 5 taken 96% (fallthrough)
branch 6 taken 4%
branch 7 taken 100%
branch 8 taken 0% (fallthrough)
291: 361: ptr++;
-: 362: }
-: 363:
61: 364: ret->value = strndup(start, ptr - start);
call 0 returned 100%
61: 365: if (ret->value == NULL) {
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 366: virSexprError(VIR_ERR_NO_MEMORY,
call 0 never executed
-: 367: "failed to copy a string");
-: 368: }
-: 369: }
-: 370:
86: 371: ret->kind = SEXPR_VALUE;
86: 372: if (ret->value == NULL)
branch 0 taken 100% (fallthrough)
branch 1 taken 0%
#####: 373: goto error;
-: 374: }
-: 375:
135: 376: *end = ptr - buffer;
-: 377:
135: 378: return ret;
-: 379:
#####: 380: error:
#####: 381: sexpr_free(ret);
call 0 never executed
#####: 382: return (NULL);
-: 383:}
-: 384:
-: 385:/**
-: 386: * string2sexpr:
-: 387: * @buffer: a zero terminated buffer containing an S-Expression in UTF-8
-: 388: *
-: 389: * Parse the S-Expression in the buffer.
-: 390: * Note that failure in this function is catrosphic. If it returns
-: 391: * NULL, you've leaked memory and you're currently OOM. It will always
-: 392: * parse an SEXPR given a buffer
-: 393: *
-: 394: * Returns a pointer to the resulting parsed S-Expression, or NULL in case of
-: 395: * hard error.
-: 396: */
-: 397:struct sexpr *
-: 398:string2sexpr(const char *buffer)
function string2sexpr called 2 returned 100% blocks executed 100%
2: 399:{
2: 400: size_t dummy = 0;
-: 401:
2: 402: return _string2sexpr(buffer, &dummy);
call 0 returned 100%
-: 403:}
-: 404:
-: 405:
-: 406:/**
-: 407: * sexpr_lookup:
-: 408: * @sexpr: a pointer to a parsed S-Expression
-: 409: * @node: a path for the sub expression to lookup in the S-Expression
-: 410: *
-: 411: * Search a sub expression in the S-Expression based on its path
-: 412: * NOTE: path are limited to 4096 bytes.
-: 413: *
-: 414: * Returns the pointer to the sub expression or NULL if not found.
-: 415: */
-: 416:struct sexpr *
-: 417:sexpr_lookup(struct sexpr *sexpr, const char *node)
function sexpr_lookup called 97 returned 100% blocks executed 38%
97: 418:{
-: 419: char buffer[4096], *ptr, *token;
-: 420:
97: 421: if ((node == NULL) || (sexpr == NULL))
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 422: return (NULL);
-: 423:
97: 424: snprintf(buffer, sizeof(buffer), "%s", node);
call 0 returned 100%
-: 425:
97: 426: ptr = buffer;
194: 427: token = strsep(&ptr, "/");
branch 0 taken 100% (fallthrough)
branch 1 taken 0%
branch 2 taken 100% (fallthrough)
branch 3 taken 0%
branch 4 never executed
branch 5 never executed
branch 6 never executed
branch 7 never executed
call 8 never executed
call 9 never executed
-: 428:
97: 429: if (sexpr->kind != SEXPR_CONS || sexpr->car->kind != SEXPR_VALUE) {
branch 0 taken 96% (fallthrough)
branch 1 taken 4%
branch 2 taken 0% (fallthrough)
branch 3 taken 100%
4: 430: return NULL;
-: 431: }
-: 432:
93: 433: if (strcmp(sexpr->car->value, token) != 0) {
call 0 returned 100%
branch 1 taken 43% (fallthrough)
branch 2 taken 57%
40: 434: return NULL;
-: 435: }
-: 436:
274: 437: for (token = strsep(&ptr, "/"); token; token = strsep(&ptr, "/")) {
branch 0 taken 100% (fallthrough)
branch 1 taken 0%
branch 2 taken 100% (fallthrough)
branch 3 taken 0%
branch 4 never executed
branch 5 never executed
branch 6 never executed
branch 7 never executed
call 8 never executed
call 9 never executed
branch 10 taken 100% (fallthrough)
branch 11 taken 0%
branch 12 taken 100% (fallthrough)
branch 13 taken 0%
branch 14 never executed
branch 15 never executed
branch 16 never executed
branch 17 never executed
call 18 never executed
call 19 never executed
branch 20 taken 71%
branch 21 taken 29% (fallthrough)
-: 438: struct sexpr *i;
-: 439:
97: 440: if (token == NULL)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 441: continue;
-: 442:
97: 443: sexpr = sexpr->cdr;
439: 444: for (i = sexpr; i->kind != SEXPR_NIL; i = i->cdr) {
branch 0 taken 97%
branch 1 taken 3% (fallthrough)
426: 445: if (i->kind != SEXPR_CONS ||
branch 0 taken 100% (fallthrough)
branch 1 taken 0%
branch 2 taken 100% (fallthrough)
branch 3 taken 0%
branch 4 taken 100% (fallthrough)
branch 5 taken 0%
-: 446: i->car->kind != SEXPR_CONS ||
-: 447: i->car->car->kind != SEXPR_VALUE) {
-: 448: continue;
-: 449: }
-: 450:
426: 451: if (strcmp(i->car->car->value, token) == 0) {
call 0 returned 100%
branch 1 taken 20% (fallthrough)
branch 2 taken 80%
84: 452: sexpr = i->car;
84: 453: break;
-: 454: }
-: 455: }
-: 456:
97: 457: if (i->kind == SEXPR_NIL) {
branch 0 taken 13% (fallthrough)
branch 1 taken 87%
13: 458: break;
-: 459: }
-: 460: }
-: 461:
53: 462: if (token != NULL) {
branch 0 taken 25% (fallthrough)
branch 1 taken 75%
13: 463: return NULL;
-: 464: }
-: 465:
40: 466: if (sexpr->kind != SEXPR_CONS || sexpr->cdr->kind != SEXPR_CONS)
branch 0 taken 100% (fallthrough)
branch 1 taken 0%
branch 2 taken 0% (fallthrough)
branch 3 taken 100%
#####: 467: return NULL;
-: 468:
40: 469: return sexpr->cdr;
-: 470:}
-: 471:
-: 472:/**
-: 473: * sexpr_node:
-: 474: * @sexpr: a pointer to a parsed S-Expression
-: 475: * @node: a path for the node to lookup in the S-Expression
-: 476: *
-: 477: * Search a node value in the S-Expression based on its path
-: 478: * NOTE: path are limited to 4096 bytes.
-: 479: *
-: 480: * Returns the value of the node or NULL if not found.
-: 481: */
-: 482:const char *
-: 483:sexpr_node(struct sexpr *sexpr, const char *node)
function sexpr_node called 45 returned 100% blocks executed 100%
45: 484:{
45: 485: struct sexpr *n = sexpr_lookup(sexpr, node);
call 0 returned 100%
-: 486:
45: 487: return (n && n->car->kind == SEXPR_VALUE) ? n->car->value : NULL;
branch 0 taken 76% (fallthrough)
branch 1 taken 24%
branch 2 taken 100% (fallthrough)
branch 3 taken 0%
-: 488:}