Fixes for recursive opendir
authorJanusz Majnert <j.majnert@samsung.com>
Wed, 24 Oct 2012 10:56:11 +0000 (12:56 +0200)
committerTaejeong Lee <taejeong.lee@samsung.com>
Fri, 2 Nov 2012 07:10:36 +0000 (16:10 +0900)
[Issue#] N/A
[Feature] Replacing recursive opendir with safe fts_ functions
[Cause] Recursive opendir may reach limit of open dirs for process
[Solution] Replace with standard fts_* functions for traversing directories
[Verification] Install an encrypted widget and verify that encryption works

Major rewrite to resource encryption functions was done - verify by installing
an encrypted widget and checking that eligible resources are really encrypted.
Minor fixes added, mainly to close directories that are no longer used.

Change-Id: I51e36f225d49cd46b5454c0cf7cbda09d9e7c1c1

src/jobs/widget_install/task_encrypt_resource.cpp
src/jobs/widget_install/task_manifest_file.cpp
src/jobs/widget_install/task_plugins_copy.cpp
src/jobs/widget_install/task_update_files.cpp
src/jobs/widget_install/task_widget_config.cpp [changed mode: 0755->0644]
src/wrt-installer/wrt_installer.cpp
src/wrt-installer/wrt_installer_api.cpp

index 77172eb..dcec387 100644 (file)
@@ -24,7 +24,7 @@
 #include <unistd.h>
 #include <string>
 #include <sys/stat.h>
-#include <dirent.h>
+#include <fts.h>
 
 #include <dpl/log/log.h>
 #include <dpl/errno_string.h>
@@ -50,7 +50,7 @@ std::set<std::string>& getSupportedForEncryption()
     return encryptSet;
 }
 
-bool isSupportedForEncryption(std::string file)
+bool isSupportedForEncryption(const std::string &file)
 {
     size_t foundKey = file.rfind(".");
     if (std::string::npos != foundKey) {
@@ -82,39 +82,54 @@ void TaskEncryptResource::StepEncryptResource()
 
 void TaskEncryptResource::EncryptDirectory(std::string path)
 {
-    DIR* pkgDir = opendir(path.c_str());
-    if (!pkgDir) {
-        LogDebug("Package directory doesn't exist");
-        ThrowMsg(Exceptions::InternalError, "Error occurs during read \
-                directory");
+    FTS *fts;
+    FTSENT *ftsent;
+    char * const paths[] = {const_cast<char * const>(path.c_str()), NULL};
+
+    if ((fts = fts_open(paths, FTS_PHYSICAL|FTS_NOCHDIR, NULL)) == NULL) {
+        //ERROR
+        int error = errno;
+        LogWarning(__PRETTY_FUNCTION__ << ": fts_open failed with error: "
+                << strerror(error));
+        ThrowMsg(Exceptions::InternalError, "Error reading directory: "
+                << path);
     }
 
-    struct dirent* dirent;
-    struct stat statInfo;
-    do {
-        if ((dirent = readdir(pkgDir))) {
-            std::string dirName = dirent->d_name;
-            std::string absFileName = path + "/" + dirName;
-            if (stat(absFileName.c_str(), &statInfo) != 0) {
-                ThrowMsg(Exceptions::InternalError, "Error occurs read file");
-            }
-
-            if (S_ISDIR(statInfo.st_mode)) {
-                if(strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name,
-                            "..") == 0) {
-                    continue;
-                }
-                EncryptDirectory(absFileName);
-            } else {
-                if (isSupportedForEncryption(absFileName)) {
-                    EncryptFile(absFileName);
+    while ((ftsent = fts_read(fts)) != NULL) {
+        switch (ftsent->fts_info) {
+            case FTS_DP:
+            case FTS_DC:
+            case FTS_D:
+            case FTS_DEFAULT:
+            case FTS_SLNONE:
+                //directories, non-regular files, dangling symbolic links
+                break;
+            case FTS_F:
+            case FTS_NSOK:
+            case FTS_SL:
+                //regular files and other objects that can be counted
+                if (isSupportedForEncryption(ftsent->fts_path)) {
+                    EncryptFile(ftsent->fts_path);
                 }
-            }
+                break;
+            case FTS_NS:
+            case FTS_DOT:
+            case FTS_DNR:
+            case FTS_ERR:
+            default:
+                LogWarning(__PRETTY_FUNCTION__
+                        << ": traversal failed on file: "
+                        << ftsent->fts_path
+                        << " with error: "
+                        << strerror(ftsent->fts_errno));
+                ThrowMsg(Exceptions::InternalError, "Error reading file");
         }
     }
-    while(dirent);
-    if (closedir(pkgDir)) {
-        LogError("Fail to close directory : " << path);
+
+    if (fts_close(fts) == -1) {
+        int error = errno;
+        LogWarning(__PRETTY_FUNCTION__ << ": fts_close failed with error: "
+                << strerror(error));
     }
 }
 
index edd18f1..7951e2e 100644 (file)
@@ -35,6 +35,7 @@
 #include <dpl/wrt-dao-ro/global_config.h>
 #include <dpl/log/log.h>
 #include <dpl/file_input.h>
+#include <dpl/errno_string.h>
 #include <dpl/file_output.h>
 #include <dpl/copy.h>
 #include <dpl/exception.h>
@@ -450,6 +451,10 @@ void TaskManifestFile::getFileList(const char* path,
             list.push_back(file_name);
         }
     }while(d_ent);
+    if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
+        LogError("Failed to close dir: " << path << " with error: "
+                << DPL::GetErrnoString());
+    }
 }
 
 void TaskManifestFile::stepGenerateManifest()
index 7860797..a0fbecc 100644 (file)
@@ -24,6 +24,7 @@
 #include <dpl/log/log.h>
 #include <dpl/string.h>
 #include <dpl/utils/wrt_utility.h>
+#include <dpl/errno_string.h>
 #include <widget_install_context.h>
 #include <widget_install/widget_install_errors.h>
 #include <dpl/exception.h>
@@ -95,15 +96,21 @@ void TaskPluginsCopy::StepFindPlugins()
     while ((entry = readdir(dir)) != NULL){
         tempname = m_npsource + "/" + entry->d_name;
         if(lstat(tempname.c_str(), &st) != 0) {
-            LogDebug("Failed to call \"lstat\" (errno:" <<errno <<") on entry - skipping");
+            LogDebug("Failed to call \"lstat\" (errno:" <<errno
+                    <<") on entry - skipping");
             continue;
         }
         /* Directories other than "." and ".." should not be found*/
         if(S_ISDIR(st.st_mode)){
-            if(strncmp(entry->d_name, "..", 2)!=0 && strncmp(entry->d_name, ".", 1)!=0) {
-                LogError("Directory detected instead of plugin file: " << entry->d_name);
+            if(strncmp(entry->d_name, "..", 2)!=0
+                        && strncmp(entry->d_name, ".", 1)!=0) {
+                LogError("Directory detected instead of plugin file: "
+                        << entry->d_name);
                 /* Subdirectories inside plugins/ARCH are not supported */
-                closedir(dir);
+                if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
+                    LogError("Failed to close dir: " << m_npsource
+                            << " with error: " << DPL::GetErrnoString());
+                }
                 ThrowMsg(Exceptions::PluginsSubdirectory,
                         "Subdirectories inside plugins directory are not supported");
             }
@@ -124,7 +131,10 @@ void TaskPluginsCopy::StepFindPlugins()
             LogWarning("Non-plugin file found: " <<tempname);
         }
     }
-    closedir(dir);
+    if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
+        LogError("Failed to close dir: " << m_npsource << " with error: "
+                << DPL::GetErrnoString());
+    }
     /* If no .so files found (list is empty) abort taks*/
     if(m_nplugins.empty()) {
         LogError("No valid plugin files found");
index b13ab39..0ba0a07 100644 (file)
@@ -39,8 +39,8 @@
 
 #include <dpl/wrt-dao-rw/widget_dao.h>
 #include <dpl/wrt-dao-ro/global_config.h>
-#include <dpl/utils/wrt_utility.h>
 #include <dpl/exception.h>
+#include <dpl/errno_string.h>
 
 using namespace WrtDB;
 
@@ -125,6 +125,11 @@ void TaskUpdateFiles::ReadDirList(std::string dirPath, ExistFileList &list,
         }
     }
     while(dirent);
+    //closing the directory
+    if (-1 == TEMP_FAILURE_RETRY(closedir(pkgDir))) {
+        LogError("Failed to close dir: " << dirPath << " with error: "
+                << DPL::GetErrnoString());
+    }
 }
 
 void TaskUpdateFiles::StepResourceFilesBackup()
old mode 100755 (executable)
new mode 100644 (file)
index f7c9c9f..dc0d3f9
@@ -164,8 +164,9 @@ void TaskWidgetConfig::ReadLocaleFolders()
         LogError("readdir() failed with " << DPL::GetErrnoString());
     }
 
-    if (closedir(localeDir)) {
-        LogError("closedir() failed with " << DPL::GetErrnoString());
+    if (-1 == TEMP_FAILURE_RETRY(closedir(localeDir))) {
+        LogError("Failed to close dir: " << localePath << " with error: "
+                << DPL::GetErrnoString());
     }
 }
 
@@ -715,7 +716,10 @@ bool TaskWidgetConfig::parseConfigurationFileWidget(WrtDB::ConfigParserData& con
                     LogDebug("Invalid widget configuration file!");
                     //                    _rethrown_exception.Dump();
                     *pErrCode = WRT_WM_ERR_INVALID_ARCHIVE;
-                    closedir(dir);
+                    if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
+                        LogError("Failed to close dir: " << _currentPath << " with error: "
+                                << DPL::GetErrnoString());
+                    }
                     return false;
                 }
 
@@ -724,7 +728,10 @@ bool TaskWidgetConfig::parseConfigurationFileWidget(WrtDB::ConfigParserData& con
             }
         }
     }
-    closedir(dir);
+    if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
+        LogError("Failed to close dir: " << _currentPath << " with error: "
+                << DPL::GetErrnoString());
+    }
 
     //We must have config.xml so leaveing if we doesn't
     if (!has_config_xml) {
index b02a2dc..11dcb57 100644 (file)
@@ -43,6 +43,7 @@
 #include <dpl/zip_input.h>
 #include <dpl/binary_queue.h>
 #include <dpl/copy.h>
+#include <dpl/errno_string.h>
 #include <dpl/utils/wrt_global_settings.h>
 #include "option_parser.h"
 #include <parser_runner.h>
@@ -416,7 +417,8 @@ void WrtInstaller::installPluginsStep()
         ::PostEvent(WRTInstallerNS::InstallPluginEvent());
 
     if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
-        LogError("Failed to close dir: " << dir);
+        LogError("Failed to close dir: " << PLUGIN_PATH << " with error: "
+                << DPL::GetErrnoString());
     }
 }
 
index 9921fdf..2a3d48c 100755 (executable)
@@ -30,6 +30,7 @@
 #include <dpl/assert.h>
 #include <dpl/semaphore.h>
 #include <dpl/sstream.h>
+#include <dpl/errno_string.h>
 #include <libxml/parser.h>
 #include <vconf.h>
 
@@ -486,7 +487,8 @@ extern "C"
             }
 
             if (-1 == TEMP_FAILURE_RETRY(closedir(dir))) {
-                LogError("Failed to close dir: " << dir);
+                LogError("Failed to close dir: " << PLUGIN_PATH << " with error: "
+                        << DPL::GetErrnoString());
             }
 
             if (0 != unlink(installRequest.c_str())) {