1 /*
2 *
3 * Copyright (C) 2007 Uwe Hermann <[email protected]>
4 * Copyright (C) 2008 Advanced Micro Devices, Inc.
5 * Copyright (C) 2010 coresystems GmbH
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include <libpayload.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include <inttypes.h>
35 #include <limits.h>
36 #include <errno.h>
37
38 /**
39 * Calculate the length of a fixed-size string.
40 *
41 * @param str The input string.
42 * @param maxlen Return at most maxlen characters as length of the string.
43 * @return The length of the string, not including the final NUL character.
44 * The maximum length returned is maxlen.
45 */
strnlen(const char * str,size_t maxlen)46 size_t strnlen(const char *str, size_t maxlen)
47 {
48 size_t len = 0;
49
50 /* NULL and empty strings have length 0. */
51 if (!str)
52 return 0;
53
54 /* Loop until we find a NUL character, or maxlen is reached. */
55 while ((*str++ != '\0') && (len < maxlen))
56 len++;
57
58 return len;
59 }
60
61 /**
62 * Calculate the length of a string.
63 *
64 * @param str The input string.
65 * @return The length of the string, not including the final NUL character.
66 */
strlen(const char * str)67 size_t strlen(const char *str)
68 {
69 size_t len = 0;
70
71 /* NULL and empty strings have length 0. */
72 if (!str)
73 return 0;
74
75 /* Loop until we find a NUL character. */
76 while (*str++ != '\0')
77 len++;
78
79 return len;
80 }
81
82 /**
83 * Compare two strings.
84 *
85 * @param s1 The first string.
86 * @param s2 The second string.
87 * @return Returns a value less than zero, if s1 is shorter than s2. Returns
88 * zero, if s1 equals s2. Returns a value greater than zero, if
89 * s1 is longer than s2.
90 */
strcasecmp(const char * s1,const char * s2)91 int strcasecmp(const char *s1, const char *s2)
92 {
93 int res;
94
95 for (size_t i = 0; 1; i++) {
96 res = tolower(s1[i]) - tolower(s2[i]);
97 if (res || (s1[i] == '\0'))
98 break;
99 }
100
101 return res;
102 }
103
104 /**
105 * Compare two strings with fixed length.
106 *
107 * @param s1 The first string.
108 * @param s2 The second string.
109 * @param maxlen Return at most maxlen characters as length of the string.
110 * @return A non-zero value if s1 and s2 differ, or zero if s1 equals s2.
111 */
strncasecmp(const char * s1,const char * s2,size_t maxlen)112 int strncasecmp(const char *s1, const char *s2, size_t maxlen)
113 {
114 int res = 0;
115
116 for (size_t i = 0; i < maxlen; i++) {
117 res = tolower(s1[i]) - tolower(s2[i]);
118 if (res || (s1[i] == '\0'))
119 break;
120 }
121
122 return res;
123 }
124
125 /**
126 * Compare two strings.
127 *
128 * @param s1 The first string.
129 * @param s2 The second string.
130 * @return Returns a value less than zero, if s1 is shorter than s2. Returns
131 * zero, if s1 equals s2. Returns a value greater than zero, if
132 * s1 is longer than s2.
133 */
strcmp(const char * s1,const char * s2)134 int strcmp(const char *s1, const char *s2)
135 {
136 int res;
137
138 for (size_t i = 0; 1; i++) {
139 res = s1[i] - s2[i];
140 if (res || (s1[i] == '\0'))
141 break;
142 }
143
144 return res;
145 }
146
147 /**
148 * Compare two strings with fixed length.
149 *
150 * @param s1 The first string.
151 * @param s2 The second string.
152 * @param maxlen Return at most maxlen characters as length of the string.
153 * @return A non-zero value if s1 and s2 differ, or zero if s1 equals s2.
154 */
strncmp(const char * s1,const char * s2,size_t maxlen)155 int strncmp(const char *s1, const char *s2, size_t maxlen)
156 {
157 int res = 0;
158
159 for (size_t i = 0; i < maxlen; i++) {
160 res = s1[i] - s2[i];
161 if (res || (s1[i] == '\0'))
162 break;
163 }
164
165 return res;
166 }
167
168 /**
169 * Copy a string with a maximum length.
170 *
171 * @param d The destination memory.
172 * @param s The source string.
173 * @param n Copy at most n characters as length of the string.
174 * @return A pointer to the destination memory.
175 */
strncpy(char * d,const char * s,size_t n)176 char *strncpy(char *d, const char *s, size_t n)
177 {
178 /* Use +1 to get the NUL terminator. */
179 size_t max = n > strlen(s) + 1 ? strlen(s) + 1 : n;
180
181 for (size_t i = 0; i < max; i++)
182 d[i] = (char)s[i];
183
184 return d;
185 }
186
187 /**
188 * Copy a string.
189 *
190 * @param d The destination memory.
191 * @param s The source string.
192 * @return A pointer to the destination memory.
193 */
strcpy(char * d,const char * s)194 char *strcpy(char *d, const char *s)
195 {
196 return strncpy(d, s, strlen(s) + 1);
197 }
198
199 /**
200 * Concatenates two strings
201 *
202 * @param d The destination string.
203 * @param s The source string.
204 * @return A pointer to the destination string.
205 */
strcat(char * d,const char * s)206 char *strcat(char *d, const char *s)
207 {
208 char *p = d + strlen(d);
209 size_t sl = strlen(s);
210
211 for (size_t i = 0; i < sl; i++)
212 p[i] = s[i];
213
214 p[sl] = '\0';
215 return d;
216 }
217
218 /**
219 * Concatenates two strings with a maximum length.
220 *
221 * @param d The destination string.
222 * @param s The source string.
223 * @param n Not more than n characters from s will be appended to d.
224 * @return A pointer to the destination string.
225 */
strncat(char * d,const char * s,size_t n)226 char *strncat(char *d, const char *s, size_t n)
227 {
228 char *p = d + strlen(d);
229 size_t sl = strlen(s);
230 size_t max = n > sl ? sl : n;
231
232 for (size_t i = 0; i < max; i++)
233 p[i] = s[i];
234
235 p[max] = '\0';
236 return d;
237 }
238
239 /**
240 * Concatenates two strings with a maximum length.
241 *
242 * @param d The destination string.
243 * @param s The source string.
244 * @param n d will have at most n-1 characters (plus NUL) after invocation.
245 * @return The total length of the concatenated string.
246 */
strlcat(char * d,const char * s,size_t n)247 size_t strlcat(char *d, const char *s, size_t n)
248 {
249 size_t sl = strlen(s);
250 size_t dl = strlen(d);
251
252 if (n <= dl + 1)
253 return sl + dl;
254
255 char *p = d + dl;
256 size_t max = n > (sl + dl) ? sl : (n - dl - 1);
257
258 for (size_t i = 0; i < max; i++)
259 p[i] = s[i];
260
261 p[max] = '\0';
262 return sl + dl;
263 }
264
265 /**
266 * Find a character in a string.
267 *
268 * @param s The string.
269 * @param c The character.
270 * @return A pointer to the first occurrence of the character in the
271 * string, or NULL if the character was not encountered within the string.
272 */
strchr(const char * s,int c)273 char *strchr(const char *s, int c)
274 {
275 char *p = (char *)s;
276
277 for (; *p != 0; p++) {
278 if (*p == c)
279 return p;
280 }
281
282 return NULL;
283 }
284
285 /**
286 * Find a character in a string.
287 *
288 * @param s The string.
289 * @param c The character.
290 * @return A pointer to the last occurrence of the character in the
291 * string, or NULL if the character was not encountered within the string.
292 */
293
strrchr(const char * s,int c)294 char *strrchr(const char *s, int c)
295 {
296 char *p = (char *)s + strlen(s);
297
298 for (; p >= s; p--) {
299 if (*p == c)
300 return p;
301 }
302
303 return NULL;
304 }
305
306 /**
307 * Duplicate a string.
308 *
309 * @param s The string to duplicate.
310 * @return A pointer to the copy of the original string.
311 */
strdup(const char * s)312 char *strdup(const char *s)
313 {
314 size_t n = strlen(s);
315 char *p = malloc(n + 1);
316
317 if (p != NULL) {
318 strncpy(p, s, n);
319 p[n] = 0;
320 }
321 return p;
322 }
323
324 /**
325 * Duplicate a string with a max length of size
326 *
327 * @param s The string to duplicate.
328 * @param size The max length of the string
329 * @return A pointer to the copy of the original string.
330 */
strndup(const char * s,size_t size)331 char *strndup(const char *s, size_t size)
332 {
333 size_t n = strnlen(s, size);
334 char *p = malloc(n + 1);
335
336 if (p != NULL) {
337 strncpy(p, s, n);
338 p[n] = 0;
339 }
340 return p;
341 }
342
343 /**
344 * Find a substring within a string.
345 *
346 * @param h The haystack string.
347 * @param n The needle string (substring).
348 * @return A pointer to the first occurrence of the substring in
349 * the string, or NULL if the substring was not encountered within the string.
350 */
strstr(const char * h,const char * n)351 char *strstr(const char *h, const char *n)
352 {
353 size_t hn = strlen(h);
354 size_t nn = strlen(n);
355
356 if (hn < nn)
357 return NULL;
358
359 for (size_t i = 0; i <= hn - nn; i++)
360 if (!memcmp(&h[i], n, nn))
361 return (char *)&h[i];
362
363 return NULL;
364 }
365
366 /**
367 * Separate strings.
368 *
369 * @param stringp reference of the string to separate.
370 * @param delim string containing all delimiters.
371 * @return Token string.
372 */
strsep(char ** stringp,const char * delim)373 char *strsep(char **stringp, const char *delim)
374 {
375 char *walk, *token;
376
377 if (!stringp || !*stringp || !**stringp)
378 return NULL;
379
380 token = walk = *stringp;
381
382 /* Walk, search for delimiters */
383 while (*walk && !strchr(delim, *walk))
384 walk++;
385
386 if (*walk) {
387 /* NUL terminate */
388 *walk = '\0';
389 walk++;
390 }
391
392 *stringp = walk;
393
394 return token;
395 }
396
397 /* Check that a character is in the valid range for the
398 given base
399 */
400
_valid(char ch,int base)401 static int _valid(char ch, int base)
402 {
403 char end = (base > 9) ? '9' : '0' + (base - 1);
404
405 /* all bases will be some subset of the 0-9 range */
406
407 if (ch >= '0' && ch <= end)
408 return 1;
409
410 /* Bases > 11 will also have to match in the a-z range */
411
412 if (base > 11) {
413 if (tolower(ch) >= 'a' &&
414 tolower(ch) <= 'a' + (base - 11))
415 return 1;
416 }
417
418 return 0;
419 }
420
421 /* Return the "value" of the character in the given base */
422
_offset(char ch,int base)423 static int _offset(char ch, int base)
424 {
425 if (ch >= '0' && ch <= '9')
426 return ch - '0';
427 else
428 return 10 + tolower(ch) - 'a';
429 }
430
431 /**
432 * Convert the initial portion of a string into a signed int
433 * @param ptr A pointer to the string to convert
434 * @param endptr A pointer to the unconverted part of the string
435 * @param base The base of the number to convert, or 0 for auto
436 * @return A signed integer representation of the string
437 */
438
strtoll(const char * orig_ptr,char ** endptr,int base)439 long long int strtoll(const char *orig_ptr, char **endptr, int base)
440 {
441 const char *ptr = orig_ptr;
442 int is_negative = 0;
443
444 /* Purge whitespace */
445
446 for ( ; *ptr && isspace(*ptr); ptr++);
447
448 if (ptr[0] == '-') {
449 is_negative = 1;
450 ptr++;
451 }
452
453 unsigned long long uval = strtoull(ptr, endptr, base);
454
455 /* If the whole string is unparseable, endptr should point to start. */
456 if (endptr && *endptr == ptr)
457 *endptr = (char *)orig_ptr;
458
459 if (uval > (unsigned long long)LLONG_MAX + !!is_negative)
460 uval = (unsigned long long)LLONG_MAX + !!is_negative;
461
462 if (is_negative)
463 return -uval;
464 else
465 return uval;
466 }
467
strtol(const char * ptr,char ** endptr,int base)468 long int strtol(const char *ptr, char **endptr, int base)
469 {
470 long long int val = strtoll(ptr, endptr, base);
471 if (val > LONG_MAX)
472 return LONG_MAX;
473 if (val < LONG_MIN)
474 return LONG_MIN;
475 return val;
476 }
477
atol(const char * nptr)478 long atol(const char *nptr)
479 {
480 return strtol(nptr, NULL, 10);
481 }
482
483 /**
484 * Convert the initial portion of a string into an unsigned int
485 * @param ptr A pointer to the string to convert
486 * @param endptr A pointer to the unconverted part of the string
487 * @param base The base of the number to convert, or 0 for auto
488 * @return An unsigned integer representation of the string
489 */
490
strtoull(const char * ptr,char ** endptr,int base)491 unsigned long long int strtoull(const char *ptr, char **endptr, int base)
492 {
493 unsigned long long int ret = 0;
494
495 if (endptr != NULL)
496 *endptr = (char *) ptr;
497
498 /* Purge whitespace */
499
500 for ( ; *ptr && isspace(*ptr); ptr++);
501
502 if (!*ptr)
503 return 0;
504
505 /* Determine the base */
506
507 if (base == 0) {
508 if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X'))
509 base = 16;
510 else if (ptr[0] == '0') {
511 base = 8;
512 ptr++;
513 } else {
514 base = 10;
515 }
516 }
517
518 /* Base 16 allows the 0x on front - so skip over it */
519
520 if (base == 16) {
521 if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X') &&
522 _valid(ptr[2], base))
523 ptr += 2;
524 }
525
526 for ( ; *ptr && _valid(*ptr, base); ptr++)
527 ret = (ret * base) + _offset(*ptr, base);
528
529 if (endptr != NULL)
530 *endptr = (char *) ptr;
531
532 return ret;
533 }
534
strtoul(const char * ptr,char ** endptr,int base)535 unsigned long int strtoul(const char *ptr, char **endptr, int base)
536 {
537 unsigned long long val = strtoull(ptr, endptr, base);
538 if (val > ULONG_MAX)
539 return ULONG_MAX;
540 return val;
541 }
542
543 /**
544 * Determine the number of leading characters in s that match characters in a
545 * @param s A pointer to the string to analyse
546 * @param a A pointer to an array of characters that match the prefix
547 * @return The number of matching characters
548 */
strspn(const char * s,const char * a)549 size_t strspn(const char *s, const char *a)
550 {
551 size_t i;
552 size_t al = strlen(a);
553 for (i = 0; s[i] != 0; i++) {
554 int found = 0;
555 for (size_t j = 0; j < al; j++) {
556 if (s[i] == a[j]) {
557 found = 1;
558 break;
559 }
560 }
561 if (!found)
562 break;
563 }
564 return i;
565 }
566
567 /**
568 * Determine the number of leading characters in s that do not match characters in a
569 * @param s A pointer to the string to analyse
570 * @param a A pointer to an array of characters that do not match the prefix
571 * @return The number of not matching characters
572 */
strcspn(const char * s,const char * a)573 size_t strcspn(const char *s, const char *a)
574 {
575 size_t i;
576 size_t al = strlen(a);
577 for (i = 0; s[i] != 0; i++) {
578 int found = 0;
579 for (size_t j = 0; j < al; j++) {
580 if (s[i] == a[j]) {
581 found = 1;
582 break;
583 }
584 }
585 if (found)
586 break;
587 }
588 return i;
589 }
590
591 /**
592 * Extract first token in string str that is delimited by a character in tokens.
593 * Destroys str and eliminates the token delimiter.
594 * @param str A pointer to the string to tokenize.
595 * @param delim A pointer to an array of characters that delimit the token
596 * @param ptr A pointer to a string pointer to keep state of the tokenizer
597 * @return Pointer to token
598 */
strtok_r(char * str,const char * delim,char ** ptr)599 char *strtok_r(char *str, const char *delim, char **ptr)
600 {
601 /* start new tokenizing job or continue existing one? */
602 if (str == NULL)
603 str = *ptr;
604
605 /* skip over prefix delimiters */
606 char *start = str + strspn(str, delim);
607
608 if (start[0] == '\0')
609 return NULL;
610
611 /* find first delimiter character */
612 char *end = start + strcspn(start, delim);
613 *ptr = end;
614 if (end[0] != '\0')
615 *(*ptr)++ = '\0';
616
617 return start;
618 }
619
620 /**
621 * Extract first token in string str that is delimited by a character in tokens.
622 * Destroys str, eliminates the token delimiter and uses global state.
623 * @param str A pointer to the string to tokenize.
624 * @param delim A pointer to an array of characters that delimit the token
625 * @return Pointer to token
626 */
strtok(char * str,const char * delim)627 char *strtok(char *str, const char *delim)
628 {
629 static char *strtok_ptr;
630
631 return strtok_r(str, delim, &strtok_ptr);
632 }
633
634 /**
635 * Print error message and error number
636 * @param s Error message to print
637 */
perror(const char * s)638 void perror(const char *s)
639 {
640 printf("%s: %d\n", s?s:"(none)", errno);
641 }
642
643 /**
644 * Get a message string describing the given error number.
645 *
646 * @param errnum The error number to be interpreted
647 * @return A pointer to a string describing the given error number
648 */
strerror(int errnum)649 char *strerror(int errnum)
650 {
651 /* Reserve enough space for the string below + INT64_MIN in decimal + \0 */
652 static char errstr[35];
653 snprintf(errstr, sizeof(errstr), "Unknown error %d", errnum);
654 return errstr;
655 }
656
657 /*
658 * Simple routine to convert UTF-16 to ASCII, giving up with ? if too high.
659 * A single code point may convert to ?? if not in the BMP.
660 * @param utf16_string A string encoded in UTF-16LE
661 * @param maxlen Maximum possible length of the string in code points
662 * @return Newly allocated ASCII string
663 */
utf16le_to_ascii(const uint16_t * utf16_string,size_t maxlen)664 char *utf16le_to_ascii(const uint16_t *utf16_string, size_t maxlen)
665 {
666 char *ascii_string = xmalloc(maxlen + 1); /* +1 for trailing \0 */
667 ascii_string[maxlen] = '\0';
668 for (size_t i = 0; i < maxlen; i++) {
669 uint16_t wchar = utf16_string[i];
670 ascii_string[i] = wchar > 0x7f ? '?' : (char)wchar;
671 }
672 return ascii_string;
673 }
674