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