From: jongmyeongko Date: Mon, 19 Dec 2016 14:10:32 +0000 (+0900) Subject: refactor getsize sync function X-Git-Tag: accepted/tizen/3.0/common/20161227.101249~1 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fappfw%2Fpkgmgr-server.git;a=commitdiff_plain;h=882d44fdc021c34c7f38e66ac2f9c311cf285128 refactor getsize sync function Submit with: https://review.tizen.org/gerrit/#/c/105817/ https://review.tizen.org/gerrit/#/c/105823/ https://review.tizen.org/gerrit/#/c/105825/ Change-Id: I2b5a17199324a1f0ee6a2bac0f5adf8d077283f8 Signed-off-by: jongmyeongko --- diff --git a/include/pkgmgr-server.h b/include/pkgmgr-server.h index 530ca0d..e22bfeb 100644 --- a/include/pkgmgr-server.h +++ b/include/pkgmgr-server.h @@ -65,6 +65,7 @@ enum request_type { REQUEST_TYPE_ENABLE_APP, REQUEST_TYPE_DISABLE_APP, REQUEST_TYPE_GETSIZE, + REQUEST_TYPE_GETSIZE_SYNC, REQUEST_TYPE_CLEARDATA, REQUEST_TYPE_CLEARCACHE, REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID, diff --git a/include/queue.h b/include/queue.h index 27fd907..d89d78c 100644 --- a/include/queue.h +++ b/include/queue.h @@ -20,6 +20,12 @@ #include +struct job_extra_info { + int getsize_fd; + char *getsize_fifo; + GIOChannel *getsize_io; +}; + struct backend_job { uid_t target_uid; uid_t caller_uid; @@ -31,6 +37,7 @@ struct backend_job { int backend_slot; char *backend_type; char *backend_path; + struct job_extra_info *extra; }; int _is_queue_empty(int pos); @@ -41,5 +48,6 @@ struct backend_job *_pop_queue(int pos); void _free_backend_job(struct backend_job *job); int _init_backend_queue(void); void _fini_backend_queue(void); +void __free_extra_info(struct backend_job *job); #endif // _QUEUE_H_ diff --git a/org.tizen.pkgmgr.conf b/org.tizen.pkgmgr.conf index e94bf6c..7ad7a4b 100644 --- a/org.tizen.pkgmgr.conf +++ b/org.tizen.pkgmgr.conf @@ -25,6 +25,7 @@ + diff --git a/src/pkgmgr-server.c b/src/pkgmgr-server.c index c3d33d1..d390f90 100644 --- a/src/pkgmgr-server.c +++ b/src/pkgmgr-server.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -59,6 +60,7 @@ #define EXT_STORAGE_APPDATA_GROUP 10002 #define MEDIA_STORAGE_GROUP 10502 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) +#define MAX_LONGLONG_LENGTH 32 typedef struct { char **env; @@ -89,7 +91,7 @@ static int pipe_sig[2]; static GIOChannel *pipe_io; static guint pipe_wid; static GHashTable *backend_info_table; -static GMainLoop *mainloop = NULL; +static GMainLoop *mainloop; static int __check_backend_status_for_exit(void); static int __check_queue_status_for_exit(void); @@ -116,6 +118,67 @@ static void __set_backend_free(int position) backend_busy = backend_busy & ~(1 << position); } +static gboolean getsize_io_handler(GIOChannel *io, GIOCondition cond, + gpointer data) +{ + GError *err = NULL; + GIOStatus s; + gsize len; + char buf[MAX_LONGLONG_LENGTH]; + long long result = 0; + struct backend_job *job = (struct backend_job *)data; + + s = g_io_channel_read_chars(io, (gchar *)buf, sizeof(buf), &len, &err); + if (s != G_IO_STATUS_NORMAL) { + ERR("getsize fd read failed: %s", err->message); + g_error_free(err); + result = -1; + } else { + if (strlen(buf) == 0) { + ERR("empty result"); + result = -1; + } else { + result = atoll(buf); + } + } + + _return_value_to_caller(job->req_id, g_variant_new("(ix)", + (result < 0) ? PKGMGR_R_ERROR : PKGMGR_R_OK, result)); + + unlink(job->extra->getsize_fifo); + free(job->extra->getsize_fifo); + job->extra->getsize_fifo = NULL; + + return FALSE; +} + +static int __setup_size_info_io(struct backend_job *job) +{ + guint getsize_wid; + + job->extra->getsize_fd = open(job->extra->getsize_fifo, + O_RDONLY | O_NONBLOCK); + if (job->extra->getsize_fd < 0) { + ERR("failed to open the fifo(%s), errno(%d)", + job->extra->getsize_fifo, errno); + return -1; + } + + job->extra->getsize_io = g_io_channel_unix_new(job->extra->getsize_fd); + if (!job->extra->getsize_io) + return -1; + g_io_channel_set_encoding(job->extra->getsize_io, NULL, NULL); + g_io_channel_set_buffered(job->extra->getsize_io, FALSE); + getsize_wid = g_io_add_watch(job->extra->getsize_io, + G_IO_IN, getsize_io_handler, job); + if (!getsize_wid) { + ERR("failed to add io watch"); + return -1; + } + + return 0; +} + static gboolean pipe_io_handler(GIOChannel *io, GIOCondition cond, gpointer data) { @@ -151,6 +214,14 @@ static gboolean pipe_io_handler(GIOChannel *io, GIOCondition cond, DBG("backend[%s] exit", job->backend_type); } + if (job->extra) { + if (job->extra->getsize_fifo) { + ERR("invalid backend close"); + _return_value_to_caller(job->req_id, + g_variant_new("(ix)", PKGMGR_R_ERROR, -1)); + } + } + g_hash_table_remove(backend_info_table, (gconstpointer)info.pid); g_idle_add(queue_job, NULL); @@ -356,7 +427,7 @@ static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data) return 0; } -void free_user_context(user_ctx* ctx) +void free_user_context(user_ctx *ctx) { char **env = NULL; int i = 0; @@ -542,7 +613,7 @@ void __set_environment(gpointer user_data) static int __fork_and_exec_with_args(char **argv, uid_t uid) { - user_ctx* user_context; + user_ctx *user_context; GError *error = NULL; gboolean ret; int pid; @@ -559,6 +630,8 @@ static int __fork_and_exec_with_args(char **argv, uid_t uid) if (ret != TRUE) { ERR("Failed to excute backend: %s", error->message); g_error_free(error); + free_user_context(user_context); + return -1; } free_user_context(user_context); @@ -1033,6 +1106,59 @@ static int __process_getsize(struct backend_job *job) return pid; } +static int __process_getsize_sync(struct backend_job *job) +{ + static const char backend_cmd[] = "/usr/bin/pkg_getsize"; + char **argv; + char args[MAX_PKG_ARGS_LEN]; + char fifo_path[PATH_MAX]; + int pid; + + snprintf(fifo_path, sizeof(fifo_path), "/tmp/pkgmgr/%s", + job->req_id); + + job->extra = calloc(1, sizeof(struct job_extra_info)); + if (!job->extra) { + ERR("memory alloc failed"); + goto error; + } + + job->extra->getsize_fifo = strdup(fifo_path); + if (!job->extra->getsize_fifo) { + ERR("out of memory"); + goto error; + } + + if (mkfifo(job->extra->getsize_fifo, 0600) < 0) { + ERR("failed to mkfifo"); + goto error; + } + + snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d --sync", + backend_cmd, job->pkgid, job->args, job->caller_uid, + job->req_id, job->target_uid); + argv = __generate_argv(args); + pid = __fork_and_exec_with_args(argv, APPFW_UID); + + g_strfreev(argv); + + if (pid < 0) { + ERR("failed to execute backend"); + goto error; + } + if (__setup_size_info_io(job) < 0) { + ERR("failed to setup io handler"); + goto error; + } + + return pid; + +error: + _return_value_to_caller(job->req_id, + g_variant_new("(ix)", PKGMGR_R_ERROR, -1)); + return -1; +} + static int __process_cleardata(struct backend_job *job) { char *backend_cmd; @@ -1329,6 +1455,18 @@ static int __process_set_app_label(struct backend_job *job) return ret; } +static int __post_process(int ret, int x, struct backend_job *job) +{ + if (ret < 0) { + __set_backend_free(x); + _free_backend_job(job); + } else { + g_hash_table_insert(backend_info_table, (gpointer)ret, + (gpointer)job); + } + return 0; +} + gboolean queue_job(void *data) { struct backend_job *job = NULL; @@ -1372,56 +1510,41 @@ gboolean queue_job(void *data) case REQUEST_TYPE_INSTALL: __set_backend_busy(x); ret = __process_install(job); - g_hash_table_insert(backend_info_table, (gpointer)ret, - (gpointer)job); + __post_process(ret, x, job); break; case REQUEST_TYPE_MOUNT_INSTALL: __set_backend_busy(x); ret = __process_mount_install(job); - g_hash_table_insert(backend_info_table, (gpointer)ret, - (gpointer)job); + __post_process(ret, x, job); break; case REQUEST_TYPE_REINSTALL: __set_backend_busy(x); ret = __process_reinstall(job); - g_hash_table_insert(backend_info_table, (gpointer)ret, - (gpointer)job); + __post_process(ret, x, job); break; case REQUEST_TYPE_UNINSTALL: __set_backend_busy(x); ret = __process_uninstall(job); - g_hash_table_insert(backend_info_table, (gpointer)ret, - (gpointer)job); + __post_process(ret, x, job); break; case REQUEST_TYPE_MOVE: __set_backend_busy(x); ret = __process_move(job); - g_hash_table_insert(backend_info_table, (gpointer)ret, - (gpointer)job); + __post_process(ret, x, job); break; case REQUEST_TYPE_ENABLE_PKG: __set_backend_busy(x); ret = __process_enable_pkg(job); - if (ret == -1) { + if (ret < 0) _send_fail_signal(job); - __set_backend_free(x); - _free_backend_job(job); - } else { - g_hash_table_insert(backend_info_table, (gpointer)ret, - (gpointer)job); - } + __post_process(ret, x, job); break; case REQUEST_TYPE_DISABLE_PKG: __set_backend_busy(x); ret = __process_disable_pkg(job); - if (ret == -1) { + if (ret < 0) _send_fail_signal(job); - __set_backend_free(x); - _free_backend_job(job); - } else { - g_hash_table_insert(backend_info_table, (gpointer)ret, - (gpointer)job); - } + __post_process(ret, x, job); break; case REQUEST_TYPE_ENABLE_APP: ret = __process_enable_app(job); @@ -1434,20 +1557,24 @@ gboolean queue_job(void *data) case REQUEST_TYPE_GETSIZE: __set_backend_busy(x); ret = __process_getsize(job); - g_hash_table_insert(backend_info_table, (gpointer)ret, - (gpointer)job); + __post_process(ret, x, job); + break; + case REQUEST_TYPE_GETSIZE_SYNC: + __set_backend_busy(x); + ret = __process_getsize_sync(job); + if (ret < 0) + __free_extra_info(job); + __post_process(ret, x, job); break; case REQUEST_TYPE_CLEARDATA: __set_backend_busy(x); ret = __process_cleardata(job); - g_hash_table_insert(backend_info_table, (gpointer)ret, - (gpointer)job); + __post_process(ret, x, job); break; case REQUEST_TYPE_CLEARCACHE: __set_backend_busy(x); ret = __process_clearcache(job); - g_hash_table_insert(backend_info_table, (gpointer)ret, - (gpointer)job); + __post_process(ret, x, job); break; case REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID: ret = __process_enable_global_app_for_uid(job); diff --git a/src/queue.c b/src/queue.c index 11e6ace..68b0476 100644 --- a/src/queue.c +++ b/src/queue.c @@ -159,8 +159,25 @@ static gboolean __str_equal(gconstpointer v1, gconstpointer v2) return strcasecmp(str1, str2) == 0; } +void __free_extra_info(struct backend_job *job) +{ + if (job->extra) { + if (job->extra->getsize_io) + g_io_channel_unref(job->extra->getsize_io); + if (job->extra->getsize_fd) + close(job->extra->getsize_fd); + if (job->extra->getsize_fifo) { + unlink(job->extra->getsize_fifo); + free(job->extra->getsize_fifo); + } + free(job->extra); + job->extra = NULL; + } +} + void _free_backend_job(struct backend_job *job) { + __free_extra_info(job); free(job->req_id); free(job->pkgid); free(job->appid); diff --git a/src/request.c b/src/request.c index 4db0f6d..fce8210 100644 --- a/src/request.c +++ b/src/request.c @@ -97,6 +97,13 @@ static const char instropection_xml[] = " " " " " " + " " + " " + " " + " " + " " + " " + " " " " " " " " @@ -914,6 +921,45 @@ static int __handle_request_getsize(uid_t caller_uid, return 0; } +static int __handle_request_getsize_sync(uid_t caller_uid, + GDBusMethodInvocation *invocation, GVariant *parameters) +{ + uid_t target_uid = (uid_t)-1; + char *pkgid = NULL; + int get_type = -1; + char *reqkey; + char buf[4]; + + g_variant_get(parameters, "(u&si)", &target_uid, &pkgid, &get_type); + if (target_uid == (uid_t)-1 || pkgid == NULL || get_type == -1) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(is)", PKGMGR_R_ECOMM, "")); + return -1; + } + + reqkey = __generate_reqkey(pkgid); + if (reqkey == NULL) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(is)", PKGMGR_R_ENOMEM, "")); + return -1; + } + + snprintf(buf, sizeof(buf), "%d", get_type); + if (_push_queue(target_uid, caller_uid, reqkey, REQUEST_TYPE_GETSIZE_SYNC, + "pkgtool", pkgid, buf)) { + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(is)", PKGMGR_R_ESYSTEM, "")); + free(reqkey); + return -1; + } + + if (!g_hash_table_insert(req_table, (gpointer)reqkey, + (gpointer)invocation)) + ERR("reqkey already exists"); + + return 0; +} + static int __handle_request_cleardata(uid_t caller_uid, GDBusMethodInvocation *invocation, GVariant *parameters) { @@ -1442,6 +1488,8 @@ static void __handle_method_call(GDBusConnection *connection, ret = __handle_request_disable_pkgs(uid, invocation, parameters); else if (g_strcmp0(method_name, "getsize") == 0) ret = __handle_request_getsize(uid, invocation, parameters); + else if (g_strcmp0(method_name, "getsize_sync") == 0) + ret = __handle_request_getsize_sync(uid, invocation, parameters); else if (g_strcmp0(method_name, "clearcache") == 0) ret = __handle_request_clearcache(uid, invocation, parameters); else if (g_strcmp0(method_name, "enable_app") == 0)