Tizen 2.1 base
[platform/framework/web/wrt-plugins-common.git] / src / modules / tizen / Filesystem / Node.cpp
index 527fa85..582fcba 100755 (executable)
@@ -20,6 +20,7 @@
 #include <sys/types.h>
 #include <cstdio>
 #include <unistd.h>
+#include <fts.h>
 #include <dirent.h>
 #include <errno.h>
 #include <pcrecpp.h>
@@ -144,6 +145,7 @@ NodeList Node::getChildNodes(const NodeFilterPtr& filter) const
             continue;
         }
         Try {
+            Assert(m_path);
             INodePtr node = Node::resolve(*m_path + entry->d_name);
             node->setPermissions(getPermissions()); // inherit access rights
             if (NodeFilterMatcher::match(node, filter)) {
@@ -184,6 +186,8 @@ INodePtr Node::createChild(
         ThrowMsg(Commons::SecurityException, "Not enough permissions.");
     }
 
+    Assert(m_path);
+    Assert(path);
     IPathPtr childPath = *m_path + *path;
     if (exists(childPath)) {
         ThrowMsg(Commons::PlatformException, "Node already exists.");
@@ -279,6 +283,8 @@ INodePtr Node::getParent() const
 {
     LocationPaths roots = IManager::getInstance().getLocationPaths();
     for (LocationPaths::iterator it = roots.begin(); it != roots.end(); ++it) {
+        Assert(*it);
+        Assert(m_path);
         if (*(*it) == *m_path) {
             return INodePtr();
         }
@@ -413,46 +419,78 @@ void Node::removeAsFile(const IPathPtr& path)
 void Node::removeAsDirectory(const IPathPtr& path,
                              bool recursive)
 {
+    Assert(path);
     if (recursive) {
-        DIR* dir = opendir(path->getFullPath().c_str());
-        if (!dir) {
-            LogError("File: " << path->getFullPath().c_str());
-            ThrowMsg(Commons::PlatformException,
-                     "Node does not exist or access denied.");
+        FTS *fts;
+        FTSENT *ftsent;
+        int error = 0;
+        std::string pth=path->getFullPath();
+        char * const paths[] = {const_cast<char * const>(pth.c_str()), NULL};
+
+        if ((fts = fts_open(paths, FTS_PHYSICAL|FTS_NOCHDIR, NULL)) == NULL) {
+            //ERROR
+            error = errno;
+            LogError(__PRETTY_FUNCTION__ << ": fts_open on "
+                    << pth
+                    << " failed with error: "
+                    << strerror(error));
+            ThrowMsg(Commons::PlatformException, "Failed to traverse Node");
         }
-        errno = 0;
-        struct dirent *entry = NULL;
-        while ((entry = readdir(dir))) {
-            if (!strncmp(entry->d_name, ".",
-                         1) || !strncmp(entry->d_name, "..", 2)) {
-                continue;
-            }
-            IPathPtr subPath = *path + entry->d_name;
-            struct stat info;
-            memset(&info, 0, sizeof(struct stat));
-            if (lstat(subPath->getFullPath().c_str(), &info) == 0) {
-                Try {
-                    if (S_ISDIR(info.st_mode)) {
-                        removeAsDirectory(subPath, true);
-                    } else if (S_ISREG(info.st_mode)) {
-                        removeAsFile(subPath);
+
+        while ((ftsent = fts_read(fts)) != NULL) {
+            switch (ftsent->fts_info) {
+                case FTS_D:
+                    //directory in preorder - do nothing
+                    break;
+                case FTS_DP:
+                    //directory in postorder - remove
+                    errno = 0;
+                    if (rmdir(ftsent->fts_accpath) != 0) {
+                        if (errno == EEXIST) {
+                            ThrowMsg(Commons::PlatformException,
+                                    "Node has child nodes.");
+                        }
+                        ThrowMsg(Commons::PlatformException,
+                                "Error while removing platform node.");
                     }
-                }
-                Catch(Commons::PlatformException) {
-                }
-                // TODO: Not sure if above exception should be swallowed.
+                    break;
+                case FTS_DC:
+                case FTS_F:
+                case FTS_NSOK:
+                case FTS_SL:
+                case FTS_SLNONE:
+                case FTS_DEFAULT:
+                    {
+                        //regular files and other objects that can safely be removed
+                        IPathPtr file_path = IPath::create(ftsent->fts_path);
+                        removeAsFile(file_path);
+                        break;
+                    }
+                case FTS_NS:
+                case FTS_DOT:
+                case FTS_DNR:
+                case FTS_ERR:
+                default:
+                    LogWarning(__PRETTY_FUNCTION__
+                            << ": traversal failed with error: "
+                            << strerror(ftsent->fts_errno));
+                    break;
             }
         }
-        closedir(dir);
-    }
 
-    errno = 0;
-    if (rmdir(path->getFullPath().c_str()) != 0) {
-        if (errno == EEXIST) {
-            ThrowMsg(Commons::PlatformException, "Node has child nodes.");
+        if (fts_close(fts) == -1) {
+            error = errno;
+            LogWarning(__PRETTY_FUNCTION__ << ": fts_close failed with error: "
+                    << strerror(error));
+        }
+    } else {
+        if (rmdir(path->getFullPath().c_str()) != 0) {
+            if (errno == EEXIST) {
+                ThrowMsg(Commons::PlatformException, "Node has child nodes.");
+            }
+            ThrowMsg(Commons::PlatformException,
+                    "Error while removing platform node.");
         }
-        ThrowMsg(Commons::PlatformException,
-                 "Error while removing platform node.");
     }
 }