#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#45402 | jack andrews | 19 Jun |