List:Commits« Previous MessageNext Message »
From:jack andrews Date:July 1 2009 12:54pm
Subject:bzr commit into mysql-5.1-telco-7.0 branch (jack:2937) Bug#45402
View as plain text  
#At file:///C:/w/repo/mysql-5.1-telco-7.0-bug45402/ based on revid:jack@stripped

 2937 jack andrews	2009-07-01
      Bug #45402        Win32AsyncFile::rmrfReq can run an infinite loop
      
              - implemented and tested win32 implementation

    modified:
      storage/ndb/include/util/DirIterator.hpp
      storage/ndb/src/common/util/DirIterator.cpp
=== modified file 'storage/ndb/include/util/DirIterator.hpp'
--- a/storage/ndb/include/util/DirIterator.hpp	2009-06-29 10:15:39 +0000
+++ b/storage/ndb/include/util/DirIterator.hpp	2009-07-01 10:53:50 +0000
@@ -16,14 +16,47 @@
 #ifndef DirIterator_HPP
 #define DirIterator_HPP
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
 class DirIterator {
   class DirIteratorImpl& m_impl;
+  DirIterator(const DirIterator&);  // not impl
+  DirIterator& operator=(const DirIterator&); // not impl
 public:
+
+  struct Entry {
+    enum { UNKNOWN, ISFILE, ISDIR } type;
+    const char* name;
+    Entry() :
+      type(UNKNOWN), name(0) {};
+  };
   DirIterator();
   ~DirIterator();
 
-  int open(const char* path);
-  const char* next_file(void);
+  // 0: success
+  int open(const char *path);
+  int close();
+  const char* path();
+  const char* next_entry(Entry &);
+
+  // 0 - no more files, char* otherwise
+  const char* next_file() {
+    const char*s; 
+    Entry entry;
+    do {
+      s = next_entry(entry); 
+    } while (s && entry.type != Entry::ISFILE);
+    return s;
+  }
 };
 
+
+/*
+  Remove a directory and all it's subdirecrories
+*/
+
+int remove_dir_recursive(const char* name);
+
 #endif

=== modified file 'storage/ndb/src/common/util/DirIterator.cpp'
--- a/storage/ndb/src/common/util/DirIterator.cpp	2009-06-29 10:15:39 +0000
+++ b/storage/ndb/src/common/util/DirIterator.cpp	2009-07-01 10:53:50 +0000
@@ -15,8 +15,18 @@
 
 #include "DirIterator.hpp"
 #include <stdio.h>
+#include <sys/types.h> 
+#include <sys/stat.h>
+
+#define require(x) do {\
+  long x_,e=errno=0;x_=(x);e=errno;if(!x_) {\
+    fprintf(stderr,"required %s, got %ld\n%s:%d\n",#x,x_,__FILE__,__LINE__);\
+    errno=e;\
+    perror("perror: ");\
+    assert(0); exit(1); }\
+} while(0)
 
-#ifndef __WIN__
+#ifndef _WIN32
 
 #include <dirent.h>
 
@@ -28,7 +38,7 @@ class DirIteratorImpl {
   DIR* m_dirp;
   const char *m_path;
 
-  bool is_regular_file(struct dirent* dp) const {
+  Entry to_entry(struct dirent* dp) const {
 #ifdef _DIRENT_HAVE_D_TYPE
     /*
       Using dirent's d_type field to determine if
@@ -43,9 +53,9 @@ class DirIteratorImpl {
 
     struct stat buf;
     if (stat(fullpath.c_str(), &buf))
-      return false; // 'stat' failed
+      return UNDEFINED; // 'stat' failed
 
-    return S_ISREG(buf.st_mode);
+    return ... S_ISREG(buf.st_mode);
 
   }
 
@@ -65,41 +75,69 @@ public:
     return 0;
   }
 
-  const char* next_file(void){
+  const char* next_file(const Entry &entry){
     struct dirent* dp;
     while ((dp = readdir(m_dirp)) != NULL &&
            !is_regular_file(dp))
       ;
-    return dp ? dp->d_name : NULL;
+      return dp ? dp->d_name : NULL;
   }
 };
 
 #else
 
 #include <BaseString.hpp>
+#include <direct.h>
 
 class DirIteratorImpl {
-  bool m_first;
+  bool m_first, m_end;
   WIN32_FIND_DATA m_find_data;
   HANDLE m_find_handle;
+  intptr_t m_handle;
+  BaseString m_path;
 
-  bool is_dir(const WIN32_FIND_DATA find_data) const {
-    return (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+  bool to_entry(DirIterator::Entry &e, const WIN32_FIND_DATA find_data) const {
+    DWORD atts = find_data.dwFileAttributes;
+    e.name = m_find_data.cFileName;
+    e.type = DirIterator::Entry::UNKNOWN;
+    if (atts & FILE_ATTRIBUTE_DIRECTORY)
+      e.type = DirIterator::Entry::ISDIR;
+    if ((atts & FILE_ATTRIBUTE_NORMAL) || (atts & FILE_ATTRIBUTE_TEMPORARY))
+      e.type = DirIterator::Entry::ISFILE;
+    return true;
+  }
+
+  BaseString normalize_path(const char *path)
+  { BaseString rv = path;
+    int len = rv.length();
+    if (rv.c_str()[len-1] == DIR_SEPARATOR[0])
+      rv.substr(0,len-1);
+    return rv;
   }
 
 public:
   DirIteratorImpl():
+    m_path(),
     m_first(true),
+    m_end(false),
     m_find_handle(INVALID_HANDLE_VALUE) {};
 
   ~DirIteratorImpl() {
-    FindClose(m_find_handle);
+    close();
+  }
+
+  int close() {
+    if(m_find_handle != INVALID_HANDLE_VALUE)
+      if(!FindClose(m_find_handle))
+        return -1;
+    return 0;
   }
 
   int open(const char* path){
-    BaseString path_buf;
-    path_buf.assfmt("%s\\*", path);
-    m_find_handle = FindFirstFile(path_buf.c_str(), &m_find_data);
+    m_path = normalize_path(path);
+    BaseString pattern;
+    pattern.assfmt("%s\\*", m_path);
+    m_find_handle = FindFirstFile(pattern.c_str(), &m_find_data);
     if(m_find_handle == INVALID_HANDLE_VALUE)
     {
       if (GetLastError() == ERROR_FILE_NOT_FOUND)
@@ -110,22 +148,30 @@ public:
     return 0;
   }
 
-  const char* next_file(void){
-	  while(m_first || FindNextFile(m_find_handle, &m_find_data))
+  const char* next_entry(DirIterator::Entry &entry){
+    const char *s;
+    while(m_first || FindNextFile(m_find_handle, &m_find_data))
     {
-      m_first= false;
-      
-	    if (!is_dir(m_find_data))
-        return m_find_data.cFileName;
+      s = m_find_data.cFileName;
+      m_first = false;
+      if(!strcmp(s,".") || !strcmp(s,".."))
+        continue;
+      bool result = to_entry(entry,m_find_data);
+      if (!result)
+        return 0;
+      return s;
     }
     return NULL;    
   }
 
+  const char* path() {
+    return m_path.c_str();
+  }
+
 };
 
 #endif
 
-
 DirIterator::DirIterator() :
   m_impl(*new DirIteratorImpl())
 {
@@ -142,8 +188,98 @@ int DirIterator::open(const char* path)
   return m_impl.open(path);
 }
 
-const char* DirIterator::next_file(void)
+int DirIterator::close()
 {
-  return m_impl.next_file();
+  return m_impl.close();
 }
 
+const char *DirIterator::path()
+{
+  return m_impl.path();
+}
+
+const char* DirIterator::next_entry(Entry &entry)
+{
+  return m_impl.next_entry(entry);
+}
+
+#ifdef _WIN32
+static inline int unlink(const char *s)
+{
+  return _unlink(s);
+}
+static inline int rmdir(const char *s)
+{
+  return _rmdir(s);
+}
+#endif
+
+static inline int remove_dir_recursive(const char* dir) {
+  struct stat statbuf;
+  if(stat(dir,&statbuf)==-1 && errno==ENOENT)
+    return -1;
+  Vector<BaseString> bss;
+  bss.push(dir,0);
+  for (;bss.size();) {
+    DirIterator di;
+    DirIterator::Entry entry;
+    const char *name;
+    int has_entries;
+    int rv;
+    require(!(rv = di.open(bss[0].c_str())));
+    has_entries = (int)di.next_entry(entry);
+    if (!has_entries) {
+      require(!rmdir(di.path()));
+      bss.erase(0); //pop
+      di.close();
+      continue;
+    }
+    di.close();
+    require(!di.open(bss[0].c_str()));
+    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()));
+      } else {
+        bss.push(bs,0);
+      }
+    }
+  }
+  return 0;
+}
+
+#ifdef TAP_TEST
+#include <NdbTap.hpp>
+
+inline int mkdirectory(const char *path) {
+#ifdef _WIN32
+  return mkdir(path);
+#else
+  return mkdir(path,0777);
+#endif
+}
+
+#define TMP "tmp_dir_iterator"
+TAPTEST(DirIterator)
+{
+  struct stat statbuf;
+  remove_dir_recursive(TMP);
+  OK(stat(TMP,&statbuf)==-1 && errno==ENOENT);
+  OK(!mkdirectory(TMP));
+  fclose(fopen(TMP DIR_SEPARATOR "a","w"));
+  OK(!mkdirectory(TMP DIR_SEPARATOR "d"));
+  OK(!mkdirectory(TMP DIR_SEPARATOR "e"));
+  fclose(fopen(TMP DIR_SEPARATOR "d" DIR_SEPARATOR "a","w"));
+  fclose(fopen(TMP DIR_SEPARATOR "d" DIR_SEPARATOR "b","w"));
+  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.
+#endif
+
+  OK(!remove_dir_recursive(TMP));
+  OK(stat(TMP,&statbuf)==-1 && errno==ENOENT);
+  return 1;
+}
+#endif


Attachment: [text/bzr-bundle] bzr/jack@sun.com-20090701105350-cb9w6ccfggwx8i3l.bundle
Thread
bzr commit into mysql-5.1-telco-7.0 branch (jack:2937) Bug#45402jack andrews1 Jul