read.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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. ssize_t read_close(int fd, void *buf, size_t size)
  80. {
  81. int e;
  82. size = full_read(fd, buf, size);
  83. e = errno;
  84. close(fd);
  85. errno = e;
  86. return size;
  87. }
  88. ssize_t open_read_close(const char *filename, void *buf, size_t size)
  89. {
  90. int fd = open(filename, O_RDONLY);
  91. if (fd < 0)
  92. return fd;
  93. return read_close(fd, buf, size);
  94. }
  95. void *xmalloc_open_read_close(const char *filename, size_t *sizep)
  96. {
  97. char *buf;
  98. size_t size = sizep ? *sizep : INT_MAX;
  99. int fd = xopen(filename, O_RDONLY);
  100. /* /proc/N/stat files report len 0 here */
  101. /* In order to make such files readable, we add small const */
  102. off_t len = xlseek(fd, 0, SEEK_END) + 256;
  103. xlseek(fd, 0, SEEK_SET);
  104. if (len > size)
  105. bb_error_msg_and_die("file '%s' is too big", filename);
  106. size = len;
  107. buf = xmalloc(size + 1);
  108. size = read_close(fd, buf, size);
  109. if ((ssize_t)size < 0)
  110. bb_perror_msg_and_die("'%s'", filename);
  111. xrealloc(buf, size + 1);
  112. buf[size] = '\0';
  113. if (sizep) *sizep = size;
  114. return buf;
  115. }