summaryrefslogtreecommitdiff
path: root/xwalk/common/virtual_fs.cc
diff options
context:
space:
mode:
Diffstat (limited to 'xwalk/common/virtual_fs.cc')
-rw-r--r--xwalk/common/virtual_fs.cc317
1 files changed, 317 insertions, 0 deletions
diff --git a/xwalk/common/virtual_fs.cc b/xwalk/common/virtual_fs.cc
new file mode 100644
index 00000000..93984a0b
--- /dev/null
+++ b/xwalk/common/virtual_fs.cc
@@ -0,0 +1,317 @@
+// Copyright (c) 2014 Intel Corporation. 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 <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <pkgmgr-info.h>
+#include <tzplatform_config.h>
+
+#include <cassert>
+#include <algorithm>
+#include <sstream>
+#include <string>
+
+#include "common/extension.h"
+
+namespace {
+
+const char kInternalStorage[] = "internal";
+const char kRemovableStorage[] = "removable";
+
+const char kStorageTypeInternal[] = "INTERNAL";
+const char kStorageTypeExternal[] = "EXTERNAL";
+const char kStorageStateMounted[] = "MOUNTED";
+const char kStorageStateRemoved[] = "REMOVED";
+const char kStorageStateUnmountable[] = "UNMOUNTABLE";
+
+} // namespace
+
+namespace vfs_const {
+
+const unsigned kDefaultFileMode = 0755;
+const char kLocationCamera[] = "camera";
+const char kLocationMusic[] = "music";
+const char kLocationImages[] = "images";
+const char kLocationVideos[] = "videos";
+const char kLocationDownloads[] = "downloads";
+const char kLocationDocuments[] = "documents";
+const char kLocationRingtones[] = "ringtones";
+const char kLocationWgtPackage[] = "wgt-package";
+const char kLocationWgtPrivate[] = "wgt-private";
+const char kLocationWgtPrivateTmp[] = "wgt-private-tmp";
+
+} // namespace vfs_const
+
+VirtualFS::VirtualFS() {
+ std::string app_path = GetApplicationPath();
+ if (!app_path.empty()) {
+ AddInternalStorage(vfs_const::kLocationWgtPackage, app_path);
+ AddInternalStorage(vfs_const::kLocationWgtPrivate, JoinPath(app_path, "private"));
+ AddInternalStorage(vfs_const::kLocationWgtPrivateTmp, JoinPath(app_path, "tmp"));
+ }
+
+ AddInternalStorage(vfs_const::kLocationCamera, tzplatform_getenv(TZ_USER_CAMERA));
+ AddInternalStorage(vfs_const::kLocationMusic, tzplatform_getenv(TZ_USER_SOUNDS));
+ AddInternalStorage(vfs_const::kLocationImages, tzplatform_getenv(TZ_USER_IMAGES));
+ AddInternalStorage(vfs_const::kLocationVideos, tzplatform_getenv(TZ_USER_VIDEOS));
+ AddInternalStorage(vfs_const::kLocationDownloads, tzplatform_getenv(TZ_USER_DOWNLOADS));
+ AddInternalStorage(vfs_const::kLocationDocuments, tzplatform_getenv(TZ_USER_DOCUMENTS));
+ AddInternalStorage(vfs_const::kLocationRingtones,
+ tzplatform_mkpath(TZ_USER_SHARE, "settings/Ringtones"));
+ storage_changed_cb_ = NULL;
+ cb_user_data_ = NULL;
+}
+
+VirtualFS::~VirtualFS() {
+}
+
+std::string VirtualFS::JoinPath(const std::string& one,
+ const std::string& another) {
+ return one + '/' + another;
+}
+
+bool VirtualFS::MakePath(const std::string& path, int mode) {
+ // Path should start with '/' and contain at least 1 character after '/'.
+ if (path.empty() || path[0] != '/' || path.length() < 2)
+ return false;
+
+ struct stat st;
+ std::string dir = path;
+ if (stat(dir.c_str(), &st) == 0)
+ return true;
+
+ // Add trailing '/' if missing, so we can iterate till the end of the path.
+ if (dir[dir.size() - 1] != '/')
+ dir += '/';
+
+ for (std::string::iterator iter = dir.begin(); iter != dir.end();) {
+ std::string::iterator cur_iter = std::find(iter, dir.end(), '/');
+
+ // If '/' is found at the beginning of the string, iterate to the next '/'.
+ if (cur_iter == iter) {
+ ++iter;
+ cur_iter = std::find(iter, dir.end(), '/');
+ }
+
+ std::string new_path = std::string(dir.begin(), cur_iter);
+
+ // If path doesn't exist, try to create one and continue iteration.
+ // In case of error, stop iteration and return.
+ if (stat(new_path.c_str(), &st) != 0) {
+ if (mkdir(new_path.c_str(), mode) != 0 && errno != EEXIST )
+ return false;
+ // If path exists and it is not a directory, stop iteration and return.
+ } else if (!S_ISDIR(st.st_mode)) {
+ return false;
+ }
+
+ // Advance iterator and create next parent folder.
+ iter = cur_iter;
+ if (cur_iter != dir.end())
+ ++iter;
+ }
+ return true;
+}
+
+int VirtualFS::GetDirEntryCount(const char* path) {
+ int count = 0;
+ DIR* dir = opendir(path);
+ if (!dir)
+ return count;
+
+ struct dirent entry;
+ struct dirent *result;
+ int ret = readdir_r(dir, &entry, &result);
+
+ for (; ret == 0 && result != NULL; ret = readdir_r(dir, &entry, &result)) {
+ if (entry.d_type == DT_REG || entry.d_type == DT_DIR)
+ count++;
+ }
+
+ closedir(dir);
+ return count;
+}
+
+std::string VirtualFS::GetAppId(const std::string& package_id) {
+ char* appid = NULL;
+ pkgmgrinfo_pkginfo_h pkginfo_handle;
+ int ret = pkgmgrinfo_pkginfo_get_pkginfo(package_id.c_str(), &pkginfo_handle);
+ if (ret != PMINFO_R_OK)
+ return std::string();
+ ret = pkgmgrinfo_pkginfo_get_mainappid(pkginfo_handle, &appid);
+ if (ret != PMINFO_R_OK) {
+ pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_handle);
+ return std::string();
+ }
+
+ std::string retval(appid);
+ pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_handle);
+ return retval;
+}
+
+std::string VirtualFS::GetExecPath(const std::string& app_id) {
+ char* exec_path = NULL;
+ pkgmgrinfo_appinfo_h appinfo_handle;
+ int ret = pkgmgrinfo_appinfo_get_appinfo(app_id.c_str(), &appinfo_handle);
+ if (ret != PMINFO_R_OK)
+ return std::string();
+ ret = pkgmgrinfo_appinfo_get_exec(appinfo_handle, &exec_path);
+ if (ret != PMINFO_R_OK) {
+ pkgmgrinfo_appinfo_destroy_appinfo(appinfo_handle);
+ return std::string();
+ }
+
+ std::string retval(exec_path);
+ pkgmgrinfo_appinfo_destroy_appinfo(appinfo_handle);
+ return retval;
+}
+
+bool VirtualFS::GetStorageByLabel(const std::string& label, Storage& storage) {
+ storage_foreach_device_supported(OnStorageDeviceSupported, this);
+ Storages::const_iterator it = storages_.find(label);
+
+ if (it == storages_.end()) {
+ return false;
+ }
+ storage = it->second;
+ return true;
+}
+
+Storages::iterator VirtualFS::begin() {
+ storage_foreach_device_supported(OnStorageDeviceSupported, this);
+ return storages_.begin();
+}
+
+Storages::const_iterator VirtualFS::end() const {
+ return storages_.end();
+}
+
+std::string VirtualFS::GetApplicationPath() {
+ std::string id_str = common::Extension::GetRuntimeVariable("app_id", 64);
+ std::string pkg_id = id_str.substr(1, id_str.rfind('"') - 1);
+ if (pkg_id.empty())
+ return std::string();
+ std::string app_id = GetAppId(pkg_id);
+ if (app_id.empty())
+ return std::string();
+ std::string exec_path = GetExecPath(app_id);
+ if (exec_path.empty())
+ return std::string();
+
+ size_t index = exec_path.find(pkg_id);
+ if (index != std::string::npos)
+ return exec_path.substr(0, index + pkg_id.length());
+ return std::string();
+}
+
+std::string VirtualFS::GetRealPath(const std::string& fullPath) const {
+ std::size_t pos = fullPath.find_first_of('/');
+ Storages::const_iterator it = storages_.find(fullPath.substr(0, pos));
+
+ if (it == storages_.end())
+ return std::string();
+
+ if (pos != std::string::npos)
+ return it->second.GetFullPath() + fullPath.substr(pos);
+
+ return it->second.GetFullPath();
+}
+
+void VirtualFS::AddInternalStorage(
+ const std::string& label, const std::string& path) {
+ if (MakePath(path, vfs_const::kDefaultFileMode))
+ storages_.insert(StorageLabelPair(label,
+ Storage(-1,
+ Storage::STORAGE_TYPE_INTERNAL,
+ Storage::STORAGE_STATE_MOUNTED,
+ path)));
+}
+
+void VirtualFS::AddStorage(int id,
+ storage_type_e type,
+ storage_state_e state,
+ const std::string& path) {
+ std::string label;
+ if (type == STORAGE_TYPE_INTERNAL)
+ label = kInternalStorage + std::to_string(id);
+ else if (type == STORAGE_TYPE_EXTERNAL)
+ label = kRemovableStorage + std::to_string(id);
+
+ storages_.insert(StorageLabelPair(label,
+ Storage(id,
+ type,
+ state,
+ path)));
+ if (std::find(watched_storages_.begin(),
+ watched_storages_.end(), id) != watched_storages_.end()) {
+ watched_storages_.push_back(id);
+ storage_set_state_changed_cb(id, OnStorageStateChanged, this);
+ }
+}
+
+void VirtualFS::SetOnStorageChangedCb(CallBackFunctionPtr cb, void* user_data) {
+ storage_changed_cb_ = cb;
+ cb_user_data_ = user_data;
+}
+
+void VirtualFS::NotifyStorageStateChanged(int id, storage_state_e state) {
+ for (Storages::iterator it = storages_.begin(); it != storages_.end(); ++it) {
+ if (it->second.GetId() == id) {
+ it->second.SetState(state);
+ if (storage_changed_cb_) {
+ storage_changed_cb_(it->first, it->second, cb_user_data_);
+ }
+ break;
+ }
+ }
+}
+
+bool VirtualFS::OnStorageDeviceSupported(
+ int id, storage_type_e type, storage_state_e state,
+ const char* path, void* user_data) {
+ reinterpret_cast<VirtualFS*>(user_data)->AddStorage(
+ id, type, state, path);
+ return true;
+}
+
+void VirtualFS::OnStorageStateChanged(
+ int id, storage_state_e state, void* user_data) {
+ reinterpret_cast<VirtualFS*>(user_data)->NotifyStorageStateChanged(
+ id, state);
+}
+
+/*
+ * Storage Class
+ */
+
+Storage::Storage(
+ int id, int type, int state, const std::string& fullpath)
+ : id_(id),
+ type_(type),
+ state_(state),
+ full_path_(fullpath) { }
+
+std::string Storage::GetType() const {
+ return (type_ == Storage::STORAGE_TYPE_INTERNAL) ? kStorageTypeInternal :
+ kStorageTypeExternal;
+}
+
+std::string Storage::GetState() const {
+ switch (state_) {
+ case Storage::STORAGE_STATE_MOUNTED:
+ case Storage::STORAGE_STATE_MOUNTED_READONLY:
+ return kStorageStateMounted;
+ case Storage::STORAGE_STATE_REMOVED:
+ return kStorageStateRemoved;
+ case Storage::STORAGE_STATE_UNMOUNTABLE:
+ return kStorageStateUnmountable;
+ default:
+ assert(!"Not reached");
+ }
+ return std::string();
+}