Tizen 2.0 Release
[apps/core/preloaded/myfiles.git] / src / common / file-operation / mf-delete-internal.c
1 /*
2  * Copyright 2013         Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.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
7  *
8  *  http://floralicense.org/license/
9  *
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.
15  */
16
17
18
19 #include <stdio.h>
20 #include <glib.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <stdlib.h>
25 //#include <fts.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <sys/syscall.h>
29 #include <ftw.h>
30
31 #include "mf-delete-internal.h"
32 #include "mf-cancel.h"
33 #include "mf-fo-common.h"
34 #include "mf-fo-internal.h"
35 #include "mf-fo-debug.h"
36 #include "mf-media-content.h"
37
38 GSList *delete_list = NULL;
39
40 #ifndef SAFE_FREE
41 #define SAFE_FREE(x) do {\
42                                 if ((x) != NULL) {\
43                                         free(x); \
44                                         x = NULL;\
45                                 } \
46                         } while (0)
47 #endif
48
49 int _mf_delete_delete_regfile(const char *file, struct stat *file_statp, mf_cancel *cancel, _mf_fo_msg_cb msg_cb, void *msg_data)
50 {
51         mode_t mode = 0;
52         off_t size = 0;
53         int err = 0;
54         char err_buf[MF_ERR_BUF] = {0,};
55         if (!file) {
56                 mf_fo_loge("file is NULL");
57                 err = MF_FO_ERR_SET(MF_FO_ERR_SRC_CLASS | MF_FO_ERR_ARGUMENT);
58                 if (msg_cb) {
59                         msg_cb(MF_MSG_ERROR, NULL, 0, err, msg_data);
60                 }
61                 return err;
62         }
63
64         if (cancel && mf_cancel_check_cancel(cancel)) {
65                 return 1;
66         }
67
68         if (file_statp) {
69                 mode = file_statp->st_mode;
70                 size = file_statp->st_size;
71         } else {
72                 struct stat info;
73                 if (stat(file, &info)) {
74                         MF_FILE_ERROR_LOG(err_buf, "Fail to stat file ", file);
75                         err = (_mf_fo_errno_to_mferr(errno) | MF_FO_ERR_SRC_CLASS);
76                         if (msg_cb) {
77                                 msg_cb(MF_MSG_ERROR, file, 0, err, msg_data);
78                         }
79                         return err;
80                 }
81                 mode = info.st_mode;
82                 size = info.st_size;
83         }
84
85         if (!S_ISREG(mode)) {
86                 mf_fo_loge("[%s] is not regular file", file);
87
88                 err = MF_FO_ERR_SET(MF_FO_ERR_SRC_CLASS | MF_FO_ERR_TYPE);
89                 if (msg_cb) {
90                         msg_cb(MF_MSG_ERROR, file, 0, err, msg_data);
91                 }
92                 return err;
93         }
94
95         if (remove(file)) {
96                 MF_FILE_ERROR_LOG(err_buf, "Fail to delete ", file);
97                 err = (_mf_fo_errno_to_mferr(errno) | MF_FO_ERR_SRC_CLASS);
98                 if (msg_cb) {
99                         msg_cb(MF_MSG_ERROR, file, 0, err, msg_data);
100                 }
101                 return err;
102         }
103
104         mf_fo_logd("success to delete FILE : %s", file);
105         /*success message*/
106         if (msg_cb) {
107                 msg_cb(MF_MSG_DOING, file, size, 0, msg_data);
108         }
109
110         return 0;
111 }
112
113 static int __get_delete_directory_hierarchies( const char *pathname, const struct stat *statptr, int type)
114 {
115         mf_fo_dir_list_info *info = NULL;
116         mf_debug("pathname is [%s]\t type is [%d]\t",
117                 pathname, type);
118
119         switch (type) {
120
121         case FTW_F:
122                 info = calloc(sizeof(mf_fo_dir_list_info), 1);
123                 info->ftw_path = g_strdup(pathname);
124                 info->type = type;
125                 delete_list = g_slist_prepend(delete_list, info);
126                 mf_debug("File pathname is [%s]", pathname);
127                 break;
128         case FTW_D:
129                 info = calloc(sizeof(mf_fo_dir_list_info), 1);
130                 info->ftw_path = g_strdup(pathname);
131                 info->type = type;
132                 delete_list = g_slist_prepend(delete_list, info);
133                 mf_debug("Directory pathname is [%s]", pathname);
134                 //process file
135                 break;
136         default:
137                 mf_debug("Default pathname is [%s]", pathname);
138         }
139
140         return 0;
141 }
142
143 int _mf_delete_delete_directory(const char *dir, mf_cancel *cancel, _mf_fo_msg_cb msg_cb, void *msg_data)
144 {
145         int err = 0;
146         int ret = -1;
147         char err_buf[MF_ERR_BUF] = {0,};
148         if (!dir) {
149                 mf_fo_loge("check argument dir");
150                 err = MF_FO_ERR_SET(MF_FO_ERR_SRC_CLASS | MF_FO_ERR_ARGUMENT);
151                 if (msg_cb) {
152                         msg_cb(MF_MSG_ERROR, NULL, 0, err, msg_data);
153                 }
154                 return err;
155         }
156
157         ret = ftw(dir, __get_delete_directory_hierarchies, 16);
158         if (ret == 0) {
159                 mf_debug();
160                 mf_fo_dir_list_info *ent = NULL;
161                 GSList *list = NULL;
162                 list = delete_list;
163                 while (list) {
164                         if (cancel && mf_cancel_check_cancel(cancel)) {
165                                 goto DO_CANCEL;
166                         }
167                         ent = (mf_fo_dir_list_info *)list->data;
168                         if (ent->type == FTW_F) {
169                                 if (ent->ftw_path == NULL || strlen(ent->ftw_path) == 0) {
170                                         list = g_slist_next(list);
171                                         continue;
172                                 }
173                                 err = _mf_delete_delete_regfile(ent->ftw_path, NULL, cancel, msg_cb, msg_data);
174                                 if (err == 0) {
175                                         mf_media_content_scan_file(ent->ftw_path);
176                                 }
177                                 if (err > 0) {
178                                         goto DO_CANCEL;
179                                 } else if (err < 0) {
180                                         goto ERROR_CLOSE_FD;
181                                 }
182
183                         } else if (ent->type == FTW_D) {
184                                 if (cancel && mf_cancel_check_cancel(cancel)) {
185                                         goto DO_CANCEL;
186                                 }
187                                 if (ent->ftw_path == NULL || strlen(ent->ftw_path) == 0) {
188                                         list = g_slist_next(list);
189                                         continue;
190                                 }
191
192                                 if (remove(ent->ftw_path)) {
193                                         MF_FILE_ERROR_LOG(err_buf, "Fail to delete ", ent->ftw_path);
194                                         err = (_mf_fo_errno_to_mferr(errno) | MF_FO_ERR_SRC_CLASS);
195                                         if (msg_cb) {
196                                                 msg_cb(MF_MSG_ERROR, ent->ftw_path, 0, err, msg_data);
197                                         }
198                                         goto ERROR_CLOSE_FD;
199                                 } else {
200                                         mf_fo_logd("success to delete DIR : %s", ent->ftw_path);
201                                         if (msg_cb) {
202                                                 msg_cb(MF_MSG_DOING, ent->ftw_path, 0, 0, msg_data);
203                                         }
204                                 }
205                         }
206                         mf_debug("ent->path is [%s]", ent->ftw_path);
207                         list = g_slist_next(list);
208                 }
209         } else {
210                 err = (_mf_fo_errno_to_mferr(errno) | MF_FO_ERR_SRC_CLASS);
211                 if (msg_cb) {
212                         msg_cb(MF_MSG_ERROR, dir, 0, err, msg_data);
213                 }
214                 _mf_fo_free_directory_hierarchies(&delete_list);
215                 return err;
216         }
217
218         _mf_fo_free_directory_hierarchies(&delete_list);
219
220         return 0;
221
222 ERROR_CLOSE_FD:
223         _mf_fo_free_directory_hierarchies(&delete_list);
224         return err;
225
226 DO_CANCEL:
227         _mf_fo_free_directory_hierarchies(&delete_list);
228         return 1;
229 }
230
231 int _mf_delete_del_internal(const char *item, mf_cancel *cancel, _mf_fo_msg_cb msg_callback, void *msg_data)
232 {
233         struct stat info;
234         int err = 0;
235         char err_buf[MF_ERR_BUF] = {0,};
236         if (!item || strlen(item) <= 1) {
237                 err = MF_FO_ERR_SET(MF_FO_ERR_SRC_CLASS | MF_FO_ERR_ARGUMENT);
238                 if (msg_callback) {
239                         msg_callback(MF_MSG_ERROR, NULL, 0, err, msg_data);
240                 }
241                 return err;
242         }
243
244         if (stat(item, &info)) {
245                 MF_FILE_ERROR_LOG(err_buf, "Fail to stat item ", item);
246                 err = (_mf_fo_errno_to_mferr(errno) | MF_FO_ERR_SRC_CLASS);
247                 if (msg_callback) {
248                         msg_callback(MF_MSG_ERROR, item, 0, err, msg_data);
249                 }
250                 return err;
251         }
252
253         if (cancel && mf_cancel_check_cancel(cancel)) {
254                 goto DO_CANCEL;
255         }
256
257         if (S_ISDIR(info.st_mode)) {
258                 err = _mf_delete_delete_directory(item, cancel, msg_callback, msg_data);
259                 if (err == 0) {
260                         mf_media_content_scan_folder(item);
261                 }
262         } else if (S_ISREG(info.st_mode)) {
263                 err = _mf_delete_delete_regfile(item, &info, cancel, msg_callback, msg_data);
264                 if (err == 0) {
265                         mf_media_content_scan_file(item);
266                 }
267         } else {
268
269                 mf_fo_loge("item[%s] is not file or directory", item);
270                 err = MF_FO_ERR_SET(MF_FO_ERR_SRC_CLASS | MF_FO_ERR_TYPE | MF_FO_ERR_REPORT_CLASS);
271                 if (msg_callback) {
272                         msg_callback(MF_MSG_ERROR, item, 0, err, msg_data);
273                 }
274                 return err;
275         }
276
277         if (err > 0) {
278                 goto DO_CANCEL;
279         } else if (err < 0) {
280                 goto ERROR_RETURN;
281         }
282
283         return 0;
284
285 ERROR_RETURN:
286         return err;
287
288 DO_CANCEL:
289         return 1;
290 }