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