io.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /** @file io.c
  2. * @brief Enchanced base IO functions.
  3. */
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <assert.h>
  7. #include <errno.h>
  8. #include <stdio.h>
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <sys/uio.h>
  12. #include <sys/stat.h>
  13. #include <fcntl.h>
  14. #include <poll.h>
  15. #include "faux/faux.h"
  16. /** @brief Writes data to file.
  17. *
  18. * The system write() can be interrupted by signal. This function will retry to
  19. * write in a case of interrupted call.
  20. *
  21. * @param [in] fd File descriptor.
  22. * @param [in] buf Buffer to write.
  23. * @param [in] n Number of bytes to write.
  24. * @return Number of bytes written or < 0 on error.
  25. */
  26. ssize_t faux_write(int fd, const void *buf, size_t n)
  27. {
  28. ssize_t bytes_written = 0;
  29. assert(fd != -1);
  30. assert(buf);
  31. if ((-1 == fd) || !buf)
  32. return -1;
  33. if (0 == n)
  34. return 0;
  35. do {
  36. bytes_written = write(fd, buf, n);
  37. } while ((bytes_written < 0) && (EINTR == errno));
  38. return bytes_written;
  39. }
  40. /** @brief Writes data block to file.
  41. *
  42. * The system write() can be interrupted by signal or can write less bytes
  43. * than specified. This function will continue to write data until all data
  44. * will be written or error occured. Function support even non-blocking file
  45. * descriptors. It uses poll() for such fd.
  46. *
  47. * @param [in] fd File descriptor.
  48. * @param [in] buf Buffer to write.
  49. * @param [in] n Number of bytes to write.
  50. * @return Number of bytes written.
  51. * < n then insufficient space or error (but some data was already written).
  52. * < 0 - error.
  53. */
  54. ssize_t faux_write_block(int fd, const void *buf, size_t n)
  55. {
  56. size_t total_written = 0;
  57. size_t left = n;
  58. const void *data = buf;
  59. struct pollfd fds = {};
  60. fds.fd = fd;
  61. fds.events = POLLOUT;
  62. do {
  63. int prc = 0;
  64. fds.revents = 0; // Reset revents before poll()
  65. prc = poll(&fds, 1, -1);
  66. if (prc < 0) {
  67. if (EINTR == errno)
  68. continue;
  69. if (total_written != 0)
  70. break;
  71. return -1;
  72. }
  73. if (fds.revents & POLLOUT) {
  74. ssize_t bytes_written = 0;
  75. bytes_written = faux_write(fd, data, left);
  76. if (bytes_written < 0) { // Error
  77. if (total_written != 0)
  78. break;
  79. return -1;
  80. }
  81. if (0 == bytes_written) // Insufficient space
  82. break;
  83. data += bytes_written;
  84. left = left - bytes_written;
  85. total_written += bytes_written;
  86. }
  87. if (fds.revents & (POLLHUP | POLLERR | POLLNVAL)) {
  88. if (total_written != 0)
  89. break;
  90. return -1;
  91. }
  92. } while (left > 0);
  93. return total_written;
  94. }
  95. /** @brief Reads data from file.
  96. *
  97. * The system read() can be interrupted by signal. This function will retry to
  98. * read if it was interrupted by signal.
  99. *
  100. * @param [in] fd File descriptor.
  101. * @param [in] buf Buffer to write.
  102. * @param [in] n Number of bytes to write.
  103. * @return Number of bytes readed or < 0 on error.
  104. * 0 bytes indicates EOF
  105. */
  106. ssize_t faux_read(int fd, void *buf, size_t n)
  107. {
  108. ssize_t bytes_readed = 0;
  109. assert(fd != -1);
  110. assert(buf);
  111. if ((-1 == fd) || !buf)
  112. return -1;
  113. if (0 == n)
  114. return 0;
  115. do {
  116. bytes_readed = read(fd, buf, n);
  117. } while ((bytes_readed < 0) && (EINTR == errno));
  118. return bytes_readed;
  119. }
  120. /** @brief Reads data block from file.
  121. *
  122. * The system read() can be interrupted by signal or can read less bytes
  123. * than specified. This function will continue to read data until all data
  124. * will be readed or error occured. Function works even for non-blocking
  125. * file descriptors.
  126. *
  127. * @param [in] fd File descriptor.
  128. * @param [in] buf Buffer to write.
  129. * @param [in] n Number of bytes to write.
  130. * @return Number of bytes readed.
  131. * < n EOF or error (but some data was already readed).
  132. * < 0 Error.
  133. */
  134. size_t faux_read_block(int fd, void *buf, size_t n)
  135. {
  136. size_t total_readed = 0;
  137. size_t left = n;
  138. void *data = buf;
  139. struct pollfd fds = {};
  140. fds.fd = fd;
  141. fds.events = POLLIN;
  142. do {
  143. int prc = 0;
  144. fds.revents = 0; // Reset revents before poll()
  145. prc = poll(&fds, 1, -1);
  146. if (prc < 0) {
  147. if (EINTR == errno)
  148. continue;
  149. if (total_readed != 0)
  150. break;
  151. return -1;
  152. }
  153. if (fds.revents & POLLIN) {
  154. ssize_t bytes_readed = 0;
  155. bytes_readed = read(fd, data, left);
  156. if (bytes_readed < 0) {
  157. if (total_readed != 0)
  158. break;
  159. return -1;
  160. }
  161. if (0 == bytes_readed) // EOF
  162. break;
  163. data += bytes_readed;
  164. left = left - bytes_readed;
  165. total_readed += bytes_readed;
  166. }
  167. if (fds.revents & (POLLHUP | POLLERR | POLLNVAL)) {
  168. if (total_readed != 0)
  169. break;
  170. return -1;
  171. }
  172. } while (left > 0);
  173. return total_readed;
  174. }
  175. /** @brief Reads whole file to buffer.
  176. *
  177. * Allocates buffer and read whole file to it.
  178. *
  179. * @param [in] path File name.
  180. * @param [out] buf Output buffer with file content.
  181. * @warn Buffer must be freed with faux_free().
  182. * @return Number of bytes readed.
  183. * = n Empty file. The data param will be set to NULL.
  184. * < 0 Error.
  185. */
  186. ssize_t faux_read_whole_file(const char *path, void **data)
  187. {
  188. ssize_t expected_size = 0;
  189. struct stat statbuf = {};
  190. char *buf = NULL;
  191. size_t buf_full_size = 0;
  192. ssize_t bytes_readed = 0;
  193. size_t total_readed = 0;
  194. int fd = -1;
  195. assert(path);
  196. assert(data);
  197. if (!path || !data)
  198. return -1;
  199. if (stat(path, &statbuf) < 0)
  200. return -1;
  201. // Regular file?
  202. if (!S_ISREG(statbuf.st_mode))
  203. return -1;
  204. // Get expected file size
  205. expected_size = faux_filesize(path);
  206. if (expected_size < 0)
  207. return -1;
  208. // Add some extra space to buffer. Because actual filesize can
  209. // differ while reading. Try to read more data than expected.
  210. expected_size++;
  211. // Open file
  212. fd = open(path, O_RDONLY);
  213. if (fd < 0)
  214. return -1;
  215. // Allocate buffer
  216. buf_full_size = expected_size;
  217. buf = faux_zmalloc(buf_full_size);
  218. if (!buf) {
  219. close(fd);
  220. return -1;
  221. }
  222. while ((bytes_readed = faux_read(fd, buf + total_readed,
  223. buf_full_size - total_readed)) > 0) {
  224. total_readed += bytes_readed;
  225. // Enlarge buffer if needed
  226. if (total_readed == buf_full_size) {
  227. char *p = NULL;
  228. buf_full_size = buf_full_size * 2;
  229. p = realloc(buf, buf_full_size);
  230. if (!p) {
  231. free(buf);
  232. close(fd);
  233. return -1;
  234. }
  235. buf = p;
  236. }
  237. }
  238. close(fd);
  239. // Something went wrong
  240. if (bytes_readed < 0) {
  241. free(buf);
  242. return -1;
  243. }
  244. // Empty file
  245. if (0 == total_readed) {
  246. free(buf);
  247. *data = NULL;
  248. return 0;
  249. }
  250. // Shrink buffer to actual data size
  251. if (total_readed < buf_full_size) {
  252. char *p = NULL;
  253. p = realloc(buf, total_readed);
  254. if (!p) {
  255. free(buf);
  256. return -1;
  257. }
  258. buf = p;
  259. }
  260. *data = buf;
  261. return total_readed;
  262. }