diff options
author | ocean <ocean@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2006-01-01 05:49:01 +0000 |
---|---|---|
committer | ocean <ocean@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2006-01-01 05:49:01 +0000 |
commit | bece43b9ab395402f97826d332b3f960d64b73a5 (patch) | |
tree | 97fb9053a86116544c313f0a55665317bcf1f021 | |
parent | 3d88eb65dc3de6279730a580ca49045f15bfbb3e (diff) | |
download | ruby-bece43b9ab395402f97826d332b3f960d64b73a5.tar.gz ruby-bece43b9ab395402f97826d332b3f960d64b73a5.tar.xz ruby-bece43b9ab395402f97826d332b3f960d64b73a5.zip |
* win32/win32.c (rb_w32_seekdir): should not segfault even if passed
the location which rb_w32_telldir didn't return. (and should change
`bits' position) [ruby-core:7035]
* win32/dir.h: ditto. (stores `loc' instead of `bitpos')
* test/ruby/test_dir.rb: added.
git-svn-id: http://svn.ruby-lang.org/repos/ruby/trunk@9782 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | test/ruby/test_dir.rb | 42 | ||||
-rw-r--r-- | win32/dir.h | 2 | ||||
-rw-r--r-- | win32/win32.c | 48 |
4 files changed, 83 insertions, 19 deletions
@@ -1,3 +1,13 @@ +Sun Jan 1 14:42:54 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp> + + * win32/win32.c (rb_w32_seekdir): should not segfault even if passed + the location which rb_w32_telldir didn't return. (and should change + `bits' position) [ruby-core:7035] + + * win32/dir.h: ditto. (stores `loc' instead of `bitpos') + + * test/ruby/test_dir.rb: added. + Sat Dec 31 22:57:00 2005 Nobuyoshi Nakada <nobu@ruby-lang.org> * eval.c (rb_thread_save_context): should not recycle scope object used diff --git a/test/ruby/test_dir.rb b/test/ruby/test_dir.rb new file mode 100644 index 000000000..09685bee8 --- /dev/null +++ b/test/ruby/test_dir.rb @@ -0,0 +1,42 @@ +require 'test/unit' + +require 'tmpdir' +require 'fileutils' + +class TestDir < Test::Unit::TestCase + + ROOT = File.join(Dir.tmpdir, "__test_dir__#{$$}") + + def setup + Dir.mkdir(ROOT) + for i in ?a..?z + if i % 2 == 0 + FileUtils.touch(File.join(ROOT, i.chr)) + else + FileUtils.mkdir(File.join(ROOT, i.chr)) + end + end + end + + def teardown + FileUtils.rm_rf ROOT if File.directory?(ROOT) + end + + def test_seek + dir = Dir.open(ROOT) + begin + cache = [] + loop do + pos = dir.tell + break unless name = dir.read + cache << [pos, name] + end + for x in cache.sort_by {|x| x[0] % 3 } # shuffle + dir.seek(x[0]) + assert_equal(x[1], dir.read) + end + ensure + dir.close + end + end +end diff --git a/win32/dir.h b/win32/dir.h index e12c6e159..f472832d2 100644 --- a/win32/dir.h +++ b/win32/dir.h @@ -21,9 +21,9 @@ typedef struct { char *curr; long size; long nfiles; + long loc; /* [0, nfiles) */ struct direct dirstr; char *bits; /* used for d_isdir and d_isrep */ - long bitpos; /* used for d_isdir and d_isrep */ } DIR; diff --git a/win32/win32.c b/win32/win32.c index a5665cf00..9c06e2562 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -1461,6 +1461,21 @@ rb_w32_opendir(const char *filename) return p; } +// +// Move to next entry +// + +static void +move_to_next_entry(DIR *dirp) +{ + if (dirp->curr) { + dirp->loc++; + 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 @@ -1470,7 +1485,6 @@ rb_w32_opendir(const char *filename) struct direct * rb_w32_readdir(DIR *dirp) { - int len; static int dummy = 0; if (dirp->curr) { @@ -1479,9 +1493,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 @@ -1491,19 +1504,14 @@ rb_w32_readdir(DIR *dirp) // // Attributes // - dirp->dirstr.d_isdir = GetBit(dirp->bits, dirp->bitpos); - dirp->bitpos++; - dirp->dirstr.d_isrep = GetBit(dirp->bits, dirp->bitpos); - dirp->bitpos++; + dirp->dirstr.d_isdir = GetBit(dirp->bits, dirp->loc * 2); + dirp->dirstr.d_isrep = GetBit(dirp->bits, dirp->loc * 2 + 1); // // 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); @@ -1518,7 +1526,7 @@ rb_w32_readdir(DIR *dirp) long rb_w32_telldir(DIR *dirp) { - return (long) dirp->curr; /* ouch! pointer to long cast */ + return dirp->loc; } // @@ -1528,7 +1536,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 && dirp->loc < loc) { + move_to_next_entry(dirp); + } } // @@ -1538,8 +1550,8 @@ rb_w32_seekdir(DIR *dirp, long loc) void rb_w32_rewinddir(DIR *dirp) { - dirp->curr = dirp->start; - dirp->bitpos = 0; + dirp->curr = dirp->start; + dirp->loc = 0; } // @@ -1549,9 +1561,9 @@ rb_w32_rewinddir(DIR *dirp) void rb_w32_closedir(DIR *dirp) { - free(dirp->start); - free(dirp->bits); - free(dirp); + free(dirp->start); + free(dirp->bits); + free(dirp); } #if (defined _MT || defined __MSVCRT__) && !defined __BORLANDC__ |