dfs_win32.c 14 KB

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