dfs_win32.c 13 KB

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