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