Jelajahi Sumber

Merge pull request #424 from prife/master

dfs_win32: add seekdir support, fix #346
Bernard Xiong 10 tahun lalu
induk
melakukan
1158fba15b
1 mengubah file dengan 82 tambahan dan 65 penghapusan
  1. 82 65
      bsp/simulator/drivers/dfs_win32.c

+ 82 - 65
bsp/simulator/drivers/dfs_win32.c

@@ -50,6 +50,14 @@
 
 #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.
  * google  "System Error Codes (Windows)"
  * 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;
     if (oflag & DFS_O_DIRECTORY)   /* operations about dir */
     {
-        struct _finddata_t  dir;
-        int handle;
+        WINDIR *wdirp;
+        HANDLE handle;
         int len;
 
         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, "*.*");
         /* _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);
             goto __err;
         }
-
-        /* save this pointer,will used by  dfs_win32_getdents*/
-        file->data = (void *)handle;
+        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 DFS_STATUS_OK;
     }
@@ -243,25 +261,22 @@ __err:
 
 static int dfs_win32_close(struct dfs_fd *file)
 {
-    int oflag;
-
-    oflag = file->flags;
-    if (oflag & DFS_O_DIRECTORY)
+    if (file->flags & DFS_O_DIRECTORY)
     {
-        /* operations about dir */
-        if (_findclose((intptr_t)file->data) < 0)
-            goto __err;
-
-        return 0;
+        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;
     }
 
-    /* regular file operations */
-    if (_close((int)(file->data)) < 0)
-        goto __err;
-
-    return 0;
-
-__err:
     return win32_result_to_dfs(GetLastError());
 }
 
@@ -316,16 +331,19 @@ static int dfs_win32_seek(struct dfs_fd *file,
     /* set offset as current offset */
     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);
         if (result >= 0)
             return offset;
+        else
+            return win32_result_to_dfs(GetLastError());
     }
-
-    return win32_result_to_dfs(GetLastError());
 }
 
 /* return the size of struct dirent*/
@@ -334,53 +352,52 @@ static int dfs_win32_getdents(
     struct dirent *dirp,
     rt_uint32_t count)
 {
-    rt_uint32_t index;
-    struct dirent *d;
-    struct _finddata_t  fileinfo;
-    int handle;
+    WINDIR *wdirp;
+    struct dirent *d = dirp;
     int result;
 
-    handle = (int)(file->data);
-    RT_ASSERT(handle != RT_NULL);
+    /* make integer count */
+    if (count / sizeof(struct dirent) != 1)
+        return -DFS_STATUS_EINVAL;
 
-    /* round count, count is always 1 */
-    count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
-    if (count == 0) return -DFS_STATUS_EINVAL;
+    wdirp = (WINDIR*)(file->data);
+    RT_ASSERT(wdirp != RT_NULL);
+    if (wdirp->curr == NULL) //no more entries in this directory
+        return 0;
 
-    index = 0;
-    /* usually, the while loop should only be looped only once! */
-    while (1)
+    /* get the current entry */
+    if (wdirp->finddata.attrib & _A_SUBDIR)
+        d->d_type = DFS_DT_DIR;
+    else
+        d->d_type = DFS_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)
     {
-        d = dirp + index;
-        if (_findnext(handle, &fileinfo) != 0) //-1 failed
-            goto __err;
-
-        if (fileinfo.attrib & _A_SUBDIR)
-            d->d_type = DFS_DT_DIR;  /* directory */
+        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
-            d->d_type = DFS_DT_REG;
-
-        /* write the rest arguments of struct dirent* dirp  */
-        d->d_namlen = strlen(fileinfo.name);
-        d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
-        strcpy(d->d_name, fileinfo.name);
-
-        index ++;
-        if (index * sizeof(struct dirent) >= count)
-            break;
+        {
+            if ((result = GetLastError()) == ERROR_NO_MORE_FILES)
+                wdirp->curr = NULL;
+            else
+                return win32_result_to_dfs(result);
+        }
     }
-    if (index == 0)
-        return 0;
-
-    file->pos += index * sizeof(struct dirent);
 
-    return index * sizeof(struct dirent);
-
-__err:
-    if ((result = GetLastError()) == ERROR_NO_MORE_FILES)
-        return 0;
-    else
-        return win32_result_to_dfs(result);
+    return sizeof(struct dirent);
 }
 
 static int dfs_win32_unlink(struct dfs_filesystem *fs, const char *path)