summaryrefslogtreecommitdiffstats
path: root/common/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/utils.c')
-rw-r--r--common/utils.c530
1 files changed, 0 insertions, 530 deletions
diff --git a/common/utils.c b/common/utils.c
deleted file mode 100644
index 58dac02..0000000
--- a/common/utils.c
+++ /dev/null
@@ -1,530 +0,0 @@
1/*
2 * utils.c
3 * Miscellaneous utilities for string manipulation,
4 * file I/O and plist helper.
5 *
6 * Copyright (c) 2014-2019 Nikias Bassen, All Rights Reserved.
7 * Copyright (c) 2013-2014 Martin Szulecki, All Rights Reserved.
8 * Copyright (c) 2013 Federico Mena Quintero
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25#ifdef HAVE_CONFIG_H
26#include <config.h>
27#endif
28
29#include <stdarg.h>
30#include <stdlib.h>
31#include <string.h>
32#include <time.h>
33#include <sys/time.h>
34#include <inttypes.h>
35#include <ctype.h>
36
37#include "utils.h"
38
39#ifndef HAVE_STPCPY
40/**
41 * Copy characters from one string into another
42 *
43 * @note: The strings should not overlap, as the behavior is undefined.
44 *
45 * @s1: The source string.
46 * @s2: The destination string.
47 *
48 * @return a pointer to the terminating `\0' character of @s1,
49 * or NULL if @s1 or @s2 is NULL.
50 */
51char *stpcpy(char *s1, const char *s2)
52{
53 if (s1 == NULL || s2 == NULL)
54 return NULL;
55
56 strcpy(s1, s2);
57
58 return s1 + strlen(s2);
59}
60#endif
61
62/**
63 * Concatenate strings into a newly allocated string
64 *
65 * @note: Specify NULL for the last string in the varargs list
66 *
67 * @str: The first string in the list
68 * @...: Subsequent strings. Use NULL for the last item.
69 *
70 * @return a newly allocated string, or NULL if @str is NULL. This will also
71 * return NULL and set errno to ENOMEM if memory is exhausted.
72 */
73char *string_concat(const char *str, ...)
74{
75 size_t len;
76 va_list args;
77 char *s;
78 char *result;
79 char *dest;
80
81 if (!str)
82 return NULL;
83
84 /* Compute final length */
85
86 len = strlen(str) + 1; /* plus 1 for the null terminator */
87
88 va_start(args, str);
89 s = va_arg(args, char *);
90 while (s) {
91 len += strlen(s);
92 s = va_arg(args, char*);
93 }
94 va_end(args);
95
96 /* Concat each string */
97
98 result = malloc(len);
99 if (!result)
100 return NULL; /* errno remains set */
101
102 dest = result;
103
104 dest = stpcpy(dest, str);
105
106 va_start(args, str);
107 s = va_arg(args, char *);
108 while (s) {
109 dest = stpcpy(dest, s);
110 s = va_arg(args, char *);
111 }
112 va_end(args);
113
114 return result;
115}
116
117char *string_append(char* str, ...)
118{
119 size_t len = 0;
120 size_t slen;
121 va_list args;
122 char *s;
123 char *result;
124 char *dest;
125
126 /* Compute final length */
127
128 if (str) {
129 len = strlen(str);
130 }
131 slen = len;
132 len++; /* plus 1 for the null terminator */
133
134 va_start(args, str);
135 s = va_arg(args, char *);
136 while (s) {
137 len += strlen(s);
138 s = va_arg(args, char*);
139 }
140 va_end(args);
141
142 result = realloc(str, len);
143 if (!result)
144 return NULL; /* errno remains set */
145
146 dest = result + slen;
147
148 /* Concat additional strings */
149
150 va_start(args, str);
151 s = va_arg(args, char *);
152 while (s) {
153 dest = stpcpy(dest, s);
154 s = va_arg(args, char *);
155 }
156 va_end(args);
157
158 return result;
159}
160
161char *string_build_path(const char *elem, ...)
162{
163 if (!elem)
164 return NULL;
165 va_list args;
166 int len = strlen(elem)+1;
167 va_start(args, elem);
168 char *arg = va_arg(args, char*);
169 while (arg) {
170 len += strlen(arg)+1;
171 arg = va_arg(args, char*);
172 }
173 va_end(args);
174
175 char* out = (char*)malloc(len);
176 strcpy(out, elem);
177
178 va_start(args, elem);
179 arg = va_arg(args, char*);
180 while (arg) {
181 strcat(out, "/");
182 strcat(out, arg);
183 arg = va_arg(args, char*);
184 }
185 va_end(args);
186 return out;
187}
188
189char *string_format_size(uint64_t size)
190{
191 char buf[80];
192 double sz;
193 if (size >= 1000000000000LL) {
194 sz = ((double)size / 1000000000000.0f);
195 sprintf(buf, "%0.1f TB", sz);
196 } else if (size >= 1000000000LL) {
197 sz = ((double)size / 1000000000.0f);
198 sprintf(buf, "%0.1f GB", sz);
199 } else if (size >= 1000000LL) {
200 sz = ((double)size / 1000000.0f);
201 sprintf(buf, "%0.1f MB", sz);
202 } else if (size >= 1000LL) {
203 sz = ((double)size / 1000.0f);
204 sprintf(buf, "%0.1f KB", sz);
205 } else {
206 sprintf(buf, "%d Bytes", (int)size);
207 }
208 return strdup(buf);
209}
210
211char *string_toupper(char* str)
212{
213 char *res = strdup(str);
214 unsigned int i;
215 for (i = 0; i < strlen(res); i++) {
216 res[i] = toupper(res[i]);
217 }
218 return res;
219}
220
221static int get_rand(int min, int max)
222{
223 int retval = (rand() % (max - min)) + min;
224 return retval;
225}
226
227char *generate_uuid()
228{
229 const char *chars = "ABCDEF0123456789";
230 int i = 0;
231 char *uuid = (char *) malloc(sizeof(char) * 37);
232
233 srand(time(NULL));
234
235 for (i = 0; i < 36; i++) {
236 if (i == 8 || i == 13 || i == 18 || i == 23) {
237 uuid[i] = '-';
238 continue;
239 } else {
240 uuid[i] = chars[get_rand(0, 16)];
241 }
242 }
243
244 /* make it a real string */
245 uuid[36] = '\0';
246
247 return uuid;
248}
249
250void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length)
251{
252 FILE *f;
253 uint64_t size;
254
255 *length = 0;
256
257 f = fopen(filename, "rb");
258 if (!f) {
259 return;
260 }
261
262 fseek(f, 0, SEEK_END);
263 size = ftell(f);
264 rewind(f);
265
266 if (size == 0) {
267 fclose(f);
268 return;
269 }
270
271 *buffer = (char*)malloc(sizeof(char)*(size+1));
272 if (fread(*buffer, sizeof(char), size, f) != size) {
273 fclose(f);
274 return;
275 }
276 fclose(f);
277
278 *length = size;
279}
280
281void buffer_write_to_filename(const char *filename, const char *buffer, uint64_t length)
282{
283 FILE *f;
284
285 f = fopen(filename, "wb");
286 if (f) {
287 fwrite(buffer, sizeof(char), length, f);
288 fclose(f);
289 }
290}
291
292int plist_read_from_filename(plist_t *plist, const char *filename)
293{
294 char *buffer = NULL;
295 uint64_t length;
296
297 if (!filename)
298 return 0;
299
300 buffer_read_from_filename(filename, &buffer, &length);
301
302 if (!buffer) {
303 return 0;
304 }
305
306 if ((length > 8) && (memcmp(buffer, "bplist00", 8) == 0)) {
307 plist_from_bin(buffer, length, plist);
308 } else {
309 plist_from_xml(buffer, length, plist);
310 }
311
312 free(buffer);
313
314 return 1;
315}
316
317int plist_write_to_filename(plist_t plist, const char *filename, enum plist_format_t format)
318{
319 char *buffer = NULL;
320 uint32_t length;
321
322 if (!plist || !filename)
323 return 0;
324
325 if (format == PLIST_FORMAT_XML)
326 plist_to_xml(plist, &buffer, &length);
327 else if (format == PLIST_FORMAT_BINARY)
328 plist_to_bin(plist, &buffer, &length);
329 else
330 return 0;
331
332 buffer_write_to_filename(filename, buffer, length);
333
334 free(buffer);
335
336 return 1;
337}
338
339static const char base64_str[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
340static const char base64_pad = '=';
341
342static char *base64encode(const unsigned char *buf, size_t size)
343{
344 if (!buf || !(size > 0)) return NULL;
345 int outlen = (size / 3) * 4;
346 char *outbuf = (char*)malloc(outlen+5); // 4 spare bytes + 1 for '\0'
347 size_t n = 0;
348 size_t m = 0;
349 unsigned char input[3];
350 unsigned int output[4];
351 while (n < size) {
352 input[0] = buf[n];
353 input[1] = (n+1 < size) ? buf[n+1] : 0;
354 input[2] = (n+2 < size) ? buf[n+2] : 0;
355 output[0] = input[0] >> 2;
356 output[1] = ((input[0] & 3) << 4) + (input[1] >> 4);
357 output[2] = ((input[1] & 15) << 2) + (input[2] >> 6);
358 output[3] = input[2] & 63;
359 outbuf[m++] = base64_str[(int)output[0]];
360 outbuf[m++] = base64_str[(int)output[1]];
361 outbuf[m++] = (n+1 < size) ? base64_str[(int)output[2]] : base64_pad;
362 outbuf[m++] = (n+2 < size) ? base64_str[(int)output[3]] : base64_pad;
363 n+=3;
364 }
365 outbuf[m] = 0; // 0-termination!
366 return outbuf;
367}
368
369static void plist_node_print_to_stream(plist_t node, int* indent_level, FILE* stream);
370
371static void plist_array_print_to_stream(plist_t node, int* indent_level, FILE* stream)
372{
373 /* iterate over items */
374 int i, count;
375 plist_t subnode = NULL;
376
377 count = plist_array_get_size(node);
378
379 for (i = 0; i < count; i++) {
380 subnode = plist_array_get_item(node, i);
381 fprintf(stream, "%*s", *indent_level, "");
382 fprintf(stream, "%d: ", i);
383 plist_node_print_to_stream(subnode, indent_level, stream);
384 }
385}
386
387static void plist_dict_print_to_stream(plist_t node, int* indent_level, FILE* stream)
388{
389 /* iterate over key/value pairs */
390 plist_dict_iter it = NULL;
391
392 char* key = NULL;
393 plist_t subnode = NULL;
394 plist_dict_new_iter(node, &it);
395 plist_dict_next_item(node, it, &key, &subnode);
396 while (subnode)
397 {
398 fprintf(stream, "%*s", *indent_level, "");
399 fprintf(stream, "%s", key);
400 if (plist_get_node_type(subnode) == PLIST_ARRAY)
401 fprintf(stream, "[%d]: ", plist_array_get_size(subnode));
402 else
403 fprintf(stream, ": ");
404 free(key);
405 key = NULL;
406 plist_node_print_to_stream(subnode, indent_level, stream);
407 plist_dict_next_item(node, it, &key, &subnode);
408 }
409 free(it);
410}
411
412static void plist_node_print_to_stream(plist_t node, int* indent_level, FILE* stream)
413{
414 char *s = NULL;
415 char *data = NULL;
416 double d;
417 uint8_t b;
418 uint64_t u = 0;
419 struct timeval tv = { 0, 0 };
420
421 plist_type t;
422
423 if (!node)
424 return;
425
426 t = plist_get_node_type(node);
427
428 switch (t) {
429 case PLIST_BOOLEAN:
430 plist_get_bool_val(node, &b);
431 fprintf(stream, "%s\n", (b ? "true" : "false"));
432 break;
433
434 case PLIST_UINT:
435 plist_get_uint_val(node, &u);
436 fprintf(stream, "%"PRIu64"\n", u);
437 break;
438
439 case PLIST_REAL:
440 plist_get_real_val(node, &d);
441 fprintf(stream, "%f\n", d);
442 break;
443
444 case PLIST_STRING:
445 plist_get_string_val(node, &s);
446 fprintf(stream, "%s\n", s);
447 free(s);
448 break;
449
450 case PLIST_KEY:
451 plist_get_key_val(node, &s);
452 fprintf(stream, "%s: ", s);
453 free(s);
454 break;
455
456 case PLIST_DATA:
457 plist_get_data_val(node, &data, &u);
458 if (u > 0) {
459 s = base64encode((unsigned char*)data, u);
460 free(data);
461 if (s) {
462 fprintf(stream, "%s\n", s);
463 free(s);
464 } else {
465 fprintf(stream, "\n");
466 }
467 } else {
468 fprintf(stream, "\n");
469 }
470 break;
471
472 case PLIST_DATE:
473 plist_get_date_val(node, (int32_t*)&tv.tv_sec, (int32_t*)&tv.tv_usec);
474 {
475 time_t ti = (time_t)tv.tv_sec + MAC_EPOCH;
476 struct tm *btime = localtime(&ti);
477 if (btime) {
478 s = (char*)malloc(24);
479 memset(s, 0, 24);
480 if (strftime(s, 24, "%Y-%m-%dT%H:%M:%SZ", btime) <= 0) {
481 free (s);
482 s = NULL;
483 }
484 }
485 }
486 if (s) {
487 fprintf(stream, "%s\n", s);
488 free(s);
489 } else {
490 fprintf(stream, "\n");
491 }
492 break;
493
494 case PLIST_ARRAY:
495 fprintf(stream, "\n");
496 (*indent_level)++;
497 plist_array_print_to_stream(node, indent_level, stream);
498 (*indent_level)--;
499 break;
500
501 case PLIST_DICT:
502 fprintf(stream, "\n");
503 (*indent_level)++;
504 plist_dict_print_to_stream(node, indent_level, stream);
505 (*indent_level)--;
506 break;
507
508 default:
509 break;
510 }
511}
512
513void plist_print_to_stream(plist_t plist, FILE* stream)
514{
515 int indent = 0;
516
517 if (!plist || !stream)
518 return;
519
520 switch (plist_get_node_type(plist)) {
521 case PLIST_DICT:
522 plist_dict_print_to_stream(plist, &indent, stream);
523 break;
524 case PLIST_ARRAY:
525 plist_array_print_to_stream(plist, &indent, stream);
526 break;
527 default:
528 plist_node_print_to_stream(plist, &indent, stream);
529 }
530}