dfs_win32.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. /*
  2. * File : rtthread.h
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006-2012, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE.
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2012-11-27 prife the first version
  13. * 2013-03-03 aozima add dfs_win32_stat st_mtime support.
  14. * 2017-10-20 urey support rt-thread 3.0
  15. */
  16. #include <rtthread.h>
  17. #include <rtlibc.h>
  18. #include <dfs_fs.h>
  19. #include <dfs_file.h>
  20. #include <rtdevice.h>
  21. #include <io.h>
  22. #include <fcntl.h>
  23. #include <string.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <WinError.h>
  27. #include <windows.h>
  28. #if defined(__MINGW32__) && defined(_NO_OLDNAMES)
  29. #define O_RDONLY _O_RDONLY
  30. #define O_WRONLY _O_WRONLY
  31. #define O_RDWR _O_RDWR
  32. #define O_ACCMODE _O_ACCMODE
  33. #define O_APPEND _O_APPEND
  34. #define O_CREAT _O_CREAT
  35. #define O_TRUNC _O_TRUNC
  36. #define O_EXCL _O_EXCL
  37. #define O_TEXT _O_TEXT
  38. #define O_BINARY _O_BINARY
  39. #define O_TEMPORARY _O_TEMPORARY
  40. #define O_NOINHERIT _O_NOINHERIT
  41. #define O_SEQUENTIAL _O_SEQUENTIAL
  42. #define O_RANDOM _O_RANDOM
  43. #endif
  44. /*
  45. * RT-Thread DFS Interface for win-directory as an disk device
  46. */
  47. #define FILE_PATH_MAX 256 /* the longest file path */
  48. #define WIN32_DIRDISK_ROOT "./disk" /* "F:\\Project\\svn\\rtt\\trunk\\bsp\\simulator_test" */
  49. typedef struct {
  50. HANDLE handle;
  51. char *start;
  52. char *end;
  53. char *curr;
  54. struct _finddata_t finddata;
  55. } WINDIR;
  56. /* There are so many error codes in windows, you'd better google for details.
  57. * google "System Error Codes (Windows)"
  58. * http://msdn.microsoft.com/ZH-CN/library/windows/desktop/ms681381(v=vs.85).aspx
  59. */
  60. struct _errcode_map
  61. {
  62. rt_uint16_t dfserr;
  63. rt_uint16_t win32err;
  64. };
  65. static const struct _errcode_map errcode_table[] =
  66. {
  67. {ENOENT, ERROR_FILE_NOT_FOUND },
  68. {ENOENT, ERROR_PATH_NOT_FOUND },
  69. {EEXIST, ERROR_FILE_EXISTS },
  70. {EEXIST, ERROR_ALREADY_EXISTS },
  71. {ENOTEMPTY, ERROR_DIR_NOT_EMPTY },
  72. {EBUSY, ERROR_PATH_BUSY },
  73. {EINVAL, ERROR_ACCESS_DENIED },
  74. #if 0 /* TODO: MORE NEED BE ADDED */
  75. {DFS_STATUS_EISDIR, ERROR_FILE_EXISTS },
  76. {DFS_STATUS_ENOTDIR, ERROR_FILE_EXISTS },
  77. {DFS_STATUS_EBADF, ERROR_FILE_EXISTS },
  78. {DFS_STATUS_EBUSY, ERROR_FILE_EXISTS },
  79. {DFS_STATUS_ENOMEM, ERROR_FILE_EXISTS },
  80. {DFS_STATUS_ENOSPC, ERROR_FILE_EXISTS },
  81. #endif
  82. };
  83. static int win32_result_to_dfs(DWORD res)
  84. {
  85. int i;
  86. int err = 0;
  87. for (i = 0; i < sizeof(errcode_table) / sizeof(struct _errcode_map); i++)
  88. {
  89. if (errcode_table[i].win32err == (res & 0xFFFF))
  90. {
  91. err = -errcode_table[i].dfserr;
  92. return err;
  93. }
  94. }
  95. /* unknown error */
  96. rt_kprintf("dfs win32 error not supported yet: %d\n", res);
  97. return -1;
  98. }
  99. static int dfs_win32_mount(
  100. struct dfs_filesystem *fs,
  101. unsigned long rwflag,
  102. const void *data)
  103. {
  104. return 0;
  105. }
  106. static int dfs_win32_unmount(struct dfs_filesystem *fs)
  107. {
  108. return 0;
  109. }
  110. static int dfs_win32_mkfs(rt_device_t devid)
  111. {
  112. return -ENOSYS;
  113. }
  114. static int dfs_win32_statfs(struct dfs_filesystem *fs,
  115. struct statfs *buf)
  116. {
  117. return -ENOSYS;
  118. }
  119. static char *winpath_dirdup(char *des, const char *src)
  120. {
  121. char *path;
  122. int i = 0;
  123. path = rt_malloc(FILE_PATH_MAX);
  124. if (path == RT_NULL)
  125. return RT_NULL;
  126. strcpy(path, des);
  127. strcat(path, src);
  128. while (1)
  129. {
  130. if (path[i] == 0)
  131. break;
  132. if (path[i] == '/')
  133. path[i] = '\\';
  134. i++;
  135. }
  136. return path;
  137. }
  138. /* This function can convert the path in rt-thread/dfs to the path in windows */
  139. char * dfs_win32_dirdup(char * path)
  140. {
  141. char * file_path;
  142. file_path = winpath_dirdup(WIN32_DIRDISK_ROOT, path);
  143. return file_path;
  144. }
  145. static int dfs_win32_open(struct dfs_fd *file)
  146. {
  147. int fd;
  148. uint32_t oflag, mode;
  149. char *file_path;
  150. int res;
  151. oflag = file->flags;
  152. if (oflag & O_DIRECTORY) /* operations about dir */
  153. {
  154. WINDIR *wdirp;
  155. HANDLE handle;
  156. int len;
  157. file_path = winpath_dirdup(WIN32_DIRDISK_ROOT, file->path);
  158. if (oflag & O_CREAT) /* create a dir*/
  159. {
  160. res = CreateDirectory(file_path, NULL);
  161. if (res == 0)
  162. {
  163. rt_free(file_path);
  164. return win32_result_to_dfs(GetLastError());
  165. }
  166. }
  167. len = strlen(file_path);
  168. if (file_path[len - 1] != '\\')
  169. {
  170. file_path[len] = '\\';
  171. file_path[len + 1] = 0;
  172. }
  173. strcat(file_path, "*.*");
  174. /* _findfirst will get '.' */
  175. /* save this pointer,will used by dfs_win32_getdents*/
  176. wdirp = rt_malloc(sizeof(WINDIR));
  177. RT_ASSERT(wdirp != NULL);
  178. if ((handle = _findfirst(file_path, &wdirp->finddata)) == -1)
  179. {
  180. rt_free(wdirp);
  181. rt_free(file_path);
  182. goto __err;
  183. }
  184. len = strlen(wdirp->finddata.name) + 1;
  185. wdirp->handle = handle;
  186. //wdirp->nfiles = 1;
  187. wdirp->start = malloc(len); //not rt_malloc!
  188. wdirp->end = wdirp->curr = wdirp->start;
  189. wdirp->end += len;
  190. strncpy(wdirp->curr, wdirp->finddata.name, len);
  191. file->data = (void *)wdirp;
  192. rt_free(file_path);
  193. return 0;
  194. }
  195. /* regular file operations */
  196. mode = O_BINARY;
  197. if (oflag & O_RDONLY) mode |= O_RDONLY;
  198. if (oflag & O_WRONLY) mode |= O_WRONLY;
  199. if (oflag & O_RDWR) mode |= O_RDWR;
  200. /* Opens the file, if it is existing. If not, a new file is created. */
  201. if (oflag & O_CREAT) mode |= O_CREAT;
  202. /* Creates a new file. If the file is existing, it is truncated and overwritten. */
  203. if (oflag & O_TRUNC) mode |= O_TRUNC;
  204. /* Creates a new file. The function fails if the file is already existing. */
  205. if (oflag & O_EXCL) mode |= O_EXCL;
  206. file_path = winpath_dirdup(WIN32_DIRDISK_ROOT, file->path);
  207. fd = _open(file_path, mode, 0x0100 | 0x0080); /* _S_IREAD | _S_IWRITE */
  208. rt_free(file_path);
  209. if (fd < 0)
  210. goto __err;
  211. /* save this pointer, it will be used when calling read(), write(),
  212. * flush(), seek(), and will be free when calling close()*/
  213. file->data = (void *)fd;
  214. file->pos = 0;
  215. file->size = _lseek(fd, 0, SEEK_END);
  216. if (oflag & O_APPEND)
  217. {
  218. file->pos = file->size;
  219. }
  220. else
  221. _lseek(fd, 0, SEEK_SET);
  222. return 0;
  223. __err:
  224. res = GetLastError();
  225. return win32_result_to_dfs(res);
  226. }
  227. static int dfs_win32_close(struct dfs_fd *file)
  228. {
  229. if (file->flags & O_DIRECTORY)
  230. {
  231. WINDIR *wdirp = (WINDIR*)(file->data);
  232. RT_ASSERT(wdirp != RT_NULL);
  233. if (_findclose((intptr_t)wdirp->handle) == 0) {
  234. free(wdirp->start); //NOTE: here we don't use rt_free!
  235. rt_free(wdirp);
  236. return 0;
  237. }
  238. }
  239. else /* regular file operations */
  240. {
  241. if (_close((int)(file->data)) == 0)
  242. return 0;
  243. }
  244. return win32_result_to_dfs(GetLastError());
  245. }
  246. static int dfs_win32_ioctl(struct dfs_fd *file, int cmd, void *args)
  247. {
  248. return -ENOSYS;
  249. }
  250. static int dfs_win32_read(struct dfs_fd *file, void *buf, size_t len)
  251. {
  252. int fd;
  253. int char_read;
  254. fd = (int)(file->data);
  255. char_read = _read(fd, buf, len);
  256. if (char_read < 0)
  257. return win32_result_to_dfs(GetLastError());
  258. /* update position */
  259. file->pos = _lseek(fd, 0, SEEK_CUR);
  260. return char_read;
  261. }
  262. static int dfs_win32_write(struct dfs_fd *file, const void *buf, size_t len)
  263. {
  264. int fd;
  265. int char_write;
  266. fd = (int)(file->data);
  267. char_write = _write(fd, buf, len);
  268. if (char_write < 0)
  269. return win32_result_to_dfs(GetLastError());
  270. /* update position */
  271. file->pos = _lseek(fd, 0, SEEK_CUR);
  272. return char_write;
  273. }
  274. static int dfs_win32_flush(struct dfs_fd *file)
  275. {
  276. return 0;
  277. }
  278. static int dfs_win32_seek(struct dfs_fd *file,
  279. rt_off_t offset)
  280. {
  281. int result;
  282. /* set offset as current offset */
  283. if (file->type == FT_DIRECTORY)
  284. {
  285. WINDIR* wdirp = (WINDIR*)(file->data);
  286. RT_ASSERT(wdirp != RT_NULL);
  287. wdirp->curr = wdirp->start + offset;
  288. return offset;
  289. }
  290. else //file->type == FT_REGULAR)
  291. {
  292. result = _lseek((int)(file->data), offset, SEEK_SET);
  293. if (result >= 0)
  294. return offset;
  295. else
  296. return win32_result_to_dfs(GetLastError());
  297. }
  298. }
  299. /* return the size of struct dirent*/
  300. static int dfs_win32_getdents(struct dfs_fd *file, struct dirent *dirp, rt_uint32_t count)
  301. {
  302. WINDIR *wdirp;
  303. struct dirent *d = dirp;
  304. int result;
  305. /* make integer count */
  306. if (count / sizeof(struct dirent) != 1)
  307. return -EINVAL;
  308. wdirp = (WINDIR*)(file->data);
  309. RT_ASSERT(wdirp != RT_NULL);
  310. if (wdirp->curr == NULL) //no more entries in this directory
  311. return 0;
  312. /* get the current entry */
  313. if (wdirp->finddata.attrib & _A_SUBDIR)
  314. d->d_type = DT_DIR;
  315. else
  316. d->d_type = DT_REG;
  317. d->d_namlen = strlen(wdirp->curr);
  318. strncpy(d->d_name, wdirp->curr, DFS_PATH_MAX);
  319. d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
  320. wdirp->curr += (strlen(wdirp->curr) + 1);
  321. file->pos = wdirp->curr - wdirp->start + sizeof(struct dirent);//NOTE!
  322. /* now set up for the next call to readdir */
  323. if (wdirp->curr >= wdirp->end)
  324. {
  325. if (_findnext(wdirp->handle, &wdirp->finddata) == 0)
  326. {
  327. char* old_start = wdirp->start;
  328. long name_len = strlen(wdirp->finddata.name) + 1;
  329. wdirp->start = realloc(wdirp->start, wdirp->end - wdirp->start + name_len);
  330. wdirp->curr = wdirp->start + (wdirp->curr - old_start);
  331. wdirp->end = wdirp->curr + name_len;
  332. strcpy(wdirp->curr, wdirp->finddata.name);
  333. }
  334. else
  335. {
  336. if ((result = GetLastError()) == ERROR_NO_MORE_FILES)
  337. wdirp->curr = NULL;
  338. else
  339. return win32_result_to_dfs(result);
  340. }
  341. }
  342. return sizeof(struct dirent);
  343. }
  344. static int dfs_win32_unlink(struct dfs_filesystem *fs, const char *path)
  345. {
  346. int result;
  347. char *fp;
  348. fp = winpath_dirdup(WIN32_DIRDISK_ROOT, path);
  349. if (fp == RT_NULL)
  350. {
  351. rt_kprintf("out of memory.\n");
  352. return -ENOMEM;
  353. }
  354. result = GetFileAttributes(fp);
  355. if (result == INVALID_FILE_ATTRIBUTES)
  356. goto __err;
  357. if (result & FILE_ATTRIBUTE_DIRECTORY)//winnt.h
  358. {
  359. if (RemoveDirectory(fp) == RT_FALSE)
  360. goto __err;
  361. }
  362. else //(result & FILE_ATTRIBUTE_NORMAL)
  363. {
  364. if (_unlink(fp) < 0)
  365. goto __err;
  366. }
  367. rt_free(fp);
  368. return 0;
  369. __err:
  370. rt_free(fp);
  371. return win32_result_to_dfs(GetLastError());
  372. }
  373. static int dfs_win32_rename(
  374. struct dfs_filesystem *fs,
  375. const char *oldpath,
  376. const char *newpath)
  377. {
  378. int result;
  379. char *op, *np;
  380. op = winpath_dirdup(WIN32_DIRDISK_ROOT, oldpath);
  381. np = winpath_dirdup(WIN32_DIRDISK_ROOT, newpath);
  382. if (op == RT_NULL || np == RT_NULL)
  383. {
  384. rt_kprintf("out of memory.\n");
  385. return -ENOMEM;
  386. }
  387. /* If the function fails, the return value is zero. */
  388. result = MoveFile(op, np);
  389. rt_free(op);
  390. rt_free(np);
  391. if (result == 0)
  392. return win32_result_to_dfs(GetLastError());
  393. return 0;
  394. }
  395. static int dfs_win32_stat(struct dfs_filesystem *fs, const char *path, struct stat *st)
  396. {
  397. WIN32_FIND_DATA fileInfo;
  398. HANDLE hFind;
  399. char *fp;
  400. fp = winpath_dirdup(WIN32_DIRDISK_ROOT, path);
  401. if (fp == RT_NULL)
  402. {
  403. rt_kprintf("out of memory.\n");
  404. return -ENOMEM;
  405. }
  406. hFind = FindFirstFile(fp, &fileInfo);
  407. rt_free(fp);
  408. if (hFind == INVALID_HANDLE_VALUE)
  409. goto __err;
  410. st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
  411. S_IWUSR | S_IWGRP | S_IWOTH;
  412. /* convert file info to dfs stat structure */
  413. if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  414. {
  415. st->st_mode &= ~S_IFREG;
  416. st->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
  417. }
  418. st->st_dev = 0;
  419. st->st_size = fileInfo.nFileSizeLow;
  420. /* get st_mtime. */
  421. {
  422. LARGE_INTEGER time_tmp;
  423. time_tmp.LowPart = fileInfo.ftLastWriteTime.dwLowDateTime;
  424. time_tmp.HighPart = fileInfo.ftLastWriteTime.dwHighDateTime;
  425. /* removes the diff between 1970 and 1601. */
  426. time_tmp.QuadPart -= 11644473600000 * 10000;
  427. /* converts back from 100-nanoseconds to seconds. */
  428. time_tmp.QuadPart /= 10UL * 1000 * 1000;
  429. st->st_mtime = time_tmp.QuadPart;
  430. }
  431. FindClose(hFind);
  432. return 0;
  433. __err:
  434. return win32_result_to_dfs(GetLastError());
  435. }
  436. static const struct dfs_file_ops dfs_win32_file_ops =
  437. {
  438. dfs_win32_open,
  439. dfs_win32_close,
  440. dfs_win32_ioctl,
  441. dfs_win32_read,
  442. dfs_win32_write,
  443. dfs_win32_flush,
  444. dfs_win32_seek,
  445. dfs_win32_getdents,
  446. };
  447. static const struct dfs_filesystem_ops dfs_win32_ops =
  448. {
  449. "wdir", /* file system type: dir */
  450. DFS_FS_FLAG_DEFAULT,
  451. &dfs_win32_file_ops,
  452. dfs_win32_mount,
  453. dfs_win32_unmount,
  454. dfs_win32_mkfs,
  455. dfs_win32_statfs,
  456. dfs_win32_unlink,
  457. dfs_win32_stat,
  458. dfs_win32_rename,
  459. };
  460. int dfs_win32_init(void)
  461. {
  462. /* register uffs file system */
  463. dfs_register(&dfs_win32_ops);
  464. return 0;
  465. }
  466. static rt_err_t nop_init(rt_device_t dev)
  467. {
  468. return RT_EOK;
  469. }
  470. static rt_err_t nop_open(rt_device_t dev, rt_uint16_t oflag)
  471. {
  472. return RT_EOK;
  473. }
  474. static rt_err_t nop_close(rt_device_t dev)
  475. {
  476. return RT_EOK;
  477. }
  478. static rt_size_t nop_read(rt_device_t dev,
  479. rt_off_t pos,
  480. void *buffer,
  481. rt_size_t size)
  482. {
  483. return size;
  484. }
  485. static rt_size_t nop_write(rt_device_t dev,
  486. rt_off_t pos,
  487. const void *buffer,
  488. rt_size_t size)
  489. {
  490. return size;
  491. }
  492. static rt_err_t nop_control(rt_device_t dev, int cmd, void *args)
  493. {
  494. return RT_EOK;
  495. }
  496. static struct rt_device win_sharedir_dev;
  497. rt_err_t rt_win_sharedir_init(const char *name)
  498. {
  499. rt_device_t dev;
  500. dev = &win_sharedir_dev;
  501. RT_ASSERT(dev != RT_NULL);
  502. /* set device class and generic device interface */
  503. dev->type = RT_Device_Class_Block;
  504. dev->init = nop_init;
  505. dev->open = nop_open;
  506. dev->read = nop_read;
  507. dev->write = nop_write;
  508. dev->close = nop_close;
  509. dev->control = nop_control;
  510. dev->rx_indicate = RT_NULL;
  511. dev->tx_complete = RT_NULL;
  512. /* register to RT-Thread device system */
  513. return rt_device_register(dev, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
  514. }