123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604 |
- /*
- * File : rtthread.h
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2006-2012, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE.
- *
- * Change Logs:
- * Date Author Notes
- * 2012-11-27 prife the first version
- * 2013-03-03 aozima add dfs_win32_stat st_mtime support.
- * 2017-10-20 urey support rt-thread 3.0
- */
- #include <rtthread.h>
- #include <rtlibc.h>
- #include <dfs_fs.h>
- #include <dfs_file.h>
- #include <rtdevice.h>
- #include <io.h>
- #include <fcntl.h>
- #include <string.h>
- #include <stdio.h>
- #include <string.h>
- #include <WinError.h>
- #include <windows.h>
- #if defined(__MINGW32__) && defined(_NO_OLDNAMES)
- #define O_RDONLY _O_RDONLY
- #define O_WRONLY _O_WRONLY
- #define O_RDWR _O_RDWR
- #define O_ACCMODE _O_ACCMODE
- #define O_APPEND _O_APPEND
- #define O_CREAT _O_CREAT
- #define O_TRUNC _O_TRUNC
- #define O_EXCL _O_EXCL
- #define O_TEXT _O_TEXT
- #define O_BINARY _O_BINARY
- #define O_TEMPORARY _O_TEMPORARY
- #define O_NOINHERIT _O_NOINHERIT
- #define O_SEQUENTIAL _O_SEQUENTIAL
- #define O_RANDOM _O_RANDOM
- #endif
- /*
- * RT-Thread DFS Interface for win-directory as an disk device
- */
- #define FILE_PATH_MAX 256 /* the longest file path */
- #define WIN32_DIRDISK_ROOT "./disk" /* "F:\\Project\\svn\\rtt\\trunk\\bsp\\simulator_test" */
- typedef struct {
- HANDLE handle;
- char *start;
- char *end;
- char *curr;
- struct _finddata_t finddata;
- } WINDIR;
- /* There are so many error codes in windows, you'd better google for details.
- * google "System Error Codes (Windows)"
- * http://msdn.microsoft.com/ZH-CN/library/windows/desktop/ms681381(v=vs.85).aspx
- */
- struct _errcode_map
- {
- rt_uint16_t dfserr;
- rt_uint16_t win32err;
- };
- static const struct _errcode_map errcode_table[] =
- {
- {ENOENT, ERROR_FILE_NOT_FOUND },
- {ENOENT, ERROR_PATH_NOT_FOUND },
- {EEXIST, ERROR_FILE_EXISTS },
- {EEXIST, ERROR_ALREADY_EXISTS },
- {ENOTEMPTY, ERROR_DIR_NOT_EMPTY },
- {EBUSY, ERROR_PATH_BUSY },
- {EINVAL, ERROR_ACCESS_DENIED },
- #if 0 /* TODO: MORE NEED BE ADDED */
- {DFS_STATUS_EISDIR, ERROR_FILE_EXISTS },
- {DFS_STATUS_ENOTDIR, ERROR_FILE_EXISTS },
- {DFS_STATUS_EBADF, ERROR_FILE_EXISTS },
- {DFS_STATUS_EBUSY, ERROR_FILE_EXISTS },
- {DFS_STATUS_ENOMEM, ERROR_FILE_EXISTS },
- {DFS_STATUS_ENOSPC, ERROR_FILE_EXISTS },
- #endif
- };
- static int win32_result_to_dfs(DWORD res)
- {
- int i;
- int err = 0;
- for (i = 0; i < sizeof(errcode_table) / sizeof(struct _errcode_map); i++)
- {
- if (errcode_table[i].win32err == (res & 0xFFFF))
- {
- err = -errcode_table[i].dfserr;
- return err;
- }
- }
- /* unknown error */
- rt_kprintf("dfs win32 error not supported yet: %d\n", res);
- return -1;
- }
- static int dfs_win32_mount(
- struct dfs_filesystem *fs,
- unsigned long rwflag,
- const void *data)
- {
- return 0;
- }
- static int dfs_win32_unmount(struct dfs_filesystem *fs)
- {
- return 0;
- }
- static int dfs_win32_mkfs(rt_device_t devid)
- {
- return -ENOSYS;
- }
- static int dfs_win32_statfs(struct dfs_filesystem *fs,
- struct statfs *buf)
- {
- return -ENOSYS;
- }
- static char *winpath_dirdup(char *des, const char *src)
- {
- char *path;
- int i = 0;
- path = rt_malloc(FILE_PATH_MAX);
- if (path == RT_NULL)
- return RT_NULL;
- strcpy(path, des);
- strcat(path, src);
- while (1)
- {
- if (path[i] == 0)
- break;
- if (path[i] == '/')
- path[i] = '\\';
- i++;
- }
- return path;
- }
- /* This function can convert the path in rt-thread/dfs to the path in windows */
- char * dfs_win32_dirdup(char * path)
- {
- char * file_path;
- file_path = winpath_dirdup(WIN32_DIRDISK_ROOT, path);
- return file_path;
- }
- static int dfs_win32_open(struct dfs_fd *file)
- {
- int fd;
- uint32_t oflag, mode;
- char *file_path;
- int res;
- oflag = file->flags;
- if (oflag & O_DIRECTORY) /* operations about dir */
- {
- WINDIR *wdirp;
- HANDLE handle;
- int len;
- file_path = winpath_dirdup(WIN32_DIRDISK_ROOT, file->path);
- if (oflag & O_CREAT) /* create a dir*/
- {
- res = CreateDirectory(file_path, NULL);
- if (res == 0)
- {
- rt_free(file_path);
- return win32_result_to_dfs(GetLastError());
- }
- }
- len = strlen(file_path);
- if (file_path[len - 1] != '\\')
- {
- file_path[len] = '\\';
- file_path[len + 1] = 0;
- }
- strcat(file_path, "*.*");
- /* _findfirst will get '.' */
- /* save this pointer,will used by dfs_win32_getdents*/
- wdirp = rt_malloc(sizeof(WINDIR));
- RT_ASSERT(wdirp != NULL);
- if ((handle = _findfirst(file_path, &wdirp->finddata)) == -1)
- {
- rt_free(wdirp);
- rt_free(file_path);
- goto __err;
- }
- len = strlen(wdirp->finddata.name) + 1;
- wdirp->handle = handle;
- //wdirp->nfiles = 1;
- wdirp->start = malloc(len); //not rt_malloc!
- wdirp->end = wdirp->curr = wdirp->start;
- wdirp->end += len;
- strncpy(wdirp->curr, wdirp->finddata.name, len);
- file->data = (void *)wdirp;
- rt_free(file_path);
- return 0;
- }
- /* regular file operations */
- mode = O_BINARY;
- if (oflag & O_RDONLY) mode |= O_RDONLY;
- if (oflag & O_WRONLY) mode |= O_WRONLY;
- if (oflag & O_RDWR) mode |= O_RDWR;
- /* Opens the file, if it is existing. If not, a new file is created. */
- if (oflag & O_CREAT) mode |= O_CREAT;
- /* Creates a new file. If the file is existing, it is truncated and overwritten. */
- if (oflag & O_TRUNC) mode |= O_TRUNC;
- /* Creates a new file. The function fails if the file is already existing. */
- if (oflag & O_EXCL) mode |= O_EXCL;
- file_path = winpath_dirdup(WIN32_DIRDISK_ROOT, file->path);
- fd = _open(file_path, mode, 0x0100 | 0x0080); /* _S_IREAD | _S_IWRITE */
- rt_free(file_path);
- if (fd < 0)
- goto __err;
- /* save this pointer, it will be used when calling read(), write(),
- * flush(), seek(), and will be free when calling close()*/
- file->data = (void *)fd;
- file->pos = 0;
- file->size = _lseek(fd, 0, SEEK_END);
- if (oflag & O_APPEND)
- {
- file->pos = file->size;
- }
- else
- _lseek(fd, 0, SEEK_SET);
- return 0;
- __err:
- res = GetLastError();
- return win32_result_to_dfs(res);
- }
- static int dfs_win32_close(struct dfs_fd *file)
- {
- if (file->flags & O_DIRECTORY)
- {
- WINDIR *wdirp = (WINDIR*)(file->data);
- RT_ASSERT(wdirp != RT_NULL);
- if (_findclose((intptr_t)wdirp->handle) == 0) {
- free(wdirp->start); //NOTE: here we don't use rt_free!
- rt_free(wdirp);
- return 0;
- }
- }
- else /* regular file operations */
- {
- if (_close((int)(file->data)) == 0)
- return 0;
- }
- return win32_result_to_dfs(GetLastError());
- }
- static int dfs_win32_ioctl(struct dfs_fd *file, int cmd, void *args)
- {
- return -ENOSYS;
- }
- static int dfs_win32_read(struct dfs_fd *file, void *buf, size_t len)
- {
- int fd;
- int char_read;
- fd = (int)(file->data);
- char_read = _read(fd, buf, len);
- if (char_read < 0)
- return win32_result_to_dfs(GetLastError());
- /* update position */
- file->pos = _lseek(fd, 0, SEEK_CUR);
- return char_read;
- }
- static int dfs_win32_write(struct dfs_fd *file, const void *buf, size_t len)
- {
- int fd;
- int char_write;
- fd = (int)(file->data);
- char_write = _write(fd, buf, len);
- if (char_write < 0)
- return win32_result_to_dfs(GetLastError());
- /* update position */
- file->pos = _lseek(fd, 0, SEEK_CUR);
- return char_write;
- }
- static int dfs_win32_flush(struct dfs_fd *file)
- {
- return 0;
- }
- static int dfs_win32_seek(struct dfs_fd *file,
- rt_off_t offset)
- {
- int result;
- /* set offset as current offset */
- if (file->type == FT_DIRECTORY)
- {
- WINDIR* wdirp = (WINDIR*)(file->data);
- RT_ASSERT(wdirp != RT_NULL);
- wdirp->curr = wdirp->start + offset;
- return offset;
- }
- else //file->type == FT_REGULAR)
- {
- result = _lseek((int)(file->data), offset, SEEK_SET);
- if (result >= 0)
- return offset;
- else
- return win32_result_to_dfs(GetLastError());
- }
- }
- /* return the size of struct dirent*/
- static int dfs_win32_getdents(struct dfs_fd *file, struct dirent *dirp, rt_uint32_t count)
- {
- WINDIR *wdirp;
- struct dirent *d = dirp;
- int result;
- /* make integer count */
- if (count / sizeof(struct dirent) != 1)
- return -EINVAL;
- wdirp = (WINDIR*)(file->data);
- RT_ASSERT(wdirp != RT_NULL);
- if (wdirp->curr == NULL) //no more entries in this directory
- return 0;
- /* get the current entry */
- if (wdirp->finddata.attrib & _A_SUBDIR)
- d->d_type = DT_DIR;
- else
- d->d_type = DT_REG;
- d->d_namlen = strlen(wdirp->curr);
- strncpy(d->d_name, wdirp->curr, DFS_PATH_MAX);
- d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
- wdirp->curr += (strlen(wdirp->curr) + 1);
- file->pos = wdirp->curr - wdirp->start + sizeof(struct dirent);//NOTE!
- /* now set up for the next call to readdir */
- if (wdirp->curr >= wdirp->end)
- {
- if (_findnext(wdirp->handle, &wdirp->finddata) == 0)
- {
- char* old_start = wdirp->start;
- long name_len = strlen(wdirp->finddata.name) + 1;
- wdirp->start = realloc(wdirp->start, wdirp->end - wdirp->start + name_len);
- wdirp->curr = wdirp->start + (wdirp->curr - old_start);
- wdirp->end = wdirp->curr + name_len;
- strcpy(wdirp->curr, wdirp->finddata.name);
- }
- else
- {
- if ((result = GetLastError()) == ERROR_NO_MORE_FILES)
- wdirp->curr = NULL;
- else
- return win32_result_to_dfs(result);
- }
- }
- return sizeof(struct dirent);
- }
- static int dfs_win32_unlink(struct dfs_filesystem *fs, const char *path)
- {
- int result;
- char *fp;
- fp = winpath_dirdup(WIN32_DIRDISK_ROOT, path);
- if (fp == RT_NULL)
- {
- rt_kprintf("out of memory.\n");
- return -ENOMEM;
- }
- result = GetFileAttributes(fp);
- if (result == INVALID_FILE_ATTRIBUTES)
- goto __err;
- if (result & FILE_ATTRIBUTE_DIRECTORY)//winnt.h
- {
- if (RemoveDirectory(fp) == RT_FALSE)
- goto __err;
- }
- else //(result & FILE_ATTRIBUTE_NORMAL)
- {
- if (_unlink(fp) < 0)
- goto __err;
- }
- rt_free(fp);
- return 0;
- __err:
- rt_free(fp);
- return win32_result_to_dfs(GetLastError());
- }
- static int dfs_win32_rename(
- struct dfs_filesystem *fs,
- const char *oldpath,
- const char *newpath)
- {
- int result;
- char *op, *np;
- op = winpath_dirdup(WIN32_DIRDISK_ROOT, oldpath);
- np = winpath_dirdup(WIN32_DIRDISK_ROOT, newpath);
- if (op == RT_NULL || np == RT_NULL)
- {
- rt_kprintf("out of memory.\n");
- return -ENOMEM;
- }
- /* If the function fails, the return value is zero. */
- result = MoveFile(op, np);
- rt_free(op);
- rt_free(np);
- if (result == 0)
- return win32_result_to_dfs(GetLastError());
- return 0;
- }
- static int dfs_win32_stat(struct dfs_filesystem *fs, const char *path, struct stat *st)
- {
- WIN32_FIND_DATA fileInfo;
- HANDLE hFind;
- char *fp;
- fp = winpath_dirdup(WIN32_DIRDISK_ROOT, path);
- if (fp == RT_NULL)
- {
- rt_kprintf("out of memory.\n");
- return -ENOMEM;
- }
- hFind = FindFirstFile(fp, &fileInfo);
- rt_free(fp);
- if (hFind == INVALID_HANDLE_VALUE)
- goto __err;
- st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
- S_IWUSR | S_IWGRP | S_IWOTH;
- /* convert file info to dfs stat structure */
- if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- st->st_mode &= ~S_IFREG;
- st->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
- }
- st->st_dev = 0;
- st->st_size = fileInfo.nFileSizeLow;
- /* get st_mtime. */
- {
- LARGE_INTEGER time_tmp;
- time_tmp.LowPart = fileInfo.ftLastWriteTime.dwLowDateTime;
- time_tmp.HighPart = fileInfo.ftLastWriteTime.dwHighDateTime;
- /* removes the diff between 1970 and 1601. */
- time_tmp.QuadPart -= 11644473600000 * 10000;
- /* converts back from 100-nanoseconds to seconds. */
- time_tmp.QuadPart /= 10UL * 1000 * 1000;
- st->st_mtime = time_tmp.QuadPart;
- }
- FindClose(hFind);
- return 0;
- __err:
- return win32_result_to_dfs(GetLastError());
- }
- static const struct dfs_file_ops dfs_win32_file_ops =
- {
- dfs_win32_open,
- dfs_win32_close,
- dfs_win32_ioctl,
- dfs_win32_read,
- dfs_win32_write,
- dfs_win32_flush,
- dfs_win32_seek,
- dfs_win32_getdents,
- };
- static const struct dfs_filesystem_ops dfs_win32_ops =
- {
- "wdir", /* file system type: dir */
- DFS_FS_FLAG_DEFAULT,
- &dfs_win32_file_ops,
- dfs_win32_mount,
- dfs_win32_unmount,
- dfs_win32_mkfs,
- dfs_win32_statfs,
- dfs_win32_unlink,
- dfs_win32_stat,
- dfs_win32_rename,
- };
- int dfs_win32_init(void)
- {
- /* register uffs file system */
- dfs_register(&dfs_win32_ops);
- return 0;
- }
- static rt_err_t nop_init(rt_device_t dev)
- {
- return RT_EOK;
- }
- static rt_err_t nop_open(rt_device_t dev, rt_uint16_t oflag)
- {
- return RT_EOK;
- }
- static rt_err_t nop_close(rt_device_t dev)
- {
- return RT_EOK;
- }
- static rt_size_t nop_read(rt_device_t dev,
- rt_off_t pos,
- void *buffer,
- rt_size_t size)
- {
- return size;
- }
- static rt_size_t nop_write(rt_device_t dev,
- rt_off_t pos,
- const void *buffer,
- rt_size_t size)
- {
- return size;
- }
- static rt_err_t nop_control(rt_device_t dev, int cmd, void *args)
- {
- return RT_EOK;
- }
- static struct rt_device win_sharedir_dev;
- rt_err_t rt_win_sharedir_init(const char *name)
- {
- rt_device_t dev;
- dev = &win_sharedir_dev;
- RT_ASSERT(dev != RT_NULL);
- /* set device class and generic device interface */
- dev->type = RT_Device_Class_Block;
- dev->init = nop_init;
- dev->open = nop_open;
- dev->read = nop_read;
- dev->write = nop_write;
- dev->close = nop_close;
- dev->control = nop_control;
- dev->rx_indicate = RT_NULL;
- dev->tx_complete = RT_NULL;
- /* register to RT-Thread device system */
- return rt_device_register(dev, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
- }
|