#include <boost/filesystem.hpp>
-#include <dbus/dbus.h>
+#include <gio/gio.h>
+#include <glib.h>
#include <cstdlib>
+#include <functional>
namespace bf = boost::filesystem;
} // namespace
-void DBusMessageDeleter(DBusMessage* message) {
- dbus_message_unref(message);
-}
+namespace common_installer {
-void DBusErrorDeleter(DBusError* error) {
- dbus_error_free(error);
- std::default_delete<DBusError>();
-}
+class DBusProxy {
+ public:
+ DBusProxy() : conn_(nullptr), proxy_(nullptr) {
+ if (!Init())
+ LOG(ERROR) << "Failed to initialize DBus proxy";
+ }
-namespace common_installer {
+ ~DBusProxy() {
+ if (proxy_)
+ g_object_unref(proxy_);
+ if (conn_) {
+ g_dbus_connection_flush_sync(conn_, nullptr, nullptr);
+ g_object_unref(conn_);
+ }
+ }
+
+ bool Init() {
+ GError* error = nullptr;
+ conn_ = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error);
+ if (!conn_ || error) {
+ LOG(ERROR) << "g_bus_get_sync() failed: " << error->message;
+ g_error_free(error);
+ return false;
+ }
+ proxy_ = g_dbus_proxy_new_sync(conn_, G_DBUS_PROXY_FLAGS_NONE, nullptr,
+ kTzipBusName, kTzipObjectPath, kTzipInterfaceName, nullptr, &error);
+ if (!proxy_ || error) {
+ LOG(ERROR) << "g_dbus_proxy_new_sync() failed: " << error->message;
+ g_error_free(error);
+ return false;
+ }
+ return true;
+ }
+
+ GVariant* ProxyCallSync(const char* method, GVariant* params) {
+ if (!proxy_) {
+ LOG(ERROR) << "DBus proxy is not initialized";
+ return nullptr;
+ }
+ GError* error = nullptr;
+ GVariant* ret = g_dbus_proxy_call_sync(proxy_, method,
+ params, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error);
+ if (error) {
+ LOG(ERROR) << "g_dbus_proxy_call_sync() of " << method << " failed: "
+ << error->message;
+ g_error_free(error);
+ }
+ return ret;
+ }
+
+ private:
+ GDBusConnection* conn_;
+ GDBusProxy* proxy_;
+};
class TzipInterface::Pimpl {
public:
explicit Pimpl(const boost::filesystem::path& mount_path) :
- mount_path_(mount_path) { }
+ mount_path_(mount_path), dbus_proxy_(new DBusProxy()) { }
bool MountZip(const boost::filesystem::path& zip_path) {
zip_path_ = zip_path;
- DBusConnection *conn = dbus_bus_get(DBUS_BUS_SYSTEM, nullptr);
- if (!conn) {
- return false;
- }
-
if (bf::exists(mount_path_)) {
LOG(WARNING) << "Mount path(" << mount_path_ << ") already exists! "
<< "We will remove it...";
bf::remove(mount_path_);
}
- std::unique_ptr<DBusMessage, void(*)(DBusMessage*)> msg(
- dbus_message_new_method_call(kTzipBusName, kTzipObjectPath,
- kTzipInterfaceName,
- kTzipMountMethod),
- DBusMessageDeleter);
- if (!msg) {
- LOG(ERROR) << "Could not create new dbus message";
+ if (!bf::exists(zip_path)) {
+ LOG(WARNING) << "zip path(" << zip_path << ") doesn't exist!";
return false;
}
const char* zip_path_str = zip_path_.string().c_str();
const char* tzip_smack_rule = kTzipSmackRule;
- if (!dbus_message_append_args(msg.get(),
- DBUS_TYPE_STRING, &mount_path_str,
- DBUS_TYPE_STRING, &zip_path_str,
- DBUS_TYPE_STRING, &tzip_smack_rule,
- DBUS_TYPE_INVALID)) {
- return false;
- }
-
- if (dbus_connection_send(conn, msg.get(), nullptr) == FALSE) {
+ GVariant* r = dbus_proxy_->ProxyCallSync(kTzipMountMethod,
+ g_variant_new("(sss)", mount_path_str, zip_path_str, tzip_smack_rule));
+ if (!r) {
LOG(ERROR) << "Could not send DBUS message when mounting zip file";
return false;
}
- return WaitForMounted();
+ g_variant_unref(r);
+
+ return WaitForCondition([=](bool *success)->bool {
+ return IsMounted(success);
+ });
}
bool UnmountZip() {
- DBusConnection *conn = dbus_bus_get(DBUS_BUS_SYSTEM, nullptr);
- if (!conn) {
- return false;
- }
-
- std::unique_ptr<DBusMessage, void(*)(DBusMessage*)> msg(
- dbus_message_new_method_call(kTzipBusName, kTzipObjectPath,
- kTzipInterfaceName,
- kTzipUnmountMethod),
- DBusMessageDeleter);
- if (!msg) {
- LOG(ERROR) << "Could not create new dbus message";
- return false;
- }
-
const char* mount_path_str = mount_path_.string().c_str();
- if (!dbus_message_append_args(msg.get(),
- DBUS_TYPE_STRING, &mount_path_str,
- DBUS_TYPE_INVALID)) {
- return false;
- }
- if (dbus_connection_send(conn, msg.get(), nullptr) == FALSE) {
+ GVariant* r = dbus_proxy_->ProxyCallSync(kTzipUnmountMethod,
+ g_variant_new("(s)", mount_path_str));
+ if (!r) {
LOG(ERROR) << "Could not send DBUS message when unmounting zip file";
return false;
}
+ g_variant_unref(r);
- return true;
+ return WaitForCondition([=](bool *success)->bool {
+ return IsUnmounted(success);
+ });
}
private:
- bool IsMounted() {
- int ret = -1;
- int r = -1;
- DBusMessage *reply;
- std::unique_ptr<DBusError, void(*)(DBusError*)> err(new DBusError(),
- DBusErrorDeleter);
-
- DBusConnection* conn = dbus_bus_get(DBUS_BUS_SYSTEM, nullptr);
- if (!conn) {
- return false;
- }
- std::unique_ptr<DBusMessage, void(*)(DBusMessage*)> msg(
- dbus_message_new_method_call(kTzipBusName, kTzipObjectPath,
- kTzipInterfaceName,
- kTzipIsMountedMethod),
- DBusMessageDeleter);
- if (!msg) {
- return false;
- }
-
+ bool IsMounted(bool *success) {
const char* mount_path_str = mount_path_.string().c_str();
- if (!dbus_message_append_args(msg.get(),
- DBUS_TYPE_STRING, &mount_path_str,
- DBUS_TYPE_INVALID)) {
- return false;
- }
-
- dbus_error_init(err.get());
- reply = dbus_connection_send_with_reply_and_block(conn, msg.get(), 500,
- err.get());
- if (!reply) {
- return false;
- }
-
- r = dbus_message_get_args(reply, err.get(), DBUS_TYPE_INT32, &ret,
- DBUS_TYPE_INVALID);
+ GVariant* r = dbus_proxy_->ProxyCallSync(kTzipIsMountedMethod,
+ g_variant_new("(s)", mount_path_str));
if (!r) {
+ *success = false;
return false;
}
+ gint ret;
+ g_variant_get(r, "(i)", &ret);
+ g_variant_unref(r);
+ *success = true;
return ret != 0;
}
- bool WaitForMounted() {
+ bool IsUnmounted(bool *success) {
+ return !IsMounted(success);
+ }
+
+ bool WaitForCondition(std::function<bool(bool*)> condition) {
if (!mount_path_.empty()) {
bool rv = false;
int cnt = 0;
while (cnt < kTzipMountMaximumRetryCount) {
- rv = IsMounted();
- if (rv)
+ bool success;
+ rv = condition(&success);
+ if (rv && success)
break;
sleep(1);
cnt++;
boost::filesystem::path mount_path_;
boost::filesystem::path zip_path_;
+ std::unique_ptr<DBusProxy> dbus_proxy_;
};
-
TzipInterface::TzipInterface(const boost::filesystem::path& mount_path)
: impl_(new Pimpl(mount_path)) {}