Check errors aggressively
[platform/core/system/stability-monitor.git] / src / raw_data_providers / proc_tsm.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 <errno.h>
20 #include <fcntl.h>
21 #include <stdio.h>
22 #include <sys/stat.h>
23 #include <sys/syscall.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27
28 #include "log.h"
29 #include "raw_data.h"
30
31 #define PROC_TSM_MODULE_NAME "proc_tsm"
32 #define PROC_TSM_PATH "/proc/tsm"
33 #define MAX_LINE 100
34 #define finit_module(fd, params, flags) syscall(__NR_finit_module, fd, params, flags)
35
36
37 static int str_to_ullarray(char *str, unsigned long long *array)
38 {
39     char *ptr = str;
40     int n = 0;
41
42     while (*ptr != '\n' && *ptr != 0)
43         if (n < MAX_PARAMS_PER_LINE) {
44             array[n++] = strtoull(ptr, &ptr, 10);
45         } else {
46             _W("Reached maximum number of parameters per line (%d), discarding others",
47                MAX_PARAMS_PER_LINE);
48             break;
49         }
50
51     return n;
52 }
53
54 /* Read data prepared by kernel module */
55 static int get_raw_data(struct list_head *rd)
56 {
57     char buf[MAX_LINE] = {0,};
58     struct raw_data_item *rd_i;
59     int ret;
60     FILE *fp;
61
62     fp = fopen(PROC_TSM_PATH, "r");
63     if (!fp) {
64         _E("Unable to open " PROC_TSM_PATH ": %m");
65         return -EINVAL;
66     }
67
68     while (fgets(buf, MAX_LINE, fp) != NULL) {
69         ret = raw_data_new_item(rd, &rd_i);
70         if (ret)
71             goto error;
72
73         ret = str_to_ullarray(buf, rd_i->v);
74         if (ret <= 0) {
75             _E("Unable to parse raw data from kernel: \"%s\"\n", buf);
76             goto error;
77         }
78     }
79
80     if (fclose(fp) == -1)
81         _W("Unable to close file " PROC_TSM_PATH ": %m");
82     return 0;
83
84 error:
85     if (fclose(fp) == -1)
86         _W("Unable to close file " PROC_TSM_PATH ": %m");
87     raw_data_cleanup(rd);
88     return ret;
89 }
90
91 /* Load kernel module if not loaded */
92 static int init(void)
93 {
94     int fd, ret = 0;
95
96     if (access(PROC_TSM_PATH, O_RDONLY) == 0) {
97         _D("Kernel module already loaded\n");
98         return 0;
99     }
100
101     fd = open(KMOD_PATH, O_RDONLY);
102     if (fd == -1) {
103         _E("Unable to open file descriptor");
104         return -1;
105     }
106
107     ret = finit_module(fd, "", 0);
108     if (ret)
109         _E("Unable to load kernel module: %m");
110     close(fd);
111     return ret;
112 }
113
114 static void cleanup(void)
115 {
116     return;
117 }
118
119 struct raw_data_provider proc_tsm_module = {
120     .name = PROC_TSM_MODULE_NAME,
121     .init = init,
122     .get_raw_data = get_raw_data,
123     .cleanup = cleanup,
124 };
125
126 RAW_DATA_PROVIDER_REGISTER(&proc_tsm_module);