From 14decb738730386dce4bcc6928a1d5027b221ddd Mon Sep 17 00:00:00 2001 From: James Turner Date: Sun, 9 Jun 2013 19:17:23 +0100 Subject: [PATCH] simgear::Dir helpers - remove all children of the dir - check is the dir has children / is empty --- simgear/misc/sg_dir.cxx | 89 ++++++++++++++++++++++++++++++++++------- simgear/misc/sg_dir.hxx | 11 +++++ 2 files changed, 85 insertions(+), 15 deletions(-) diff --git a/simgear/misc/sg_dir.cxx b/simgear/misc/sg_dir.cxx index a6711a4c..9a084a6d 100644 --- a/simgear/misc/sg_dir.cxx +++ b/simgear/misc/sg_dir.cxx @@ -256,6 +256,55 @@ PathList Dir::children(int types, const std::string& nameFilter) const return result; } +bool Dir::isEmpty() const +{ + bool empty= true; +#ifdef _WIN32 + WIN32_FIND_DATA fData; + HANDLE find = FindFirstFile("\\*", &fData); + if (find == INVALID_HANDLE_VALUE) { + return true; + } + +// since an empty dir will still have . and .. children, we need +// watch for those - anything else means the dir is really non-empty + bool done = false; + for (; !done; done = (FindNextFile(find, &fData) == 0)) { + if (fData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + if (!strcmp(fData.cFileName,".") || !strcmp(fData.cFileName,"..")) { + continue; + } + } + + empty = false; + break; + } + + FindClose(find); +#else + DIR* dp = opendir(_path.c_str()); + if (!dp) { + return true; + } + + while (true) { + struct dirent* entry = readdir(dp); + if (!entry) { + break; // done iteration + } + + if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) { + continue; + } + + empty = false; + break; + } + closedir(dp); +#endif + return empty; +} + bool Dir::exists() const { return _path.isDir(); @@ -299,28 +348,38 @@ bool Dir::create(mode_t mode) return (err == 0); } +bool Dir::removeChildren() const +{ + bool ok; + PathList cs = children(NO_DOT_OR_DOTDOT | INCLUDE_HIDDEN | TYPE_FILE | TYPE_DIR); + BOOST_FOREACH(SGPath path, cs) { + if (path.isDir()) { + Dir childDir(path); + ok = childDir.remove(true); + } else { + ok = path.remove(); + } + + if (!ok) { + SG_LOG(SG_IO, SG_WARN, "failed to remove:" << path); + return false; + } + } // of child iteration + + return true; +} + bool Dir::remove(bool recursive) { if (!exists()) { - SG_LOG(SG_IO, SG_WARN, "attempt to remove non-existant dir:" << _path.str()); + SG_LOG(SG_IO, SG_WARN, "attempt to remove non-existant dir:" << _path); return false; } if (recursive) { - bool ok; - PathList cs = children(NO_DOT_OR_DOTDOT | INCLUDE_HIDDEN | TYPE_FILE | TYPE_DIR); - BOOST_FOREACH(SGPath path, cs) { - if (path.isDir()) { - Dir childDir(path); - ok = childDir.remove(true); - } else { - ok = path.remove(); - } - - if (!ok) { - return false; - } - } // of child iteration + if (!removeChildren()) { + return false; + } } // of recursive deletion #ifdef _WIN32 diff --git a/simgear/misc/sg_dir.hxx b/simgear/misc/sg_dir.hxx index 109a0d4b..336c2ee1 100644 --- a/simgear/misc/sg_dir.hxx +++ b/simgear/misc/sg_dir.hxx @@ -72,6 +72,11 @@ namespace simgear PathList children(int types = 0, const std::string& nameGlob = "") const; + /** + * test if the directory contains no children (except '.' and '..') + */ + bool isEmpty() const; + SGPath file(const std::string& name) const; SGPath path() const @@ -90,6 +95,12 @@ namespace simgear */ bool remove(bool recursive = false); + /** + * remove our children but not us + */ + bool removeChildren() const; + + /** * Check that the directory at the path exists (and is a directory!) */ -- 2.39.5