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 : : #include <config.h>
35 : :
36 : : #include <errno.h>
37 : : #include <stdbool.h>
38 : : #include <stddef.h>
39 : : #include <stdint.h>
40 : : #include <string.h>
41 : : #include <stdarg.h>
42 : : #include <stdlib.h>
43 : :
44 : : /* System dependent headers */
45 : : #include <byteswap.h>
46 : : #include <endian.h>
47 : : #include <sys/mman.h>
48 : : #include <sys/param.h>
49 : : #include <unistd.h>
50 : :
51 : : #if defined(HAVE_ERROR_H)
52 : : #include <error.h>
53 : : #elif defined(HAVE_ERR_H)
54 : : extern int error_message_count;
55 : : void error(int status, int errnum, const char *format, ...);
56 : : #else
57 : : #error "err.h or error.h must be available"
58 : : #endif
59 : :
60 : : /* error (EXIT_FAILURE, ...) should be noreturn but on some systems it
61 : : isn't. This may cause warnings about code that should not be reachable.
62 : : So have an explicit error_exit wrapper that is noreturn (because it
63 : : calls exit explicitly). */
64 : : #define error_exit(errnum,...) do { \
65 : : error (EXIT_FAILURE,errnum,__VA_ARGS__); \
66 : : exit (EXIT_FAILURE); \
67 : : } while (0)
68 : :
69 : : #if BYTE_ORDER == LITTLE_ENDIAN
70 : : # define LE32(n) (n)
71 : : # define LE64(n) (n)
72 : : # define BE32(n) bswap_32 (n)
73 : : # define BE64(n) bswap_64 (n)
74 : : #elif BYTE_ORDER == BIG_ENDIAN
75 : : # define BE32(n) (n)
76 : : # define BE64(n) (n)
77 : : # define LE32(n) bswap_32 (n)
78 : : # define LE64(n) bswap_64 (n)
79 : : #else
80 : : # error "Unknown byte order"
81 : : #endif
82 : :
83 : : #ifndef MAX
84 : : #define MAX(m, n) ((m) < (n) ? (n) : (m))
85 : : #endif
86 : :
87 : : #ifndef MIN
88 : : #define MIN(m, n) ((m) < (n) ? (m) : (n))
89 : : #endif
90 : :
91 : : #if !HAVE_DECL_POWEROF2
92 : : #define powerof2(x) (((x) & ((x) - 1)) == 0)
93 : : #endif
94 : :
95 : : #if !HAVE_DECL_MEMPCPY
96 : : #define mempcpy(dest, src, n) \
97 : : ((void *) ((char *) memcpy (dest, src, n) + (size_t) n))
98 : : #endif
99 : :
100 : : #if !HAVE_DECL_REALLOCARRAY
101 : : static inline void *
102 : : reallocarray (void *ptr, size_t nmemb, size_t size)
103 : : {
104 : : if (size > 0 && nmemb > SIZE_MAX / size)
105 : : {
106 : : errno = ENOMEM;
107 : : return NULL;
108 : : }
109 : : return realloc (ptr, nmemb * size);
110 : : }
111 : : #endif
112 : :
113 : : /* Return TRUE if the start of STR matches PREFIX, FALSE otherwise. */
114 : :
115 : : static inline int
116 : 13872032 : startswith (const char *str, const char *prefix)
117 : : {
118 : 13872032 : return strncmp (str, prefix, strlen (prefix)) == 0;
119 : : }
120 : :
121 : : /* Return TRUE if STR[FROM] is a valid string with a zero terminator
122 : : at or before STR[TO - 1]. Note FROM is an index into the STR
123 : : array, while TO is the maximum size of the STR array. This
124 : : function returns FALSE when TO is zero or FROM >= TO. */
125 : : static inline bool
126 : 11870287 : validate_str (const char *str, size_t from, size_t to)
127 : : {
128 : : #if HAVE_DECL_MEMRCHR
129 : : // Check end first, which is likely a zero terminator,
130 : : // to prevent function call
131 : 11870287 : return (to > 0
132 [ + - - + ]: 11870287 : && (str[to - 1] == '\0'
133 [ # # ]: 0 : || (to > from
134 [ # # ]: 0 : && memrchr (&str[from], '\0', to - from - 1) != NULL)));
135 : : #else
136 : : do {
137 : : if (to <= from)
138 : : return false;
139 : :
140 : : to--;
141 : : } while (str[to]);
142 : :
143 : : return true;
144 : : #endif
145 : : }
146 : :
147 : : /* A special gettext function we use if the strings are too short. */
148 : : #define sgettext(Str) \
149 : : ({ const char *__res = strrchr (_(Str), '|'); \
150 : : __res ? __res + 1 : Str; })
151 : :
152 : : #define gettext_noop(Str) Str
153 : :
154 : : #ifndef TEMP_FAILURE_RETRY
155 : : #define TEMP_FAILURE_RETRY(expression) \
156 : : ({ ssize_t __res; \
157 : : do \
158 : : __res = expression; \
159 : : while (__res == -1 && errno == EINTR); \
160 : : __res; })
161 : : #endif
162 : :
163 : : #ifndef ACCESSPERMS
164 : : #define ACCESSPERMS (S_IRWXU|S_IRWXG|S_IRWXO) /* 0777 */
165 : : #endif
166 : :
167 : : #ifndef ALLPERMS
168 : : #define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO) /* 07777 */
169 : : #endif
170 : :
171 : : #ifndef DEFFILEMODE
172 : : #define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)/* 0666 */
173 : : #endif
174 : :
175 : : static inline ssize_t __attribute__ ((unused))
176 : 2122812 : pwrite_retry (int fd, const void *buf, size_t len, off_t off)
177 : : {
178 : 2122812 : ssize_t recvd = 0;
179 : :
180 : 2122812 : do
181 : : {
182 [ - + - - ]: 2122812 : ssize_t ret = TEMP_FAILURE_RETRY (pwrite (fd, ((char *)buf) + recvd, len - recvd,
183 : : off + recvd));
184 [ + + ]: 2122812 : if (ret <= 0)
185 [ + - ]: 496 : return ret < 0 ? ret : recvd;
186 : :
187 : 2122316 : recvd += ret;
188 : : }
189 [ - + ]: 2122316 : while ((size_t) recvd < len);
190 : :
191 : : return recvd;
192 : : }
193 : :
194 : : static inline ssize_t __attribute__ ((unused))
195 : 180 : write_retry (int fd, const void *buf, size_t len)
196 : : {
197 : 180 : ssize_t recvd = 0;
198 : :
199 : 180 : do
200 : : {
201 [ - + - - ]: 180 : ssize_t ret = TEMP_FAILURE_RETRY (write (fd, ((char *)buf) + recvd, len - recvd));
202 [ - + ]: 180 : if (ret <= 0)
203 [ # # ]: 0 : return ret < 0 ? ret : recvd;
204 : :
205 : 180 : recvd += ret;
206 : : }
207 [ - + ]: 180 : while ((size_t) recvd < len);
208 : :
209 : : return recvd;
210 : : }
211 : :
212 : : static inline ssize_t __attribute__ ((unused))
213 : 1511034 : pread_retry (int fd, void *buf, size_t len, off_t off)
214 : : {
215 : 1511034 : ssize_t recvd = 0;
216 : :
217 : 1521060 : do
218 : : {
219 [ + + - + : 3042120 : ssize_t ret = TEMP_FAILURE_RETRY (pread (fd, ((char *)buf) + recvd, len - recvd,
- - ]
220 : : off + recvd));
221 [ + + ]: 1521060 : if (ret <= 0)
222 [ + - ]: 10038 : return ret < 0 ? ret : recvd;
223 : :
224 : 1511022 : recvd += ret;
225 : : }
226 [ + + ]: 1511022 : while ((size_t) recvd < len);
227 : :
228 : : return recvd;
229 : : }
230 : :
231 : : /* The demangler from libstdc++. */
232 : : extern char *__cxa_demangle (const char *mangled_name, char *output_buffer,
233 : : size_t *length, int *status);
234 : :
235 : : /* A static assertion. This will cause a compile-time error if EXPR,
236 : : which must be a compile-time constant, is false. */
237 : :
238 : : #define eu_static_assert(expr) \
239 : : extern int never_defined_just_used_for_checking[(expr) ? 1 : -1] \
240 : : __attribute__ ((unused))
241 : :
242 : : /* We really want a basename implementation that doesn't modify the
243 : : input argument. Normally you get that from string.h with _GNU_SOURCE
244 : : define. But some libc implementations don't define it and other
245 : : define it, but provide an implementation that still modifies the
246 : : argument. So define our own and poison a bare basename symbol. */
247 : : static inline const char *
248 : 22260 : xbasename(const char *s)
249 : : {
250 : 22260 : const char *p = strrchr(s, '/');
251 [ + + ]: 22260 : return p ? p+1 : s;
252 : : }
253 : : #pragma GCC poison basename
254 : :
255 : : #endif /* system.h */
|