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"
34 static dd_list *cb_list[STORAGE_CALLBACK_MAX];
36 static int storage_ext_get_dev_state(storage_ext_device *dev,
37 enum storage_ext_state blk_state,
38 storage_state_e *state)
44 case STORAGE_EXT_ADDED:
45 *state = STORAGE_STATE_UNMOUNTABLE;
47 case STORAGE_EXT_REMOVED:
48 *state = STORAGE_STATE_REMOVED;
50 case STORAGE_EXT_CHANGED:
52 case STORAGE_EXT_UNMOUNTED:
53 *state = STORAGE_STATE_UNMOUNTABLE;
55 case STORAGE_EXT_MOUNTED:
56 if (dev->flags & MOUNT_READONLY)
57 *state = STORAGE_STATE_MOUNTED_READ_ONLY;
59 *state = STORAGE_STATE_MOUNTED;
64 case STORAGE_EXT_BLOCKED:
65 *state = STORAGE_STATE_UNMOUNTABLE;
72 int storage_ext_get_space(int storage_id,
73 unsigned long long *total, unsigned long long *available)
75 storage_state_e state;
78 unsigned long long t = 0, a = 0;
79 storage_ext_device *dev;
84 dev = calloc(1, sizeof(storage_ext_device));
86 //LCOV_EXCL_START System Error
92 ret = storage_ext_get_device_info(storage_id, dev);
94 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
98 ret = storage_ext_get_dev_state(dev, STORAGE_EXT_CHANGED, &state);
100 _E("Failed to get state of storage (id:%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
104 if (state >= STORAGE_STATE_MOUNTED) {
105 #ifndef __USE_FILE_OFFSET64
106 ret = storage_get_external_memory_size_with_path(dev->mount_point, &s);
108 ret = storage_get_external_memory_size64_with_path(dev->mount_point, &s);
111 _E("Failed to get external memory size of (%s)(ret:%d)", dev->mount_point, ret); //LCOV_EXCL_LINE
115 t = (unsigned long long)s.f_frsize*s.f_blocks;
116 a = (unsigned long long)s.f_bsize*s.f_bavail;
126 storage_ext_release_device(&dev);
130 int storage_ext_foreach_device_list(storage_device_supported_cb callback, void *user_data)
134 dd_list *list = NULL, *elem;
135 storage_ext_device *dev;
136 storage_state_e state;
141 ret = storage_ext_get_list(&list);
143 _E("Failed to get external storage list from deviced (%d)", errno); //LCOV_EXCL_LINE
147 DD_LIST_FOREACH(list, elem, dev) {
148 ret = storage_ext_get_dev_state(dev, STORAGE_EXT_CHANGED, &state);
150 _E("Failed to get storage state (devnode:%s, ret:%d)", dev->devnode, ret); //LCOV_EXCL_LINE
154 ret_cb = callback(dev->storage_id, STORAGE_TYPE_EXTERNAL,
155 state, dev->mount_point, user_data);
161 storage_ext_release_list(&list);
165 //LCOV_EXCL_START Not called Callback
166 static int storage_ext_id_changed(storage_ext_device *dev, enum storage_ext_state blk_state, void *data)
168 enum storage_cb_type type = (enum storage_cb_type)data;
169 struct storage_cb_info *cb_info;
171 storage_state_e state;
177 if (type != STORAGE_CALLBACK_ID)
180 ret = storage_ext_get_dev_state(dev, blk_state, &state);
182 _E("Failed to get storage state (devnode:%s, ret:%d)", dev->devnode, ret);
186 DD_LIST_FOREACH(cb_list[STORAGE_CALLBACK_ID], elem, cb_info)
187 cb_info->state_cb(cb_info->id, state, cb_info->user_data);
192 static int storage_ext_type_changed(storage_ext_device *dev, enum storage_ext_state blk_state, void *data)
194 enum storage_cb_type type = (enum storage_cb_type)data;
195 struct storage_cb_info *cb_info;
197 storage_state_e state;
199 storage_dev_e strdev;
200 const char *fstype, *fsuuid, *mountpath;
205 if (type != STORAGE_CALLBACK_TYPE)
208 ret = storage_ext_get_dev_state(dev, blk_state, &state);
210 _E("Failed to get storage state (devnode:%s, ret:%d)", dev->devnode, ret);
214 if (dev->type == STORAGE_EXT_SCSI)
215 strdev = STORAGE_DEV_EXT_USB_MASS_STORAGE;
216 else if (dev->type == STORAGE_EXT_MMC)
217 strdev = STORAGE_DEV_EXT_SDCARD;
219 _E("Invalid dev type (%d)", dev->type);
223 fstype = (dev->fs_type ? (const char *)dev->fs_type : "");
224 fsuuid = (dev->fs_uuid ? (const char *)dev->fs_uuid : "");
225 mountpath = (dev->mount_point ? (const char *)dev->mount_point : "");
227 DD_LIST_FOREACH(cb_list[STORAGE_CALLBACK_TYPE], elem, cb_info)
228 if (cb_info->type_cb)
229 cb_info->type_cb(dev->storage_id, strdev, state,
230 fstype, fsuuid, mountpath, dev->primary,
231 dev->flags, cb_info->user_data);
238 static bool check_if_callback_exist(enum storage_cb_type type,
239 struct storage_cb_info *info, struct storage_cb_info **cb_data)
241 struct storage_cb_info *cb_info;
247 if (type == STORAGE_CALLBACK_ID) {
248 DD_LIST_FOREACH(cb_list[type], elem, cb_info) {
249 if (cb_info->id == info->id &&
250 cb_info->state_cb == info->state_cb) {
256 if (type == STORAGE_CALLBACK_TYPE) {
257 DD_LIST_FOREACH(cb_list[type], elem, cb_info) {
258 if (cb_info->type == info->type &&
259 cb_info->type_cb == info->type_cb)
273 int storage_ext_register_cb(enum storage_cb_type type, struct storage_cb_info *info)
275 struct storage_cb_info *cb_info;
277 storage_ext_changed_cb callback;
283 case STORAGE_CALLBACK_ID:
284 callback = storage_ext_id_changed;
286 case STORAGE_CALLBACK_TYPE:
287 callback = storage_ext_type_changed;
290 _E("Invalid callback type (%d)", type);
294 n = DD_LIST_LENGTH(cb_list[type]);
296 ret = storage_ext_register_device_change(callback, (void *)type);
301 if (check_if_callback_exist(type, info, NULL)) {
302 _E("The callback is already registered");
306 /* add device changed callback to list (local) */
307 cb_info = malloc(sizeof(struct storage_cb_info));
311 memcpy(cb_info, info, sizeof(struct storage_cb_info));
312 DD_LIST_APPEND(cb_list[type], cb_info);
317 int storage_ext_unregister_cb(enum storage_cb_type type, struct storage_cb_info *info)
319 struct storage_cb_info *cb_info;
321 storage_ext_changed_cb callback;
327 case STORAGE_CALLBACK_ID:
328 callback = storage_ext_id_changed;
330 case STORAGE_CALLBACK_TYPE:
331 callback = storage_ext_type_changed;
334 _E("Invalid callback type (%d)", type);
338 if (!check_if_callback_exist(type, info, &cb_info)) {
339 _E("The callback is not registered");
343 /* remove device callback from list (local) */
345 DD_LIST_REMOVE(cb_list[type], cb_info);
349 /* check if this callback is last element */
350 n = DD_LIST_LENGTH(cb_list[type]);
352 storage_ext_unregister_device_change(callback);
357 int storage_ext_get_root(int storage_id, char *path, size_t len)
360 storage_ext_device *dev;
361 char file_name[PATH_LEN];
371 snprintf(file_name, PATH_LEN, EXTERNAL_STORAGE_PATH"/%d", storage_id);
373 if (access(file_name, R_OK) == 0) {
374 fp = fopen(file_name, "r");
376 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
381 tmp = fgets(path, len, fp);
385 _D("Failed to get path");
390 dev = calloc(1, sizeof(storage_ext_device));
392 //LCOV_EXCL_START System Error
398 ret = storage_ext_get_device_info(storage_id, dev);
400 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
401 storage_ext_release_device(&dev);
405 snprintf(path, len, "%s", dev->mount_point);
406 storage_ext_release_device(&dev);
415 int storage_ext_get_state(int storage_id, storage_state_e *state)
417 storage_ext_device *dev;
426 dev = calloc(1, sizeof(storage_ext_device));
428 //LCOV_EXCL_START System Error
434 ret = storage_ext_get_device_info(storage_id, dev);
436 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
440 ret = storage_ext_get_dev_state(dev, STORAGE_EXT_CHANGED, state);
442 _E("Failed to get state of storage id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
445 storage_ext_release_device(&dev);
449 int storage_ext_get_primary_mmc_path(char *path, size_t len)
451 dd_list *list = NULL, *elem;
452 storage_ext_device *dev;
455 ret = storage_ext_get_list(&list);
457 _E("Failed to get external storage list from deviced (%d)", errno); //LCOV_EXCL_LINE
461 DD_LIST_FOREACH(list, elem, dev) {
463 snprintf(path, len, "%s", dev->mount_point);
473 storage_ext_release_list(&list);