fdb_file.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
  3. * Copyright (c) 2020, enkiller, <462747508@qq.com>
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. */
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include "flashdb.h"
  10. #include "fdb_low_lvl.h"
  11. #define FDB_LOG_TAG "[file]"
  12. #ifdef FDB_USING_FILE_MODE
  13. #define DB_PATH_MAX 256
  14. static void get_db_file_path(fdb_db_t db,
  15. uint32_t addr,
  16. char* path,
  17. size_t size) {
  18. #define DB_NAME_MAX 8
  19. /* from db_name.fdb.0 to db_name.fdb.n */
  20. char file_name[DB_NAME_MAX + 4 + 10];
  21. uint32_t sec_addr = FDB_ALIGN_DOWN(addr, db->sec_size);
  22. int index = sec_addr / db->sec_size;
  23. snprintf(file_name, sizeof(file_name), "%.*s.fdb.%d", DB_NAME_MAX, db->name,
  24. index);
  25. if (strlen(db->storage.dir) + 1 + strlen(file_name) >= size) {
  26. /* path is too long */
  27. FDB_ASSERT(0)
  28. }
  29. snprintf(path, size, "%s/%s", db->storage.dir, file_name);
  30. }
  31. #if defined(FDB_USING_FILE_POSIX_MODE)
  32. #include <sys/types.h>
  33. #include <sys/stat.h>
  34. #include <fcntl.h>
  35. #if !defined(_MSC_VER)
  36. #include <unistd.h>
  37. #endif
  38. static int open_db_file(fdb_db_t db, uint32_t addr, bool clean) {
  39. uint32_t sec_addr = FDB_ALIGN_DOWN(addr, db->sec_size);
  40. int fd = db->cur_file;
  41. char path[DB_PATH_MAX];
  42. if (sec_addr != db->cur_sec || fd <= 0 || clean) {
  43. get_db_file_path(db, addr, path, DB_PATH_MAX);
  44. if (fd > 0) {
  45. close(fd);
  46. fd = -1;
  47. }
  48. if (clean) {
  49. /* clean the old file */
  50. fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0777);
  51. if (fd <= 0) {
  52. FDB_INFO("Error: open (%s) file failed.\n", path);
  53. } else {
  54. close(fd);
  55. fd = -1;
  56. }
  57. }
  58. /* open the database file */
  59. fd = open(path, O_RDWR, 0777);
  60. db->cur_sec = sec_addr;
  61. }
  62. db->cur_file = fd;
  63. return db->cur_file;
  64. }
  65. fdb_err_t _fdb_file_read(fdb_db_t db, uint32_t addr, void* buf, size_t size) {
  66. fdb_err_t result = FDB_NO_ERR;
  67. int fd = open_db_file(db, addr, false);
  68. if (fd > 0) {
  69. /* get the offset address is relative to the start of the current file
  70. */
  71. addr = addr % db->sec_size;
  72. if ((lseek(fd, addr, SEEK_SET) != addr) ||
  73. (read(fd, buf, size) != size))
  74. result = FDB_READ_ERR;
  75. } else {
  76. result = FDB_READ_ERR;
  77. }
  78. return result;
  79. }
  80. fdb_err_t _fdb_file_write(fdb_db_t db,
  81. uint32_t addr,
  82. const void* buf,
  83. size_t size,
  84. bool sync) {
  85. fdb_err_t result = FDB_NO_ERR;
  86. int fd = open_db_file(db, addr, false);
  87. if (fd > 0) {
  88. /* get the offset address is relative to the start of the current file
  89. */
  90. addr = addr % db->sec_size;
  91. if ((lseek(fd, addr, SEEK_SET) != addr) ||
  92. (write(fd, buf, size) != size))
  93. result = FDB_WRITE_ERR;
  94. if (sync) {
  95. fsync(fd);
  96. }
  97. } else {
  98. result = FDB_WRITE_ERR;
  99. }
  100. return result;
  101. }
  102. fdb_err_t _fdb_file_erase(fdb_db_t db, uint32_t addr, size_t size) {
  103. fdb_err_t result = FDB_NO_ERR;
  104. int fd = open_db_file(db, addr, true);
  105. if (fd > 0) {
  106. #define BUF_SIZE 32
  107. uint8_t buf[BUF_SIZE];
  108. size_t i;
  109. lseek(fd, 0, SEEK_SET);
  110. for (i = 0; i * BUF_SIZE < size; i++) {
  111. memset(buf, 0xFF, BUF_SIZE);
  112. write(fd, buf, BUF_SIZE);
  113. }
  114. memset(buf, 0xFF, BUF_SIZE);
  115. write(fd, buf, size - i * BUF_SIZE);
  116. fsync(fd);
  117. } else {
  118. result = FDB_ERASE_ERR;
  119. }
  120. return result;
  121. }
  122. #elif defined(FDB_USING_FILE_LIBC_MODE)
  123. static FILE* open_db_file(fdb_db_t db, uint32_t addr, bool clean) {
  124. uint32_t sec_addr = FDB_ALIGN_DOWN(addr, db->sec_size);
  125. if (sec_addr != db->cur_sec || db->cur_file == NULL || clean) {
  126. char path[DB_PATH_MAX];
  127. get_db_file_path(db, addr, path, DB_PATH_MAX);
  128. if (db->cur_file) {
  129. fclose(db->cur_file);
  130. }
  131. if (clean) {
  132. /* clean the old file */
  133. db->cur_file = fopen(path, "wb+");
  134. if (db->cur_file == NULL) {
  135. FDB_INFO("Error: open (%s) file failed.\n", path);
  136. } else {
  137. fclose(db->cur_file);
  138. }
  139. }
  140. /* open the database file */
  141. db->cur_file = fopen(path, "rb+");
  142. db->cur_sec = sec_addr;
  143. }
  144. return db->cur_file;
  145. }
  146. fdb_err_t _fdb_file_read(fdb_db_t db, uint32_t addr, void* buf, size_t size) {
  147. fdb_err_t result = FDB_NO_ERR;
  148. FILE* fp = open_db_file(db, addr, false);
  149. if (fp) {
  150. addr = addr % db->sec_size;
  151. if ((fseek(fp, addr, SEEK_SET) != 0) ||
  152. (fread(buf, size, 1, fp) != size))
  153. result = FDB_READ_ERR;
  154. } else {
  155. result = FDB_READ_ERR;
  156. }
  157. return result;
  158. }
  159. fdb_err_t _fdb_file_write(fdb_db_t db,
  160. uint32_t addr,
  161. const void* buf,
  162. size_t size,
  163. bool sync) {
  164. fdb_err_t result = FDB_NO_ERR;
  165. FILE* fp = open_db_file(db, addr, false);
  166. if (fp) {
  167. addr = addr % db->sec_size;
  168. if ((fseek(fp, addr, SEEK_SET) != 0) ||
  169. (fwrite(buf, size, 1, fp) != size))
  170. result = FDB_READ_ERR;
  171. if (sync) {
  172. fflush(fp);
  173. }
  174. } else {
  175. result = FDB_READ_ERR;
  176. }
  177. return result;
  178. }
  179. fdb_err_t _fdb_file_erase(fdb_db_t db, uint32_t addr, size_t size) {
  180. fdb_err_t result = FDB_NO_ERR;
  181. FILE* fp = open_db_file(db, addr, true);
  182. if (fp != NULL) {
  183. #define BUF_SIZE 32
  184. uint8_t buf[BUF_SIZE];
  185. size_t i;
  186. fseek(fp, 0, SEEK_SET);
  187. for (i = 0; i * BUF_SIZE < size; i++) {
  188. memset(buf, 0xFF, BUF_SIZE);
  189. fwrite(buf, BUF_SIZE, 1, fp);
  190. }
  191. memset(buf, 0xFF, BUF_SIZE);
  192. fwrite(buf, size - i * BUF_SIZE, 1, fp);
  193. fflush(fp);
  194. } else {
  195. result = FDB_ERASE_ERR;
  196. }
  197. return result;
  198. }
  199. #endif /* defined(FDB_USING_FILE_LIBC_MODE) */
  200. #endif /* FDB_USING_FILE_MODE */