Use custom resolvePath() instead of ::realpath() 91/73391/1
authorKyungwook Tak <k.tak@samsung.com>
Wed, 8 Jun 2016 04:25:07 +0000 (13:25 +0900)
committerKyungwook Tak <k.tak@samsung.com>
Wed, 8 Jun 2016 04:25:07 +0000 (13:25 +0900)
::realpath() expands all symbolic links. When getting scannable file, we
have to focus on symbolic link itself because we cannot remove every
symbolic links when it comes to the regular file in scannable list even
though symbolic link path is in parameter.

Change-Id: If0d69419d9103a6ecff9ea56afdaa21b7e03613f
Signed-off-by: Kyungwook Tak <k.tak@samsung.com>
src/framework/service/cs-logic.cpp

index dea0a56..de1b45a 100644 (file)
@@ -52,6 +52,60 @@ void setCoreUsage(const csr_cs_core_usage_e &cu)
        }
 }
 
+// resolve all of "/." and "/.." in absolute path (which starts with '/')
+std::string resolvePath(const std::string &_path)
+{
+       auto path = _path;
+
+       while (path.back() == '/')
+               path.pop_back();
+
+       size_t from = 0;
+       size_t to = 0;
+
+       while (true) {
+               if (path.empty()) {
+                       path = "/";
+                       break;
+               }
+
+               auto len = path.length();
+
+               if (from >= len)
+                       break;
+
+               while (len > from + 1 && path[from + 1] == '/') {
+                       path.erase(from, 1);
+                       --len;
+               }
+
+               to = path.find_first_of('/', from + 1);
+
+               if (to == std::string::npos)
+                       to = len;
+
+               auto substr = path.substr(from, to - from);
+
+               if (substr == "/.") {
+                       path.erase(from, 2);
+               } else if (substr == "/..") {
+                       path.erase(from, 3);
+
+                       if (from == 0)
+                               continue;
+
+                       auto parent = path.find_last_of('/', from - 1);
+                       path.erase(parent, from - parent);
+
+                       from = parent;
+               } else {
+                       from = to;
+               }
+       }
+
+       return path;
+}
+
 } // namespace anonymous
 
 CsLogic::CsLogic(const std::shared_ptr<CsLoader> &loader,
@@ -467,10 +521,10 @@ RawBuffer CsLogic::canonicalizePaths(const StrSet &paths)
        StrSet canonicalized;
 
        for (const auto &path : paths) {
-               auto target = File::getPkgPath(path);
-               auto resolved = ::realpath(target.c_str(), nullptr);
+               auto resolved = resolvePath(path);
+               auto target = File::getPkgPath(resolved);
 
-               if (resolved == nullptr) {
+               if (::access(target.c_str(), R_OK) != 0) {
                        const int err = errno;
                        if (err == ENOENT)
                                ThrowExc(CSR_ERROR_FILE_DO_NOT_EXIST, "File do not exist: " << target);
@@ -482,12 +536,9 @@ RawBuffer CsLogic::canonicalizePaths(const StrSet &paths)
                                                 " with errno: " << err);
                }
 
-               std::string resolvedStr(resolved);
-               free(resolved);
-
-               if (canonicalized.find(resolvedStr) == canonicalized.end()) {
-                       INFO("Insert to canonicalized list: " << resolvedStr);
-                       canonicalized.emplace(std::move(resolvedStr));
+               if (canonicalized.find(target) == canonicalized.end()) {
+                       INFO("Insert to canonicalized list: " << target);
+                       canonicalized.emplace(std::move(target));
                }
        }