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/storaged/external-storage"
32 #define EXTENDED_INTERNAL_PATH "/run/storaged/extended-internal-sd"
35 #define LUKS_NAME "crypto_LUKS"
37 static dd_list *cb_list[STORAGE_CALLBACK_MAX];
39 static int storage_ext_get_dev_state(storage_ext_device *dev,
40 enum storage_ext_state blk_state,
41 storage_state_e *state)
47 case STORAGE_EXT_ADDED:
48 *state = STORAGE_STATE_UNMOUNTABLE;
50 case STORAGE_EXT_REMOVED:
51 *state = STORAGE_STATE_REMOVED;
53 case STORAGE_EXT_CHANGED:
55 case STORAGE_EXT_UNMOUNTED:
56 *state = STORAGE_STATE_UNMOUNTABLE;
58 case STORAGE_EXT_MOUNTED:
59 if (dev->flags & MOUNT_READONLY)
60 *state = STORAGE_STATE_MOUNTED_READ_ONLY;
62 *state = STORAGE_STATE_MOUNTED;
67 case STORAGE_EXT_BLOCKED:
68 *state = STORAGE_STATE_UNMOUNTABLE;
75 int storage_ext_get_space(int storage_id,
76 unsigned long long *total, unsigned long long *available)
78 storage_state_e state;
81 unsigned long long t = 0, a = 0;
82 storage_ext_device *dev;
87 dev = calloc(1, sizeof(storage_ext_device));
89 //LCOV_EXCL_START System Error
95 ret = storage_ext_get_device_info(storage_id, dev);
97 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
101 ret = storage_ext_get_dev_state(dev, STORAGE_EXT_CHANGED, &state);
103 _E("Failed to get state of storage (id:%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
107 if (state >= STORAGE_STATE_MOUNTED) {
108 #ifdef __USE_FILE_OFFSET64
109 ret = storage_get_external_memory_size64_with_path(dev->mount_point, &s);
111 ret = storage_get_external_memory_size_with_path(dev->mount_point, &s);
114 _E("Failed to get external memory size of (%s)(ret:%d)", dev->mount_point, ret); //LCOV_EXCL_LINE
118 t = (unsigned long long)s.f_frsize*s.f_blocks;
119 a = (unsigned long long)s.f_bsize*s.f_bavail;
129 storage_ext_release_device(&dev);
133 int storage_ext_foreach_device_list(storage_device_supported_cb callback, void *user_data)
137 dd_list *list = NULL, *elem;
138 storage_ext_device *dev;
139 storage_state_e state;
144 ret = storage_ext_get_list(&list);
146 _E("Failed to get external storage list from deviced (%d)", errno); //LCOV_EXCL_LINE
150 DD_LIST_FOREACH(list, elem, dev) {
151 ret = storage_ext_get_dev_state(dev, STORAGE_EXT_CHANGED, &state);
153 _E("Failed to get storage state (devnode:%s, ret:%d)", dev->devnode, ret); //LCOV_EXCL_LINE
157 if (dev->type == STORAGE_EXT_MMC_EXTENDED_INTERNAL)
158 ret_cb = callback(dev->storage_id,
159 STORAGE_TYPE_EXTENDED_INTERNAL,
160 state, dev->mount_point, user_data);
162 ret_cb = callback(dev->storage_id, STORAGE_TYPE_EXTERNAL,
163 state, dev->mount_point, user_data);
169 storage_ext_release_list(&list);
173 //LCOV_EXCL_START Not called Callback
174 static int storage_ext_id_changed(storage_ext_device *dev, enum storage_ext_state blk_state, void *data)
176 enum storage_cb_type type = (enum storage_cb_type)data;
177 struct storage_cb_info *cb_info;
179 storage_state_e state;
185 if (type != STORAGE_CALLBACK_ID)
188 ret = storage_ext_get_dev_state(dev, blk_state, &state);
190 _E("Failed to get storage state (devnode:%s, ret:%d)", dev->devnode, ret);
194 DD_LIST_FOREACH(cb_list[STORAGE_CALLBACK_ID], elem, cb_info)
195 cb_info->state_cb(cb_info->id, state, cb_info->user_data);
200 static int storage_ext_type_changed(storage_ext_device *dev, enum storage_ext_state blk_state, void *data)
202 enum storage_cb_type type = (enum storage_cb_type)data;
203 struct storage_cb_info *cb_info;
205 storage_state_e state;
207 storage_dev_e strdev;
208 storage_type_e storage_type;
209 const char *fstype, *fsuuid, *mountpath;
214 if (type != STORAGE_CALLBACK_TYPE)
217 ret = storage_ext_get_dev_state(dev, blk_state, &state);
219 _E("Failed to get storage state (devnode:%s, ret:%d)", dev->devnode, ret);
223 if (dev->type == STORAGE_EXT_SCSI) {
224 strdev = STORAGE_DEV_EXT_USB_MASS_STORAGE;
225 storage_type = STORAGE_TYPE_EXTERNAL;
226 } else if (dev->type == STORAGE_EXT_MMC) {
227 strdev = STORAGE_DEV_EXT_SDCARD;
228 storage_type = STORAGE_TYPE_EXTERNAL;
229 } else if (dev->type == STORAGE_EXT_MMC_EXTENDED_INTERNAL) {
230 strdev = STORAGE_DEV_EXTENDED_INTERNAL;
231 storage_type = STORAGE_TYPE_EXTENDED_INTERNAL;
233 _E("Invalid dev type (%d)", dev->type);
237 fstype = (dev->fs_type ? (const char *)dev->fs_type : "");
238 fsuuid = (dev->fs_uuid ? (const char *)dev->fs_uuid : "");
239 mountpath = (dev->mount_point ? (const char *)dev->mount_point : "");
241 if (!strncmp(fstype, LUKS_NAME, strlen(LUKS_NAME)))
242 storage_type = STORAGE_TYPE_EXTENDED_INTERNAL;
244 DD_LIST_FOREACH(cb_list[STORAGE_CALLBACK_TYPE], elem, cb_info) {
245 if (cb_info->type != storage_type)
247 if (cb_info->type_cb)
248 cb_info->type_cb(dev->storage_id, strdev, state,
249 fstype, fsuuid, mountpath, dev->primary,
250 dev->flags, cb_info->user_data);
258 static bool check_if_callback_exist(enum storage_cb_type type,
259 struct storage_cb_info *info, struct storage_cb_info **cb_data)
261 struct storage_cb_info *cb_info;
267 if (type == STORAGE_CALLBACK_ID) {
268 DD_LIST_FOREACH(cb_list[type], elem, cb_info) {
269 if (cb_info->id == info->id &&
270 cb_info->state_cb == info->state_cb) {
276 if (type == STORAGE_CALLBACK_TYPE) {
277 DD_LIST_FOREACH(cb_list[type], elem, cb_info) {
278 if (cb_info->type == info->type &&
279 cb_info->type_cb == info->type_cb)
293 int storage_ext_register_cb(enum storage_cb_type type, struct storage_cb_info *info)
295 struct storage_cb_info *cb_info;
297 storage_ext_changed_cb callback;
303 case STORAGE_CALLBACK_ID:
304 callback = storage_ext_id_changed;
306 case STORAGE_CALLBACK_TYPE:
307 callback = storage_ext_type_changed;
310 _E("Invalid callback type (%d)", type);
314 n = DD_LIST_LENGTH(cb_list[type]);
316 ret = storage_ext_register_device_change(callback, (void *)type);
321 if (check_if_callback_exist(type, info, NULL)) {
322 _E("The callback is already registered");
326 /* add device changed callback to list (local) */
327 cb_info = malloc(sizeof(struct storage_cb_info));
331 memcpy(cb_info, info, sizeof(struct storage_cb_info));
332 DD_LIST_APPEND(cb_list[type], cb_info);
337 int storage_ext_unregister_cb(enum storage_cb_type type, struct storage_cb_info *info)
339 struct storage_cb_info *cb_info;
341 storage_ext_changed_cb callback;
347 case STORAGE_CALLBACK_ID:
348 callback = storage_ext_id_changed;
350 case STORAGE_CALLBACK_TYPE:
351 callback = storage_ext_type_changed;
354 _E("Invalid callback type (%d)", type);
358 if (!check_if_callback_exist(type, info, &cb_info)) {
359 _E("The callback is not registered");
363 /* remove device callback from list (local) */
365 DD_LIST_REMOVE(cb_list[type], cb_info);
369 /* check if this callback is last element */
370 n = DD_LIST_LENGTH(cb_list[type]);
372 storage_ext_unregister_device_change(callback);
377 int storage_ext_get_root(int storage_id, char *path, size_t len, bool *extendedinternal)
380 storage_ext_device *dev;
381 char file_name[PATH_LEN];
382 char file_name2[PATH_LEN];
391 if (!extendedinternal)
394 snprintf(file_name, PATH_LEN, EXTERNAL_STORAGE_PATH"/%d", storage_id);
395 snprintf(file_name2, PATH_LEN, EXTENDED_INTERNAL_PATH"/%d", storage_id);
397 *extendedinternal = false;
399 if (access(file_name, R_OK) == 0) {
400 fp = fopen(file_name, "r");
402 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
407 tmp = fgets(path, len, fp);
411 _D("Failed to get path");
414 *extendedinternal = false;
415 } else if (access(file_name2, R_OK) == 0) {
416 fp = fopen(file_name2, "r");
418 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
423 tmp = fgets(path, len, fp);
427 _D("Failed to get path");
430 *extendedinternal = true;
432 dev = calloc(1, sizeof(storage_ext_device));
434 //LCOV_EXCL_START System Error
440 ret = storage_ext_get_device_info(storage_id, dev);
442 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
443 storage_ext_release_device(&dev);
447 snprintf(path, len, "%s", dev->mount_point);
448 if (dev->type == STORAGE_EXT_MMC_EXTENDED_INTERNAL)
449 *extendedinternal = true;
451 *extendedinternal = false;
452 storage_ext_release_device(&dev);
461 int storage_ext_get_state(int storage_id, storage_state_e *state)
463 storage_ext_device *dev;
472 dev = calloc(1, sizeof(storage_ext_device));
474 //LCOV_EXCL_START System Error
480 ret = storage_ext_get_device_info(storage_id, dev);
482 _E("Cannot get the storage with id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
486 ret = storage_ext_get_dev_state(dev, STORAGE_EXT_CHANGED, state);
488 _E("Failed to get state of storage id (%d, ret:%d)", storage_id, ret); //LCOV_EXCL_LINE
491 storage_ext_release_device(&dev);
495 int storage_ext_get_primary_mmc_path(char *path, size_t len)
497 dd_list *list = NULL, *elem;
498 storage_ext_device *dev;
501 ret = storage_ext_get_list(&list);
503 _E("Failed to get external storage list from deviced (%d)", errno); //LCOV_EXCL_LINE
507 DD_LIST_FOREACH(list, elem, dev) {
509 snprintf(path, len, "%s", dev->mount_point);
519 storage_ext_release_list(&list);