[Common] Add path getting functions for Virtual Filesystem
authorpius.lee <pius.lee@samsung.com>
Tue, 10 Feb 2015 15:47:46 +0000 (00:47 +0900)
committerPawel Andruszkiewicz <p.andruszkie@samsung.com>
Mon, 30 Mar 2015 07:33:53 +0000 (16:33 +0900)
[Verified] tested with self made test case with every virtual roots

Change-Id: Icacb883cc37b3da34c02f1216a01c0fffcacf1b8
Signed-off-by: pius.lee <pius.lee@samsung.com>
packaging/webapi-plugins.spec
src/common/common.gyp
src/common/virtual_fs.cc [new file with mode: 0644]
src/common/virtual_fs.h [new file with mode: 0644]

index 1bbcb3eeace88594fd93d4f993d52ef87128273d..b0f158811e7eca6b09cebdcacaedb3059afee7bf 100755 (executable)
@@ -177,6 +177,7 @@ BuildRequires: pkgconfig(vconf)
 BuildRequires: pkgconfig(x11)
 BuildRequires: pkgconfig(xrandr)
 BuildRequires: pkgconfig(ecore)
+BuildRequires: pkgconfig(storage)
 BuildRequires: python
 BuildRequires: pkgconfig(capi-base-common)
 BuildRequires: pkgconfig(capi-system-info)
@@ -215,10 +216,6 @@ BuildRequires: pkgconfig(capi-data-control)
 BuildRequires: pkgconfig(capi-web-url-download)
 %endif
 
-%if 0%{?tizen_feature_filesystem_support}
-BuildRequires: pkgconfig(storage)
-%endif
-
 %if 0%{?tizen_feature_power_support}
 BuildRequires: pkgconfig(deviced)
 %endif
index d0e4e0cdd35719ead856bdee7a0f650ad2df9765..5431b0631ce49871fc7fbedd5a74ced4a295d5c5 100644 (file)
@@ -38,7 +38,9 @@
         #'multi_callback_user_data.h',
         'platform_result.cc',
         'platform_result.h',
-        'assert.h'
+        'assert.h',
+        'virtual_fs.cc',
+        'virtual_fs.h',
       ],
       'cflags': [
         '-fvisibility=default',
@@ -49,6 +51,7 @@
             'packages': [
               'capi-appfw-app-manager',
               'capi-appfw-package-manager',
+              'storage',
             ]
           },
           'conditions': [
         'libraries' : [
           '-ltizen_common',
         ],
+        'variables': {
+          'packages': [
+            'storage',
+          ],
+        },
       },
     },
   ],
diff --git a/src/common/virtual_fs.cc b/src/common/virtual_fs.cc
new file mode 100644 (file)
index 0000000..8b0b26c
--- /dev/null
@@ -0,0 +1,310 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "common/virtual_fs.h"
+
+#include <map>
+
+#include <app_manager.h>
+#include <package_manager.h>
+
+#include "common/extension.h"
+#include "common/logger.h"
+#include "common/optional.h"
+#include "common/scope_exit.h"
+
+namespace {
+
+const std::string kVirtualRootCamera = "camera";
+const std::string kVirtualRootDocuments = "documents";
+const std::string kVirtualRootDownloads = "downloads";
+const std::string kVirtualRootImages = "images";
+const std::string kVirtualRootMusic = "music";
+const std::string kVirtualRootRingtones = "ringtones";
+const std::string kVirtualRootVideos = "videos";
+const std::string kVirtualRootWgtPackage = "wgt-package";
+const std::string kVirtualRootWgtPrivate = "wgt-private";
+const std::string kVirtualRootWgtPrivateTmp = "wgt-private-tmp";
+
+const std::string kFileUriPrefix = "file://";
+
+const std::map<storage_directory_e, const std::string*> kStorageDirectories = {
+  {STORAGE_DIRECTORY_CAMERA, &kVirtualRootCamera},
+  {STORAGE_DIRECTORY_DOCUMENTS, &kVirtualRootDocuments},
+  {STORAGE_DIRECTORY_DOWNLOADS, &kVirtualRootDownloads},
+  {STORAGE_DIRECTORY_IMAGES, &kVirtualRootImages},
+  {STORAGE_DIRECTORY_MUSIC, &kVirtualRootMusic},
+  {STORAGE_DIRECTORY_SYSTEM_RINGTONES, &kVirtualRootRingtones},
+  {STORAGE_DIRECTORY_VIDEOS, &kVirtualRootVideos}
+};
+
+std::map<int, common::VirtualStorage> g_storages;
+
+std::map<const std::string, common::VirtualRoot> g_virtual_roots;
+
+void AddVirtualRoot(const std::string& name, const std::string& path) {
+  g_virtual_roots.insert(std::make_pair(name, common::VirtualRoot(name, path)));
+}
+
+void OnStorageStateChanged(int storage_id, storage_state_e state, void *user_data) {
+  const auto it = g_storages.find(storage_id);
+
+  if (it != g_storages.end()) {
+    it->second.state_ = state;
+  } else {
+    LoggerE("Unknown storage: %d", storage_id);
+  }
+}
+
+bool OnStorageDeviceSupported(int storage_id, storage_type_e type,
+                              storage_state_e state, const char *path,
+                              void *user_data) {
+  g_storages.insert(std::make_pair(storage_id, common::VirtualStorage(storage_id, type, state, path)));
+
+  storage_set_state_changed_cb(storage_id, OnStorageStateChanged, nullptr);
+
+  if (STORAGE_TYPE_INTERNAL == type) {
+    // virtual roots are only on internal storage
+    for (const auto& kv : kStorageDirectories) {
+      char* directory = nullptr;
+      storage_directory_e dir = kv.first;
+
+      int err = storage_get_directory(storage_id, dir, &directory);
+
+      if (STORAGE_ERROR_NONE == err  && nullptr != directory) {
+        AddVirtualRoot(*kv.second, directory);
+        free(directory);
+      }
+    }
+  }
+
+  return true;
+}
+
+common::optional<std::string> GetRootDir() {
+  std::string app_id = common::GetCurrentExtension()->GetRuntimeVariable("app_id", 64);
+
+  app_info_h app_info;
+  int err = app_info_create(app_id.c_str(), &app_info);
+  if (APP_MANAGER_ERROR_NONE != err) {
+    LoggerE("Can't create app info handle from appId (%s)", app_id.c_str());
+    return nullptr;
+  }
+  SCOPE_EXIT {
+    app_info_destroy(app_info);
+  };
+
+  char* package = nullptr;
+  err = app_info_get_package(app_info, &package);
+  if (APP_MANAGER_ERROR_NONE != err) {
+    LoggerE("Can't get package name from app info (%s)", get_error_message(err));
+    return nullptr;
+  }
+  SCOPE_EXIT {
+    free(package);
+  };
+
+  package_info_h pkg_info;
+  err = package_info_create(package, &pkg_info);
+  if (PACKAGE_MANAGER_ERROR_NONE != err) {
+    LoggerE("Can't create package info handle from pkg (%s)", get_error_message(err));
+    return nullptr;
+  }
+  SCOPE_EXIT {
+    package_info_destroy(pkg_info);
+  };
+
+  char* root = nullptr;
+  package_info_get_root_path(pkg_info, &root);
+  if (PACKAGE_MANAGER_ERROR_NONE != err) {
+    LoggerE("Can't get root path from package info (%s)", get_error_message(err));
+    return nullptr;
+  }
+
+  return std::string(root);
+}
+
+}  // namespace
+
+namespace common {
+
+std::string to_string(storage_type_e type) {
+  switch (type) {
+    case STORAGE_TYPE_INTERNAL:
+      return "INTERNAL";
+
+    case STORAGE_TYPE_EXTERNAL:
+      return "EXTERNAL";
+
+    default:
+      LoggerE("Unknown storage type: %d", type);
+      return "UNKNOWN";
+  }
+}
+
+std::string to_string(storage_state_e state) {
+  switch (state) {
+    case STORAGE_STATE_UNMOUNTABLE:
+      return "UNMOUNTABLE";
+
+    case STORAGE_STATE_REMOVED:
+      return "REMOVED";
+
+    case STORAGE_STATE_MOUNTED:
+    case STORAGE_STATE_MOUNTED_READ_ONLY:
+      return "MOUNTED";
+
+    default:
+      LoggerE("Unknown storage state: %d", state);
+      return "UNKNOWN";
+  }
+}
+
+VirtualRoot::VirtualRoot(const std::string& name, const std::string& path)
+    : name_(name),
+      path_(path) {
+}
+
+picojson::value VirtualRoot::ToJson() const {
+  picojson::value v{picojson::object{}};
+  picojson::object& obj = v.get<picojson::object>();
+
+  obj["name"] = picojson::value(name_);
+  obj["path"] = picojson::value(path_);
+
+  return v;
+}
+
+VirtualStorage::VirtualStorage(int id, storage_type_e type,
+                               storage_state_e state, const std::string& path)
+    : id_(id),
+      type_(type),
+      state_(state),
+      path_(path) {
+  switch (type_) {
+    case STORAGE_TYPE_INTERNAL:
+      name_ = "internal";
+      break;
+
+    case STORAGE_TYPE_EXTERNAL:
+      name_ = "removable";
+      break;
+
+    default:
+      name_ = "unknown";
+      LoggerE("Unknown storage type: %d", type);
+      break;
+  }
+  name_ += std::to_string(id_);
+}
+
+picojson::value VirtualStorage::ToJson() const {
+  picojson::value v{picojson::object{}};
+  picojson::object& obj = v.get<picojson::object>();
+
+  obj["storage_id"] = picojson::value(static_cast<double>(id_));
+  obj["type"] = picojson::value(to_string(type_));
+  obj["state"] = picojson::value(to_string(state_));
+  obj["path"] = picojson::value(path_);
+  obj["name"] = picojson::value(name_);
+
+  return v;
+}
+
+VirtualFs::VirtualFs() : app_root_(GetRootDir()) {
+  if (app_root_) {
+    AddVirtualRoot(kVirtualRootWgtPackage, *app_root_ + "/res/wgt");
+    AddVirtualRoot(kVirtualRootWgtPrivate, *app_root_ + "/data");
+    AddVirtualRoot(kVirtualRootWgtPrivateTmp, *app_root_ + "/tmp");
+  }
+
+  int err = storage_foreach_device_supported(OnStorageDeviceSupported, nullptr);
+
+  if (err != STORAGE_ERROR_NONE) {
+    LoggerE("Unknown Error on getting storage paths");
+  }
+
+  int id = -1;
+  // add virtual roots to storages
+  for (const auto kw : g_virtual_roots) {
+    const int storage_id = id--;
+    VirtualStorage vs{storage_id, STORAGE_TYPE_INTERNAL, STORAGE_STATE_MOUNTED, kw.second.path_};
+    vs.name_ = kw.second.name_;
+    g_storages.insert(std::make_pair(storage_id, vs));
+  }
+}
+
+VirtualFs::~VirtualFs() {
+  for (const auto kv : g_storages) {
+    storage_unset_state_changed_cb(kv.second.id_, OnStorageStateChanged);
+  }
+}
+
+VirtualFs& VirtualFs::GetInstance() {
+  static VirtualFs vfs;
+  return vfs;
+}
+
+optional<std::string> VirtualFs::GetVirtualRootDirectory(const std::string& name) const {
+  const auto it = g_virtual_roots.find(name);
+  if (it != g_virtual_roots.end()) {
+    return it->second.path_;
+  }
+  return nullptr;
+}
+optional<std::string> VirtualFs::GetApplicationDirectory() const {
+  return app_root_;
+}
+
+std::string VirtualFs::GetRealPath(const std::string& path_or_uri) const {
+  std::string realpath;
+  std::size_t pos = path_or_uri.find(kFileUriPrefix);
+  if (pos != std::string::npos) {
+    realpath = path_or_uri.substr(pos + kFileUriPrefix.size());
+  } else {
+    realpath = path_or_uri;
+  }
+  pos = realpath.find('/');
+  if (pos != 0) {
+    const std::string prefix = realpath.substr(0, pos);
+    const auto it = g_virtual_roots.find(prefix);
+    if (it != g_virtual_roots.end()) {
+      realpath.replace(0, it->second.path_.size(), it->second.path_);
+    } else {
+      LoggerE("Unknown virtual root");
+    }
+  }
+  return realpath;
+}
+
+std::string VirtualFs::GetVirtualPath(const std::string& real_path) const {
+  for (const auto& kv : g_virtual_roots) {
+    if (0 == real_path.compare(0, kv.second.path_.size(), kv.second.path_)) {
+      return std::string(real_path).replace(0, kv.second.path_.size(), kv.first);
+    }
+  }
+  return real_path;
+}
+
+std::vector<VirtualRoot> VirtualFs::GetVirtualRoots() const {
+  std::vector<VirtualRoot> r;
+
+  for (const auto kv : g_virtual_roots) {
+    r.push_back(kv.second);
+  }
+
+  return r;
+}
+
+std::vector<VirtualStorage> VirtualFs::GetStorages() const {
+  std::vector<VirtualStorage> r;
+
+  for (const auto kv : g_storages) {
+    r.push_back(kv.second);
+  }
+
+  return r;
+}
+
+}  // namespace common
diff --git a/src/common/virtual_fs.h b/src/common/virtual_fs.h
new file mode 100644 (file)
index 0000000..da9e21a
--- /dev/null
@@ -0,0 +1,92 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_VIRTUAL_FS_H_
+#define COMMON_VIRTUAL_FS_H_
+
+#include <string>
+#include <vector>
+
+#include <storage.h>
+
+#include "common/optional.h"
+#include "common/picojson.h"
+
+namespace common {
+
+std::string to_string(storage_type_e type);
+std::string to_string(storage_state_e state);
+
+struct VirtualRoot {
+  VirtualRoot(const std::string& name, const std::string& path);
+  picojson::value ToJson() const;
+  std::string name_;
+  std::string path_;
+};
+
+struct VirtualStorage {
+  VirtualStorage(int id, storage_type_e type, storage_state_e state,
+                 const std::string& path = "");
+  picojson::value ToJson() const;
+  int id_;
+  storage_type_e type_;
+  storage_state_e state_;
+  std::string path_;
+  std::string name_;
+};
+
+class VirtualFs {
+ public:
+  /**
+   * Get absolute path of Virtual Roots
+   *
+   * @return absolute path on success
+   */
+  optional<std::string> GetVirtualRootDirectory(const std::string& name) const;
+
+  /**
+   * Get root directory of current application.
+   *
+   * @return absolute path on success
+   */
+  optional<std::string> GetApplicationDirectory() const;
+
+  /**
+   * Get real path (absolute path) from virtual path
+   *
+   * @remark
+   * this function never fail.
+   * if you want virtual path is not exist, check with getVirtualRoot()
+   *
+   * @return real path
+   */
+  std::string GetRealPath(const std::string& path_or_uri) const;
+
+  /**
+   * Get virtual path from real path
+   *
+   * @return virtual path
+   */
+  std::string GetVirtualPath(const std::string& real_path) const;
+
+  std::vector<VirtualRoot> GetVirtualRoots() const;
+
+  std::vector<VirtualStorage> GetStorages() const;
+
+  // TODO: add stat method
+
+  static VirtualFs& GetInstance();
+
+ private:
+  VirtualFs();
+  VirtualFs(const VirtualFs&) = delete;
+  VirtualFs& operator =(const VirtualFs&) = delete;
+  ~VirtualFs();
+
+  optional<std::string> app_root_;
+};
+
+}  // namespace common
+
+#endif  // COMMON_VIRTUAL_FS_H_