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