4 * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: YoungHun Kim <yh8004.kim@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 #include "muse_core_internal.h"
27 #define LOG_TAG "MUSED_CORE"
29 #define STR_TIME_FORMAT "%m-%d %H:%M:%S"
31 #define MUSE_WATCHDOG_CHECK_PERIOD 10
32 #define MUSE_WATCHDOG_CHECK_COUNT 3
33 #define MUSE_WATCHDOG_TIMER_PERIOD 5
35 static const char *msg_type[] = { "normal type", "fds type" };
37 static GMutex msg_lock;
38 static GMutex msg_ipc_lock;
40 static GMutex fd_state_lock;
41 static GHashTable *fd_state_table;
43 static int _muse_get_valid_fd_count(int *fds);
44 static void _muse_msg_json_set_error(muse_core_msg_parse_err_e *err, int jerr);
45 static json_object *_muse_msg_json_tokener_parse_len(const char *str, int *len, muse_core_msg_parse_err_e *err);
46 static gboolean _muse_msg_is_mem_ptr_valid(gpointer ptr);
47 static void _muse_msg_json_factory_args(json_object *jobj, va_list ap);
48 static json_object *_muse_msg_json_find_obj(json_object *jobj, const char *find_key);
49 static gboolean _muse_msg_json_get_obj_value(json_object *obj, muse_core_msg_type_e m_type, void *data);
52 void muse_core_gcov_flush(void)
57 void muse_core_setenv(const char *name, const char *value, int replace)
59 setenv(name, value, replace);
64 static int _muse_get_valid_fd_count(int *fds)
67 for (idx = 0; idx < MUSE_NUM_FD; idx++) {
68 if (fds[idx] == MUSE_ERR)
74 static void _muse_msg_json_set_error(muse_core_msg_parse_err_e *err, int jerr)
78 case json_tokener_success:
79 *err = MUSE_MSG_PARSE_ERROR_NONE;
81 case json_tokener_continue:
82 *err = MUSE_MSG_PARSE_ERROR_CONTINUE;
85 *err = MUSE_MSG_PARSE_ERROR_OTHER;
91 static json_object *_muse_msg_json_tokener_parse_len(const char *str, int *len, muse_core_msg_parse_err_e *err)
93 struct json_tokener *tok = NULL;
94 struct json_object *obj = NULL;
97 muse_return_val_if_fail(str, NULL);
99 tok = json_tokener_new();
102 LOGE("tokener creation error");
106 str_len = strlen(str);
107 obj = json_tokener_parse_ex(tok, str, str_len);
110 LOGE("parsing error : [length : %d] %s", str_len, str);
115 *len = tok->char_offset;
117 if (tok->err != json_tokener_success) {
118 LOGE("Json Error(%d) : %s", tok->err, json_tokener_error_desc(tok->err));
119 json_object_put(obj);
122 _muse_msg_json_set_error(err, tok->err);
126 json_tokener_free(tok);
131 static gboolean _muse_msg_is_mem_ptr_valid(gpointer ptr)
133 size_t page_size = sysconf(_SC_PAGESIZE);
134 gpointer base = (gpointer)((size_t)ptr / page_size * page_size);
136 return msync(base, page_size, MS_ASYNC) == 0;
139 static void _muse_msg_json_factory_args(json_object *jobj, va_list ap)
146 while ((type = va_arg(ap, int)) != 0) {
147 name = va_arg(ap, char *);
150 json_object_object_add(jobj, name, json_object_new_int(va_arg(ap, int32_t)));
152 case MUSE_TYPE_INT64:
153 json_object_object_add(jobj, name, json_object_new_int64(va_arg(ap, int64_t)));
155 case MUSE_TYPE_POINTER:
156 if (sizeof(intptr_t) == 8)
157 json_object_object_add(jobj, name, json_object_new_int64(va_arg(ap, intptr_t)));
159 json_object_object_add(jobj, name, json_object_new_int(va_arg(ap, intptr_t)));
161 case MUSE_TYPE_DOUBLE:
162 json_object_object_add(jobj, name, json_object_new_double(va_arg(ap, double)));
164 case MUSE_TYPE_STRING:
165 json_object_object_add(jobj, name, json_object_new_string(va_arg(ap, char *)));
167 case MUSE_TYPE_ARRAY:
168 len = va_arg(ap, int);
169 value = va_arg(ap, int *);
170 jarr = json_object_new_array();
172 for (idx = 0; idx < len; idx++)
173 json_object_array_add(jarr, json_object_new_int(value[idx]));
174 json_object_object_add(jobj, name, jarr);
177 LOGE("Unexpected type");
182 static json_object *_muse_msg_json_find_obj(json_object *jobj, const char *find_key)
186 muse_return_val_if_fail(jobj, NULL);
188 muse_return_val_if_fail(find_key, NULL);
190 key_len = strlen(find_key);
192 json_object_object_foreach(jobj, key, val) {
193 if (strlen(key) == key_len && !memcmp(key, find_key, key_len))
200 static gboolean _muse_msg_json_get_obj_value(json_object *obj, muse_core_msg_type_e m_type, void *data)
202 int j_type, idx, len;
204 const char *src = NULL;
206 muse_return_val_if_fail(obj, FALSE);
207 muse_return_val_if_fail(data, FALSE);
209 j_type = json_object_get_type(obj);
212 LOGD("json_type_null");
214 case json_type_double:
215 *(double *)data = json_object_get_double(obj);
218 if (m_type == MUSE_TYPE_ANY || m_type == MUSE_TYPE_INT) {
219 *(int32_t *)data = json_object_get_int(obj);
220 } else if (m_type == MUSE_TYPE_INT64) {
221 *(int64_t *)data = json_object_get_int64(obj);
222 } else if (m_type == MUSE_TYPE_POINTER) {
223 if (!_muse_msg_is_mem_ptr_valid(obj)) {
224 LOGE("memory pointer is not valid");
227 if (sizeof(intptr_t) == 8)
228 *(intptr_t *)data = json_object_get_int64(obj);
230 *(intptr_t *)data = json_object_get_int(obj);
231 } else if (m_type == MUSE_TYPE_DOUBLE) {
232 *(double *)data = json_object_get_double(obj);
235 case json_type_object:
237 case json_type_string:
238 src = json_object_get_string(obj);
239 muse_return_val_if_fail(src, FALSE);
240 g_strlcpy((gchar *)data, src, MUSE_MSG_MAX_LENGTH);
242 case json_type_array:
243 int_data = (int *)data;
244 len = json_object_array_length(obj);
245 for (idx = 0; idx < len; idx++)
246 int_data[idx] = json_object_get_int(json_object_array_get_idx(obj, idx));
249 LOGE("The value (%d) of json type is invalid", j_type);
256 void muse_core_log_cmd_info(char *cmd)
259 char buf[MUSE_MSG_LEN_MAX];
261 muse_return_if_fail(cmd);
263 fp = popen(cmd, "r");
266 while (fgets(buf, MUSE_MSG_LEN_MAX, fp))
269 if (pclose(fp) == -1)
270 LOGE("Fail to pclose");
274 bool muse_server_is_ready(void)
276 return access(MUSE_SERVER_READY, F_OK) == 0;
279 int muse_core_connection_close(int sock_fd)
281 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
283 if (!muse_core_fd_is_valid(sock_fd)) {
284 if (sock_fd != STDIN_FILENO)
285 LOGE("[%d] invalid socket", sock_fd);
286 return MM_ERROR_INVALID_ARGUMENT;
289 if (shutdown(sock_fd, SHUT_RDWR) == MUSE_ERR) {
290 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
291 LOGE("[%d] failed to shutdown [error %s %d]", sock_fd, err_msg, errno);
294 if (close(sock_fd) == MUSE_ERR) {
295 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
296 LOGE("[%d] failed to close [error %s %d]", sock_fd, err_msg, errno);
299 muse_core_dump_fd_state(sock_fd);
301 g_mutex_lock(&fd_state_lock);
303 if (!g_hash_table_remove(fd_state_table, GINT_TO_POINTER(sock_fd)))
304 LOGW("fail : remove fd %d from table[%p]", sock_fd, fd_state_table);
306 g_mutex_unlock(&fd_state_lock);
308 return MM_ERROR_NONE;
311 int muse_core_set_nonblocking(int fd, bool value)
313 int flags = fcntl(fd, F_GETFL, NULL);
314 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
317 flags = value ? (flags | O_NONBLOCK) : (flags & ~O_NONBLOCK);
318 if (fcntl(fd, F_SETFL, flags) == -1) {
319 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
320 LOGE("fcntl (%d, F_SETFL, %d) [error %s %d]", fd, flags, err_msg, errno);
321 return MM_ERROR_FILE_INTERNAL;
323 LOGD("fcntl (%d, F_SETFL)", fd);
326 LOGE("failed to get flags for %d", fd);
327 return MM_ERROR_FILE_INTERNAL;
330 return MM_ERROR_NONE;
333 int muse_core_set_socket_timeout(int sock_fd, int timeout_sec)
335 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
340 tv.tv_sec = timeout_sec;
343 if (setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv, (socklen_t)sizeof(tv)) == MUSE_ERR) {
344 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
345 LOGE("[%d] Failed to set socket send timeout option [error %s %d]", sock_fd, err_msg, errno);
346 return MM_ERROR_UNKNOWN;
349 if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, (socklen_t)sizeof(tv)) == MUSE_ERR) {
350 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
351 LOGE("[%d] Failed to set socket recv timeout option [error %s %d]", sock_fd, err_msg, errno);
352 return MM_ERROR_UNKNOWN;
357 return MM_ERROR_NONE;
360 bool muse_core_fd_is_valid(int fd)
362 muse_core_update_fd_state(fd);
363 return (fcntl(fd, F_GETFL) != MUSE_ERR || errno != EBADF) && (fd > STDERR_FILENO);
366 void muse_core_fd_close(int fd)
368 if (!muse_core_fd_is_valid(fd)) {
369 LOGW("%d is invalid fd", fd);
377 int muse_core_msg_send(int sock_fd, const char *msg)
379 muse_return_val_if_fail(msg, MM_ERROR_INVALID_ARGUMENT);
380 return muse_core_msg_send_fd(sock_fd, NULL, msg);
383 int muse_core_msg_send_fd(int sock_fd, int *fds, const char *buf)
385 int ret = MM_ERROR_NONE;
386 muse_msg_info_t msg_info = {0,};
387 struct cmsghdr *cptr;
390 char data[CMSG_SPACE(sizeof(int) * MUSE_NUM_FD)];
391 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
395 muse_return_val_if_fail(buf, MM_ERROR_INVALID_ARGUMENT);
396 muse_return_val_if_fail(muse_core_fd_is_valid(sock_fd), MM_ERROR_INVALID_ARGUMENT);
399 msg_info.type = MUSE_MSG_TYPE_NORMAL;
401 msg_info.type = MUSE_MSG_TYPE_FDS;
403 msg_info.marker = MUSE_MSG_HEAD;
404 msg_info.size = strlen(buf);
406 g_mutex_lock(&msg_ipc_lock);
408 ret = send(sock_fd, &msg_info, sizeof(muse_msg_info_t), 0);
409 if (ret != sizeof(muse_msg_info_t)) {
410 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
411 LOGE("msg info [type : %s size : %d] send failed : %d [error %s %d]",
412 msg_type[msg_info.type], msg_info.size, ret, err_msg, errno);
417 if (msg_info.type == MUSE_MSG_TYPE_NORMAL) {
418 ret = send(sock_fd, buf, msg_info.size, 0);
419 if (ret != (int)msg_info.size) {
420 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
421 LOGE("[%s] send failed : %d [error %s %d]", buf, ret, err_msg, errno);
427 /* MUSE_MSG_TYPE_FDS */
428 memset(&iov, 0, sizeof(iov));
429 iov.iov_base = (void *)buf;
430 iov.iov_len = msg_info.size;
432 memset(&msg, 0, sizeof(msg));
438 msg.msg_control = data;
439 msg.msg_controllen = sizeof(data);
441 cptr = CMSG_FIRSTHDR(&msg);
443 fd_cnt = _muse_get_valid_fd_count(fds);
444 cptr->cmsg_len = CMSG_LEN(sizeof(int) * fd_cnt);
445 cptr->cmsg_level = SOL_SOCKET;
446 cptr->cmsg_type = SCM_RIGHTS;
447 fdptr = (int *)CMSG_DATA(cptr);
449 memcpy(fdptr, fds, sizeof(int) * fd_cnt);
451 /* the value of msg_controllen increases after memcpy so reassigns the original value */
452 msg.msg_controllen = cptr->cmsg_len;
455 if ((ret = sendmsg(sock_fd, &msg, 0)) == SEND_FAIL) {
456 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
457 LOGE("[%d] fail to send msg - [error %s %d]", sock_fd, err_msg, errno);
461 g_mutex_unlock(&msg_ipc_lock);
466 int muse_core_msg_recv(int sock_fd, char *msg, int msg_len)
468 muse_return_val_if_fail(msg, MM_ERROR_INVALID_ARGUMENT);
469 return muse_core_msg_recv_fd(sock_fd, msg, msg_len, NULL);
472 int muse_core_msg_recv_fd(int sock_fd, char *buf, int buf_len, int *out_fd)
476 struct cmsghdr *cptr;
479 muse_msg_info_t msg_info = {0,};
480 char data[CMSG_SPACE(sizeof(int) * MUSE_NUM_FD)];
481 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
483 muse_return_val_if_fail(buf, MM_ERROR_INVALID_ARGUMENT);
484 muse_return_val_if_fail(muse_core_fd_is_valid(sock_fd), MM_ERROR_INVALID_ARGUMENT);
486 /* get the msg type and length */
487 if (!muse_core_msg_recv_len(sock_fd, (char *)&msg_info, sizeof(muse_msg_info_t))) {
489 LOGE("[pid : %d] [fd : %d] msg info receive failed", pid, sock_fd);
490 muse_core_log_process_thread_info(pid);
494 if (msg_info.size > 0 && buf_len < msg_info.size) {
495 LOGE("stack overflow caution !! [recv buf's length (%d) must be larger than msg's length (%d)", buf_len, msg_info.size);
499 if (msg_info.marker != MUSE_MSG_HEAD) {
500 LOGE("invalid marker 0x%x", msg_info.marker);
504 if (msg_info.type == MUSE_MSG_TYPE_NORMAL) {
505 if (!muse_core_msg_recv_len(sock_fd, buf, msg_info.size)) {
506 LOGE("msg receive failed");
512 memset(&iov, 0, sizeof(iov));
513 iov.iov_base = (void *)buf;
514 iov.iov_len = msg_info.size;
516 memset(&msg, 0, sizeof(msg));
521 msg.msg_control = data;
522 msg.msg_controllen = sizeof(data);
524 if ((ret = recvmsg(sock_fd, &msg, 0)) == RECV_FAIL) {
525 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
526 LOGE("fail to receive msg [error %s %d]", err_msg, errno);
531 cptr = CMSG_FIRSTHDR(&msg);
533 memcpy(out_fd, CMSG_DATA(cptr), cptr->cmsg_len - CMSG_LEN(0));
542 char *muse_core_msg_new(int api, ...)
549 jobj = json_object_new_object();
551 muse_return_val_if_fail(jobj, NULL);
553 json_object_object_add(jobj, MSG_KEY_API, json_object_new_int(api));
556 _muse_msg_json_factory_args(jobj, ap);
559 jsonMsg = json_object_to_json_string(jobj);
560 sndMsg = g_strdup(jsonMsg);
562 if (api == API_CREATE)
563 SECURE_LOGD("%s", sndMsg);
565 json_object_put(jobj);
570 bool muse_core_msg_deserialize(const char *key, char *buf, int *parse_len,
571 muse_core_msg_parse_err_e *err, muse_core_msg_type_e m_type, void *data)
573 json_object *obj = NULL, *jobj = NULL;
576 muse_return_val_if_fail(key, false);
577 muse_return_val_if_fail(buf, false);
578 muse_return_val_if_fail(m_type >= MUSE_TYPE_INT && m_type < MUSE_TYPE_MAX, false);
579 muse_return_val_if_fail(data, false);
581 g_mutex_lock(&msg_lock);
583 jobj = _muse_msg_json_tokener_parse_len(buf, parse_len, err);
585 LOGE("jobj is NULL");
586 g_mutex_unlock(&msg_lock);
590 obj = _muse_msg_json_find_obj(jobj, key);
592 LOGE("\"%s\" key is not founded", key);
593 json_object_put(jobj);
594 g_mutex_unlock(&msg_lock);
598 ret = (bool)_muse_msg_json_get_obj_value(obj, m_type, data);
600 json_object_put(jobj);
602 g_mutex_unlock(&msg_lock);
607 void muse_core_msg_free(char *msg)
612 void *muse_core_msg_object_new(char *str, int *parse_len, muse_core_msg_parse_err_e *err)
616 muse_return_val_if_fail(str, NULL);
618 g_mutex_lock(&msg_lock);
620 jobj = (void *)_muse_msg_json_tokener_parse_len(str, parse_len, err);
622 g_mutex_unlock(&msg_lock);
627 bool muse_core_msg_object_get_value(const char *key, void *jobj, muse_core_msg_type_e m_type, void *data)
632 muse_return_val_if_fail(key, false);
633 muse_return_val_if_fail(jobj, false);
634 muse_return_val_if_fail(data, false);
635 muse_return_val_if_fail(m_type >= MUSE_TYPE_INT && m_type < MUSE_TYPE_MAX, false);
637 g_mutex_lock(&msg_lock);
639 obj = _muse_msg_json_find_obj((json_object *)jobj, key);
641 LOGE("\"%s\" key is not found", key);
642 g_mutex_unlock(&msg_lock);
646 ret = (bool)_muse_msg_json_get_obj_value(obj, m_type, data);
648 g_mutex_unlock(&msg_lock);
653 void muse_core_msg_object_free(void *jobj)
655 muse_return_if_fail(jobj);
657 g_mutex_lock(&msg_lock);
659 json_object_put((json_object *)jobj);
661 g_mutex_unlock(&msg_lock);
664 bool muse_core_msg_recv_len(int fd, char *buf, int msg_len)
668 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
670 if (!muse_core_fd_is_valid(fd) || !buf || msg_len <= 0) {
671 LOGE("invalid param : fd %d, buf %p, msg_len %d", fd, buf, msg_len);
676 recv_len = recv(fd, buf + offset, msg_len - offset, 0);
678 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
679 LOGE("[%d] recv failed [error %s %d]", fd, err_msg, errno);
681 } else if (recv_len == 0) {
682 LOGD("[%d] EOF", fd);
687 } while (offset < msg_len);
689 if (offset != msg_len) {
690 LOGE("invalid length received : try %d -> result %d", msg_len, offset);
697 void muse_core_dump_fd_state(int fd)
699 g_mutex_lock(&fd_state_lock);
700 LOGI("[%d] %s", fd, (char *)g_hash_table_lookup(fd_state_table, GINT_TO_POINTER(fd)));
701 g_mutex_unlock(&fd_state_lock);
704 void muse_core_update_fd_state(int fd)
706 char atime[MUSE_MSG_TIME_LEN] = {'\0',};
708 g_mutex_lock(&fd_state_lock);
711 fd_state_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
713 muse_core_get_cur_time(NULL, atime);
714 g_hash_table_insert(fd_state_table, GINT_TO_POINTER(fd), g_strdup(atime));
716 g_mutex_unlock(&fd_state_lock);
719 void muse_core_create_fd_table(void)
721 g_mutex_lock(&fd_state_lock);
723 if (fd_state_table) {
724 LOGW("fd state table [%p] is already created", fd_state_table);
728 fd_state_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
730 LOGE("fail to create new fd state table");
732 g_mutex_unlock(&fd_state_lock);
735 void muse_core_remove_all_fd_table(void)
737 g_mutex_lock(&fd_state_lock);
738 g_hash_table_remove_all(fd_state_table);
739 g_mutex_unlock(&fd_state_lock);
742 void muse_core_destroy_fd_table(void)
744 g_mutex_lock(&fd_state_lock);
745 g_hash_table_destroy(fd_state_table);
746 fd_state_table = NULL;
747 g_mutex_unlock(&fd_state_lock);
750 void muse_core_get_cur_time(struct timespec *time, char *time_buf)
752 char cur_time[MUSE_MSG_LEN];
756 muse_return_if_fail(clock_gettime(CLOCK_MONOTONIC, &tv) == 0);
762 strftime(cur_time, MUSE_MSG_LEN, STR_TIME_FORMAT, localtime_r(&(tv.tv_sec), &newtime));
763 snprintf(time_buf, MUSE_MSG_TIME_LEN, "%s.%03ld", cur_time, tv.tv_nsec);
767 void muse_core_log_process_thread_info(int pid)
769 char cmd[MUSE_MSG_LEN_MAX];
771 snprintf(cmd, sizeof(cmd), "/bin/cat /proc/%d/status | /bin/grep Threads", pid);
772 muse_core_log_cmd_info(cmd);
775 void muse_core_log_process_opened_fds(int pid)
777 char dir_path[MUSE_MSG_LEN_MAX];
778 struct dirent *de = NULL;
781 snprintf(dir_path, sizeof(dir_path), "/proc/%d/fd", pid); /* /proc/%d/fd is directory */
782 dr = opendir(dir_path);
783 muse_return_if_fail(dr);
785 LOGI("directory path : %s", dir_path);
787 while ((de = readdir(dr)) != NULL)
788 LOGW("%s\n", de->d_name);
793 void muse_core_log_process_cpu_memory(int pid)
795 char cmd[MUSE_MSG_LEN_MAX];
797 snprintf(cmd, sizeof(cmd), "/bin/ps -Lo pcpu,pmem,tid,comm -p %d", pid);
798 muse_core_log_cmd_info(cmd);
801 int muse_core_get_process_cpu_usage(int pid)
805 char cmd[MUSE_MSG_LEN_MAX];
806 char buf[MUSE_MSG_LEN_MAX];
808 snprintf(cmd, sizeof(cmd), "/bin/ps -Lo pcpu,pmem,tid,comm -p %d", pid);
810 fp = popen(cmd, "r");
813 while (fgets(buf, MUSE_MSG_LEN_MAX, fp)) {
815 cpu += atoi(g_strstrip(buf));
818 if (pclose(fp) == -1)
819 LOGE("Fail to pclose");
825 void muse_core_log_file_list(const char *path)
827 char cmd[MUSE_MSG_LEN_MAX];
829 snprintf(cmd, sizeof(cmd), "/bin/ls -alt %s", path);
830 muse_core_log_cmd_info(cmd);
833 void muse_core_remove_symlink(const char *path)
835 char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
838 muse_return_if_fail(path);
840 r = realpath(path, NULL);
842 if (strncmp(r, path, strlen(path) + 1) != 0) {
843 LOGW("symbolic link exists [%s] -> [%s]", path, r);
848 if (errno != ENOENT) {
849 strerror_r(errno, err_msg, MUSE_MSG_LEN_MAX);
850 LOGE("realpath failed [error %s %d]", err_msg, errno);