Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2015 Intel Corporation.
3 : : * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES.
4 : : * All rights reserved.
5 : : */
6 : :
7 : : #include "spdk/stdinc.h"
8 : :
9 : : #include "spdk/string.h"
10 : :
11 : : char *
12 : 23461 : spdk_vsprintf_append_realloc(char *buffer, const char *format, va_list args)
13 : : {
14 : 8703 : va_list args_copy;
15 : : char *new_buffer;
16 : 23461 : int orig_size = 0, new_size;
17 : :
18 : : /* Original buffer size */
19 [ + + ]: 23461 : if (buffer) {
20 [ - + ]: 20 : orig_size = strlen(buffer);
21 : 5 : }
22 : :
23 : : /* Necessary buffer size */
24 : 23461 : va_copy(args_copy, args);
25 [ - + ]: 23461 : new_size = vsnprintf(NULL, 0, format, args_copy);
26 : 23461 : va_end(args_copy);
27 : :
28 [ + + ]: 23461 : if (new_size < 0) {
29 : 0 : return NULL;
30 : : }
31 [ + - + - ]: 23461 : new_size += orig_size + 1;
32 : :
33 : 23461 : new_buffer = realloc(buffer, new_size);
34 [ + + ]: 23461 : if (new_buffer == NULL) {
35 : 0 : return NULL;
36 : : }
37 : :
38 [ + + + - ]: 23461 : vsnprintf(new_buffer + orig_size, new_size - orig_size, format, args);
39 : :
40 : 23461 : return new_buffer;
41 : 3325 : }
42 : :
43 : : char *
44 : 28 : spdk_sprintf_append_realloc(char *buffer, const char *format, ...)
45 : : {
46 : 21 : va_list args;
47 : : char *ret;
48 : :
49 : 28 : va_start(args, format);
50 : 28 : ret = spdk_vsprintf_append_realloc(buffer, format, args);
51 : 28 : va_end(args);
52 : :
53 : 28 : return ret;
54 : : }
55 : :
56 : : char *
57 : 23433 : spdk_vsprintf_alloc(const char *format, va_list args)
58 : : {
59 : 23433 : return spdk_vsprintf_append_realloc(NULL, format, args);
60 : : }
61 : :
62 : : char *
63 : 11347 : spdk_sprintf_alloc(const char *format, ...)
64 : : {
65 : 5850 : va_list args;
66 : : char *ret;
67 : :
68 : 11347 : va_start(args, format);
69 : 11347 : ret = spdk_vsprintf_alloc(format, args);
70 : 11347 : va_end(args);
71 : :
72 : 11347 : return ret;
73 : : }
74 : :
75 : : char *
76 : 1102 : spdk_strlwr(char *s)
77 : : {
78 : : char *p;
79 : :
80 [ - + ]: 1102 : if (s == NULL) {
81 : 0 : return NULL;
82 : : }
83 : :
84 : 1102 : p = s;
85 [ + + # # ]: 48327 : while (*p != '\0') {
86 [ # # # # ]: 47225 : *p = tolower(*p);
87 [ # # ]: 47225 : p++;
88 : : }
89 : :
90 : 1102 : return s;
91 : 0 : }
92 : :
93 : : char *
94 : 8143 : spdk_strsepq(char **stringp, const char *delim)
95 : : {
96 : : char *p, *q, *r;
97 : 8143 : int quoted = 0, bslash = 0;
98 : :
99 [ + - ]: 8143 : p = *stringp;
100 [ + + ]: 8143 : if (p == NULL) {
101 : 186 : return NULL;
102 : : }
103 : :
104 : 7957 : r = q = p;
105 [ + + + + : 37272 : while (*q != '\0' && *q != '\n') {
+ - + + ]
106 : : /* eat quoted characters */
107 [ - + ]: 33137 : if (bslash) {
108 : 0 : bslash = 0;
109 [ # # # # : 0 : *r++ = *q++;
# # # # ]
110 : 0 : continue;
111 [ - + ]: 33137 : } else if (quoted) {
112 [ # # # # : 0 : if (quoted == '"' && *q == '\\') {
# # ]
113 : 0 : bslash = 1;
114 [ # # ]: 0 : q++;
115 : 0 : continue;
116 [ # # # # ]: 0 : } else if (*q == quoted) {
117 : 0 : quoted = 0;
118 [ # # ]: 0 : q++;
119 : 0 : continue;
120 : : }
121 [ # # # # : 0 : *r++ = *q++;
# # # # ]
122 : 0 : continue;
123 [ + + - + ]: 33137 : } else if (*q == '\\') {
124 : 0 : bslash = 1;
125 [ # # ]: 0 : q++;
126 : 0 : continue;
127 [ + - + + : 33137 : } else if (*q == '"' || *q == '\'') {
+ - - + ]
128 [ # # ]: 0 : quoted = *q;
129 [ # # ]: 0 : q++;
130 : 0 : continue;
131 : : }
132 : :
133 : : /* separator? */
134 [ + + + + : 33137 : if (strchr(delim, *q) == NULL) {
- + ]
135 [ + - + - : 29315 : *r++ = *q++;
+ - + - ]
136 : 29315 : continue;
137 : : }
138 : :
139 : : /* new string */
140 [ # # ]: 3822 : q++;
141 : 3822 : break;
142 : : }
143 [ + - ]: 7957 : *r = '\0';
144 : :
145 : : /* skip tailer */
146 [ + + - + : 7957 : while (*q != '\0' && strchr(delim, *q) != NULL) {
- + # # -
+ ]
147 [ # # ]: 0 : q++;
148 : : }
149 [ + + - + ]: 7957 : if (*q != '\0') {
150 [ # # ]: 3597 : *stringp = q;
151 : 99 : } else {
152 [ + - ]: 4360 : *stringp = NULL;
153 : : }
154 : :
155 : 7957 : return p;
156 : 247 : }
157 : :
158 : : char *
159 : 3924 : spdk_str_trim(char *s)
160 : : {
161 : : char *p, *q;
162 : :
163 [ - + ]: 3924 : if (s == NULL) {
164 : 0 : return NULL;
165 : : }
166 : :
167 : : /* remove header */
168 : 3924 : p = s;
169 [ + + - + : 3924 : while (*p != '\0' && isspace(*p)) {
# # # # #
# # # #
# ]
170 [ # # ]: 0 : p++;
171 : : }
172 : :
173 : : /* remove tailer */
174 [ - + # # ]: 3924 : q = p + strlen(p);
175 [ + + + + : 33230 : while (q - 1 >= p && isspace(*(q - 1))) {
# # # # #
# # # # #
# # ]
176 [ # # ]: 29306 : q--;
177 [ # # ]: 29306 : *q = '\0';
178 : : }
179 : :
180 : : /* if remove header, move */
181 [ + + ]: 3924 : if (p != s) {
182 : 0 : q = s;
183 [ # # # # ]: 0 : while (*p != '\0') {
184 [ # # # # : 0 : *q++ = *p++;
# # # # ]
185 : : }
186 [ # # ]: 0 : *q = '\0';
187 : 0 : }
188 : :
189 : 3924 : return s;
190 : 138 : }
191 : :
192 : : void
193 : 111526 : spdk_strcpy_pad(void *dst, const char *src, size_t size, int pad)
194 : : {
195 : : size_t len;
196 : :
197 [ + + ]: 111526 : len = strlen(src);
198 [ + + ]: 111526 : if (len < size) {
199 [ + + + + ]: 107704 : memcpy(dst, src, len);
200 [ + + + - ]: 107704 : memset((char *)dst + len, pad, size - len);
201 : 10224 : } else {
202 [ - + - + ]: 3822 : memcpy(dst, src, size);
203 : : }
204 : 111526 : }
205 : :
206 : : size_t
207 : 130 : spdk_strlen_pad(const void *str, size_t size, int pad)
208 : : {
209 : : const uint8_t *start;
210 : : const uint8_t *iter;
211 : : uint8_t pad_byte;
212 : :
213 : 130 : pad_byte = (uint8_t)pad;
214 : 130 : start = (const uint8_t *)str;
215 : :
216 [ + + ]: 130 : if (size == 0) {
217 : 0 : return 0;
218 : : }
219 : :
220 [ # # # # ]: 130 : iter = start + size - 1;
221 : 2 : while (1) {
222 [ + + # # ]: 16841 : if (*iter != pad_byte) {
223 [ # # ]: 130 : return iter - start + 1;
224 : : }
225 : :
226 [ - + ]: 16711 : if (iter == start) {
227 : : /* Hit the start of the string finding only pad_byte. */
228 : 0 : return 0;
229 : : }
230 [ # # ]: 16711 : iter--;
231 : : }
232 : 2 : }
233 : :
234 : : int
235 : 20 : spdk_parse_ip_addr(char *ip, char **host, char **port)
236 : : {
237 : : char *p;
238 : :
239 [ - + ]: 20 : if (ip == NULL) {
240 : 0 : return -EINVAL;
241 : : }
242 : :
243 [ # # ]: 20 : *host = NULL;
244 [ # # ]: 20 : *port = NULL;
245 : :
246 [ + + # # : 20 : if (ip[0] == '[') {
# # ]
247 : : /* IPv6 */
248 [ - + ]: 12 : p = strchr(ip, ']');
249 [ + + ]: 12 : if (p == NULL) {
250 : 0 : return -EINVAL;
251 : : }
252 [ # # # # ]: 12 : *host = &ip[1];
253 [ # # ]: 12 : *p = '\0';
254 : :
255 [ # # ]: 12 : p++;
256 [ + + # # ]: 12 : if (*p == '\0') {
257 : 4 : return 0;
258 [ - + # # ]: 8 : } else if (*p != ':') {
259 : 0 : return -EINVAL;
260 : : }
261 : :
262 [ # # ]: 8 : p++;
263 [ + + # # ]: 8 : if (*p == '\0') {
264 : 4 : return 0;
265 : : }
266 : :
267 [ # # ]: 4 : *port = p;
268 : 1 : } else {
269 : : /* IPv4 */
270 [ - + ]: 8 : p = strchr(ip, ':');
271 [ + + ]: 8 : if (p == NULL) {
272 [ # # ]: 4 : *host = ip;
273 : 4 : return 0;
274 : : }
275 : :
276 [ # # ]: 4 : *host = ip;
277 [ # # ]: 4 : *p = '\0';
278 : :
279 [ # # ]: 4 : p++;
280 [ + + # # ]: 4 : if (*p == '\0') {
281 : 0 : return 0;
282 : : }
283 : :
284 [ # # ]: 4 : *port = p;
285 : : }
286 : :
287 : 8 : return 0;
288 : 5 : }
289 : :
290 : : size_t
291 : 170 : spdk_str_chomp(char *s)
292 : : {
293 [ - + ]: 170 : size_t len = strlen(s);
294 : 170 : size_t removed = 0;
295 : :
296 [ + + ]: 206 : while (len > 0) {
297 [ + + + + : 198 : if (s[len - 1] != '\r' && s[len - 1] != '\n') {
# # # # #
# # # ]
298 : 162 : break;
299 : : }
300 : :
301 [ # # # # ]: 36 : s[len - 1] = '\0';
302 : 36 : len--;
303 : 36 : removed++;
304 : : }
305 : :
306 : 170 : return removed;
307 : : }
308 : :
309 : : void
310 : 1087 : spdk_strerror_r(int errnum, char *buf, size_t buflen)
311 : : {
312 : : int rc;
313 : :
314 : : #if defined(__USE_GNU)
315 : : char *new_buffer;
316 [ + + ]: 1048 : new_buffer = strerror_r(errnum, buf, buflen);
317 [ + + ]: 1048 : if (new_buffer == buf) {
318 : 62 : rc = 0;
319 [ + - ]: 986 : } else if (new_buffer != NULL) {
320 [ - + ]: 986 : snprintf(buf, buflen, "%s", new_buffer);
321 : 986 : rc = 0;
322 : 1 : } else {
323 : 0 : rc = 1;
324 : : }
325 : : #else
326 : 39 : rc = strerror_r(errnum, buf, buflen);
327 : : #endif
328 : :
329 [ + + ]: 1087 : if (rc != 0) {
330 [ # # ]: 20 : snprintf(buf, buflen, "Unknown error %d", errnum);
331 : 20 : }
332 : 1087 : }
333 : :
334 : : int
335 : 753 : spdk_parse_capacity(const char *cap_str, uint64_t *cap, bool *has_prefix)
336 : : {
337 : : int rc;
338 : 248 : char bin_prefix;
339 : :
340 : 753 : rc = sscanf(cap_str, "%"SCNu64"%c", cap, &bin_prefix);
341 [ + + ]: 753 : if (rc == 1) {
342 [ + + ]: 668 : if (has_prefix != NULL) {
343 [ + - ]: 154 : *has_prefix = false;
344 : 40 : }
345 : 668 : return 0;
346 [ + + ]: 85 : } else if (rc == 0) {
347 [ + + # # ]: 8 : if (errno == 0) {
348 : : /* No scanf matches - the string does not start with a digit */
349 : 4 : return -EINVAL;
350 : : } else {
351 : : /* Parsing error */
352 [ # # # # ]: 4 : return -errno;
353 : : }
354 : : }
355 : :
356 [ + + ]: 77 : if (has_prefix != NULL) {
357 [ # # ]: 32 : *has_prefix = true;
358 : 8 : }
359 : :
360 [ + + + + ]: 77 : switch (bin_prefix) {
361 : 42 : case 'k':
362 : : case 'K':
363 [ # # ]: 46 : *cap *= 1024;
364 : 46 : break;
365 : 24 : case 'm':
366 : : case 'M':
367 [ # # ]: 27 : *cap *= 1024 * 1024;
368 : 27 : break;
369 : 3 : case 'g':
370 : : case 'G':
371 [ # # ]: 4 : *cap *= 1024 * 1024 * 1024;
372 : 4 : break;
373 : 0 : default:
374 : 0 : return -EINVAL;
375 : : }
376 : :
377 : 77 : return 0;
378 : 70 : }
379 : :
380 : : bool
381 : 223424 : spdk_mem_all_zero(const void *data, size_t size)
382 : : {
383 : 223424 : const uint8_t *buf = data;
384 : :
385 [ + + ]: 453664905 : while (size--) {
386 [ + + + - : 453446142 : if (*buf++ != 0) {
+ + ]
387 : 4661 : return false;
388 : : }
389 : : }
390 : :
391 : 218763 : return true;
392 : 4541 : }
393 : :
394 : : long int
395 : 7677 : spdk_strtol(const char *nptr, int base)
396 : : {
397 : : long val;
398 : 1036 : char *endptr;
399 : :
400 : : /* Since strtoll() can legitimately return 0, LONG_MAX, or LONG_MIN
401 : : * on both success and failure, the calling program should set errno
402 : : * to 0 before the call.
403 : : */
404 [ + - ]: 7677 : errno = 0;
405 : :
406 [ + + ]: 7677 : val = strtol(nptr, &endptr, base);
407 : :
408 [ + + + + : 7677 : if (!errno && *endptr != '\0') {
+ - + + ]
409 : : /* Non integer character was found. */
410 : 77 : return -EINVAL;
411 [ + + + + : 7600 : } else if (errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) {
+ - # # ]
412 : : /* Overflow occurred. */
413 : 8 : return -ERANGE;
414 [ + + + + : 7592 : } else if (errno != 0 && val == 0) {
# # ]
415 : : /* Other error occurred. */
416 [ # # # # ]: 7 : return -errno;
417 [ + + ]: 7585 : } else if (val < 0) {
418 : : /* Input string was negative number. */
419 : 16 : return -ERANGE;
420 : : }
421 : :
422 : 7569 : return val;
423 : 1823 : }
424 : :
425 : : long long int
426 : 3719 : spdk_strtoll(const char *nptr, int base)
427 : : {
428 : : long long val;
429 : 349 : char *endptr;
430 : :
431 : : /* Since strtoll() can legitimately return 0, LLONG_MAX, or LLONG_MIN
432 : : * on both success and failure, the calling program should set errno
433 : : * to 0 before the call.
434 : : */
435 [ + - ]: 3719 : errno = 0;
436 : :
437 [ + + ]: 3719 : val = strtoll(nptr, &endptr, base);
438 : :
439 [ + + + + : 3719 : if (!errno && *endptr != '\0') {
+ - + - ]
440 : : /* Non integer character was found. */
441 : 11 : return -EINVAL;
442 [ + + + + : 3708 : } else if (errno == ERANGE && (val == LLONG_MAX || val == LLONG_MIN)) {
+ - # # ]
443 : : /* Overflow occurred. */
444 : 8 : return -ERANGE;
445 [ + + + + : 3700 : } else if (errno != 0 && val == 0) {
# # ]
446 : : /* Other error occurred. */
447 [ # # # # ]: 6 : return -errno;
448 [ + + ]: 3694 : } else if (val < 0) {
449 : : /* Input string was negative number. */
450 : 8 : return -ERANGE;
451 : : }
452 : :
453 : 3686 : return val;
454 : 113 : }
455 : :
456 : : void
457 : 4230 : spdk_strarray_free(char **strarray)
458 : : {
459 : : size_t i;
460 : :
461 [ + + ]: 4230 : if (strarray == NULL) {
462 : 4173 : return;
463 : : }
464 : :
465 [ + + + - : 199 : for (i = 0; strarray[i] != NULL; i++) {
+ + ]
466 [ + - + - ]: 142 : free(strarray[i]);
467 : 29 : }
468 : 57 : free(strarray);
469 : 231 : }
470 : :
471 : : char **
472 : 53 : spdk_strarray_from_string(const char *str, const char *delim)
473 : : {
474 : 53 : const char *c = str;
475 : 53 : size_t count = 0;
476 : : char **result;
477 : : size_t i;
478 : :
479 [ + + # # ]: 53 : assert(str != NULL);
480 [ + + # # ]: 53 : assert(delim != NULL);
481 : :
482 : : /* Count number of entries. */
483 : 79 : for (;;) {
484 [ + + + + ]: 122 : const char *next = strpbrk(c, delim);
485 : :
486 : 122 : count++;
487 : :
488 [ + + ]: 122 : if (next == NULL) {
489 : 53 : break;
490 : : }
491 : :
492 [ + - ]: 69 : c = next + 1;
493 : : }
494 : :
495 : : /* Account for the terminating NULL entry. */
496 : 53 : result = calloc(count + 1, sizeof(char *));
497 [ + + ]: 53 : if (result == NULL) {
498 : 0 : return NULL;
499 : : }
500 : :
501 : 53 : c = str;
502 : :
503 [ + + ]: 175 : for (i = 0; i < count; i++) {
504 [ + + + + ]: 122 : const char *next = strpbrk(c, delim);
505 : :
506 [ + + ]: 122 : if (next == NULL) {
507 [ + + + - : 53 : result[i] = strdup(c);
+ - ]
508 : 10 : } else {
509 [ + + + - : 69 : result[i] = strndup(c, next - c);
+ - ]
510 : : }
511 : :
512 [ + + + - : 122 : if (result[i] == NULL) {
- + ]
513 : 0 : spdk_strarray_free(result);
514 : 0 : return NULL;
515 : : }
516 : :
517 [ + + ]: 122 : if (next != NULL) {
518 [ + - ]: 69 : c = next + 1;
519 : 14 : }
520 : 24 : }
521 : :
522 : 53 : return result;
523 : 10 : }
524 : :
525 : : char **
526 : 46 : spdk_strarray_dup(const char **strarray)
527 : : {
528 : : size_t count, i;
529 : : char **result;
530 : :
531 [ + + # # ]: 46 : assert(strarray != NULL);
532 : :
533 [ + + + - : 150 : for (count = 0; strarray[count] != NULL; count++)
+ + ]
534 : : ;
535 : :
536 : 46 : result = calloc(count + 1, sizeof(char *));
537 [ + + ]: 46 : if (result == NULL) {
538 : 0 : return NULL;
539 : : }
540 : :
541 [ + + ]: 150 : for (i = 0; i < count; i++) {
542 [ + + + - : 104 : result[i] = strdup(strarray[i]);
+ - + - +
- ]
543 [ + + + - : 104 : if (result[i] == NULL) {
- + ]
544 : 0 : spdk_strarray_free(result);
545 : 0 : return NULL;
546 : : }
547 : 13 : }
548 : :
549 : 46 : return result;
550 : 5 : }
551 : :
552 : : int
553 : 84 : spdk_strcpy_replace(char *dst, size_t size, const char *src, const char *search,
554 : : const char *replace)
555 : : {
556 : : const char *p, *q;
557 : : char *r;
558 : : size_t c, search_size, replace_size, dst_size;
559 : :
560 [ + + + - : 84 : if (dst == NULL || src == NULL || search == NULL || replace == NULL) {
+ - - + ]
561 : 4 : return -EINVAL;
562 : : }
563 : :
564 [ - + ]: 80 : search_size = strlen(search);
565 [ - + ]: 80 : replace_size = strlen(replace);
566 : :
567 : 80 : c = 0;
568 [ + + - + : 148 : for (p = strstr(src, search); p != NULL; p = strstr(p + search_size, search)) {
- + - + +
+ # # ]
569 : 68 : c++;
570 : 11 : }
571 : :
572 [ - + ]: 80 : dst_size = strlen(src) + (replace_size - search_size) * c;
573 [ + + ]: 80 : if (dst_size >= size) {
574 : 4 : return -EINVAL;
575 : : }
576 : :
577 : 76 : q = src;
578 : 76 : r = dst;
579 : :
580 [ + + - + : 140 : for (p = strstr(src, search); p != NULL; p = strstr(p + search_size, search)) {
- + - + +
+ # # ]
581 [ - + - + ]: 64 : memcpy(r, q, p - q);
582 [ # # ]: 64 : r += p - q;
583 : :
584 [ - + - + ]: 64 : memcpy(r, replace, replace_size);
585 [ # # ]: 64 : r += replace_size;
586 : :
587 [ # # ]: 64 : q = p + search_size;
588 : 10 : }
589 : :
590 [ - + - + : 76 : memcpy(r, q, strlen(q));
- + ]
591 [ - + # # ]: 76 : r += strlen(q);
592 : :
593 [ # # ]: 76 : *r = '\0';
594 : :
595 : 76 : return 0;
596 : 9 : }
|