From: Mateusz Moscicki Date: Tue, 13 Aug 2024 09:43:18 +0000 (+0200) Subject: Code reorganize to make SAM happy X-Git-Tag: accepted/tizen/unified/20241006.053324~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bd2eaa93ee942fb76d31159db95c341af0c5f35f;p=platform%2Fcore%2Fsystem%2Fupdate-control.git Code reorganize to make SAM happy Functions have been separated into utils/ and base/. In common/ is the code that calls fota_* and recovery_* functions. SAM score has been improved from 3.62 to 4.92 Change-Id: I285e1f7c53feb3415de22b4a57879bc1ca80a744 --- diff --git a/update-manager/base/base-boot-status-checker.c b/update-manager/base/base-boot-status-checker.c new file mode 100644 index 0000000..ddfeeb6 --- /dev/null +++ b/update-manager/base/base-boot-status-checker.c @@ -0,0 +1,14 @@ +#include "base.h" + +static int boot_status = -1; + +void base_set_boot_status_checker(int status) +{ + boot_status = status; +} + +bool base_boot_status_checker_is_success() +{ + return (boot_status == VCONFKEY_SYSMAN_BOOTING_SUCCESS); +} + diff --git a/update-manager/base/base-client-controller.c b/update-manager/base/base-client-controller.c new file mode 100644 index 0000000..9503370 --- /dev/null +++ b/update-manager/base/base-client-controller.c @@ -0,0 +1,43 @@ +#include "base.h" + +int base_client_controller_launch(const char* appid, const char *key, const char *value) +{ + int ret = 0, status = 0; + bundle *bundle_data = NULL; + + bundle_data = bundle_create(); + if (bundle_data == NULL) { + _CLOGE("bundle_create failed"); + status = -1; + goto launch_destroy; + } + + ret = aul_svc_set_operation(bundle_data, AUL_SVC_OPERATION_DEFAULT); + if (ret != AUL_R_OK) { + _CLOGE("aul_svc_set_operation failed : %d", ret); + status = -1; + goto launch_destroy; + } + + ret = aul_svc_add_data(bundle_data, key, value); + if (ret != AUL_R_OK) { + _CLOGE("aul_svc_add_data failed : %d", ret); + status = -1; + goto launch_destroy; + } + + ret = aul_launch_app_for_uid(appid, bundle_data, OWNER_UID); + if (ret < AUL_R_OK) { + _CLOGE("aul_launch_app_for_uid failed : %d", ret); + status = -1; + } + +launch_destroy: + if (bundle_data) { + ret = bundle_free(bundle_data); + if (ret != BUNDLE_ERROR_NONE) + _CLOGW("bundle_free failed : %d", ret); + } + + return status; +} diff --git a/update-manager/base/base-client-info-checker.c b/update-manager/base/base-client-info-checker.c new file mode 100644 index 0000000..083af7e --- /dev/null +++ b/update-manager/base/base-client-info-checker.c @@ -0,0 +1,85 @@ +#include "../base/base.h" + +int base_client_info_checker_get_appid(pkgmgrinfo_appinfo_h handle, char **app_id) +{ + int ret = 0, status = 0; + pkgmgrinfo_appinfo_h appinfo_h = NULL; + + if (app_id == NULL) { + _CLOGE("invalid params, app_id is should be address"); + status = -1; + goto callback_destroy; + } + + if (*app_id != NULL) { + _CLOGE("client app id already exists : %s", *app_id); + status = -1; + goto callback_destroy; + } + + ret = pkgmgrinfo_appinfo_clone_appinfo(handle, &appinfo_h); + if (ret != PMINFO_R_OK) { + _CLOGE("pkgmgrinfo_appinfo_clone_appinfo failed : %d", ret); + status = -1; + goto callback_destroy; + } + + ret = pkgmgrinfo_appinfo_get_appid(appinfo_h, app_id); + if (ret != PMINFO_R_OK) { + _CLOGE("app_info_get_app_id failed : %d", ret); + status = -1; + goto callback_destroy; + } + + *app_id = strndup(*app_id, strlen(*app_id)); + if (*app_id == NULL) { + _CLOGE("Failed strndup : %m"); + status = -1; + goto callback_destroy; + } + +callback_destroy: + if (appinfo_h) { + ret = pkgmgrinfo_appinfo_destroy_appinfo(appinfo_h); + if (ret != PMINFO_R_OK) + _CLOGW("pkgmgrinfo_appinfo_destroy_appinfo failed : %d ", ret); + } + + return status; +} + +int base_client_info_checker_filter(const char* key, const char* value, pkgmgrinfo_app_list_cb cb) +{ + int ret = 0, status = 0; + pkgmgrinfo_appinfo_metadata_filter_h filter_h = NULL; + + ret = pkgmgrinfo_appinfo_metadata_filter_create(&filter_h); + if (ret != PMINFO_R_OK) { + _CLOGE("pkgmgrinfo_appinfo_metadata_filter_create failed : %d", ret); + status = -1; + goto init_destroy; + } + + ret = pkgmgrinfo_appinfo_metadata_filter_add(filter_h, key, value); + if (ret != PMINFO_R_OK) { + _CLOGE("pkgmgrinfo_appinfo_metadata_filter_add failed : %d", ret); + status = -1; + goto init_destroy; + } + + ret = pkgmgrinfo_appinfo_metadata_filter_foreach(filter_h, cb, NULL); + if (ret != PMINFO_R_OK) { + _CLOGE("pkgmgrinfo_appinfo_usr_metadata_filter_foreach failed : %d", ret); + status = -1; + goto init_destroy; + } + +init_destroy: + if (filter_h) { + ret = pkgmgrinfo_appinfo_metadata_filter_destroy(filter_h); + if (ret != PMINFO_R_OK) + _CLOGW("pkgmgrinfo_appinfo_metadata_filter_destroy failed : %d", ret); + } + + return status; +} diff --git a/update-manager/base/base.h b/update-manager/base/base.h new file mode 100644 index 0000000..e9f40dd --- /dev/null +++ b/update-manager/base/base.h @@ -0,0 +1,40 @@ +#ifndef __BASE_H__ +#define __BASE_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Log */ +#define COMMON_LOG_TAG "UPDATE_MANAGER" + +#define _CLOGD(fmt, arg...) SLOG(LOG_INFO, COMMON_LOG_TAG, fmt, ##arg) +#define _CLOGI(fmt, arg...) SLOG(LOG_INFO, COMMON_LOG_TAG, fmt, ##arg) +#define _CLOGW(fmt, arg...) SLOG(LOG_WARN, COMMON_LOG_TAG, fmt, ##arg) +#define _CLOGE(fmt, arg...) SLOG(LOG_ERROR, COMMON_LOG_TAG, fmt, ##arg) + +/* Constant */ +#define MAX_BUFFER_SIZE 256 +#define OWNER_UID 5001 + +#define DBUS_INTERFACE_NAME "org.tizen.update.manager" +#define DBUS_NODE_NAME "/org/tizen/update/manager" + +int base_client_controller_launch(const char *, const char *, const char *); + +int base_client_info_checker_get_appid(pkgmgrinfo_appinfo_h, char **); +int base_client_info_checker_filter(const char *, const char *, pkgmgrinfo_app_list_cb); + +void base_set_boot_status_checker(int); +bool base_boot_status_checker_is_success(void); + +#endif /* __BASE_H__ */ diff --git a/update-manager/common/common-boot-status-checker.c b/update-manager/common/common-boot-status-checker.c index 5a62ceb..6926d27 100644 --- a/update-manager/common/common-boot-status-checker.c +++ b/update-manager/common/common-boot-status-checker.c @@ -1,22 +1,18 @@ +#include "../base/base.h" #include "common.h" #include "../recovery/recovery-manager.h" #include "../fota/fota-manager.h" -static int boot_status = -1; - -bool common_boot_status_checker_is_success() -{ - return (boot_status == VCONFKEY_SYSMAN_BOOTING_SUCCESS); -} - void common_boot_status_checker_callback(keynode_t *node, void *user_data) { int ret = 0; + int boot_status; ret = vconf_keynode_get_type(node); if (ret == VCONF_TYPE_INT) { boot_status = vconf_keynode_get_int(node); - if (common_boot_status_checker_is_success()) { + base_set_boot_status_checker(boot_status); + if (base_boot_status_checker_is_success()) { ret = vconf_ignore_key_changed(VCONFKEY_SYSMAN_BOOTINGSTATUS, common_boot_status_checker_callback); if (ret == VCONF_OK) _CLOGI("Success to remove bootstatus callback"); @@ -41,15 +37,17 @@ void common_boot_status_checker_callback(keynode_t *node, void *user_data) int common_boot_status_checker_init() { int ret = 0; + int boot_status; _CLOGI("Start process to get boot status"); ret = vconf_get_int(VCONFKEY_SYSMAN_BOOTINGSTATUS, &boot_status); + base_set_boot_status_checker(boot_status); if (ret != VCONF_OK) { _CLOGE("vconf_get_int for %s failed: %d", VCONFKEY_SYSMAN_BOOTINGSTATUS, ret); return -1; } - if (common_boot_status_checker_is_success()) { + if (base_boot_status_checker_is_success()) { _CLOGI("Success to get boot status : success"); } else { ret = vconf_notify_key_changed(VCONFKEY_SYSMAN_BOOTINGSTATUS, common_boot_status_checker_callback, NULL); @@ -67,7 +65,7 @@ int common_boot_status_checker_fini() { int ret = 0; - if (!common_boot_status_checker_is_success()) { + if (!base_boot_status_checker_is_success()) { ret = vconf_ignore_key_changed(VCONFKEY_SYSMAN_BOOTINGSTATUS, common_boot_status_checker_callback); if (ret != VCONF_OK) _CLOGW("vconf_ignore_key_changed for %s failed : %d", VCONFKEY_SYSMAN_BOOTINGSTATUS, ret); diff --git a/update-manager/common/common-client-controller.c b/update-manager/common/common-client-controller.c deleted file mode 100644 index 8be288e..0000000 --- a/update-manager/common/common-client-controller.c +++ /dev/null @@ -1,43 +0,0 @@ -#include "common.h" - -int common_client_controller_launch(const char* appid, const char *key, const char *value) -{ - int ret = 0, status = 0; - bundle *bundle_data = NULL; - - bundle_data = bundle_create(); - if (bundle_data == NULL) { - _CLOGE("bundle_create failed"); - status = -1; - goto launch_destroy; - } - - ret = aul_svc_set_operation(bundle_data, AUL_SVC_OPERATION_DEFAULT); - if (ret != AUL_R_OK) { - _CLOGE("aul_svc_set_operation failed : %d", ret); - status = -1; - goto launch_destroy; - } - - ret = aul_svc_add_data(bundle_data, key, value); - if (ret != AUL_R_OK) { - _CLOGE("aul_svc_add_data failed : %d", ret); - status = -1; - goto launch_destroy; - } - - ret = aul_launch_app_for_uid(appid, bundle_data, OWNER_UID); - if (ret < AUL_R_OK) { - _CLOGE("aul_launch_app_for_uid failed : %d", ret); - status = -1; - } - -launch_destroy: - if (bundle_data) { - ret = bundle_free(bundle_data); - if (ret != BUNDLE_ERROR_NONE) - _CLOGW("bundle_free failed : %d", ret); - } - - return status; -} diff --git a/update-manager/common/common-client-info-checker.c b/update-manager/common/common-client-info-checker.c deleted file mode 100644 index f37eba2..0000000 --- a/update-manager/common/common-client-info-checker.c +++ /dev/null @@ -1,85 +0,0 @@ -#include "common.h" - -int common_client_info_checker_get_appid(pkgmgrinfo_appinfo_h handle, char **app_id) -{ - int ret = 0, status = 0; - pkgmgrinfo_appinfo_h appinfo_h = NULL; - - if (app_id == NULL) { - _CLOGE("invalid params, app_id is should be address"); - status = -1; - goto callback_destroy; - } - - if (*app_id != NULL) { - _CLOGE("client app id already exists : %s", *app_id); - status = -1; - goto callback_destroy; - } - - ret = pkgmgrinfo_appinfo_clone_appinfo(handle, &appinfo_h); - if (ret != PMINFO_R_OK) { - _CLOGE("pkgmgrinfo_appinfo_clone_appinfo failed : %d", ret); - status = -1; - goto callback_destroy; - } - - ret = pkgmgrinfo_appinfo_get_appid(appinfo_h, app_id); - if (ret != PMINFO_R_OK) { - _CLOGE("app_info_get_app_id failed : %d", ret); - status = -1; - goto callback_destroy; - } - - *app_id = strndup(*app_id, strlen(*app_id)); - if (*app_id == NULL) { - _CLOGE("Failed strndup : %m"); - status = -1; - goto callback_destroy; - } - -callback_destroy: - if (appinfo_h) { - ret = pkgmgrinfo_appinfo_destroy_appinfo(appinfo_h); - if (ret != PMINFO_R_OK) - _CLOGW("pkgmgrinfo_appinfo_destroy_appinfo failed : %d ", ret); - } - - return status; -} - -int common_client_info_checker_filter(const char* key, const char* value, pkgmgrinfo_app_list_cb cb) -{ - int ret = 0, status = 0; - pkgmgrinfo_appinfo_metadata_filter_h filter_h = NULL; - - ret = pkgmgrinfo_appinfo_metadata_filter_create(&filter_h); - if (ret != PMINFO_R_OK) { - _CLOGE("pkgmgrinfo_appinfo_metadata_filter_create failed : %d", ret); - status = -1; - goto init_destroy; - } - - ret = pkgmgrinfo_appinfo_metadata_filter_add(filter_h, key, value); - if (ret != PMINFO_R_OK) { - _CLOGE("pkgmgrinfo_appinfo_metadata_filter_add failed : %d", ret); - status = -1; - goto init_destroy; - } - - ret = pkgmgrinfo_appinfo_metadata_filter_foreach(filter_h, cb, NULL); - if (ret != PMINFO_R_OK) { - _CLOGE("pkgmgrinfo_appinfo_usr_metadata_filter_foreach failed : %d", ret); - status = -1; - goto init_destroy; - } - -init_destroy: - if (filter_h) { - ret = pkgmgrinfo_appinfo_metadata_filter_destroy(filter_h); - if (ret != PMINFO_R_OK) - _CLOGW("pkgmgrinfo_appinfo_metadata_filter_destroy failed : %d", ret); - } - - return status; -} \ No newline at end of file diff --git a/update-manager/common/common-dbus-manager.c b/update-manager/common/common-dbus-manager.c deleted file mode 100644 index ebaec69..0000000 --- a/update-manager/common/common-dbus-manager.c +++ /dev/null @@ -1,222 +0,0 @@ -#include -#include "common.h" -#include "../fota/fota-manager.h" -#include "update-manager-dbus.h" - -static guint owner_id; - -typedef enum { - RO_UPDATE, - FINISH, - RO_UPDATE_AND_FINISH, -} dbus_handler_action; - -typedef struct _dbus_handler_arg { - dbus_handler_action action; - OrgTizenUpdateManager *skeleton; - GDBusMethodInvocation *invocation; -} dbus_handler_arg; - -static pid_t dbus_get_sender_pid(GDBusMethodInvocation *invocation) -{ - const gchar *sender = g_dbus_method_invocation_get_sender(invocation); - GDBusConnection *conn = g_dbus_method_invocation_get_connection(invocation); - if (sender == NULL || conn == NULL) { - _FLOGW("Failed to get invocation data"); - return 0; - } - GError *error = NULL; - GVariant *result = g_dbus_connection_call_sync(conn, - "org.freedesktop.DBus", - "/", - "org.freedesktop.DBus", - "GetConnectionUnixProcessID", - g_variant_new("(s)", sender), - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error); - if (!result || error) { - _FLOGW("Failed to get sender PID: %s", error ? error->message : ""); - g_error_free(error); - return 0; - } - - pid_t pid; - g_variant_get(result, "(u)", &pid); - g_variant_unref(result); - return pid; -} - -void *dbus_call_handler(void *arg) -{ - int ret = 0; - pid_t pid = 0; - dbus_handler_arg *handler_arg = (dbus_handler_arg *) arg; - - if (handler_arg->action != FINISH) - pid = dbus_get_sender_pid(handler_arg->invocation); - - switch (handler_arg->action) { - case RO_UPDATE: - ret = fota_installer_ro_update(pid); - if (ret < 0) - _FLOGW("Failed to perform : %d", ret); - org_tizen_update_manager_complete_ro_update(handler_arg->skeleton, handler_arg->invocation, ret); - break; - case FINISH: - ret = fota_installer_finish_update(); - if (ret < 0) - _FLOGW("Failed to perform : %d", ret); - org_tizen_update_manager_complete_finish_update(handler_arg->skeleton, handler_arg->invocation, ret); - break; - case RO_UPDATE_AND_FINISH: - ret = fota_installer_ro_update_and_finish_update(pid); - if (ret < 0) - _FLOGW("Failed to perform : %d", ret); - org_tizen_update_manager_complete_ro_update_and_finish_update(handler_arg->skeleton, handler_arg->invocation, ret); - break; - } - - free(arg); - g_thread_exit(0); -} - -gboolean dbus_manager_ro_update(OrgTizenUpdateManager *skeleton, GDBusMethodInvocation *invocation) -{ - _FLOGD("Dbus status: called"); - dbus_handler_arg *arg = (dbus_handler_arg *)malloc(sizeof(dbus_handler_arg)); - if (!arg) { - _FLOGE("Failed to malloc"); - goto fail; - } - - arg->action = RO_UPDATE; - arg->skeleton = skeleton; - arg->invocation = invocation; - - GError *error = NULL; - GThread *thread = g_thread_try_new(NULL, (GThreadFunc)dbus_call_handler, (void *)arg, &error); - if (error != NULL) { - _FLOGE("Failed to create thread: %s", error->message); - goto fail; - } - - g_thread_unref(thread); - - return TRUE; - -fail: - if (arg) - free(arg); - - org_tizen_update_manager_complete_ro_update(skeleton, invocation, -1); - return TRUE; -} - -gboolean dbus_manager_finish_update(OrgTizenUpdateManager *skeleton, GDBusMethodInvocation *invocation) -{ - _FLOGD("Dbus status: called"); - dbus_handler_arg *arg = (dbus_handler_arg *)malloc(sizeof(dbus_handler_arg)); - if (!arg) { - _FLOGE("Failed to malloc"); - goto fail; - } - - arg->action = FINISH; - arg->skeleton = skeleton; - arg->invocation = invocation; - - GError *error = NULL; - GThread *thread = g_thread_try_new(NULL, (GThreadFunc)dbus_call_handler, (void *)arg, &error); - if (error != NULL) { - _FLOGE("Failed to create thread: %s", error->message); - goto fail; - } - - g_thread_unref(thread); - - return TRUE; - -fail: - if (arg) - free(arg); - - org_tizen_update_manager_complete_finish_update(skeleton, invocation, -1); - return TRUE; -} - -/* - * This is not supposed to be called asynchronously, so this doesn't need a separate thread. - * This new thread is only for consistency with functions above. - */ -gboolean dbus_manager_ro_update_and_finish_update(OrgTizenUpdateManager *skeleton, GDBusMethodInvocation *invocation) -{ - _FLOGD("Dbus status: called"); - dbus_handler_arg *arg = (dbus_handler_arg *)malloc(sizeof(dbus_handler_arg)); - if (!arg) { - _FLOGE("Failed to malloc"); - goto fail; - } - - arg->action = RO_UPDATE_AND_FINISH; - arg->skeleton = skeleton; - arg->invocation = invocation; - - GError *error = NULL; - GThread *thread = g_thread_try_new(NULL, (GThreadFunc)dbus_call_handler, (void *)arg, &error); - if (error != NULL) { - _FLOGE("Failed to create thread: %s", error->message); - goto fail; - } - - g_thread_unref(thread); - - return TRUE; - -fail: - if (arg) - free(arg); - - org_tizen_update_manager_complete_ro_update_and_finish_update(skeleton, invocation, -1); - return TRUE; -} - -void dbus_manager_on_name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data) -{ - _CLOGD("Dbus status: name lost"); -} - -void dbus_manager_on_name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data) -{ - _CLOGD("Dbus status: name acquired"); - - OrgTizenUpdateManager *skeleton = org_tizen_update_manager_skeleton_new(); - - g_signal_connect(skeleton, "handle-ro-update", G_CALLBACK(dbus_manager_ro_update), NULL); - g_signal_connect(skeleton, "handle-finish-update", G_CALLBACK(dbus_manager_finish_update), NULL); - g_signal_connect(skeleton, "handle-ro-update-and-finish-update", G_CALLBACK(dbus_manager_ro_update_and_finish_update), NULL); - - g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(skeleton), connection, DBUS_NODE_NAME, NULL); -} - -void dbus_manager_on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data) -{ - _CLOGD("Dbus status: bus acquired"); -} - -int dbus_manager_init() -{ - owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM, DBUS_INTERFACE_NAME, G_BUS_NAME_OWNER_FLAGS_NONE, - dbus_manager_on_bus_acquired, dbus_manager_on_name_acquired, dbus_manager_on_name_lost, NULL, NULL); - - return 0; -} - -int dbus_manager_fini() -{ - g_bus_unown_name(owner_id); - - return 0; -} diff --git a/update-manager/common/common-storage-checker.c b/update-manager/common/common-storage-checker.c index 26d8b14..41cbb75 100644 --- a/update-manager/common/common-storage-checker.c +++ b/update-manager/common/common-storage-checker.c @@ -1,3 +1,4 @@ +#include "../base/base.h" #include "common.h" #include "../recovery/recovery-manager.h" #include "../fota/fota-manager.h" diff --git a/update-manager/common/common-tar.c b/update-manager/common/common-tar.c deleted file mode 100644 index c7de444..0000000 --- a/update-manager/common/common-tar.c +++ /dev/null @@ -1,180 +0,0 @@ -#include "common.h" - -#include -#include -#include -#include -#include - -// for the sake of simplicity this stays global -static gzFile gz_tar = NULL; - -int gzip_open(const char *pathname, int oflags, ...) -{ - if (gz_tar != NULL) { - errno = EALREADY; - return -1; - } - - // We assume oflags == O_RDONLY, since that's what we actually use. - // Also we don't care about the mode since we are lazy. - if (oflags != O_RDONLY) { - errno = ENOTSUP; - return -1; - } - - gz_tar = gzopen(pathname, "r"); - if (gz_tar == NULL) { - _CLOGE("gzopen() failed with errno: %d\n", errno); - return -1; - } - - return 1; -} - -int gzip_close(__attribute__((unused)) int useless_fd) -{ - if (gz_tar == NULL) { - errno = EINVAL; - return -1; - } - - int ret = gzclose(gz_tar); - if (ret != Z_OK) - _CLOGE("gzclose() failed with errno: %d\n", errno); - - return ret; -} - -ssize_t gzip_read(__attribute__((unused)) int useless_fd, void *buf, size_t len) -{ - if (gz_tar == NULL) { - errno = EINVAL; - return -1; - } - - int ret = gzread(gz_tar, buf, len); - if (ret <= 0) { - if (gzeof(gz_tar)) - _CLOGE("gzread() failed - EOF reached\n"); - else - _CLOGE("gzread() failed with error: %s\n", gzerror(gz_tar, NULL)); - } - - return ret; -} - -ssize_t gzip_write(__attribute__((unused)) int useless_fd, __attribute__((unused)) const void *buf, __attribute__((unused)) size_t len) -{ - // Again, we do not use this. - errno = ENOTSUP; - return -1; -} - -static int str_ends_with(const char *str, const char *suffix) -{ - size_t str_length = strlen(str); - size_t suffix_length = strlen(suffix); - - return ((str_length > suffix_length) && (memcmp(str + str_length - suffix_length, suffix, suffix_length + 1) == 0)); -} - -static int tar_get_tartype(const char *tar_path, tartype_t **type) -{ - static tartype_t gzip_type = {gzip_open, gzip_close, gzip_read, gzip_write}; - - if (str_ends_with(tar_path, ".tar")) { - *type = NULL; - } - else if (str_ends_with(tar_path, ".tar.gz")) { - *type = &gzip_type; - } - else if (str_ends_with(tar_path, ".tgz")) { - *type = &gzip_type; - } - else { - _CLOGE("Unknown/unsupported file extension for delta - %s\n", tar_path); - return -1; - } - - return 0; -} - -static int tar_init_with_type(TAR **tar, const char *tar_path, tartype_t *type) -{ - if (tar_open(tar, tar_path, type, O_RDONLY, 0, 0) < 0) { - *tar = NULL; - _CLOGE("tar_open() fail!\n"); - return -1; - } - - return 0; -} - -int util_file_untar(const char *tar_path, const char *dest_path, const char *extract_file_name) -{ - TAR *tar; - tartype_t *type; - DIR *dir; - - if (tar_get_tartype(tar_path, &type)) { - _CLOGE("tar_get_tartype() error!\n"); - return -1; - } - - dir = opendir(dest_path); - if (dir == NULL) { - _CLOGE("Directory %s could not be opened, errno: %d\n", dest_path, errno); - return -1; - } - closedir(dir); - - if (tar_init_with_type(&tar, tar_path, type)) { - _CLOGE("tar_init_with_type() error!\n"); - return -1; - } - - int ret = 0; - char extracted_file_path[MAX_BUFFER_SIZE]; - snprintf(extracted_file_path, MAX_BUFFER_SIZE, "%s/%s", dest_path, extract_file_name); - - for (;;) - { - switch (th_read(tar)) - { - case -1: - _CLOGE("th_read() fail!\n"); - ret = -1; - goto cleanup; - case 1: - _CLOGE("EOF reached - incorrect delta!\n"); - ret = -1; - goto cleanup; - case 0: - break; - } - - char *current_pathname = th_get_pathname(tar); - - if (strcmp(current_pathname, extract_file_name) == 0) { - if (tar_extract_file(tar, extracted_file_path) < 0) { - _CLOGE("tar_extract_file() fail!\n"); - ret = -1; - goto cleanup; - } - _CLOGI("%s successfully extracted from %s\n", extract_file_name, tar_path); - goto cleanup; - } - - if (TH_ISREG(tar) && (tar_skip_regfile(tar) < 0)) { - _CLOGE("tar_skip_regfile() fail!\n"); - ret = -1; - goto cleanup; - } - } - -cleanup: - tar_close(tar); - gz_tar = NULL; - return ret; -} \ No newline at end of file diff --git a/update-manager/common/common-util.c b/update-manager/common/common-util.c deleted file mode 100644 index 20a911d..0000000 --- a/update-manager/common/common-util.c +++ /dev/null @@ -1,208 +0,0 @@ -#include -#include "common.h" -#include "sha1.h" - -int util_file_mkdir(const char *path) -{ - int ret = 0; - gboolean exist = FALSE; - - exist = g_file_test(path, G_FILE_TEST_IS_DIR); - if (!exist) { - ret = mkdir(path, 0775); - if (ret < 0) { - _CLOGE("Failed to make %s : %m", path); - return -1; - } - } - - return 0; -} - -int util_file_remove(const char *path) -{ - int ret = 0; - gboolean exist = FALSE; - - exist = g_file_test(path, G_FILE_TEST_EXISTS); - if (exist) { - ret = remove(path); - if (ret < 0) { - _CLOGE("Failed to remove %s : %m", path); - return -1; - } - } - - return 0; -} - -int util_file_symlink(const char *target_path, const char *link_path) -{ - int ret = 0; - gboolean exist = FALSE; - - exist = g_file_test(target_path, G_FILE_TEST_EXISTS); - if (!exist) { - _CLOGE("Failed to find %s", target_path); - return -1; - } - - ret = util_file_remove(link_path); - if (ret < 0) - return -1; - - ret = symlink(target_path, link_path); - if (ret < 0) { - _CLOGE("Failed to symlink from %s to %s : %m", target_path, link_path); - return -1; - } - - return 0; -} - -int util_file_read_single_line(const char *path, char buf[]) -{ - int status = 0; - FILE *fp = NULL; - - fp = fopen(path, "r"); - if (fp != NULL) { - if (fgets(buf, MAX_BUFFER_SIZE, fp) == NULL) { - _CLOGE("Failed to read : %s", path); - status = -1; - } - fclose(fp); - } else { - _CLOGE("Failed to open : %s", path); - status = -1; - } - - return status; -} - -int util_file_write_line(const char *path, const char *msg) -{ - int ret = 0, status = 0; - FILE *fp = NULL; - - fp = fopen(path, "w"); - if (fp != NULL) { - ret = fprintf(fp, "%s", msg); - if (ret < 0) { - _CLOGE("Failed to write, path : %s, msg : %s", path, msg); - status = -1; - } - fclose(fp); - } else { - _CLOGE("Failed to open : %s", path); - status = -1; - } - - return status; -} - -static int read_checksum_for(const char *checksum_path, const char *file_name, char *sha1_hex, size_t sha1_hex_len) -{ - int result = -1; - - if (sha1_hex_len < (2 * SHA1_LEN + 1)) { - _CLOGE("Checksum buffer too small"); - return result; - } - - FILE *checksum_fp = fopen(checksum_path, "r"); - if (!checksum_fp) { - _CLOGE("Cannot open %s", checksum_path); - return result; - } - - char *line = NULL; - size_t line_len = 0; - - while (getline(&line, &line_len, checksum_fp) != -1) { - char *saveptr = NULL; - char *checksum = NULL; - char *checksum_fname = NULL; - - checksum = strtok_r(line, " \n", &saveptr); - - if (checksum == NULL) - continue; - - if (strlen(checksum) != (2 * SHA1_LEN)) - continue; - - checksum_fname = strtok_r(NULL, " \n", &saveptr); - - if (checksum_fname == NULL) - continue; - - if (strncmp(checksum_fname, file_name, strlen(file_name) + 1) == 0) { - strncpy(sha1_hex, checksum, sha1_hex_len - 1); - sha1_hex[sha1_hex_len - 1] = '\0'; - result = 0; - break; - } - } - - free(line); - fclose(checksum_fp); - return result; -} - -static int calculate_checksum(const char *file_path, char *sha1_hex, size_t sha1_hex_len) -{ - if (sha1_hex_len != (2 * SHA1_LEN + 1)) { - _CLOGE("Checksum buffer too small"); - return -1; - } - - int file_fd = open(file_path, O_RDONLY); - if (file_fd == -1) { - _CLOGE("Cannot open %s", file_path); - return -1; - } - - SHA1_CTX context; - SHA1Init(&context); - - unsigned char buf[1024]; - - int bytes; - while ((bytes = read(file_fd, buf, sizeof(buf))) > 0) - SHA1Update(&context, buf, bytes); - - close(file_fd); - - unsigned char sha1[SHA1_LEN * 2 + 1]; - SHA1Final(sha1, &context); - - const char HEX_DIGITS[] = "0123456789abcdef"; - - for (size_t i = 0; i < SHA1_LEN; i++) { - sha1_hex[2 * i] = HEX_DIGITS[sha1[i] / 16]; - sha1_hex[2 * i + 1] = HEX_DIGITS[sha1[i] % 16]; - } - sha1_hex[sha1_hex_len - 1] = '\0'; - return 0; -} - -int verify_checksum(const char *checksum_path, const char *file_path) -{ - char *file_name = rindex(file_path, '/'); - if (!file_name || ! ++file_name) { - _CLOGE("Cannot extract the file name from path"); - return -1; - } - - char sha1_from_file[SHA1_LEN * 2 + 1]; - char sha1_calculated[SHA1_LEN * 2 + 1]; - - if (read_checksum_for(checksum_path, file_name, sha1_from_file, sizeof(sha1_from_file)) != 0) - return -1; - - if (calculate_checksum(file_path, sha1_calculated, sizeof(sha1_calculated)) != 0) - return -1; - - return strncmp(sha1_from_file, sha1_calculated, sizeof(sha1_from_file)); -} diff --git a/update-manager/common/common.h b/update-manager/common/common.h index afa4f3f..800363e 100644 --- a/update-manager/common/common.h +++ b/update-manager/common/common.h @@ -1,62 +1,13 @@ #ifndef __COMMON_H__ #define __COMMON_H__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include - -/* Log */ -#define COMMON_LOG_TAG "UPDATE_MANAGER" - -#define _CLOGD(fmt, arg...) SLOG(LOG_INFO, COMMON_LOG_TAG, fmt, ##arg) -#define _CLOGI(fmt, arg...) SLOG(LOG_INFO, COMMON_LOG_TAG, fmt, ##arg) -#define _CLOGW(fmt, arg...) SLOG(LOG_WARN, COMMON_LOG_TAG, fmt, ##arg) -#define _CLOGE(fmt, arg...) SLOG(LOG_ERROR, COMMON_LOG_TAG, fmt, ##arg) - -/* Constant */ -#define MAX_BUFFER_SIZE 256 -#define OWNER_UID 5001 - -#define DBUS_INTERFACE_NAME "org.tizen.update.manager" -#define DBUS_NODE_NAME "/org/tizen/update/manager" - -/* Enum */ /* Function */ int common_boot_status_checker_init(void); int common_boot_status_checker_fini(void); -bool common_boot_status_checker_is_success(void); - -int common_client_controller_launch(const char *, const char *, const char *); - -int common_client_info_checker_get_appid(pkgmgrinfo_appinfo_h, char **); -int common_client_info_checker_filter(const char *, const char *, pkgmgrinfo_app_list_cb); int common_storage_checker_init(void); int common_storage_checker_fini(void); -int dbus_manager_init(void); -int dbus_manager_fini(void); - -int util_file_mkdir(const char *); -int util_file_remove(const char *); -int util_file_symlink(const char *, const char *); -int util_file_read_single_line(const char *, char[]); -int util_file_write_line(const char *, const char *); -int util_file_untar(const char *, const char *, const char *); -int verify_checksum(const char *checksum_path, const char *file_path); - #endif /* __COMMON_H__ */ diff --git a/update-manager/common/sha1.c b/update-manager/common/sha1.c deleted file mode 100644 index dafcf6f..0000000 --- a/update-manager/common/sha1.c +++ /dev/null @@ -1,298 +0,0 @@ -/* -SHA-1 in C -By Steve Reid -100% Public Domain - -Test Vectors (from FIPS PUB 180-1) -"abc" - A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D -"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 -A million repetitions of "a" - 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F -*/ - -/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */ -/* #define SHA1HANDSOFF * Copies data before messing with it. */ - -#define SHA1HANDSOFF - -#include -#include -#include - -/* for uint32_t */ -#include - -#include "sha1.h" - - -#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) - -/* blk0() and blk() perform the initial expand. */ -/* I got the idea of expanding during the round function from SSLeay */ -#if BYTE_ORDER == LITTLE_ENDIAN -#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ - |(rol(block->l[i],8)&0x00FF00FF)) -#elif BYTE_ORDER == BIG_ENDIAN -#define blk0(i) block->l[i] -#else -#error "Endianness not defined!" -#endif -#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ - ^block->l[(i+2)&15]^block->l[i&15],1)) - -/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); -#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); -#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); - - -/* Hash a single 512-bit block. This is the core of the algorithm. */ - -void SHA1Transform( - uint32_t state[5], - const unsigned char buffer[64] -) -{ - uint32_t a, b, c, d, e; - - typedef union - { - unsigned char c[64]; - uint32_t l[16]; - } CHAR64LONG16; - -#ifdef SHA1HANDSOFF - CHAR64LONG16 block[1]; /* use array to appear as a pointer */ - - memcpy(block, buffer, 64); -#else - /* The following had better never be used because it causes the - * pointer-to-const buffer to be cast into a pointer to non-const. - * And the result is written through. I threw a "const" in, hoping - * this will cause a diagnostic. - */ - CHAR64LONG16 *block = (const CHAR64LONG16 *) buffer; -#endif - /* Copy context->state[] to working vars */ - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - /* 4 rounds of 20 operations each. Loop unrolled. */ - R0(a, b, c, d, e, 0); - R0(e, a, b, c, d, 1); - R0(d, e, a, b, c, 2); - R0(c, d, e, a, b, 3); - R0(b, c, d, e, a, 4); - R0(a, b, c, d, e, 5); - R0(e, a, b, c, d, 6); - R0(d, e, a, b, c, 7); - R0(c, d, e, a, b, 8); - R0(b, c, d, e, a, 9); - R0(a, b, c, d, e, 10); - R0(e, a, b, c, d, 11); - R0(d, e, a, b, c, 12); - R0(c, d, e, a, b, 13); - R0(b, c, d, e, a, 14); - R0(a, b, c, d, e, 15); - R1(e, a, b, c, d, 16); - R1(d, e, a, b, c, 17); - R1(c, d, e, a, b, 18); - R1(b, c, d, e, a, 19); - R2(a, b, c, d, e, 20); - R2(e, a, b, c, d, 21); - R2(d, e, a, b, c, 22); - R2(c, d, e, a, b, 23); - R2(b, c, d, e, a, 24); - R2(a, b, c, d, e, 25); - R2(e, a, b, c, d, 26); - R2(d, e, a, b, c, 27); - R2(c, d, e, a, b, 28); - R2(b, c, d, e, a, 29); - R2(a, b, c, d, e, 30); - R2(e, a, b, c, d, 31); - R2(d, e, a, b, c, 32); - R2(c, d, e, a, b, 33); - R2(b, c, d, e, a, 34); - R2(a, b, c, d, e, 35); - R2(e, a, b, c, d, 36); - R2(d, e, a, b, c, 37); - R2(c, d, e, a, b, 38); - R2(b, c, d, e, a, 39); - R3(a, b, c, d, e, 40); - R3(e, a, b, c, d, 41); - R3(d, e, a, b, c, 42); - R3(c, d, e, a, b, 43); - R3(b, c, d, e, a, 44); - R3(a, b, c, d, e, 45); - R3(e, a, b, c, d, 46); - R3(d, e, a, b, c, 47); - R3(c, d, e, a, b, 48); - R3(b, c, d, e, a, 49); - R3(a, b, c, d, e, 50); - R3(e, a, b, c, d, 51); - R3(d, e, a, b, c, 52); - R3(c, d, e, a, b, 53); - R3(b, c, d, e, a, 54); - R3(a, b, c, d, e, 55); - R3(e, a, b, c, d, 56); - R3(d, e, a, b, c, 57); - R3(c, d, e, a, b, 58); - R3(b, c, d, e, a, 59); - R4(a, b, c, d, e, 60); - R4(e, a, b, c, d, 61); - R4(d, e, a, b, c, 62); - R4(c, d, e, a, b, 63); - R4(b, c, d, e, a, 64); - R4(a, b, c, d, e, 65); - R4(e, a, b, c, d, 66); - R4(d, e, a, b, c, 67); - R4(c, d, e, a, b, 68); - R4(b, c, d, e, a, 69); - R4(a, b, c, d, e, 70); - R4(e, a, b, c, d, 71); - R4(d, e, a, b, c, 72); - R4(c, d, e, a, b, 73); - R4(b, c, d, e, a, 74); - R4(a, b, c, d, e, 75); - R4(e, a, b, c, d, 76); - R4(d, e, a, b, c, 77); - R4(c, d, e, a, b, 78); - R4(b, c, d, e, a, 79); - /* Add the working vars back into context.state[] */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - /* Wipe variables */ - a = b = c = d = e = 0; -#ifdef SHA1HANDSOFF - memset(block, '\0', sizeof(block)); -#endif -} - - -/* SHA1Init - Initialize new context */ - -void SHA1Init( - SHA1_CTX * context -) -{ - /* SHA1 initialization constants */ - context->state[0] = 0x67452301; - context->state[1] = 0xEFCDAB89; - context->state[2] = 0x98BADCFE; - context->state[3] = 0x10325476; - context->state[4] = 0xC3D2E1F0; - context->count[0] = context->count[1] = 0; -} - - -/* Run your data through this. */ - -void SHA1Update( - SHA1_CTX * context, - const unsigned char *data, - uint32_t len -) -{ - uint32_t i; - - uint32_t j; - - j = context->count[0]; - if ((context->count[0] += len << 3) < j) - context->count[1]++; - context->count[1] += (len >> 29); - j = (j >> 3) & 63; - if ((j + len) > 63) - { - memcpy(&context->buffer[j], data, (i = 64 - j)); - SHA1Transform(context->state, context->buffer); - for (; i + 63 < len; i += 64) - { - SHA1Transform(context->state, &data[i]); - } - j = 0; - } - else - i = 0; - memcpy(&context->buffer[j], &data[i], len - i); -} - - -/* Add padding and return the message digest. */ - -void SHA1Final( - unsigned char digest[20], - SHA1_CTX * context -) -{ - unsigned i; - - unsigned char finalcount[8]; - - unsigned char c; - -#if 0 /* untested "improvement" by DHR */ - /* Convert context->count to a sequence of bytes - * in finalcount. Second element first, but - * big-endian order within element. - * But we do it all backwards. - */ - unsigned char *fcp = &finalcount[8]; - - for (i = 0; i < 2; i++) - { - uint32_t t = context->count[i]; - - int j; - - for (j = 0; j < 4; t >>= 8, j++) - *--fcp = (unsigned char) t} -#else - for (i = 0; i < 8; i++) - { - finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ - } -#endif - c = 0200; - SHA1Update(context, &c, 1); - while ((context->count[0] & 504) != 448) - { - c = 0000; - SHA1Update(context, &c, 1); - } - SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ - for (i = 0; i < 20; i++) - { - digest[i] = (unsigned char) - ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); - } - /* Wipe variables */ - memset(context, '\0', sizeof(*context)); - memset(&finalcount, '\0', sizeof(finalcount)); -} - -void SHA1( - char *hash_out, - const char *str, - int len) -{ - SHA1_CTX ctx; - unsigned int ii; - - assert(len >= 0); - - SHA1Init(&ctx); - for (ii=0; ii<(unsigned int)len; ii+=1) - SHA1Update(&ctx, (const unsigned char*)str + ii, 1); - SHA1Final((unsigned char *)hash_out, &ctx); -} - diff --git a/update-manager/common/sha1.h b/update-manager/common/sha1.h deleted file mode 100644 index 8ffba8a..0000000 --- a/update-manager/common/sha1.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef SHA1_H -#define SHA1_H - -/* - SHA-1 in C - By Steve Reid - 100% Public Domain - */ - -#include "stdint.h" - -#define SHA1_LEN 20 - -typedef struct -{ - uint32_t state[5]; - uint32_t count[2]; - unsigned char buffer[64]; -} SHA1_CTX; - -void SHA1Transform( - uint32_t state[5], - const unsigned char buffer[64] - ); - -void SHA1Init( - SHA1_CTX * context - ); - -void SHA1Update( - SHA1_CTX * context, - const unsigned char *data, - uint32_t len - ); - -void SHA1Final( - unsigned char digest[20], - SHA1_CTX * context - ); - -void SHA1( - char *hash_out, - const char *str, - int len); - -#endif /* SHA1_H */ diff --git a/update-manager/fota/fota-client-controller.c b/update-manager/fota/fota-client-controller.c index 9b2addf..b7b744a 100644 --- a/update-manager/fota/fota-client-controller.c +++ b/update-manager/fota/fota-client-controller.c @@ -1,4 +1,4 @@ -#include "../common/common.h" +#include "../base/base.h" #include "fota-manager.h" #define FOTA_CLIENT_APP_CTRL_PLUG_KEY "fota-plug" @@ -27,14 +27,14 @@ int fota_client_controller_process_event() return 1; } - if (!common_boot_status_checker_is_success()) { + if (!base_boot_status_checker_is_success()) { _FLOGI("Failed to launch fota client, user session is unset"); return 2; } for(idx = 0; idx < FOTA_EVENT_SIZE; ++idx) { if (fota_event_values[idx] != NULL) { - ret = common_client_controller_launch(appid, fota_event_keys[idx], fota_event_values[idx]); + ret = base_client_controller_launch(appid, fota_event_keys[idx], fota_event_values[idx]); if (ret < 0) { _FLOGE("Failed to launch fota client : %d, appid: %s, key : %s, value : %s", ret, appid, fota_event_keys[idx], fota_event_values[idx]); diff --git a/update-manager/fota/fota-client-info-checker.c b/update-manager/fota/fota-client-info-checker.c index 9e98cc3..6fb4893 100644 --- a/update-manager/fota/fota-client-info-checker.c +++ b/update-manager/fota/fota-client-info-checker.c @@ -1,4 +1,4 @@ -#include "../common/common.h" +#include "../base/base.h" #include "fota-manager.h" #define FOTA_CLIENT_METADATA_KEY "tizen-fota-manager" @@ -15,7 +15,7 @@ int fota_client_info_checker_callback(pkgmgrinfo_appinfo_h handle, void *user_da { int ret = 0; - ret = common_client_info_checker_get_appid(handle, &fota_client_app_id); + ret = base_client_info_checker_get_appid(handle, &fota_client_app_id); if (ret < 0) { _FLOGE("Failed to get fota app id from handle : %d", ret); return -1; @@ -33,7 +33,7 @@ int fota_client_info_checker_init() { int ret = 0; - ret = common_client_info_checker_filter(FOTA_CLIENT_METADATA_KEY, FOTA_CLIENT_METADATA_VALUE, fota_client_info_checker_callback); + ret = base_client_info_checker_filter(FOTA_CLIENT_METADATA_KEY, FOTA_CLIENT_METADATA_VALUE, fota_client_info_checker_callback); if (ret < 0) { _FLOGE("Failed to set fota client app filter : %d, key : %s, value : %s", ret, FOTA_CLIENT_METADATA_KEY, FOTA_CLIENT_METADATA_VALUE); diff --git a/update-manager/fota/fota-common.c b/update-manager/fota/fota-common.c index ab0d5c3..0fa147c 100644 --- a/update-manager/fota/fota-common.c +++ b/update-manager/fota/fota-common.c @@ -14,7 +14,8 @@ * limitations under the License. */ -#include "common/common.h" +#include "base/base.h" +#include "utils/utils.h" #include "fota-manager.h" int check_is_delta_appropriate(const char *delta_path, const char *delta_with_tools_path, bool *checksum_available) diff --git a/update-manager/fota/fota-dbus-manager.c b/update-manager/fota/fota-dbus-manager.c new file mode 100644 index 0000000..3b9d491 --- /dev/null +++ b/update-manager/fota/fota-dbus-manager.c @@ -0,0 +1,222 @@ +#include +#include "../base/base.h" +#include "../fota/fota-manager.h" +#include "update-manager-dbus.h" + +static guint owner_id; + +typedef enum { + RO_UPDATE, + FINISH, + RO_UPDATE_AND_FINISH, +} dbus_handler_action; + +typedef struct _dbus_handler_arg { + dbus_handler_action action; + OrgTizenUpdateManager *skeleton; + GDBusMethodInvocation *invocation; +} dbus_handler_arg; + +static pid_t dbus_get_sender_pid(GDBusMethodInvocation *invocation) +{ + const gchar *sender = g_dbus_method_invocation_get_sender(invocation); + GDBusConnection *conn = g_dbus_method_invocation_get_connection(invocation); + if (sender == NULL || conn == NULL) { + _FLOGW("Failed to get invocation data"); + return 0; + } + GError *error = NULL; + GVariant *result = g_dbus_connection_call_sync(conn, + "org.freedesktop.DBus", + "/", + "org.freedesktop.DBus", + "GetConnectionUnixProcessID", + g_variant_new("(s)", sender), + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (!result || error) { + _FLOGW("Failed to get sender PID: %s", error ? error->message : ""); + g_error_free(error); + return 0; + } + + pid_t pid; + g_variant_get(result, "(u)", &pid); + g_variant_unref(result); + return pid; +} + +void *dbus_call_handler(void *arg) +{ + int ret = 0; + pid_t pid = 0; + dbus_handler_arg *handler_arg = (dbus_handler_arg *) arg; + + if (handler_arg->action != FINISH) + pid = dbus_get_sender_pid(handler_arg->invocation); + + switch (handler_arg->action) { + case RO_UPDATE: + ret = fota_installer_ro_update(pid); + if (ret < 0) + _FLOGW("Failed to perform : %d", ret); + org_tizen_update_manager_complete_ro_update(handler_arg->skeleton, handler_arg->invocation, ret); + break; + case FINISH: + ret = fota_installer_finish_update(); + if (ret < 0) + _FLOGW("Failed to perform : %d", ret); + org_tizen_update_manager_complete_finish_update(handler_arg->skeleton, handler_arg->invocation, ret); + break; + case RO_UPDATE_AND_FINISH: + ret = fota_installer_ro_update_and_finish_update(pid); + if (ret < 0) + _FLOGW("Failed to perform : %d", ret); + org_tizen_update_manager_complete_ro_update_and_finish_update(handler_arg->skeleton, handler_arg->invocation, ret); + break; + } + + free(arg); + g_thread_exit(0); +} + +gboolean dbus_manager_ro_update(OrgTizenUpdateManager *skeleton, GDBusMethodInvocation *invocation) +{ + _FLOGD("Dbus status: called"); + dbus_handler_arg *arg = (dbus_handler_arg *)malloc(sizeof(dbus_handler_arg)); + if (!arg) { + _FLOGE("Failed to malloc"); + goto fail; + } + + arg->action = RO_UPDATE; + arg->skeleton = skeleton; + arg->invocation = invocation; + + GError *error = NULL; + GThread *thread = g_thread_try_new(NULL, (GThreadFunc)dbus_call_handler, (void *)arg, &error); + if (error != NULL) { + _FLOGE("Failed to create thread: %s", error->message); + goto fail; + } + + g_thread_unref(thread); + + return TRUE; + +fail: + if (arg) + free(arg); + + org_tizen_update_manager_complete_ro_update(skeleton, invocation, -1); + return TRUE; +} + +gboolean dbus_manager_finish_update(OrgTizenUpdateManager *skeleton, GDBusMethodInvocation *invocation) +{ + _FLOGD("Dbus status: called"); + dbus_handler_arg *arg = (dbus_handler_arg *)malloc(sizeof(dbus_handler_arg)); + if (!arg) { + _FLOGE("Failed to malloc"); + goto fail; + } + + arg->action = FINISH; + arg->skeleton = skeleton; + arg->invocation = invocation; + + GError *error = NULL; + GThread *thread = g_thread_try_new(NULL, (GThreadFunc)dbus_call_handler, (void *)arg, &error); + if (error != NULL) { + _FLOGE("Failed to create thread: %s", error->message); + goto fail; + } + + g_thread_unref(thread); + + return TRUE; + +fail: + if (arg) + free(arg); + + org_tizen_update_manager_complete_finish_update(skeleton, invocation, -1); + return TRUE; +} + +/* + * This is not supposed to be called asynchronously, so this doesn't need a separate thread. + * This new thread is only for consistency with functions above. + */ +gboolean dbus_manager_ro_update_and_finish_update(OrgTizenUpdateManager *skeleton, GDBusMethodInvocation *invocation) +{ + _FLOGD("Dbus status: called"); + dbus_handler_arg *arg = (dbus_handler_arg *)malloc(sizeof(dbus_handler_arg)); + if (!arg) { + _FLOGE("Failed to malloc"); + goto fail; + } + + arg->action = RO_UPDATE_AND_FINISH; + arg->skeleton = skeleton; + arg->invocation = invocation; + + GError *error = NULL; + GThread *thread = g_thread_try_new(NULL, (GThreadFunc)dbus_call_handler, (void *)arg, &error); + if (error != NULL) { + _FLOGE("Failed to create thread: %s", error->message); + goto fail; + } + + g_thread_unref(thread); + + return TRUE; + +fail: + if (arg) + free(arg); + + org_tizen_update_manager_complete_ro_update_and_finish_update(skeleton, invocation, -1); + return TRUE; +} + +void dbus_manager_on_name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data) +{ + _CLOGD("Dbus status: name lost"); +} + +void dbus_manager_on_name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data) +{ + _CLOGD("Dbus status: name acquired"); + + OrgTizenUpdateManager *skeleton = org_tizen_update_manager_skeleton_new(); + + g_signal_connect(skeleton, "handle-ro-update", G_CALLBACK(dbus_manager_ro_update), NULL); + g_signal_connect(skeleton, "handle-finish-update", G_CALLBACK(dbus_manager_finish_update), NULL); + g_signal_connect(skeleton, "handle-ro-update-and-finish-update", G_CALLBACK(dbus_manager_ro_update_and_finish_update), NULL); + + g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(skeleton), connection, DBUS_NODE_NAME, NULL); +} + +void dbus_manager_on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data) +{ + _CLOGD("Dbus status: bus acquired"); +} + +int dbus_manager_init() +{ + owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM, DBUS_INTERFACE_NAME, G_BUS_NAME_OWNER_FLAGS_NONE, + dbus_manager_on_bus_acquired, dbus_manager_on_name_acquired, dbus_manager_on_name_lost, NULL, NULL); + + return 0; +} + +int dbus_manager_fini() +{ + g_bus_unown_name(owner_id); + + return 0; +} diff --git a/update-manager/fota/fota-installer.c b/update-manager/fota/fota-installer.c index 7b4cd3d..8649725 100644 --- a/update-manager/fota/fota-installer.c +++ b/update-manager/fota/fota-installer.c @@ -5,7 +5,8 @@ #include -#include "../common/common.h" +#include "../base/base.h" +#include "../utils/utils.h" #include "fota-manager.h" #define APP_SHARED_DIR "/opt/usr/home/owner/apps_rw" diff --git a/update-manager/fota/fota-manager.h b/update-manager/fota/fota-manager.h index b25efb8..de647b2 100644 --- a/update-manager/fota/fota-manager.h +++ b/update-manager/fota/fota-manager.h @@ -65,4 +65,8 @@ void fota_storage_checker_unplug(int, const char *); int check_is_delta_appropriate(const char *delta_path, const char *delta_with_tools_path, bool *checksum_available); bool check_delta_exist(const char *base_dir, struct deltas *deltas); +int dbus_manager_init(void); +int dbus_manager_fini(void); + + #endif /* __FOTA_MANAGER_H__ */ diff --git a/update-manager/fota/fota-storage-checker.c b/update-manager/fota/fota-storage-checker.c index d60b31d..a7ce628 100644 --- a/update-manager/fota/fota-storage-checker.c +++ b/update-manager/fota/fota-storage-checker.c @@ -1,4 +1,5 @@ -#include "../common/common.h" +#include "../base/base.h" +#include "../utils/utils.h" #include "fota-manager.h" static int fota_storage_id = -1; diff --git a/update-manager/main.c b/update-manager/main.c index 5fc60a8..92b7dfb 100644 --- a/update-manager/main.c +++ b/update-manager/main.c @@ -1,3 +1,4 @@ +#include "base/base.h" #include "common/common.h" #include "recovery/recovery-manager.h" #include "fota/fota-manager.h" diff --git a/update-manager/recovery/recovery-client-controller.c b/update-manager/recovery/recovery-client-controller.c index b2c07a4..1fb5d95 100644 --- a/update-manager/recovery/recovery-client-controller.c +++ b/update-manager/recovery/recovery-client-controller.c @@ -1,4 +1,4 @@ -#include "../common/common.h" +#include "../base/base.h" #include "recovery-manager.h" #define RECOVERY_CLIENT_APP_CTRL_PLUG_KEY "recovery-plug" @@ -24,14 +24,14 @@ int recovery_client_controller_process_event() return 1; } - if (!common_boot_status_checker_is_success()) { + if (!base_boot_status_checker_is_success()) { _RLOGI("Failed to launch recovery client, user session is unset"); return 2; } for(idx = 0; idx < RECOVERY_EVENT_SIZE; ++idx) { if (recovery_event_values[idx] != NULL) { - ret = common_client_controller_launch(appid, recovery_event_keys[idx], recovery_event_values[idx]); + ret = base_client_controller_launch(appid, recovery_event_keys[idx], recovery_event_values[idx]); if (ret < 0) { _RLOGE("Failed to launch recovery client : %d, appid: %s, key : %s, value : %s", ret, appid, recovery_event_keys[idx], recovery_event_values[idx]); @@ -86,4 +86,4 @@ int recovery_client_controller_add_event(recovery_event_idx idx, const char *val } return 0; -} \ No newline at end of file +} diff --git a/update-manager/recovery/recovery-client-info-checker.c b/update-manager/recovery/recovery-client-info-checker.c index f6aed75..d7e5624 100644 --- a/update-manager/recovery/recovery-client-info-checker.c +++ b/update-manager/recovery/recovery-client-info-checker.c @@ -1,4 +1,4 @@ -#include "../common/common.h" +#include "../base/base.h" #include "recovery-manager.h" #define RECOVERY_CLIENT_METADATA_KEY "tizen-recovery-manager" @@ -15,7 +15,7 @@ int recovery_client_info_checker_callback(pkgmgrinfo_appinfo_h handle, void *use { int ret = 0; - ret = common_client_info_checker_get_appid(handle, &recovery_client_app_id); + ret = base_client_info_checker_get_appid(handle, &recovery_client_app_id); if (ret < 0) { _RLOGE("Failed to get recovery app id from handle : %d", ret); return -1; @@ -35,7 +35,7 @@ int recovery_client_info_checker_init() { int ret = 0; - ret = common_client_info_checker_filter(RECOVERY_CLIENT_METADATA_KEY, RECOVERY_CLIENT_METADATA_VALUE, recovery_client_info_checker_callback); + ret = base_client_info_checker_filter(RECOVERY_CLIENT_METADATA_KEY, RECOVERY_CLIENT_METADATA_VALUE, recovery_client_info_checker_callback); if (ret < 0) { _RLOGE("Failed to set recovery client app filter : %d, key : %s, value : %s", ret, RECOVERY_CLIENT_METADATA_KEY, RECOVERY_CLIENT_METADATA_VALUE); diff --git a/update-manager/recovery/recovery-storage-checker.c b/update-manager/recovery/recovery-storage-checker.c index d2e6c23..c11cc5b 100644 --- a/update-manager/recovery/recovery-storage-checker.c +++ b/update-manager/recovery/recovery-storage-checker.c @@ -1,4 +1,4 @@ -#include "../common/common.h" +#include "../base/base.h" #include "recovery-manager.h" static int recovery_storage_id = -1; diff --git a/update-manager/utils/sha1.c b/update-manager/utils/sha1.c new file mode 100644 index 0000000..dafcf6f --- /dev/null +++ b/update-manager/utils/sha1.c @@ -0,0 +1,298 @@ +/* +SHA-1 in C +By Steve Reid +100% Public Domain + +Test Vectors (from FIPS PUB 180-1) +"abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */ +/* #define SHA1HANDSOFF * Copies data before messing with it. */ + +#define SHA1HANDSOFF + +#include +#include +#include + +/* for uint32_t */ +#include + +#include "sha1.h" + + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#elif BYTE_ORDER == BIG_ENDIAN +#define blk0(i) block->l[i] +#else +#error "Endianness not defined!" +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void SHA1Transform( + uint32_t state[5], + const unsigned char buffer[64] +) +{ + uint32_t a, b, c, d, e; + + typedef union + { + unsigned char c[64]; + uint32_t l[16]; + } CHAR64LONG16; + +#ifdef SHA1HANDSOFF + CHAR64LONG16 block[1]; /* use array to appear as a pointer */ + + memcpy(block, buffer, 64); +#else + /* The following had better never be used because it causes the + * pointer-to-const buffer to be cast into a pointer to non-const. + * And the result is written through. I threw a "const" in, hoping + * this will cause a diagnostic. + */ + CHAR64LONG16 *block = (const CHAR64LONG16 *) buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a, b, c, d, e, 0); + R0(e, a, b, c, d, 1); + R0(d, e, a, b, c, 2); + R0(c, d, e, a, b, 3); + R0(b, c, d, e, a, 4); + R0(a, b, c, d, e, 5); + R0(e, a, b, c, d, 6); + R0(d, e, a, b, c, 7); + R0(c, d, e, a, b, 8); + R0(b, c, d, e, a, 9); + R0(a, b, c, d, e, 10); + R0(e, a, b, c, d, 11); + R0(d, e, a, b, c, 12); + R0(c, d, e, a, b, 13); + R0(b, c, d, e, a, 14); + R0(a, b, c, d, e, 15); + R1(e, a, b, c, d, 16); + R1(d, e, a, b, c, 17); + R1(c, d, e, a, b, 18); + R1(b, c, d, e, a, 19); + R2(a, b, c, d, e, 20); + R2(e, a, b, c, d, 21); + R2(d, e, a, b, c, 22); + R2(c, d, e, a, b, 23); + R2(b, c, d, e, a, 24); + R2(a, b, c, d, e, 25); + R2(e, a, b, c, d, 26); + R2(d, e, a, b, c, 27); + R2(c, d, e, a, b, 28); + R2(b, c, d, e, a, 29); + R2(a, b, c, d, e, 30); + R2(e, a, b, c, d, 31); + R2(d, e, a, b, c, 32); + R2(c, d, e, a, b, 33); + R2(b, c, d, e, a, 34); + R2(a, b, c, d, e, 35); + R2(e, a, b, c, d, 36); + R2(d, e, a, b, c, 37); + R2(c, d, e, a, b, 38); + R2(b, c, d, e, a, 39); + R3(a, b, c, d, e, 40); + R3(e, a, b, c, d, 41); + R3(d, e, a, b, c, 42); + R3(c, d, e, a, b, 43); + R3(b, c, d, e, a, 44); + R3(a, b, c, d, e, 45); + R3(e, a, b, c, d, 46); + R3(d, e, a, b, c, 47); + R3(c, d, e, a, b, 48); + R3(b, c, d, e, a, 49); + R3(a, b, c, d, e, 50); + R3(e, a, b, c, d, 51); + R3(d, e, a, b, c, 52); + R3(c, d, e, a, b, 53); + R3(b, c, d, e, a, 54); + R3(a, b, c, d, e, 55); + R3(e, a, b, c, d, 56); + R3(d, e, a, b, c, 57); + R3(c, d, e, a, b, 58); + R3(b, c, d, e, a, 59); + R4(a, b, c, d, e, 60); + R4(e, a, b, c, d, 61); + R4(d, e, a, b, c, 62); + R4(c, d, e, a, b, 63); + R4(b, c, d, e, a, 64); + R4(a, b, c, d, e, 65); + R4(e, a, b, c, d, 66); + R4(d, e, a, b, c, 67); + R4(c, d, e, a, b, 68); + R4(b, c, d, e, a, 69); + R4(a, b, c, d, e, 70); + R4(e, a, b, c, d, 71); + R4(d, e, a, b, c, 72); + R4(c, d, e, a, b, 73); + R4(b, c, d, e, a, 74); + R4(a, b, c, d, e, 75); + R4(e, a, b, c, d, 76); + R4(d, e, a, b, c, 77); + R4(c, d, e, a, b, 78); + R4(b, c, d, e, a, 79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +#ifdef SHA1HANDSOFF + memset(block, '\0', sizeof(block)); +#endif +} + + +/* SHA1Init - Initialize new context */ + +void SHA1Init( + SHA1_CTX * context +) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +void SHA1Update( + SHA1_CTX * context, + const unsigned char *data, + uint32_t len +) +{ + uint32_t i; + + uint32_t j; + + j = context->count[0]; + if ((context->count[0] += len << 3) < j) + context->count[1]++; + context->count[1] += (len >> 29); + j = (j >> 3) & 63; + if ((j + len) > 63) + { + memcpy(&context->buffer[j], data, (i = 64 - j)); + SHA1Transform(context->state, context->buffer); + for (; i + 63 < len; i += 64) + { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } + else + i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +} + + +/* Add padding and return the message digest. */ + +void SHA1Final( + unsigned char digest[20], + SHA1_CTX * context +) +{ + unsigned i; + + unsigned char finalcount[8]; + + unsigned char c; + +#if 0 /* untested "improvement" by DHR */ + /* Convert context->count to a sequence of bytes + * in finalcount. Second element first, but + * big-endian order within element. + * But we do it all backwards. + */ + unsigned char *fcp = &finalcount[8]; + + for (i = 0; i < 2; i++) + { + uint32_t t = context->count[i]; + + int j; + + for (j = 0; j < 4; t >>= 8, j++) + *--fcp = (unsigned char) t} +#else + for (i = 0; i < 8; i++) + { + finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ + } +#endif + c = 0200; + SHA1Update(context, &c, 1); + while ((context->count[0] & 504) != 448) + { + c = 0000; + SHA1Update(context, &c, 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + for (i = 0; i < 20; i++) + { + digest[i] = (unsigned char) + ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); + } + /* Wipe variables */ + memset(context, '\0', sizeof(*context)); + memset(&finalcount, '\0', sizeof(finalcount)); +} + +void SHA1( + char *hash_out, + const char *str, + int len) +{ + SHA1_CTX ctx; + unsigned int ii; + + assert(len >= 0); + + SHA1Init(&ctx); + for (ii=0; ii<(unsigned int)len; ii+=1) + SHA1Update(&ctx, (const unsigned char*)str + ii, 1); + SHA1Final((unsigned char *)hash_out, &ctx); +} + diff --git a/update-manager/utils/sha1.h b/update-manager/utils/sha1.h new file mode 100644 index 0000000..8ffba8a --- /dev/null +++ b/update-manager/utils/sha1.h @@ -0,0 +1,46 @@ +#ifndef SHA1_H +#define SHA1_H + +/* + SHA-1 in C + By Steve Reid + 100% Public Domain + */ + +#include "stdint.h" + +#define SHA1_LEN 20 + +typedef struct +{ + uint32_t state[5]; + uint32_t count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +void SHA1Transform( + uint32_t state[5], + const unsigned char buffer[64] + ); + +void SHA1Init( + SHA1_CTX * context + ); + +void SHA1Update( + SHA1_CTX * context, + const unsigned char *data, + uint32_t len + ); + +void SHA1Final( + unsigned char digest[20], + SHA1_CTX * context + ); + +void SHA1( + char *hash_out, + const char *str, + int len); + +#endif /* SHA1_H */ diff --git a/update-manager/utils/utils-tar.c b/update-manager/utils/utils-tar.c new file mode 100644 index 0000000..733192b --- /dev/null +++ b/update-manager/utils/utils-tar.c @@ -0,0 +1,180 @@ +#include "../base/base.h" + +#include +#include +#include +#include +#include + +// for the sake of simplicity this stays global +static gzFile gz_tar = NULL; + +int gzip_open(const char *pathname, int oflags, ...) +{ + if (gz_tar != NULL) { + errno = EALREADY; + return -1; + } + + // We assume oflags == O_RDONLY, since that's what we actually use. + // Also we don't care about the mode since we are lazy. + if (oflags != O_RDONLY) { + errno = ENOTSUP; + return -1; + } + + gz_tar = gzopen(pathname, "r"); + if (gz_tar == NULL) { + _CLOGE("gzopen() failed with errno: %d\n", errno); + return -1; + } + + return 1; +} + +int gzip_close(__attribute__((unused)) int useless_fd) +{ + if (gz_tar == NULL) { + errno = EINVAL; + return -1; + } + + int ret = gzclose(gz_tar); + if (ret != Z_OK) + _CLOGE("gzclose() failed with errno: %d\n", errno); + + return ret; +} + +ssize_t gzip_read(__attribute__((unused)) int useless_fd, void *buf, size_t len) +{ + if (gz_tar == NULL) { + errno = EINVAL; + return -1; + } + + int ret = gzread(gz_tar, buf, len); + if (ret <= 0) { + if (gzeof(gz_tar)) + _CLOGE("gzread() failed - EOF reached\n"); + else + _CLOGE("gzread() failed with error: %s\n", gzerror(gz_tar, NULL)); + } + + return ret; +} + +ssize_t gzip_write(__attribute__((unused)) int useless_fd, __attribute__((unused)) const void *buf, __attribute__((unused)) size_t len) +{ + // Again, we do not use this. + errno = ENOTSUP; + return -1; +} + +static int str_ends_with(const char *str, const char *suffix) +{ + size_t str_length = strlen(str); + size_t suffix_length = strlen(suffix); + + return ((str_length > suffix_length) && (memcmp(str + str_length - suffix_length, suffix, suffix_length + 1) == 0)); +} + +static int tar_get_tartype(const char *tar_path, tartype_t **type) +{ + static tartype_t gzip_type = {gzip_open, gzip_close, gzip_read, gzip_write}; + + if (str_ends_with(tar_path, ".tar")) { + *type = NULL; + } + else if (str_ends_with(tar_path, ".tar.gz")) { + *type = &gzip_type; + } + else if (str_ends_with(tar_path, ".tgz")) { + *type = &gzip_type; + } + else { + _CLOGE("Unknown/unsupported file extension for delta - %s\n", tar_path); + return -1; + } + + return 0; +} + +static int tar_init_with_type(TAR **tar, const char *tar_path, tartype_t *type) +{ + if (tar_open(tar, tar_path, type, O_RDONLY, 0, 0) < 0) { + *tar = NULL; + _CLOGE("tar_open() fail!\n"); + return -1; + } + + return 0; +} + +int util_file_untar(const char *tar_path, const char *dest_path, const char *extract_file_name) +{ + TAR *tar; + tartype_t *type; + DIR *dir; + + if (tar_get_tartype(tar_path, &type)) { + _CLOGE("tar_get_tartype() error!\n"); + return -1; + } + + dir = opendir(dest_path); + if (dir == NULL) { + _CLOGE("Directory %s could not be opened, errno: %d\n", dest_path, errno); + return -1; + } + closedir(dir); + + if (tar_init_with_type(&tar, tar_path, type)) { + _CLOGE("tar_init_with_type() error!\n"); + return -1; + } + + int ret = 0; + char extracted_file_path[MAX_BUFFER_SIZE]; + snprintf(extracted_file_path, MAX_BUFFER_SIZE, "%s/%s", dest_path, extract_file_name); + + for (;;) + { + switch (th_read(tar)) + { + case -1: + _CLOGE("th_read() fail!\n"); + ret = -1; + goto cleanup; + case 1: + _CLOGE("EOF reached - incorrect delta!\n"); + ret = -1; + goto cleanup; + case 0: + break; + } + + char *current_pathname = th_get_pathname(tar); + + if (strcmp(current_pathname, extract_file_name) == 0) { + if (tar_extract_file(tar, extracted_file_path) < 0) { + _CLOGE("tar_extract_file() fail!\n"); + ret = -1; + goto cleanup; + } + _CLOGI("%s successfully extracted from %s\n", extract_file_name, tar_path); + goto cleanup; + } + + if (TH_ISREG(tar) && (tar_skip_regfile(tar) < 0)) { + _CLOGE("tar_skip_regfile() fail!\n"); + ret = -1; + goto cleanup; + } + } + +cleanup: + tar_close(tar); + gz_tar = NULL; + return ret; +} diff --git a/update-manager/utils/utils.c b/update-manager/utils/utils.c new file mode 100644 index 0000000..20ce17c --- /dev/null +++ b/update-manager/utils/utils.c @@ -0,0 +1,208 @@ +#include +#include "utils.h" +#include "sha1.h" + +int util_file_mkdir(const char *path) +{ + int ret = 0; + gboolean exist = FALSE; + + exist = g_file_test(path, G_FILE_TEST_IS_DIR); + if (!exist) { + ret = mkdir(path, 0775); + if (ret < 0) { + _CLOGE("Failed to make %s : %m", path); + return -1; + } + } + + return 0; +} + +int util_file_remove(const char *path) +{ + int ret = 0; + gboolean exist = FALSE; + + exist = g_file_test(path, G_FILE_TEST_EXISTS); + if (exist) { + ret = remove(path); + if (ret < 0) { + _CLOGE("Failed to remove %s : %m", path); + return -1; + } + } + + return 0; +} + +int util_file_symlink(const char *target_path, const char *link_path) +{ + int ret = 0; + gboolean exist = FALSE; + + exist = g_file_test(target_path, G_FILE_TEST_EXISTS); + if (!exist) { + _CLOGE("Failed to find %s", target_path); + return -1; + } + + ret = util_file_remove(link_path); + if (ret < 0) + return -1; + + ret = symlink(target_path, link_path); + if (ret < 0) { + _CLOGE("Failed to symlink from %s to %s : %m", target_path, link_path); + return -1; + } + + return 0; +} + +int util_file_read_single_line(const char *path, char buf[]) +{ + int status = 0; + FILE *fp = NULL; + + fp = fopen(path, "r"); + if (fp != NULL) { + if (fgets(buf, MAX_BUFFER_SIZE, fp) == NULL) { + _CLOGE("Failed to read : %s", path); + status = -1; + } + fclose(fp); + } else { + _CLOGE("Failed to open : %s", path); + status = -1; + } + + return status; +} + +int util_file_write_line(const char *path, const char *msg) +{ + int ret = 0, status = 0; + FILE *fp = NULL; + + fp = fopen(path, "w"); + if (fp != NULL) { + ret = fprintf(fp, "%s", msg); + if (ret < 0) { + _CLOGE("Failed to write, path : %s, msg : %s", path, msg); + status = -1; + } + fclose(fp); + } else { + _CLOGE("Failed to open : %s", path); + status = -1; + } + + return status; +} + +static int read_checksum_for(const char *checksum_path, const char *file_name, char *sha1_hex, size_t sha1_hex_len) +{ + int result = -1; + + if (sha1_hex_len < (2 * SHA1_LEN + 1)) { + _CLOGE("Checksum buffer too small"); + return result; + } + + FILE *checksum_fp = fopen(checksum_path, "r"); + if (!checksum_fp) { + _CLOGE("Cannot open %s", checksum_path); + return result; + } + + char *line = NULL; + size_t line_len = 0; + + while (getline(&line, &line_len, checksum_fp) != -1) { + char *saveptr = NULL; + char *checksum = NULL; + char *checksum_fname = NULL; + + checksum = strtok_r(line, " \n", &saveptr); + + if (checksum == NULL) + continue; + + if (strlen(checksum) != (2 * SHA1_LEN)) + continue; + + checksum_fname = strtok_r(NULL, " \n", &saveptr); + + if (checksum_fname == NULL) + continue; + + if (strncmp(checksum_fname, file_name, strlen(file_name) + 1) == 0) { + strncpy(sha1_hex, checksum, sha1_hex_len - 1); + sha1_hex[sha1_hex_len - 1] = '\0'; + result = 0; + break; + } + } + + free(line); + fclose(checksum_fp); + return result; +} + +static int calculate_checksum(const char *file_path, char *sha1_hex, size_t sha1_hex_len) +{ + if (sha1_hex_len != (2 * SHA1_LEN + 1)) { + _CLOGE("Checksum buffer too small"); + return -1; + } + + int file_fd = open(file_path, O_RDONLY); + if (file_fd == -1) { + _CLOGE("Cannot open %s", file_path); + return -1; + } + + SHA1_CTX context; + SHA1Init(&context); + + unsigned char buf[1024]; + + int bytes; + while ((bytes = read(file_fd, buf, sizeof(buf))) > 0) + SHA1Update(&context, buf, bytes); + + close(file_fd); + + unsigned char sha1[SHA1_LEN * 2 + 1]; + SHA1Final(sha1, &context); + + const char HEX_DIGITS[] = "0123456789abcdef"; + + for (size_t i = 0; i < SHA1_LEN; i++) { + sha1_hex[2 * i] = HEX_DIGITS[sha1[i] / 16]; + sha1_hex[2 * i + 1] = HEX_DIGITS[sha1[i] % 16]; + } + sha1_hex[sha1_hex_len - 1] = '\0'; + return 0; +} + +int verify_checksum(const char *checksum_path, const char *file_path) +{ + char *file_name = rindex(file_path, '/'); + if (!file_name || ! ++file_name) { + _CLOGE("Cannot extract the file name from path"); + return -1; + } + + char sha1_from_file[SHA1_LEN * 2 + 1]; + char sha1_calculated[SHA1_LEN * 2 + 1]; + + if (read_checksum_for(checksum_path, file_name, sha1_from_file, sizeof(sha1_from_file)) != 0) + return -1; + + if (calculate_checksum(file_path, sha1_calculated, sizeof(sha1_calculated)) != 0) + return -1; + + return strncmp(sha1_from_file, sha1_calculated, sizeof(sha1_from_file)); +} diff --git a/update-manager/utils/utils.h b/update-manager/utils/utils.h new file mode 100644 index 0000000..72897c0 --- /dev/null +++ b/update-manager/utils/utils.h @@ -0,0 +1,19 @@ +#ifndef __UTILS_H__ +#define __UTILS_H__ + +#include +#include +#include +#include + +#include "../base/base.h" + +int util_file_mkdir(const char *); +int util_file_remove(const char *); +int util_file_symlink(const char *, const char *); +int util_file_read_single_line(const char *, char[]); +int util_file_write_line(const char *, const char *); +int util_file_untar(const char *, const char *, const char *); +int verify_checksum(const char *checksum_path, const char *file_path); + +#endif /* __UTILS_H__ */