1 /* Declarations for common convenience functions.
2 Copyright (C) 2006-2011 Red Hat, Inc.
3 Copyright (C) 2022 Mark J. Wielaard <[email protected]>
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 *
reallocarray(void * ptr,size_t nmemb,size_t size)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
startswith(const char * str,const char * prefix)115 startswith (const char *str, const char *prefix)
116 {
117 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))
pwrite_retry(int fd,const void * buf,size_t len,off_t off)149 pwrite_retry (int fd, const void *buf, size_t len, off_t off)
150 {
151 ssize_t recvd = 0;
152
153 do
154 {
155 ssize_t ret = TEMP_FAILURE_RETRY (pwrite (fd, ((char *)buf) + recvd, len - recvd,
156 off + recvd));
157 if (ret <= 0)
158 return ret < 0 ? ret : recvd;
159
160 recvd += ret;
161 }
162 while ((size_t) recvd < len);
163
164 return recvd;
165 }
166
167 static inline ssize_t __attribute__ ((unused))
write_retry(int fd,const void * buf,size_t len)168 write_retry (int fd, const void *buf, size_t len)
169 {
170 ssize_t recvd = 0;
171
172 do
173 {
174 ssize_t ret = TEMP_FAILURE_RETRY (write (fd, ((char *)buf) + recvd, len - recvd));
175 if (ret <= 0)
176 return ret < 0 ? ret : recvd;
177
178 recvd += ret;
179 }
180 while ((size_t) recvd < len);
181
182 return recvd;
183 }
184
185 static inline ssize_t __attribute__ ((unused))
pread_retry(int fd,void * buf,size_t len,off_t off)186 pread_retry (int fd, void *buf, size_t len, off_t off)
187 {
188 ssize_t recvd = 0;
189
190 do
191 {
192 ssize_t ret = TEMP_FAILURE_RETRY (pread (fd, ((char *)buf) + recvd, len - recvd,
193 off + recvd));
194 if (ret <= 0)
195 return ret < 0 ? ret : recvd;
196
197 recvd += ret;
198 }
199 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 *
xbasename(const char * s)221 xbasename(const char *s)
222 {
223 const char *p = strrchr(s, '/');
224 return p ? p+1 : s;
225 }
226 #pragma GCC poison basename
227
228 #endif /* system.h */
229