List:Commits« Previous MessageNext Message »
From:jack andrews Date:June 19 2009 10:58am
Subject:bzr commit into mysql-5.1-telco-7.0 branch (jack:2936) Bug#45402
View as plain text  
#At file:///C:/w/repo/mysql-5.1-telco-7.0-bug45402/ based on revid:jack@stripped

 2936 jack andrews	2009-06-19
      Bug #45402  	Win32AsyncFile::rmrfReq can run an infinite loop
       . worked on supporting code
       . with test case (that does a rm -rf)

    added:
      storage/ndb/include/util/DirIterator.hpp
      storage/ndb/src/common/util/DirIterator.cpp
    modified:
      storage/ndb/src/common/util/CMakeLists.txt
=== added file 'storage/ndb/include/util/DirIterator.hpp'
--- a/storage/ndb/include/util/DirIterator.hpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/include/util/DirIterator.hpp	2009-06-19 10:56:58 +0000
@@ -0,0 +1,101 @@
+/* Copyright (C) 2009 Sun Microsystems, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef DirIterator_HPP
+#define DirIterator_HPP
+#include <util/BaseString.hpp>
+#include <stdio.h>
+
+enum fileinfo_e {ISDIR=1,ISFILE=2} ;
+typedef struct fileinfo {
+  char *name;
+  enum fileinfo_e type;
+} *FILEINFO;
+enum return_codes_e {NOTADIR=8,DIREMPTY,NOMORE,CHECKERRNO=128};
+
+typedef struct di *DI;
+
+int di_open(DI *di, const char *path);
+int di_next(DI  di, FILEINFO fi);
+const char *di_path(DI di);
+int di_close(DI *pdi);
+typedef int (*di_callback_t)(void *self, const char *name);
+int di_walk(const char *dir, void *self, di_callback_t on_dir, di_callback_t on_file);
+
+class DirIterator {
+  DI impl;
+  DirIterator(const DirIterator&){}  // don't copy these objects
+  DirIterator& operator=(const DirIterator&){}
+public:
+  DirIterator() : impl(0) {};
+  ~DirIterator() { close(); }
+
+  int open(const BaseString &path)
+  {
+    int rv_, rv = di_open(&impl,path.c_str());
+    if (rv) 
+      return rv;
+    struct fileinfo fi;
+    rv = di_next(impl,&fi);
+    di_close(&impl);
+    rv_ = di_open(&impl,path.c_str());
+    return rv ? DIREMPTY : rv_;
+  }
+
+  const char *get_path() 
+  { 
+    return di_path(impl);
+  }
+
+  int close()
+  {
+    return impl ? di_close(&impl) : 0;
+  }
+
+
+  // 0 - no more.  otherwise return next filename not a dir
+  // return val is valid until another next_XXX() call
+  const char* next_entry(bool& is_dir)
+  {
+    int rv;
+    struct fileinfo fi;
+
+    rv = di_next(impl, &fi);
+    is_dir = fi.type & ISDIR;
+    return rv ? 0 : fi.name;
+  }
+
+  const char* next_file(void)
+  {
+    bool is_dir;
+    const char *rv;
+    while ((rv=next_entry(is_dir)) && !is_dir)
+      ;
+    return rv ? 0 : rv;
+  }
+};
+
+int di_on_dir(void *self, const char *name);
+int di_on_file(void *self, const char *name);
+struct DirIteratorWalk
+{
+  virtual int on_dir(const BaseString&) = 0;
+  virtual int on_file(const BaseString&) = 0;
+  int walk(const BaseString &dir)
+  {
+    return di_walk(dir.c_str(), this, di_on_dir, di_on_file);
+  }
+};
+#endif

=== modified file 'storage/ndb/src/common/util/CMakeLists.txt'
--- a/storage/ndb/src/common/util/CMakeLists.txt	2009-06-02 14:00:06 +0000
+++ b/storage/ndb/src/common/util/CMakeLists.txt	2009-06-19 10:56:58 +0000
@@ -54,6 +54,7 @@ ADD_LIBRARY(ndbgeneral STATIC
             basestring_vsnprintf.c
             Bitmask.cpp
 	    ndbinfo.c
+	    DirIterator.cpp
 )
 TARGET_LINK_LIBRARIES(ndbgeneral zlib)
 
@@ -67,3 +68,8 @@ SET_TARGET_PROPERTIES(Bitmask-t
                       PROPERTIES COMPILE_FLAGS "-DTEST_BITMASK")
 TARGET_LINK_LIBRARIES(Bitmask-t ndbgeneral)
 
+ADD_EXECUTABLE(DirIterator-t DirIterator.cpp)
+SET_TARGET_PROPERTIES(DirIterator-t
+                      PROPERTIES COMPILE_FLAGS "-DTAP_TEST")
+TARGET_LINK_LIBRARIES(DirIterator-t ndbgeneral mysys wsock32)
+

=== added file 'storage/ndb/src/common/util/DirIterator.cpp'
--- a/storage/ndb/src/common/util/DirIterator.cpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/common/util/DirIterator.cpp	2009-06-19 10:56:58 +0000
@@ -0,0 +1,264 @@
+/* Copyright (C) 2009 Sun Microsystems, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#include <DirIterator.hpp>
+#ifdef _WIN32
+#include <direct.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+struct di {
+#ifdef _WIN32
+  char *path, *pat;
+  struct _finddata_t finddata;
+  intptr_t handle;
+  int first, end;
+#else
+#endif
+};
+
+static int di_normalize_path(const char *path, char **norm_path)
+{
+  *norm_path = strdup(path);
+  if (!*norm_path)
+    return CHECKERRNO;
+  int len = strlen(*norm_path);
+  if ((*norm_path)[len-1] == DIR_SEPARATOR[0])
+    (*norm_path)[len-1] = 0;
+  return 0;
+}
+
+const char *di_path(DI di)
+{
+  return di->path;
+}
+
+int di_open(DI *di, const char *path) {
+  struct _stat statbuf;
+  int rv, pathlen;
+  DI d ;
+  char *norm_path = 0;
+
+  *di = (DI)malloc(sizeof(struct di));
+  d=*di;
+  if(!d)
+    return CHECKERRNO;
+  if (rv = di_normalize_path(path, &norm_path)) {
+    int err = errno;
+    if (norm_path) 
+      free(norm_path);
+    errno = err;
+    return rv;
+  }
+#ifdef _WIN32
+  d->handle = -1;
+  d->path = (char*)malloc(strlen(norm_path) + 8);
+  if (!d->path)
+    return CHECKERRNO;
+  strcpy(d->path,norm_path);
+  free(norm_path);
+  pathlen = strlen(d->path);
+  assert(d->path[pathlen-1]!='\\');
+  rv = _stat(d->path, &statbuf);
+  if (rv || !(statbuf.st_mode & _S_IFDIR))
+    return NOTADIR;
+  d->pat = (char*)malloc(strlen(d->path) + 8);
+  if (!d->pat)
+    return CHECKERRNO;
+  sprintf(d->pat, "%s\\*", d->path);
+  d->first = 1;
+  d->end = 0;
+#else
+#endif
+  return 0;
+}
+int di_close(DI *pdi)
+{
+  DI di=*pdi;
+  if (di->handle != -1) {
+    _findclose(di->handle);
+    di->handle = -1;
+  }
+  if (di->path) {
+    free(di->path);
+    di->path = 0;
+  }
+  free(di);
+  *pdi=0;
+  return 0;
+}
+int di_next(DI di, FILEINFO fi)
+{
+#ifdef _WIN32
+  if (di->end)
+    return NOMORE;
+  if (di->first) {
+    if ((di->handle = _findfirst(di->pat, &di->finddata)) == -1L) {
+      di->end = 1;
+      DBUG_PRINT("info", ("findfirst returned error, errno: %d", errno));
+      return CHECKERRNO;
+    }
+  }
+  while ( di->first || !(di->end = !!_findnext(di->handle,&di->finddata)) ) {
+      di->first = 0;
+      char *s=di->finddata.name;
+      if (di->finddata.attrib & (_A_HIDDEN | _A_SYSTEM))
+        continue;
+      if(!strcmp(s,".") || !strcmp(s,".."))
+        continue;
+      fi->name = s;
+      fi->type = (di->finddata.attrib&_A_SUBDIR)?ISDIR:ISFILE;
+      return 0;
+  }
+  _findclose(di->handle);
+  di->handle = -1;
+#else
+  struct dirent *ent;
+  struct stat statbuf;
+  DIR* dir = opendir(path);
+  if(!dir) {
+    DBUG_PRINT("error", ("couldn't opendir(%s)", path));
+    return 1;
+  }
+  while (ent=readdir(dir))
+  { char s=ent->d_name;
+    int mode=0;
+    if(!strcmp(s,".") || !strcmp(s,".."))
+      continue;
+    if (stat(s, &statbuf) == -1)
+      continue;
+    mode=statbuf->st_mode;
+    struct fileinfo info={s,S_ISDIR(mode)?ISDIR:ISFILE};
+    infos.push_back(info);
+  }
+  (void) closedir(dirp);
+#endif
+  return NOMORE;
+}
+
+#ifdef TAP_TEST
+#include <NdbTap.hpp>
+#include <sys/types.h> 
+#include <sys/stat.h>
+
+typedef Vector<BaseString>  BSS;
+
+int deltree(char *dir)
+{
+  struct _stat statbuf;
+  if(_stat(dir,&statbuf)==-1 && errno==ENOENT)
+    return CHECKERRNO;
+  BSS bss;
+  bss.push(dir,0);
+  for (;bss.size();) {
+    DirIterator di;
+    const char *name;
+    bool is_dir;
+    int rv = di.open(bss[0].c_str());
+    OK(rv != NOTADIR && rv != CHECKERRNO);
+    if (rv == DIREMPTY) {
+      OK(!_rmdir(di.get_path()));
+      bss.erase(0); //pop
+      continue;
+    }
+    while (name = di.next_entry(is_dir)) {
+      BaseString bs;
+      bs.assfmt("%s%s%s", di.get_path(), DIR_SEPARATOR, name);
+      if (!is_dir) {  
+        OK(!_unlink(bs.c_str()));
+      } else {
+        bss.push(bs,0);
+      }
+    }
+  }
+  return 0;
+}
+
+int di_walk(const char *dir, void *self, di_callback_t on_dir, di_callback_t on_file)
+{
+  struct _stat statbuf;
+  if(_stat(dir,&statbuf)==-1 && errno==ENOENT)
+    return CHECKERRNO;
+  BSS bss;
+  bss.push(dir,0);
+  for (;bss.size();) {
+    DirIterator di;
+    const char *name;
+    bool is_dir;
+    int rv = di.open(bss[0].c_str());
+    OK(rv != NOTADIR && rv != CHECKERRNO);
+    if (rv == DIREMPTY) {
+      OK(!on_dir(self, di.get_path()));
+      bss.erase(0); //pop
+      continue;
+    }
+    while (name = di.next_entry(is_dir)) {
+      BaseString bs;
+      bs.assfmt("%s%s%s", di.get_path(), DIR_SEPARATOR, name);
+      if (!is_dir) {  
+        OK(!on_file(self, bs.c_str()));
+      } else {
+        bss.push(bs,0);
+      }
+    }
+  }
+  return 0;
+}
+
+int di_on_dir(void *self, const char *name)
+{
+  return ((DirIteratorWalk*)self)->on_dir(name);
+}
+int di_on_file(void *self, const char *name)
+{
+  return ((DirIteratorWalk*)self)->on_file(name);
+}
+
+
+struct RM_RF : DirIteratorWalk
+{
+  int on_dir(const BaseString &name)
+  {
+    return _rmdir(name.c_str());
+  }
+  int on_file(const BaseString &name)
+  {
+    return _unlink(name.c_str());
+  }
+};
+
+#define TMP "tmp_dir_iterator"
+TAPTEST(DirIterator)
+{
+  struct _stat statbuf;
+  RM_RF rm_rf;
+  rm_rf.walk(TMP);
+  //deltree_walk(TMP);
+  OK(_stat(TMP,&statbuf)==-1 && errno==ENOENT);
+  OK(0==mkdir(TMP));
+  fclose(fopen(TMP DIR_SEPARATOR "a","w"));
+  OK(!mkdir(TMP DIR_SEPARATOR "d"));
+  OK(!mkdir(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"));
+
+  OK(!rm_rf.walk(TMP));
+  OK(_stat(TMP,&statbuf)==-1 && errno==ENOENT);
+  return 1;
+}
+#endif
\ No newline at end of file


Attachment: [text/bzr-bundle] bzr/jack@sun.com-20090619105658-5pg6uri17ixssb7x.bundle
Thread
bzr commit into mysql-5.1-telco-7.0 branch (jack:2936) Bug#45402jack andrews19 Jun