--- /dev/null
+// 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();
+}
--- /dev/null
+// 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.
+
+#ifndef COMMON_VIRTUAL_FS_H_
+#define COMMON_VIRTUAL_FS_H_
+
+#include <appfw/app_storage.h>
+
+#include <map>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace vfs_const {
+
+extern const unsigned kDefaultFileMode;
+extern const char kLocationCamera[];
+extern const char kLocationMusic[];
+extern const char kLocationImages[];
+extern const char kLocationVideos[];
+extern const char kLocationDownloads[];
+extern const char kLocationDocuments[];
+extern const char kLocationRingtones[];
+extern const char kLocationWgtPackage[];
+extern const char kLocationWgtPrivate[];
+extern const char kLocationWgtPrivateTmp[];
+
+} // namespace vfs_const
+
+class Storage {
+ public:
+ /* Mapped to storage_type_e */
+ enum StorageType {
+ STORAGE_TYPE_INTERNAL, STORAGE_TYPE_EXTERNAL,
+ };
+
+ /* Mapped to storage_state_e */
+ enum StorageState {
+ STORAGE_STATE_UNMOUNTABLE = -2,
+ STORAGE_STATE_REMOVED = -1,
+ STORAGE_STATE_MOUNTED = 0,
+ STORAGE_STATE_MOUNTED_READONLY = 1,
+ };
+
+ Storage(int id = 0, int type = 0, int state = 0,
+ const std::string& fullpath = "");
+
+ std::string GetType() const;
+ std::string GetState() const;
+ int GetId() const { return id_; }
+ const std::string& GetFullPath() const { return full_path_; }
+ void SetState(int state) { state_ = state; }
+
+ private:
+ int id_;
+ int type_;
+ int state_;
+ std::string full_path_;
+};
+
+typedef std::map<std::string, Storage> Storages;
+typedef void(*CallBackFunctionPtr)(const std::string&, Storage, void*);
+
+/**
+ * The VirtualFS class provide an abstraction of the TIZEN virtual filesystem.
+ * It manages mounted storages and virtual roots, creating missing directories
+ * if needed.
+ * Convenient functions are also provided for working with paths (real or
+ * virtual).
+ */
+class VirtualFS {
+ public:
+ VirtualFS();
+ ~VirtualFS();
+ /**
+ * Resolve the given fullpath within the virtual filesystem to an absolute
+ * path within the real filesystem.
+ * @param fullPath: fully-qualified path of the form: <root name>/<path>
+ * where <rootname> is the name of the virtual root and <path> is the path
+ * to the file or directory relative to that root.
+ * @return full Linux path.
+ */
+ std::string GetRealPath(const std::string& fullPath) const;
+ bool GetStorageByLabel(const std::string& label, Storage& storage);
+ Storages::iterator begin();
+ Storages::const_iterator end() const;
+ void SetOnStorageChangedCb(CallBackFunctionPtr cb, void* user_data);
+
+ /**
+ * Concatenate two paths.
+ * @param one: base path.
+ * @param another: path within 'one'.
+ * @return new path.
+ */
+ static std::string JoinPath(const std::string& one,
+ const std::string& another);
+ /**
+ * Create full path and parent directories when needed.
+ * Similar to "mkdir -p".
+ * @param path: the path to be created.
+ * @param mode: the unix access mode applied to the new directories.
+ * @return true if success.
+ */
+ static bool MakePath(const std::string& path, int mode);
+ static int GetDirEntryCount(const char* path);
+ static std::string GetAppId(const std::string& package_id);
+ static std::string GetExecPath(const std::string& app_id);
+ static std::string GetApplicationPath();
+
+ private:
+ void AddInternalStorage(const std::string& label, const std::string& path);
+ void AddStorage(int storage, storage_type_e type, storage_state_e state,
+ const std::string& path);
+ void NotifyStorageStateChanged(int id, storage_state_e state);
+ static bool OnStorageDeviceSupported(int id, storage_type_e type,
+ storage_state_e state, const char* path, void* user_data);
+ static void OnStorageStateChanged(int id, storage_state_e state,
+ void* user_data);
+
+ CallBackFunctionPtr storage_changed_cb_;
+ void* cb_user_data_;
+
+ typedef std::pair<std::string, Storage> StorageLabelPair;
+ Storages storages_;
+ std::vector<int> watched_storages_;
+};
+
+#endif // COMMON_VIRTUAL_FS_H_
'download_instance_desktop.cc',
'download_instance_tizen.cc',
'download_utils.h',
+ '../common/virtual_fs.cc',
+ '../common/virtual_fs.h',
],
'conditions': [
['tizen == 1', {
};
var ensureType = function(o, expected) {
- if (typeof o != expected) {
+ if (typeof o != expected || o === undefined) {
throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
}
};
throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
}
requests[request.uid] = request;
- // If listener is equal to 'undefined', 'listener !== null' is still true.
- // So change condition 'listener !== null' to 'listener != null'.
- if (listener != null) {
+ if (arguments.length > 1 && listener !== null) {
ensureType(listener, 'object');
exports.setListener(request.uid, listener);
}
DownloadArgs* args = new DownloadArgs(d->uid, this);
args_.push_back(args);
+ if (d->destination.empty()) {
+ OnFailedInfo(args,
+ ToString(EnumToPChar(DOWNLOAD_ERROR_INVALID_DESTINATION)));
+ return;
+ }
+
// create and start
CHECK(download_create(&d->download_id), args);
CHECK(download_set_state_changed_cb(d->download_id, OnStateChanged,
#include "common/extension.h"
#include "common/utils.h"
+#include "common/virtual_fs.h"
#include "web/download.h"
namespace picojson {
~DownloadInstance();
private:
+ VirtualFS vfs_;
virtual void HandleMessage(const char* msg);
virtual void HandleSyncMessage(const char* msg);
typedef std::map<std::string, DownloadItemRefPtr> DownloadItemMap;
DownloadItemMap downloads_;
- // TODO(hdq): This depends on filesystem api?
const std::string GetFullDestinationPath(const std::string destination) const;
- const std::string GetActualFolder(const std::string& destination) const;
bool GetDownloadID(const picojson::value& msg,
int& download_id, DownloadArgs** args);
#include <tzplatform_config.h>
#include <unistd.h>
-const std::string DownloadInstance::GetActualFolder(
- const std::string& destination) const {
- typedef std::map<std::string, std::string> LocationMap;
- static const LocationMap::value_type data[] = {
- LocationMap::value_type("documents", "Documents"),
- LocationMap::value_type("downloads", "Downloads"),
- LocationMap::value_type("images", "Images"),
- LocationMap::value_type("music", "Sounds"),
- LocationMap::value_type("videos", "Videos"),
- };
- static const LocationMap locations(data, data + sizeof data / sizeof data[0]);
- LocationMap::const_iterator location = locations.find(destination);
- if (location == locations.end()) {
- return destination;
- } else {
- return location->second;
- }
-}
-
const std::string DownloadInstance::GetFullDestinationPath(
const std::string destination) const {
- // TODO(hdq): User should be able to choose store to external storage
- // i.e. /opt/storage/sdcard/Downloads
- const std::string default_folder("Downloads");
- const std::string location =
- destination.empty() ? default_folder : destination;
- std::string path =
- tzplatform_getenv(TZ_USER_CONTENT) + GetActualFolder(location);
-
- // Create path if not exist
- struct stat path_stat;
- if (stat(path.c_str(), &path_stat) == -1
- && mkdir(path.c_str(), 0777) != 0) {
- path = tzplatform_getenv(TZ_USER_CONTENT) + default_folder;
- }
-
- return path;
+ std::string real_path;
+ if (destination.empty())
+ real_path = vfs_.GetRealPath(vfs_const::kLocationDownloads);
+ else
+ real_path = vfs_.GetRealPath(destination);
+ return real_path;
}
});
handle("bnstart2", "Start Download2", function() {
- r2 = new tizen.DownloadRequest(url2, "Images"); // Test saving to specific folder
+ r2 = new tizen.DownloadRequest(url2, "images"); // Test saving to specific folder
id2 = tizen.download.start(r2, listener);
urls[id2] = url2;
- output.value += "> asked to start download "+url2+" to Images folder\n";
+ output.value += "> asked to start download "+url2+" to images folder\n";
});
handle("button2", "Pause Download2", function() {
'filesystem_extension.h',
'filesystem_instance.cc',
'filesystem_instance.h',
+ '../common/virtual_fs.cc',
+ '../common/virtual_fs.h',
],
'includes': [
'../common/pkg-config.gypi',
#include <errno.h>
#include <fcntl.h>
#include <iconv.h>
-#include <pkgmgr-info.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <tzplatform_config.h>
#include <utility>
namespace {
-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";
-
-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";
const char kPlatformEncoding[] = "UTF-8";
const size_t kBufferSize = 1024 * 4;
unsigned int lastStreamId = 0;
-
bool IsWritable(const struct stat& st) {
if (st.st_mode & S_IWOTH)
return true;
return false;
}
-std::string JoinPath(const std::string& one, const std::string& another) {
- return one + '/' + another;
-}
-
-// This function creates full path and parent directories when needed.
-// Similar to "mkdir -p".
-bool makePath(const std::string& path) {
- // 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 (auto iter = dir.begin(); iter != dir.end();) {
- auto 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(), kDefaultFileMode) != 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 get_dir_entry_count(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 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;
+picojson::object StorageToJSON(Storage storage,
+ const std::string& label) {
+ picojson::object storage_object;
+ storage_object["label"] = picojson::value(label);
+ storage_object["type"] = picojson::value(storage.GetType());
+ storage_object["state"] = picojson::value(storage.GetState());
+ return storage_object;
}
-std::string GetApplicationPath() {
- std::string id_str = common::Extension::GetRuntimeVariable("app_id", 64);
- picojson::value id_val;
- std::istringstream buf(id_str);
- std::string error = picojson::parse(id_val, buf);
- if (!error.empty()) {
- std::cerr << "Got invalid package ID." << std::endl;
- return std::string();
- }
-
- std::string app_id = id_val.get<std::string>();
- if (app_id.empty())
- return std::string();
-
- std::string exec_path = GetExecPath(app_id);
- if (exec_path.empty())
- return std::string();
+} // namespace
- size_t index = exec_path.find(app_id);
- if (index != std::string::npos)
- return exec_path.substr(0, index + app_id.length());
- return std::string();
+FilesystemInstance::FilesystemInstance() {
}
-}; // namespace
-
-FilesystemInstance::FilesystemInstance() {
- std::string app_path = GetApplicationPath();
- if (!app_path.empty()) {
- AddInternalStorage(kLocationWgtPackage, app_path);
- AddInternalStorage(kLocationWgtPrivate, JoinPath(app_path, "private"));
- AddInternalStorage(kLocationWgtPrivateTmp, JoinPath(app_path, "tmp"));
- }
-
- AddInternalStorage(kLocationCamera, tzplatform_getenv(TZ_USER_CAMERA));
- AddInternalStorage(kLocationMusic, tzplatform_getenv(TZ_USER_SOUNDS));
- AddInternalStorage(kLocationImages, tzplatform_getenv(TZ_USER_IMAGES));
- AddInternalStorage(kLocationVideos, tzplatform_getenv(TZ_USER_VIDEOS));
- AddInternalStorage(kLocationDownloads, tzplatform_getenv(TZ_USER_DOWNLOADS));
- AddInternalStorage(kLocationDocuments, tzplatform_getenv(TZ_USER_DOCUMENTS));
- AddInternalStorage(kLocationRingtones, \
- tzplatform_mkpath(TZ_USER_SHARE, "settings/Ringtones"));
+void FilesystemInstance::Initialize() {
+ vfs_.SetOnStorageChangedCb(OnStorageStateChanged, this);
}
FilesystemInstance::~FilesystemInstance() {
mode = msg.contains("mode") ? msg.get("mode").to_str() : "rw";
- size_t pos_wgt_pkg = location.find(kLocationWgtPackage);
- size_t pos_ringtones = location.find(kLocationRingtones);
+ size_t pos_wgt_pkg = location.find(vfs_const::kLocationWgtPackage);
+ size_t pos_ringtones = location.find(vfs_const::kLocationRingtones);
if (pos_wgt_pkg != std::string::npos || pos_ringtones != std::string::npos) {
if (mode == "w" || mode == "rw" || mode == "a") {
if (pos_wgt_pkg != std::string::npos ||
pos_ringtones != std::string::npos ||
- location.find(kLocationWgtPrivate) != std::string::npos)
+ location.find(vfs_const::kLocationWgtPrivate) != std::string::npos)
check_if_inside_default = false;
std::string real_path;
real_path = location.substr(sizeof("file://") - 1);
check_if_inside_default = false;
} else {
- real_path = GetRealPath(location);
+ real_path = vfs_.GetRealPath(location);
}
if (real_path.empty()) {
void FilesystemInstance::HandleFileSystemManagerGetStorage(
const picojson::value& msg) {
- storage_foreach_device_supported(OnStorageDeviceSupported, this);
- Storages::const_iterator it = storages_.find(msg.get("label").to_str());
-
- if (it == storages_.end()) {
+ Storage storage;
+ std::string label = msg.get("label").to_str();
+ if (!vfs_.GetStorageByLabel(label, storage)) {
PostAsyncErrorReply(msg, NOT_FOUND_ERR);
return;
}
- picojson::object storage_object = it->second.toJSON(it->first);
+ picojson::object storage_object = StorageToJSON(storage, label);
PostAsyncSuccessReply(msg, storage_object);
}
void FilesystemInstance::HandleFileSystemManagerListStorages(
const picojson::value& msg) {
- storage_foreach_device_supported(OnStorageDeviceSupported, this);
picojson::array storage_objects;
- Storages::const_iterator it = storages_.begin();
- while (it != storages_.end()) {
- picojson::object storage_object = it->second.toJSON(it->first);
+ Storages::const_iterator it = vfs_.begin();
+ while (it != vfs_.end()) {
+ picojson::object storage_object = StorageToJSON(it->second, it->first);
storage_objects.push_back(picojson::value(storage_object));
++it;
}
return;
}
- std::string real_path = GetRealPath(msg.get("fullPath").to_str());
+ std::string real_path = vfs_.GetRealPath(msg.get("fullPath").to_str());
char* real_path_cstr = realpath(real_path.c_str(), NULL);
if (!real_path_cstr) {
free(real_path_cstr);
}
bool recursive = msg.get("recursive").evaluate_as_boolean();
- std::string real_path = GetRealPath(msg.get("directoryPath").to_str());
+ std::string real_path = vfs_.GetRealPath(msg.get("directoryPath").to_str());
if (real_path.empty()) {
PostAsyncErrorReply(msg, INVALID_VALUES_ERR);
return;
return;
}
- std::string real_path = GetRealPath(msg.get("filePath").to_str());
+ std::string real_path = vfs_.GetRealPath(msg.get("filePath").to_str());
if (real_path.empty()) {
PostAsyncErrorReply(msg, INVALID_VALUES_ERR);
return;
return;
}
- std::string real_path = GetRealPath(msg.get("fullPath").to_str());
+ std::string real_path = vfs_.GetRealPath(msg.get("fullPath").to_str());
if (real_path.empty()) {
PostAsyncErrorReply(msg, INVALID_VALUES_ERR);
return;
if (!strcmp(entry.d_name, ".") || !strcmp(entry.d_name, ".."))
continue;
- a.push_back(picojson::value(JoinPath(msg.get("fullPath").to_str(),
- entry.d_name)));
+ a.push_back(picojson::value(VirtualFS::JoinPath(
+ msg.get("fullPath").to_str(), entry.d_name)));
}
closedir(directory);
bool unlink_when_done_;
public:
PosixFile(const std::string& path, int mode)
- : fd_(open(path.c_str(), mode, kDefaultFileMode))
+ : fd_(open(path.c_str(), mode, vfs_const::kDefaultFileMode))
, mode_(mode)
, path_(path)
, unlink_when_done_(mode & O_CREAT) {}
} // end file case
// element is a directory, create if not exists
- int status = mkdir(to.c_str(), kDefaultFileMode);
+ int status = mkdir(to.c_str(), vfs_const::kDefaultFileMode);
if (status != 0 && errno != EEXIST) {
std::cerr << "failed to create destination dir: " << to << std::endl;
return false;
bool overwrite = msg.get("overwrite").evaluate_as_boolean();
std::string real_origin_path =
- GetRealPath(msg.get("originFilePath").to_str());
+ vfs_.GetRealPath(msg.get("originFilePath").to_str());
std::string real_destination_path =
ResolveImplicitDestination(real_origin_path,
- GetRealPath(msg.get("destinationFilePath").to_str()));
+ vfs_.GetRealPath(msg.get("destinationFilePath").to_str()));
if (!CopyAndRenameSanityChecks(msg, real_origin_path, real_destination_path,
overwrite))
bool overwrite = msg.get("overwrite").evaluate_as_boolean();
std::string real_origin_path =
- GetRealPath(msg.get("originFilePath").to_str());
+ vfs_.GetRealPath(msg.get("originFilePath").to_str());
std::string real_destination_path =
ResolveImplicitDestination(real_origin_path,
- GetRealPath(msg.get("destinationFilePath").to_str()));
+ vfs_.GetRealPath(msg.get("destinationFilePath").to_str()));
if (!CopyAndRenameSanityChecks(msg, real_origin_path, real_destination_path,
overwrite))
return;
}
- std::string full_path = JoinPath(msg.get("fullPath").to_str(),
+ std::string full_path = VirtualFS::JoinPath(msg.get("fullPath").to_str(),
msg.get("relativeDirPath").to_str());
if (full_path.empty()) {
SetSyncError(reply, INVALID_VALUES_ERR);
return;
}
- std::string real_path = GetRealPath(full_path);
+ std::string real_path = vfs_.GetRealPath(full_path);
if (real_path.empty()) {
SetSyncError(reply, INVALID_VALUES_ERR);
return;
}
- if (!makePath(real_path)) {
+ if (!VirtualFS::MakePath(real_path, vfs_const::kDefaultFileMode)) {
SetSyncError(reply, IO_ERR);
return;
}
return;
}
- std::string full_path = JoinPath(msg.get("fullPath").to_str(),
- msg.get("relativeFilePath").to_str());
+ std::string full_path = VirtualFS::JoinPath(
+ msg.get("fullPath").to_str(),
+ msg.get("relativeFilePath").to_str());
if (full_path.empty()) {
SetSyncError(reply, INVALID_VALUES_ERR);
return;
}
- std::string real_path = GetRealPath(full_path);
+ std::string real_path = vfs_.GetRealPath(full_path);
if (real_path.empty()) {
SetSyncError(reply, INVALID_VALUES_ERR);
return;
}
int result = open(real_path.c_str(), O_CREAT | O_WRONLY | O_EXCL,
- kDefaultFileMode);
+ vfs_const::kDefaultFileMode);
if (result < 0) {
SetSyncError(reply, IO_ERR);
return;
}
std::string full_path = msg.get("fullPath").to_str();
- std::string real_path = GetRealPath(full_path);
+ std::string real_path = vfs_.GetRealPath(full_path);
if (real_path.empty()) {
SetSyncError(reply, INVALID_VALUES_ERR);
return;
}
free(real_path_c);
- std::string uri_path = JoinPath("file:/", full_path);
+ std::string uri_path = VirtualFS::JoinPath("file:/", full_path);
SetSyncSuccess(reply, uri_path);
}
return;
}
- std::string full_path = JoinPath(msg.get("fullPath").to_str(),
- msg.get("relativeFilePath").to_str());
+ std::string full_path = VirtualFS::JoinPath(msg.get("fullPath").to_str(),
+ msg.get("relativeFilePath").to_str());
if (full_path.empty()) {
SetSyncError(reply, INVALID_VALUES_ERR);
return;
}
- std::string real_path = GetRealPath(full_path);
+ std::string real_path = vfs_.GetRealPath(full_path);
if (real_path.empty()) {
SetSyncError(reply, INVALID_VALUES_ERR);
return;
return;
}
- std::string real_path = GetRealPath(msg.get("fullPath").to_str());
+ std::string real_path = vfs_.GetRealPath(msg.get("fullPath").to_str());
if (real_path.empty()) {
SetSyncError(reply, INVALID_VALUES_ERR);
return;
o["isDirectory"] = picojson::value(is_directory);
if (is_directory)
o["length"] = picojson::value(
- static_cast<double>(get_dir_entry_count(real_path.c_str())));
+ static_cast<double>(VirtualFS::GetDirEntryCount(real_path.c_str())));
picojson::value v(o);
return;
}
-std::string FilesystemInstance::GetRealPath(const std::string& fullPath) {
- std::size_t pos = fullPath.find_first_of('/');
- std::string virtual_root = fullPath;
-
- if (pos != std::string::npos) {
- virtual_root = fullPath.substr(0, pos);
- }
-
- Storages::const_iterator it = storages_.find(virtual_root);
-
- if (it == storages_.end())
- return std::string();
-
- if (pos != std::string::npos)
- return it->second.GetFullPath() + fullPath.substr(pos);
-
- return it->second.GetFullPath();
-}
-
-void FilesystemInstance::AddInternalStorage(
- const std::string& label, const std::string& path) {
- if (makePath(path))
- storages_.insert(SorageLabelPair(label,
- Storage(-1,
- Storage::STORAGE_TYPE_INTERNAL,
- Storage::STORAGE_STATE_MOUNTED,
- path)));
-}
-
-void FilesystemInstance::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(SorageLabelPair(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 FilesystemInstance::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);
- picojson::object reply;
- reply["storage"] = picojson::value(it->second.toJSON(it->first));
- reply["cmd"] = picojson::value("storageChanged");
- picojson::value value(reply);
- PostMessage(value.serialize().c_str());
- break;
- }
- }
+void FilesystemInstance::NotifyStorageStateChanged(const std::string& label,
+ Storage storage) {
+ picojson::object reply;
+ reply["storage"] = picojson::value(StorageToJSON(storage, label));
+ reply["cmd"] = picojson::value("storageChanged");
+ picojson::value value(reply);
+ PostMessage(value.serialize().c_str());
}
-bool FilesystemInstance::OnStorageDeviceSupported(
- int id, storage_type_e type, storage_state_e state,
- const char* path, void* user_data) {
- reinterpret_cast<FilesystemInstance*>(user_data)->AddStorage(
- id, type, state, path);
- return true;
-}
-
-void FilesystemInstance::OnStorageStateChanged(
- int id, storage_state_e state, void* user_data) {
+void FilesystemInstance::OnStorageStateChanged(const std::string& label,
+ Storage storage, void* user_data) {
reinterpret_cast<FilesystemInstance*>(user_data)->NotifyStorageStateChanged(
- id, state);
-}
-
-FilesystemInstance::Storage::Storage(
- int id, int type, int state, const std::string& fullpath)
- : id_(id),
- type_(type),
- state_(state),
- fullpath_(fullpath) { }
-
-picojson::object FilesystemInstance::Storage::toJSON(
- const std::string& label) const {
- picojson::object storage_object;
- storage_object["label"] = picojson::value(label);
- storage_object["type"] = picojson::value(type());
- storage_object["state"] = picojson::value(state());
- return storage_object;
-}
-
-std::string FilesystemInstance::Storage::type() const {
- return (type_ == Storage::STORAGE_TYPE_INTERNAL) ? kStorageTypeInternal :
- kStorageTypeExternal;
-}
-
-std::string FilesystemInstance::Storage::state() 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();
+ label, storage);
}
#ifndef FILESYSTEM_FILESYSTEM_INSTANCE_H_
#define FILESYSTEM_FILESYSTEM_INSTANCE_H_
-#include <app_storage.h>
-
-#include <set>
-#include <string>
-#include <map>
#include <fstream>
#include <iostream>
+#include <map>
+#include <set>
+#include <string>
#include <utility>
-#include <vector>
#include "common/extension.h"
#include "common/picojson.h"
+#include "common/virtual_fs.h"
#include "tizen/tizen.h"
class FilesystemInstance : public common::Instance {
~FilesystemInstance();
// common::Instance implementation
+ void Initialize();
void HandleMessage(const char* message);
void HandleSyncMessage(const char* message);
private:
- class Storage {
- public:
- /* Mapped to storage_type_e */
- enum StorageType {
- STORAGE_TYPE_INTERNAL,
- STORAGE_TYPE_EXTERNAL,
- };
-
- /* Mapped to storage_state_e */
- enum StorageState {
- STORAGE_STATE_UNMOUNTABLE = -2,
- STORAGE_STATE_REMOVED = -1,
- STORAGE_STATE_MOUNTED = 0,
- STORAGE_STATE_MOUNTED_READONLY = 1,
- };
-
- Storage(int id, int type, int state, const std::string& fullpath);
-
- picojson::object toJSON(const std::string& label) const;
-
- std::string type() const;
- std::string state() const;
- int GetId() const { return id_; }
- const std::string& GetFullPath() const { return fullpath_; }
- void SetState(int state) { state_ = state; }
-
- private:
- int id_;
- int type_;
- int state_;
- std::string fullpath_;
- };
-
/* Asynchronous messages */
void HandleFileSystemManagerResolve(const picojson::value& msg);
void HandleFileSystemManagerGetStorage(const picojson::value& msg);
void SetSyncSuccess(std::string& reply, std::string& output);
void SetSyncSuccess(std::string& reply, picojson::value& output);
- std::string GetRealPath(const std::string& fullPath);
- void AddInternalStorage(const std::string& label, const std::string& path);
- void AddStorage(int storage, storage_type_e type, storage_state_e state,
- const std::string& path);
- void NotifyStorageStateChanged(int id, storage_state_e state);
- static bool OnStorageDeviceSupported(int id, storage_type_e type,
- storage_state_e state, const char *path, void *user_data);
- static void OnStorageStateChanged(int id, storage_state_e state,
- void *user_data);
+ void NotifyStorageStateChanged(const std::string& label, Storage storage);
+ static void OnStorageStateChanged(const std::string& label, Storage storage,
+ void* user_data);
typedef std::tuple<std::ios_base::openmode, std::fstream*,
std::string> FStream;
typedef std::map<unsigned int, FStream> FStreamMap;
FStreamMap fstream_map_;
- typedef std::map<std::string, Storage> Storages;
- typedef std::pair<std::string, Storage> SorageLabelPair;
- Storages storages_;
- std::vector<int> watched_storages_;
+ VirtualFS vfs_;
};
#endif // FILESYSTEM_FILESYSTEM_INSTANCE_H_