external: support foreach function for external storages 11/67711/5
authorTaeyoung Kim <ty317.kim@samsung.com>
Thu, 28 Apr 2016 06:25:59 +0000 (15:25 +0900)
committerTaeyoung Kim <ty317.kim@samsung.com>
Fri, 29 Apr 2016 01:21:26 +0000 (10:21 +0900)
- External storage information can be get from deviced.
  Thus the dbus method call from deviced is used to
  get the information.

Change-Id: Iac56c26ed766b8a72a78ba970152c7105b0672a1
Signed-off-by: Taeyoung Kim <ty317.kim@samsung.com>
CMakeLists.txt
packaging/libstorage.spec
src/storage-external-dbus.c [new file with mode: 0755]
src/storage-external-dbus.h [new file with mode: 0644]
src/storage-external.c [new file with mode: 0755]
src/storage-external.h [new file with mode: 0755]
src/storage-sdcard.c [deleted file]
src/storage.c

index a846ba6..56482b0 100644 (file)
@@ -10,7 +10,15 @@ SET(VERSION 0.1)
 SET(INC_DIR include)
 INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/${INC_DIR})
 
-SET(dependents "dlog capi-base-common vconf glib-2.0 libtzplatform-config capi-system-system-settings")
+SET(dependents
+               dlog
+               capi-base-common
+               vconf
+               glib-2.0
+               gio-2.0
+               libtzplatform-config
+               capi-system-system-settings
+)
 SET(pc_dependents "capi-base-common")
 
 INCLUDE(FindPkgConfig)
@@ -36,7 +44,8 @@ SET(SRCS
        src/statvfs.c
        src/storage.c
        src/storage-internal.c
-       src/storage-sdcard.c)
+       src/storage-external.c
+       src/storage-external-dbus.c)
 
 ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${TARGET_SRCS})
 TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${rpkgs_LDFLAGS})
index 9f1087a..0204e53 100644 (file)
@@ -11,6 +11,7 @@ BuildRequires:  pkgconfig(dlog)
 BuildRequires:  pkgconfig(capi-base-common)
 BuildRequires:  pkgconfig(vconf)
 BuildRequires:  pkgconfig(glib-2.0)
+BuildRequires:  pkgconfig(gio-2.0)
 BuildRequires:  pkgconfig(libtzplatform-config)
 BuildRequires:  pkgconfig(capi-system-system-settings)
 
diff --git a/src/storage-external-dbus.c b/src/storage-external-dbus.c
new file mode 100755 (executable)
index 0000000..1f39362
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * libstorage
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <vconf.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <gio/gio.h>
+#include <glib.h>
+#include <limits.h>
+
+#include "log.h"
+#include "storage-external-dbus.h"
+
+#define CHECK_STR(a) (a ? a : "")
+
+#define STORAGE_EXT_GET_LIST       "GetDeviceList"
+
+#define DBUS_REPLY_TIMEOUT (-1)
+
+static void storage_ext_release_internal(storage_ext_device *dev)
+{
+       if (!dev)
+               return;
+       free(dev->devnode);
+       free(dev->syspath);
+       free(dev->fs_usage);
+       free(dev->fs_type);
+       free(dev->fs_version);
+       free(dev->fs_uuid);
+       free(dev->mount_point);
+}
+
+void storage_ext_release_device(storage_ext_device **dev)
+{
+       if (!dev || !*dev)
+               return;
+       storage_ext_release_internal(*dev);
+       free(*dev);
+       *dev = NULL;
+}
+
+void storage_ext_release_list(dd_list **list)
+{
+       storage_ext_device *dev;
+       dd_list *elem;
+
+       if (*list == NULL)
+               return;
+
+       DD_LIST_FOREACH(*list, elem, dev) {
+               storage_ext_release_internal(dev);
+               free(dev);
+       }
+
+       g_list_free(*list);
+       *list = NULL;
+}
+
+static GDBusConnection *get_dbus_connection(void)
+{
+       GError *err = NULL;
+       static GDBusConnection *conn;
+
+       if (conn)
+               return conn;
+
+#if !GLIB_CHECK_VERSION(2, 35, 0)
+       g_type_init();
+#endif
+
+       conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+       if (!conn) {
+               if (err) {
+                       _E("fail to get dbus connection : %s", err->message);
+                       g_clear_error(&err);
+               } else
+                       _E("fail to get dbus connection");
+               return NULL;
+       }
+       return conn;
+}
+
+static GVariant *dbus_method_call_sync(const gchar *dest, const gchar *path,
+                               const gchar *iface, const gchar *method, GVariant *param)
+{
+       GDBusConnection *conn;
+       GError *err = NULL;
+       GVariant *ret;
+
+       if (!dest || !path || !iface || !method || !param)
+               return NULL;
+
+       conn = get_dbus_connection();
+       if (!conn) {
+               _E("fail to get dbus connection");
+               return NULL;
+       }
+
+       ret = g_dbus_connection_call_sync(conn,
+                       dest, path, iface, method,
+                       param, NULL, G_DBUS_CALL_FLAGS_NONE,
+                       -1, NULL, &err);
+       if (!ret) {
+               if (err) {
+                       _E("dbus method sync call failed(%s)", err->message);
+                       g_clear_error(&err);
+               } else
+                       _E("g_dbus_connection_call_sync() failed");
+               return NULL;
+       }
+
+       return ret;
+}
+
+int storage_ext_get_list(dd_list **list)
+{
+       GVariant *result;
+       GVariantIter *iter;
+       storage_ext_device *elem, info;
+       int ret;
+
+       if (!list)
+               return -EINVAL;
+
+       result = dbus_method_call_sync(STORAGE_EXT_BUS_NAME,
+                       STORAGE_EXT_PATH_MANAGER,
+                       STORAGE_EXT_IFACE_MANAGER,
+                       STORAGE_EXT_GET_LIST,
+                       g_variant_new("(s)", "all"));
+       if (!result) {
+               _E("Failed to get storage_ext device info");
+               return -EIO;
+       }
+
+       g_variant_get(result, "(a(issssssisibii))", &iter);
+
+       while (g_variant_iter_loop(iter, "(issssssisibii)",
+                               &info.type, &info.devnode, &info.syspath,
+                               &info.fs_usage, &info.fs_type,
+                               &info.fs_version, &info.fs_uuid,
+                               &info.readonly, &info.mount_point,
+                               &info.state, &info.primary,
+                               &info.flags, &info.storage_id)) {
+
+               elem = (storage_ext_device *)malloc(sizeof(storage_ext_device));
+               if (!elem) {
+                       _E("malloc() failed");
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               elem->type = info.type;
+               elem->readonly = info.readonly;
+               elem->state = info.state;
+               elem->primary = info.primary;
+               elem->devnode = strdup(CHECK_STR(info.devnode));
+               elem->syspath = strdup(CHECK_STR(info.syspath));
+               elem->fs_usage = strdup(CHECK_STR(info.fs_usage));
+               elem->fs_type = strdup(CHECK_STR(info.fs_type));
+               elem->fs_version = strdup(CHECK_STR(info.fs_version));
+               elem->fs_uuid = strdup(CHECK_STR(info.fs_uuid));
+               elem->mount_point = strdup(CHECK_STR(info.mount_point));
+               elem->flags = info.flags;
+               elem->storage_id = info.storage_id;
+
+               DD_LIST_APPEND(*list, elem);
+       }
+
+       ret = g_list_length(*list);
+
+out:
+       if (ret < 0)
+               storage_ext_release_list(list);
+       g_variant_iter_free(iter);
+       g_variant_unref(result);
+       return ret;
+}
diff --git a/src/storage-external-dbus.h b/src/storage-external-dbus.h
new file mode 100644 (file)
index 0000000..7a0867a
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * libstorage
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef __STORAGE_EXTERNAL_DBUS_H__
+#define __STORAGE_EXTERNAL_DBUS_H__
+
+#include <stdbool.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include "list.h"
+
+#define STORAGE_EXT_BUS_NAME              "org.tizen.system.deviced"
+#define STORAGE_EXT_PATH                  "/Org/Tizen/System/DeviceD/Block"
+#define STORAGE_EXT_PATH_DEVICES          STORAGE_EXT_PATH"/Devices"
+#define STORAGE_EXT_PATH_MANAGER          STORAGE_EXT_PATH"/Manager"
+#define STORAGE_EXT_IFACE                 STORAGE_EXT_BUS_NAME".Block"
+#define STORAGE_EXT_IFACE_MANAGER         STORAGE_EXT_BUS_NAME".BlockManager"
+
+enum mount_state {
+       STORAGE_EXT_UNMOUNTED,
+       STORAGE_EXT_MOUNTED,
+};
+
+enum storage_ext_state {
+       STORAGE_EXT_REMOVED,
+       STORAGE_EXT_ADDED,
+       STORAGE_EXT_CHANGED,
+};
+
+enum storage_ext_type {
+       STORAGE_EXT_SCSI,
+       STORAGE_EXT_MMC,
+};
+
+enum storage_ext_flags {
+       FLAG_NONE        = 0,
+       UNMOUNT_UNSAFE   = 1 << 0,
+       FS_BROKEN        = 1 << 1,
+       FS_EMPTY         = 1 << 2,
+       FS_NOT_SUPPORTED = 1 << 3,
+       MOUNT_READONLY   = 1 << 4,
+};
+
+typedef struct _storage_ext_device {
+       enum storage_ext_type type;
+       char *devnode;
+       char *syspath;
+       char *fs_usage;
+       char *fs_type;
+       char *fs_version;
+       char *fs_uuid;
+       bool readonly;
+       char *mount_point;
+       enum mount_state state;
+       bool primary;   /* the first partition */
+       int flags;
+       int storage_id;
+} storage_ext_device;
+
+void storage_ext_release_device(storage_ext_device **dev);
+void storage_ext_release_list(dd_list **list);
+int storage_ext_get_list(dd_list **list);
+
+#endif /* __STORAGE_EXTERNAL_DBUS_H__ */
diff --git a/src/storage-external.c b/src/storage-external.c
new file mode 100755 (executable)
index 0000000..c671645
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/statvfs.h>
+#include <vconf.h>
+#include <tzplatform_config.h>
+
+#include "common.h"
+#include "list.h"
+#include "log.h"
+#include "storage-external-dbus.h"
+
+static int storage_ext_get_dev_state(storage_ext_device *dev,
+               enum storage_ext_state blk_state,
+               storage_state_e *state)
+{
+       if (!dev || !state)
+               return -EINVAL;
+
+       switch (blk_state) {
+       case STORAGE_EXT_REMOVED:
+               *state = STORAGE_STATE_REMOVED;
+               return 0;
+       case STORAGE_EXT_CHANGED:
+               switch (dev->state) {
+               case STORAGE_EXT_UNMOUNTED:
+                       *state = STORAGE_STATE_UNMOUNTABLE;
+                       return 0;
+               case STORAGE_EXT_MOUNTED:
+                       if (dev->flags & MOUNT_READONLY)
+                               *state = STORAGE_STATE_MOUNTED_READ_ONLY;
+                       else
+                               *state = STORAGE_STATE_MOUNTED;
+                       return 0;
+               default:
+                       return -EINVAL;
+               }
+       default:
+               return -EINVAL;
+       }
+}
+
+int storage_ext_foreach_device_list(storage_device_supported_cb callback, void *user_data)
+{
+       int ret;
+       bool ret_cb;
+       dd_list *list = NULL, *elem;
+       storage_ext_device *dev;
+       storage_state_e state;
+
+       if (!callback)
+               return -EINVAL;
+
+       ret = storage_ext_get_list(&list);
+       if (ret < 0) {
+               _E("Failed to get external storage list from deviced (%d)", errno);
+               return ret;
+       }
+
+       DD_LIST_FOREACH(list, elem, dev) {
+               ret = storage_ext_get_dev_state(dev, STORAGE_EXT_CHANGED, &state);
+               if (ret < 0) {
+                       _E("Failed to get storage state (devnode:%s, ret:%d)", dev->devnode, ret);
+                       continue;
+               }
+
+               ret_cb = callback(dev->storage_id, STORAGE_TYPE_EXTERNAL,
+                               state, dev->mount_point, user_data);
+               if (!ret_cb)
+                       break;
+       }
+
+       if (list)
+               storage_ext_release_list(&list);
+       return 0;
+}
\ No newline at end of file
diff --git a/src/storage-external.h b/src/storage-external.h
new file mode 100755 (executable)
index 0000000..45c4167
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __STORAGE_EXTERNAL_H__
+#define __STORAGE_EXTERNAL_H__
+
+#include <stdio.h>
+#include "common.h"
+#include "storage-external-dbus.h"
+
+int storage_ext_foreach_device_list(storage_device_supported_cb callback, void *user_data);
+
+#endif /* __STORAGE_EXTERNAL_H__ */
diff --git a/src/storage-sdcard.c b/src/storage-sdcard.c
deleted file mode 100755 (executable)
index 742586e..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/statvfs.h>
-#include <vconf.h>
-#include <tzplatform_config.h>
-
-#include "common.h"
-#include "list.h"
-#include "log.h"
-
-#define SDCARD_NODE "sdcard"
-
-#ifndef __USE_FILE_OFFSET64
-int __WEAK__ storage_get_external_memory_size(struct statvfs *buf);
-#else
-int __WEAK__ storage_get_external_memory_size64(struct statvfs *buf);
-#endif
-
-static dd_list *cb_list[STORAGE_CALLBACK_MAX];
-
-static int sdcard_get_state(void)
-{
-       int val, ret;
-
-       ret = vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &val);
-       if (ret < 0)
-               return -EPERM;
-
-       switch (val) {
-       case VCONFKEY_SYSMAN_MMC_MOUNTED:
-               return STORAGE_STATE_MOUNTED;
-       case VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED:
-               return STORAGE_STATE_UNMOUNTABLE;
-       case VCONFKEY_SYSMAN_MMC_REMOVED:
-       default:
-               break;
-       }
-
-       return STORAGE_STATE_REMOVED;
-}
-
-static int sdcard_get_space(unsigned long long *total, unsigned long long *available)
-{
-       storage_state_e state;
-       struct statvfs s;
-       int ret;
-       unsigned long long t = 0, a = 0;
-
-       state = sdcard_get_state();
-       if (state >= STORAGE_STATE_MOUNTED) {
-#ifndef __USE_FILE_OFFSET64
-               ret = storage_get_external_memory_size(&s);
-#else
-               ret = storage_get_external_memory_size64(&s);
-#endif
-               if (ret < 0)
-                       return -EPERM;
-
-               t = (unsigned long long)s.f_frsize*s.f_blocks;
-               a = (unsigned long long)s.f_bsize*s.f_bavail;
-       }
-
-       if (total)
-               *total = t;
-       if (available)
-               *available = a;
-
-       return 0;
-}
-
-static const char *sdcard_get_root(void)
-{
-       return tzplatform_mkpath(TZ_SYS_MEDIA, SDCARD_NODE);
-}
-
-static void sdcard_state_cb(keynode_t *key, void *data)
-{
-       struct storage_cb_info *cb_info;
-       dd_list *elem;
-       storage_state_e state;
-
-       state = sdcard_get_state();
-
-       DD_LIST_FOREACH(cb_list[STORAGE_CALLBACK_STATE], elem, cb_info)
-               cb_info->state_cb(cb_info->id, state, cb_info->user_data);
-}
-
-static int register_request(enum storage_cb_type type)
-{
-       switch (type) {
-       case STORAGE_CALLBACK_STATE:
-               return vconf_notify_key_changed(VCONFKEY_SYSMAN_MMC_STATUS,
-                               sdcard_state_cb, NULL);
-       default:
-               break;
-       }
-
-       return -EINVAL;
-}
-
-static int release_request(enum storage_cb_type type)
-{
-       switch (type) {
-       case STORAGE_CALLBACK_STATE:
-               return vconf_ignore_key_changed(VCONFKEY_SYSMAN_MMC_STATUS,
-                               sdcard_state_cb);
-       default:
-               break;
-       }
-
-       return -EINVAL;
-}
-
-static int sdcard_register_cb(enum storage_cb_type type, struct storage_cb_info *info)
-{
-       struct storage_cb_info *cb_info;
-       dd_list *elem;
-       int ret, n;
-
-       if (type < 0 || type >= STORAGE_CALLBACK_MAX)
-               return -EINVAL;
-
-       if (!info)
-               return -EINVAL;
-
-       /* check if it is the first request */
-       n = DD_LIST_LENGTH(cb_list[type]);
-       if (n == 0) {
-               ret = register_request(type);
-               if (ret < 0)
-                       return -EPERM;
-       }
-
-       /* check for the same request */
-       DD_LIST_FOREACH(cb_list[type], elem, cb_info) {
-               if (cb_info->id == info->id &&
-                   cb_info->state_cb == info->state_cb)
-                       return -EEXIST;
-       }
-
-       /* add device changed callback to list (local) */
-       cb_info = malloc(sizeof(struct storage_cb_info));
-       if (!cb_info)
-               return -errno;
-
-       memcpy(cb_info, info, sizeof(struct storage_cb_info));
-       DD_LIST_APPEND(cb_list[type], cb_info);
-
-       return 0;
-}
-
-static int sdcard_unregister_cb(enum storage_cb_type type, struct storage_cb_info *info)
-{
-       struct storage_cb_info *cb_info;
-       dd_list *elem;
-       int ret, n;
-
-       if (type < 0 || type >= STORAGE_CALLBACK_MAX)
-               return -EINVAL;
-
-       if (!info)
-               return -EINVAL;
-
-       /* search for the same element with callback */
-       DD_LIST_FOREACH(cb_list[type], elem, cb_info) {
-               if (cb_info->id == info->id &&
-                   cb_info->state_cb == info->state_cb)
-                       break;
-       }
-
-       if (!cb_info)
-               return -EINVAL;
-
-       /* remove device callback from list (local) */
-       DD_LIST_REMOVE(cb_list[type], cb_info);
-       free(cb_info);
-
-       /* check if this callback is last element */
-       n = DD_LIST_LENGTH(cb_list[type]);
-       if (n == 0) {
-               ret = release_request(type);
-               if (ret < 0)
-                       return -EPERM;
-       }
-
-       return 0;
-}
-
-const struct storage_ops sdcard = {
-       .type = STORAGE_TYPE_EXTERNAL,
-       .root = sdcard_get_root,
-       .get_state = sdcard_get_state,
-       .get_space = sdcard_get_space,
-       .register_cb = sdcard_register_cb,
-       .unregister_cb = sdcard_unregister_cb,
-};
-
-STORAGE_OPS_REGISTER(&sdcard)
index cb4409a..cc04ab5 100644 (file)
@@ -24,6 +24,7 @@
 #include "common.h"
 #include "list.h"
 #include "log.h"
+#include "storage-external.h"
 
 const char *dir_path[STORAGE_DIRECTORY_MAX] = {
        [STORAGE_DIRECTORY_IMAGES] = "Images",
@@ -68,7 +69,11 @@ API int storage_foreach_device_supported(storage_device_supported_cb callback, v
                        break;
        }
 
-       /* TODO external storage */
+       ret = storage_ext_foreach_device_list(callback, user_data);
+       if (ret < 0) {
+               _E("Failed to iterate external devices (%d)", ret);
+               return STORAGE_ERROR_OPERATION_FAILED;
+       }
 
        return STORAGE_ERROR_NONE;
 }