fdb_file.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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 "fdb_low_lvl.h"
  10. #include "flashdb.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 <fcntl.h>
  33. #include <sys/stat.h>
  34. #include <sys/types.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, pika_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, pika_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. pika_bool sync) {
  85. fdb_err_t result = FDB_NO_ERR;
  86. int fd = open_db_file(db, addr, pika_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, pika_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, pika_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. pika_platform_fclose(db->cur_file);
  130. db->cur_file = 0;
  131. }
  132. if (clean) {
  133. /* clean the old file */
  134. db->cur_file = pika_platform_fopen(path, "wb+");
  135. if (db->cur_file == NULL) {
  136. FDB_INFO("Error: open (%s) file failed.\n", path);
  137. } else {
  138. pika_platform_fclose(db->cur_file);
  139. db->cur_file = 0;
  140. }
  141. }
  142. /* open the database file to read and write */
  143. db->cur_file = pika_platform_fopen(path, "rb+");
  144. db->cur_sec = sec_addr;
  145. }
  146. return db->cur_file;
  147. }
  148. fdb_err_t _fdb_file_read(fdb_db_t db, uint32_t addr, void* buf, size_t size) {
  149. fdb_err_t result = FDB_NO_ERR;
  150. FILE* fp = open_db_file(db, addr, pika_false);
  151. if (fp) {
  152. addr = addr % db->sec_size;
  153. if ((pika_platform_fseek(fp, addr, SEEK_SET) != 0)) {
  154. printf("Error: seek (%s) file failed.\n", db->name);
  155. result = FDB_READ_ERR;
  156. }
  157. size_t sizer = pika_platform_fread(buf, 1, size, fp);
  158. if (sizer != size) {
  159. printf("Error: read (%s) file failed.\n", db->name);
  160. result = FDB_READ_ERR;
  161. }
  162. } else {
  163. result = FDB_READ_ERR;
  164. }
  165. return result;
  166. }
  167. fdb_err_t _fdb_file_write(fdb_db_t db,
  168. uint32_t addr,
  169. const void* buf,
  170. size_t size,
  171. pika_bool sync) {
  172. fdb_err_t result = FDB_NO_ERR;
  173. FILE* fp = open_db_file(db, addr, pika_false);
  174. if (fp) {
  175. addr = addr % db->sec_size;
  176. if ((pika_platform_fseek(fp, addr, SEEK_SET) != 0)) {
  177. printf("Error: seek (%s) file failed.\n", db->name);
  178. result = FDB_READ_ERR;
  179. }
  180. size_t sizew = pika_platform_fwrite(buf, 1, size, fp);
  181. if (sizew != size) {
  182. printf("Error: write (%s) file failed.\n", db->name);
  183. result = FDB_WRITE_ERR;
  184. }
  185. if (sync) {
  186. pika_platform_fflush(fp);
  187. }
  188. } else {
  189. result = FDB_READ_ERR;
  190. }
  191. return result;
  192. }
  193. fdb_err_t _fdb_file_erase(fdb_db_t db, uint32_t addr, size_t size) {
  194. fdb_err_t result = FDB_NO_ERR;
  195. FILE* fp = open_db_file(db, addr, pika_true);
  196. if (fp != NULL) {
  197. #define BUF_SIZE 32
  198. uint8_t buf[BUF_SIZE];
  199. size_t i;
  200. pika_platform_fseek(fp, 0, SEEK_SET);
  201. for (i = 0; i * BUF_SIZE < size; i++) {
  202. memset(buf, 0xFF, BUF_SIZE);
  203. size_t sizew = pika_platform_fwrite(buf, 1, BUF_SIZE, fp);
  204. if (sizew != BUF_SIZE) {
  205. FDB_PRINT("Error: write (%s) file failed.\n", db->name);
  206. result = FDB_WRITE_ERR;
  207. break;
  208. }
  209. }
  210. memset(buf, 0xFF, BUF_SIZE);
  211. size_t sizew = pika_platform_fwrite(buf, 1, size - i * BUF_SIZE, fp);
  212. if (sizew != size - i * BUF_SIZE) {
  213. FDB_PRINT("Error: write (%s) file failed.\n", db->name);
  214. result = FDB_WRITE_ERR;
  215. }
  216. pika_platform_fflush(fp);
  217. } else {
  218. result = FDB_ERASE_ERR;
  219. }
  220. return result;
  221. }
  222. #endif /* defined(FDB_USING_FILE_LIBC_MODE) */
  223. #endif /* FDB_USING_FILE_MODE */