List:Commits« Previous MessageNext Message »
From:jack andrews Date:July 1 2009 6:39pm
Subject:bzr commit into mysql-5.1-telco-7.0 branch (jack:2938) Bug#45402
View as plain text  
#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#45402jack andrews1 Jul