rdbd_file.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  1. /*
  2. * Copyright (c) 2018, Real-Thread Information Technology Ltd
  3. * All rights reserved
  4. *
  5. * This software is dual-licensed: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation. For the terms of this
  8. * license, see <http://www.gnu.org/licenses/>.
  9. *
  10. * You are free to use this software under the terms of the GNU General
  11. * Public License, but WITHOUT ANY WARRANTY; without even the implied
  12. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. * See the GNU General Public License for more details.
  14. *
  15. * Alternatively, you can license this software under a commercial
  16. * license, please send mail to business@rt-thread.com for contact.
  17. *
  18. * Change Logs:
  19. * Date Author Notes
  20. * 2018-09-25 ZYH the first version
  21. */
  22. #include <rdbd.h>
  23. #include "rtdevice.h"
  24. #include <stdio.h>
  25. #include <string.h>
  26. //#include <dirent.h>
  27. #include <dstr.h>
  28. #include <rdbd_service.h>
  29. #include <rdbd_service_manager.h>
  30. #include <fcntl.h>
  31. #include <sys/time.h>
  32. #include <libc.h>
  33. #include <dfs_select.h>
  34. #include <dfs_posix.h>
  35. //select dfs
  36. //select libc
  37. //select dstr v0.2.0
  38. #define RDBD_FILE_HASH_FNV_SEED 0x811C9DC5
  39. #undef DBG_ENABLE
  40. #define DBG_SECTION_NAME "RDBD FILE"
  41. #define DBG_LEVEL DBG_LOG
  42. #define DBG_COLOR
  43. #include <rtdbg.h>
  44. #define RDBD_FILE_CTRL_NEW_FILE 0x40
  45. #define RDBD_FILE_CTRL_WRITE_FILE 0x41
  46. #define RDBD_FILE_CTRL_WRITE_DONE 0x42
  47. #define RDBD_FILE_CTRL_LIST_DIR 0x43
  48. #define RDBD_FILE_CTRL_READ_FILE 0x44
  49. #define RDBD_FILE_CTRL_RM_FILE 0x45
  50. #define RDBD_FTLE_CTRL_GET_HASH 0x46
  51. #define RDBD_FTLE_CTRL_DIR_SYNC_START 0x47
  52. #define RDBD_FTLE_CTRL_DIR_SYNC_STOP 0x48
  53. #define RDBD_FTLE_CTRL_CHECK_PATH 0x49
  54. #define RDBD_FTLE_CTRL_PATH_IS_DIR 0x01
  55. #define RDBD_FTLE_CTRL_PATH_IS_FILE 0x02
  56. #define RDBD_FTLE_CTRL_PATH_NONE 0x00
  57. #define RDBD_FILE_READ_BLOCK_SIZE 4096
  58. #define RDBD_FILE_HEADER_SIZE (sizeof(struct rdbd_file_control_msg_header))
  59. #define RDBD_FILE_MSG_SIZE(x) (RDBD_FILE_MSG_MSG(x)->header.pathlength + RDBD_FILE_MSG_MSG(x)->header.length + RDBD_FILE_HEADER_SIZE)
  60. #define RDBD_FILE_MSG_RAW(x) ((rt_uint8_t *)x)
  61. #define RDBD_FILE_MSG_MSG(x) ((rdbd_file_ctrl_msg_t)x)
  62. struct rdbd_file_control_msg_header
  63. {
  64. rt_uint16_t command;
  65. rt_uint16_t pathlength;
  66. rt_uint32_t offset;
  67. rt_uint32_t length;
  68. };
  69. struct rdbd_file_session
  70. {
  71. rt_list_t list;
  72. char * path;
  73. int flag;
  74. int fd;
  75. };
  76. static struct rdbd_file_session * create_session(rt_list_t * session_list, char * path, int flag)
  77. {
  78. struct rdbd_file_session * session;
  79. if(session_list )
  80. session = rt_calloc(sizeof(struct rdbd_file_session), 1);
  81. if(RT_NULL == session_list || RT_NULL == path)
  82. {
  83. LOG_E("Invalid args %s,%d", __FUNCTION__, __LINE__);
  84. return RT_NULL;
  85. }
  86. session->fd = -1;
  87. session->flag = flag;
  88. session->path = rt_strdup(path);
  89. if(RT_NULL == session->path)
  90. {
  91. LOG_E("No memory create session");
  92. goto _error;
  93. }
  94. session->fd = open(session->path, session->flag);
  95. if(session->fd < 0)
  96. {
  97. LOG_E("Open file %s error", session->path);
  98. goto _error;
  99. }
  100. rt_list_insert_before(session_list, &session->list);
  101. return session;
  102. _error:
  103. if(session)
  104. {
  105. if(session->path)
  106. {
  107. rt_free(session->path);
  108. }
  109. if(session->fd >= 0)
  110. {
  111. close(session->fd);
  112. }
  113. free(session);
  114. }
  115. return RT_NULL;
  116. }
  117. static struct rdbd_file_session * find_session(rt_list_t * session_list, char * path)
  118. {
  119. rt_list_t * node;
  120. if(RT_NULL == session_list || RT_NULL == path)
  121. {
  122. LOG_E("Invalid args %s,%d", __FUNCTION__, __LINE__);
  123. return RT_NULL;
  124. }
  125. for(node = session_list->next;
  126. node != session_list;
  127. node = node->next)
  128. {
  129. if(strcmp(path, rt_list_entry(node, struct rdbd_file_session, list)->path) == 0)
  130. {
  131. return rt_list_entry(node, struct rdbd_file_session, list);
  132. }
  133. }
  134. return RT_NULL;
  135. }
  136. static int delete_session(struct rdbd_file_session * session)
  137. {
  138. if(RT_NULL == session)
  139. {
  140. LOG_E("Invalid args %s,%d", __FUNCTION__, __LINE__);
  141. return -1;
  142. }
  143. fsync(session->fd);
  144. close(session->fd);
  145. rt_free(session->path);
  146. rt_list_remove(&session->list);
  147. rt_free(session);
  148. return 0;
  149. }
  150. static int read_session(struct rdbd_file_session * session, off_t offset, rt_uint8_t * buffer, rt_size_t len)
  151. {
  152. if(RT_NULL == session || RT_NULL == buffer)
  153. {
  154. LOG_E("Invalid args %s,%d", __FUNCTION__, __LINE__);
  155. return -1;
  156. }
  157. if((session->flag & 0xF) == O_WRONLY)
  158. {
  159. LOG_E("Invalid read %s,%d", __FUNCTION__, __LINE__);
  160. return -1;
  161. }
  162. LOG_I("seek to %d", offset);
  163. lseek(session->fd, offset, SEEK_SET);
  164. LOG_I("Read fd %d, 0x%08X %d", session->fd, buffer, len);
  165. return read(session->fd, buffer, len);
  166. }
  167. static int write_session(struct rdbd_file_session * session, off_t offset, const rt_uint8_t * buffer, rt_size_t len)
  168. {
  169. if(RT_NULL == session || RT_NULL == buffer)
  170. {
  171. LOG_E("Invalid args %s,%d", __FUNCTION__, __LINE__);
  172. return -1;
  173. }
  174. if((session->flag & 0xF) == O_RDONLY)
  175. {
  176. LOG_E("Invalid write %s,%d", __FUNCTION__, __LINE__);
  177. return -1;
  178. }
  179. lseek(session->fd, offset, SEEK_SET);
  180. return write(session->fd, buffer, len);
  181. }
  182. struct rdbd_file_control_msg
  183. {
  184. struct rdbd_file_control_msg_header header;
  185. rt_uint8_t msg[RT_UINT16_MAX];
  186. };
  187. typedef struct rdbd_file_control_msg * rdbd_file_ctrl_msg_t;
  188. struct file_request_send
  189. {
  190. rt_list_t list;
  191. char * msg;
  192. int msg_pos;
  193. int request_file_send;
  194. };
  195. static rt_uint32_t rdbd_file_calc_hash(const char * filename);
  196. static rt_dstr_t * get_file_list(const char *pathname);
  197. static int file_service_request_send(rt_list_t * header, struct rdbd_file_control_msg * msg, int request_file_send);
  198. static int file_service_delete_request(struct file_request_send * request);
  199. static void file_service_thread_entry(void * arg)
  200. {
  201. struct rdbd_service * file_service= (struct rdbd_service *)arg;
  202. fd_set readset, writeset;
  203. int result = 0;
  204. int res = 0;
  205. int max_fd = file_service->in_pipe_read_fd + 1;
  206. rt_list_t request_write_list;
  207. rt_list_t session_list;
  208. struct file_request_send * request;
  209. rdbd_file_ctrl_msg_t msg = RT_NULL;
  210. int msg_pos = 0;
  211. rt_dstr_t * file_list;
  212. char * path;
  213. struct rdbd_file_session * session = RT_NULL;
  214. rt_list_init(&request_write_list);
  215. rt_list_init(&session_list);
  216. while(1)
  217. {
  218. FD_ZERO(&readset);
  219. FD_ZERO(&writeset);
  220. FD_SET(file_service->in_pipe_read_fd, &readset);
  221. if(!rt_list_isempty(&request_write_list)) //need write data to pc
  222. {
  223. FD_SET(file_service->out_pipe_write_fd, &writeset);
  224. if(file_service->out_pipe_write_fd > (max_fd - 1))
  225. {
  226. max_fd = file_service->out_pipe_write_fd + 1;
  227. }
  228. }
  229. res = select(max_fd, &readset, &writeset, RT_NULL, RT_NULL);
  230. if(res > 0)
  231. {
  232. if(FD_ISSET(file_service->in_pipe_read_fd, &readset))
  233. {
  234. if(msg == RT_NULL)
  235. {
  236. msg = rt_calloc(RDBD_FILE_HEADER_SIZE, 1);
  237. msg_pos = read(file_service->in_pipe_read_fd, RDBD_FILE_MSG_RAW(msg), RDBD_FILE_HEADER_SIZE);
  238. if(msg_pos < 0)
  239. {
  240. msg_pos = 0;
  241. }
  242. }
  243. else if(msg_pos < RDBD_FILE_HEADER_SIZE)//continue read header
  244. {
  245. result = read(file_service->in_pipe_read_fd,
  246. RDBD_FILE_MSG_RAW(msg) + msg_pos,
  247. RDBD_FILE_HEADER_SIZE - msg_pos);//read header
  248. if(result > 0)
  249. {
  250. msg_pos += result;
  251. }
  252. }
  253. else if(msg_pos < (RDBD_FILE_MSG_SIZE(msg)))//read body
  254. {
  255. if(msg_pos == RDBD_FILE_HEADER_SIZE)
  256. {
  257. msg = rt_realloc(msg, RDBD_FILE_MSG_SIZE(msg));//realloc
  258. }
  259. result = read(file_service->in_pipe_read_fd,
  260. RDBD_FILE_MSG_RAW(msg) + msg_pos,
  261. RDBD_FILE_MSG_SIZE(msg) - msg_pos);//read body
  262. if(result > 0)
  263. {
  264. msg_pos += result;
  265. }
  266. if(msg_pos == RDBD_FILE_MSG_SIZE(msg))//read done
  267. {
  268. path = rt_calloc(1,msg->header.pathlength + 1);
  269. if(RT_NULL == path)
  270. {
  271. LOG_E("no memory");
  272. RT_ASSERT(0);
  273. }
  274. rt_strncpy(path, (const char *)msg->msg, msg->header.pathlength);
  275. LOG_D("path: %s", path);
  276. path[msg->header.pathlength] = '\0';
  277. if(RDBD_FILE_CTRL_NEW_FILE == msg->header.command || RDBD_FILE_CTRL_WRITE_FILE == msg->header.command)//Done
  278. {
  279. while (1) //replace '\\' to '/'
  280. {
  281. char *p;
  282. p = strchr(path, '\\');
  283. if (p)
  284. {
  285. *p = '/';
  286. }
  287. else
  288. {
  289. break;
  290. }
  291. }
  292. {
  293. char *begin, *end;
  294. begin = path;
  295. char *_path;
  296. while (1)
  297. {
  298. end = strchr(begin, '/'); //find '\\' since begin
  299. if (end == NULL) //if not find '\\' finsh
  300. {
  301. break;
  302. }
  303. if (begin == end) //if begin is '\\'
  304. {
  305. begin += 1;
  306. continue;
  307. }
  308. _path = rt_malloc(end - path + 1);
  309. if (_path == RT_NULL) //malloc fail
  310. {
  311. break;//???
  312. }
  313. strncpy(_path, path, end - path); //copy path
  314. _path[end - path] = '\0';
  315. {
  316. if (access(_path, 0) != 0) //dir not exist
  317. {
  318. if (mkdir(_path, 0777) != 0) //create fail
  319. {
  320. LOG_E("mkdir %s failed", _path);
  321. free(_path);
  322. _path = RT_NULL;
  323. break;
  324. }
  325. }
  326. }
  327. free(_path);
  328. _path = RT_NULL;
  329. begin = end + 1; //next
  330. }
  331. }
  332. switch(msg->header.command)
  333. {
  334. case RDBD_FILE_CTRL_NEW_FILE:
  335. session = create_session(&session_list, path, O_CREAT|O_TRUNC|O_WRONLY);
  336. if(session == RT_NULL)
  337. {
  338. LOG_E("Create file error %s", path);
  339. RT_ASSERT(0);
  340. }
  341. break;
  342. case RDBD_FILE_CTRL_WRITE_FILE:
  343. session = find_session(&session_list, path);
  344. if(session == RT_NULL)
  345. {
  346. LOG_E("Please open the file %s first", path);
  347. RT_ASSERT(0);
  348. }
  349. break;
  350. default:
  351. RT_ASSERT(0);
  352. }
  353. LOG_D("Offset %d", msg->header.offset);
  354. LOG_D("Write %d", msg->header.length);
  355. if(msg->header.length)
  356. {
  357. if(write_session(session, msg->header.offset, &msg->msg[msg->header.pathlength], msg->header.length) != msg->header.length)
  358. {
  359. LOG_W("Space not enought");
  360. }
  361. }
  362. session = RT_NULL;
  363. //end of function release mem
  364. }
  365. else if(RDBD_FILE_CTRL_WRITE_DONE == msg->header.command)
  366. {
  367. session = find_session(&session_list, path);
  368. if(session == RT_NULL)
  369. {
  370. LOG_W("Not need release session %s", path);
  371. RT_ASSERT(0);
  372. }
  373. delete_session(session);
  374. }
  375. else if(RDBD_FILE_CTRL_READ_FILE == msg->header.command)
  376. {
  377. msg = rt_realloc(msg, msg->header.pathlength + RDBD_FILE_READ_BLOCK_SIZE + RDBD_FILE_HEADER_SIZE);
  378. if(msg == RT_NULL)
  379. {
  380. LOG_E("No memory");
  381. RT_ASSERT(0);
  382. }
  383. session = create_session(&session_list, path, O_RDONLY);
  384. if(session == RT_NULL)
  385. {
  386. LOG_E("Open file error %s", path);
  387. RT_ASSERT(0);
  388. }
  389. msg->header.offset = 0;
  390. msg->header.length = read_session(session, msg->header.offset, &msg->msg[msg->header.pathlength], RDBD_FILE_READ_BLOCK_SIZE);
  391. file_service_request_send(&request_write_list, msg, 1);
  392. msg = RT_NULL;
  393. }
  394. else if(RDBD_FILE_CTRL_RM_FILE == msg->header.command)
  395. {
  396. remove(path);
  397. }
  398. else if(RDBD_FILE_CTRL_LIST_DIR == msg->header.command)
  399. {
  400. file_list = get_file_list(path);
  401. msg->header.offset = 0;
  402. msg->header.pathlength = 0;
  403. msg->header.length = rt_dstr_strlen(file_list);
  404. msg = rt_realloc(msg, RDBD_FILE_MSG_SIZE(msg));
  405. memcpy(msg->msg, file_list->str, msg->header.length);
  406. file_service_request_send(&request_write_list, msg, 0);
  407. rt_dstr_del(file_list);
  408. file_list = RT_NULL;
  409. msg = RT_NULL;
  410. }
  411. else if(RDBD_FTLE_CTRL_GET_HASH == msg->header.command)
  412. {
  413. msg->header.length = 4;
  414. msg->header.offset = 0;
  415. msg = rt_realloc(msg, RDBD_FILE_MSG_SIZE(msg));
  416. {
  417. rt_uint32_t hash = rdbd_file_calc_hash(path);
  418. memcpy(&msg->msg[msg->header.pathlength], &hash, 4);
  419. }
  420. file_service_request_send(&request_write_list, msg, 0);
  421. msg = RT_NULL;
  422. }
  423. else if(RDBD_FTLE_CTRL_DIR_SYNC_START == msg->header.command)
  424. {
  425. //TO DO
  426. }
  427. else if(RDBD_FTLE_CTRL_DIR_SYNC_STOP == msg->header.command)
  428. {
  429. //TO DO
  430. }
  431. else if(RDBD_FTLE_CTRL_CHECK_PATH == msg->header.command)
  432. {
  433. msg->header.length = 1;
  434. msg->header.offset = 0;
  435. msg = rt_realloc(msg, RDBD_FILE_MSG_SIZE(msg));
  436. {
  437. struct stat filestat;
  438. if (stat(path, &filestat) == -1)
  439. {
  440. msg->msg[msg->header.pathlength] = RDBD_FTLE_CTRL_PATH_NONE;
  441. }
  442. else
  443. {
  444. if((filestat.st_mode & S_IFMT) == S_IFDIR)
  445. {
  446. msg->msg[msg->header.pathlength] = RDBD_FTLE_CTRL_PATH_IS_DIR;
  447. }
  448. else
  449. {
  450. msg->msg[msg->header.pathlength] = RDBD_FTLE_CTRL_PATH_IS_FILE;
  451. }
  452. }
  453. }
  454. file_service_request_send(&request_write_list, msg, 0);
  455. msg = RT_NULL;
  456. }
  457. if(RT_NULL != path)
  458. {
  459. rt_free(path);
  460. path = RT_NULL;
  461. }
  462. if(RT_NULL != msg)
  463. {
  464. rt_free(msg);
  465. msg = RT_NULL;
  466. }
  467. }
  468. }
  469. }
  470. if(!rt_list_isempty(&request_write_list)) //need write data to pc
  471. {
  472. if(FD_ISSET(file_service->out_pipe_write_fd, &writeset))
  473. {
  474. request = rt_list_entry(request_write_list.next, struct file_request_send, list);
  475. result = write(file_service->out_pipe_write_fd,
  476. request->msg + request->msg_pos, RDBD_FILE_MSG_SIZE(request->msg) - request->msg_pos);
  477. if(result > 0)
  478. {
  479. request->msg_pos += result;
  480. }
  481. if(request->msg_pos == RDBD_FILE_MSG_SIZE(request->msg))
  482. {
  483. request->msg_pos = 0;
  484. if(request->request_file_send && 0 != RDBD_FILE_MSG_MSG(request->msg)->header.length)
  485. {
  486. RDBD_FILE_MSG_MSG(request->msg)->header.offset += RDBD_FILE_MSG_MSG(request->msg)->header.length;
  487. path = rt_calloc(1,RDBD_FILE_MSG_MSG(request->msg)->header.pathlength + 1);
  488. if(RT_NULL == path)
  489. {
  490. LOG_E("No memory");
  491. RT_ASSERT(0);
  492. }
  493. rt_strncpy(path, (const char *)RDBD_FILE_MSG_MSG(request->msg)->msg, RDBD_FILE_MSG_MSG(request->msg)->header.pathlength);
  494. path[RDBD_FILE_MSG_MSG(request->msg)->header.pathlength] = '\0';
  495. request->msg = rt_realloc(request->msg, RDBD_FILE_MSG_MSG(request->msg)->header.pathlength + RDBD_FILE_READ_BLOCK_SIZE + RDBD_FILE_HEADER_SIZE);
  496. if(request->msg == RT_NULL)
  497. {
  498. LOG_E("No memory");
  499. RT_ASSERT(0);
  500. }
  501. session = find_session(&session_list, path);
  502. if(session == RT_NULL)
  503. {
  504. LOG_E("Please open the file %s first", path);
  505. RT_ASSERT(0);
  506. }
  507. free(path);
  508. path = RT_NULL;
  509. RDBD_FILE_MSG_MSG(request->msg)->header.length = read_session(session, RDBD_FILE_MSG_MSG(request->msg)->header.offset, &RDBD_FILE_MSG_MSG(request->msg)->msg[RDBD_FILE_MSG_MSG(request->msg)->header.pathlength], RDBD_FILE_READ_BLOCK_SIZE);
  510. if(RDBD_FILE_MSG_MSG(request->msg)->header.length == 0)
  511. {
  512. RDBD_FILE_MSG_MSG(request->msg)->header.command = RDBD_FILE_CTRL_WRITE_DONE;
  513. request->request_file_send = 0;
  514. delete_session(session);
  515. session = RT_NULL;
  516. }
  517. }
  518. else
  519. {
  520. file_service_delete_request(request);
  521. }
  522. }
  523. }
  524. }
  525. }
  526. }
  527. }
  528. static int start(void * args);
  529. static int stop(void * args);
  530. static int resume(void * args);
  531. static int suspend(void * args);
  532. static struct rdbd_service_control_ops control_ops =
  533. {
  534. start,
  535. stop,
  536. resume,
  537. suspend,
  538. };
  539. static int file_service_request_send(rt_list_t * header, struct rdbd_file_control_msg * msg, int request_file_send)
  540. {
  541. struct file_request_send * request;
  542. if(RT_NULL == header || RT_NULL == msg)
  543. {
  544. LOG_E("Write request arg error");
  545. return -1;
  546. }
  547. request = rt_malloc(sizeof(struct file_request_send));
  548. if(RT_NULL == request)
  549. {
  550. LOG_E("No memory request send to file");
  551. return -1;
  552. }
  553. request->msg = (char *)msg;
  554. request->msg_pos = 0;
  555. request->request_file_send = request_file_send;
  556. rt_list_insert_before(header, &request->list);
  557. return 0;
  558. }
  559. static int file_service_delete_request(struct file_request_send * request)
  560. {
  561. if(RT_NULL == request)
  562. {
  563. LOG_E("Delete request arg error");
  564. return -1;
  565. }
  566. if(RT_NULL != request->msg)
  567. {
  568. rt_free(request->msg);
  569. }
  570. rt_list_remove(&request->list);
  571. rt_free(request);
  572. return 0;
  573. }
  574. int rdbd_file_service_init(void)
  575. {
  576. struct rdbd_service * file_service;
  577. rdbd_t usbrdbd = rdbd_find("usb");
  578. if(RT_NULL == usbrdbd)
  579. {
  580. LOG_E("rdbd usb find error");
  581. return -1;
  582. }
  583. file_service = rdbd_create_service(RDBD_SERVICE_ID_FILE, "file", &control_ops, RT_NULL, "filein", 1024,"fileout", 1024, RDBD_SERVICE_FLAG_WR|RDBD_SERVICE_FLAG_RD);
  584. if(RT_NULL == file_service)
  585. {
  586. LOG_E("file_service create error");
  587. goto _error;
  588. }
  589. LOG_I("Service %s created :", file_service->name);
  590. LOG_I("in_pipe_path %s", file_service->in_pipe_path);
  591. LOG_I("out_pipe_path %s", file_service->out_pipe_path);
  592. LOG_I("service_id %d", file_service->service_id);
  593. LOG_I("status %d", file_service->status);
  594. rdbd_service_install(usbrdbd, file_service);
  595. rdbd_service_control(file_service, RDBD_SERVICE_START, file_service);
  596. return 0;
  597. _error:
  598. if(RT_NULL != usbrdbd)
  599. {
  600. //TO DO
  601. }
  602. return -1;
  603. }
  604. INIT_APP_EXPORT(rdbd_file_service_init);
  605. static int start(void * args)
  606. {
  607. struct rdbd_service * file_service = (struct rdbd_service *)args;
  608. if(RT_NULL == file_service)
  609. {
  610. LOG_E("Start up service error, args is null");
  611. return -1;
  612. }
  613. if(file_service->flag & RDBD_SERVICE_FLAG_RD)
  614. {
  615. file_service->in_pipe_read_fd = open(file_service->in_pipe_path, O_RDONLY | O_NONBLOCK, 0);
  616. if(file_service->in_pipe_read_fd < 0)
  617. {
  618. LOG_E("Start up service %s error open in pipe failed",file_service->name);
  619. return -1;
  620. }
  621. }
  622. if(file_service->flag & RDBD_SERVICE_FLAG_WR)
  623. {
  624. file_service->out_pipe_write_fd = open(file_service->out_pipe_path, O_WRONLY | O_NONBLOCK, 0);
  625. if(file_service->out_pipe_write_fd < 0)
  626. {
  627. LOG_E("Start up service %s error open out pipe failed",file_service->name);
  628. goto _error;
  629. }
  630. }
  631. if(file_service->flag & RDBD_SERVICE_FLAG_RD)
  632. {
  633. file_service->in_pipe_write_fd = open(file_service->in_pipe_path, O_WRONLY | O_NONBLOCK, 0);
  634. if(file_service->in_pipe_write_fd < 0)
  635. {
  636. LOG_E("Start up transfer error open in pipe failed",file_service->name);
  637. return -1;
  638. }
  639. }
  640. if(file_service->flag & RDBD_SERVICE_FLAG_WR)
  641. {
  642. file_service->out_pipe_read_fd = open(file_service->out_pipe_path, O_RDONLY | O_NONBLOCK, 0);
  643. if(file_service->out_pipe_read_fd < 0)
  644. {
  645. LOG_E("Start up transfer error open out pipe failed",file_service->name);
  646. goto _error;
  647. }
  648. }
  649. file_service->service_thread = rt_thread_create(file_service->name,
  650. file_service_thread_entry,
  651. file_service,
  652. 2048,
  653. 21,
  654. 20);
  655. if(RT_NULL != file_service->service_thread)
  656. {
  657. if(RT_EOK != rt_thread_startup(file_service->service_thread))
  658. {
  659. rt_thread_delete(file_service->service_thread);
  660. file_service->service_thread = RT_NULL;
  661. goto _error;
  662. }
  663. }
  664. else
  665. {
  666. goto _error;
  667. }
  668. return 0;
  669. _error:
  670. stop(args);
  671. return -1;
  672. }
  673. static int stop(void * args)
  674. {
  675. struct rdbd_service * file_service = (struct rdbd_service *)args;
  676. if(RT_NULL == file_service)
  677. {
  678. LOG_E("Stop service error, args is null");
  679. return -1;
  680. }
  681. if(RT_NULL != file_service->service_thread)
  682. {
  683. if(RT_EOK != rt_thread_delete(file_service->service_thread))
  684. {
  685. LOG_E("Delete thread %s failed", file_service->service_thread->name);
  686. return -1;
  687. }
  688. file_service->service_thread = RT_NULL;
  689. }
  690. if(file_service->in_pipe_read_fd >= 0)
  691. {
  692. if(close(file_service->in_pipe_read_fd) < 0)
  693. {
  694. LOG_E("Close fd %d failed", file_service->in_pipe_read_fd);
  695. return -1;
  696. }
  697. file_service->in_pipe_read_fd = -1;
  698. }
  699. if(file_service->in_pipe_write_fd >= 0)
  700. {
  701. if(close(file_service->in_pipe_write_fd) < 0)
  702. {
  703. LOG_E("Close fd %d failed", file_service->in_pipe_write_fd);
  704. return -1;
  705. }
  706. file_service->in_pipe_write_fd = -1;
  707. }
  708. if(file_service->in_pipe_write_fd >= 0)
  709. {
  710. if(close(file_service->in_pipe_write_fd) < 0)
  711. {
  712. LOG_E("Close fd %d failed", file_service->in_pipe_write_fd);
  713. return -1;
  714. }
  715. file_service->in_pipe_write_fd = -1;
  716. }
  717. if(file_service->out_pipe_write_fd >= 0)
  718. {
  719. if(close(file_service->out_pipe_write_fd) < 0)
  720. {
  721. LOG_E("Close fd %d failed", file_service->out_pipe_write_fd);
  722. return -1;
  723. }
  724. file_service->out_pipe_write_fd = -1;
  725. }
  726. return 0;
  727. }
  728. static int resume(void * args)
  729. {
  730. //Not need
  731. return 0;
  732. }
  733. static int suspend(void * args)
  734. {
  735. //Not need
  736. return 0;
  737. }
  738. static rt_dstr_t * get_file_list(const char *pathname)
  739. {
  740. rt_dstr_t * list = RT_NULL, *fullpath = RT_NULL, *temp_list = RT_NULL;
  741. struct dirent * dir = NULL;
  742. DIR * root_dir = NULL;
  743. struct stat filestat;
  744. list = rt_dstr_new("");
  745. root_dir = opendir(pathname);
  746. if(root_dir == NULL)
  747. {
  748. return list;
  749. }
  750. while(1)
  751. {
  752. dir = readdir(root_dir);
  753. if(dir == NULL)
  754. {
  755. break;
  756. }
  757. if (strncmp(dir->d_name, ".", 1) == 0)
  758. continue; /* skip hide file*/
  759. if(strcmp("/", pathname) == 0)
  760. {
  761. fullpath = rt_dstr_sprintf(fullpath, "/%s", dir->d_name);
  762. }
  763. else
  764. {
  765. fullpath = rt_dstr_sprintf(fullpath, "%s/%s", pathname, dir->d_name);
  766. }
  767. if (stat(fullpath->str, &filestat) == -1)
  768. {
  769. LOG_E("cannot access the file %s", fullpath->str);
  770. return list;
  771. }
  772. if ((filestat.st_mode & S_IFMT) == S_IFDIR)
  773. {
  774. temp_list = get_file_list(fullpath->str);
  775. list = rt_dstr_append_printf(list, "%s", temp_list->str);
  776. rt_dstr_del(temp_list);
  777. temp_list = RT_NULL;
  778. }
  779. else
  780. {
  781. list = rt_dstr_append_printf(list, "%s\n", fullpath->str);
  782. }
  783. rt_dstr_del(fullpath);
  784. fullpath = RT_NULL;
  785. }
  786. closedir(root_dir);
  787. return list;
  788. }
  789. int list_dir(void)
  790. {
  791. int i = 0;
  792. rt_dstr_t * list = get_file_list("/");
  793. while(list->str[i] != '\0')
  794. {
  795. rt_kprintf("%c",list->str[i++]);
  796. }
  797. rt_dstr_del(list);
  798. return 0;
  799. }
  800. MSH_CMD_EXPORT(list_dir, list dir);
  801. /* hash a single byte */
  802. static rt_uint32_t fnv1a_r(unsigned char oneByte, rt_uint32_t hash)
  803. {
  804. return (oneByte ^ hash) * 0x01000193; // 0x01000193 = 16777619
  805. }
  806. static rt_uint32_t rdbd_file_calc_hash(const char * filename)
  807. {
  808. FILE * fp = NULL;
  809. int ch;
  810. uint32_t hash = RDBD_FILE_HASH_FNV_SEED;
  811. fp = fopen(filename, "r");
  812. if(fp == NULL)
  813. {
  814. LOG_W("%s not found!", filename);
  815. return 0;
  816. }
  817. while(1)
  818. {
  819. ch = fgetc(fp);
  820. if(ch == EOF)
  821. {
  822. break;
  823. }
  824. hash = fnv1a_r(ch, hash);
  825. }
  826. fclose(fp);
  827. return hash;
  828. }