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