file.h 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #ifndef FILE_H
  2. #define FILE_H
  3. #include <stdint.h>
  4. #define CONCAT(a, b) CONCAT_INNER(a, b)
  5. #define CONCAT_INNER(a, b) a ## b
  6. #define UNIQUE_NAME(base) CONCAT(base, __COUNTER__)
  7. enum file_err {
  8. FILE_ERR_OK,
  9. FILE_ERR_FAIL_OPEN,
  10. FILE_ERR_FAIL_SEEK,
  11. FILE_ERR_FAIL_READ,
  12. FILE_ERR_FAIL_WRITE,
  13. FILE_ERR_FAIL_CALLOC,
  14. FILE_ERR_FAIL_CLOSE,
  15. FILE_ERR_FILE_EMPTY,
  16. FILE_ERR_FAIL_WROTE_MORE,
  17. FILE_ERR_EMPTY,
  18. };
  19. struct ret_void_p_err {
  20. void *f1; /* ptr */
  21. size_t f2; /* size */
  22. enum file_err f3; /* err */
  23. };
  24. struct ret_void_p_err file_read_all(const char *filepath);
  25. enum file_err file_save(const char *filepath, const char *str, size_t str_size);
  26. #if defined(BMP_IMP) || defined(IMP)
  27. #include <unistd.h>
  28. #include <fcntl.h>
  29. struct ret_void_p_err
  30. file_read_all(const char *filepath)
  31. {
  32. enum file_err err = FILE_ERR_OK;
  33. int32_t fd = open(filepath, O_RDONLY);
  34. if ( fd < 0 ) {
  35. err = FILE_ERR_FAIL_OPEN;
  36. goto err;
  37. }
  38. off_t file_size = lseek(fd, 0, SEEK_END);
  39. if ( file_size < 0 ) {
  40. err = FILE_ERR_FAIL_SEEK;
  41. goto err_close;
  42. }
  43. lseek(fd, 0, SEEK_SET);
  44. printf("file->size = %ld\n", file_size);
  45. if ( file_size == 0 ) {
  46. err = FILE_ERR_EMPTY;
  47. goto err_close;
  48. }
  49. const size_t buf_size = ((size_t)file_size) + 1;
  50. uint8_t *buf = calloc(sizeof(uint8_t), buf_size);
  51. if ( buf == NULL ) {
  52. err = FILE_ERR_FAIL_CALLOC;
  53. goto err_close;
  54. }
  55. {
  56. ssize_t rd = read(fd, buf, (size_t)file_size);
  57. if ( rd < 0 ) {
  58. err = FILE_ERR_FAIL_READ;
  59. free(buf);
  60. goto err_close;
  61. }
  62. if ( rd == 0 ) {
  63. err = FILE_ERR_FILE_EMPTY;
  64. free(buf);
  65. goto err_close;
  66. }
  67. }
  68. if ( close(fd) != 0 ) {
  69. /* It should be possible to handle EIO */
  70. err = FILE_ERR_FAIL_CLOSE;
  71. goto err;
  72. }
  73. return (struct ret_void_p_err) {
  74. .f1 = buf,
  75. .f2 = buf_size,
  76. .f3 = err
  77. };
  78. err_close: ;
  79. if ( close(fd) != 0 ) {
  80. /* It should be possible to handle EIO */
  81. err = FILE_ERR_FAIL_CLOSE;
  82. goto err;
  83. }
  84. err: ;
  85. return (struct ret_void_p_err) {
  86. .f1 = NULL,
  87. .f2 = 0,
  88. .f3 = err
  89. };
  90. }
  91. enum file_err
  92. file_save(const char *filepath, const char *str, size_t str_size)
  93. {
  94. int32_t fd = open(filepath, O_WRONLY);
  95. if ( fd < 0 ) {
  96. return FILE_ERR_FAIL_OPEN;
  97. }
  98. ssize_t wrote = write(fd, str, str_size);
  99. if ( wrote == -1 ) {
  100. return FILE_ERR_FAIL_WRITE;
  101. }
  102. if ( ((size_t) wrote) != str_size ) {
  103. return FILE_ERR_FAIL_WROTE_MORE;
  104. }
  105. if ( close(fd) != 0 ) {
  106. /* It should be possible to handle EIO */
  107. return FILE_ERR_FAIL_CLOSE;
  108. }
  109. return FILE_ERR_OK;
  110. }
  111. #endif
  112. #endif