3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <sys/statvfs.h>
32 #define MEMORY_GIGABYTE_VALUE 1073741824
33 #define MEMORY_MEGABYTE_VALUE 1048576
35 #define MEMORY_STATUS_USR_PATH "/opt/usr"
36 #define EXTERNAL_MEMORY_PATH "/opt/storage/sdcard"
37 #define STORAGE_CONF_FILE "/etc/storage/libstorage.conf"
39 /* it's for 32bit file offset */
41 unsigned long int f_bsize;
42 unsigned long int f_frsize;
43 unsigned long int f_blocks;
44 unsigned long int f_bfree;
45 unsigned long int f_bavail;
46 unsigned long int f_files;
47 unsigned long int f_ffree;
48 unsigned long int f_favail;
49 unsigned long int f_fsid;
50 #ifdef _STATVFSBUF_F_UNUSED
53 unsigned long int f_flag;
54 unsigned long int f_namemax;
59 #define MAX_SECTION 64
60 #define WHITESPACE " \t"
61 #define NEWLINE "\n\r"
64 #define MATCH(a, b) (!strncmp(a, b, strlen(a)))
65 #define SET_CONF(a, b) (a = (b > 0.0 ? b : a))
73 struct storage_config_info {
79 static struct storage_config_info storage_info;
81 static inline char *trim_str(char *s)
85 s += strspn(s, WHITESPACE);
88 for (t = strchr(s, 0); t > s; t--)
89 if (!strchr(WHITESPACE, t[-1]))
95 static int config_parse(const char *file_name, int cb(struct parse_result *result,
96 void *user_data), void *user_data)
99 struct parse_result result;
100 /* use stack for parsing */
102 char section[MAX_SECTION];
103 char *start, *end, *name, *value;
104 int lineno = 0, ret = 0;
106 if (!file_name || !cb) {
112 f = fopen(file_name, "r");
114 _E("Failed to open file %s", file_name);
119 /* parsing line by line */
120 while (fgets(line, MAX_LINE, f) != NULL) {
124 start[strcspn(start, NEWLINE)] = '\0';
125 start = trim_str(start);
127 if (*start == COMMENT) {
129 } else if (*start == '[') {
131 end = strchr(start, ']');
132 if (!end || *end != ']') {
138 strncpy(section, start + 1, sizeof(section));
139 section[MAX_SECTION-1] = '\0';
141 /* parse name & value */
142 end = strchr(start, '=');
143 if (!end || *end != '=') {
148 name = trim_str(start);
149 value = trim_str(end + 1);
150 end = strchr(value, COMMENT);
151 if (end && *end == COMMENT) {
153 value = trim_str(value);
156 result.section = section;
158 result.value = value;
159 /* callback with parse result */
160 ret = cb(&result, user_data);
167 _D("Success to load %s", file_name);
174 _E("Failed to read %s:%d!", file_name, lineno);
178 static int load_config(struct parse_result *result, void *user_data)
180 static int check_size = -1;
181 struct storage_config_info *info = (struct storage_config_info *)user_data;
188 if (!MATCH(result->section, "STORAGE"))
192 value = result->value;
194 if (info->check_size > 0 && check_size < 0)
195 check_size = (storage_info.total_size < info->check_size)? 1 : 0;
196 if (MATCH(name, "CHECK_SIZE"))
197 info->check_size = atoi(value);
198 else if (check_size == 0 && MATCH(name, "RESERVE"))
199 info->reserved_size = atoi(value);
200 else if (check_size == 1 && MATCH(name, "RESERVE_LITE"))
201 info->reserved_size = atoi(value);
206 static void storage_config_load(struct storage_config_info *info)
210 ret = config_parse(STORAGE_CONF_FILE, load_config, info);
212 _E("Failed to load %s, %d Use default value!", STORAGE_CONF_FILE, ret);
215 static int get_memory_size(const char *path, struct statvfs_32 *buf)
222 ret = statvfs(path, &s);
226 buf->f_bsize = s.f_bsize;
227 buf->f_frsize = s.f_frsize;
228 buf->f_blocks = (unsigned long)s.f_blocks;
229 buf->f_bfree = (unsigned long)s.f_bfree;
230 buf->f_bavail = (unsigned long)s.f_bavail;
231 buf->f_files = (unsigned long)s.f_files;
232 buf->f_ffree = (unsigned long)s.f_ffree;
233 buf->f_favail = (unsigned long)s.f_favail;
234 buf->f_fsid = s.f_fsid;
235 buf->f_flag = s.f_flag;
236 buf->f_namemax = s.f_namemax;
241 API int storage_get_internal_memory_size(struct statvfs *buf)
243 struct statvfs_32 temp;
244 static unsigned long reserved = 0;
248 _E("input param error");
252 ret = get_memory_size(MEMORY_STATUS_USR_PATH, &temp);
253 if (ret || temp.f_bsize == 0) {
254 _E("fail to get memory size");
259 storage_info.total_size = (double)temp.f_frsize * temp.f_blocks;
260 storage_config_load(&storage_info);
261 reserved = (unsigned long)storage_info.reserved_size;
262 reserved = reserved/temp.f_bsize;
263 _I("total %4.4lf check %4.4lf reserved %4.4lf",
264 storage_info.total_size, storage_info.check_size, storage_info.reserved_size);
266 if (temp.f_bavail < reserved)
269 temp.f_bavail -= reserved;
271 memcpy(buf, &temp, sizeof(temp));
275 API int storage_get_internal_memory_size64(struct statvfs *buf)
277 static unsigned long reserved = 0;
281 _E("input param error");
285 ret = statvfs(MEMORY_STATUS_USR_PATH, buf);
287 _E("fail to get memory size");
292 storage_info.total_size = (double)(buf->f_frsize * buf->f_blocks);
293 storage_config_load(&storage_info);
294 reserved = (unsigned long)storage_info.reserved_size;
295 reserved = reserved/buf->f_bsize;
296 _I("total %4.4lf check %4.4lf reserved %4.4lf",
297 storage_info.total_size, storage_info.check_size, storage_info.reserved_size);
299 if (buf->f_bavail < reserved)
302 buf->f_bavail -= reserved;
306 static int mount_check(const char* path)
310 const char* table = "/etc/mtab";
313 fp = setmntent(table, "r");
316 while ((mnt=getmntent(fp))) {
317 if (!strcmp(mnt->mnt_dir, path)) {
326 API int storage_get_external_memory_size(struct statvfs *buf)
328 struct statvfs_32 temp;
331 _D("storage_get_external_memory_size");
333 _E("input param error");
337 if (!mount_check(EXTERNAL_MEMORY_PATH)) {
338 memset(buf, 0, sizeof(struct statvfs_32));
342 ret = get_memory_size(EXTERNAL_MEMORY_PATH, &temp);
344 _E("fail to get memory size");
348 memcpy(buf, &temp, sizeof(temp));
352 API int storage_get_external_memory_size64(struct statvfs *buf)
356 _D("storage_get_external_memory_size64");
358 _E("input param error");
362 if (!mount_check(EXTERNAL_MEMORY_PATH)) {
363 memset(buf, 0, sizeof(struct statvfs));
367 ret = statvfs(EXTERNAL_MEMORY_PATH, buf);
369 _E("fail to get memory size");