#At file:///C:/w/repo/mysql-5.1-telco-7.0-bug45402/ based on revid:jack@stripped
2938 jack andrews 2009-07-01
Bug #45402 Win32AsyncFile::rmrfReq can run an infinite loop
- ported to *n?x
- added test for symlink
modified:
storage/ndb/src/common/util/DirIterator.cpp
=== modified file 'storage/ndb/src/common/util/DirIterator.cpp'
--- a/storage/ndb/src/common/util/DirIterator.cpp 2009-07-01 10:53:50 +0000
+++ b/storage/ndb/src/common/util/DirIterator.cpp 2009-07-01 18:37:41 +0000
@@ -36,26 +36,41 @@
class DirIteratorImpl {
DIR* m_dirp;
- const char *m_path;
+ BaseString m_path;
- Entry to_entry(struct dirent* dp) const {
+ bool to_entry(DirIterator::Entry &entry, struct dirent* dp) const {
+ entry.type = DirIterator::Entry::UNKNOWN;
#ifdef _DIRENT_HAVE_D_TYPE
/*
Using dirent's d_type field to determine if
it's a regular file
*/
- if(dp->d_type != DT_UNKNOWN)
- return (dp->d_type == DT_REG);
+ switch (dp->d_type){
+ case DT_REG:
+ entry.type = DirIterator::Entry::ISFILE;
+ return true;
+ case DT_DIR:
+ entry.type = DirIterator::Entry::ISDIR;
+ return true;
+ } // Fallback to use 'stat'
#endif
/* Using stat to read more info about the file */
BaseString fullpath;
- fullpath.assfmt("%s/%s", m_path, dp->d_name);
+ fullpath.assfmt("%s/%s", m_path.c_str(), dp->d_name);
struct stat buf;
if (stat(fullpath.c_str(), &buf))
- return UNDEFINED; // 'stat' failed
+ return false;
- return ... S_ISREG(buf.st_mode);
+ if (S_ISREG(buf.st_mode)) {
+ entry.type = DirIterator::Entry::ISFILE;
+ return true;
+ }
+ if (S_ISDIR(buf.st_mode)) {
+ entry.type = DirIterator::Entry::ISDIR;
+ return true;
+ }
+ return false;
}
@@ -64,7 +79,7 @@ public:
m_dirp(NULL) {};
~DirIteratorImpl() {
- closedir(m_dirp);
+ close();
}
int open(const char* path){
@@ -75,13 +90,36 @@ public:
return 0;
}
- const char* next_file(const Entry &entry){
+ const char* next_entry(DirIterator::Entry &entry){
struct dirent* dp;
- while ((dp = readdir(m_dirp)) != NULL &&
- !is_regular_file(dp))
- ;
- return dp ? dp->d_name : NULL;
+ const char *s;
+ while ((dp = readdir(m_dirp)) != NULL) {
+ s = dp->d_name;
+ if(!strcmp(s,".") || !strcmp(s,".."))
+ continue;
+ to_entry(entry, dp);
+ return s;
+ }
+ return 0;
}
+
+ const char* next_file(DirIterator::Entry &entry){
+ while(next_entry(entry))
+ if(entry.type==DirIterator::Entry::ISFILE);
+ return entry.name;
+ return 0;
+ }
+
+ int close() {
+ if(m_dirp)
+ closedir(m_dirp);
+ m_dirp = 0;
+ }
+
+ const char *path() {
+ return m_path.c_str();
+ }
+
};
#else
@@ -214,7 +252,7 @@ static inline int rmdir(const char *s)
}
#endif
-static inline int remove_dir_recursive(const char* dir) {
+int ndb_remove_dir_recursive(const char* dir) {
struct stat statbuf;
if(stat(dir,&statbuf)==-1 && errno==ENOENT)
return -1;
@@ -227,7 +265,7 @@ static inline int remove_dir_recursive(c
int has_entries;
int rv;
require(!(rv = di.open(bss[0].c_str())));
- has_entries = (int)di.next_entry(entry);
+ has_entries = (long)di.next_entry(entry);
if (!has_entries) {
require(!rmdir(di.path()));
bss.erase(0); //pop
@@ -239,10 +277,12 @@ static inline int remove_dir_recursive(c
while ((name = di.next_entry(entry))) {
BaseString bs;
bs.assfmt("%s%s%s", di.path(), DIR_SEPARATOR, name);
- if (entry.type!=DirIterator::Entry::ISDIR) {
- require(!unlink(bs.c_str()));
+ if (entry.type==DirIterator::Entry::ISDIR) {
+ // a link can appear as a dir, so try to delete link first
+ if(unlink(bs.c_str()))
+ bss.push(bs,0);
} else {
- bss.push(bs,0);
+ require(!unlink(bs.c_str()));
}
}
}
@@ -250,6 +290,7 @@ static inline int remove_dir_recursive(c
}
#ifdef TAP_TEST
+#include <unistd.h>
#include <NdbTap.hpp>
inline int mkdirectory(const char *path) {
@@ -264,7 +305,7 @@ inline int mkdirectory(const char *path)
TAPTEST(DirIterator)
{
struct stat statbuf;
- remove_dir_recursive(TMP);
+ ndb_remove_dir_recursive(TMP);
OK(stat(TMP,&statbuf)==-1 && errno==ENOENT);
OK(!mkdirectory(TMP));
fclose(fopen(TMP DIR_SEPARATOR "a","w"));
@@ -275,10 +316,10 @@ TAPTEST(DirIterator)
fclose(fopen(TMP DIR_SEPARATOR "d" DIR_SEPARATOR "c","w"));
fclose(fopen(TMP DIR_SEPARATOR "d" DIR_SEPARATOR "c.x","w"));
#ifndef _WIN32
- create symlink to test that, too.
+ OK(!symlink("/etc",TMP "/d/symlink"));
#endif
- OK(!remove_dir_recursive(TMP));
+ OK(!ndb_remove_dir_recursive(TMP));
OK(stat(TMP,&statbuf)==-1 && errno==ENOENT);
return 1;
}
Attachment: [text/bzr-bundle] bzr/jack@sun.com-20090701183741-qzfs3vuhcs48n982.bundle
| Thread |
|---|
| • bzr commit into mysql-5.1-telco-7.0 branch (jack:2938) Bug#45402 | jack andrews | 1 Jul |