read.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Utility routines.
  4. *
  5. * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
  6. *
  7. * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  8. */
  9. #include "libbb.h"
  10. #define ZIPPED (ENABLE_FEATURE_SEAMLESS_LZMA \
  11. || ENABLE_FEATURE_SEAMLESS_BZ2 \
  12. || ENABLE_FEATURE_SEAMLESS_GZ \
  13. /* || ENABLE_FEATURE_SEAMLESS_Z */ \
  14. )
  15. #if ZIPPED
  16. #include "unarchive.h"
  17. #endif
  18. ssize_t FAST_FUNC safe_read(int fd, void *buf, size_t count)
  19. {
  20. ssize_t n;
  21. do {
  22. n = read(fd, buf, count);
  23. } while (n < 0 && errno == EINTR);
  24. return n;
  25. }
  26. /* Suppose that you are a shell. You start child processes.
  27. * They work and eventually exit. You want to get user input.
  28. * You read stdin. But what happens if last child switched
  29. * its stdin into O_NONBLOCK mode?
  30. *
  31. * *** SURPRISE! It will affect the parent too! ***
  32. * *** BIG SURPRISE! It stays even after child exits! ***
  33. *
  34. * This is a design bug in UNIX API.
  35. * fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) | O_NONBLOCK);
  36. * will set nonblocking mode not only on _your_ stdin, but
  37. * also on stdin of your parent, etc.
  38. *
  39. * In general,
  40. * fd2 = dup(fd1);
  41. * fcntl(fd2, F_SETFL, fcntl(fd2, F_GETFL, 0) | O_NONBLOCK);
  42. * sets both fd1 and fd2 to O_NONBLOCK. This includes cases
  43. * where duping is done implicitly by fork() etc.
  44. *
  45. * We need
  46. * fcntl(fd2, F_SETFD, fcntl(fd2, F_GETFD, 0) | O_NONBLOCK);
  47. * (note SETFD, not SETFL!) but such thing doesn't exist.
  48. *
  49. * Alternatively, we need nonblocking_read(fd, ...) which doesn't
  50. * require O_NONBLOCK dance at all. Actually, it exists:
  51. * n = recv(fd, buf, len, MSG_DONTWAIT);
  52. * "MSG_DONTWAIT:
  53. * Enables non-blocking operation; if the operation
  54. * would block, EAGAIN is returned."
  55. * but recv() works only for sockets!
  56. *
  57. * So far I don't see any good solution, I can only propose
  58. * that affected readers should be careful and use this routine,
  59. * which detects EAGAIN and uses poll() to wait on the fd.
  60. * Thankfully, poll() doesn't care about O_NONBLOCK flag.
  61. */
  62. ssize_t FAST_FUNC nonblock_safe_read(int fd, void *buf, size_t count)
  63. {
  64. struct pollfd pfd[1];
  65. ssize_t n;
  66. while (1) {
  67. n = safe_read(fd, buf, count);
  68. if (n >= 0 || errno != EAGAIN)
  69. return n;
  70. /* fd is in O_NONBLOCK mode. Wait using poll and repeat */
  71. pfd[0].fd = fd;
  72. pfd[0].events = POLLIN;
  73. safe_poll(pfd, 1, -1);
  74. }
  75. }
  76. /*
  77. * Read all of the supplied buffer from a file.
  78. * This does multiple reads as necessary.
  79. * Returns the amount read, or -1 on an error.
  80. * A short read is returned on an end of file.
  81. */
  82. ssize_t FAST_FUNC full_read(int fd, void *buf, size_t len)
  83. {
  84. ssize_t cc;
  85. ssize_t total;
  86. total = 0;
  87. while (len) {
  88. cc = safe_read(fd, buf, len);
  89. if (cc < 0) {
  90. if (total) {
  91. /* we already have some! */
  92. /* user can do another read to know the error code */
  93. return total;
  94. }
  95. return cc; /* read() returns -1 on failure. */
  96. }
  97. if (cc == 0)
  98. break;
  99. buf = ((char *)buf) + cc;
  100. total += cc;
  101. len -= cc;
  102. }
  103. return total;
  104. }
  105. /* Die with an error message if we can't read the entire buffer. */
  106. void FAST_FUNC xread(int fd, void *buf, size_t count)
  107. {
  108. if (count) {
  109. ssize_t size = full_read(fd, buf, count);
  110. if ((size_t)size != count)
  111. bb_error_msg_and_die("short read");
  112. }
  113. }
  114. /* Die with an error message if we can't read one character. */
  115. unsigned char FAST_FUNC xread_char(int fd)
  116. {
  117. char tmp;
  118. xread(fd, &tmp, 1);
  119. return tmp;
  120. }
  121. // Reads one line a-la fgets (but doesn't save terminating '\n').
  122. // Reads byte-by-byte. Useful when it is important to not read ahead.
  123. // Bytes are appended to pfx (which must be malloced, or NULL).
  124. char* FAST_FUNC xmalloc_reads(int fd, char *buf, size_t *maxsz_p)
  125. {
  126. char *p;
  127. size_t sz = buf ? strlen(buf) : 0;
  128. size_t maxsz = maxsz_p ? *maxsz_p : (INT_MAX - 4095);
  129. goto jump_in;
  130. while (sz < maxsz) {
  131. if ((size_t)(p - buf) == sz) {
  132. jump_in:
  133. buf = xrealloc(buf, sz + 128);
  134. p = buf + sz;
  135. sz += 128;
  136. }
  137. /* nonblock_safe_read() because we are used by e.g. shells */
  138. if (nonblock_safe_read(fd, p, 1) != 1) { /* EOF/error */
  139. if (p == buf) { /* we read nothing */
  140. free(buf);
  141. return NULL;
  142. }
  143. break;
  144. }
  145. if (*p == '\n')
  146. break;
  147. p++;
  148. }
  149. *p = '\0';
  150. if (maxsz_p)
  151. *maxsz_p = p - buf;
  152. p++;
  153. return xrealloc(buf, p - buf);
  154. }
  155. ssize_t FAST_FUNC read_close(int fd, void *buf, size_t size)
  156. {
  157. /*int e;*/
  158. size = full_read(fd, buf, size);
  159. /*e = errno;*/
  160. close(fd);
  161. /*errno = e;*/
  162. return size;
  163. }
  164. ssize_t FAST_FUNC open_read_close(const char *filename, void *buf, size_t size)
  165. {
  166. int fd = open(filename, O_RDONLY);
  167. if (fd < 0)
  168. return fd;
  169. return read_close(fd, buf, size);
  170. }
  171. // Read (potentially big) files in one go. File size is estimated
  172. // by stat. Extra '\0' byte is appended.
  173. void* FAST_FUNC xmalloc_read(int fd, size_t *maxsz_p)
  174. {
  175. char *buf;
  176. size_t size, rd_size, total;
  177. size_t to_read;
  178. struct stat st;
  179. to_read = maxsz_p ? *maxsz_p : (INT_MAX - 4095); /* max to read */
  180. /* Estimate file size */
  181. st.st_size = 0; /* in case fstat fails, assume 0 */
  182. fstat(fd, &st);
  183. /* /proc/N/stat files report st_size 0 */
  184. /* In order to make such files readable, we add small const */
  185. size = (st.st_size | 0x3ff) + 1;
  186. total = 0;
  187. buf = NULL;
  188. while (1) {
  189. if (to_read < size)
  190. size = to_read;
  191. buf = xrealloc(buf, total + size + 1);
  192. rd_size = full_read(fd, buf + total, size);
  193. if ((ssize_t)rd_size == (ssize_t)(-1)) { /* error */
  194. free(buf);
  195. return NULL;
  196. }
  197. total += rd_size;
  198. if (rd_size < size) /* EOF */
  199. break;
  200. if (to_read <= rd_size)
  201. break;
  202. to_read -= rd_size;
  203. /* grow by 1/8, but in [1k..64k] bounds */
  204. size = ((total / 8) | 0x3ff) + 1;
  205. if (size > 64*1024)
  206. size = 64*1024;
  207. }
  208. buf = xrealloc(buf, total + 1);
  209. buf[total] = '\0';
  210. if (maxsz_p)
  211. *maxsz_p = total;
  212. return buf;
  213. }
  214. #ifdef USING_LSEEK_TO_GET_SIZE
  215. /* Alternatively, file size can be obtained by lseek to the end.
  216. * The code is slightly bigger. Retained in case fstat approach
  217. * will not work for some weird cases (/proc, block devices, etc).
  218. * (NB: lseek also can fail to work for some weird files) */
  219. // Read (potentially big) files in one go. File size is estimated by
  220. // lseek to end.
  221. void* FAST_FUNC xmalloc_open_read_close(const char *filename, size_t *maxsz_p)
  222. {
  223. char *buf;
  224. size_t size;
  225. int fd;
  226. off_t len;
  227. fd = open(filename, O_RDONLY);
  228. if (fd < 0)
  229. return NULL;
  230. /* /proc/N/stat files report len 0 here */
  231. /* In order to make such files readable, we add small const */
  232. size = 0x3ff; /* read only 1k on unseekable files */
  233. len = lseek(fd, 0, SEEK_END) | 0x3ff; /* + up to 1k */
  234. if (len != (off_t)-1) {
  235. xlseek(fd, 0, SEEK_SET);
  236. size = maxsz_p ? *maxsz_p : (INT_MAX - 4095);
  237. if (len < size)
  238. size = len;
  239. }
  240. buf = xmalloc(size + 1);
  241. size = read_close(fd, buf, size);
  242. if ((ssize_t)size < 0) {
  243. free(buf);
  244. return NULL;
  245. }
  246. buf = xrealloc(buf, size + 1);
  247. buf[size] = '\0';
  248. if (maxsz_p)
  249. *maxsz_p = size;
  250. return buf;
  251. }
  252. #endif
  253. // Read (potentially big) files in one go. File size is estimated
  254. // by stat.
  255. void* FAST_FUNC xmalloc_open_read_close(const char *filename, size_t *maxsz_p)
  256. {
  257. char *buf;
  258. int fd;
  259. fd = open(filename, O_RDONLY);
  260. if (fd < 0)
  261. return NULL;
  262. buf = xmalloc_read(fd, maxsz_p);
  263. close(fd);
  264. return buf;
  265. }
  266. void* FAST_FUNC xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p)
  267. {
  268. void *buf = xmalloc_open_read_close(filename, maxsz_p);
  269. if (!buf)
  270. bb_perror_msg_and_die("can't read '%s'", filename);
  271. return buf;
  272. }
  273. int FAST_FUNC open_zipped(const char *fname)
  274. {
  275. #if !ZIPPED
  276. return open(fname, O_RDONLY);
  277. #else
  278. unsigned char magic[2];
  279. char *sfx;
  280. int fd;
  281. #if BB_MMU
  282. IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd);
  283. enum { xformer_prog = 0 };
  284. #else
  285. enum { xformer = 0 };
  286. const char *xformer_prog;
  287. #endif
  288. fd = open(fname, O_RDONLY);
  289. if (fd < 0)
  290. return fd;
  291. sfx = strrchr(fname, '.');
  292. if (sfx) {
  293. if (ENABLE_FEATURE_SEAMLESS_LZMA && strcmp(sfx, ".lzma") == 0)
  294. /* .lzma has no header/signature, just trust it */
  295. open_transformer(fd, unpack_lzma_stream, "unlzma");
  296. else
  297. if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, ".gz") == 0)
  298. || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, ".bz2") == 0)
  299. ) {
  300. /* .gz and .bz2 both have 2-byte signature, and their
  301. * unpack_XXX_stream want this header skipped. */
  302. xread(fd, &magic, 2);
  303. #if ENABLE_FEATURE_SEAMLESS_GZ
  304. #if BB_MMU
  305. xformer = unpack_gz_stream;
  306. #else
  307. xformer_prog = "gunzip";
  308. #endif
  309. #endif
  310. if (!ENABLE_FEATURE_SEAMLESS_GZ
  311. || magic[0] != 0x1f || magic[1] != 0x8b
  312. ) {
  313. if (!ENABLE_FEATURE_SEAMLESS_BZ2
  314. || magic[0] != 'B' || magic[1] != 'Z'
  315. ) {
  316. bb_error_msg_and_die("no gzip"
  317. IF_FEATURE_SEAMLESS_BZ2("/bzip2")
  318. " magic");
  319. }
  320. #if BB_MMU
  321. xformer = unpack_bz2_stream;
  322. #else
  323. xformer_prog = "bunzip2";
  324. #endif
  325. } else {
  326. #if !BB_MMU
  327. /* NOMMU version of open_transformer execs
  328. * an external unzipper that wants
  329. * file position at the start of the file */
  330. xlseek(fd, 0, SEEK_SET);
  331. #endif
  332. }
  333. open_transformer(fd, xformer, xformer_prog);
  334. }
  335. }
  336. return fd;
  337. #endif
  338. }
  339. void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p)
  340. {
  341. int fd;
  342. char *image;
  343. fd = open_zipped(fname);
  344. if (fd < 0)
  345. return NULL;
  346. image = xmalloc_read(fd, maxsz_p);
  347. if (!image)
  348. bb_perror_msg("read error from '%s'", fname);
  349. close(fd);
  350. return image;
  351. }