xref: /OK3568_Linux_fs/u-boot/lib/avb/libavb/avb_util.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (C) 2016 The Android Open Source Project
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person
5*4882a593Smuzhiyun  * obtaining a copy of this software and associated documentation
6*4882a593Smuzhiyun  * files (the "Software"), to deal in the Software without
7*4882a593Smuzhiyun  * restriction, including without limitation the rights to use, copy,
8*4882a593Smuzhiyun  * modify, merge, publish, distribute, sublicense, and/or sell copies
9*4882a593Smuzhiyun  * of the Software, and to permit persons to whom the Software is
10*4882a593Smuzhiyun  * furnished to do so, subject to the following conditions:
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  * The above copyright notice and this permission notice shall be
13*4882a593Smuzhiyun  * included in all copies or substantial portions of the Software.
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*4882a593Smuzhiyun  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*4882a593Smuzhiyun  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18*4882a593Smuzhiyun  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19*4882a593Smuzhiyun  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20*4882a593Smuzhiyun  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21*4882a593Smuzhiyun  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*4882a593Smuzhiyun  * SOFTWARE.
23*4882a593Smuzhiyun  */
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #include <android_avb/avb_util.h>
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #include <stdarg.h>
28*4882a593Smuzhiyun 
avb_be32toh(uint32_t in)29*4882a593Smuzhiyun uint32_t avb_be32toh(uint32_t in) {
30*4882a593Smuzhiyun   uint8_t* d = (uint8_t*)&in;
31*4882a593Smuzhiyun   uint32_t ret;
32*4882a593Smuzhiyun   ret = ((uint32_t)d[0]) << 24;
33*4882a593Smuzhiyun   ret |= ((uint32_t)d[1]) << 16;
34*4882a593Smuzhiyun   ret |= ((uint32_t)d[2]) << 8;
35*4882a593Smuzhiyun   ret |= ((uint32_t)d[3]);
36*4882a593Smuzhiyun   return ret;
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun 
avb_be64toh(uint64_t in)39*4882a593Smuzhiyun uint64_t avb_be64toh(uint64_t in) {
40*4882a593Smuzhiyun   uint8_t* d = (uint8_t*)&in;
41*4882a593Smuzhiyun   uint64_t ret;
42*4882a593Smuzhiyun   ret = ((uint64_t)d[0]) << 56;
43*4882a593Smuzhiyun   ret |= ((uint64_t)d[1]) << 48;
44*4882a593Smuzhiyun   ret |= ((uint64_t)d[2]) << 40;
45*4882a593Smuzhiyun   ret |= ((uint64_t)d[3]) << 32;
46*4882a593Smuzhiyun   ret |= ((uint64_t)d[4]) << 24;
47*4882a593Smuzhiyun   ret |= ((uint64_t)d[5]) << 16;
48*4882a593Smuzhiyun   ret |= ((uint64_t)d[6]) << 8;
49*4882a593Smuzhiyun   ret |= ((uint64_t)d[7]);
50*4882a593Smuzhiyun   return ret;
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun /* Converts a 32-bit unsigned integer from host to big-endian byte order. */
avb_htobe32(uint32_t in)54*4882a593Smuzhiyun uint32_t avb_htobe32(uint32_t in) {
55*4882a593Smuzhiyun   union {
56*4882a593Smuzhiyun     uint32_t word;
57*4882a593Smuzhiyun     uint8_t bytes[4];
58*4882a593Smuzhiyun   } ret;
59*4882a593Smuzhiyun   ret.bytes[0] = (in >> 24) & 0xff;
60*4882a593Smuzhiyun   ret.bytes[1] = (in >> 16) & 0xff;
61*4882a593Smuzhiyun   ret.bytes[2] = (in >> 8) & 0xff;
62*4882a593Smuzhiyun   ret.bytes[3] = in & 0xff;
63*4882a593Smuzhiyun   return ret.word;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun /* Converts a 64-bit unsigned integer from host to big-endian byte order. */
avb_htobe64(uint64_t in)67*4882a593Smuzhiyun uint64_t avb_htobe64(uint64_t in) {
68*4882a593Smuzhiyun   union {
69*4882a593Smuzhiyun     uint64_t word;
70*4882a593Smuzhiyun     uint8_t bytes[8];
71*4882a593Smuzhiyun   } ret;
72*4882a593Smuzhiyun   ret.bytes[0] = (in >> 56) & 0xff;
73*4882a593Smuzhiyun   ret.bytes[1] = (in >> 48) & 0xff;
74*4882a593Smuzhiyun   ret.bytes[2] = (in >> 40) & 0xff;
75*4882a593Smuzhiyun   ret.bytes[3] = (in >> 32) & 0xff;
76*4882a593Smuzhiyun   ret.bytes[4] = (in >> 24) & 0xff;
77*4882a593Smuzhiyun   ret.bytes[5] = (in >> 16) & 0xff;
78*4882a593Smuzhiyun   ret.bytes[6] = (in >> 8) & 0xff;
79*4882a593Smuzhiyun   ret.bytes[7] = in & 0xff;
80*4882a593Smuzhiyun   return ret.word;
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun 
avb_safe_memcmp(const void * s1,const void * s2,size_t n)83*4882a593Smuzhiyun int avb_safe_memcmp(const void* s1, const void* s2, size_t n) {
84*4882a593Smuzhiyun   const unsigned char* us1 = s1;
85*4882a593Smuzhiyun   const unsigned char* us2 = s2;
86*4882a593Smuzhiyun   int result = 0;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun   if (0 == n) {
89*4882a593Smuzhiyun     return 0;
90*4882a593Smuzhiyun   }
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun   /*
93*4882a593Smuzhiyun    * Code snippet without data-dependent branch due to Nate Lawson
94*4882a593Smuzhiyun    * (nate@root.org) of Root Labs.
95*4882a593Smuzhiyun    */
96*4882a593Smuzhiyun   while (n--) {
97*4882a593Smuzhiyun     result |= *us1++ ^ *us2++;
98*4882a593Smuzhiyun   }
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun   return result != 0;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun 
avb_safe_add_to(uint64_t * value,uint64_t value_to_add)103*4882a593Smuzhiyun bool avb_safe_add_to(uint64_t* value, uint64_t value_to_add) {
104*4882a593Smuzhiyun   uint64_t original_value;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun   avb_assert(value != NULL);
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun   original_value = *value;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun   *value += value_to_add;
111*4882a593Smuzhiyun   if (*value < original_value) {
112*4882a593Smuzhiyun     avb_error("Overflow when adding values.\n");
113*4882a593Smuzhiyun     return false;
114*4882a593Smuzhiyun   }
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun   return true;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
avb_safe_add(uint64_t * out_result,uint64_t a,uint64_t b)119*4882a593Smuzhiyun bool avb_safe_add(uint64_t* out_result, uint64_t a, uint64_t b) {
120*4882a593Smuzhiyun   uint64_t dummy;
121*4882a593Smuzhiyun   if (out_result == NULL) {
122*4882a593Smuzhiyun     out_result = &dummy;
123*4882a593Smuzhiyun   }
124*4882a593Smuzhiyun   *out_result = a;
125*4882a593Smuzhiyun   return avb_safe_add_to(out_result, b);
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun 
avb_validate_utf8(const uint8_t * data,size_t num_bytes)128*4882a593Smuzhiyun bool avb_validate_utf8(const uint8_t* data, size_t num_bytes) {
129*4882a593Smuzhiyun   size_t n;
130*4882a593Smuzhiyun   unsigned int num_cc;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun   for (n = 0, num_cc = 0; n < num_bytes; n++) {
133*4882a593Smuzhiyun     uint8_t c = data[n];
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun     if (num_cc > 0) {
136*4882a593Smuzhiyun       if ((c & (0x80 | 0x40)) == 0x80) {
137*4882a593Smuzhiyun         /* 10xx xxxx */
138*4882a593Smuzhiyun       } else {
139*4882a593Smuzhiyun         goto fail;
140*4882a593Smuzhiyun       }
141*4882a593Smuzhiyun       num_cc--;
142*4882a593Smuzhiyun     } else {
143*4882a593Smuzhiyun       if (c < 0x80) {
144*4882a593Smuzhiyun         num_cc = 0;
145*4882a593Smuzhiyun       } else if ((c & (0x80 | 0x40 | 0x20)) == (0x80 | 0x40)) {
146*4882a593Smuzhiyun         /* 110x xxxx */
147*4882a593Smuzhiyun         num_cc = 1;
148*4882a593Smuzhiyun       } else if ((c & (0x80 | 0x40 | 0x20 | 0x10)) == (0x80 | 0x40 | 0x20)) {
149*4882a593Smuzhiyun         /* 1110 xxxx */
150*4882a593Smuzhiyun         num_cc = 2;
151*4882a593Smuzhiyun       } else if ((c & (0x80 | 0x40 | 0x20 | 0x10 | 0x08)) ==
152*4882a593Smuzhiyun                  (0x80 | 0x40 | 0x20 | 0x10)) {
153*4882a593Smuzhiyun         /* 1111 0xxx */
154*4882a593Smuzhiyun         num_cc = 3;
155*4882a593Smuzhiyun       } else {
156*4882a593Smuzhiyun         goto fail;
157*4882a593Smuzhiyun       }
158*4882a593Smuzhiyun     }
159*4882a593Smuzhiyun   }
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun   if (num_cc != 0) {
162*4882a593Smuzhiyun     goto fail;
163*4882a593Smuzhiyun   }
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun   return true;
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun fail:
168*4882a593Smuzhiyun   return false;
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun 
avb_str_concat(char * buf,size_t buf_size,const char * str1,size_t str1_len,const char * str2,size_t str2_len)171*4882a593Smuzhiyun bool avb_str_concat(char* buf,
172*4882a593Smuzhiyun                     size_t buf_size,
173*4882a593Smuzhiyun                     const char* str1,
174*4882a593Smuzhiyun                     size_t str1_len,
175*4882a593Smuzhiyun                     const char* str2,
176*4882a593Smuzhiyun                     size_t str2_len) {
177*4882a593Smuzhiyun   uint64_t combined_len;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun   if (!avb_safe_add(&combined_len, str1_len, str2_len)) {
180*4882a593Smuzhiyun     avb_error("Overflow when adding string sizes.\n");
181*4882a593Smuzhiyun     return false;
182*4882a593Smuzhiyun   }
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun   if (combined_len > buf_size - 1) {
185*4882a593Smuzhiyun     avb_error("Insufficient buffer space.\n");
186*4882a593Smuzhiyun     return false;
187*4882a593Smuzhiyun   }
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun   avb_memcpy(buf, str1, str1_len);
190*4882a593Smuzhiyun   avb_memcpy(buf + str1_len, str2, str2_len);
191*4882a593Smuzhiyun   buf[combined_len] = '\0';
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun   return true;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun 
avb_malloc(size_t size)196*4882a593Smuzhiyun void* avb_malloc(size_t size) {
197*4882a593Smuzhiyun   void* ret = avb_malloc_(size);
198*4882a593Smuzhiyun   if (ret == NULL) {
199*4882a593Smuzhiyun     avb_error("Failed to allocate memory.\n");
200*4882a593Smuzhiyun     return NULL;
201*4882a593Smuzhiyun   }
202*4882a593Smuzhiyun   return ret;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
avb_calloc(size_t size)205*4882a593Smuzhiyun void* avb_calloc(size_t size) {
206*4882a593Smuzhiyun   void* ret = avb_malloc(size);
207*4882a593Smuzhiyun   if (ret == NULL) {
208*4882a593Smuzhiyun     return NULL;
209*4882a593Smuzhiyun   }
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun   avb_memset(ret, '\0', size);
212*4882a593Smuzhiyun   return ret;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun 
avb_strdup(const char * str)215*4882a593Smuzhiyun char* avb_strdup(const char* str) {
216*4882a593Smuzhiyun   size_t len = avb_strlen(str);
217*4882a593Smuzhiyun   char* ret = avb_malloc(len + 1);
218*4882a593Smuzhiyun   if (ret == NULL) {
219*4882a593Smuzhiyun     return NULL;
220*4882a593Smuzhiyun   }
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun   avb_memcpy(ret, str, len);
223*4882a593Smuzhiyun   ret[len] = '\0';
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun   return ret;
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun 
avb_strstr(const char * haystack,const char * needle)228*4882a593Smuzhiyun const char* avb_strstr(const char* haystack, const char* needle) {
229*4882a593Smuzhiyun   size_t n, m;
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun   /* Look through |haystack| and check if the first character of
232*4882a593Smuzhiyun    * |needle| matches. If so, check the rest of |needle|.
233*4882a593Smuzhiyun    */
234*4882a593Smuzhiyun   for (n = 0; haystack[n] != '\0'; n++) {
235*4882a593Smuzhiyun     if (haystack[n] != needle[0]) {
236*4882a593Smuzhiyun       continue;
237*4882a593Smuzhiyun     }
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun     for (m = 1;; m++) {
240*4882a593Smuzhiyun       if (needle[m] == '\0') {
241*4882a593Smuzhiyun         return haystack + n;
242*4882a593Smuzhiyun       }
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun       if (haystack[n + m] != needle[m]) {
245*4882a593Smuzhiyun         break;
246*4882a593Smuzhiyun       }
247*4882a593Smuzhiyun     }
248*4882a593Smuzhiyun   }
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun   return NULL;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
avb_strv_find_str(const char * const * strings,const char * str,size_t str_size)253*4882a593Smuzhiyun const char* avb_strv_find_str(const char* const* strings,
254*4882a593Smuzhiyun                               const char* str,
255*4882a593Smuzhiyun                               size_t str_size) {
256*4882a593Smuzhiyun   size_t n;
257*4882a593Smuzhiyun   for (n = 0; strings[n] != NULL; n++) {
258*4882a593Smuzhiyun     if (avb_strlen(strings[n]) == str_size &&
259*4882a593Smuzhiyun         avb_memcmp(strings[n], str, str_size) == 0) {
260*4882a593Smuzhiyun       return strings[n];
261*4882a593Smuzhiyun     }
262*4882a593Smuzhiyun   }
263*4882a593Smuzhiyun   return NULL;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun 
avb_replace(const char * str,const char * search,const char * replace)266*4882a593Smuzhiyun char* avb_replace(const char* str, const char* search, const char* replace) {
267*4882a593Smuzhiyun   char* ret = NULL;
268*4882a593Smuzhiyun   size_t ret_len = 0;
269*4882a593Smuzhiyun   size_t search_len, replace_len;
270*4882a593Smuzhiyun   const char* str_after_last_replace;
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun   search_len = avb_strlen(search);
273*4882a593Smuzhiyun   replace_len = avb_strlen(replace);
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun   str_after_last_replace = str;
276*4882a593Smuzhiyun   while (*str != '\0') {
277*4882a593Smuzhiyun     const char* s;
278*4882a593Smuzhiyun     size_t num_before;
279*4882a593Smuzhiyun     size_t num_new;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun     s = avb_strstr(str, search);
282*4882a593Smuzhiyun     if (s == NULL) {
283*4882a593Smuzhiyun       break;
284*4882a593Smuzhiyun     }
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun     num_before = s - str;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun     if (ret == NULL) {
289*4882a593Smuzhiyun       num_new = num_before + replace_len + 1;
290*4882a593Smuzhiyun       ret = avb_malloc(num_new);
291*4882a593Smuzhiyun       if (ret == NULL) {
292*4882a593Smuzhiyun         goto out;
293*4882a593Smuzhiyun       }
294*4882a593Smuzhiyun       avb_memcpy(ret, str, num_before);
295*4882a593Smuzhiyun       avb_memcpy(ret + num_before, replace, replace_len);
296*4882a593Smuzhiyun       ret[num_new - 1] = '\0';
297*4882a593Smuzhiyun       ret_len = num_new - 1;
298*4882a593Smuzhiyun     } else {
299*4882a593Smuzhiyun       char* new_str;
300*4882a593Smuzhiyun       num_new = ret_len + num_before + replace_len + 1;
301*4882a593Smuzhiyun       new_str = avb_malloc(num_new);
302*4882a593Smuzhiyun       if (new_str == NULL) {
303*4882a593Smuzhiyun         goto out;
304*4882a593Smuzhiyun       }
305*4882a593Smuzhiyun       avb_memcpy(new_str, ret, ret_len);
306*4882a593Smuzhiyun       avb_memcpy(new_str + ret_len, str, num_before);
307*4882a593Smuzhiyun       avb_memcpy(new_str + ret_len + num_before, replace, replace_len);
308*4882a593Smuzhiyun       new_str[num_new - 1] = '\0';
309*4882a593Smuzhiyun       avb_free(ret);
310*4882a593Smuzhiyun       ret = new_str;
311*4882a593Smuzhiyun       ret_len = num_new - 1;
312*4882a593Smuzhiyun     }
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun     str = s + search_len;
315*4882a593Smuzhiyun     str_after_last_replace = str;
316*4882a593Smuzhiyun   }
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun   if (ret == NULL) {
319*4882a593Smuzhiyun     ret = avb_strdup(str_after_last_replace);
320*4882a593Smuzhiyun     if (ret == NULL) {
321*4882a593Smuzhiyun       goto out;
322*4882a593Smuzhiyun     }
323*4882a593Smuzhiyun   } else {
324*4882a593Smuzhiyun     size_t num_remaining = avb_strlen(str_after_last_replace);
325*4882a593Smuzhiyun     size_t num_new = ret_len + num_remaining + 1;
326*4882a593Smuzhiyun     char* new_str = avb_malloc(num_new);
327*4882a593Smuzhiyun     if (new_str == NULL) {
328*4882a593Smuzhiyun       goto out;
329*4882a593Smuzhiyun     }
330*4882a593Smuzhiyun     avb_memcpy(new_str, ret, ret_len);
331*4882a593Smuzhiyun     avb_memcpy(new_str + ret_len, str_after_last_replace, num_remaining);
332*4882a593Smuzhiyun     new_str[num_new - 1] = '\0';
333*4882a593Smuzhiyun     avb_free(ret);
334*4882a593Smuzhiyun     ret = new_str;
335*4882a593Smuzhiyun     ret_len = num_new - 1;
336*4882a593Smuzhiyun   }
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun out:
339*4882a593Smuzhiyun   return ret;
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun /* We only support a limited amount of strings in avb_strdupv(). */
343*4882a593Smuzhiyun #define AVB_STRDUPV_MAX_NUM_STRINGS 32
344*4882a593Smuzhiyun 
avb_strdupv(const char * str,...)345*4882a593Smuzhiyun char* avb_strdupv(const char* str, ...) {
346*4882a593Smuzhiyun   va_list ap;
347*4882a593Smuzhiyun   const char* strings[AVB_STRDUPV_MAX_NUM_STRINGS];
348*4882a593Smuzhiyun   size_t lengths[AVB_STRDUPV_MAX_NUM_STRINGS];
349*4882a593Smuzhiyun   size_t num_strings, n;
350*4882a593Smuzhiyun   uint64_t total_length;
351*4882a593Smuzhiyun   char *ret = NULL, *dest;
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun   num_strings = 0;
354*4882a593Smuzhiyun   total_length = 0;
355*4882a593Smuzhiyun   va_start(ap, str);
356*4882a593Smuzhiyun   do {
357*4882a593Smuzhiyun     size_t str_len = avb_strlen(str);
358*4882a593Smuzhiyun     strings[num_strings] = str;
359*4882a593Smuzhiyun     lengths[num_strings] = str_len;
360*4882a593Smuzhiyun     if (!avb_safe_add_to(&total_length, str_len)) {
361*4882a593Smuzhiyun       avb_fatal("Overflow while determining total length.\n");
362*4882a593Smuzhiyun       break;
363*4882a593Smuzhiyun     }
364*4882a593Smuzhiyun     num_strings++;
365*4882a593Smuzhiyun     if (num_strings == AVB_STRDUPV_MAX_NUM_STRINGS) {
366*4882a593Smuzhiyun       avb_fatal("Too many strings passed.\n");
367*4882a593Smuzhiyun       break;
368*4882a593Smuzhiyun     }
369*4882a593Smuzhiyun     str = va_arg(ap, const char*);
370*4882a593Smuzhiyun   } while (str != NULL);
371*4882a593Smuzhiyun   va_end(ap);
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun   ret = avb_malloc(total_length + 1);
374*4882a593Smuzhiyun   if (ret == NULL) {
375*4882a593Smuzhiyun     goto out;
376*4882a593Smuzhiyun   }
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun   dest = ret;
379*4882a593Smuzhiyun   for (n = 0; n < num_strings; n++) {
380*4882a593Smuzhiyun     avb_memcpy(dest, strings[n], lengths[n]);
381*4882a593Smuzhiyun     dest += lengths[n];
382*4882a593Smuzhiyun   }
383*4882a593Smuzhiyun   *dest = '\0';
384*4882a593Smuzhiyun   avb_assert(dest == ret + total_length);
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun out:
387*4882a593Smuzhiyun   return ret;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun 
avb_basename(const char * str)390*4882a593Smuzhiyun const char* avb_basename(const char* str) {
391*4882a593Smuzhiyun   int64_t n;
392*4882a593Smuzhiyun   size_t len;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun   len = avb_strlen(str);
395*4882a593Smuzhiyun   if (len >= 2) {
396*4882a593Smuzhiyun     for (n = len - 2; n >= 0; n--) {
397*4882a593Smuzhiyun       if (str[n] == '/') {
398*4882a593Smuzhiyun         return str + n + 1;
399*4882a593Smuzhiyun       }
400*4882a593Smuzhiyun     }
401*4882a593Smuzhiyun   }
402*4882a593Smuzhiyun   return str;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun 
avb_uppercase(char * str)405*4882a593Smuzhiyun void avb_uppercase(char* str) {
406*4882a593Smuzhiyun   size_t i;
407*4882a593Smuzhiyun   for (i = 0; str[i] != '\0'; ++i) {
408*4882a593Smuzhiyun     if (str[i] <= 0x7A && str[i] >= 0x61) {
409*4882a593Smuzhiyun       str[i] -= 0x20;
410*4882a593Smuzhiyun     }
411*4882a593Smuzhiyun   }
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun 
avb_bin2hex(const uint8_t * data,size_t data_len)414*4882a593Smuzhiyun char* avb_bin2hex(const uint8_t* data, size_t data_len) {
415*4882a593Smuzhiyun   const char hex_digits[17] = "0123456789abcdef";
416*4882a593Smuzhiyun   char* hex_data;
417*4882a593Smuzhiyun   size_t n;
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun   hex_data = avb_malloc(data_len * 2 + 1);
420*4882a593Smuzhiyun   if (hex_data == NULL) {
421*4882a593Smuzhiyun     return NULL;
422*4882a593Smuzhiyun   }
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun   for (n = 0; n < data_len; n++) {
425*4882a593Smuzhiyun     hex_data[n * 2] = hex_digits[data[n] >> 4];
426*4882a593Smuzhiyun     hex_data[n * 2 + 1] = hex_digits[data[n] & 0x0f];
427*4882a593Smuzhiyun   }
428*4882a593Smuzhiyun   hex_data[n * 2] = '\0';
429*4882a593Smuzhiyun   return hex_data;
430*4882a593Smuzhiyun }
431