Merge pull request #424 from prife/master

dfs_win32: add seekdir support, fix #346
This commit is contained in:
Bernard Xiong 2015-02-02 09:08:23 +08:00
commit 1158fba15b
1 changed files with 83 additions and 66 deletions

View File

@ -50,6 +50,14 @@
#define WIN32_DIRDISK_ROOT "." /* "F:\\Project\\svn\\rtt\\trunk\\bsp\\simulator_test" */ #define WIN32_DIRDISK_ROOT "." /* "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. /* There are so many error codes in windows, you'd better google for details.
* google "System Error Codes (Windows)" * google "System Error Codes (Windows)"
* http://msdn.microsoft.com/ZH-CN/library/windows/desktop/ms681381(v=vs.85).aspx * http://msdn.microsoft.com/ZH-CN/library/windows/desktop/ms681381(v=vs.85).aspx
@ -166,8 +174,8 @@ static int dfs_win32_open(struct dfs_fd *file)
oflag = file->flags; oflag = file->flags;
if (oflag & DFS_O_DIRECTORY) /* operations about dir */ if (oflag & DFS_O_DIRECTORY) /* operations about dir */
{ {
struct _finddata_t dir; WINDIR *wdirp;
int handle; HANDLE handle;
int len; int len;
file_path = winpath_dirdup(WIN32_DIRDISK_ROOT, file->path); file_path = winpath_dirdup(WIN32_DIRDISK_ROOT, file->path);
@ -191,14 +199,24 @@ static int dfs_win32_open(struct dfs_fd *file)
strcat(file_path, "*.*"); strcat(file_path, "*.*");
/* _findfirst will get '.' */ /* _findfirst will get '.' */
if ((handle = _findfirst(file_path, &dir)) == -1) /* 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); rt_free(file_path);
goto __err; 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);
/* save this pointer,will used by dfs_win32_getdents*/ file->data = (void *)wdirp;
file->data = (void *)handle;
rt_free(file_path); rt_free(file_path);
return DFS_STATUS_OK; return DFS_STATUS_OK;
} }
@ -243,25 +261,22 @@ __err:
static int dfs_win32_close(struct dfs_fd *file) static int dfs_win32_close(struct dfs_fd *file)
{ {
int oflag; if (file->flags & DFS_O_DIRECTORY)
oflag = file->flags;
if (oflag & DFS_O_DIRECTORY)
{ {
/* operations about dir */ WINDIR *wdirp = (WINDIR*)(file->data);
if (_findclose((intptr_t)file->data) < 0) RT_ASSERT(wdirp != RT_NULL);
goto __err; 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 0;
} }
/* regular file operations */
if (_close((int)(file->data)) < 0)
goto __err;
return 0;
__err:
return win32_result_to_dfs(GetLastError()); return win32_result_to_dfs(GetLastError());
} }
@ -316,16 +331,19 @@ static int dfs_win32_seek(struct dfs_fd *file,
/* set offset as current offset */ /* set offset as current offset */
if (file->type == FT_DIRECTORY) if (file->type == FT_DIRECTORY)
{ {
return -DFS_STATUS_ENOSYS; WINDIR* wdirp = (WINDIR*)(file->data);
RT_ASSERT(wdirp != RT_NULL);
wdirp->curr = wdirp->start + offset;
return offset;
} }
else if (file->type == FT_REGULAR) else //file->type == FT_REGULAR)
{ {
result = _lseek((int)(file->data), offset, SEEK_SET); result = _lseek((int)(file->data), offset, SEEK_SET);
if (result >= 0) if (result >= 0)
return offset; return offset;
} else
return win32_result_to_dfs(GetLastError()); return win32_result_to_dfs(GetLastError());
}
} }
/* return the size of struct dirent*/ /* return the size of struct dirent*/
@ -334,53 +352,52 @@ static int dfs_win32_getdents(
struct dirent *dirp, struct dirent *dirp,
rt_uint32_t count) rt_uint32_t count)
{ {
rt_uint32_t index; WINDIR *wdirp;
struct dirent *d; struct dirent *d = dirp;
struct _finddata_t fileinfo;
int handle;
int result; int result;
handle = (int)(file->data); /* make integer count */
RT_ASSERT(handle != RT_NULL); if (count / sizeof(struct dirent) != 1)
return -DFS_STATUS_EINVAL;
/* round count, count is always 1 */ wdirp = (WINDIR*)(file->data);
count = (count / sizeof(struct dirent)) * sizeof(struct dirent); RT_ASSERT(wdirp != RT_NULL);
if (count == 0) return -DFS_STATUS_EINVAL; if (wdirp->curr == NULL) //no more entries in this directory
return 0;
index = 0; /* get the current entry */
/* usually, the while loop should only be looped only once! */ if (wdirp->finddata.attrib & _A_SUBDIR)
while (1) d->d_type = DFS_DT_DIR;
{
d = dirp + index;
if (_findnext(handle, &fileinfo) != 0) //-1 failed
goto __err;
if (fileinfo.attrib & _A_SUBDIR)
d->d_type = DFS_DT_DIR; /* directory */
else else
d->d_type = DFS_DT_REG; d->d_type = DFS_DT_REG;
d->d_namlen = strlen(wdirp->curr);
/* write the rest arguments of struct dirent* dirp */ strncpy(d->d_name, wdirp->curr, DFS_PATH_MAX);
d->d_namlen = strlen(fileinfo.name);
d->d_reclen = (rt_uint16_t)sizeof(struct dirent); d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
strcpy(d->d_name, fileinfo.name); wdirp->curr += (strlen(wdirp->curr) + 1);
file->pos = wdirp->curr - wdirp->start + sizeof(struct dirent);//NOTE!
index ++; /* now set up for the next call to readdir */
if (index * sizeof(struct dirent) >= count) if (wdirp->curr >= wdirp->end)
break; {
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);
} }
if (index == 0) else
return 0; {
file->pos += index * sizeof(struct dirent);
return index * sizeof(struct dirent);
__err:
if ((result = GetLastError()) == ERROR_NO_MORE_FILES) if ((result = GetLastError()) == ERROR_NO_MORE_FILES)
return 0; wdirp->curr = NULL;
else else
return win32_result_to_dfs(result); return win32_result_to_dfs(result);
}
}
return sizeof(struct dirent);
} }
static int dfs_win32_unlink(struct dfs_filesystem *fs, const char *path) static int dfs_win32_unlink(struct dfs_filesystem *fs, const char *path)