Add CleanupStorage Function 59/218459/1
authorYunmi Ha <yunmi.ha@samsung.com>
Thu, 31 Oct 2019 05:28:24 +0000 (14:28 +0900)
committerHyotaek Shim <hyotaek.shim@samsung.com>
Fri, 22 Nov 2019 10:54:11 +0000 (10:54 +0000)
Refer to the config file,
delete the data according to the storage level.
config: /etc/storaged/cleanup-storage.conf

Change-Id: I589c7a03fa65ac17a62d12bcd301510485ea8731
Signed-off-by: Yunmi Ha <yunmi.ha@samsung.com>
(cherry picked from commit 94b941f2ee66702934f3d7168faa7c5b166a0aa5)

packaging/storaged.spec
src/storage/CMakeLists.txt
src/storage/cleanup.c [new file with mode: 0644]
src/storage/cleanup.h [new file with mode: 0644]
src/storage/cleanup_config.c [new file with mode: 0644]
src/storage/cleanup_config.h [new file with mode: 0644]
src/storage/sample-cleanup-storage.conf [new file with mode: 0644]
src/storage/storage.c

index a4e8e0f..78ec20d 100644 (file)
@@ -28,6 +28,7 @@ BuildRequires:        pkgconfig(app2sd)
 BuildRequires: pkgconfig(blkid)
 BuildRequires: pkgconfig(mount)
 BuildRequires: pkgconfig(libsyscommon)
+BuildRequires: pkgconfig(json-c)
 
 BuildRequires: pkgconfig(capi-ui-efl-util)
 BuildRequires: pkgconfig(capi-appfw-application)
index 43a614b..0b62347 100644 (file)
@@ -6,6 +6,7 @@ pkg_check_modules(${PROJECT_NAME}_pkgs REQUIRED
                dlog
                gio-2.0
                glib-2.0
+               json-c
                storage
                vconf
                libsyscommon
@@ -19,6 +20,7 @@ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wall -Werror -fvisibility=hidden -rdynamic")
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC")
 SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
 
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/storage)
 INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/shared)
 
 FILE(GLOB ALL_SRCS "*.c")
diff --git a/src/storage/cleanup.c b/src/storage/cleanup.c
new file mode 100644 (file)
index 0000000..af6e0ec
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2019, 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 <unistd.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <pthread.h>
+#include <assert.h>
+#include <json-c/json.h>
+#include <sys/stat.h>
+#include <gmodule.h>
+#include <limits.h>
+
+#include "log.h"
+#include "cleanup.h"
+#include "cleanup_config.h"
+
+enum cleanup_running_type {
+       CLEANUP_TYPE_NONE       = 0,
+       CLEANUP_TYPE_SYSTEM,
+       CLEANUP_TYPE_USER
+};
+
+struct cleanup_request {
+       int cleanup_mode;
+       int level;
+};
+
+#define REMOVE(path) { \
+       if(remove(path) != 0) {         \
+               _E("Failed to remove(%s): %d", path, errno);    \
+               return -errno;                  \
+       }       \
+       _D("Remove (%s)", path);        \
+}
+
+#define ASSERT(ret, format, arg...) {\
+       if (!ret) {     \
+               _E(format, ##arg);      \
+               assert(ret);    \
+       }       \
+}
+
+static pthread_mutex_t mutex_cancel;
+static pthread_mutex_t mutex_lock;
+static pthread_t cleanup_th = 0;
+static GList *request_queue = NULL;
+static int cleanup_canceled = 0;
+
+static int is_cleanup_canceled()
+{
+       int ret = 0;
+       ASSERT((pthread_mutex_lock(&mutex_cancel) == 0), "Assert: Failed to pthread_mutex_lock for cancel.");
+       ret = cleanup_canceled;
+       pthread_mutex_unlock(&mutex_cancel);
+
+       return ret;
+}
+
+static void cleanup_cancel()
+{
+       ASSERT((pthread_mutex_lock(&mutex_cancel) == 0), "Assert: Failed to pthread_mutex_lock for cancel.");
+       cleanup_canceled = 1;
+       pthread_mutex_unlock(&mutex_cancel);
+}
+
+static int find_sub_except_item(const char *item, const char *path)
+{
+       if (strstr(item, path)) {
+               _D("Find except item: %s, path: %s", item, path);
+               return 0;
+       }
+
+       return -1;
+}
+
+static int remove_path(const char *path, GList *except)
+{
+       if (!path)
+               return -EINVAL;
+
+       if (!except)
+               REMOVE(path)
+       else if (except && !g_list_find_custom(except, path, (GCompareFunc)find_sub_except_item))
+               REMOVE(path);
+
+       return 0;
+}
+
+static int cleanup_recursive(const char *path, GList *except)
+{
+       DIR *dir = NULL;
+       struct dirent *dent;
+       struct stat fstat;
+       char sub_path[PATH_MAX] = {0,};
+       int ret;
+
+       if (except && g_list_find_custom(except, path, (GCompareFunc)strcmp))
+               return 0;
+
+       if (is_cleanup_canceled())
+               return 0;
+
+       ret = lstat(path, &fstat);
+       if (ret)
+               return -EINVAL;
+
+       if ((fstat.st_mode & S_IFMT) == S_IFDIR) {
+               if (access(path, W_OK) != 0) {
+                       _E("Failed to access file status(%s).", path);
+                       return -EINVAL;
+               }
+
+               dir = opendir(path);
+               if (!dir) {
+                       _E("Failed to open dir(%s).", path);
+                       return -EINVAL;
+               }
+
+               while((dent = readdir(dir))) {
+                       if(strcmp(dent->d_name, ".") == 0 ||
+                               strcmp(dent->d_name, "..") == 0)
+                               continue;
+
+                       if (is_cleanup_canceled()) {
+                               ret = -EINVAL;
+                               break;
+                       }
+
+                       if (PATH_MAX <= (strlen(path) + strlen(dent->d_name) + 1)) {
+                               _E("File path sould be shorter than %d. But %d.", PATH_MAX, strlen(path) + strlen(dent->d_name) + 1);
+                               continue;
+                       }
+
+                       snprintf(sub_path, PATH_MAX, "%s/%s", path, dent->d_name);
+                       ret = cleanup_recursive(sub_path, except);
+                       if (ret != 0)
+                               break;
+               }
+               closedir(dir);
+               if (!ret)
+                       ret = remove_path(path, except);
+       } else
+               REMOVE(path);
+
+       return ret;
+}
+
+static int add_request_queue(int type, int level)
+{
+       int ret = 0;
+       struct cleanup_request *request = NULL, *item = NULL;
+       GList *list = NULL;
+
+       ASSERT((pthread_mutex_lock(&mutex_lock) == 0), "Assert: Failed to pthread_mutex_lock.");
+
+       for (list = g_list_first(request_queue); list != NULL; list = g_list_next(list)) {
+               item = list->data;
+
+               if ((item->cleanup_mode == type) && (item->level == level)) {
+                       _D("cleanup request is already added.");
+                       goto cleanup;
+               }
+       }
+
+       request = malloc(sizeof(struct cleanup_request));
+       if (!request) {
+               ret = -ENOMEM;
+               goto cleanup;
+       }
+
+       request->cleanup_mode = type;
+       request->level = level;
+       request_queue = g_list_append(request_queue, request);
+
+cleanup:
+       pthread_mutex_unlock(&mutex_lock);
+       return ret;
+}
+
+static void remove_request_queue(struct cleanup_request *item)
+{
+       ASSERT((pthread_mutex_lock(&mutex_lock) == 0), "Assert: Failed to pthread_mutex_lock.");
+
+       request_queue = g_list_remove(request_queue, item);
+       free(item);
+       pthread_mutex_unlock(&mutex_lock);
+}
+
+static struct cleanup_request *get_request_queue()
+{
+       GList *list = NULL;
+
+       ASSERT((pthread_mutex_lock(&mutex_lock) == 0), "Assert: Failed to pthread_mutex_lock.");
+
+       list = g_list_first(request_queue);
+       pthread_mutex_unlock(&mutex_lock);
+
+       return (list)? list->data :NULL;
+}
+
+static GList *get_cleanup_config(int type)
+{
+       if (type == CLEANUP_TYPE_SYSTEM)
+               return get_cleanup_config_system();
+       else if (type == CLEANUP_TYPE_USER)
+               return get_cleanup_config_user();
+
+       return NULL;
+}
+
+// Called by thread
+void *cleanup_storage_start(void *arg)
+{
+       GList *list_config = NULL;
+       GList *list = NULL;
+       struct cleanup_config *config = NULL;
+       struct cleanup_request *request = NULL;
+
+       pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+       while(true) {
+               request = get_request_queue();
+               if (!request) {
+                       _D("There is no more cleanup request.");
+                       break;
+               }
+
+               _D("Cleanup: mode=%d, level=%d", request->cleanup_mode, request->level);
+               list_config = get_cleanup_config(request->cleanup_mode);
+               for (list= g_list_first(list_config); NULL != list; list = g_list_next(list)) {
+                       config = list->data;
+                       if (request->level <= config->level)
+                               cleanup_recursive(config->path, config->exclusion_list);
+               }
+
+               remove_request_queue(request);
+       }
+       cleanup_th = 0;
+       _D("Cleanup thread exit.");
+       return NULL;
+}
+
+void cleanup_storage(enum tzplatform_variable path_id, int level)
+{
+       bool bth = (get_request_queue() == NULL);
+       int type = CLEANUP_TYPE_NONE;
+       int ret;
+
+       if (path_id == TZ_SYS_OPT)
+               type = CLEANUP_TYPE_SYSTEM;
+       else if (path_id == TZ_SYS_USER)
+               type = CLEANUP_TYPE_USER;
+       else {
+               _D("Not supported path type: %d", path_id);
+               return ;
+       }
+
+       if (!get_cleanup_config(type)) {
+               _D("There is no list for cleanup.");
+               return ;
+       }
+
+       if (add_request_queue(type, level) != 0) {
+               _E("Failed to add request.");
+               return ;
+       }
+       //_D("Add cleanup request.(type:%d, level:%d)", type, level);
+
+       if (bth) {
+               ret = pthread_create(&cleanup_th, NULL, cleanup_storage_start, NULL);
+               if (ret != 0)
+                       _E("Failed to start pthread: %d", ret);
+       }
+}
+
+void init_cleanup_storage()
+{
+       load_cleanup_config();
+
+       pthread_mutex_init(&mutex_lock, NULL);
+       pthread_mutex_init(&mutex_cancel, NULL);
+}
+
+void free_cleanup_storage()
+{
+       ASSERT((pthread_mutex_lock(&mutex_lock) == 0), "Assert: Failed to pthread_mutex_lock.");
+       if (request_queue)
+               g_list_free_full(request_queue, free);
+       request_queue = NULL;
+       pthread_mutex_unlock(&mutex_lock);
+
+       if (cleanup_th) {
+               _D("Cancel cleanup thread %d.", (int)cleanup_th);
+               cleanup_cancel();
+               //pthread_cancel(cleanup_th);
+               pthread_join(cleanup_th, NULL);
+               _D("Exit cleanup thread %d.", (int)cleanup_th);
+       }
+
+       free_cleanup_config();
+}
diff --git a/src/storage/cleanup.h b/src/storage/cleanup.h
new file mode 100644 (file)
index 0000000..46bfaa1
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * storaged
+ *
+ * Copyright (c) 2019 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 __STORAGED_CLEANUP_H__
+#define __STORAGED_CLEANUP_H__
+
+#include <stdio.h>
+#include <tzplatform_config.h>
+
+void init_cleanup_storage();
+void free_cleanup_storage();
+
+void cleanup_storage(enum tzplatform_variable path_id, int level);
+
+#endif  /* #define __STORAGED_CLEANUP_H___ */
diff --git a/src/storage/cleanup_config.c b/src/storage/cleanup_config.c
new file mode 100644 (file)
index 0000000..2717992
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2019, 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 <unistd.h>
+#include <stdio.h>
+#include <json-c/json.h>
+#include <tzplatform_config.h>
+
+#include "log.h"
+#include "cleanup_config.h"
+
+char *cleanup_level_str[] = {
+       "full",
+       "critical",
+       "warning",
+       "normal"
+};
+
+#define DEF_CLEANUP_CONFIG_FILE     "/etc/storaged/cleanup-storage.conf"
+#define RESULT(ret, val)       \
+{ \
+       if (ret)                                \
+               *ret = val;                     \
+}
+
+static GList *cleanup_list_system = NULL;
+static GList *cleanup_list_user = NULL;
+
+static void free_config_item(void *data)
+{
+       struct cleanup_config *item = data;
+
+       if (item->path) {
+               free(item->path);
+               item->path = NULL;
+       }
+
+       if (item->exclusion_list) {
+               g_list_free_full(item->exclusion_list, free);
+               item->exclusion_list = NULL;
+       }
+
+       free(item);
+}
+
+void free_cleanup_config()
+{
+       if (cleanup_list_system) {
+               g_list_free_full(cleanup_list_system, free_config_item);
+               cleanup_list_system = NULL;
+       }
+
+       if (cleanup_list_user) {
+               g_list_free_full(cleanup_list_user, free_config_item);
+               cleanup_list_user = NULL;
+       }
+}
+
+static int get_config_string_field(struct json_object *root, const char *key, char** value)
+{
+       struct json_object *node = NULL;
+       const char *node_value;
+
+       if (!json_object_object_get_ex(root, key, &node)) {
+               _D("Config doesn't contain path param.");
+               return 0;
+       }
+
+       if (!json_object_is_type(node, json_type_string)) {
+               _E("'%s' type should be string. but it isn't.", key);
+               return -EINVAL;
+       }
+
+       node_value = json_object_get_string(node);
+       *value = strdup(node_value);
+       if (*value == NULL) {
+               _E("Failed to duplicate string.");
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static GList *get_config_array_field(struct json_object *root, const char *key, int *ret)
+{
+       struct json_object *node = NULL, *obj;
+       int i, len;
+       const char *str = NULL;
+       char *temp;
+       GList *list = NULL;
+
+       if (!json_object_object_get_ex(root, key, &node)) {
+               _D("Config doesn't contain '%s' param.", key);
+               RESULT(ret, 0);
+               return NULL;
+       }
+
+    if (!json_object_is_type(node, json_type_array)) {
+               _E("'%s' type should be array. but it isn't.", key);
+               RESULT(ret, -EINVAL);
+               return NULL;
+       }
+
+       len = json_object_array_length(node);
+       for (i = 0; i < len; i++) {
+               obj = json_object_array_get_idx(node, i);
+               str = json_object_get_string(obj);
+               if (!str)
+               {
+                       _E("Failed to get stirng value from json object.");
+                       RESULT(ret, -EINVAL);
+                       goto cleanup;
+               }
+
+               temp = strdup(str);
+               if (!temp) {
+                       _E("Failed to duplicate array item string");
+                       RESULT(ret, -ENOMEM);
+                       goto cleanup;
+               }
+
+               list = g_list_append(list, temp);
+       }
+
+       RESULT(ret, 0);
+       return list;
+
+cleanup:
+       g_list_free_full(list, free);
+       return NULL;
+}
+
+static int get_cleanup_level(const char *level_str)
+{
+       int ret = -EINVAL;
+       int i;
+
+       if (level_str == NULL)
+               return -EINVAL;
+
+       for (i = 0; i< CLEANUP_LEVEL_NONE; i++) {
+               if (strcmp(level_str, cleanup_level_str[i]) == 0)
+                       break;
+       }
+
+       if (i < CLEANUP_LEVEL_NONE)
+               ret = i;
+
+       return ret;
+}
+
+static int add_config_item(struct json_object *obj, struct cleanup_config *item)
+{
+       char *temp = NULL;
+       int ret;
+
+       if (!item) {
+               _E("Parameter is invalid.");
+               return -EINVAL;
+       }
+
+       if (get_config_string_field(obj, "level", &temp) != 0) {
+               _E("There is no level node.");
+               return -EINVAL;
+       }
+
+       item->level = get_cleanup_level(temp);
+       free(temp);
+
+       if (item->level < 0) {
+               _E("Invalid level value.");
+               return -EINVAL;
+       }
+
+       if (get_config_string_field(obj, "path", &item->path) != 0)
+               return -EINVAL;
+
+       //todo.
+       //check duplicated path
+
+       item->exclusion_list = get_config_array_field(obj, "except", &ret);
+       if (ret != 0)
+               return -EINVAL;
+
+       //_D("Get config item: level=%d, path=%s, except count=%d", item->level, item->path, g_list_length(item->exclusion_list));
+       return 0;
+}
+
+static GList *parsing_json_array_object_to_list(struct json_object *array, int *ret)
+{
+       int i, len, item_size;
+       GList *list = NULL;
+       struct cleanup_config *item = NULL;
+       struct json_object *obj = NULL;
+
+       if (!json_object_is_type(array, json_type_array)) {
+               _E("Config value is not an array.");
+               RESULT(ret, -EINVAL);
+               return NULL;
+       }
+
+       len = json_object_array_length(array);
+       for (i = 0; i < len; ++i) {
+               obj = json_object_array_get_idx(array, i);
+               if (!json_object_is_type(obj, json_type_object)) {
+                       _E("Array item is not an object.");
+                       RESULT(ret, -EINVAL);
+                       goto cleanup;
+               }
+
+               item_size = sizeof(struct cleanup_config);
+               item = malloc(item_size);
+               if (!item) {
+                       _E("Memory allocation fail. size=%d", item_size);
+                       RESULT(ret, -ENOMEM);
+                       goto cleanup;
+               }
+               memset(item, '\0', item_size);
+
+               if (add_config_item(json_object_get(obj), item) != 0) {
+                       RESULT(ret, -EINVAL);
+                       goto cleanup;
+               }
+               list = g_list_append(list, item);
+       }
+       RESULT(ret, 0);
+       return list;
+cleanup:
+       if (item)
+               free(item);
+
+       g_list_free_full(list, free_config_item);
+       return NULL;
+}
+
+int load_json_object_with_file(const char *file)
+{
+       struct json_object *root_node, *array;
+       const char *root = NULL;
+       int ret = 0;
+
+       root_node = json_object_from_file(file);
+       if (root_node == NULL) {
+               _E("Could not create object from json file '%s'", file);
+               return -EINVAL;
+       }
+
+       root = tzplatform_getenv(TZ_SYS_OPT);
+       if (json_object_object_get_ex(root_node, root, &array)) {
+               cleanup_list_system = parsing_json_array_object_to_list(array, &ret);
+               if(ret != 0)
+                       goto cleanup;
+               _D("'%s' config has %d items.", root,  g_list_length(cleanup_list_system));
+       }
+
+       root = tzplatform_getenv(TZ_SYS_USER);
+       if (json_object_object_get_ex(root_node, root, &array)) {
+               cleanup_list_user = parsing_json_array_object_to_list(array, &ret);
+               if (ret != 0)
+                       goto cleanup;
+               _D("'%s' config has %d items.", root, g_list_length(cleanup_list_user));
+       }
+
+cleanup:
+       json_object_put(root_node);
+       return ret;
+}
+
+int load_cleanup_config()
+{
+       int ret = 0;
+
+       ret = access(DEF_CLEANUP_CONFIG_FILE, F_OK|R_OK);
+       if (ret) {
+               if (errno == ENOENT) {
+                       _D("Config file doesn't exist '%s'", DEF_CLEANUP_CONFIG_FILE);
+                       return -ENOENT;
+               }
+               _E("Could not access config file '%s'", DEF_CLEANUP_CONFIG_FILE);
+               return -errno;
+    }
+
+       _D("Using cleanup config file: '%s'", DEF_CLEANUP_CONFIG_FILE);
+
+       ret = load_json_object_with_file(DEF_CLEANUP_CONFIG_FILE);
+
+       return ret;
+}
+
+GList *get_cleanup_config_system()
+{
+       return cleanup_list_system;
+}
+
+GList *get_cleanup_config_user()
+{
+       return cleanup_list_user;
+}
diff --git a/src/storage/cleanup_config.h b/src/storage/cleanup_config.h
new file mode 100644 (file)
index 0000000..c7614eb
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * storaged
+ *
+ * Copyright (c) 2019 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 __STORAGED_CLEANUP_CONFIG_H__
+#define __STORAGED_CLEANUP_CONFIG_H__
+
+#include <stdio.h>
+#include <gmodule.h>
+
+enum cleanup_level {
+    CLEANUP_LEVEL_FULL = 0,
+    CLEANUP_LEVEL_CRITICAL,
+    CLEANUP_LEVEL_WARNING,
+    CLEANUP_LEVEL_NORMAL,
+    CLEANUP_LEVEL_NONE
+};
+
+struct cleanup_config {
+    int     level;
+    char    *path;
+    GList   *exclusion_list;
+};
+
+int load_cleanup_config();
+void free_cleanup_config();
+
+GList *get_cleanup_config_system();
+GList *get_cleanup_config_user();
+
+#endif  /* #define __STORAGED_CLEANUP_CONFIG_H___ */
diff --git a/src/storage/sample-cleanup-storage.conf b/src/storage/sample-cleanup-storage.conf
new file mode 100644 (file)
index 0000000..5325515
--- /dev/null
@@ -0,0 +1,30 @@
+{
+       "/opt":[
+               {
+                       "level":"critical",
+                       "path":"/opt/val/test",
+                       "except":[
+                               "/opt/val/test/except1",
+                               "/opt/val/test/except2"
+                       ]
+               }
+       ],
+       "/opt/usr":[
+               {
+                       "level":"full",
+                       "path":"/opt/usr/logtest"
+               },
+               {
+                       "level":"full",
+                       "path":"/opt/usr/etc/test"
+               },
+               {
+                       "level":"full",
+                       "path":"/opt/usr/etc/test_crash"
+               },
+               {
+                       "level":"critical",
+                       "path":"/opt/usr/data/test_GL"
+               }
+       ]
+}
index 24a613f..1badb90 100644 (file)
@@ -38,6 +38,7 @@
 #include "config-parser.h"
 #include "module-intf.h"
 #include "storaged_common.h"
+#include "cleanup.h"
 
 #define MEMORY_STATUS_TMP_PATH  "/tmp"
 #define MEMORY_STATUS_OPT_PATH  "/opt"
@@ -185,6 +186,8 @@ out:
                                g_variant_new("(is)", path, value));
        if (ret < 0)
                _E("Failed to send dbus signal");
+
+       cleanup_storage(path, level);
 }
 
 static void _popup_cb(GVariant *var, void *user_data, GError *err)
@@ -721,6 +724,8 @@ static void storage_init(void *data)
        if (ret < 0)
                _E("Failed to make directory: %d", errno);
 
+       init_cleanup_storage();
+
        id_storage_poweroff = subscribe_dbus_signal(NULL, DEVICED_PATH_POWEROFF,
                        DEVICED_INTERFACE_POWEROFF,
                        SIGNAL_POWEROFF_STATE,
@@ -731,6 +736,7 @@ static void storage_init(void *data)
 
 static void storage_exit(void *data)
 {
+       free_cleanup_storage();
        /* unregister notifier for below each event */
        unsubscribe_dbus_signal(NULL, id_storage_poweroff);
 }