1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include "libbb.h"
24
25
26
27
28
29
30#ifndef DMALLOC
31
32
33
34
35
36void* FAST_FUNC malloc_or_warn(size_t size)
37{
38 void *ptr = malloc(size);
39 if (ptr == NULL && size != 0)
40 bb_error_msg(bb_msg_memory_exhausted);
41 return ptr;
42}
43
44
45void* FAST_FUNC xmalloc(size_t size)
46{
47 void *ptr = malloc(size);
48 if (ptr == NULL && size != 0)
49 bb_error_msg_and_die(bb_msg_memory_exhausted);
50 return ptr;
51}
52
53
54
55
56void* FAST_FUNC xrealloc(void *ptr, size_t size)
57{
58 ptr = realloc(ptr, size);
59 if (ptr == NULL && size != 0)
60 bb_error_msg_and_die(bb_msg_memory_exhausted);
61 return ptr;
62}
63#endif
64
65
66void* FAST_FUNC xzalloc(size_t size)
67{
68 void *ptr = xmalloc(size);
69 memset(ptr, 0, size);
70 return ptr;
71}
72
73
74char* FAST_FUNC xstrdup(const char *s)
75{
76 char *t;
77
78 if (s == NULL)
79 return NULL;
80
81 t = strdup(s);
82
83 if (t == NULL)
84 bb_error_msg_and_die(bb_msg_memory_exhausted);
85
86 return t;
87}
88
89
90
91char* FAST_FUNC xstrndup(const char *s, int n)
92{
93 int m;
94 char *t;
95
96 if (ENABLE_DEBUG && s == NULL)
97 bb_error_msg_and_die("xstrndup bug");
98
99
100
101 m = n;
102 t = (char*) s;
103 while (m) {
104 if (!*t) break;
105 m--;
106 t++;
107 }
108 n -= m;
109 t = xmalloc(n + 1);
110 t[n] = '\0';
111
112 return memcpy(t, s, n);
113}
114
115
116
117FILE* FAST_FUNC xfopen(const char *path, const char *mode)
118{
119 FILE *fp = fopen(path, mode);
120 if (fp == NULL)
121 bb_perror_msg_and_die("can't open '%s'", path);
122 return fp;
123}
124
125
126int FAST_FUNC xopen3(const char *pathname, int flags, int mode)
127{
128 int ret;
129
130 ret = open(pathname, flags, mode);
131 if (ret < 0) {
132 bb_perror_msg_and_die("can't open '%s'", pathname);
133 }
134 return ret;
135}
136
137
138int FAST_FUNC xopen(const char *pathname, int flags)
139{
140 return xopen3(pathname, flags, 0666);
141}
142
143
144
145
146
147int FAST_FUNC xopen_nonblocking(const char *pathname)
148{
149 return xopen(pathname, O_RDONLY | O_NONBLOCK);
150}
151
152
153int FAST_FUNC open3_or_warn(const char *pathname, int flags, int mode)
154{
155 int ret;
156
157 ret = open(pathname, flags, mode);
158 if (ret < 0) {
159 bb_perror_msg("can't open '%s'", pathname);
160 }
161 return ret;
162}
163
164
165int FAST_FUNC open_or_warn(const char *pathname, int flags)
166{
167 return open3_or_warn(pathname, flags, 0666);
168}
169
170void FAST_FUNC xunlink(const char *pathname)
171{
172 if (unlink(pathname))
173 bb_perror_msg_and_die("can't remove file '%s'", pathname);
174}
175
176void FAST_FUNC xrename(const char *oldpath, const char *newpath)
177{
178 if (rename(oldpath, newpath))
179 bb_perror_msg_and_die("can't move '%s' to '%s'", oldpath, newpath);
180}
181
182int FAST_FUNC rename_or_warn(const char *oldpath, const char *newpath)
183{
184 int n = rename(oldpath, newpath);
185 if (n)
186 bb_perror_msg("can't move '%s' to '%s'", oldpath, newpath);
187 return n;
188}
189
190void FAST_FUNC xpipe(int filedes[2])
191{
192 if (pipe(filedes))
193 bb_perror_msg_and_die("can't create pipe");
194}
195
196void FAST_FUNC xdup2(int from, int to)
197{
198 if (dup2(from, to) != to)
199 bb_perror_msg_and_die("can't duplicate file descriptor");
200}
201
202
203void FAST_FUNC xmove_fd(int from, int to)
204{
205 if (from == to)
206 return;
207 xdup2(from, to);
208 close(from);
209}
210
211
212void FAST_FUNC xwrite(int fd, const void *buf, size_t count)
213{
214 if (count) {
215 ssize_t size = full_write(fd, buf, count);
216 if ((size_t)size != count)
217 bb_error_msg_and_die("short write");
218 }
219}
220void FAST_FUNC xwrite_str(int fd, const char *str)
221{
222 xwrite(fd, str, strlen(str));
223}
224
225void FAST_FUNC xclose(int fd)
226{
227 if (close(fd))
228 bb_perror_msg_and_die("close failed");
229}
230
231
232off_t FAST_FUNC xlseek(int fd, off_t offset, int whence)
233{
234 off_t off = lseek(fd, offset, whence);
235 if (off == (off_t)-1) {
236 if (whence == SEEK_SET)
237 bb_perror_msg_and_die("lseek(%"OFF_FMT"u)", offset);
238 bb_perror_msg_and_die("lseek");
239 }
240 return off;
241}
242
243int FAST_FUNC xmkstemp(char *template)
244{
245 int fd = mkstemp(template);
246 if (fd < 0)
247 bb_perror_msg_and_die("can't create temp file '%s'", template);
248 return fd;
249}
250
251
252void FAST_FUNC die_if_ferror(FILE *fp, const char *fn)
253{
254 if (ferror(fp)) {
255
256 bb_error_msg_and_die("%s: I/O error", fn);
257 }
258}
259
260
261void FAST_FUNC die_if_ferror_stdout(void)
262{
263 die_if_ferror(stdout, bb_msg_standard_output);
264}
265
266int FAST_FUNC fflush_all(void)
267{
268 return fflush(NULL);
269}
270
271
272int FAST_FUNC bb_putchar(int ch)
273{
274 return putchar(ch);
275}
276
277
278
279void FAST_FUNC xprint_and_close_file(FILE *file)
280{
281 fflush_all();
282
283 if (bb_copyfd_eof(fileno(file), STDOUT_FILENO) == -1)
284 xfunc_die();
285
286 fclose(file);
287}
288
289
290
291char* FAST_FUNC xasprintf(const char *format, ...)
292{
293 va_list p;
294 int r;
295 char *string_ptr;
296
297 va_start(p, format);
298 r = vasprintf(&string_ptr, format, p);
299 va_end(p);
300
301 if (r < 0)
302 bb_error_msg_and_die(bb_msg_memory_exhausted);
303 return string_ptr;
304}
305
306void FAST_FUNC xsetenv(const char *key, const char *value)
307{
308 if (setenv(key, value, 1))
309 bb_error_msg_and_die(bb_msg_memory_exhausted);
310}
311
312
313
314
315void FAST_FUNC bb_unsetenv(const char *var)
316{
317 char *tp = strchr(var, '=');
318
319 if (!tp) {
320 unsetenv(var);
321 return;
322 }
323
324
325
326
327
328
329 tp = xstrndup(var, tp - var);
330 unsetenv(tp);
331 free(tp);
332}
333
334void FAST_FUNC bb_unsetenv_and_free(char *var)
335{
336 bb_unsetenv(var);
337 free(var);
338}
339
340
341
342
343void FAST_FUNC xsetgid(gid_t gid)
344{
345 if (setgid(gid)) bb_perror_msg_and_die("setgid");
346}
347
348
349void FAST_FUNC xsetuid(uid_t uid)
350{
351 if (setuid(uid)) bb_perror_msg_and_die("setuid");
352}
353
354
355void FAST_FUNC xchdir(const char *path)
356{
357 if (chdir(path))
358 bb_perror_msg_and_die("chdir(%s)", path);
359}
360
361void FAST_FUNC xchroot(const char *path)
362{
363 if (chroot(path))
364 bb_perror_msg_and_die("can't change root directory to %s", path);
365}
366
367
368DIR* FAST_FUNC warn_opendir(const char *path)
369{
370 DIR *dp;
371
372 dp = opendir(path);
373 if (!dp)
374 bb_perror_msg("can't open '%s'", path);
375 return dp;
376}
377
378
379DIR* FAST_FUNC xopendir(const char *path)
380{
381 DIR *dp;
382
383 dp = opendir(path);
384 if (!dp)
385 bb_perror_msg_and_die("can't open '%s'", path);
386 return dp;
387}
388
389
390int FAST_FUNC xsocket(int domain, int type, int protocol)
391{
392 int r = socket(domain, type, protocol);
393
394 if (r < 0) {
395
396#if ENABLE_VERBOSE_RESOLUTION_ERRORS
397 const char *s = "INET";
398# ifdef AF_PACKET
399 if (domain == AF_PACKET) s = "PACKET";
400# endif
401# ifdef AF_NETLINK
402 if (domain == AF_NETLINK) s = "NETLINK";
403# endif
404IF_FEATURE_IPV6(if (domain == AF_INET6) s = "INET6";)
405 bb_perror_msg_and_die("socket(AF_%s,%d,%d)", s, type, protocol);
406#else
407 bb_perror_msg_and_die("socket");
408#endif
409 }
410
411 return r;
412}
413
414
415void FAST_FUNC xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen)
416{
417 if (bind(sockfd, my_addr, addrlen)) bb_perror_msg_and_die("bind");
418}
419
420
421void FAST_FUNC xlisten(int s, int backlog)
422{
423 if (listen(s, backlog)) bb_perror_msg_and_die("listen");
424}
425
426
427
428ssize_t FAST_FUNC xsendto(int s, const void *buf, size_t len, const struct sockaddr *to,
429 socklen_t tolen)
430{
431 ssize_t ret = sendto(s, buf, len, 0, to, tolen);
432 if (ret < 0) {
433 if (ENABLE_FEATURE_CLEAN_UP)
434 close(s);
435 bb_perror_msg_and_die("sendto");
436 }
437 return ret;
438}
439
440
441void FAST_FUNC xstat(const char *name, struct stat *stat_buf)
442{
443 if (stat(name, stat_buf))
444 bb_perror_msg_and_die("can't stat '%s'", name);
445}
446
447void FAST_FUNC xfstat(int fd, struct stat *stat_buf, const char *errmsg)
448{
449
450
451
452
453 if (fstat(fd, stat_buf))
454 bb_simple_perror_msg_and_die(errmsg);
455}
456
457
458void FAST_FUNC selinux_or_die(void)
459{
460#if ENABLE_SELINUX
461 int rc = is_selinux_enabled();
462 if (rc == 0) {
463 bb_error_msg_and_die("SELinux is disabled");
464 } else if (rc < 0) {
465 bb_error_msg_and_die("is_selinux_enabled() failed");
466 }
467#else
468 bb_error_msg_and_die("SELinux support is disabled");
469#endif
470}
471
472int FAST_FUNC ioctl_or_perror_and_die(int fd, unsigned request, void *argp, const char *fmt,...)
473{
474 int ret;
475 va_list p;
476
477 ret = ioctl(fd, request, argp);
478 if (ret < 0) {
479 va_start(p, fmt);
480 bb_verror_msg(fmt, p, strerror(errno));
481
482 va_end(p);
483 xfunc_die();
484 }
485 return ret;
486}
487
488int FAST_FUNC ioctl_or_perror(int fd, unsigned request, void *argp, const char *fmt,...)
489{
490 va_list p;
491 int ret = ioctl(fd, request, argp);
492
493 if (ret < 0) {
494 va_start(p, fmt);
495 bb_verror_msg(fmt, p, strerror(errno));
496 va_end(p);
497 }
498 return ret;
499}
500
501#if ENABLE_IOCTL_HEX2STR_ERROR
502int FAST_FUNC bb_ioctl_or_warn(int fd, unsigned request, void *argp, const char *ioctl_name)
503{
504 int ret;
505
506 ret = ioctl(fd, request, argp);
507 if (ret < 0)
508 bb_simple_perror_msg(ioctl_name);
509 return ret;
510}
511int FAST_FUNC bb_xioctl(int fd, unsigned request, void *argp, const char *ioctl_name)
512{
513 int ret;
514
515 ret = ioctl(fd, request, argp);
516 if (ret < 0)
517 bb_simple_perror_msg_and_die(ioctl_name);
518 return ret;
519}
520#else
521int FAST_FUNC bb_ioctl_or_warn(int fd, unsigned request, void *argp)
522{
523 int ret;
524
525 ret = ioctl(fd, request, argp);
526 if (ret < 0)
527 bb_perror_msg("ioctl %#x failed", request);
528 return ret;
529}
530int FAST_FUNC bb_xioctl(int fd, unsigned request, void *argp)
531{
532 int ret;
533
534 ret = ioctl(fd, request, argp);
535 if (ret < 0)
536 bb_perror_msg_and_die("ioctl %#x failed", request);
537 return ret;
538}
539#endif
540
541char* FAST_FUNC xmalloc_ttyname(int fd)
542{
543 char *buf = xzalloc(128);
544 int r = ttyname_r(fd, buf, 127);
545 if (r) {
546 free(buf);
547 buf = NULL;
548 }
549 return buf;
550}
551
552void FAST_FUNC generate_uuid(uint8_t *buf)
553{
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587 pid_t pid;
588 int i;
589
590 i = open("/dev/urandom", O_RDONLY);
591 if (i >= 0) {
592 read(i, buf, 16);
593 close(i);
594 }
595
596
597
598 srand(monotonic_us());
599 pid = getpid();
600 while (1) {
601 for (i = 0; i < 16; i++)
602 buf[i] ^= rand() >> 5;
603 if (pid == 0)
604 break;
605 srand(pid);
606 pid = 0;
607 }
608
609
610 buf[4 + 2 ] = (buf[4 + 2 ] & 0x0f) | 0x40;
611
612 buf[4 + 2 + 2] = (buf[4 + 2 + 2] & 0x3f) | 0x80;
613}
614
615#if BB_MMU
616pid_t FAST_FUNC xfork(void)
617{
618 pid_t pid;
619 pid = fork();
620 if (pid < 0)
621 bb_perror_msg_and_die("vfork"+1);
622 return pid;
623}
624#endif
625