2 * Copyright 2013 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.1 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://floralicense.org/license/
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
26 #include <sys/types.h>
29 #include <sys/statvfs.h>
30 #include <sys/mount.h>
32 #include <sys/smack.h>
36 #if defined(HAVE_LIVEBOX)
37 #include <livebox-errno.h>
39 #include "lite-errno.h"
47 int emergency_mounted;
49 .emergency_mounted = 0,
54 HAPI unsigned long util_string_hash(const char *str)
56 unsigned long ret = 0;
59 ret += (unsigned long)(*str++);
66 HAPI double util_timestamp(void)
68 #if defined(_USE_ECORE_TIME_GET)
69 return ecore_time_get();
72 if (gettimeofday(&tv, NULL) < 0) {
73 static unsigned long internal_count = 0;
74 ErrPrint("failed to get time of day: %s\n", strerror(errno));
75 tv.tv_sec = internal_count++;
79 return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
83 HAPI int util_check_ext(const char *filename, const char *check_ptr)
87 name_len = strlen(filename);
88 while (--name_len >= 0 && *check_ptr) {
89 if (filename[name_len] != *check_ptr) {
90 return LB_STATUS_ERROR_INVALID;
96 return LB_STATUS_SUCCESS;
99 static inline int check_native_livebox(const char *pkgname)
104 len = strlen(pkgname) * 2;
105 len += strlen(ROOT_PATH);
106 len += strlen("%s/libexec/liblive-%s.so");
108 path = malloc(len + 1);
110 ErrPrint("Heap: %s\n", strerror(errno));
111 return LB_STATUS_ERROR_MEMORY;
114 snprintf(path, len, "%s%s/libexec/liblive-%s.so", ROOT_PATH, pkgname, pkgname);
115 if (access(path, F_OK | R_OK) != 0) {
116 ErrPrint("%s is not a valid package\n", pkgname);
118 return LB_STATUS_ERROR_INVALID;
122 return LB_STATUS_SUCCESS;
125 static inline int check_web_livebox(const char *pkgname)
130 len = strlen(pkgname) * 2;
131 len += strlen("/opt/usr/apps/%s/res/wgt/livebox/index.html");
133 path = malloc(len + 1);
135 ErrPrint("Heap: %s\n", strerror(errno));
136 return LB_STATUS_ERROR_MEMORY;
139 snprintf(path, len, "/opt/usr/apps/%s/res/wgt/livebox/index.html", pkgname);
140 if (access(path, F_OK | R_OK) != 0) {
141 ErrPrint("%s is not a valid package\n", pkgname);
143 return LB_STATUS_ERROR_INVALID;
147 return LB_STATUS_SUCCESS;
150 HAPI int util_validate_livebox_package(const char *pkgname)
153 ErrPrint("Invalid argument\n");
154 return LB_STATUS_ERROR_INVALID;
157 if (!check_native_livebox(pkgname) || !check_web_livebox(pkgname)) {
158 return LB_STATUS_SUCCESS;
161 return LB_STATUS_ERROR_INVALID;
164 HAPI int util_unlink(const char *filename)
171 return LB_STATUS_ERROR_INVALID;
174 desclen = strlen(filename) + 6; /* .desc */
175 descfile = malloc(desclen);
177 ErrPrint("Heap: %s\n", strerror(errno));
178 return LB_STATUS_ERROR_MEMORY;
181 ret = snprintf(descfile, desclen, "%s.desc", filename);
183 ErrPrint("Error: %s\n", strerror(errno));
185 return LB_STATUS_ERROR_FAULT;
188 (void)unlink(descfile);
190 (void)unlink(filename);
192 return LB_STATUS_SUCCESS;
195 HAPI char *util_slavename(void)
197 char slavename[BUFSIZ];
198 static unsigned long idx = 0;
200 snprintf(slavename, sizeof(slavename), "%lu_%lf", idx++, util_timestamp());
201 return strdup(slavename);
204 HAPI const char *util_basename(const char *name)
207 length = name ? strlen(name) : 0;
212 while (--length > 0 && name[length] != '/');
214 return length <= 0 ? name : (name + length + (name[length] == '/'));
218 * Return size of stroage in Bytes unit.
220 HAPI unsigned long long util_free_space(const char *path)
223 unsigned long long space;
225 if (statvfs(path, &st) < 0) {
226 ErrPrint("statvfs: %s\n", strerror(errno));
230 space = (unsigned long long)st.f_bsize * (unsigned long long)st.f_bavail;
231 DbgPrint("Available size: %llu, f_bsize: %lu, f_bavail: %lu\n", space, st.f_bsize, st.f_bavail);
234 * Must have to check the overflow
240 static inline char *extend_heap(char *buffer, int *sz, int incsz)
245 tmp = realloc(buffer, *sz);
247 ErrPrint("Heap: %s\n", strerror(errno));
254 HAPI char *util_replace_string(const char *src, const char *pattern, const char *replace)
269 if (!src || !pattern) {
273 out_sz = strlen(src);
276 ErrPrint("Heap: %s\n", strerror(errno));
281 for (state = STATE_START, ptr = src; state != STATE_END; ptr++) {
286 } else if (!isblank(*ptr)) {
294 } else if (*ptr == *pattern) {
301 if (out_idx == out_sz) {
302 tmp = extend_heap(ret, &out_sz, strlen(replace) + 1);
314 * If there is no space for copying the replacement,
315 * Extend size of the return buffer.
317 if (out_sz - out_idx < strlen(replace) + 1) {
318 tmp = extend_heap(ret, &out_sz, strlen(replace) + 1);
326 strcpy(ret + out_idx, replace);
327 out_idx += strlen(replace);
331 } else if (*ptr != pattern[idx]) {
334 /* Copy the first matched character */
337 if (out_idx == out_sz) {
338 tmp = extend_heap(ret, &out_sz, strlen(replace) + 1);
360 HAPI const char *util_uri_to_path(const char *uri)
364 len = strlen(SCHEMA_FILE);
365 if (strncasecmp(uri, SCHEMA_FILE, len)) {
372 HAPI double util_time_delay_for_compensation(double period)
374 unsigned long long curtime;
375 unsigned long long _period;
376 unsigned long long remain;
380 if (period == 0.0f) {
381 DbgPrint("Period is ZERO\n");
385 if (gettimeofday(&tv, NULL) < 0){
386 ErrPrint("gettimeofday: %s\n", strerror(errno));
390 curtime = (unsigned long long)tv.tv_sec * 1000000llu + (unsigned long long)tv.tv_usec;
392 _period = (unsigned long long)(period * (double)1000000);
393 if (_period == 0llu) {
394 ErrPrint("%lf <> %llu\n", period, _period);
398 remain = curtime % _period;
400 ret = (double)remain / (double)1000000;
404 HAPI void *util_timer_add(double interval, Eina_Bool (*cb)(void *data), void *data)
409 timer = ecore_timer_add(interval, cb, data);
414 delay = util_time_delay_for_compensation(interval) - interval;
415 ecore_timer_delay(timer, delay);
416 DbgPrint("Compensate timer: %lf\n", delay);
421 HAPI void util_timer_interval_set(void *timer, double interval)
424 ecore_timer_interval_set(timer, interval);
426 delay = util_time_delay_for_compensation(interval) - interval;
427 ecore_timer_delay(timer, delay);
430 HAPI int util_unlink_files(const char *folder)
434 struct dirent *entry;
438 if (lstat(folder, &info) < 0) {
439 ErrPrint("Error: %s\n", strerror(errno));
440 return LB_STATUS_ERROR_IO;
443 if (!S_ISDIR(info.st_mode)) {
444 ErrPrint("Error: %s is not a folder", folder);
445 return LB_STATUS_ERROR_INVALID;
448 handle = opendir(folder);
450 ErrPrint("Error: %s\n", strerror(errno));
451 return LB_STATUS_ERROR_IO;
454 while ((entry = readdir(handle))) {
455 if (!strcmp(entry->d_name, ".")) {
459 if (!strcmp(entry->d_name, "..")) {
463 len = strlen(folder) + strlen(entry->d_name) + 3;
464 abspath = calloc(1, len);
466 ErrPrint("Heap: %s\n", strerror(errno));
469 snprintf(abspath, len - 1, "%s/%s", folder, entry->d_name);
471 if (unlink(abspath) < 0) {
472 DbgPrint("unlink: %s\n", strerror(errno));
478 if (closedir(handle) < 0) {
479 ErrPrint("closedir: %s\n", strerror(errno));
481 return LB_STATUS_SUCCESS;
484 HAPI void util_remove_emergency_disk(void)
487 ret = umount(IMAGE_PATH);
489 ErrPrint("umount: %s\n", strerror(errno));
492 DbgPrint("Try to unmount[%s] %d\n", IMAGE_PATH, ret);
493 s_info.emergency_mounted = 0;
496 HAPI void util_prepare_emergency_disk(void)
508 static const char *tag[] = {
521 buf = strdup(EMERGENCY_DISK);
523 ErrPrint("Failed to prepare emergency disk info\n");
527 rollback_ptr = ptr = buf;
532 while (tag[tag_idx] != NULL && ptr != (buf + len)) {
533 if (tag[tag_idx][idx] == '\0') {
534 if (*ptr == '=' || isblank(*ptr)) {
538 ErrPrint("source[%s] is overrided\n", source);
541 while ((*ptr != '\0' && *ptr != ';') && (*ptr == '=' || isblank(*ptr))) {
546 while (*ptr != '\0' && *ptr != ';') {
550 if (*source == '\0') {
555 rollback_ptr = ptr + 1;
560 ErrPrint("type[%s] is overrided\n", type);
563 while ((*ptr != '\0' && *ptr != ';') && (*ptr == '=' || isblank(*ptr))) {
568 while (*ptr != '\0' && *ptr != ';') {
577 rollback_ptr = ptr + 1;
582 ErrPrint("option[%s] is overrided\n", option);
585 while ((*ptr != '\0' && *ptr != ';') && (*ptr == '=' || isblank(*ptr))) {
590 while (*ptr != '\0' && *ptr != ';') {
594 if (*option == '\0') {
599 rollback_ptr = ptr + 1;
610 } else if (tag[tag_idx][idx] != *ptr) {
620 DbgPrint("source[%s] type[%s] option[%s]\n", source, type, option);
622 ret = mount(source, IMAGE_PATH, type, MS_NOSUID | MS_NOEXEC, option);
625 ErrPrint("Failed to mount: %s\n", strerror(errno));
631 ErrPrint("Disk space is not enough, use the tmpfs. Currently required minimum space is %lu bytes\n", MINIMUM_SPACE);
632 if (chmod(IMAGE_PATH, 0750) < 0) {
633 ErrPrint("chmod: %s\n", strerror(errno));
636 if (chown(IMAGE_PATH, 5000, 5000) < 0) {
637 ErrPrint("chown: %s\n", strerror(errno));
640 ret = smack_setlabel(IMAGE_PATH, DATA_SHARE_LABEL, SMACK_LABEL_ACCESS);
642 ErrPrint("Failed to set SMACK for %s (%d)\n", IMAGE_PATH, ret);
644 ret = smack_setlabel(IMAGE_PATH, "1", SMACK_LABEL_TRANSMUTE);
645 DbgPrint("[%s] is successfully created (t: %d)\n", IMAGE_PATH, ret);
648 if (mkdir(ALWAYS_PATH, 0755) < 0) {
649 ErrPrint("mkdir: (%s) %s\n", ALWAYS_PATH, strerror(errno));
651 if (chmod(ALWAYS_PATH, 0750) < 0) {
652 ErrPrint("chmod: %s\n", strerror(errno));
655 if (chown(ALWAYS_PATH, 5000, 5000) < 0) {
656 ErrPrint("chown: %s\n", strerror(errno));
659 ret = smack_setlabel(ALWAYS_PATH, DATA_SHARE_LABEL, SMACK_LABEL_ACCESS);
661 ErrPrint("Failed to set SMACK for %s (%d)\n", ALWAYS_PATH, ret);
663 ret = smack_setlabel(ALWAYS_PATH, "1", SMACK_LABEL_TRANSMUTE);
664 DbgPrint("[%s] is successfully created (t: %d)\n", ALWAYS_PATH, ret);
668 if (mkdir(READER_PATH, 0755) < 0) {
669 ErrPrint("mkdir: (%s) %s\n", READER_PATH, strerror(errno));
671 if (chmod(READER_PATH, 0750) < 0) {
672 ErrPrint("chmod: %s\n", strerror(errno));
675 if (chown(READER_PATH, 5000, 5000) < 0) {
676 ErrPrint("chown: %s\n", strerror(errno));
679 ret = smack_setlabel(READER_PATH, DATA_SHARE_LABEL, SMACK_LABEL_ACCESS);
681 ErrPrint("Failed to set SMACK for %s (%d)\n", READER_PATH, ret);
683 ret = smack_setlabel(READER_PATH, "1", SMACK_LABEL_TRANSMUTE);
684 DbgPrint("[%s] is successfully created (t: %d)\n", READER_PATH, ret);
688 s_info.emergency_mounted = 1;
691 HAPI int util_emergency_disk_is_mounted(void)
693 return s_info.emergency_mounted;
696 HAPI void util_setup_log_disk(void)
700 if (access(SLAVE_LOG_PATH, R_OK | W_OK | X_OK) == 0) {
701 DbgPrint("[%s] is already accessible\n", SLAVE_LOG_PATH);
705 DbgPrint("Initiate the critical log folder [%s]\n", SLAVE_LOG_PATH);
706 if (mkdir(SLAVE_LOG_PATH, 0755) < 0) {
707 ErrPrint("mkdir: %s\n", strerror(errno));
709 if (chmod(SLAVE_LOG_PATH, 0750) < 0) {
710 ErrPrint("chmod: %s\n", strerror(errno));
713 if (chown(SLAVE_LOG_PATH, 5000, 5000) < 0) {
714 ErrPrint("chown: %s\n", strerror(errno));
717 ret = smack_setlabel(SLAVE_LOG_PATH, DATA_SHARE_LABEL, SMACK_LABEL_ACCESS);
719 ErrPrint("Failed to set SMACK for %s (%d)\n", SLAVE_LOG_PATH, ret);
721 ret = smack_setlabel(SLAVE_LOG_PATH, "1", SMACK_LABEL_TRANSMUTE);
722 DbgPrint("[%s] is successfully created (t: %d)\n", SLAVE_LOG_PATH, ret);
727 HAPI int util_service_is_enabled(const char *tag)
729 return !!strcasestr(SERVICES, tag);