List:Commits« Previous MessageNext Message »
From:jack andrews Date:June 25 2009 6:44pm
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-25
      Bug #45402   Win32AsyncFile::rmrfReq can run an infinite loop
        . supporting code with test
        . test code 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
      storage/ndb/src/common/util/Makefile.am
=== 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-25 18:40:13 +0000
@@ -0,0 +1,102 @@
+/* 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&){return *this;}
+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;
+  virtual ~DirIteratorWalk(){}
+  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-25 18:40:13 +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-25 18:40:13 +0000
@@ -0,0 +1,305 @@
+/* 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>
+#else
+#include <dirent.h>
+#endif
+#include <sys/stat.h>
+
+struct di {
+  char *path;
+#ifdef _WIN32
+  char *pat;
+  struct _finddata_t finddata;
+  intptr_t handle;
+  int first, end;
+#else
+  DIR *dir;
+#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;
+}
+
+#ifdef _WIN32
+#define stat _stat 
+#define S_IFDIR _S_IFDIR
+#endif
+
+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;
+  memset(d,0,sizeof(struct 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;
+  }
+  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;
+#ifdef _WIN32
+  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;
+  d->handle = -1;
+#else
+  d->dir = opendir(path);
+  if(!d->dir)
+    return CHECKERRNO;
+#endif
+  return 0;
+}
+
+int di_close(DI *pdi)
+{
+  DI di=*pdi;
+#ifdef _WIN32
+  if (di->handle != -1) {
+    _findclose(di->handle);
+    di->handle = -1;
+  }
+#else
+  if (di->dir) {
+    closedir(di->dir);
+    di->dir = 0;
+  }
+#endif
+  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;
+  while ((ent = readdir(di->dir)))
+  { char *s=ent->d_name,*pathname;
+    int mode=0,size;
+    if(!strcmp(s,".") || !strcmp(s,".."))
+      continue;
+    pathname = (char*)malloc(strlen(s)+strlen(di->path)+4);
+    sprintf(pathname,"%s/%s",di->path,s);
+    if (stat(pathname, &statbuf) == -1) {
+      free(pathname);
+      return CHECKERRNO;
+    }
+    free(pathname);
+    mode = statbuf.st_mode;
+    fi->name = s;
+    fi->type = S_ISDIR(mode)?ISDIR:ISFILE;
+    return 0;
+  }
+  (void)closedir(di->dir);
+  di->dir = 0;
+#endif
+  return NOMORE;
+}
+
+typedef Vector<BaseString>  BSS;
+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());
+    assert(rv != NOTADIR && rv != CHECKERRNO);
+    if (rv == DIREMPTY) {
+      assert(!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) {  
+        assert(!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);
+}
+
+
+#ifdef TAP_TEST
+#include <NdbTap.hpp>
+#include <sys/types.h> 
+#include <sys/stat.h>
+#ifdef _WIN32
+#define unlink _unlink
+#define rmdir _rmdir
+#endif
+
+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;
+}
+
+struct RM_RF : DirIteratorWalk
+{
+  int on_dir(const BaseString &name)
+  {
+    int rv = rmdir(name.c_str());
+    if (rv)
+      perror("rmdir: ");
+    return rv;
+  }
+  int on_file(const BaseString &name)
+  {
+    int rv = unlink(name.c_str());
+    if (rv)
+      perror("unlink: ");
+    return rv;
+  }
+};
+
+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;
+  RM_RF rm_rf;
+  rm_rf.walk(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"));
+
+  OK(!rm_rf.walk(TMP));
+  OK(stat(TMP,&statbuf)==-1 && errno==ENOENT);
+  return 1;
+}
+#endif
+

=== modified file 'storage/ndb/src/common/util/Makefile.am'
--- a/storage/ndb/src/common/util/Makefile.am	2009-06-03 16:04:23 +0000
+++ b/storage/ndb/src/common/util/Makefile.am	2009-06-25 18:40:13 +0000
@@ -29,14 +29,20 @@ libgeneral_la_SOURCES = \
             ConfigValues.cpp ndb_init.cpp basestring_vsnprintf.c \
             Bitmask.cpp \
 	    ndb_rand.c \
-	    ndbinfo.c
+	    ndbinfo.c DirIterator.cpp
 
 INCLUDES_LOC = @ZLIB_INCLUDES@
 
 libndbazio_la_SOURCES = azio.c
 libndbazio_la_LIBADD = @ZLIB_LIBS@
 
-noinst_PROGRAMS = BaseString-t HashMap-t Bitmask-t
+noinst_PROGRAMS = BaseString-t HashMap-t Bitmask-t DirIterator-t
+
+DirIterator_t_SOURCES = DirIterator.cpp
+DirIterator_t_CXXFLAGS = -DTAP_TEST
+DirIterator_t_LDADD = \
+	libgeneral.la \
+	$(top_builddir)/mysys/libmysyslt.la
 
 BaseString_t_SOURCES = BaseString.cpp
 BaseString_t_CXXFLAGS = -DTEST_BASE_STRING


Attachment: [text/bzr-bundle] bzr/jack@sun.com-20090625184013-0hvr1oqxggfcxt85.bundle
Thread
bzr commit into mysql-5.1-telco-7.0 branch (jack:2936) Bug#45402jack andrews25 Jun