2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #include <sys/statvfs.h>
24 #include <tzplatform_config.h>
29 #include "storage-external-dbus.h"
31 #define EXTERNAL_STORAGE_PATH "/run/external-storage"
32 #define EXTENDED_INTERNAL_PATH "/run/extended-internal-sd"
35 static dd_list *cb_list[STORAGE_CALLBACK_MAX];
37 static int storage_ext_get_dev_state(storage_ext_device *dev,
38 enum storage_ext_state blk_state,
39 storage_state_e *state)
45 case STORAGE_EXT_ADDED:
46 *state = STORAGE_STATE_UNMOUNTABLE;
48 case STORAGE_EXT_REMOVED:
49 *state = STORAGE_STATE_REMOVED;
51 case STORAGE_EXT_CHANGED:
53 case STORAGE_EXT_UNMOUNTED:
54 *state = STORAGE_STATE_UNMOUNTABLE;
56 case STORAGE_EXT_MOUNTED:
57 if (dev->flags & MOUNT_READONLY)
58 *state = STORAGE_STATE_MOUNTED_READ_ONLY;
60 *state = STORAGE_STATE_MOUNTED;
65 case STORAGE_EXT_BLOCKED:
66 *state = STORAGE_STATE_UNMOUNTABLE;
73 int storage_ext_get_space(int storage_id,
74 unsigned long long *total, unsigned long long *available)
76 storage_state_e state;
79 unsigned long long t = 0, a = 0;
80 storage_ext_device *dev;
85 dev = calloc(1, sizeof(storage_ext_device));
87 //LCOV_EXCL_START System Error
93 ret = storage_ext_get_device_info(storage_id, dev);
95 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
99 ret = storage_ext_get_dev_state(dev, STORAGE_EXT_CHANGED, &state);
101 _E("Failed to get state of storage (id:%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
105 if (state >= STORAGE_STATE_MOUNTED) {
106 #ifndef __USE_FILE_OFFSET64
107 ret = storage_get_external_memory_size_with_path(dev->mount_point, &s);
109 ret = storage_get_external_memory_size64_with_path(dev->mount_point, &s);
112 _E("Failed to get external memory size of (%s)(ret:%d)", dev->mount_point, ret); //LCOV_EXCL_LINE
116 t = (unsigned long long)s.f_frsize*s.f_blocks;
117 a = (unsigned long long)s.f_bsize*s.f_bavail;
127 storage_ext_release_device(&dev);
131 int storage_ext_foreach_device_list(storage_device_supported_cb callback, void *user_data)
135 dd_list *list = NULL, *elem;
136 storage_ext_device *dev;
137 storage_state_e state;
142 ret = storage_ext_get_list(&list);
144 _E("Failed to get external storage list from deviced (%d)", errno); //LCOV_EXCL_LINE
148 DD_LIST_FOREACH(list, elem, dev) {
149 ret = storage_ext_get_dev_state(dev, STORAGE_EXT_CHANGED, &state);
151 _E("Failed to get storage state (devnode:%s, ret:%d)", dev->devnode, ret); //LCOV_EXCL_LINE
155 if (dev->type == STORAGE_EXT_MMC_EXTENDED_INTERNAL)
156 ret_cb = callback(dev->storage_id,
157 STORAGE_TYPE_EXTENDED_INTERNAL,
158 state, dev->mount_point, user_data);
160 ret_cb = callback(dev->storage_id, STORAGE_TYPE_EXTERNAL,
161 state, dev->mount_point, user_data);
167 storage_ext_release_list(&list);
171 //LCOV_EXCL_START Not called Callback
172 static int storage_ext_id_changed(storage_ext_device *dev, enum storage_ext_state blk_state, void *data)
174 enum storage_cb_type type = (enum storage_cb_type)data;
175 struct storage_cb_info *cb_info;
177 storage_state_e state;
183 if (type != STORAGE_CALLBACK_ID)
186 ret = storage_ext_get_dev_state(dev, blk_state, &state);
188 _E("Failed to get storage state (devnode:%s, ret:%d)", dev->devnode, ret);
192 DD_LIST_FOREACH(cb_list[STORAGE_CALLBACK_ID], elem, cb_info)
193 cb_info->state_cb(cb_info->id, state, cb_info->user_data);
198 static int storage_ext_type_changed(storage_ext_device *dev, enum storage_ext_state blk_state, void *data)
200 enum storage_cb_type type = (enum storage_cb_type)data;
201 struct storage_cb_info *cb_info;
203 storage_state_e state;
205 storage_dev_e strdev;
206 const char *fstype, *fsuuid, *mountpath;
211 if (type != STORAGE_CALLBACK_TYPE)
214 ret = storage_ext_get_dev_state(dev, blk_state, &state);
216 _E("Failed to get storage state (devnode:%s, ret:%d)", dev->devnode, ret);
220 if (dev->type == STORAGE_EXT_SCSI)
221 strdev = STORAGE_DEV_EXT_USB_MASS_STORAGE;
222 else if (dev->type == STORAGE_EXT_MMC)
223 strdev = STORAGE_DEV_EXT_SDCARD;
224 else if (dev->type == STORAGE_EXT_MMC_EXTENDED_INTERNAL)
225 strdev = STORAGE_DEV_EXTENDED_INTERNAL;
227 _E("Invalid dev type (%d)", dev->type);
231 fstype = (dev->fs_type ? (const char *)dev->fs_type : "");
232 fsuuid = (dev->fs_uuid ? (const char *)dev->fs_uuid : "");
233 mountpath = (dev->mount_point ? (const char *)dev->mount_point : "");
235 DD_LIST_FOREACH(cb_list[STORAGE_CALLBACK_TYPE], elem, cb_info)
236 if (cb_info->type_cb)
237 cb_info->type_cb(dev->storage_id, strdev, state,
238 fstype, fsuuid, mountpath, dev->primary,
239 dev->flags, cb_info->user_data);
246 static bool check_if_callback_exist(enum storage_cb_type type,
247 struct storage_cb_info *info, struct storage_cb_info **cb_data)
249 struct storage_cb_info *cb_info;
255 if (type == STORAGE_CALLBACK_ID) {
256 DD_LIST_FOREACH(cb_list[type], elem, cb_info) {
257 if (cb_info->id == info->id &&
258 cb_info->state_cb == info->state_cb) {
264 if (type == STORAGE_CALLBACK_TYPE) {
265 DD_LIST_FOREACH(cb_list[type], elem, cb_info) {
266 if (cb_info->type == info->type &&
267 cb_info->type_cb == info->type_cb)
281 int storage_ext_register_cb(enum storage_cb_type type, struct storage_cb_info *info)
283 struct storage_cb_info *cb_info;
285 storage_ext_changed_cb callback;
291 case STORAGE_CALLBACK_ID:
292 callback = storage_ext_id_changed;
294 case STORAGE_CALLBACK_TYPE:
295 callback = storage_ext_type_changed;
298 _E("Invalid callback type (%d)", type);
302 n = DD_LIST_LENGTH(cb_list[type]);
304 ret = storage_ext_register_device_change(callback, (void *)type);
309 if (check_if_callback_exist(type, info, NULL)) {
310 _E("The callback is already registered");
314 /* add device changed callback to list (local) */
315 cb_info = malloc(sizeof(struct storage_cb_info));
319 memcpy(cb_info, info, sizeof(struct storage_cb_info));
320 DD_LIST_APPEND(cb_list[type], cb_info);
325 int storage_ext_unregister_cb(enum storage_cb_type type, struct storage_cb_info *info)
327 struct storage_cb_info *cb_info;
329 storage_ext_changed_cb callback;
335 case STORAGE_CALLBACK_ID:
336 callback = storage_ext_id_changed;
338 case STORAGE_CALLBACK_TYPE:
339 callback = storage_ext_type_changed;
342 _E("Invalid callback type (%d)", type);
346 if (!check_if_callback_exist(type, info, &cb_info)) {
347 _E("The callback is not registered");
351 /* remove device callback from list (local) */
353 DD_LIST_REMOVE(cb_list[type], cb_info);
357 /* check if this callback is last element */
358 n = DD_LIST_LENGTH(cb_list[type]);
360 storage_ext_unregister_device_change(callback);
365 int storage_ext_get_root(int storage_id, char *path, size_t len, bool *extendedinternal)
368 storage_ext_device *dev;
369 char file_name[PATH_LEN];
370 char file_name2[PATH_LEN];
379 if (!extendedinternal)
382 snprintf(file_name, PATH_LEN, EXTERNAL_STORAGE_PATH"/%d", storage_id);
383 snprintf(file_name2, PATH_LEN, EXTENDED_INTERNAL_PATH"/%d", storage_id);
385 *extendedinternal = false;
387 if (access(file_name, R_OK) == 0) {
388 fp = fopen(file_name, "r");
390 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
395 tmp = fgets(path, len, fp);
399 _D("Failed to get path");
402 *extendedinternal = false;
403 } else if (access(file_name2, R_OK) == 0) {
404 fp = fopen(file_name2, "r");
406 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
411 tmp = fgets(path, len, fp);
415 _D("Failed to get path");
418 *extendedinternal = true;
420 dev = calloc(1, sizeof(storage_ext_device));
422 //LCOV_EXCL_START System Error
428 ret = storage_ext_get_device_info(storage_id, dev);
430 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
431 storage_ext_release_device(&dev);
435 snprintf(path, len, "%s", dev->mount_point);
436 if (dev->type == STORAGE_EXT_MMC_EXTENDED_INTERNAL)
437 *extendedinternal = true;
439 *extendedinternal = false;
440 storage_ext_release_device(&dev);
449 int storage_ext_get_state(int storage_id, storage_state_e *state)
451 storage_ext_device *dev;
460 dev = calloc(1, sizeof(storage_ext_device));
462 //LCOV_EXCL_START System Error
468 ret = storage_ext_get_device_info(storage_id, dev);
470 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
474 ret = storage_ext_get_dev_state(dev, STORAGE_EXT_CHANGED, state);
476 _E("Failed to get state of storage id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
479 storage_ext_release_device(&dev);
483 int storage_ext_get_primary_mmc_path(char *path, size_t len)
485 dd_list *list = NULL, *elem;
486 storage_ext_device *dev;
489 ret = storage_ext_get_list(&list);
491 _E("Failed to get external storage list from deviced (%d)", errno); //LCOV_EXCL_LINE
495 DD_LIST_FOREACH(list, elem, dev) {
497 snprintf(path, len, "%s", dev->mount_point);
507 storage_ext_release_list(&list);