file.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #ifndef FILE_H
  2. #define FILE_H
  3. #include <stddef.h>
  4. #include <stdint.h>
  5. #define CONCAT(a, b) CONCAT_INNER(a, b)
  6. #define CONCAT_INNER(a, b) a ## b
  7. #define UNIQUE_NAME(base) CONCAT(base, __COUNTER__)
  8. enum file_err {
  9. FILE_ERR_OK,
  10. FILE_ERR_FAIL_OPEN,
  11. FILE_ERR_FAIL_SEEK,
  12. FILE_ERR_FAIL_READ,
  13. FILE_ERR_FAIL_WRITE,
  14. FILE_ERR_FAIL_CALLOC,
  15. FILE_ERR_FAIL_CLOSE,
  16. FILE_ERR_FILE_EMPTY,
  17. FILE_ERR_FAIL_WROTE_MORE,
  18. FILE_ERR_EMPTY
  19. };
  20. uint8_t *file_read_all(const char *filepath, size_t *ret_size,
  21. enum file_err *ret_err);
  22. void file_save(const char *filepath, const char *str, size_t str_size,
  23. enum file_err *ret_err);
  24. void file_err_set(enum file_err *err, enum file_err err_);
  25. const char *file_err_to_cstr(enum file_err err);
  26. #if defined(BMP_IMP) || defined(IMP)
  27. #include <stdlib.h>
  28. #include <unistd.h>
  29. #include <fcntl.h>
  30. #include <sys/stat.h>
  31. uint8_t *
  32. file_read_all(const char *filepath, size_t *ret_size, enum file_err *ret_err)
  33. {
  34. int32_t fd = -1;
  35. off_t file_size = -1;
  36. size_t buf_size = 0;
  37. uint8_t *buf = NULL;
  38. fd = open(filepath, O_RDONLY);
  39. if ( fd < 0 ) {
  40. file_err_set(ret_err, FILE_ERR_FAIL_OPEN);
  41. return NULL;
  42. }
  43. file_size = lseek(fd, 0, SEEK_END);
  44. if ( file_size < 0 ) {
  45. file_err_set(ret_err, FILE_ERR_FAIL_SEEK);
  46. close(fd);
  47. return NULL;
  48. }
  49. lseek(fd, 0, SEEK_SET);
  50. if ( file_size == 0 ) {
  51. file_err_set(ret_err, FILE_ERR_EMPTY);
  52. close(fd);
  53. return NULL;
  54. }
  55. buf_size = ((size_t)file_size) + 1;
  56. buf = calloc(buf_size, sizeof(uint8_t));
  57. if ( buf == NULL ) {
  58. file_err_set(ret_err, FILE_ERR_FAIL_CALLOC);
  59. close(fd);
  60. return NULL;
  61. }
  62. {
  63. ssize_t rd = read(fd, buf, (size_t)file_size);
  64. if ( rd < 0 ) {
  65. file_err_set(ret_err, FILE_ERR_FAIL_READ);
  66. close(fd);
  67. free(buf);
  68. return NULL;
  69. }
  70. if ( rd == 0 ) {
  71. file_err_set(ret_err, FILE_ERR_FILE_EMPTY);
  72. close(fd);
  73. free(buf);
  74. return NULL;
  75. }
  76. }
  77. if ( close(fd) != 0 ) {
  78. /* It should be possible to handle EIO */
  79. file_err_set(ret_err, FILE_ERR_FAIL_CLOSE);
  80. close(fd);
  81. return NULL;
  82. }
  83. if ( ret_size != NULL ) {
  84. *ret_size = buf_size;
  85. }
  86. file_err_set(ret_err, FILE_ERR_OK);
  87. return buf;
  88. }
  89. void
  90. file_save(const char *filepath, const char *str, size_t str_size,
  91. enum file_err *ret_err)
  92. {
  93. ssize_t wrote = -1;
  94. int32_t fd = open(filepath,
  95. O_WRONLY | O_CREAT | O_TRUNC,
  96. S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
  97. if ( fd < 0 ) {
  98. file_err_set(ret_err, FILE_ERR_FAIL_OPEN);
  99. return;
  100. }
  101. wrote = write(fd, str, str_size);
  102. if ( wrote == -1 ) {
  103. file_err_set(ret_err, FILE_ERR_FAIL_WRITE);
  104. return;
  105. }
  106. if ( ((size_t) wrote) != str_size ) {
  107. file_err_set(ret_err, FILE_ERR_FAIL_WROTE_MORE);
  108. return;
  109. }
  110. if ( close(fd) != 0 ) {
  111. /* It should be possible to handle EIO */
  112. file_err_set(ret_err, FILE_ERR_FAIL_CLOSE);
  113. close(fd);
  114. return;
  115. }
  116. file_err_set(ret_err, FILE_ERR_OK);
  117. }
  118. void
  119. file_err_set(enum file_err *err, enum file_err err_)
  120. {
  121. if ( err != NULL ) {
  122. *err = err_;
  123. }
  124. }
  125. const char *
  126. file_err_to_cstr(enum file_err err)
  127. {
  128. switch ( err ) {
  129. case FILE_ERR_OK: return "FILE_ERR_OK"; break;
  130. case FILE_ERR_FAIL_OPEN: return "FILE_ERR_FAIL_OPEN"; break;
  131. case FILE_ERR_FAIL_SEEK: return "FILE_ERR_FAIL_SEEK"; break;
  132. case FILE_ERR_FAIL_READ: return "FILE_ERR_FAIL_READ"; break;
  133. case FILE_ERR_FAIL_WRITE: return "FILE_ERR_FAIL_WRITE"; break;
  134. case FILE_ERR_FAIL_CALLOC: return "FILE_ERR_FAIL_CALLOC"; break;
  135. case FILE_ERR_FAIL_CLOSE: return "FILE_ERR_FAIL_CLOSE"; break;
  136. case FILE_ERR_FILE_EMPTY: return "FILE_ERR_FILE_EMPTY"; break;
  137. case FILE_ERR_FAIL_WROTE_MORE: return "FILE_ERR_FAIL_WROTE_MORE"; break;
  138. case FILE_ERR_EMPTY: return "FILE_ERR_EMPTY"; break;
  139. }
  140. return "FILE ERR INVALID";
  141. }
  142. #endif
  143. #endif