Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0-only */
2 : : /*
3 : : * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
4 : : */
5 : :
6 : : #include "bpfilter/helper.h"
7 : :
8 : : #include <ctype.h>
9 : : #include <errno.h>
10 : : #include <fcntl.h>
11 : : #include <libgen.h>
12 : : #include <limits.h>
13 : : #include <stdio.h>
14 : : #include <stdlib.h>
15 : : #include <string.h>
16 : : #include <sys/types.h>
17 : : #include <unistd.h>
18 : :
19 : : #include "bpfilter/logger.h"
20 : :
21 : : #define OPEN_MODE_644 (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
22 : :
23 : 6481 : void closep(int *fd)
24 : : {
25 [ + + ]: 6481 : if (*fd < 0)
26 : : return;
27 : :
28 [ + + ]: 2650 : if (close(*fd))
29 [ + - ]: 2 : bf_warn_r(errno, "failed to close fd %d, assuming file is closed", *fd);
30 : :
31 : 2650 : *fd = -1;
32 : : }
33 : :
34 : 1034 : int bf_strncpy(char *dst, size_t len, const char *src)
35 : : {
36 : : size_t src_len;
37 : : size_t copy_len;
38 : :
39 : : assert(dst);
40 : : assert(src);
41 : : assert(len);
42 : :
43 : 1034 : src_len = strlen(src);
44 : 1034 : copy_len = bf_min(src_len, len - 1);
45 : :
46 : 1034 : memcpy(dst, src, copy_len);
47 : 1034 : dst[copy_len] = '\0';
48 : :
49 [ + + ]: 1034 : return copy_len != src_len ? -E2BIG : 0;
50 : : }
51 : :
52 : 1865 : int bf_realloc(void **ptr, size_t size)
53 : : {
54 : : _cleanup_free_ void *_ptr;
55 : :
56 : : assert(ptr);
57 : :
58 : 1865 : _ptr = realloc(*ptr, size);
59 [ + - ]: 1865 : if (!_ptr)
60 : : return -ENOMEM;
61 : :
62 : 1865 : *ptr = TAKE_PTR(_ptr);
63 : :
64 : 1865 : return 0;
65 : : }
66 : :
67 : 11 : int bf_read_file(const char *path, void **buf, size_t *len)
68 : : {
69 : 11 : _cleanup_close_ int fd = -1;
70 : : _cleanup_free_ void *_buf = NULL;
71 : : size_t _len;
72 : : ssize_t r;
73 : :
74 : : assert(path);
75 : : assert(buf);
76 : : assert(len);
77 : :
78 : 11 : fd = open(path, O_RDONLY);
79 [ + + ]: 11 : if (fd < 0)
80 [ + - ]: 1 : return bf_err_r(errno, "failed to open %s", path);
81 : :
82 : 10 : _len = lseek(fd, 0, SEEK_END);
83 : 10 : lseek(fd, 0, SEEK_SET);
84 : :
85 : 10 : _buf = malloc(_len);
86 [ - + ]: 10 : if (!_buf)
87 [ # # ]: 0 : return bf_err_r(errno, "failed to allocate memory");
88 : :
89 : 10 : r = read(fd, _buf, _len);
90 [ - + ]: 10 : if (r < 0)
91 [ # # ]: 0 : return bf_err_r(errno, "failed to read serialized data");
92 [ - + ]: 10 : if ((size_t)r != _len)
93 [ # # ]: 0 : return bf_err_r(EIO, "can't read full serialized data");
94 : :
95 : 10 : closep(&fd);
96 : :
97 : 10 : *buf = TAKE_PTR(_buf);
98 : 10 : *len = _len;
99 : :
100 : 10 : return 0;
101 : : }
102 : :
103 : 122 : static int _bf_get_tmpfile_fd(const char *base,
104 : : char tmpfile_path[static PATH_MAX])
105 : : {
106 : : _cleanup_free_ char *tmp = NULL;
107 : : size_t path_len;
108 : : char *dir;
109 : : int fd;
110 : :
111 : : /* The dirname call may modify its argument. */
112 : 122 : tmp = strdup(base);
113 [ - + ]: 122 : if (!tmp)
114 [ # # ]: 0 : return bf_err_r(ENOMEM, "could not duplicate path %s", base);
115 : :
116 : 122 : dir = dirname(tmp);
117 : :
118 : 122 : path_len =
119 : 122 : snprintf(tmpfile_path, PATH_MAX, "%s%s", dir, "/bpfilter.tmp.XXXXXX");
120 [ - + ]: 122 : if (path_len >= PATH_MAX)
121 [ # # ]: 0 : return bf_err_r(ENAMETOOLONG, "tmpfile name too long (%lu bytes)",
122 : : path_len);
123 : :
124 : 122 : fd = mkstemp(tmpfile_path);
125 [ - + ]: 122 : if (fd < 0)
126 [ # # ]: 0 : return bf_err_r(errno, "failed to open %s", tmpfile_path);
127 : :
128 : : return fd;
129 : : }
130 : :
131 : 122 : int bf_write_file(const char *path, const void *buf, size_t len)
132 : : {
133 : 122 : _cleanup_close_ int fd = -1;
134 : : ssize_t r;
135 : : int err;
136 : : char tmpfile_path[PATH_MAX];
137 : :
138 : : assert(path);
139 : : assert(buf);
140 : :
141 : 122 : fd = _bf_get_tmpfile_fd(path, tmpfile_path);
142 [ - + ]: 122 : if (fd < 0)
143 [ # # ]: 0 : return bf_err_r(fd, "failed to get temporary file name");
144 : :
145 : 122 : r = write(fd, buf, len);
146 [ - + ]: 122 : if (r < 0)
147 [ # # ]: 0 : return bf_err_r(errno, "failed to write to %s", tmpfile_path);
148 [ - + ]: 122 : if ((size_t)r != len)
149 [ # # ]: 0 : return bf_err_r(EIO, "can't write full data to %s", tmpfile_path);
150 : :
151 : 122 : closep(&fd);
152 : :
153 [ - + ]: 122 : if (rename(tmpfile_path, path) < 0) {
154 : 0 : err = errno;
155 : 0 : unlink(tmpfile_path);
156 [ # # ]: 0 : return bf_err_r(err, "failed to move %s to %s", tmpfile_path, path);
157 : : }
158 : :
159 : : return 0;
160 : : }
161 : :
162 : 951 : char *bf_ltrim(char *str)
163 : : {
164 : : assert(str);
165 : :
166 [ + + ]: 2736 : while (isspace(*str))
167 : 1785 : str++;
168 : 951 : return str;
169 : : }
170 : :
171 : 952 : char *bf_rtrim(char *str)
172 : : {
173 : : assert(str);
174 : :
175 : 952 : char *back = str + strlen(str);
176 : :
177 [ + + ]: 952 : if (back == str)
178 : : return str;
179 : :
180 : : do {
181 : 967 : --back;
182 [ + + + + ]: 967 : } while (back > str && isspace(*back));
183 : :
184 [ + + + + ]: 898 : if (back == str && isspace(*back))
185 : 1 : *back = '\0';
186 : : else
187 : 897 : *(back + 1) = '\0';
188 : :
189 : : return str;
190 : : }
191 : :
192 : 943 : char *bf_trim(char *str)
193 : : {
194 : : assert(str);
195 : :
196 : 943 : return bf_rtrim(bf_ltrim(str));
197 : : }
|