Branch data Line data Source code
1 : : /* Declarations for common convenience functions.
2 : : Copyright (C) 2006-2011 Red Hat, Inc.
3 : : Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
4 : : Copyright (C) 2023 Khem Raj.
5 : : This file is part of elfutils.
6 : :
7 : : This file is free software; you can redistribute it and/or modify
8 : : it under the terms of either
9 : :
10 : : * the GNU Lesser General Public License as published by the Free
11 : : Software Foundation; either version 3 of the License, or (at
12 : : your option) any later version
13 : :
14 : : or
15 : :
16 : : * the GNU General Public License as published by the Free
17 : : Software Foundation; either version 2 of the License, or (at
18 : : your option) any later version
19 : :
20 : : or both in parallel, as here.
21 : :
22 : : elfutils is distributed in the hope that it will be useful, but
23 : : WITHOUT ANY WARRANTY; without even the implied warranty of
24 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 : : General Public License for more details.
26 : :
27 : : You should have received copies of the GNU General Public License and
28 : : the GNU Lesser General Public License along with this program. If
29 : : not, see <http://www.gnu.org/licenses/>. */
30 : :
31 : : #ifndef LIB_SYSTEM_H
32 : : #define LIB_SYSTEM_H 1
33 : :
34 : : /* Prevent double inclusion of config.h, config.h includes eu-config.h. */
35 : : #ifdef HAVE_CONFIG_H
36 : : #ifndef EU_CONFIG_H
37 : : # include <config.h>
38 : : #endif
39 : : #endif
40 : :
41 : : #include <errno.h>
42 : : #include <stdbool.h>
43 : : #include <stddef.h>
44 : : #include <stdint.h>
45 : : #include <string.h>
46 : : #include <stdarg.h>
47 : : #include <stdlib.h>
48 : :
49 : : /* System dependent headers */
50 : : #include <byteswap.h>
51 : : #include <endian.h>
52 : : #include <sys/mman.h>
53 : : #include <sys/param.h>
54 : : #include <unistd.h>
55 : :
56 : : #if defined(HAVE_ERROR_H)
57 : : #include <error.h>
58 : : #elif defined(HAVE_ERR_H)
59 : : extern int error_message_count;
60 : : void error(int status, int errnum, const char *format, ...);
61 : : #else
62 : : #error "err.h or error.h must be available"
63 : : #endif
64 : :
65 : : /* error (EXIT_FAILURE, ...) should be noreturn but on some systems it
66 : : isn't. This may cause warnings about code that should not be reachable.
67 : : So have an explicit error_exit wrapper that is noreturn (because it
68 : : calls exit explicitly). */
69 : : #define error_exit(errnum,...) do { \
70 : : error (EXIT_FAILURE,errnum,__VA_ARGS__); \
71 : : exit (EXIT_FAILURE); \
72 : : } while (0)
73 : :
74 : : #if BYTE_ORDER == LITTLE_ENDIAN
75 : : # define LE32(n) (n)
76 : : # define LE64(n) (n)
77 : : # define BE32(n) bswap_32 (n)
78 : : # define BE64(n) bswap_64 (n)
79 : : #elif BYTE_ORDER == BIG_ENDIAN
80 : : # define BE32(n) (n)
81 : : # define BE64(n) (n)
82 : : # define LE32(n) bswap_32 (n)
83 : : # define LE64(n) bswap_64 (n)
84 : : #else
85 : : # error "Unknown byte order"
86 : : #endif
87 : :
88 : : #ifndef MAX
89 : : #define MAX(m, n) ((m) < (n) ? (n) : (m))
90 : : #endif
91 : :
92 : : #ifndef MIN
93 : : #define MIN(m, n) ((m) < (n) ? (m) : (n))
94 : : #endif
95 : :
96 : : #if !HAVE_DECL_POWEROF2
97 : : #define powerof2(x) (((x) & ((x) - 1)) == 0)
98 : : #endif
99 : :
100 : : #if !HAVE_DECL_MEMPCPY
101 : : #define mempcpy(dest, src, n) \
102 : : ((void *) ((char *) memcpy (dest, src, n) + (size_t) n))
103 : : #endif
104 : :
105 : : #if !HAVE_DECL_REALLOCARRAY
106 : : static inline void *
107 : : reallocarray (void *ptr, size_t nmemb, size_t size)
108 : : {
109 : : if (size > 0 && nmemb > SIZE_MAX / size)
110 : : {
111 : : errno = ENOMEM;
112 : : return NULL;
113 : : }
114 : : return realloc (ptr, nmemb * size);
115 : : }
116 : : #endif
117 : :
118 : : /* Return TRUE if the start of STR matches PREFIX, FALSE otherwise. */
119 : :
120 : : static inline int
121 : 13872498 : startswith (const char *str, const char *prefix)
122 : : {
123 : 13872498 : return strncmp (str, prefix, strlen (prefix)) == 0;
124 : : }
125 : :
126 : : /* Return TRUE if STR[FROM] is a valid string with a zero terminator
127 : : at or before STR[TO - 1]. Note FROM is an index into the STR
128 : : array, while TO is the maximum size of the STR array. This
129 : : function returns FALSE when TO is zero or FROM >= TO. */
130 : : static inline bool
131 : 11874034 : validate_str (const char *str, size_t from, size_t to)
132 : : {
133 : : #if HAVE_DECL_MEMRCHR
134 : : // Check end first, which is likely a zero terminator,
135 : : // to prevent function call
136 : 11874034 : return (to > 0
137 [ + # - + ]: 11874034 : && (str[to - 1] == '\0'
138 [ # # ]: 0 : || (to > from
139 [ # # ]: 0 : && memrchr (&str[from], '\0', to - from - 1) != NULL)));
140 : : #else
141 : : do {
142 : : if (to <= from)
143 : : return false;
144 : :
145 : : to--;
146 : : } while (str[to]);
147 : :
148 : : return true;
149 : : #endif
150 : : }
151 : :
152 : : /* A special gettext function we use if the strings are too short. */
153 : : #define sgettext(Str) \
154 : : ({ const char *__res = strrchr (_(Str), '|'); \
155 : : __res ? __res + 1 : Str; })
156 : :
157 : : #define gettext_noop(Str) Str
158 : :
159 : : #ifndef TEMP_FAILURE_RETRY
160 : : #define TEMP_FAILURE_RETRY(expression) \
161 : : ({ ssize_t __res; \
162 : : do \
163 : : __res = expression; \
164 : : while (__res == -1 && errno == EINTR); \
165 : : __res; })
166 : : #endif
167 : :
168 : : #ifndef ACCESSPERMS
169 : : #define ACCESSPERMS (S_IRWXU|S_IRWXG|S_IRWXO) /* 0777 */
170 : : #endif
171 : :
172 : : #ifndef ALLPERMS
173 : : #define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO) /* 07777 */
174 : : #endif
175 : :
176 : : #ifndef DEFFILEMODE
177 : : #define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)/* 0666 */
178 : : #endif
179 : :
180 : : static inline ssize_t __attribute__ ((unused))
181 : 2124234 : pwrite_retry (int fd, const void *buf, size_t len, off_t off)
182 : : {
183 : 2124234 : ssize_t recvd = 0;
184 : :
185 : 2124234 : do
186 : : {
187 [ - + - - ]: 2124234 : ssize_t ret = TEMP_FAILURE_RETRY (pwrite (fd, ((char *)buf) + recvd, len - recvd,
188 : : off + recvd));
189 [ + + ]: 2124234 : if (ret <= 0)
190 [ + - ]: 496 : return ret < 0 ? ret : recvd;
191 : :
192 : 2123738 : recvd += ret;
193 : : }
194 [ - + ]: 2123738 : while ((size_t) recvd < len);
195 : :
196 : : return recvd;
197 : : }
198 : :
199 : : static inline ssize_t __attribute__ ((unused))
200 : 180 : write_retry (int fd, const void *buf, size_t len)
201 : : {
202 : 180 : ssize_t recvd = 0;
203 : :
204 : 180 : do
205 : : {
206 [ - + - - ]: 180 : ssize_t ret = TEMP_FAILURE_RETRY (write (fd, ((char *)buf) + recvd, len - recvd));
207 [ - + ]: 180 : if (ret <= 0)
208 [ # # ]: 0 : return ret < 0 ? ret : recvd;
209 : :
210 : 180 : recvd += ret;
211 : : }
212 [ - + ]: 180 : while ((size_t) recvd < len);
213 : :
214 : : return recvd;
215 : : }
216 : :
217 : : static inline ssize_t __attribute__ ((unused))
218 : 1511086 : pread_retry (int fd, void *buf, size_t len, off_t off)
219 : : {
220 : 1511086 : ssize_t recvd = 0;
221 : :
222 : 1521112 : do
223 : : {
224 [ + + - + : 3042224 : ssize_t ret = TEMP_FAILURE_RETRY (pread (fd, ((char *)buf) + recvd, len - recvd,
- - ]
225 : : off + recvd));
226 [ + + ]: 1521112 : if (ret <= 0)
227 [ + - ]: 10038 : return ret < 0 ? ret : recvd;
228 : :
229 : 1511074 : recvd += ret;
230 : : }
231 [ + + ]: 1511074 : while ((size_t) recvd < len);
232 : :
233 : : return recvd;
234 : : }
235 : :
236 : : /* The demangler from libstdc++. */
237 : : extern char *__cxa_demangle (const char *mangled_name, char *output_buffer,
238 : : size_t *length, int *status);
239 : :
240 : : /* A static assertion. This will cause a compile-time error if EXPR,
241 : : which must be a compile-time constant, is false. */
242 : :
243 : : #define eu_static_assert(expr) \
244 : : extern int never_defined_just_used_for_checking[(expr) ? 1 : -1] \
245 : : __attribute__ ((unused))
246 : :
247 : : /* We really want a basename implementation that doesn't modify the
248 : : input argument. Normally you get that from string.h with _GNU_SOURCE
249 : : define. But some libc implementations don't define it and other
250 : : define it, but provide an implementation that still modifies the
251 : : argument. So define our own and poison a bare basename symbol. */
252 : : static inline const char *
253 : 22296 : xbasename(const char *s)
254 : : {
255 : 22296 : const char *p = strrchr(s, '/');
256 [ + + ]: 22296 : return p ? p+1 : s;
257 : : }
258 : : #pragma GCC poison basename
259 : :
260 : : #endif /* system.h */
|