read.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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. ssize_t safe_read(int fd, void *buf, size_t count)
  11. {
  12. ssize_t n;
  13. do {
  14. n = read(fd, buf, count);
  15. } while (n < 0 && errno == EINTR);
  16. return n;
  17. }
  18. /*
  19. * Read all of the supplied buffer from a file.
  20. * This does multiple reads as necessary.
  21. * Returns the amount read, or -1 on an error.
  22. * A short read is returned on an end of file.
  23. */
  24. ssize_t full_read(int fd, void *buf, size_t len)
  25. {
  26. ssize_t cc;
  27. ssize_t total;
  28. total = 0;
  29. while (len) {
  30. cc = safe_read(fd, buf, len);
  31. if (cc < 0)
  32. return cc; /* read() returns -1 on failure. */
  33. if (cc == 0)
  34. break;
  35. buf = ((char *)buf) + cc;
  36. total += cc;
  37. len -= cc;
  38. }
  39. return total;
  40. }
  41. // Die with an error message if we can't read the entire buffer.
  42. void xread(int fd, void *buf, size_t count)
  43. {
  44. if (count) {
  45. ssize_t size = full_read(fd, buf, count);
  46. if (size != count)
  47. bb_error_msg_and_die("short read");
  48. }
  49. }
  50. // Die with an error message if we can't read one character.
  51. unsigned char xread_char(int fd)
  52. {
  53. char tmp;
  54. xread(fd, &tmp, 1);
  55. return tmp;
  56. }
  57. // Read one line a-la fgets. Works only on seekable streams
  58. char *reads(int fd, char *buffer, size_t size)
  59. {
  60. char *p;
  61. if (size < 2)
  62. return NULL;
  63. size = full_read(fd, buffer, size-1);
  64. if ((ssize_t)size <= 0)
  65. return NULL;
  66. buffer[size] = '\0';
  67. p = strchr(buffer, '\n');
  68. if (p) {
  69. off_t offset;
  70. *p++ = '\0';
  71. // avoid incorrect (unsigned) widening
  72. offset = (off_t)(p-buffer) - (off_t)size;
  73. // set fd position right after '\n'
  74. if (offset && lseek(fd, offset, SEEK_CUR) == (off_t)-1)
  75. return NULL;
  76. }
  77. return buffer;
  78. }
  79. // Read one line a-la fgets. Reads byte-by-byte.
  80. // Useful when it is important to not read ahead.
  81. char *xmalloc_reads(int fd, char *buf)
  82. {
  83. char *p;
  84. int sz = buf ? strlen(buf) : 0;
  85. goto jump_in;
  86. while (1) {
  87. if (p - buf == sz) {
  88. jump_in:
  89. buf = xrealloc(buf, sz + 128);
  90. p = buf + sz;
  91. sz += 128;
  92. }
  93. if (safe_read(fd, p, 1) != 1) { /* EOF/error */
  94. if (p == buf) {
  95. /* we read nothing [and buf was NULL initially] */
  96. free(buf);
  97. return NULL;
  98. }
  99. break;
  100. }
  101. if (*p == '\n')
  102. break;
  103. p++;
  104. }
  105. *p++ = '\0';
  106. return xrealloc(buf, p - buf);
  107. }
  108. ssize_t read_close(int fd, void *buf, size_t size)
  109. {
  110. /*int e;*/
  111. size = full_read(fd, buf, size);
  112. /*e = errno;*/
  113. close(fd);
  114. /*errno = e;*/
  115. return size;
  116. }
  117. ssize_t open_read_close(const char *filename, void *buf, size_t size)
  118. {
  119. int fd = open(filename, O_RDONLY);
  120. if (fd < 0)
  121. return fd;
  122. return read_close(fd, buf, size);
  123. }
  124. // Read (potentially big) files in one go. File size is estimated by
  125. // lseek to end.
  126. void *xmalloc_open_read_close(const char *filename, size_t *sizep)
  127. {
  128. char *buf;
  129. size_t size = sizep ? *sizep : INT_MAX;
  130. int fd;
  131. off_t len;
  132. fd = xopen(filename, O_RDONLY);
  133. /* /proc/N/stat files report len 0 here */
  134. /* In order to make such files readable, we add small const */
  135. len = xlseek(fd, 0, SEEK_END) | 0x3ff; /* + up to 1k */
  136. xlseek(fd, 0, SEEK_SET);
  137. if (len < size)
  138. size = len;
  139. buf = xmalloc(size + 1);
  140. size = read_close(fd, buf, size);
  141. if ((ssize_t)size < 0)
  142. bb_perror_msg_and_die("'%s'", filename);
  143. xrealloc(buf, size + 1);
  144. buf[size] = '\0';
  145. if (sizep)
  146. *sizep = size;
  147. return buf;
  148. }