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>
28 #include <tzplatform_config.h>
32 #include "storage-external.h"
34 #define MEMORY_GIGABYTE_VALUE 1073741824
35 #define MEMORY_MEGABYTE_VALUE 1048576
37 #define EXTERNAL_MEMORY_NODE "sdcard"
38 #define STORAGE_CONF_FILE "/etc/storage/libstorage.conf"
42 #define MAX_SECTION 64
43 #define WHITESPACE " \t"
44 #define NEWLINE "\n\r"
47 #define MATCH(a, b) (!strncmp(a, b, strlen(a)))
48 #define SET_CONF(a, b) (a = (b > 0.0 ? b : a))
56 struct storage_config_info {
62 static struct storage_config_info storage_info;
64 static inline char *trim_str(char *s)
68 s += strspn(s, WHITESPACE);
71 for (t = strchr(s, 0); t > s; t--)
72 if (!strchr(WHITESPACE, t[-1]))
78 static int config_parse(const char *file_name, int cb(struct parse_result *result,
79 void *user_data), void *user_data)
82 struct parse_result result;
83 /* use stack for parsing */
85 char section[MAX_SECTION];
86 char *start, *end, *name, *value;
87 int lineno = 0, ret = 0;
89 if (!file_name || !cb) {
95 f = fopen(file_name, "r");
97 _E("Failed to open file %s", file_name); //LCOV_EXCL_LINE
102 /* parsing line by line */
103 while (fgets(line, MAX_LINE, f) != NULL) {
107 start[strcspn(start, NEWLINE)] = '\0';
108 start = trim_str(start);
110 if (*start == COMMENT) {
112 } else if (*start == '[') {
114 end = strchr(start, ']');
115 if (!end || *end != ']') {
121 strncpy(section, start + 1, sizeof(section));
122 section[MAX_SECTION-1] = '\0';
124 /* parse name & value */
125 end = strchr(start, '=');
126 if (!end || *end != '=') {
131 name = trim_str(start);
132 value = trim_str(end + 1);
133 end = strchr(value, COMMENT);
134 if (end && *end == COMMENT) {
136 value = trim_str(value);
139 result.section = section;
141 result.value = value;
142 /* callback with parse result */
143 ret = cb(&result, user_data);
150 _D("Success to load %s", file_name);
157 _E("Failed to read %s:%d!", file_name, lineno); //LCOV_EXCL_LINE
161 static int load_config(struct parse_result *result, void *user_data)
163 static int check_size = -1;
164 struct storage_config_info *info = (struct storage_config_info *)user_data;
171 if (!MATCH(result->section, "STORAGE"))
175 value = result->value;
177 if (info->check_size > 0 && check_size < 0)
178 check_size = (storage_info.total_size < info->check_size) ? 1 : 0;
179 if (MATCH(name, "CHECK_SIZE"))
180 info->check_size = atoi(value);
181 else if (check_size == 0 && MATCH(name, "RESERVE"))
182 info->reserved_size = atoi(value);
183 else if (check_size == 1 && MATCH(name, "RESERVE_LITE"))
184 info->reserved_size = atoi(value);
189 static void storage_config_load(struct storage_config_info *info)
193 ret = config_parse(STORAGE_CONF_FILE, load_config, info);
195 _E("Failed to load %s, %d Use default value!", STORAGE_CONF_FILE, ret); //LCOV_EXCL_LINE
198 static int get_memory_size(const char *path, struct statvfs_32 *buf)
205 ret = statvfs(path, &s);
207 return -errno; //LCOV_EXCL_LINE System Error
209 memset(buf, 0, sizeof(struct statvfs_32));
211 buf->f_bsize = s.f_bsize;
212 buf->f_frsize = s.f_frsize;
213 buf->f_blocks = (unsigned long)s.f_blocks;
214 buf->f_bfree = (unsigned long)s.f_bfree;
215 buf->f_bavail = (unsigned long)s.f_bavail;
216 buf->f_files = (unsigned long)s.f_files;
217 buf->f_ffree = (unsigned long)s.f_ffree;
218 buf->f_favail = (unsigned long)s.f_favail;
219 buf->f_fsid = s.f_fsid;
220 buf->f_flag = s.f_flag;
221 buf->f_namemax = s.f_namemax;
226 /* This api is intended for binaries built with _FILE_OFFSET_BITS=32 */
227 API int storage_get_internal_memory_size(struct statvfs *buf)
229 struct statvfs_32 temp;
230 static unsigned long reserved = 0;
234 _E("input param error");
235 return STORAGE_ERROR_INVALID_PARAMETER;
238 ret = get_memory_size(tzplatform_getenv(TZ_SYS_USER), &temp);
239 if (ret || temp.f_bsize == 0) {
240 _E("fail to get memory size %d", ret); //LCOV_EXCL_LINE
241 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
245 storage_info.total_size = (double)temp.f_frsize * temp.f_blocks;
246 storage_config_load(&storage_info);
247 reserved = (unsigned long)storage_info.reserved_size;
248 reserved = reserved/temp.f_bsize;
249 _I("total %4.4lf check %4.4lf reserved %4.4lf",
250 storage_info.total_size, storage_info.check_size, storage_info.reserved_size);
252 if (temp.f_bavail < reserved)
255 temp.f_bavail -= reserved;
257 memcpy(buf, &temp, sizeof(temp));
258 return STORAGE_ERROR_NONE;
261 /* This api is intended for binaries built with __USE_FILE_OFFSET64(_FILE_OFFSET_BITS=64) */
262 API int storage_get_internal_memory_size64(struct statvfs *buf)
264 static unsigned long reserved = 0;
268 _E("input param error"); //LCOV_EXCL_LINE
269 return STORAGE_ERROR_INVALID_PARAMETER;
272 ret = statvfs(tzplatform_getenv(TZ_SYS_USER), buf);
274 _E("fail to get memory size"); //LCOV_EXCL_LINE
275 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
279 storage_info.total_size = (double)(buf->f_frsize * buf->f_blocks);
280 storage_config_load(&storage_info);
281 reserved = (unsigned long)storage_info.reserved_size;
282 reserved = reserved/buf->f_bsize;
283 _I("total %4.4lf check %4.4lf reserved %4.4lf",
284 storage_info.total_size, storage_info.check_size, storage_info.reserved_size);
286 if (buf->f_bavail < reserved)
289 buf->f_bavail -= reserved;
290 return STORAGE_ERROR_NONE;
293 int mount_check(const char *path)
297 const char *table = "/etc/mtab";
300 fp = setmntent(table, "r");
303 while ((mnt = getmntent(fp))) {
304 if (!strcmp(mnt->mnt_dir, path)) {
313 static int get_external_path(char *path, size_t len)
315 return storage_ext_get_primary_mmc_path(path, len);
318 /* This api is intended for binaries built with _FILE_OFFSET_BITS=32 */
319 int storage_get_external_memory_size_with_path(char *path, struct statvfs *buf)
321 struct statvfs_32 temp;
325 _D("storage_get_external_memory_size");
327 _E("input param error");
328 return STORAGE_ERROR_INVALID_PARAMETER;
332 snprintf(ext_path, sizeof(ext_path), "%s", path);
334 if (!storage_ext_is_supported()) {
335 _D("Block module is not enabled");
336 return STORAGE_ERROR_NOT_SUPPORTED;
338 ret = get_external_path(ext_path, sizeof(ext_path));
342 _E("Failed to get external path(%d)", ret); //LCOV_EXCL_LINE
343 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
347 if (!mount_check((const char *)ext_path))
350 ret = storage_ext_get_statvfs(ext_path, &temp);
352 _E("fail to get memory size"); //LCOV_EXCL_LINE
353 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
356 memcpy(buf, &temp, sizeof(temp));
360 memset(buf, 0, sizeof(struct statvfs_32));
361 return STORAGE_ERROR_NONE;
364 /* This api is intended for binaries built with __USE_FILE_OFFSET64(_FILE_OFFSET_BITS=64) */
365 int storage_get_external_memory_size64_with_path(char *path, struct statvfs *buf)
370 _D("storage_get_external_memory_size64");
372 _E("input param error");
373 return STORAGE_ERROR_INVALID_PARAMETER;
377 snprintf(ext_path, sizeof(ext_path), "%s", path);
379 if (!storage_ext_is_supported()) {
380 _D("Block module is not enabled");
381 return STORAGE_ERROR_NOT_SUPPORTED;
383 ret = get_external_path(ext_path, sizeof(ext_path));
387 _E("Failed to get external path(%d)", ret);
388 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
392 if (!mount_check((const char *)ext_path))
395 ret = storage_ext_get_statvfs_size64(ext_path, buf);
397 //LCOV_EXCL_START System Error
398 _E("fail to get memory size");
399 return STORAGE_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
403 return STORAGE_ERROR_NONE;
406 memset(buf, 0, sizeof(struct statvfs));
410 API int storage_get_external_memory_size(struct statvfs *buf)
412 return storage_get_external_memory_size_with_path(NULL, buf);
415 API int storage_get_external_memory_size64(struct statvfs *buf)
417 return storage_get_external_memory_size64_with_path(NULL, buf);