From 73a71e19c8375e5c8a11156bcb0dfdf7866f7168 Mon Sep 17 00:00:00 2001 From: ocean Date: Sun, 1 Jan 2006 08:12:39 +0000 Subject: * win32/win32.c (rb_w32_seekdir): should not segfault even if passed the location which rb_w32_telldir didn't return. [ruby-core:7035] * test/ruby/test_dir.rb: added. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@9787 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- win32/win32.c | 45 +++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-) (limited to 'win32/win32.c') diff --git a/win32/win32.c b/win32/win32.c index 6541c3dc5b..ef6886af2b 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -1448,6 +1448,20 @@ rb_w32_opendir(const char *filename) return p; } +// +// Move to next entry +// + +static void +move_to_next_entry(DIR *dirp) +{ + if (dirp->curr) { + dirp->curr += strlen(dirp->curr) + 1; + if (dirp->curr >= (dirp->start + dirp->size)) { + dirp->curr = NULL; + } + } +} // // Readdir just returns the current string pointer and bumps the @@ -1457,7 +1471,6 @@ rb_w32_opendir(const char *filename) struct direct * rb_w32_readdir(DIR *dirp) { - int len; static int dummy = 0; if (dirp->curr) { @@ -1466,9 +1479,8 @@ rb_w32_readdir(DIR *dirp) // first set up the structure to return // - len = strlen(dirp->curr); strcpy(dirp->dirstr.d_name, dirp->curr); - dirp->dirstr.d_namlen = len; + dirp->dirstr.d_namlen = strlen(dirp->curr); // // Fake inode @@ -1479,10 +1491,7 @@ rb_w32_readdir(DIR *dirp) // Now set up for the next call to readdir // - dirp->curr += len + 1; - if (dirp->curr >= (dirp->start + dirp->size)) { - dirp->curr = NULL; - } + move_to_next_entry(dirp); return &(dirp->dirstr); @@ -1497,7 +1506,15 @@ rb_w32_readdir(DIR *dirp) long rb_w32_telldir(DIR *dirp) { - return (long) dirp->curr; /* ouch! pointer to long cast */ + long loc = 0; char *p = dirp->curr; + + rb_w32_rewinddir(dirp); + + while (p != dirp->curr) { + move_to_next_entry(dirp); loc++; + } + + return loc; } // @@ -1507,7 +1524,11 @@ rb_w32_telldir(DIR *dirp) void rb_w32_seekdir(DIR *dirp, long loc) { - dirp->curr = (char *) loc; /* ouch! long to pointer cast */ + rb_w32_rewinddir(dirp); + + while (dirp->curr && loc-- > 0) { + move_to_next_entry(dirp); + } } // @@ -1517,7 +1538,7 @@ rb_w32_seekdir(DIR *dirp, long loc) void rb_w32_rewinddir(DIR *dirp) { - dirp->curr = dirp->start; + dirp->curr = dirp->start; } // @@ -1527,8 +1548,8 @@ rb_w32_rewinddir(DIR *dirp) void rb_w32_closedir(DIR *dirp) { - free(dirp->start); - free(dirp); + free(dirp->start); + free(dirp); } EXTERN_C void __cdecl _lock_fhandle(int); -- cgit v1.2.3