multi_fstream.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /*
  2. * Copyright (c) 2019 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file file stream interface
  8. */
  9. #define SYS_LOG_DOMAIN "filestream"
  10. #include <mem_manager.h>
  11. #include <fs_manager.h>
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <assert.h>
  16. #include "file_stream.h"
  17. #include "stream_internal.h"
  18. /** file info ,used for file stream */
  19. typedef struct {
  20. /** hanlde of file fp*/
  21. struct fs_file_t fp;
  22. /** mutex used for sync*/
  23. os_mutex lock;
  24. multi_file_info_t info;
  25. uint32_t *end_rofs_list;
  26. int cur_file_index;
  27. } mfile_stream_info_t;
  28. static int file_name_has_cluster(char *file_name, char *dir, int max_dir_len, uint32_t *clust, uint32_t *blk_ofs)
  29. {
  30. char *str = NULL;
  31. char *cluster = NULL;
  32. char *blk = NULL;
  33. char *temp_ptr = NULL;
  34. int res = 0;
  35. char *temp_url = mem_malloc(strlen(file_name) + 1);
  36. if (!temp_url)
  37. goto exit;
  38. strcpy(temp_url, file_name);
  39. str = strstr(temp_url,"bycluster:");
  40. if (!str)
  41. goto exit;
  42. str += strlen("bycluster:");
  43. temp_ptr = (void *)str;
  44. /*for dir is /SD:*/
  45. if (*str == '/')
  46. str += 1;
  47. str = strchr(str, '/');
  48. if (!str)
  49. goto exit;
  50. str[0] = 0;
  51. if(strlen(temp_ptr) > max_dir_len) {
  52. memcpy(dir, temp_ptr, max_dir_len);
  53. } else {
  54. memcpy(dir, temp_ptr, strlen(temp_ptr));
  55. }
  56. str++;
  57. str = strstr(str,"cluster:");
  58. if (!str)
  59. goto exit;
  60. str += strlen("cluster:");
  61. cluster = str;
  62. str = strchr(str, '/');
  63. if (!str)
  64. goto exit;
  65. str[0] = 0;
  66. str++;
  67. blk = str;
  68. str = strchr(str, '/');
  69. if (!str)
  70. goto exit;
  71. str[0] = 0;
  72. *clust = atoi(cluster);
  73. *blk_ofs = atoi(blk);
  74. SYS_LOG_DBG("dir=%s,clust=%d,blk_ofs=%d\n", *dir, *clust, *blk_ofs);
  75. res = 1;
  76. exit:
  77. if (temp_url)
  78. mem_free(temp_url);
  79. return res;
  80. }
  81. static int _open_file(mfile_stream_info_t *info, multi_file_info_t *file_info, int index)
  82. {
  83. char dir[16] = {0};
  84. uint32_t cluster = 0;
  85. uint32_t blk_ofs = 0;
  86. int ret;
  87. char sbuf[25] = {0};
  88. file_info->get_file_name(file_info->usr_data, index, sbuf, sizeof(sbuf));
  89. if (file_name_has_cluster(sbuf, dir, sizeof(dir), &cluster, &blk_ofs)) {
  90. ret = fs_open_cluster(&info->fp, dir, cluster, blk_ofs);
  91. if (ret) {
  92. SYS_LOG_ERR("open Failed %d\n", ret);
  93. return ret;
  94. }
  95. } else {
  96. ret = fs_open(&info->fp, sbuf, FA_READ);
  97. if (ret) {
  98. SYS_LOG_ERR("open Failed %d\n", ret);
  99. return ret;
  100. }
  101. }
  102. return 0;
  103. }
  104. static int mfstream_open(io_stream_t handle, stream_mode mode)
  105. {
  106. mfile_stream_info_t *info = (mfile_stream_info_t *)handle->data;
  107. multi_file_info_t *file_info = &info->info;
  108. int i;
  109. int ret;
  110. assert(info);
  111. handle->mode = mode;
  112. handle->write_finished = 0;
  113. handle->cache_size = 0;
  114. handle->total_size = 0;
  115. for (i=0; i<file_info->file_count; i++) {
  116. ret = _open_file(info, file_info, i);
  117. if(ret) {
  118. goto failed;
  119. }
  120. if (!fs_seek(&info->fp, 0, FS_SEEK_END)) {
  121. handle->total_size += fs_tell(&info->fp);
  122. info->end_rofs_list[i] = handle->total_size;
  123. }
  124. fs_close(&info->fp);
  125. }
  126. handle->wofs = handle->total_size;
  127. _open_file(info, file_info, 0);
  128. SYS_LOG_INF("handle %p total_size %d mode %x \n",handle, handle->total_size, mode);
  129. return 0;
  130. failed:
  131. return ret;
  132. }
  133. static int mfstream_read(io_stream_t handle, unsigned char *buf, int num)
  134. {
  135. int brw;
  136. mfile_stream_info_t *info = (mfile_stream_info_t *)handle->data;
  137. multi_file_info_t *file_info = &info->info;
  138. int read_num;
  139. uint32_t rofs = handle->rofs;
  140. assert(info);
  141. brw = os_mutex_lock(&info->lock, OS_FOREVER);
  142. if (brw < 0){
  143. SYS_LOG_ERR("lock failed %d \n",brw);
  144. return brw;
  145. }
  146. if ((handle->rofs + num) <= info->end_rofs_list[info->cur_file_index]) {
  147. read_num = num;
  148. } else if (handle->rofs < info->end_rofs_list[info->cur_file_index]) {
  149. read_num = info->end_rofs_list[info->cur_file_index] - handle->rofs;
  150. } else {
  151. read_num = 0;
  152. }
  153. if (info->cur_file_index >= file_info->file_count) {
  154. goto err_out;
  155. }
  156. if(read_num) {
  157. brw = fs_read(&info->fp, buf, read_num);
  158. if (brw < 0) {
  159. SYS_LOG_ERR(" failed %d\n", brw);
  160. goto err_out;
  161. }
  162. handle->rofs += brw;
  163. }
  164. if ((read_num < num) && (info->cur_file_index < (file_info->file_count - 1))) {
  165. info->cur_file_index++;
  166. fs_close(&info->fp);
  167. _open_file(info, file_info, info->cur_file_index);
  168. brw = fs_read(&info->fp, (buf + read_num), (num - read_num));
  169. if (brw < 0) {
  170. SYS_LOG_ERR(" failed %d\n", brw);
  171. goto err_out;
  172. }
  173. handle->rofs += brw;
  174. }
  175. os_mutex_unlock(&info->lock);
  176. return handle->rofs - rofs;
  177. err_out:
  178. os_mutex_unlock(&info->lock);
  179. return brw;
  180. }
  181. static int mfstream_seek(io_stream_t handle, int offset, seek_dir origin)
  182. {
  183. mfile_stream_info_t *info = (mfile_stream_info_t *)handle->data;
  184. multi_file_info_t *file_info = &info->info;
  185. int offset_local = 0;
  186. int brw = 0;
  187. uint8_t fp_index = 0;
  188. assert(info);
  189. switch (origin) {
  190. case SEEK_DIR_CUR:
  191. offset_local = handle->rofs + offset;
  192. break;
  193. case SEEK_DIR_END:
  194. offset_local = handle->total_size + offset;
  195. break;
  196. case SEEK_DIR_BEG:
  197. offset_local = offset;
  198. break;
  199. default:
  200. break;
  201. }
  202. for (fp_index = 0; fp_index < file_info->file_count; fp_index++) {
  203. if (offset_local <= info->end_rofs_list[fp_index]) {
  204. if (fp_index) {
  205. offset_local -= info->end_rofs_list[fp_index - 1];
  206. }
  207. break;
  208. }
  209. }
  210. if (fp_index >= file_info->file_count) {
  211. return -1;
  212. }
  213. if(fp_index != info->cur_file_index) {
  214. info->cur_file_index = fp_index;
  215. fs_close(&info->fp);
  216. _open_file(info, file_info, info->cur_file_index);
  217. }
  218. brw = fs_seek(&info->fp, offset_local, SEEK_DIR_BEG);
  219. if (brw) {
  220. SYS_LOG_ERR("seek failed %d\n", brw);
  221. return -1;
  222. }
  223. offset_local = fs_tell(&info->fp);
  224. if (fp_index) {
  225. offset_local += info->end_rofs_list[fp_index - 1];
  226. }
  227. handle->rofs = offset_local;
  228. return 0;
  229. }
  230. static int mfstream_tell(io_stream_t handle)
  231. {
  232. return handle->rofs;
  233. }
  234. static int mfstream_close(io_stream_t handle)
  235. {
  236. int res;
  237. mfile_stream_info_t *info = (mfile_stream_info_t *)handle->data;
  238. assert(info);
  239. res = os_mutex_lock(&info->lock, OS_FOREVER);
  240. if (res < 0) {
  241. SYS_LOG_ERR("lock failed %d \n",res);
  242. return res;
  243. }
  244. handle->wofs = 0;
  245. handle->rofs = 0;
  246. handle->state = STATE_CLOSE;
  247. os_mutex_unlock(&info->lock);
  248. return res;
  249. }
  250. static int mfstream_destroy(io_stream_t handle)
  251. {
  252. int res;
  253. mfile_stream_info_t *info = (mfile_stream_info_t *)handle->data;
  254. assert(info);
  255. res = os_mutex_lock(&info->lock, OS_FOREVER);
  256. if (res < 0) {
  257. SYS_LOG_ERR("lock failed %d \n",res);
  258. return res;
  259. }
  260. res = fs_close(&info->fp);
  261. if (res) {
  262. SYS_LOG_ERR("close failed %d\n", res);
  263. }
  264. os_mutex_unlock(&info->lock);
  265. mem_free(info);
  266. return res;
  267. }
  268. static int mfstream_init(io_stream_t handle, void *param)
  269. {
  270. mfile_stream_info_t *info;
  271. multi_file_info_t *file_info = (multi_file_info_t*)param;
  272. info = mem_malloc(sizeof(mfile_stream_info_t) + file_info->file_count * sizeof(uint32_t));
  273. if (!info) {
  274. SYS_LOG_ERR("no memory\n");
  275. return -ENOMEM;
  276. }
  277. info->end_rofs_list = (uint32_t*)(info + 1);
  278. memcpy(&info->info, file_info, sizeof(multi_file_info_t));
  279. os_mutex_init(&info->lock);
  280. handle->data = info;
  281. return 0;
  282. }
  283. static const stream_ops_t file_stream_ops = {
  284. .init = mfstream_init,
  285. .open = mfstream_open,
  286. .read = mfstream_read,
  287. .seek = mfstream_seek,
  288. .tell = mfstream_tell,
  289. .write = NULL,
  290. .flush = NULL,
  291. .get_space = NULL,
  292. .close = mfstream_close,
  293. .destroy = mfstream_destroy,
  294. };
  295. io_stream_t multi_file_stream_create(multi_file_info_t *param)
  296. {
  297. return stream_create(&file_stream_ops, (void *)param);
  298. }