Check errors aggressively
[platform/core/system/stability-monitor.git] / src / utils.c
1 /*
2  * This file is part of stability-monitor
3  * 
4  * Copyright © 2019 Samsung Electronics
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <stdio.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include <time.h>
23 #include <limits.h>
24 #include <errno.h>
25
26 #include "log.h"
27 #include "utils.h"
28
29
30 unsigned long long time_now(void)
31 {
32     struct timespec ts;
33
34     if (clock_gettime(CLOCK_BOOTTIME, &ts) == -1) {
35         _W("Couldn't get current clock time: %m");
36         return 0;
37     }
38     return ts.tv_sec * USEC_PER_SEC + ts.tv_nsec / NSEC_PER_USEC; // us
39 }
40
41 char *get_basename(char *path)
42 {
43     char *base = strrchr(path, '/');
44     return base ? base+1 : path;
45 }
46
47 int pid_to_basename(int pid, char *basename, size_t basename_buflen)
48 {
49     char path[PATH_MAX + 1];
50     char link_name[NAME_MAX];
51     char *basename_ptr;
52     size_t basename_len;
53     int ret;
54
55     /* Assembly /proc/pid/exe */
56     ret = snprintf(link_name, sizeof(link_name), PROC_EXE_PATH, pid);
57     if (ret <= 0) {
58         return -1;
59     }
60
61     /* Readlink /proc/pid/exe (leaving space for the null terminator
62      * which readlink never appends on its own) */
63     ret = readlink(link_name, path, sizeof(path) - 1);
64     if (ret <= 0) {
65         _DD("readlink() failed, pid: %d, ret: %d\n", pid, ret);
66         return -EEXIST;
67     }
68
69     path[ret] = 0;
70
71     /* Return basename */
72     basename_ptr = get_basename(path);
73     basename_len = strlen(basename_ptr);
74
75     if (basename_len >= basename_buflen)
76         return -ENAMETOOLONG;
77
78     strncpy(basename, basename_ptr, basename_buflen);
79     basename[basename_len] = 0;
80
81     return 0;
82 }
83
84 const char *smpl2str(struct sample_s *s)
85 {
86     static char str[MAX_SAMPLE_STR];
87     int r;
88
89     if (s->type == ST_DOUBLE)
90         r = snprintf(str, MAX_SAMPLE_STR, "%2.3lf", s->value.d);
91     else if (s->type == ST_INT)
92         r = snprintf(str, MAX_SAMPLE_STR, "%d", s->value.i);
93     else if (s->type == ST_ULL)
94         r = snprintf(str, MAX_SAMPLE_STR, "%llu", s->value.ull);
95     else {
96         r = -1;
97         errno = EINVAL;
98     }
99
100     if (r == -1) {
101       _W("Couldn't parse sample: %m");
102       str[0] = '?';
103       str[1] = '\0';
104     }
105
106     return str;
107 }
108
109 int _json_object_object_merge(json_object *obj1, char *key, json_object *obj2_node)
110 {
111         struct json_object *obj1_node = NULL;
112         int ret;
113
114         ret = json_object_object_get_ex(obj1, key, &obj1_node);
115
116         /* if there is no such object in obj1 - add it */
117         if (ret == 0)
118                 goto json_add;
119
120         if (obj1_node == NULL) {
121                 _E("Unable to get json object");
122                 return -ENOMEM;
123         }
124
125         /* if there is, but obj1 or obj2 is not json_type_object - replace it */
126         if (!json_object_is_type(obj1_node, json_type_object) ||
127                 !json_object_is_type(obj2_node, json_type_object)) {
128
129                 json_object_object_del(obj1, key);
130                 goto json_add;
131         }
132
133         /* if obj1 and obj2 is json_object_type */
134         json_object_object_foreach(obj2_node, k, v) {
135                 ret = _json_object_object_merge(obj1_node, k, v);
136                 if (ret)
137                         return ret;
138         }
139
140         return 0;
141
142 json_add:
143         json_object_get(obj2_node);
144         json_object_object_add(obj1, key, obj2_node);
145         return 0;
146 }