1/* copy-paste from BusyBox */
2
3#include <autoconf.h>
4#include <libbb.h>
5
6#include <stdio.h>
7#include <string.h>
8#include <malloc.h>
9
10const char bb_msg_memory_exhausted[] ALIGN1 = "memory exhausted";
11int *const bb_errno;
12int xfunc_error_retval = EXIT_FAILURE;
13
14void FAST_FUNC xfunc_die(void)
15{
16	exit(xfunc_error_retval);
17}
18
19void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr)
20{
21	/* do nothing */
22}
23
24void FAST_FUNC bb_error_msg_and_die(const char *s, ...)
25{
26	va_list p;
27
28	va_start(p, s);
29	bb_verror_msg(s, p, NULL);
30	va_end(p);
31	xfunc_die();
32}
33
34void FAST_FUNC bb_error_msg(const char *s, ...)
35{
36	va_list p;
37
38	va_start(p, s);
39	bb_verror_msg(s, p, NULL);
40	va_end(p);
41}
42
43/* All the functions starting with "x" call bb_error_msg_and_die() if they
44 * fail, so callers never need to check for errors.  If it returned, it
45 * succeeded. */
46
47#ifndef DMALLOC
48/* dmalloc provides variants of these that do abort() on failure.
49 * Since dmalloc's prototypes overwrite the impls here as they are
50 * included after these prototypes in libbb.h, all is well.
51 */
52// Die if we can't allocate size bytes of memory.
53void* FAST_FUNC xmalloc(size_t size)
54{
55	void *ptr = malloc(size);
56	if (ptr == NULL && size != 0)
57		bb_error_msg_and_die(bb_msg_memory_exhausted);
58	return ptr;
59}
60
61// Die if we can't resize previously allocated memory.  (This returns a pointer
62// to the new memory, which may or may not be the same as the old memory.
63// It'll copy the contents to a new chunk and free the old one if necessary.)
64void* FAST_FUNC xrealloc(void *ptr, size_t size)
65{
66	ptr = realloc(ptr, size);
67	if (ptr == NULL && size != 0)
68		bb_error_msg_and_die(bb_msg_memory_exhausted);
69	return ptr;
70}
71#endif /* DMALLOC */
72
73ssize_t FAST_FUNC safe_read(int fd, void *buf, size_t count)
74{
75	ssize_t n;
76
77	do {
78		n = read(fd, buf, count);
79	} while (n < 0 && errno == EINTR);
80
81	return n;
82}
83
84/*
85 * Read all of the supplied buffer from a file.
86 * This does multiple reads as necessary.
87 * Returns the amount read, or -1 on an error.
88 * A short read is returned on an end of file.
89 */
90ssize_t FAST_FUNC full_read(int fd, void *buf, size_t len)
91{
92	ssize_t cc;
93	ssize_t total;
94
95	total = 0;
96
97	while (len) {
98		cc = safe_read(fd, buf, len);
99
100		if (cc < 0) {
101			if (total) {
102				/* we already have some! */
103				/* user can do another read to know the error code */
104				return total;
105			}
106			return cc; /* read() returns -1 on failure. */
107		}
108		if (cc == 0)
109			break;
110		buf = ((char *)buf) + cc;
111		total += cc;
112		len -= cc;
113	}
114
115	return total;
116}
117