From ee3bcebe6002c4fa09b9aaf7e147d5e16a8ca251 Mon Sep 17 00:00:00 2001 From: Sung-jae Park Date: Tue, 13 Aug 2013 10:32:20 +0900 Subject: [PATCH] Update coding convention & file-service added. file_service is introduced. (not yet fully applied) Change-Id: Ia2e94b1063e62a2b4f25feb78f945afa00d15b2e --- CMakeLists.txt | 1 + include/file_service.h | 21 ++ packaging/liblivebox-viewer.spec | 7 +- src/client.c | 74 ++-- src/critical_log.c | 20 +- src/desc_parser.c | 83 +++-- src/dlist.c | 29 +- src/fb.c | 42 ++- src/file_service.c | 709 +++++++++++++++++++++++++++++++++++++++ 9 files changed, 907 insertions(+), 79 deletions(-) create mode 100644 include/file_service.h create mode 100644 src/file_service.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 30e174f..90f8c1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 index 0000000..9212d03 --- /dev/null +++ b/include/file_service.h @@ -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 */ diff --git a/packaging/liblivebox-viewer.spec b/packaging/liblivebox-viewer.spec index d34f4bf..17f3f7a 100644 --- a/packaging/liblivebox-viewer.spec +++ b/packaging/liblivebox-viewer.spec @@ -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} diff --git a/src/client.c b/src/client.c index bb6568e..b15757d 100644 --- a/src/client.c +++ b/src/client.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -30,6 +31,7 @@ #include #include #include +#include #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; } diff --git a/src/critical_log.c b/src/critical_log.c index 02af5ac..07bb71d 100644 --- a/src/critical_log.c +++ b/src/critical_log.c @@ -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; } diff --git a/src/desc_parser.c b/src/desc_parser.c index 8050a78..74fb887 100644 --- a/src/desc_parser.c +++ b/src/desc_parser.c @@ -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; } diff --git a/src/dlist.c b/src/dlist.c index fa3082a..3ae571b 100644 --- a/src/dlist.c +++ b/src/dlist.c @@ -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++; } diff --git a/src/fb.c b/src/fb.c index 62b3b25..89c19a4 100644 --- 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 index 0000000..c72dc9c --- /dev/null +++ b/src/file_service.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#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 */ -- 2.7.4