1
2
3
4
5
6
7
8
9#include "libbb.h"
10
11#define ZIPPED (ENABLE_FEATURE_SEAMLESS_LZMA \
12 || ENABLE_FEATURE_SEAMLESS_BZ2 \
13 || ENABLE_FEATURE_SEAMLESS_GZ \
14 \
15)
16
17#if ZIPPED
18# include "archive.h"
19#endif
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58ssize_t FAST_FUNC nonblock_safe_read(int fd, void *buf, size_t count)
59{
60 struct pollfd pfd[1];
61 ssize_t n;
62
63 while (1) {
64 n = safe_read(fd, buf, count);
65 if (n >= 0 || errno != EAGAIN)
66 return n;
67
68 pfd[0].fd = fd;
69 pfd[0].events = POLLIN;
70 safe_poll(pfd, 1, -1);
71 }
72}
73
74
75
76
77char* FAST_FUNC xmalloc_reads(int fd, char *buf, size_t *maxsz_p)
78{
79 char *p;
80 size_t sz = buf ? strlen(buf) : 0;
81 size_t maxsz = maxsz_p ? *maxsz_p : (INT_MAX - 4095);
82
83 goto jump_in;
84 while (sz < maxsz) {
85 if ((size_t)(p - buf) == sz) {
86 jump_in:
87 buf = xrealloc(buf, sz + 128);
88 p = buf + sz;
89 sz += 128;
90 }
91
92 if (nonblock_safe_read(fd, p, 1) != 1) {
93 if (p == buf) {
94 free(buf);
95 return NULL;
96 }
97 break;
98 }
99 if (*p == '\n')
100 break;
101 p++;
102 }
103 *p = '\0';
104 if (maxsz_p)
105 *maxsz_p = p - buf;
106 p++;
107 return xrealloc(buf, p - buf);
108}
109
110
111
112void* FAST_FUNC xmalloc_read(int fd, size_t *maxsz_p)
113{
114 char *buf;
115 size_t size, rd_size, total;
116 size_t to_read;
117 struct stat st;
118
119 to_read = maxsz_p ? *maxsz_p : (INT_MAX - 4095);
120
121
122 st.st_size = 0;
123 fstat(fd, &st);
124
125
126 size = (st.st_size | 0x3ff) + 1;
127
128 total = 0;
129 buf = NULL;
130 while (1) {
131 if (to_read < size)
132 size = to_read;
133 buf = xrealloc(buf, total + size + 1);
134 rd_size = full_read(fd, buf + total, size);
135 if ((ssize_t)rd_size == (ssize_t)(-1)) {
136 free(buf);
137 return NULL;
138 }
139 total += rd_size;
140 if (rd_size < size)
141 break;
142 if (to_read <= rd_size)
143 break;
144 to_read -= rd_size;
145
146 size = ((total / 8) | 0x3ff) + 1;
147 if (size > 64*1024)
148 size = 64*1024;
149 }
150 buf = xrealloc(buf, total + 1);
151 buf[total] = '\0';
152
153 if (maxsz_p)
154 *maxsz_p = total;
155 return buf;
156}
157
158#ifdef USING_LSEEK_TO_GET_SIZE
159
160
161
162
163
164
165
166void* FAST_FUNC xmalloc_open_read_close(const char *filename, size_t *maxsz_p)
167{
168 char *buf;
169 size_t size;
170 int fd;
171 off_t len;
172
173 fd = open(filename, O_RDONLY);
174 if (fd < 0)
175 return NULL;
176
177
178
179 size = 0x3ff;
180 len = lseek(fd, 0, SEEK_END) | 0x3ff;
181 if (len != (off_t)-1) {
182 xlseek(fd, 0, SEEK_SET);
183 size = maxsz_p ? *maxsz_p : (INT_MAX - 4095);
184 if (len < size)
185 size = len;
186 }
187
188 buf = xmalloc(size + 1);
189 size = read_close(fd, buf, size);
190 if ((ssize_t)size < 0) {
191 free(buf);
192 return NULL;
193 }
194 buf = xrealloc(buf, size + 1);
195 buf[size] = '\0';
196
197 if (maxsz_p)
198 *maxsz_p = size;
199 return buf;
200}
201#endif
202
203
204
205void* FAST_FUNC xmalloc_open_read_close(const char *filename, size_t *maxsz_p)
206{
207 char *buf;
208 int fd;
209
210 fd = open(filename, O_RDONLY);
211 if (fd < 0)
212 return NULL;
213
214 buf = xmalloc_read(fd, maxsz_p);
215 close(fd);
216 return buf;
217}
218
219
220void FAST_FUNC xread(int fd, void *buf, size_t count)
221{
222 if (count) {
223 ssize_t size = full_read(fd, buf, count);
224 if ((size_t)size != count)
225 bb_error_msg_and_die("short read");
226 }
227}
228
229
230unsigned char FAST_FUNC xread_char(int fd)
231{
232 char tmp;
233 xread(fd, &tmp, 1);
234 return tmp;
235}
236
237void* FAST_FUNC xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p)
238{
239 void *buf = xmalloc_open_read_close(filename, maxsz_p);
240 if (!buf)
241 bb_perror_msg_and_die("can't read '%s'", filename);
242 return buf;
243}
244
245
246
247
248#if ZIPPED
249void FAST_FUNC setup_unzip_on_fd(int fd )
250{
251 const int fail_if_not_detected = 1;
252 union {
253 uint8_t b[4];
254 uint16_t b16[2];
255 uint32_t b32[1];
256 } magic;
257 int offset = -2;
258# if BB_MMU
259 IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd);
260 enum { xformer_prog = 0 };
261# else
262 enum { xformer = 0 };
263 const char *xformer_prog;
264# endif
265
266
267
268 xread(fd, magic.b16, sizeof(magic.b16[0]));
269 if (ENABLE_FEATURE_SEAMLESS_GZ
270 && magic.b16[0] == GZIP_MAGIC
271 ) {
272# if BB_MMU
273 xformer = unpack_gz_stream;
274# else
275 xformer_prog = "gunzip";
276# endif
277 goto found_magic;
278 }
279 if (ENABLE_FEATURE_SEAMLESS_BZ2
280 && magic.b16[0] == BZIP2_MAGIC
281 ) {
282# if BB_MMU
283 xformer = unpack_bz2_stream;
284# else
285 xformer_prog = "bunzip2";
286# endif
287 goto found_magic;
288 }
289 if (ENABLE_FEATURE_SEAMLESS_XZ
290 && magic.b16[0] == XZ_MAGIC1
291 ) {
292 offset = -6;
293 xread(fd, magic.b32, sizeof(magic.b32[0]));
294 if (magic.b32[0] == XZ_MAGIC2) {
295# if BB_MMU
296 xformer = unpack_xz_stream;
297
298
299# else
300 xformer_prog = "unxz";
301# endif
302 goto found_magic;
303 }
304 }
305
306
307 if (fail_if_not_detected)
308 bb_error_msg_and_die("no gzip"
309 IF_FEATURE_SEAMLESS_BZ2("/bzip2")
310 IF_FEATURE_SEAMLESS_XZ("/xz")
311 " magic");
312 xlseek(fd, offset, SEEK_CUR);
313 return;
314
315 found_magic:
316# if !BB_MMU
317
318
319
320 xlseek(fd, offset, SEEK_CUR);
321# endif
322 open_transformer(fd, xformer, xformer_prog);
323}
324#endif
325
326int FAST_FUNC open_zipped(const char *fname)
327{
328#if !ZIPPED
329 return open(fname, O_RDONLY);
330#else
331 char *sfx;
332 int fd;
333
334 fd = open(fname, O_RDONLY);
335 if (fd < 0)
336 return fd;
337
338 sfx = strrchr(fname, '.');
339 if (sfx) {
340 sfx++;
341 if (ENABLE_FEATURE_SEAMLESS_LZMA && strcmp(sfx, "lzma") == 0)
342
343 open_transformer(fd, unpack_lzma_stream, "unlzma");
344 else
345 if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, "gz") == 0)
346 || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, "bz2") == 0)
347 || (ENABLE_FEATURE_SEAMLESS_XZ && strcmp(sfx, "xz") == 0)
348 ) {
349 setup_unzip_on_fd(fd );
350 }
351 }
352
353 return fd;
354#endif
355}
356
357void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p)
358{
359 int fd;
360 char *image;
361
362 fd = open_zipped(fname);
363 if (fd < 0)
364 return NULL;
365
366 image = xmalloc_read(fd, maxsz_p);
367 if (!image)
368 bb_perror_msg("read error from '%s'", fname);
369 close(fd);
370
371 return image;
372}
373