Increase line coverage using LCOV_EXCL
[platform/core/system/libstorage.git] / src / statvfs.c
1 /*
2  * storage
3  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4  *
5  * Licensed under the Apache License, Version 2.0 (the License);
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <stdbool.h>
22 #include <string.h>
23 #include <sys/statvfs.h>
24 #include <sys/stat.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <mntent.h>
28 #include <tzplatform_config.h>
29 #include <libsyscommon/ini-parser.h>
30
31 #include "log.h"
32 #include "common.h"
33 #include "storage-external.h"
34
35 #define MEMORY_GIGABYTE_VALUE  1073741824
36 #define MEMORY_MEGABYTE_VALUE  1048576
37
38 #define EXTERNAL_MEMORY_NODE   "sdcard"
39 #define STORAGE_CONF_FILE      "/etc/storage/libstorage.conf"
40
41
42 #define MATCH(a, b)    (!strncmp(a, b, strlen(a)))
43 #define SET_CONF(a, b) (a = (b > 0.0 ? b : a))
44
45 struct storage_config_info {
46         double total_size;
47         double check_size;
48         double reserved_size;
49 };
50
51 static struct storage_config_info storage_info;
52
53 static int load_config(struct parse_result *result, void *user_data)
54 {
55         static int check_size = -1;
56         struct storage_config_info *info = (struct storage_config_info *)user_data;
57         char *name;
58         char *value;
59
60         if (!info)
61                 return -EINVAL;
62
63         if (!MATCH(result->section, "STORAGE"))
64                 return -EINVAL;
65
66         name = result->name;
67         value = result->value;
68
69         if (info->check_size > 0 && check_size < 0)
70                 check_size = (storage_info.total_size < info->check_size) ? 1 : 0;
71         if (MATCH(name, "CHECK_SIZE"))
72                 info->check_size = atoi(value);
73         else if (check_size == 0 && MATCH(name, "RESERVE"))
74                 info->reserved_size = atoi(value);
75         else if (check_size == 1 && MATCH(name, "RESERVE_LITE"))
76                 info->reserved_size = atoi(value);
77
78         return 0;
79 }
80
81 static void storage_config_load(struct storage_config_info *info)
82 {
83         int ret_val;
84
85         ret_val = config_parse(STORAGE_CONF_FILE, load_config, info);
86         if (ret_val < 0)
87                 _E("Failed to load %s, %d Use default value!", STORAGE_CONF_FILE, ret_val); //LCOV_EXCL_LINE
88 }
89
90 static int get_memory_size(const char *path, struct statvfs_32 *buf)
91 {
92         struct statvfs s;
93         int ret_val;
94
95         assert(buf);
96
97         ret_val = statvfs(path, &s);
98         if (ret_val)
99                 return -errno; //LCOV_EXCL_LINE System Error
100
101         memset(buf, 0, sizeof(struct statvfs_32));
102
103         buf->f_bsize  = s.f_bsize;
104         buf->f_frsize = s.f_frsize;
105         buf->f_blocks = (unsigned long)s.f_blocks;
106         buf->f_bfree  = (unsigned long)s.f_bfree;
107         buf->f_bavail = (unsigned long)s.f_bavail;
108         buf->f_files  = (unsigned long)s.f_files;
109         buf->f_ffree  = (unsigned long)s.f_ffree;
110         buf->f_favail = (unsigned long)s.f_favail;
111         buf->f_fsid = s.f_fsid;
112         buf->f_flag = s.f_flag;
113         buf->f_namemax = s.f_namemax;
114
115         return 0;
116 }
117
118 /* This api is intended for binaries built with _FILE_OFFSET_BITS=32 */
119 API int storage_get_internal_memory_size(struct statvfs *buf)
120 {
121         struct statvfs_32 temp = { 0, };
122         static unsigned long reserved = 0;
123         int ret_val;
124
125         if (!buf) {
126                 _E("input param error");
127                 return STORAGE_ERROR_INVALID_PARAMETER;
128         }
129
130         ret_val = get_memory_size(tzplatform_getenv(TZ_SYS_USER), &temp);
131         if (ret_val || temp.f_bsize == 0) {
132                 _E("fail to get memory size %d", ret_val); //LCOV_EXCL_LINE
133                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
134         }
135
136         if (reserved == 0) {
137                 storage_info.total_size = (double)temp.f_frsize * temp.f_blocks;
138                 storage_config_load(&storage_info);
139                 reserved = (unsigned long)storage_info.reserved_size;
140                 reserved = reserved/temp.f_bsize;
141                 _I("total %4.4lf check %4.4lf reserved %4.4lf",
142                         storage_info.total_size, storage_info.check_size, storage_info.reserved_size);
143         }
144         if (temp.f_bavail < reserved)
145                 temp.f_bavail = 0;
146         else
147                 temp.f_bavail -= reserved;
148
149         memcpy(buf, &temp, sizeof(temp));
150         return STORAGE_ERROR_NONE;
151 }
152
153 /* This api is intended for binaries built with __USE_FILE_OFFSET64(_FILE_OFFSET_BITS=64) */
154 API int storage_get_internal_memory_size64(struct statvfs *buf)
155 {
156         static unsigned long reserved = 0;
157         int ret_val;
158
159         if (!buf) {
160                 _E("input param error");
161                 return STORAGE_ERROR_INVALID_PARAMETER;
162         }
163
164         ret_val = statvfs(tzplatform_getenv(TZ_SYS_USER), buf);
165         if (ret_val) {
166                 _E("fail to get memory size"); //LCOV_EXCL_LINE
167                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
168         }
169
170         if (reserved == 0) {
171                 storage_info.total_size = (double)(buf->f_frsize * buf->f_blocks);
172                 storage_config_load(&storage_info);
173                 reserved = (unsigned long)storage_info.reserved_size;
174                 reserved = reserved/buf->f_bsize;
175                 _I("total %4.4lf check %4.4lf reserved %4.4lf",
176                         storage_info.total_size, storage_info.check_size, storage_info.reserved_size);
177         }
178         if (buf->f_bavail < reserved)
179                 buf->f_bavail = 0;
180         else
181                 buf->f_bavail -= reserved;
182         return STORAGE_ERROR_NONE;
183 }
184
185 int mount_check(const char *path)
186 {
187         int ret = false;
188         struct mntent *mnt;
189         const char *table = "/etc/mtab";
190         FILE *fp;
191
192         fp = setmntent(table, "r");
193         if (!fp)
194                 return ret;
195         while ((mnt = getmntent(fp))) {
196                 if (!strcmp(mnt->mnt_dir, path)) {
197                         ret = true;
198                         break;
199                 }
200         }
201         endmntent(fp);
202         return ret;
203 }
204
205 static int get_external_path(char *path, size_t len)
206 {
207         return storage_ext_get_primary_mmc_path(path, len);
208 }
209
210 /* This api is intended for binaries built with _FILE_OFFSET_BITS=32 */
211 int storage_get_external_memory_size_with_path(char *path, struct statvfs *buf)
212 {
213         struct statvfs_32 temp;
214         int ret_val;
215         char ext_path[32];
216
217         _D("storage_get_external_memory_size");
218         if (!buf) {
219                 _E("input param error");
220                 return STORAGE_ERROR_INVALID_PARAMETER;
221         }
222
223         if (path)
224                 snprintf(ext_path, sizeof(ext_path), "%s", path);
225         else {
226                 if (!storage_ext_is_supported()) {
227                         _D("Block module is not enabled"); //LCOV_EXCL_LINE
228                         return STORAGE_ERROR_NOT_SUPPORTED; //LCOV_EXCL_LINE
229                 }
230                 ret_val = get_external_path(ext_path, sizeof(ext_path));
231                 if (ret_val == -ENODEV)
232                         goto out_nodev;
233                 if (ret_val < 0) {
234                         _E("Failed to get external path(%d)", ret_val); //LCOV_EXCL_LINE
235                         return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
236                 }
237         }
238
239         if (!mount_check((const char *)ext_path))
240                 goto out_nodev;
241
242         ret_val = storage_ext_get_statvfs(ext_path, &temp);
243         if (ret_val != 0) {
244                 _E("fail to get memory size"); //LCOV_EXCL_LINE
245                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
246         }
247
248         memcpy(buf, &temp, sizeof(temp));
249         return 0;
250
251 out_nodev:
252         memset(buf, 0, sizeof(struct statvfs_32));
253         return STORAGE_ERROR_NONE;
254 }
255
256 /* This api is intended for binaries built with __USE_FILE_OFFSET64(_FILE_OFFSET_BITS=64) */
257 int storage_get_external_memory_size64_with_path(char *path, struct statvfs *buf)
258 {
259         int ret_val;
260         char ext_path[32];
261
262         _D("storage_get_external_memory_size64");
263         if (!buf) {
264                 _E("input param error");
265                 return STORAGE_ERROR_INVALID_PARAMETER;
266         }
267
268         if (path)
269                 snprintf(ext_path, sizeof(ext_path), "%s", path);
270         else {
271                 if (!storage_ext_is_supported()) {
272                         _D("Block module is not enabled"); //LCOV_EXCL_LINE
273                         return STORAGE_ERROR_NOT_SUPPORTED; //LCOV_EXCL_LINE
274                 }
275                 ret_val = get_external_path(ext_path, sizeof(ext_path));
276                 if (ret_val == -ENODEV)
277                         goto out_nodev;
278                 if (ret_val < 0) {
279                         _E("Failed to get external path(%d)", ret_val); //LCOV_EXCL_LINE
280                         return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
281                 }
282         }
283
284         if (!mount_check((const char *)ext_path))
285                 goto out_nodev;
286
287         ret_val = storage_ext_get_statvfs_size64(ext_path, buf);
288         if (ret_val != 0) {
289         //LCOV_EXCL_START System Error
290                 _E("fail to get memory size");
291                 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
292         //LCOV_EXCL_STOP
293         }
294
295         return STORAGE_ERROR_NONE;
296
297 out_nodev:
298         memset(buf, 0, sizeof(struct statvfs));
299         return 0;
300 }
301
302 API int storage_get_external_memory_size(struct statvfs *buf)
303 {
304         return storage_get_external_memory_size_with_path(NULL, buf);
305 }
306
307 API int storage_get_external_memory_size64(struct statvfs *buf)
308 {
309         return storage_get_external_memory_size64_with_path(NULL, buf);
310 }