-%define libisu_version 0.0.1
+%define libisu_version 0.0.2
%define integration_tests_dir /usr/libexec/isu/
Summary: Individual Service Upgrade support
Name: isu
-Version: 9.0.5
+Version: 9.0.6
Release: 1
Source0: %{name}-%{version}.tar.gz
License: MIT
InstallDir,
Uninstall,
GetVersion,
+ List,
+ PkgInfo,
};
static GMainLoop *loop;
" <arg type='s' name='version' direction='out'/>"
" <arg type='i' name='result' direction='out'/>"
" </method>"
+" <method name='list'>"
+" <arg type='as' name='result' direction='out'/>"
+" <arg type='i' name='result' direction='out'/>"
+" </method>"
+" <method name='pkg_info'>"
+" <arg type='s' name='pkg_name' direction='in'/>"
+" <arg type='s' name='name' direction='out'/>"
+" <arg type='s' name='version' direction='out'/>"
+" <arg type='as' name='services' direction='out'/>"
+" <arg type='i' name='result' direction='out'/>"
+" </method>"
" </interface>"
"</node>";
return "uninstall";
case GetVersion:
return "get_version";
+ case List:
+ return "list";
+ case PkgInfo:
+ return "list";
}
return "unknown action";
}
GDBusMessage *incoming_message = g_dbus_method_invocation_get_message(invocation);
GVariant *body = g_dbus_message_get_body(incoming_message);
gchar *data;
- g_variant_get(body, "(s)", &data);
+ if (action == List) {
+ data = "";
+ } else {
+ g_variant_get(body, "(s)", &data);
+ }
int res;
gchar *version = NULL;
+ struct _isu_pkg_list *list;
switch (action) {
case Install:
res = isu_install_internal(data);
case GetVersion:
res = isu_get_version_internal(data, &version);
break;
+ case List:
+ res = isu_list_init_internal(&list);
+ break;
default:
res = -1;
}
g_variant_new("(si)", version, res));
g_free(version);
break;
+ case List:
+ {
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("as"));
+ struct _isu_pkg_list_element *element = list->head;
+ while (element != NULL) {
+ g_variant_builder_add(&builder, "s", element->name);
+ element = element->next;
+ }
+
+ GVariant *payload = g_variant_new("(asi)", &builder, res);
+ g_dbus_method_invocation_return_value(invocation, payload);
+ isu_list_free(list);
+ break;
+ }
default:
g_dbus_method_invocation_return_value(invocation,
g_variant_new("(i)", res));
call_handler(invocation, GetVersion);
}
+static void list_handler(GDBusMethodInvocation *invocation)
+{
+ call_handler(invocation, List);
+}
+
+static void get_pkg_info_handler(GDBusMethodInvocation *invocation)
+{
+ int res = ISU_RES_OK;
+ GDBusMessage *incoming_message = g_dbus_method_invocation_get_message(invocation);
+ GVariant *body = g_dbus_message_get_body(incoming_message);
+ gchar *pkg_name;
+ g_variant_get(body, "(s)", &pkg_name);
+ char path[PATH_MAX];
+ snprintf(path, sizeof(path), "%s/%s/isu.cfg", ISU_PKG_PATH, pkg_name);
+ g_free(pkg_name);
+ struct _isu_pkg_info *pkg_info = get_pkg_info(path);
+
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("as"));
+
+ char *name = "";
+ char *version = "";
+ if (pkg_info == NULL) {
+ res = ISU_RES_ERR_INTERNAL;
+ } else {
+ name = pkg_info->name;
+ version = pkg_info->version;
+ for (size_t i = 0; i < pkg_info->service_files_len; i++) {
+ g_variant_builder_add(&builder, "s", pkg_info->service_files[i]);
+ }
+ }
+ GVariant *payload = g_variant_new("(ssasi)", name, version, &builder, res);
+ g_dbus_method_invocation_return_value(invocation, payload);
+ if (pkg_info != NULL) {
+ isu_pkg_info_free(pkg_info);
+ }
+}
+
static void method_call_handler(GDBusConnection *conn,
const gchar *sender,
const gchar *object_path,
uninstall_handler(invocation);
} else if (g_strcmp0(method_name, "get_version") == 0) {
get_version_handler(invocation);
+ } else if (g_strcmp0(method_name, "list") == 0) {
+ list_handler(invocation);
+ } else if (g_strcmp0(method_name, "pkg_info") == 0) {
+ get_pkg_info_handler(invocation);
} else {
SLOGE("Unsupported method: %s", method_name);
}
send_interface="org.tizen.system.isu"/>
</policy>
- <policy user="owner">
- <allow send_destination="org.tizen.system.isu"
- send_interface="org.tizen.system.isu"/>
- </policy>
-
<policy context="default">
<deny own="org.tizen.system.isu"/>
<deny send_destination="org.tizen.system.isu"/>
+ <check send_destination="org.tizen.system.isu"
+ privilege="http://tizen.org/privilege/isu.admin"/>
</policy>
</busconfig>
return result;
}
-isu_result isu_dbus_call(const char *method, const char *parameter, char **outparam)
-{
+static isu_result isu_dbus_make_call(const char *method, GVariant *input_param, GVariant **body) {
GError *error = NULL;
- int res;
+ int res = ISU_RES_OK;
GDBusConnection *conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
if (conn == NULL) {
SLOGE("isu_%s: g_bus_get_sync error: %s", method, error ? error->message : "");
return ISU_RES_ERR_INTERNAL;
}
- g_dbus_message_set_body(msg, g_variant_new("(s)", parameter));
+ g_dbus_message_set_body(msg, input_param);
GDBusMessage *reply = g_dbus_connection_send_message_with_reply_sync(
conn,
goto exit;
}
- GVariant *body = g_dbus_message_get_body(reply);
- if (body == NULL) {
+ *body = g_dbus_message_get_body(reply);
+ if (*body == NULL) {
SLOGE("isu_%s: get message body error", method);
res = ISU_RES_ERR_INTERNAL;
goto exit;
}
+ *body = g_variant_ref(*body);
+exit:
+ g_object_unref(msg);
+ g_object_unref(reply);
+ g_object_unref(conn);
+ return res;
+}
+
+isu_result isu_dbus_call(const char *method, const char *parameter, char **outparam)
+{
+ GVariant *body = NULL;
+ isu_result res = isu_dbus_make_call(method, g_variant_new("(s)", parameter), &body);
+ if (res != ISU_RES_OK) {
+ goto exit;
+ }
if (strcmp(method, "get_version") == 0) {
gchar *version;
g_variant_get(body, "(i)", &res);
}
exit:
- g_object_unref(msg);
- g_object_unref(reply);
- g_object_unref(conn);
+ if (body != NULL) {
+ g_variant_unref(body);
+ }
+ return res;
+}
+
+isu_result isu_dbus_list_call(struct _isu_pkg_list **list) {
+ assert(list);
+ GVariant *body = NULL;
+ const gchar **str_array = NULL;
+ isu_result res = isu_dbus_make_call("list", NULL, &body);
+ if (res != ISU_RES_OK) {
+ goto exit;
+ }
+
+ GVariant *array;
+ g_variant_get(body, "(@asi)", &array, &res);
+
+ gsize len;
+ str_array = g_variant_get_strv(array, &len);
+ g_variant_unref(array);
+
+ *list = malloc(sizeof(**list));
+ if (*list == NULL) {
+ SLOGE("Memory allocation error (%d): %m", errno);
+ res = ISU_RES_ERR_INTERNAL;
+ goto exit;
+ }
+ (*list)->head = NULL;
+ (*list)->cur = NULL;
+
+ struct _isu_pkg_list_element *prev = NULL;
+ for (size_t i = 0; i < len; i++) {
+ struct _isu_pkg_list_element *element = malloc(sizeof(*element));
+ if (element == NULL) {
+ SLOGE("Memory allocation error (%d): %m");
+ isu_list_free(*list);
+ *list = NULL;
+ res = ISU_RES_ERR_INTERNAL;
+ goto exit;
+ }
+ element->name = strdup(str_array[i]);
+ element->next = NULL;
+ if (prev == NULL) {
+ (*list)->head = element;
+ (*list)->cur = element;
+ } else {
+ prev->next = element;
+ }
+ prev = element;
+ }
+exit:
+ if (body != NULL) {
+ g_variant_unref(body);
+ }
+ if (str_array != NULL) {
+ g_free(str_array);
+ }
+ return res;
+}
+
+isu_result isu_pkg_info_call(char *pkg_name, struct _isu_pkg_info **pkg_info)
+{
+ assert(pkg_name);
+ assert(pkg_info);
+ GVariant *body = NULL;
+ const gchar **service_array = NULL;
+ isu_result res = isu_dbus_make_call("pkg_info", g_variant_new("(s)", pkg_name), &body);
+ if (res != ISU_RES_OK) {
+ goto exit;
+ }
+ GVariant *array;
+ gchar *name;
+ gchar *version;
+ g_variant_get(body, "(ss@asi)", &name, &version, &array, &res);
+
+ gsize len;
+ service_array = g_variant_get_strv(array, &len);
+ struct _isu_pkg_info *_pkg_info = malloc(sizeof(*_pkg_info));
+ if (_pkg_info == NULL) {
+ res = ISU_RES_ERR_INTERNAL;
+ goto exit;
+ }
+ _pkg_info->name = name;
+ _pkg_info->version = version;
+ _pkg_info->service_files_len = len;
+ _pkg_info->service_files = malloc(len*sizeof(*_pkg_info->service_files));
+ if (_pkg_info->service_files == NULL) {
+ free(_pkg_info);
+ res = ISU_RES_ERR_INTERNAL;
+ goto exit;
+ }
+ for (size_t i = 0; i < len; i++) {
+ _pkg_info->service_files[i] = strdup(service_array[i]);
+ }
+
+ *pkg_info = _pkg_info;
+exit:
+ if (body != NULL) {
+ g_variant_unref(body);
+ }
+ if (service_array != NULL) {
+ g_free(service_array);
+ }
return res;
}
return *version ? ISU_RES_OK : ISU_RES_ERR_NOT_EXIST;
}
+
+bool is_valid_isu_pkg(const char *path)
+{
+ assert(path);
+
+ struct stat statbuff;
+ char pathbuff[PATH_MAX+8];
+ snprintf(pathbuff, sizeof(pathbuff), "%s/%s", path, ISU_CFG);
+
+ return stat(pathbuff, &statbuff) == 0;
+}
+
+isu_result isu_list_init_internal(struct _isu_pkg_list **pkg_list)
+{
+ assert(pkg_list);
+
+ RET_IF_FEATURE_NOT_SUPPORTED(ISU_RES_ERR_FEATURE);
+ *pkg_list = malloc(sizeof(struct _isu_pkg_list));
+ if (*pkg_list == NULL) {
+ SLOGE("Memory allocation error (%d): %m\n", errno);
+ return ISU_RES_ERR_INTERNAL;
+ }
+
+ (*pkg_list)->head = NULL;
+ (*pkg_list)->cur = NULL;
+ DIR *dir = opendir(ISU_PKG_PATH);
+ if (dir == NULL) {
+ SLOGE("Open dir %s error (%d): %m\n", ISU_PKG_PATH, errno);
+ isu_list_free(*pkg_list);
+ *pkg_list = NULL;
+ return ISU_RES_ERR_INTERNAL;
+ }
+
+ struct _isu_pkg_list_element *prev = NULL;
+ struct dirent *entry;
+ while ((entry = readdir(dir)) != NULL) {
+ if (entry->d_type != DT_DIR) continue;
+
+ char pathbuff[PATH_MAX];
+ snprintf(pathbuff, sizeof(pathbuff), "%s/%s", ISU_PKG_PATH, entry->d_name);
+ if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
+ continue;
+
+ if (is_valid_isu_pkg(pathbuff)) {
+ struct _isu_pkg_list_element *element = malloc(sizeof(struct _isu_pkg_list_element));
+ if (element == NULL) {
+ SLOGE("Memory allocation error (%d): %m\n", errno);
+ isu_list_free(*pkg_list);
+ closedir(dir);
+ return ISU_RES_ERR_INTERNAL;
+ }
+ element->name = strdup(entry->d_name);
+ element->next = NULL;
+ if (prev == NULL) {
+ (*pkg_list)->head = element;
+ (*pkg_list)->cur = element;
+ } else {
+ prev->next = element;
+ }
+ prev = element;
+ } else {
+ SLOGW("Invalid ISU package directory: %s\n", pathbuff);
+ }
+ }
+
+ closedir(dir);
+
+ return ISU_RES_OK;
+}
char **service_files;
};
+bool is_valid_isu_pkg(const char *path);
isu_result isu_install_dir(const char *path);
isu_result isu_install_dir_internal(const char *path);
isu_result isu_install_internal(const char *path);
isu_file_res is_isu_file(const char *path, pid_t pid, char **source_path);
struct _isu_pkg_info* get_pkg_info(const char *isu_cfg_path);
isu_result isu_dbus_call(const char *method, const char *parameter, char **outparam);
+isu_result isu_dbus_list_call(struct _isu_pkg_list **list);
+isu_result isu_pkg_info_call(char *pkg_name, struct _isu_pkg_info **pkg_info);
isu_result remove_dir_contents(const char *path);
+isu_result isu_list_init_internal(struct _isu_pkg_list **list);
#include "libisu-internal.h"
-static bool is_valid_isu_pkg(const char *path)
-{
- assert(path);
-
- struct stat statbuff;
- char pathbuff[PATH_MAX+8];
- snprintf(pathbuff, sizeof(pathbuff), "%s/%s", path, ISU_CFG);
-
- return stat(pathbuff, &statbuff) == 0;
-}
-
/*
* Public API Functions
*/
isu_pkg_list isu_list_init()
{
- RET_IF_FEATURE_NOT_SUPPORTED(NULL);
- struct _isu_pkg_list *pkg_list = malloc(sizeof(struct _isu_pkg_list));
- if (pkg_list == NULL) {
- SLOGE("Memory allocation error (%d): %m\n", errno);
- return NULL;
- }
-
- pkg_list->head = NULL;
- pkg_list->cur = NULL;
- DIR *dir = opendir(ISU_PKG_PATH);
- if (dir == NULL) {
- SLOGE("Open dir %s error (%d): %m\n", ISU_PKG_PATH, errno);
- isu_list_free(pkg_list);
- return NULL;
- }
-
- struct _isu_pkg_list_element *prev = NULL;
- struct dirent *entry;
- while ((entry = readdir(dir)) != NULL) {
- if (entry->d_type != DT_DIR) continue;
-
- char pathbuff[PATH_MAX];
- snprintf(pathbuff, sizeof(pathbuff), "%s/%s", ISU_PKG_PATH, entry->d_name);
- if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
- continue;
-
- if (is_valid_isu_pkg(pathbuff)) {
- struct _isu_pkg_list_element *element = malloc(sizeof(struct _isu_pkg_list_element));
- if (element == NULL) {
- SLOGE("Memory allocation error (%d): %m\n", errno);
- isu_list_free(pkg_list);
- closedir(dir);
- return NULL;
- }
- element->name = strdup(entry->d_name);
- element->next = NULL;
- if (prev == NULL) {
- pkg_list->head = element;
- pkg_list->cur = element;
- } else {
- prev->next = element;
- }
- prev = element;
- } else {
- SLOGW("Invalid ISU package directory: %s\n", pathbuff);
+ struct _isu_pkg_list *list = NULL;
+ if (isu_dbus_list_call(&list) != ISU_RES_OK) {
+ if (list != NULL) {
+ isu_list_free(list);
}
+ return NULL;
}
- closedir(dir);
-
- return pkg_list;
+ return list;
}
isu_result isu_list_free(isu_pkg_list pkg_list)
if (pkg_list_i->cur == NULL)
return NULL;
- char isu_cfg_path[PATH_MAX];
- snprintf(isu_cfg_path, sizeof(isu_cfg_path), "%s/%s/%s", ISU_PKG_PATH, pkg_list_i->cur->name, ISU_CFG);
- isu_pkg_info pkg_info = get_pkg_info(isu_cfg_path);
-
+ struct _isu_pkg_info *_pkg_info = NULL;
+ isu_result res = isu_pkg_info_call(pkg_list_i->cur->name, &_pkg_info);
+ if (res != ISU_RES_OK) {
+ if (_pkg_info != NULL) {
+ free(_pkg_info);
+ }
+ return NULL;
+ }
pkg_list_i->cur = pkg_list_i->cur->next;
- return pkg_info;
+ return (isu_pkg_info)_pkg_info;
}
isu_result isu_pkg_get_name(isu_pkg_info pkg_info, char *name, size_t len)