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*)∈
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*)∈
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