1 /*
2 * SPDX-License-Identifier: ISC
3 *
4 * Copyright (c) 2020 Robert Manner <robert.manner@oneidentity.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 /*
20 * This is an open source non-commercial project. Dear PVS-Studio, please check it.
21 * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
22 */
23
24 #include "iohelpers.h"
25
26 int
rmdir_recursive(const char * path)27 rmdir_recursive(const char *path)
28 {
29 char *cmd = NULL;
30 int success = false;
31
32 if (asprintf(&cmd, "rm -rf \"%s\"", path) < 0)
33 return false;
34
35 if (system(cmd) == 0)
36 success = true;
37
38 free(cmd);
39
40 return success;
41 }
42
43 int
fwriteall(const char * file_path,const char * string)44 fwriteall(const char *file_path, const char *string)
45 {
46 int success = false;
47
48 FILE *file = fopen(file_path, "w+");
49 if (file == NULL)
50 goto cleanup;
51
52 size_t size = strlen(string);
53 if (fwrite(string, 1, size, file) < size) {
54 goto cleanup;
55 }
56
57 success = true;
58
59 cleanup:
60 if (file)
61 fclose(file);
62
63 return success;
64 }
65
66 int
freadall(const char * file_path,char * output,size_t max_len)67 freadall(const char *file_path, char *output, size_t max_len)
68 {
69 int rc = false;
70 FILE *file = fopen(file_path, "rb");
71 if (file == NULL) {
72 printf("Failed to open file '%s'\n", file_path);
73 goto cleanup;
74 }
75
76 size_t len = fread(output, 1, max_len - 1, file);
77 output[len] = '\0';
78
79 if (ferror(file) != 0) {
80 printf("Failed to read file '%s' (Error %d)\n", file_path, ferror(file));
81 goto cleanup;
82 }
83
84 if (!feof(file)) {
85 printf("File '%s' was bigger than allocated buffer %zu", file_path, max_len);
86 goto cleanup;
87 }
88
89 rc = true;
90
91 cleanup:
92 if (file)
93 fclose(file);
94
95 return rc;
96 }
97
98 int
vsnprintf_append(char * output,size_t max_output_len,const char * fmt,va_list args)99 vsnprintf_append(char *output, size_t max_output_len, const char *fmt, va_list args)
100 {
101 va_list args2;
102 va_copy(args2, args);
103
104 size_t output_len = strlen(output);
105 int rc = vsnprintf(output + output_len, max_output_len - output_len, fmt, args2);
106
107 va_end(args2);
108 return rc;
109 }
110
111 int
snprintf_append(char * output,size_t max_output_len,const char * fmt,...)112 snprintf_append(char *output, size_t max_output_len, const char *fmt, ...)
113 {
114 va_list args;
115 va_start(args, fmt);
116 int rc = vsnprintf_append(output, max_output_len, fmt, args);
117 va_end(args);
118 return rc;
119 }
120
121 int
str_array_count(char ** str_array)122 str_array_count(char **str_array)
123 {
124 int result = 0;
125 for (; str_array[result] != NULL; ++result) {}
126 return result;
127 }
128
129 void
str_array_snprint(char * out_str,size_t max_len,char ** str_array,int array_len)130 str_array_snprint(char *out_str, size_t max_len, char **str_array, int array_len)
131 {
132 if (array_len < 0)
133 array_len = str_array_count(str_array);
134
135 for (int pos = 0; pos < array_len; ++pos) {
136 snprintf_append(out_str, max_len, "%s%s", pos > 0 ? ", " : "", str_array[pos]);
137 }
138 }
139
140 char *
str_replaced(const char * source,size_t dest_len,const char * old,const char * new)141 str_replaced(const char *source, size_t dest_len, const char *old, const char *new)
142 {
143 char *result = calloc(1, dest_len);
144 char *dest = result;
145 char *pos = NULL;
146 size_t old_len = strlen(old);
147
148 while ((pos = strstr(source, old)) != NULL) {
149 size_t len = snprintf(dest, dest_len,
150 "%.*s%s", (int)(pos - source), source, new);
151 if (len >= dest_len)
152 goto fail;
153
154 dest_len -= len;
155 dest += len;
156 source = pos + old_len;
157 }
158
159 if (strlcpy(dest, source, dest_len) >= dest_len)
160 goto fail;
161
162 return result;
163
164 fail:
165 free(result);
166 return strdup("str_replace_all failed, string too long");
167 }
168
169 void
str_replace_in_place(char * string,size_t max_length,const char * old,const char * new)170 str_replace_in_place(char *string, size_t max_length, const char *old, const char *new)
171 {
172 char *replaced = str_replaced(string, max_length, old, new);
173 strlcpy(string, replaced, max_length);
174 free(replaced);
175 }
176