Update coding convention & file-service added.
authorSung-jae Park <nicesj.park@samsung.com>
Tue, 13 Aug 2013 01:32:20 +0000 (10:32 +0900)
committerSung-jae Park <nicesj.park@samsung.com>
Tue, 13 Aug 2013 02:02:44 +0000 (11:02 +0900)
file_service is introduced. (not yet fully applied)

Change-Id: Ia2e94b1063e62a2b4f25feb78f945afa00d15b2e

CMakeLists.txt
include/file_service.h [new file with mode: 0644]
packaging/liblivebox-viewer.spec
src/client.c
src/critical_log.c
src/desc_parser.c
src/dlist.c
src/fb.c
src/file_service.c [new file with mode: 0644]

index 30e174f..90f8c1b 100644 (file)
@@ -54,6 +54,7 @@ ADD_LIBRARY(${PROJECT_NAME} SHARED
        src/master_rpc.c
        src/client.c
        src/critical_log.c
+       src/file_service.c
 )
 SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR})
 SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${VERSION})
diff --git a/include/file_service.h b/include/file_service.h
new file mode 100644 (file)
index 0000000..9212d03
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2013  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+extern int file_service_send_request(const char *filename, const char *save_to, void (*result_cb)(const char *filename, const char *save_to, int ret, void *data), void *data);
+extern int file_service_fini(void);
+extern int file_service_init(void);
+
+/* End of a file */
index d34f4bf..17f3f7a 100644 (file)
@@ -1,6 +1,6 @@
 Name: liblivebox-viewer
 Summary: Library for developing the application.
-Version: 0.14.0
+Version: 0.14.1
 Release: 1
 Group: HomeTF/Livebox
 License: Flora License
@@ -33,6 +33,11 @@ Livebox viewer development library (dev)
 %setup -q
 
 %build
+%if 0%{?tizen_build_binary_release_type_eng}
+export CFLAGS="${CFLAGS} -DTIZEN_ENGINEER_MODE"
+export CXXFLAGS="${CXXFLAGS} -DTIZEN_ENGINEER_MODE"
+export FFLAGS="${FFLAGS} -DTIZEN_ENGINEER_MODE"
+%endif
 %cmake .
 make %{?jobs:-j%jobs}
 
index bb6568e..b15757d 100644 (file)
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <string.h>
 #include <stdlib.h>
+#include <pthread.h>
 
 #include <dlog.h>
 #include <glib.h>
@@ -30,6 +31,7 @@
 #include <com-core.h>
 #include <com-core_packet.h>
 #include <livebox-errno.h>
+#include <secure_socket.h>
 
 #include "debug.h"
 #include "client.h"
@@ -41,6 +43,9 @@
 #include "master_rpc.h"
 #include "conf.h"
 #include "critical_log.h"
+#include "file_service.h"
+
+int errno;
 
 static struct info {
        int fd;
@@ -281,10 +286,11 @@ static struct packet *master_lb_update_begin(pid_t pid, int handle, const struct
                lb_set_lb_fb(handler, fbfile);
 
                ret = fb_sync(lb_get_lb_fb(handler));
-               if (ret != LB_STATUS_SUCCESS)
+               if (ret != LB_STATUS_SUCCESS) {
                        ErrPrint("Failed to do sync FB (%s - %s) (%d)\n", pkgname, fbfile, ret);
-               else
+               } else {
                        lb_invoke_event_handler(handler, LB_EVENT_LB_UPDATE_BEGIN);
+               }
        } else {
                ErrPrint("Invalid request[%s], %s\n", id, fbfile);
        }
@@ -322,10 +328,11 @@ static struct packet *master_pd_update_begin(pid_t pid, int handle, const struct
                lb_set_lb_fb(handler, fbfile);
 
                ret = fb_sync(lb_get_lb_fb(handler));
-               if (ret != LB_STATUS_SUCCESS)
+               if (ret != LB_STATUS_SUCCESS) {
                        ErrPrint("Failed to do sync FB (%s - %s) (%d)\n", pkgname, fbfile, ret);
-               else
+               } else {
                        lb_invoke_event_handler(handler, LB_EVENT_PD_UPDATE_BEGIN);
+               }
        } else {
                ErrPrint("Invalid request[%s], %s\n", id, fbfile);
        }
@@ -500,14 +507,16 @@ static struct packet *master_lb_updated(pid_t pid, int handle, const struct pack
        } else if (lb_get_lb_fb(handler)) {
                lb_set_lb_fb(handler, fbfile);
                ret = fb_sync(lb_get_lb_fb(handler));
-               if (ret != LB_STATUS_SUCCESS)
+               if (ret != LB_STATUS_SUCCESS) {
                        ErrPrint("Failed to do sync FB (%s - %s) (%d)\n", pkgname, util_basename(util_uri_to_path(id)), ret);
+               }
        } else {
                ret = LB_STATUS_SUCCESS;
        }
 
-       if (ret == LB_STATUS_SUCCESS)
+       if (ret == LB_STATUS_SUCCESS) {
                lb_invoke_event_handler(handler, LB_EVENT_LB_UPDATED);
+       }
 
 out:
        return NULL;
@@ -547,8 +556,9 @@ static struct packet *master_pd_created(pid_t pid, int handle, const struct pack
        } else {
                (void)lb_set_pd_fb(handler, buf_id);
                ret = fb_sync(lb_get_pd_fb(handler));
-               if (ret < 0)
+               if (ret < 0) {
                        ErrPrint("Failed to do sync FB (%s - %s)\n", pkgname, util_basename(util_uri_to_path(id)));
+               }
        }
 
        handler->is_pd_created = (status == 0);
@@ -674,10 +684,11 @@ static struct packet *master_pd_updated(pid_t pid, int handle, const struct pack
                (void)lb_set_pd_fb(handler, fbfile);
 
                ret = fb_sync(lb_get_pd_fb(handler));
-               if (ret < 0)
+               if (ret < 0) {
                        ErrPrint("Failed to do sync FB (%s - %s), %d\n", pkgname, util_basename(util_uri_to_path(id)), ret);
-               else
+               } else {
                        lb_invoke_event_handler(handler, LB_EVENT_PD_UPDATED);
+               }
        }
 
 out:
@@ -715,8 +726,9 @@ static struct packet *master_update_mode(pid_t pid, int handle, const struct pac
                goto out;
        }
 
-       if (status == LB_STATUS_SUCCESS)
+       if (status == LB_STATUS_SUCCESS) {
                lb_set_update_mode(handler, active_mode);
+       }
 
        if (handler->update_mode_cb) {
                ret_cb_t cb;
@@ -798,8 +810,9 @@ static struct packet *master_size_changed(pid_t pid, int handle, const struct pa
                                lb_set_lb_fb(handler, fbfile);
 
                                ret = fb_sync(lb_get_lb_fb(handler));
-                               if (ret < 0)
+                               if (ret < 0) {
                                        ErrPrint("Failed to do sync FB (%s - %s)\n", pkgname, util_basename(util_uri_to_path(id)));
+                               }
 
                                /* Just update the size info only. */
                        }
@@ -869,8 +882,9 @@ static struct packet *master_period_changed(pid_t pid, int handle, const struct
                goto out;
        }
 
-       if (status == 0)
+       if (status == 0) {
                lb_set_period(handler, period);
+       }
 
        if (handler->period_changed_cb) {
                ret_cb_t cb;
@@ -923,8 +937,9 @@ static struct packet *master_group_changed(pid_t pid, int handle, const struct p
                goto out;
        }
 
-       if (status == 0)
+       if (status == 0) {
                (void)lb_set_group(handler, cluster, category);
+       }
 
        if (handler->group_changed_cb) {
                ret_cb_t cb;
@@ -1057,12 +1072,14 @@ static struct packet *master_created(pid_t pid, int handle, const struct packet
                break;
        case _LB_TYPE_SCRIPT:
        case _LB_TYPE_BUFFER:
-               if (!strlen(lb_fname))
+               if (!strlen(lb_fname)) {
                        break;
+               }
                lb_set_lb_fb(handler, lb_fname);
                ret = fb_sync(lb_get_lb_fb(handler));
-               if (ret < 0)
+               if (ret < 0) {
                        ErrPrint("Failed to do sync FB (%s - %s)\n", pkgname, util_basename(util_uri_to_path(id)));
+               }
                break;
        case _LB_TYPE_TEXT:
                lb_set_text_lb(handler);
@@ -1077,13 +1094,15 @@ static struct packet *master_created(pid_t pid, int handle, const struct packet
        switch (pd_type) {
        case _PD_TYPE_SCRIPT:
        case _PD_TYPE_BUFFER:
-               if (!strlen(pd_fname))
+               if (!strlen(pd_fname)) {
                        break;
+               }
 
                lb_set_pd_fb(handler, pd_fname);
                ret = fb_sync(lb_get_pd_fb(handler));
-               if (ret < 0)
+               if (ret < 0) {
                        ErrPrint("Failed to do sync FB (%s - %s)\n", pkgname, util_basename(util_uri_to_path(id)));
+               }
                break;
        case _PD_TYPE_TEXT:
                lb_set_text_pd(handler);
@@ -1242,10 +1261,11 @@ static void acquire_cb(struct livebox *handler, const struct packet *result, voi
        } else {
                int ret;
 
-               if (packet_get(result, "i", &ret) != 1)
+               if (packet_get(result, "i", &ret) != 1) {
                        ErrPrint("Invalid argument\n");
-               else
+               } else {
                        DbgPrint("Acquire returns: %d\n", ret);
+               }
        }
 
        return;
@@ -1356,14 +1376,17 @@ int client_init(void)
                }
        }
 
+       (void)file_service_init();
+
        DbgPrint("Server Address: %s\n", s_info.client_addr);
 
        com_core_add_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
        com_core_add_event_callback(CONNECTOR_CONNECTED, connected_cb, NULL);
-       if (vconf_notify_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb, NULL) < 0)
+       if (vconf_notify_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb, NULL) < 0) {
                ErrPrint("Failed to add vconf for service state\n");
-       else
+       } else {
                DbgPrint("vconf event callback is registered\n");
+       }
 
        master_started_cb(NULL, NULL);
        return 0;
@@ -1382,13 +1405,20 @@ const char *client_addr(void)
 int client_fini(void)
 {
        int ret;
+
+       (void)file_service_fini();
+
        ret = vconf_ignore_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb);
-       if (ret < 0)
+       if (ret < 0) {
                DbgPrint("Ignore vconf key: %d\n", ret);
+       }
+
        com_core_del_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
        com_core_del_event_callback(CONNECTOR_CONNECTED, connected_cb, NULL);
        com_core_packet_client_fini(s_info.fd);
        s_info.fd = -1;
+       free(s_info.client_addr);
+       s_info.client_addr = NULL;
        return LB_STATUS_SUCCESS;
 }
 
index 02af5ac..07bb71d 100644 (file)
@@ -52,8 +52,9 @@ int critical_log(const char *func, int line, const char *fmt, ...)
        int ret;
        struct timeval tv;
 
-       if (!s_info.fp)
+       if (!s_info.fp) {
                return LB_STATUS_ERROR_IO;
+       }
 
        gettimeofday(&tv, NULL);
        fprintf(s_info.fp, "%d %lu.%lu [%s:%d] ", getpid(), tv.tv_sec, tv.tv_usec, util_basename((char *)func), line);
@@ -74,12 +75,16 @@ int critical_log(const char *func, int line, const char *fmt, ...)
                if (filename) {
                        snprintf(filename, namelen, "%s/%d_%s", SLAVE_LOG_PATH, s_info.file_id, s_info.filename);
 
-                       if (s_info.fp)
-                               fclose(s_info.fp);
+                       if (s_info.fp) {
+                               if (fclose(s_info.fp) != 0) {
+                                       ErrPrint("fclose: %s\n", strerror(errno));
+                               }
+                       }
 
                        s_info.fp = fopen(filename, "w+");
-                       if (!s_info.fp)
+                       if (!s_info.fp) {
                                ErrPrint("Failed to open a file: %s\n", filename);
+                       }
 
                        free(filename);
                }
@@ -96,8 +101,9 @@ int critical_log_init(const char *name)
        int namelen;
        char *filename;
 
-       if (s_info.fp)
+       if (s_info.fp) {
                return 0;
+       }
 
        s_info.filename = strdup(name);
        if (!s_info.filename) {
@@ -140,7 +146,9 @@ int critical_log_fini(void)
        }
 
        if (s_info.fp) {
-               fclose(s_info.fp);
+               if (fclose(s_info.fp) != 0) {
+                       ErrPrint("fclose: %s\n", strerror(errno));
+               }
                s_info.fp = NULL;
        }
 
index 8050a78..74fb887 100644 (file)
@@ -71,8 +71,9 @@ static int update_text(struct livebox *handle, struct block *block, int is_pd)
        }
 
        ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
-       if (ops->update_text)
+       if (ops->update_text) {
                ops->update_text(handle, (const char *)block->id, (const char *)block->part, (const char *)block->data);
+       }
 
        return 0;
 }
@@ -86,8 +87,9 @@ static int update_image(struct livebox *handle, struct block *block, int is_pd)
        }
 
        ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
-       if (ops->update_image)
+       if (ops->update_image) {
                ops->update_image(handle, block->id, block->part, block->data, block->option);
+       }
 
        return 0;
 }
@@ -101,8 +103,9 @@ static int update_script(struct livebox *handle, struct block *block, int is_pd)
        }
 
        ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
-       if (ops->update_script)
+       if (ops->update_script) {
                ops->update_script(handle, block->id, block->part, block->data, block->option);
+       }
 
        return 0;
 }
@@ -117,8 +120,9 @@ static int update_signal(struct livebox *handle, struct block *block, int is_pd)
        }
 
        ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
-       if (ops->update_signal)
+       if (ops->update_signal) {
                ops->update_signal(handle, block->id, block->data, block->part);
+       }
 
        return 0;
 }
@@ -140,8 +144,9 @@ static int update_drag(struct livebox *handle, struct block *block, int is_pd)
                return LB_STATUS_ERROR_INVALID;
        }
 
-       if (ops->update_drag)
+       if (ops->update_drag) {
                ops->update_drag(handle, block->id, block->part, dx, dy);
+       }
 
        return 0;
 }
@@ -165,12 +170,13 @@ static int update_info(struct livebox *handle, struct block *block, int is_pd)
                        return LB_STATUS_ERROR_INVALID;
                }
 
-               if (ops->update_info_size)
+               if (ops->update_info_size) {
                        ops->update_info_size(handle, block->id, w, h);
-
+               }
        } else if (!strcasecmp(block->part, INFO_CATEGORY)) {
-               if (ops->update_info_category)
+               if (ops->update_info_category) {
                        ops->update_info_category(handle, block->id, block->data);
+               }
        }
 
        return 0;
@@ -182,8 +188,9 @@ static inline int update_begin(struct livebox *handle, int is_pd)
 
        ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
 
-       if (ops->update_begin)
+       if (ops->update_begin) {
                ops->update_begin(handle);
+       }
 
        return 0;
 }
@@ -194,8 +201,9 @@ static inline int update_end(struct livebox *handle, int is_pd)
 
        ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
 
-       if (ops->update_end)
+       if (ops->update_end) {
                ops->update_end(handle);
+       }
 
        return 0;
 }
@@ -290,23 +298,29 @@ int parse_desc(struct livebox *handle, const char *descfile, int is_pd)
 
                        if (!isspace(ch)) {
                                update_end(handle, is_pd);
-                               fclose(fp);
+                               if (fclose(fp) != 0) {
+                                       ErrPrint("fclose: %s\n", strerror(errno));
+                               }
                                return LB_STATUS_ERROR_INVALID;
                        }
                        break;
 
                case BLOCK_OPEN:
-                       if (isblank(ch))
+                       if (isblank(ch)) {
                                break;
+                       }
 
-                       if (ch != '\n')
+                       if (ch != '\n') {
                                goto errout;
+                       }
 
                        block = calloc(1, sizeof(*block));
                        if (!block) {
                                CRITICAL_LOG("Heap: %s\n", strerror(errno));
                                update_end(handle, is_pd);
-                               fclose(fp);
+                               if (fclose(fp) != 0) {
+                                       ErrPrint("fclose: %s\n", strerror(errno));
+                               }
                                return LB_STATUS_ERROR_MEMORY;
                        }
 
@@ -316,8 +330,9 @@ int parse_desc(struct livebox *handle, const char *descfile, int is_pd)
                        break;
 
                case FIELD:
-                       if (isspace(ch))
+                       if (isspace(ch)) {
                                break;
+                       }
 
                        if (ch == '}') {
                                state = BLOCK_CLOSE;
@@ -325,8 +340,9 @@ int parse_desc(struct livebox *handle, const char *descfile, int is_pd)
                        }
 
                        if (ch == '=') {
-                               if (field_name[field_idx][idx] != '\0')
+                               if (field_name[field_idx][idx] != '\0') {
                                        goto errout;
+                               }
 
                                switch (field_idx) {
                                case 0:
@@ -390,17 +406,25 @@ int parse_desc(struct livebox *handle, const char *descfile, int is_pd)
                                break;
                        }
 
-                       if (ch == '\n')
+                       if (ch == '\n') {
                                goto errout;
+                       }
 
                        if (field_name[field_idx][idx] != ch) {
-                               ungetc(ch, fp);
-                               while (--idx >= 0)
-                                       ungetc(field_name[field_idx][idx], fp);
+                               if (ungetc(ch, fp) != ch) {
+                                       ErrPrint("ungetc: %s\n", strerror(errno));
+                               }
+
+                               while (--idx >= 0) {
+                                       if (ungetc(field_name[field_idx][idx], fp) != field_name[field_idx][idx]) {
+                                               ErrPrint("ungetc: %s\n", strerror(errno));
+                                       }
+                               }
 
                                field_idx++;
-                               if (field_name[field_idx] == NULL)
+                               if (field_name[field_idx] == NULL) {
                                        goto errout;
+                               }
 
                                idx = 0;
                                break;
@@ -542,8 +566,9 @@ int parse_desc(struct livebox *handle, const char *descfile, int is_pd)
                case BLOCK_CLOSE:
                        if (!block->file) {
                                block->file = strdup(util_uri_to_path(handle->id));
-                               if (!block->file)
+                               if (!block->file) {
                                        goto errout;
+                               }
                        }
 
                        i = 0;
@@ -555,8 +580,9 @@ int parse_desc(struct livebox *handle, const char *descfile, int is_pd)
                                i++;
                        }
 
-                       if (!handlers[i].type)
+                       if (!handlers[i].type) {
                                ErrPrint("Unknown block type: %s\n", block->type);
+                       }
 
                        free(block->file);
                        free(block->type);
@@ -575,12 +601,15 @@ int parse_desc(struct livebox *handle, const char *descfile, int is_pd)
                } /* switch */
        } /* while */
 
-       if (state != UNKNOWN)
+       if (state != UNKNOWN) {
                goto errout;
+       }
 
        update_end(handle, is_pd);
 
-       fclose(fp);
+       if (fclose(fp) != 0) {
+               ErrPrint("fclose: %s\n", strerror(errno));
+       }
        return 0;
 
 errout:
@@ -597,7 +626,9 @@ errout:
 
        update_end(handle, is_pd);
 
-       fclose(fp);
+       if (fclose(fp) != 0) {
+               ErrPrint("fclose: %s\n", strerror(errno));
+       }
        return LB_STATUS_ERROR_INVALID;
 }
 
index fa3082a..3ae571b 100644 (file)
@@ -45,8 +45,9 @@ struct dlist *dlist_append(struct dlist *list, void *data)
        struct dlist *item;
 
        item = malloc(sizeof(*item));
-       if (!item)
+       if (!item) {
                return NULL;
+       }
 
        item->next = NULL;
        item->data = data;
@@ -71,8 +72,9 @@ struct dlist *dlist_prepend(struct dlist *list, void *data)
        struct dlist *item;
 
        item = malloc(sizeof(*item));
-       if (!item)
+       if (!item) {
                return NULL;
+       }
 
        item->data = data;
 
@@ -80,8 +82,9 @@ struct dlist *dlist_prepend(struct dlist *list, void *data)
                item->prev = item;
                item->next = NULL;
        } else {
-               if (list->prev->next)
+               if (list->prev->next) {
                        list->prev->next = item;
+               }
 
                item->prev = list->prev;
                item->next = list;
@@ -95,16 +98,19 @@ struct dlist *dlist_prepend(struct dlist *list, void *data)
 
 struct dlist *dlist_remove(struct dlist *list, struct dlist *l)
 {
-       if (!list || !l)
+       if (!list || !l) {
                return NULL;
+       }
 
-       if (l == list)
+       if (l == list) {
                list = l->next;
-       else
+       } else {
                l->prev->next = l->next;
+       }
 
-       if (l->next)
+       if (l->next) {
                l->next->prev = l->prev;
+       }
        /*!
         * \note
         * If the removed entry 'l' has no next element, it is the last element.
@@ -113,8 +119,9 @@ struct dlist *dlist_remove(struct dlist *list, struct dlist *l)
         *
         * If we didn't care about this, the head element(list) can indicates the invalid element.
         */
-       else if (list)
+       else if (list) {
                list->prev = l->prev;
+       }
 
        free(l);
        return list;
@@ -126,8 +133,9 @@ struct dlist *dlist_find_data(struct dlist *list, void *data)
        void *_data;
 
        dlist_foreach(list, l, _data) {
-               if (data == _data)
+               if (data == _data) {
                        return l;
+               }
        }
 
        return NULL;
@@ -169,8 +177,9 @@ struct dlist *dlist_nth(struct dlist *l, int nth)
 
        i = 0;
        for (n = l; n; n = n->next) {
-               if (i == nth)
+               if (i == nth) {
                        return n;
+               }
                i++;
        }
 
index 62b3b25..89c19a4 100644 (file)
--- a/src/fb.c
+++ b/src/fb.c
@@ -113,8 +113,9 @@ static inline int sync_for_file(struct fb_info *info)
 
        buffer = info->buffer;
 
-       if (!buffer) /* Ignore this sync request */
+       if (!buffer) /* Ignore this sync request */
                return LB_STATUS_SUCCESS;
+       }
 
        if (buffer->state != CREATED) {
                ErrPrint("Invalid state of a FB\n");
@@ -143,7 +144,9 @@ static inline int sync_for_file(struct fb_info *info)
 
        if (read(fd, buffer->data, info->bufsz) != info->bufsz) {
                ErrPrint("read: %s\n", strerror(errno));
-               close(fd);
+               if (close(fd) < 0) {
+                       ErrPrint("close: %s\n", strerror(errno));
+               }
 
                /*!
                 * \note
@@ -155,7 +158,9 @@ static inline int sync_for_file(struct fb_info *info)
                return LB_STATUS_SUCCESS;
        }
 
-       close(fd);
+       if (close(fd) < 0) {
+               ErrPrint("close: %s\n", strerror(errno));
+       }
        return LB_STATUS_SUCCESS;
 }
 
@@ -166,8 +171,9 @@ static inline __attribute__((always_inline)) int sync_for_pixmap(struct fb_info
        XImage *xim;
 
        buffer = info->buffer;
-       if (!buffer) /*!< Ignore this sync request */
+       if (!buffer) /*!< Ignore this sync request */
                return LB_STATUS_SUCCESS;
+       }
 
        if (buffer->state != CREATED) {
                ErrPrint("Invalid state of a FB\n");
@@ -215,9 +221,9 @@ static inline __attribute__((always_inline)) int sync_for_pixmap(struct fb_info
        si.readOnly = False;
        si.shmaddr = shmat(si.shmid, NULL, 0);
        if (si.shmaddr == (void *)-1) {
-
-               if (shmctl(si.shmid, IPC_RMID, 0) < 0)
+               if (shmctl(si.shmid, IPC_RMID, 0) < 0) {
                        ErrPrint("shmctl: %s\n", strerror(errno));
+               }
 
                return LB_STATUS_ERROR_FAULT;
        }
@@ -231,11 +237,13 @@ static inline __attribute__((always_inline)) int sync_for_pixmap(struct fb_info
                                &si,
                                info->w, info->h);
        if (xim == NULL) {
-               if (shmdt(si.shmaddr) < 0)
+               if (shmdt(si.shmaddr) < 0) {
                        ErrPrint("shmdt: %s\n", strerror(errno));
+               }
 
-               if (shmctl(si.shmid, IPC_RMID, 0) < 0)
+               if (shmctl(si.shmid, IPC_RMID, 0) < 0) {
                        ErrPrint("shmctl: %s\n", strerror(errno));
+               }
 
                return LB_STATUS_ERROR_FAULT;
        }
@@ -251,11 +259,13 @@ static inline __attribute__((always_inline)) int sync_for_pixmap(struct fb_info
        XShmDetach(s_info.disp, &si);
        XDestroyImage(xim);
 
-       if (shmdt(si.shmaddr) < 0)
+       if (shmdt(si.shmaddr) < 0) {
                ErrPrint("shmdt: %s\n", strerror(errno));
+       }
 
-       if (shmctl(si.shmid, IPC_RMID, 0) < 0)
+       if (shmctl(si.shmid, IPC_RMID, 0) < 0) {
                ErrPrint("shmctl: %s\n", strerror(errno));
+       }
 
        return LB_STATUS_SUCCESS;
 }
@@ -472,8 +482,9 @@ int fb_release_buffer(void *data)
                        buffer->state = DESTROYED;
                        free(buffer);
                
-                       if (info && info->buffer == buffer)
+                       if (info && info->buffer == buffer) {
                                info->buffer = NULL;
+                       }
                }
                break;
        case BUFFER_TYPE_FILE:
@@ -485,8 +496,9 @@ int fb_release_buffer(void *data)
                        buffer->state = DESTROYED;
                        free(buffer);
 
-                       if (info && info->buffer == buffer)
+                       if (info && info->buffer == buffer) {
                                info->buffer = NULL;
+                       }
                }
                break;
        default:
@@ -503,8 +515,9 @@ int fb_refcnt(void *data)
        struct shmid_ds buf;
        int ret;
 
-       if (!data)
+       if (!data) {
                return LB_STATUS_ERROR_INVALID;
+       }
 
        buffer = container_of(data, struct buffer, data);
 
@@ -555,8 +568,9 @@ int fb_get_size(struct fb_info *info, int *w, int *h)
 
 int fb_size(struct fb_info *info)
 {
-       if (!info)
+       if (!info) {
                return 0;
+       }
 
        info->bufsz = info->w * info->h * s_info.depth;
        return info->bufsz;
diff --git a/src/file_service.c b/src/file_service.c
new file mode 100644 (file)
index 0000000..c72dc9c
--- /dev/null
@@ -0,0 +1,709 @@
+/*
+ * Copyright 2013  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <glib.h>
+
+#include <dlog.h>
+#include <secure_socket.h>
+#include <livebox-errno.h>
+
+#include "client.h"
+#include "debug.h"
+#include "dlist.h"
+
+#define FILE_SERVICE_PORT      8209
+
+#define CRITICAL_SECTION_BEGIN(handle) \
+do { \
+       int ret; \
+       ret = pthread_mutex_lock(handle); \
+       if (ret != 0) \
+               ErrPrint("Failed to lock: %s\n", strerror(ret)); \
+} while (0)
+
+#define CRITICAL_SECTION_END(handle) \
+do { \
+       int ret; \
+       ret = pthread_mutex_unlock(handle); \
+       if (ret != 0) \
+               ErrPrint("Failed to unlock: %s\n", strerror(ret)); \
+} while (0)
+
+#define CANCEL_SECTION_BEGIN() do { \
+       int ret; \
+       ret = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); \
+       if (ret != 0) \
+               ErrPrint("Unable to set cancelate state: %s\n", strerror(ret)); \
+} while (0)
+
+#define CANCEL_SECTION_END() do { \
+       int ret; \
+       ret = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); \
+       if (ret != 0) \
+               ErrPrint("Unable to set cancelate state: %s\n", strerror(ret)); \
+} while (0)
+
+#define CLOSE_PIPE(p)  do { \
+       int status; \
+       status = close(p[PIPE_READ]); \
+       if (status < 0) \
+               ErrPrint("close: %s\n", strerror(errno)); \
+       status = close(p[PIPE_WRITE]); \
+       if (status < 0) \
+               ErrPrint("close: %s\n", strerror(errno)); \
+} while (0)
+
+#define PIPE_READ 0
+#define PIPE_WRITE 1
+#define PIPE_MAX 2
+
+#define EVT_END_CH     'c'
+#define EVT_CH         'e'
+
+static struct {
+       pthread_t file_svc_thid;
+       pthread_mutex_t file_svc_lock;
+       int ctrl_pipe[PIPE_MAX];
+       int evt_pipe[PIPE_MAX];
+       struct dlist *request_list;
+       int file_service_fd;
+} s_info = {
+       .ctrl_pipe = { -1, -1 },
+       .evt_pipe = { -1, -1 },
+       .request_list = NULL,
+       .file_service_fd = -1,
+};
+
+struct request_item {
+       char *filename;
+       char *save_to;
+       void (*result_cb)(const char *filename, const char *save_to, int ret, void *data);
+       void *data;
+       int ret;
+};
+
+/*!
+ * File transfer header.
+ * This must should be shared with client.
+ */
+struct burst_head {
+       off_t size;
+       int flen;
+       char fname[];
+};
+
+struct burst_data {
+       int size;
+       char data[];
+};
+
+static inline int put_event_ch(int fd, char ch)
+{
+       int ret;
+
+       ret = write(fd, &ch, sizeof(ch));
+       if (ret != sizeof(ch)) {
+               ErrPrint("write: %s\n", strerror(errno));
+               return ret;
+       }
+
+       return 0;
+}
+
+static inline int get_event_ch(int fd)
+{
+       int ret;
+       char ch;
+
+       ret = read(fd, &ch, sizeof(ch));
+       if (ret != sizeof(ch)) {
+               ErrPrint("read: %s\n", strerror(errno));
+               return ret;
+       }
+
+       ret = (int)((unsigned int)ch);
+       return ret;
+}
+
+static inline int file_service_close(int fd)
+{
+       return secure_socket_destroy_handle(fd);
+}
+
+static inline int file_service_open(void)
+{
+       char *addr;
+       int port;
+       char *file_addr;
+       int len;
+       int fd;
+
+       addr = malloc(strlen(client_addr()) + 1);
+       if (!addr) {
+               ErrPrint("Heap: %s\n", strerror(errno));
+               return -ENOMEM;
+       }
+
+       if (sscanf(client_addr(), COM_CORE_REMOTE_SCHEME"%[^:]:%d", addr, &port) != 2) {
+               ErrPrint("Invalid URL\n");
+               free(addr);
+               return -EINVAL;
+       }
+
+       len = strlen(COM_CORE_REMOTE_SCHEME);
+       len+= strlen(addr);
+       len+= 6;        /* Port length? */
+
+       file_addr = malloc(len);
+       if (!file_addr) {
+               ErrPrint("Heap: %s\n", strerror(errno));
+               free(addr);
+               return -ENOMEM;
+       }
+
+       snprintf(file_addr, len, COM_CORE_REMOTE_SCHEME"%s:%d", addr, FILE_SERVICE_PORT);
+       DbgPrint("File service: %s\n", file_addr);
+       fd = secure_socket_create_client(file_addr);
+       free(file_addr);
+       free(addr);
+
+       return fd;
+}
+
+/*!
+ * Service Thread
+ */
+static void write_item_to_pipe(struct request_item *item, int ret)
+{
+       item->ret = LB_STATUS_ERROR_FAULT;
+       if (write(s_info.evt_pipe[PIPE_WRITE], &item, sizeof(item)) != sizeof(item)) {
+               ErrPrint("write: %s\n", strerror(errno));
+               free(item->filename);
+               free(item->save_to);
+               free(item);
+               item = NULL;
+       }
+}
+
+/*!
+ * Service Thread
+ */
+static void *file_service_main(void *data)
+{
+       int ret = 0;
+       int select_fd;
+       struct timeval tv;
+       fd_set set;
+       int offset;
+       enum {
+               RECV_INIT,
+               RECV_HEADER,
+               RECV_DATA,
+       } recv_state;
+       struct burst_head *head;
+       struct burst_data *body;
+       int recvsz;
+       struct request_item *item;
+       int file_offset;
+       int file_fd;
+
+       head = NULL;
+       item = NULL;
+       recv_state = RECV_INIT;
+       select_fd = (s_info.file_service_fd > s_info.ctrl_pipe[PIPE_READ] ? s_info.file_service_fd : s_info.ctrl_pipe[PIPE_READ]) + 1;
+       while (ret == 0) {
+               FD_ZERO(&set);
+               FD_SET(s_info.file_service_fd, &set);
+               FD_SET(s_info.ctrl_pipe[PIPE_READ], &set);
+
+               tv.tv_sec = 3;
+               tv.tv_usec = 0;
+               ret = select(select_fd , &set, NULL, NULL, &tv);
+               if (ret < 0) {
+                       ret = -errno;
+                       if (errno == EINTR) {
+                               ErrPrint("INTERRUPTED\n");
+                               ret = 0;
+                               continue;
+                       }
+                       ErrPrint("Error: %s\n", strerror(errno));
+                       break;
+               } else if (ret == 0) {
+                       ErrPrint("Timeout\n");
+                       ret = -ETIMEDOUT;
+                       break;
+               }
+
+               if (item && FD_ISSET(s_info.file_service_fd, &set)) {
+                       switch (recv_state) {
+                       case RECV_INIT:
+                               if (head == NULL) {
+                                       recvsz = sizeof(*head);
+
+                                       head = malloc(recvsz);
+                                       if (!head) {
+                                               ErrPrint("Heap: %s\n", strerror(errno));
+                                               ret = LB_STATUS_ERROR_MEMORY;
+                                               write_item_to_pipe(item, ret);
+                                               item = NULL;
+                                               break;
+                                       }
+
+                                       offset = 0;
+                                       recv_state = RECV_HEADER;
+                               }
+                       case RECV_HEADER:
+                               if (offset < recvsz) {
+                                       ret = secure_socket_recv(s_info.file_service_fd, (char *)head + offset, recvsz - offset, NULL);
+                                       if (ret > 0) {
+                                               offset += ret;
+                                       } else {
+                                               free(head);
+                                               head = NULL;
+                                               recv_state = RECV_INIT;
+                                               ret = LB_STATUS_ERROR_FAULT;
+                                               write_item_to_pipe(item, ret);
+                                               item = NULL;
+                                               break;
+                                       }
+                               }
+
+                               if (offset == sizeof(*head)) {
+                                       void *tmp;
+
+                                       recvsz += head->flen;
+
+                                       tmp = realloc(head, recvsz);
+                                       if (!tmp) {
+                                               ErrPrint("Heap: %s\n", strerror(errno));
+
+                                               free(head);
+                                               head = NULL;
+                                               recv_state = RECV_INIT;
+
+                                               ret = LB_STATUS_ERROR_MEMORY;
+                                               write_item_to_pipe(item, ret);
+                                               item = NULL;
+                                               break;
+                                       }
+
+                                       head = tmp;
+                               } else if (offset == recvsz) {
+                                       DbgPrint("Filesize: %d, name[%s]\n", head->size, head->fname);
+                                       if (strcmp(item->filename, head->fname)) {
+                                               ErrPrint("Invalid data sequence (%s <> %s)\n", item->filename, head->fname);
+
+                                               free(head);
+                                               head = NULL;
+                                               recv_state = RECV_INIT;
+                                               ret = LB_STATUS_ERROR_FAULT;
+                                               write_item_to_pipe(item, ret);
+                                               item = NULL;
+                                               break;
+                                       }
+
+                                       file_fd = open(item->save_to, O_WRONLY|O_CREAT, 0644);
+                                       if (file_fd < 0) {
+                                               ErrPrint("open: %s\n", strerror(errno));
+                                               free(head);
+                                               head = NULL;
+                                               recv_state = RECV_INIT;
+
+                                               ret = LB_STATUS_ERROR_IO;
+                                               write_item_to_pipe(item, ret);
+                                               item = NULL;
+                                               break;
+                                       }
+
+                                       recv_state = RECV_DATA;
+                                       body = NULL;
+
+                               } else {
+                                       ErrPrint("Invalid state\n");
+                                       free(head);
+                                       head = NULL;
+                                       recv_state = RECV_INIT;
+                                       ret = LB_STATUS_ERROR_INVALID;
+                                       write_item_to_pipe(item, ret);
+                                       item = NULL;
+                               }
+                               break;
+                       case RECV_DATA:
+                               if (!body) {
+                                       body = malloc(sizeof(*body));
+                                       if (!body) {
+                                               free(head);
+                                               head = NULL;
+                                               recv_state = RECV_INIT;
+                                               ret = LB_STATUS_ERROR_MEMORY;
+                                               write_item_to_pipe(item, ret);
+                                               item = NULL;
+                                               break;
+                                       }
+
+                                       recvsz = sizeof(*body);
+                                       offset = 0;
+                               }
+
+                               ret = secure_socket_recv(s_info.file_service_fd, (char *)body + offset, recvsz - offset, NULL);
+                               if (ret > 0) {
+                                       offset += ret;
+                               } else {
+                                       free(head);
+                                       head = NULL;
+                                       free(body);
+                                       body = NULL;
+                                       recv_state = RECV_INIT;
+                                       ret = LB_STATUS_ERROR_FAULT;
+                                       write_item_to_pipe(item, ret);
+                                       item = NULL;
+                                       break;
+                               }
+
+                               if (offset == sizeof(*body)) {
+                                       void *tmp;
+
+                                       if (body->size < 0) {
+                                               ErrPrint("body->size: %d\n", body->size);
+                                               free(head);
+                                               head = NULL;
+                                               free(body);
+                                               body = NULL;
+                                               recv_state = RECV_INIT;
+                                               ret = LB_STATUS_ERROR_FAULT;
+                                               write_item_to_pipe(item, ret);
+                                               item = NULL;
+                                               break;
+                                       }
+
+                                       recvsz += body->size;
+
+                                       tmp = realloc(body, recvsz);
+                                       if (!tmp) {
+                                               ErrPrint("Heap: %s\n", strerror(errno));
+                                               free(head);
+                                               head = NULL;
+
+                                               free(body);
+                                               body = NULL;
+                                               recv_state = RECV_INIT;
+
+                                               ret = LB_STATUS_ERROR_MEMORY;
+                                               write_item_to_pipe(item, ret);
+                                               item = NULL;
+                                               break;
+                                       }
+                               } else if (offset == recvsz) {
+                                       /* Flush this to the file */
+                                       ret = write(file_fd, body->data, body->size);
+                                       if (ret < 0) {
+                                               ErrPrint("write: %s\n", strerror(errno));
+                                               free(head);
+                                               head = NULL;
+
+                                               free(body);
+                                               body = NULL;
+                                               recv_state = RECV_INIT;
+
+                                               ret = LB_STATUS_ERROR_IO;
+                                               write_item_to_pipe(item, ret);
+                                               item = NULL;
+                                               break;
+                                       } else {
+                                               if (body->size != ret) {
+                                                       DbgPrint("Body is not flushed correctly: %d, %d\n", ret, body->size);
+                                                       ret = body->size;
+                                               }
+
+                                               file_offset += ret;
+                                               if (file_offset == head->size) {
+                                                       if (close(file_fd) < 0) {
+                                                               ErrPrint("close: %s\n", strerror(errno));
+                                                       }
+                                                       ret = LB_STATUS_SUCCESS;
+                                                       write_item_to_pipe(item, ret);
+                                                       item = NULL;
+                                               }
+                                       }
+
+                                       free(body);
+                                       body = NULL;
+
+                                       free(head);
+                                       head = NULL;
+
+                                       recv_state = RECV_INIT;
+                               } else {
+                                       ErrPrint("Invalid state\n");
+
+                                       ret = -EFAULT;
+                                       free(body);
+                                       body = NULL;
+                                       free(head);
+                                       head = NULL;
+                                       recv_state = RECV_INIT;
+
+                                       ret = LB_STATUS_ERROR_FAULT;
+                                       write_item_to_pipe(item, ret);
+                                       item = NULL;
+                               }
+                               break;
+                       default:
+                               ErrPrint("Unknown event: %d\n", recv_state);
+                               ret = LB_STATUS_ERROR_FAULT;
+                               write_item_to_pipe(item, ret);
+                               item = NULL;
+                               break;
+                       }
+               } else if (item == NULL && recv_state == RECV_INIT && FD_ISSET(s_info.ctrl_pipe[PIPE_READ], &set)) {
+                       int ch;
+                       struct dlist *l;
+
+                       /* Only if the recv state is not changed, we can get next request item */
+                       ch = get_event_ch(s_info.ctrl_pipe[PIPE_READ]);
+                       if (ch == EVT_END_CH) {
+                               DbgPrint("Service thread is canceled\n");
+                               break;
+                       }
+
+                       CRITICAL_SECTION_BEGIN(&s_info.file_svc_lock);
+                       l = dlist_nth(s_info.request_list, 0);
+                       item = dlist_data(l);
+                       s_info.request_list = dlist_remove(s_info.request_list, l);
+                       CRITICAL_SECTION_END(&s_info.file_svc_lock);
+               }
+       }
+
+       return (void *)ret;
+}
+
+/* Master */
+static gboolean evt_cb(GIOChannel *src, GIOCondition cond, gpointer data)
+{
+       int fd;
+       struct request_item *item;
+
+       fd = g_io_channel_unix_get_fd(src);
+
+       if (!(cond & G_IO_IN)) {
+               DbgPrint("Client is disconencted\n");
+               return FALSE;
+       }
+
+       if ((cond & G_IO_ERR) || (cond & G_IO_HUP) || (cond & G_IO_NVAL)) {
+               DbgPrint("Client connection is lost\n");
+               return FALSE;
+       }
+
+       if (read(fd, &item, sizeof(item)) != sizeof(item)) {
+               ErrPrint("read: %s\n", strerror(errno));
+       } else {
+               if (item->result_cb) {
+                       item->result_cb(item->filename, item->save_to, item->ret, item->data);
+               }
+
+               free(item->filename);
+               free(item->save_to);
+               free(item);
+       }
+
+       return TRUE;
+}
+
+int file_service_send_request(const char *filename, const char *save_to, void (*result_cb)(const char *filename, const char *save_to, int ret, void *data), void *data)
+{
+       struct request_item *item;
+
+       item = malloc(sizeof(*item));
+       if (!item) {
+               ErrPrint("Heap: %s\n", strerror(errno));
+               return -ENOMEM;
+       }
+
+       item->filename = strdup(filename);
+       if (!item->filename) {
+               ErrPrint("Heap: %s\n", strerror(errno));
+               free(item);
+               return -ENOMEM;
+       }
+
+       item->save_to = strdup(save_to);
+       if (!item->save_to) {
+               ErrPrint("Heap: %s\n", strerror(errno));
+               free(item->filename);
+               free(item);
+               return -ENOMEM;
+       }
+
+       item->result_cb = result_cb;
+       item->data = data;
+
+       CRITICAL_SECTION_BEGIN(&s_info.file_svc_lock);
+       s_info.request_list = dlist_append(s_info.request_list, item);
+       CRITICAL_SECTION_END(&s_info.file_svc_lock);
+       return 0;
+}
+
+int file_service_init(void)
+{
+       int status;
+       GIOChannel *gio;
+       guint id;
+
+       if (strncmp(client_addr(), COM_CORE_REMOTE_SCHEME, strlen(COM_CORE_REMOTE_SCHEME))) {
+               return 0;
+       }
+
+       s_info.file_service_fd = file_service_open();
+       if (s_info.file_service_fd < 0) {
+               return -EFAULT;
+       }
+
+       if (pipe2(s_info.ctrl_pipe, O_NONBLOCK | O_CLOEXEC) < 0) {
+               ErrPrint("file service: %s\n", strerror(errno));
+               file_service_close(s_info.file_service_fd);
+               s_info.file_service_fd = -1;
+               return -EFAULT;
+       }
+
+       if (pipe2(s_info.evt_pipe, O_NONBLOCK | O_CLOEXEC) < 0) {
+               ErrPrint("file service: %s\n", strerror(errno));
+               CLOSE_PIPE(s_info.ctrl_pipe);
+               file_service_close(s_info.file_service_fd);
+               s_info.file_service_fd = -1;
+               return -EFAULT;
+       }
+
+       status = pthread_mutex_init(&s_info.file_svc_lock, NULL);
+       if (status != 0) {
+               ErrPrint("Mutex: %s\n", strerror(status));
+               CLOSE_PIPE(s_info.ctrl_pipe);
+               CLOSE_PIPE(s_info.evt_pipe);
+               file_service_close(s_info.file_service_fd);
+               s_info.file_service_fd = -1;
+               return -EFAULT;
+       }
+
+       gio = g_io_channel_unix_new(s_info.evt_pipe[PIPE_READ]);
+       if (!gio) {
+               ErrPrint("io channel new\n");
+               status = pthread_mutex_destroy(&s_info.file_svc_lock);
+               if (status != 0) {
+                       ErrPrint("destroy: %s\n", strerror(status));
+               }
+               CLOSE_PIPE(s_info.ctrl_pipe);
+               CLOSE_PIPE(s_info.evt_pipe);
+               file_service_close(s_info.file_service_fd);
+               s_info.file_service_fd = -1;
+               return -EFAULT;
+       }
+
+       g_io_channel_set_close_on_unref(gio, FALSE);
+
+       id = g_io_add_watch(gio, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, (GIOFunc)evt_cb, NULL);
+       if (id <= 0) {
+               GError *err = NULL;
+               ErrPrint("Failed to add IO watch\n");
+               g_io_channel_shutdown(gio, TRUE, &err);
+               if (err) {
+                       ErrPrint("Shutdown: %s\n", err->message);
+                       g_error_free(err);
+               }
+               g_io_channel_unref(gio);
+
+               status = pthread_mutex_destroy(&s_info.file_svc_lock);
+               if (status != 0) {
+                       ErrPrint("destroy: %s\n", strerror(status));
+               }
+               CLOSE_PIPE(s_info.ctrl_pipe);
+               CLOSE_PIPE(s_info.evt_pipe);
+               file_service_close(s_info.file_service_fd);
+               s_info.file_service_fd = -1;
+               return -EIO;
+       }
+
+       status = pthread_create(&s_info.file_svc_thid, NULL, file_service_main, NULL);
+       if (status != 0) {
+               GError *err = NULL;
+               ErrPrint("Failed to add IO watch\n");
+               g_io_channel_shutdown(gio, TRUE, &err);
+               if (err) {
+                       ErrPrint("Shutdown: %s\n", err->message);
+                       g_error_free(err);
+               }
+               g_io_channel_unref(gio);
+
+               ErrPrint("file service: %s\n", strerror(status));
+               CLOSE_PIPE(s_info.ctrl_pipe);
+               CLOSE_PIPE(s_info.evt_pipe);
+               file_service_close(s_info.file_service_fd);
+               s_info.file_service_fd = -1;
+
+               status = pthread_mutex_destroy(&s_info.file_svc_lock);
+               if (status != 0) {
+                       ErrPrint("destroy: %s\n", strerror(status));
+               }
+
+               return -EFAULT;
+       }
+
+       g_io_channel_unref(gio);
+       return 0;
+}
+
+int file_service_fini(void)
+{
+       void *svc_ret;
+       int ret;
+
+       if (strncmp(client_addr(), COM_CORE_REMOTE_SCHEME, strlen(COM_CORE_REMOTE_SCHEME))) {
+               return 0;
+       }
+
+       (void)put_event_ch(s_info.ctrl_pipe[PIPE_WRITE], EVT_END_CH);
+
+       ret = pthread_join(s_info.file_svc_thid, &svc_ret);
+       if (ret != 0) {
+               ErrPrint("join: %s\n", strerror(ret));
+       } else {
+               DbgPrint("file svc returns: %d\n", (int)svc_ret);
+       }
+
+       ret = pthread_mutex_destroy(&s_info.file_svc_lock);
+       if (ret != 0) {
+               ErrPrint("destroy: %s\n", strerror(ret));
+       }
+
+       CLOSE_PIPE(s_info.evt_pipe);
+       CLOSE_PIPE(s_info.ctrl_pipe);
+
+       return 0;
+}
+
+/* End of a file */