Replace sqlite3_free() to SQLITE3_SAFE_FREE
[platform/core/multimedia/libmedia-service.git] / src / common / media-svc-media-folder.c
1 /*
2  * libmedia-service
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Hyunjun Ko <zzoon.ko@samsung.com>, Haejeong Kim <backto.kim@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <glib/gstdio.h>
23 #include <media-util-err.h>
24 #include "media-svc-media-folder.h"
25 #include "media-svc-debug.h"
26 #include "media-svc-env.h"
27 #include "media-svc-util.h"
28 #include "media-svc-db-utils.h"
29
30 #define FOLDER_SCAN_DONE 4
31
32 extern __thread GList *g_media_svc_move_item_query_list;
33 static __thread GList *g_media_svc_insert_folder_query_list;
34
35 static int __media_svc_is_root_path(const char *folder_path, bool *is_root, uid_t uid)
36 {
37         media_svc_retvm_if(!STRING_VALID(folder_path), MS_MEDIA_ERR_INVALID_PARAMETER, "folder_path is NULL");
38
39         *is_root = FALSE;
40         int i = 0;
41         int start_len = 0;
42         int path_len = 0;
43         char *internal_path = _media_svc_get_path(uid);
44
45         if (STRING_VALID(internal_path) && (strcmp(folder_path, internal_path) == 0)) {
46                 media_svc_debug("ROOT PATH [%s]", folder_path);
47                 *is_root = TRUE;
48
49                 SAFE_FREE(internal_path);
50
51                 return MS_MEDIA_ERR_NONE;
52         }
53         SAFE_FREE(internal_path);
54
55         if (STRING_VALID(MEDIA_ROOT_PATH_SDCARD) && strncmp(folder_path, MEDIA_ROOT_PATH_SDCARD, strlen(MEDIA_ROOT_PATH_SDCARD)) == 0) {
56
57                 start_len = strlen(MEDIA_ROOT_PATH_SDCARD);
58                 path_len = strlen(folder_path);
59
60                 for (i = start_len; i < path_len; i++) {
61                         if (folder_path[i] == '/')
62                                 return MS_MEDIA_ERR_NONE;
63                 }
64
65                 media_svc_debug("ROOT PATH [%s]", folder_path);
66                 *is_root = TRUE;
67         } else if ((STRING_VALID(MEDIA_ROOT_PATH_CLOUD) && strcmp(folder_path, MEDIA_ROOT_PATH_CLOUD) == 0) ||
68                 (STRING_VALID(MEDIA_ROOT_PATH_DISC) && strcmp(folder_path, MEDIA_ROOT_PATH_DISC) == 0)) {
69                 media_svc_debug("ROOT PATH [%s]", folder_path);
70                 *is_root = TRUE;
71         }
72
73         return MS_MEDIA_ERR_NONE;
74 }
75
76 static int __media_svc_parent_is_ext_root_path(const char *folder_path, bool *is_root)
77 {
78         char *parent_folder_path = NULL;
79
80         media_svc_retvm_if(!STRING_VALID(folder_path), MS_MEDIA_ERR_INVALID_PARAMETER, "folder_path is NULL");
81
82         *is_root = FALSE;
83
84         parent_folder_path = g_path_get_dirname(folder_path);
85
86         if (!STRING_VALID(parent_folder_path)) {
87                 media_svc_error("error : g_path_get_dirname falied");
88                 SAFE_FREE(parent_folder_path);
89                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
90         }
91
92         if (STRING_VALID(MEDIA_ROOT_PATH_EXTERNAL) && (strcmp(parent_folder_path, MEDIA_ROOT_PATH_EXTERNAL) == 0)) {
93                 media_svc_debug("parent folder is ROOT PATH [%s]", parent_folder_path);
94                 *is_root = TRUE;
95         }
96
97         SAFE_FREE(parent_folder_path);
98
99         return MS_MEDIA_ERR_NONE;
100 }
101
102 int _media_svc_get_folder_id_by_foldername(sqlite3 *handle, const char *storage_id, const char *folder_name, char *folder_id, uid_t uid)
103 {
104         int ret = MS_MEDIA_ERR_NONE;
105         sqlite3_stmt *sql_stmt = NULL;
106         char *sql = NULL;
107         char parent_folder_uuid[MEDIA_SVC_UUID_SIZE+1] = {0, };
108         char *temp_parent_uuid = NULL;
109         char *parent_folder_path = NULL;
110
111         sql = sqlite3_mprintf("SELECT folder_uuid, parent_folder_uuid FROM '%s' WHERE storage_uuid = '%q' AND path = '%q';", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, folder_name);
112
113         ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
114
115         if (ret != MS_MEDIA_ERR_NONE) {
116                 if (ret == MS_MEDIA_ERR_DB_NO_RECORD)
117                         media_svc_debug("there is no folder.");
118                 else
119                         media_svc_error("error when _media_svc_get_folder_id_by_foldername. err = [%d]", ret);
120
121                 return ret;
122         }
123
124         memset(parent_folder_uuid, 0, sizeof(parent_folder_uuid));
125
126         _strncpy_safe(folder_id, (const char *)sqlite3_column_text(sql_stmt, 0), MEDIA_SVC_UUID_SIZE + 1);
127         if (STRING_VALID((const char *)sqlite3_column_text(sql_stmt, 1)))       /*root path can be null*/
128                 _strncpy_safe(parent_folder_uuid, (const char *)sqlite3_column_text(sql_stmt, 1), MEDIA_SVC_UUID_SIZE+1);
129
130         SQLITE3_FINALIZE(sql_stmt);
131
132         /*root path can be null*/
133         if (!STRING_VALID(parent_folder_uuid)) {
134                 bool is_root = FALSE;
135
136                 ret = __media_svc_is_root_path(folder_name, &is_root, uid);
137                 if (is_root)
138                         return MS_MEDIA_ERR_NONE;
139
140                 ret = __media_svc_parent_is_ext_root_path(folder_name, &is_root);
141                 if (is_root)
142                         return MS_MEDIA_ERR_NONE;
143         }
144
145         /* Notice : Below code is the code only for inserting parent folder uuid when upgrade the media db version 3 to 4 */
146         /* Check parent folder uuid */
147         if (!STRING_VALID(parent_folder_uuid)) {
148                 /* update parent_uuid */
149                 media_svc_error("[No-Error] there is no parent folder uuid. PLEASE CHECK IT");
150
151                 parent_folder_path = g_path_get_dirname(folder_name);
152                 if (!STRING_VALID(parent_folder_path)) {
153                         media_svc_error("error : g_path_get_dirname falied.");
154                         return MS_MEDIA_ERR_OUT_OF_MEMORY;
155                 }
156
157                 if (STRING_VALID(storage_id))
158                         sql = sqlite3_mprintf("SELECT folder_uuid FROM '%s' WHERE storage_uuid = '%q' AND path = '%q';", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, parent_folder_path);
159                 else
160                         sql = sqlite3_mprintf("SELECT folder_uuid FROM '%s' WHERE path = '%q';", MEDIA_SVC_DB_TABLE_FOLDER, parent_folder_path);
161
162                 SAFE_FREE(parent_folder_path);
163
164                 ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
165                 if (ret == MS_MEDIA_ERR_NONE) {
166                         temp_parent_uuid = (char *)sqlite3_column_text(sql_stmt, 0);
167                         if (temp_parent_uuid != NULL)
168                                 _strncpy_safe(parent_folder_uuid, temp_parent_uuid, MEDIA_SVC_UUID_SIZE+1);
169
170                         SQLITE3_FINALIZE(sql_stmt);
171                 }
172
173                 if (STRING_VALID(parent_folder_uuid)) {
174                         if (STRING_VALID(storage_id))
175                                 sql = sqlite3_mprintf("UPDATE %q SET parent_folder_uuid = '%q' WHERE storage_uuid = '%q' AND path = '%q';", MEDIA_SVC_DB_TABLE_FOLDER, parent_folder_uuid, storage_id, folder_name);
176                         else
177                                 sql = sqlite3_mprintf("UPDATE %q SET parent_folder_uuid = '%q' WHERE path = '%q';", MEDIA_SVC_DB_TABLE_FOLDER, parent_folder_uuid, folder_name);
178                         ret = _media_svc_sql_query(sql, uid);
179                         SQLITE3_SAFE_FREE(sql);
180                 } else {
181                         media_svc_error("error when get parent folder uuid");
182                 }
183         }
184
185         return ret;
186 }
187
188 static int __media_svc_append_folder(const char *storage_id, media_svc_storage_type_e storage_type,
189                         const char *folder_id, const char *folder_path, const char *parent_folder_uuid, bool stack_query, uid_t uid)
190 {
191         int ret = MS_MEDIA_ERR_NONE;
192         char *folder_name = NULL;
193         int folder_modified_date = 0;
194
195         folder_name = g_path_get_basename(folder_path);
196         folder_modified_date = _media_svc_get_file_time(folder_path);
197
198         /*Update Pinyin If Support Pinyin*/
199         char *folder_name_pinyin = NULL;
200         if (_media_svc_check_pinyin_support())
201                 _media_svc_get_pinyin_str(folder_name, &folder_name_pinyin);
202         /* Sometime SQLITE3 returns NO_RECORD, so need to consider conflict case.. */
203         media_svc_debug("UNIQUE:path[%s], storage_uuid[%s]", folder_path, storage_id);
204         char *sql = sqlite3_mprintf("INSERT OR IGNORE INTO %s (folder_uuid, path, name, storage_uuid, storage_type, modified_time, name_pinyin, parent_folder_uuid) \
205                                                         values (%Q, %Q, %Q, %Q, '%d', '%d', %Q, %Q); ",
206                                                         MEDIA_SVC_DB_TABLE_FOLDER, folder_id, folder_path, folder_name, storage_id, storage_type, folder_modified_date, folder_name_pinyin, parent_folder_uuid);
207
208         if (!stack_query) {
209                 ret = _media_svc_sql_query(sql, uid);
210                 SQLITE3_SAFE_FREE(sql);
211         } else {
212                 _media_svc_sql_query_add(&g_media_svc_insert_folder_query_list, &sql);
213         }
214
215         SAFE_FREE(folder_name);
216         SAFE_FREE(folder_name_pinyin);
217
218         return ret;
219 }
220
221 int _media_svc_update_folder_modified_time_by_folder_uuid(const char *folder_uuid, const char *folder_path, bool stack_query, uid_t uid)
222 {
223         int ret = MS_MEDIA_ERR_NONE;
224         int modified_time = 0;
225
226         modified_time = _media_svc_get_file_time(folder_path);
227
228         char *sql = sqlite3_mprintf("UPDATE %s SET modified_time=%d WHERE folder_uuid=%Q;", MEDIA_SVC_DB_TABLE_FOLDER, modified_time, folder_uuid);
229
230         if (!stack_query) {
231                 ret = _media_svc_sql_query(sql, uid);
232                 SQLITE3_SAFE_FREE(sql);
233         } else {
234                 _media_svc_sql_query_add(&g_media_svc_move_item_query_list, &sql);
235         }
236
237         return ret;
238 }
239
240 static int __media_svc_get_and_append_parent_folder(sqlite3 *handle, const char *storage_id, const char *path, media_svc_storage_type_e storage_type, char *folder_id, uid_t uid)
241 {
242         int ret = MS_MEDIA_ERR_NONE;
243         unsigned int next_pos = 0;
244         char *next = NULL;
245         char *dir_path = NULL;
246         const char *token = "/";
247         char *folder_uuid = NULL;
248         char parent_folder_uuid[MEDIA_SVC_UUID_SIZE + 1] = {0, };
249         bool folder_search_end = FALSE;
250         char *internal_path = NULL;
251
252         memset(parent_folder_uuid, 0, sizeof(parent_folder_uuid));
253         internal_path = _media_svc_get_path(uid);
254
255         if (STRING_VALID(internal_path) && (strncmp(path, internal_path, strlen(internal_path)) == 0))
256                 next_pos = strlen(internal_path);
257         else if (STRING_VALID(MEDIA_ROOT_PATH_SDCARD) && strncmp(path, MEDIA_ROOT_PATH_SDCARD, strlen(MEDIA_ROOT_PATH_SDCARD)) == 0)
258                 next_pos = strlen(MEDIA_ROOT_PATH_SDCARD);
259         else if (STRING_VALID(MEDIA_ROOT_PATH_CLOUD) && (strncmp(path, MEDIA_ROOT_PATH_CLOUD, strlen(MEDIA_ROOT_PATH_CLOUD)) == 0))
260                 next_pos = strlen(MEDIA_ROOT_PATH_CLOUD);
261         else if (STRING_VALID(MEDIA_ROOT_PATH_EXTERNAL) && strncmp(path, MEDIA_ROOT_PATH_EXTERNAL, strlen(MEDIA_ROOT_PATH_EXTERNAL)) == 0)
262                 next_pos = strlen(MEDIA_ROOT_PATH_EXTERNAL);
263         else if (STRING_VALID(MEDIA_ROOT_PATH_DISC) && strncmp(path, MEDIA_ROOT_PATH_DISC, strlen(MEDIA_ROOT_PATH_DISC)) == 0)
264                 next_pos = strlen(MEDIA_ROOT_PATH_DISC);
265         else {
266                 media_svc_error("Invalid Path");
267                 SAFE_FREE(internal_path);
268                 return MS_MEDIA_ERR_INTERNAL;
269         }
270
271         SAFE_FREE(internal_path);
272
273         while (!folder_search_end) {
274                 next = strstr(path + next_pos, token);
275                 if (next != NULL) {
276                         next_pos = (next - path);
277                         dir_path = strndup(path, next_pos);
278                         next_pos++;
279                 } else {
280                         dir_path = strndup(path, strlen(path));
281                         folder_search_end = TRUE;
282                         media_svc_error("[No-Error] End Path [%s]", dir_path);
283                 }
284
285                 if (STRING_VALID(MEDIA_ROOT_PATH_EXTERNAL) && (g_strcmp0(dir_path, MEDIA_ROOT_PATH_EXTERNAL) == 0)) {
286                         /*To avoid insert MEDIA_ROOT_PATH_EXTERNAL path*/
287                         SAFE_FREE(dir_path);
288                         continue;
289                 }
290
291                 ret = _media_svc_get_folder_id_by_foldername(handle, storage_id, dir_path, parent_folder_uuid, uid);
292                 if (ret == MS_MEDIA_ERR_DB_NO_RECORD) {
293                         folder_uuid = _media_info_generate_uuid();
294                         if (folder_uuid == NULL) {
295                                 media_svc_error("Invalid UUID");
296                                 SAFE_FREE(dir_path);
297                                 return MS_MEDIA_ERR_INTERNAL;
298                         }
299
300                         ret = __media_svc_append_folder(storage_id, storage_type, folder_uuid, dir_path, parent_folder_uuid, FALSE, uid);
301                         if (ret != MS_MEDIA_ERR_NONE)
302                                 media_svc_error("__media_svc_append_folder is failed");
303
304                         media_svc_error("[No-Error] New Appended folder path [%s], folder_uuid [%s], parent_folder_uuid [%s]", dir_path, folder_uuid, parent_folder_uuid);
305                         _strncpy_safe(parent_folder_uuid, folder_uuid, MEDIA_SVC_UUID_SIZE + 1);
306                 } else {
307                         media_svc_error("EXIST dir path : %s\n", dir_path);
308                 }
309
310                 SAFE_FREE(dir_path);
311         }
312
313         if (STRING_VALID(folder_uuid)) {
314                 _strncpy_safe(folder_id, folder_uuid, MEDIA_SVC_UUID_SIZE + 1);
315         } else {
316                 media_svc_error("Fail to get folder_uuid");
317                 return MS_MEDIA_ERR_INTERNAL;
318         }
319
320         return MS_MEDIA_ERR_NONE;
321 }
322
323 int _media_svc_get_and_append_folder(sqlite3 *handle, const char *storage_id, const char *path, media_svc_storage_type_e storage_type, char *folder_id, uid_t uid)
324 {
325         int ret = MS_MEDIA_ERR_NONE;
326
327         ret = _media_svc_get_folder_id_by_foldername(handle, storage_id, path, folder_id, uid);
328
329         if (ret == MS_MEDIA_ERR_DB_NO_RECORD)
330                 ret = __media_svc_get_and_append_parent_folder(handle, storage_id, path, storage_type, folder_id, uid);
331
332         return ret;
333 }
334
335 int _media_svc_get_and_append_folder_id_by_path(sqlite3 *handle, const char *storage_id, const char *path, media_svc_storage_type_e storage_type, char *folder_id, uid_t uid)
336 {
337         char *dir_path = NULL;
338         int ret = MS_MEDIA_ERR_NONE;
339
340         dir_path = g_path_get_dirname(path);
341
342         ret = _media_svc_get_and_append_folder(handle, storage_id, dir_path, storage_type, folder_id, uid);
343
344         SAFE_FREE(dir_path);
345
346         return ret;
347 }
348
349 int _media_svc_update_folder_table(const char *storage_id, uid_t uid)
350 {
351         int ret = MS_MEDIA_ERR_NONE;
352         char *sql = NULL;
353
354         sql = sqlite3_mprintf("DELETE FROM '%s' WHERE folder_uuid IN (SELECT folder_uuid FROM '%s' WHERE folder_uuid NOT IN (SELECT folder_uuid FROM '%s'));",
355                 MEDIA_SVC_DB_TABLE_FOLDER, MEDIA_SVC_DB_TABLE_FOLDER, storage_id);
356
357         ret = _media_svc_sql_query(sql, uid);
358         SQLITE3_SAFE_FREE(sql);
359
360         return ret;
361 }
362
363 static int __media_svc_count_all_folders(sqlite3 *handle, char *start_path, int *count)
364 {
365         int ret = MS_MEDIA_ERR_NONE;
366         sqlite3_stmt *sql_stmt = NULL;
367         char *sql = sqlite3_mprintf("SELECT count(*) FROM '%s' WHERE path LIKE '%q%%'", MEDIA_SVC_DB_TABLE_FOLDER, start_path);
368
369         ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
370         if (ret != MS_MEDIA_ERR_NONE) {
371                 media_svc_error("error when _media_svc_sql_prepare_to_step. err = [%d]", ret);
372                 return ret;
373         }
374
375         *count = sqlite3_column_int(sql_stmt, 0);
376
377         SQLITE3_FINALIZE(sql_stmt);
378
379         return MS_MEDIA_ERR_NONE;
380 }
381
382 int _media_svc_get_all_folders(sqlite3 *handle, char *start_path, char ***folder_list, time_t **modified_time_list, int **item_num_list, int *count)
383 {
384         int ret = MS_MEDIA_ERR_NONE;
385         int idx = 0;
386         sqlite3_stmt *sql_stmt = NULL;
387         char *sql = NULL;
388         int cnt = 0;
389         char **folder_uuid = NULL;
390         int i = 0;
391
392         ret = __media_svc_count_all_folders(handle, start_path, &cnt);
393         if (ret != MS_MEDIA_ERR_NONE) {
394                 media_svc_error("error when __media_svc_count_all_folders. err = [%d]", ret);
395                 return ret;
396         }
397
398         if (cnt > 0) {
399                 sql = sqlite3_mprintf("SELECT path, modified_time, folder_uuid FROM '%s' WHERE path LIKE '%q%%'", MEDIA_SVC_DB_TABLE_FOLDER, start_path);
400         } else {
401                 *folder_list = NULL;
402                 *modified_time_list = NULL;
403                 *item_num_list = NULL;
404                 return MS_MEDIA_ERR_NONE;
405         }
406
407         *folder_list = malloc(sizeof(char *) * cnt);
408         *modified_time_list = malloc(sizeof(int) * cnt);
409         *item_num_list = malloc(sizeof(int) * cnt);
410         folder_uuid = malloc(sizeof(char *) * cnt);
411
412         if ((*folder_list == NULL) || (*modified_time_list == NULL) || (*item_num_list == NULL) || (folder_uuid == NULL)) {
413                 media_svc_error("Out of memory");
414                 goto ERROR;
415         }
416         memset(folder_uuid, 0x0, sizeof(char *) * cnt);
417         memset(*folder_list, 0x0, sizeof(char *) * cnt);
418
419         ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
420         if (ret != MS_MEDIA_ERR_NONE) {
421                 media_svc_error("prepare error [%s]", sqlite3_errmsg(handle));
422                 goto ERROR;
423         }
424
425         media_svc_debug("QEURY OK");
426
427         while (idx < cnt) {
428                 (*folder_list)[idx] = g_strdup((char *)sqlite3_column_text(sql_stmt, 0));
429                 (*modified_time_list)[idx] = (int)sqlite3_column_int(sql_stmt, 1);
430
431                 /* get the folder's id */
432                 folder_uuid[idx] = g_strdup((char *)sqlite3_column_text(sql_stmt, 2));
433
434                 idx++;
435
436                 if (sqlite3_step(sql_stmt) != SQLITE_ROW)
437                         break;
438         }
439         SQLITE3_FINALIZE(sql_stmt);
440
441         /*get the numbder of item in the folder by using folder's id */
442         for (i = 0; i < idx; i++) {
443                 if (STRING_VALID(folder_uuid[i])) {
444                         sql = sqlite3_mprintf("SELECT COUNT(*) FROM %s WHERE (folder_uuid='%q' AND validity = 1)", MEDIA_SVC_DB_TABLE_MEDIA, folder_uuid[i]);
445                         ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
446                         if (ret != MS_MEDIA_ERR_NONE) {
447                                 media_svc_error("prepare error [%s]", sqlite3_errmsg(handle));
448                                 goto ERROR;
449                         }
450
451                         (*item_num_list)[i] = (int)sqlite3_column_int(sql_stmt, 0);
452
453                         SQLITE3_FINALIZE(sql_stmt);
454                 } else {
455                         media_svc_error("Invalid Folder Id");
456                 }
457         }
458
459         if (cnt == idx) {
460                 *count = cnt;
461                 media_svc_debug("Get Folder is OK");
462         } else {
463                 media_svc_error("Fail to get folder");
464                 ret = MS_MEDIA_ERR_INTERNAL;
465                 goto ERROR;
466         }
467
468         /* free all data */
469         for (i = 0; i < idx; i++)
470                 SAFE_FREE(folder_uuid[i]);
471
472         SAFE_FREE(folder_uuid);
473
474         return ret;
475
476 ERROR:
477
478         /* free all data */
479         for (i = 0; i < idx; i++) {
480                 SAFE_FREE((*folder_list)[i]);
481                 SAFE_FREE(folder_uuid[i]);
482         }
483         SAFE_FREE(*folder_list);
484         SAFE_FREE(*modified_time_list);
485         SAFE_FREE(*item_num_list);
486         SAFE_FREE(folder_uuid);
487
488         *count = 0;
489
490         return ret;
491 }
492
493 int _media_svc_get_folder_info_by_foldername(sqlite3 *handle, const char *storage_id, const char *folder_name, char *folder_id, time_t *modified_time)
494 {
495         int ret = MS_MEDIA_ERR_NONE;
496         sqlite3_stmt *sql_stmt = NULL;
497
498         char *sql = sqlite3_mprintf("SELECT folder_uuid, modified_time FROM %s WHERE (storage_uuid = '%q' AND path = '%q');", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, folder_name);
499
500         ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
501
502         if (ret != MS_MEDIA_ERR_NONE) {
503                 if (ret == MS_MEDIA_ERR_DB_NO_RECORD)
504                         media_svc_debug("there is no folder.");
505                 else
506                         media_svc_error("error when _media_svc_get_folder_id_by_foldername. err = [%d]", ret);
507
508                 return ret;
509         }
510
511         _strncpy_safe(folder_id, (const char *)sqlite3_column_text(sql_stmt, 0), MEDIA_SVC_UUID_SIZE + 1);
512         *modified_time = (int)sqlite3_column_int(sql_stmt, 1);
513
514         SQLITE3_FINALIZE(sql_stmt);
515
516         return ret;
517 }
518
519 int _media_svc_get_and_append_folder_id_by_folder_path(sqlite3 *handle, const char *storage_id, const char *path, media_svc_storage_type_e storage_type, char *folder_id, bool stack_query, uid_t uid)
520 {
521         char *path_name = NULL;
522         int ret = MS_MEDIA_ERR_NONE;
523         char *sql = NULL;
524
525         path_name = strdup(path);
526         if (path_name == NULL) {
527                 media_svc_error("out of memory");
528                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
529         }
530
531         ret = _media_svc_get_folder_id_by_foldername(handle, storage_id, path_name, folder_id, uid);
532         if (ret == MS_MEDIA_ERR_DB_NO_RECORD) {
533                 bool is_root = FALSE;
534                 bool is_parent_root = FALSE;
535
536                 ret = __media_svc_is_root_path(path_name, &is_root, uid);
537                 ret = __media_svc_parent_is_ext_root_path(path_name, &is_parent_root);
538
539                 char parent_folder_uuid[MEDIA_SVC_UUID_SIZE+1] = {0, };
540                 memset(parent_folder_uuid, 0x00, sizeof(parent_folder_uuid));
541
542                 if ((is_root == FALSE) && (is_parent_root == FALSE)) {
543                         /*get parent folder id*/
544                         char *parent_path_name = g_path_get_dirname(path_name);
545
546                         ret = _media_svc_get_folder_id_by_foldername(handle, storage_id, parent_path_name, parent_folder_uuid, uid);
547                         if (ret != MS_MEDIA_ERR_NONE) {
548                                 if (ret == MS_MEDIA_ERR_DB_NO_RECORD) {
549                                 /*if No-Root directory scanning start before doing storage scanning, parent_folder_uuid can be NULL.
550                                 You can remove above logic if use below logic always. but I keep above code for the performance issue.
551                                 Most case (except No-Root directory scanning start before doing storage scanning) get parent_folder_uuid well*/
552                                 media_svc_error("[No-Error] There is no proper parent_folder_uuid. so try to make it");
553                                 ret = _media_svc_get_and_append_folder(handle, storage_id, path, storage_type, folder_id, uid);
554                                 } else {
555                                         media_svc_error("error when _media_svc_get_parent_folder_id_by_foldername. err = [%d]", ret);
556                                 }
557
558                                 SAFE_FREE(path_name);
559                                 SAFE_FREE(parent_path_name);
560
561                                 return ret;
562                         }
563                 }
564
565                 char *folder_uuid = _media_info_generate_uuid();
566                 if (folder_uuid == NULL) {
567                         media_svc_error("Invalid UUID");
568                         SAFE_FREE(path_name);
569                         return MS_MEDIA_ERR_INTERNAL;
570                 }
571
572                 ret = __media_svc_append_folder(storage_id, storage_type, folder_uuid, path_name, parent_folder_uuid, stack_query, uid);
573
574                 _strncpy_safe(folder_id, folder_uuid, MEDIA_SVC_UUID_SIZE+1);
575
576         } else {
577                 sql = sqlite3_mprintf("UPDATE '%s' SET validity=1 WHERE storage_uuid = '%q' AND path = '%q';", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, path);
578
579                 if (!stack_query) {
580                         ret = _media_svc_sql_query(sql, uid);
581                         SQLITE3_SAFE_FREE(sql);
582                 } else {
583                         _media_svc_sql_query_add(&g_media_svc_insert_folder_query_list, &sql);
584                 }
585         }
586
587         SAFE_FREE(path_name);
588
589         return ret;
590 }
591
592 int _media_svc_delete_invalid_folder(const char *storage_id, int storage_type, uid_t uid)
593 {
594         int ret = MS_MEDIA_ERR_NONE;
595         char *sql = NULL;
596
597         sql = sqlite3_mprintf("DELETE FROM '%s' WHERE storage_uuid = '%q' AND storage_type = %d AND validity = 0;", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, storage_type);
598         ret = _media_svc_sql_query(sql, uid);
599
600         SQLITE3_SAFE_FREE(sql);
601
602         return ret;
603 }
604
605 int _media_svc_set_folder_validity(sqlite3 *handle, const char *storage_id, const char *start_path, int validity, bool is_recursive, uid_t uid)
606 {
607         int ret = MS_MEDIA_ERR_NONE;
608         char *sql = NULL;
609         char start_path_id[MEDIA_SVC_UUID_SIZE+1] = {0,};
610
611         if (is_recursive) {
612                 ret = _media_svc_get_folder_id_by_foldername(handle, storage_id, start_path, start_path_id, uid);
613                 media_svc_retvm_if(ret != MS_MEDIA_ERR_NONE, ret, "_media_svc_get_folder_id_by_foldername fail");
614                 media_svc_retvm_if(!STRING_VALID(start_path_id), MS_MEDIA_ERR_INVALID_PARAMETER, "start_path_id is NULL");
615
616                 sql = sqlite3_mprintf("UPDATE '%s' SET validity = %d WHERE storage_uuid = '%q' AND (path LIKE '%q/%%' OR folder_uuid ='%q')",
617                                                 MEDIA_SVC_DB_TABLE_FOLDER, validity, storage_id, start_path, start_path_id);
618         } else {
619                 sql = sqlite3_mprintf("UPDATE '%s' SET validity = %d WHERE storage_uuid = '%q' AND path = '%q';",
620                                                 MEDIA_SVC_DB_TABLE_FOLDER, validity, storage_id, start_path);
621         }
622
623         ret = _media_svc_sql_query(sql, uid);
624
625         SQLITE3_SAFE_FREE(sql);
626
627         return ret;
628 }
629
630 int _media_svc_delete_folder_by_storage_id(const char *storage_id, media_svc_storage_type_e storage_type, uid_t uid)
631 {
632         int ret = MS_MEDIA_ERR_NONE;
633         char *sql = NULL;
634
635         sql = sqlite3_mprintf("DELETE FROM '%s' WHERE storage_uuid = '%q' AND storage_type = %d;", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, storage_type);
636         ret = _media_svc_sql_query(sql, uid);
637
638         SQLITE3_SAFE_FREE(sql);
639
640         return ret;
641 }
642
643 GList **_media_svc_get_folder_list_ptr(void)
644 {
645         return &g_media_svc_insert_folder_query_list;
646 }
647
648 int _media_svc_get_folder_scan_status(sqlite3 *handle, const char *storage_id, const char *path, int *scan_status)
649 {
650         int ret = MS_MEDIA_ERR_NONE;
651         sqlite3_stmt *sql_stmt = NULL;
652         char *sql = NULL;
653
654         if (!STRING_VALID(path)) {
655                 media_svc_error("Not found valid path");
656                 ret = MS_MEDIA_ERR_INVALID_PARAMETER;
657         }
658
659         sql = sqlite3_mprintf("SELECT scan_status FROM '%s' WHERE path = '%q' AND storage_uuid = '%q'", MEDIA_SVC_DB_TABLE_FOLDER, path, storage_id);
660
661         ret = _media_svc_sql_prepare_to_step_simple(handle, sql, &sql_stmt);
662
663         media_svc_retv_if(ret != MS_MEDIA_ERR_NONE, ret);
664
665         while (sqlite3_step(sql_stmt) == SQLITE_ROW)
666                 *scan_status = sqlite3_column_int(sql_stmt, 0);
667
668         SQLITE3_FINALIZE(sql_stmt);
669
670         return ret;
671 }
672
673 int _media_svc_set_folder_scan_status(const char *storage_id, const char *path, int scan_status, uid_t uid)
674 {
675         int ret = MS_MEDIA_ERR_NONE;
676         char *sql = NULL;
677
678         if (path)
679                 sql = sqlite3_mprintf("UPDATE '%s' SET scan_status=%d WHERE path = '%q' AND storage_uuid = '%q'", MEDIA_SVC_DB_TABLE_FOLDER, scan_status, path, storage_id);
680         else
681                 sql = sqlite3_mprintf("UPDATE '%s' SET scan_status=%d WHERE storage_uuid = '%q'", MEDIA_SVC_DB_TABLE_FOLDER, scan_status, storage_id);
682
683         ret = _media_svc_sql_query(sql, uid);
684         SQLITE3_SAFE_FREE(sql);
685
686         return ret;
687 }
688
689 int _media_svc_get_folder_modified_time_by_path(sqlite3 *handle, const char *path, const char *storage_id, time_t *modified_time)
690 {
691         int ret = MS_MEDIA_ERR_NONE;
692         sqlite3_stmt *sql_stmt = NULL;
693
694         char *sql = sqlite3_mprintf("SELECT modified_time FROM '%s' WHERE path = '%q' AND storage_uuid = '%q';", MEDIA_SVC_DB_TABLE_FOLDER, path, storage_id);
695
696         ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
697
698         if (ret != MS_MEDIA_ERR_NONE) {
699                 if (ret == MS_MEDIA_ERR_DB_NO_RECORD)
700                         media_svc_debug("there is no folder.");
701                 else
702                         media_svc_error("error when _media_svc_get_folder_modified_time_by_path. err = [%d]", ret);
703
704                 return ret;
705         }
706
707         *modified_time = (int)sqlite3_column_int(sql_stmt, 0);
708
709         SQLITE3_FINALIZE(sql_stmt);
710
711         return ret;
712 }
713
714 int _media_svc_get_null_scan_folder_list(sqlite3 *handle, const char *storage_id, const char *path, char ***folder_list, int *count)
715 {
716         int ret = MS_MEDIA_ERR_NONE;
717         int idx = 0;
718         int cnt = 0;
719         char *sql = NULL;
720         char folder_id[MEDIA_SVC_UUID_SIZE+1] = {0,};
721         sqlite3_stmt *sql_stmt = NULL;
722
723         if (path == NULL) {
724                 sql = sqlite3_mprintf("SELECT count(*) FROM '%s' WHERE storage_uuid = '%q' AND scan_status!=%d", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, FOLDER_SCAN_DONE);
725                 ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
726
727                 if (ret != MS_MEDIA_ERR_NONE) {
728                         if (ret == MS_MEDIA_ERR_DB_NO_RECORD)
729                                 media_svc_debug("there is no folder.");
730                         else
731                                 media_svc_error("error when get folder_id by path. err = [%d]", ret);
732
733                         *folder_list = NULL;
734                         *count = 0;
735
736                         return ret;
737                 }
738
739                 cnt = sqlite3_column_int(sql_stmt, 0);
740                 SQLITE3_FINALIZE(sql_stmt);
741                 if (cnt > 0) {
742                         sql = sqlite3_mprintf("SELECT path FROM '%s' WHERE storage_uuid = '%q' AND scan_status!=%d", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, FOLDER_SCAN_DONE);
743                 } else {
744                         *folder_list = NULL;
745                         *count = 0;
746
747                         return MS_MEDIA_ERR_INTERNAL;
748                 }
749
750                 ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
751
752                 if (ret != MS_MEDIA_ERR_NONE) {
753                         media_svc_error("prepare error [%s]", sqlite3_errmsg(handle));
754
755                         *folder_list = NULL;
756                         *count = 0;
757
758                         return ret;
759                 }
760         } else {
761                 sql = sqlite3_mprintf("SELECT folder_uuid FROM '%s' WHERE storage_uuid = '%q' AND path = '%q'", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, path);
762                 ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
763
764                 if (ret != MS_MEDIA_ERR_NONE) {
765                         if (ret == MS_MEDIA_ERR_DB_NO_RECORD)
766                                 media_svc_debug("there is no folder.");
767                         else
768                                 media_svc_error("error when get folder_id by path [%s]. err = [%d]", path, ret);
769
770                         return ret;
771                 }
772
773                 _strncpy_safe(folder_id, (const char *)sqlite3_column_text(sql_stmt, 0), MEDIA_SVC_UUID_SIZE+1);
774
775                 SQLITE3_FINALIZE(sql_stmt);
776
777                 sql = sqlite3_mprintf("SELECT count(*) FROM '%s' WHERE path LIKE '%q%%' AND parent_folder_uuid = '%q'", MEDIA_SVC_DB_TABLE_FOLDER, path, folder_id);
778
779                 ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
780
781                 if (ret != MS_MEDIA_ERR_NONE) {
782                         media_svc_error("error when _media_svc_sql_prepare_to_step. err = [%d]", ret);
783                         return ret;
784                 }
785
786                 cnt = sqlite3_column_int(sql_stmt, 0);
787                 SQLITE3_FINALIZE(sql_stmt);
788                 if (cnt > 0) {
789                         sql = sqlite3_mprintf("SELECT path FROM '%s' WHERE path LIKE '%q%%' AND parent_folder_uuid = '%q'", MEDIA_SVC_DB_TABLE_FOLDER, path, folder_id);
790                 } else {
791                         *folder_list = NULL;
792                         *count = 0;
793
794                         return MS_MEDIA_ERR_NONE;
795                 }
796
797                 ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
798
799                 if (ret != MS_MEDIA_ERR_NONE) {
800                         media_svc_error("prepare error [%s]", sqlite3_errmsg(handle));
801
802                         *folder_list = NULL;
803                         *count = 0;
804
805                         return ret;
806                 }
807         }
808
809         *folder_list = malloc(sizeof(char *) * cnt);
810
811         while (1) {
812                 (*folder_list)[idx] = strdup((char *)sqlite3_column_text(sql_stmt, 0));
813
814                 if (sqlite3_step(sql_stmt) != SQLITE_ROW)
815                         break;
816                 idx++;
817         }
818
819         if (cnt == idx + 1) {
820                 *count = cnt;
821                 media_svc_debug("OK");
822         } else {
823                 /* free all data */
824                 int i = 0;
825                 for (i  = 0; i < idx; i++)
826                         SAFE_FREE((*folder_list)[i]);
827
828                 SAFE_FREE(*folder_list);
829                 *count = 0;
830                 ret = MS_MEDIA_ERR_INTERNAL;
831         }
832
833         SQLITE3_FINALIZE(sql_stmt);
834
835         return ret;
836 }
837
838 int _media_svc_delete_invalid_folder_by_path(sqlite3 *handle, const char *storage_id, const char *folder_path, uid_t uid, int *delete_count)
839 {
840         int ret = MS_MEDIA_ERR_NONE;
841         char *sql = NULL;
842         int del_count = 0;
843         sqlite3_stmt *sql_stmt = NULL;
844
845         if (folder_path == NULL)
846                 return MS_MEDIA_ERR_INVALID_PARAMETER;
847
848         /*check the number of the deleted folder*/
849         sql = sqlite3_mprintf("SELECT count(*) FROM '%s' WHERE (storage_uuid = '%q' AND validity = 0 AND PATH LIKE '%q/%%');", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, folder_path);
850
851         ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
852         media_svc_retv_if(ret != MS_MEDIA_ERR_NONE, ret);
853
854         del_count = sqlite3_column_int(sql_stmt, 0);
855
856         SQLITE3_FINALIZE(sql_stmt);
857         sql = NULL;
858
859         /*delete invalid folder*/
860         sql = sqlite3_mprintf("DELETE FROM '%s' WHERE (storage_uuid = '%q' AND validity = 0 AND PATH LIKE '%q%%');", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, folder_path);
861         ret = _media_svc_sql_query(sql, uid);
862
863         SQLITE3_SAFE_FREE(sql);
864
865         *delete_count = del_count;
866
867         return ret;
868 }
869
870 int _media_svc_count_folder_with_path(sqlite3 *handle, const char *storage_id, const char *path, int *count)
871 {
872         int ret = MS_MEDIA_ERR_NONE;
873         sqlite3_stmt *sql_stmt = NULL;
874
875         char *sql = sqlite3_mprintf("SELECT count(*) FROM '%s' WHERE (storage_uuid='%q' AND path='%q')", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, path);
876
877         ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
878
879         media_svc_retv_if(ret != MS_MEDIA_ERR_NONE, ret);
880
881         *count = sqlite3_column_int(sql_stmt, 0);
882
883         SQLITE3_FINALIZE(sql_stmt);
884
885         return MS_MEDIA_ERR_NONE;
886 }
887
888 int _media_svc_count_subfolder_with_path(sqlite3 *handle, const char *storage_id, const char *path, int *count)
889 {
890         int ret = MS_MEDIA_ERR_NONE;
891         sqlite3_stmt *sql_stmt = NULL;
892
893         char *sql = sqlite3_mprintf("SELECT count(*) FROM '%s' WHERE (storage_uuid='%q' AND path LIKE'%q/%%')", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, path);
894
895         ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
896
897         media_svc_retv_if(ret != MS_MEDIA_ERR_NONE, ret);
898
899         *count = sqlite3_column_int(sql_stmt, 0);
900
901         SQLITE3_FINALIZE(sql_stmt);
902
903         return MS_MEDIA_ERR_NONE;
904 }
905
906 int _media_svc_get_folder_uuid(sqlite3 *handle, const char *storage_id, const char *path, char *folder_id)
907 {
908         int ret = MS_MEDIA_ERR_NONE;
909         sqlite3_stmt *sql_stmt = NULL;
910         char *sql = NULL;
911
912         sql = sqlite3_mprintf("SELECT folder_uuid FROM '%s' WHERE (storage_uuid='%q' AND path='%q')", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, path);
913
914         ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
915
916         media_svc_retv_if(ret != MS_MEDIA_ERR_NONE, ret);
917
918         _strncpy_safe(folder_id, (const char *)sqlite3_column_text(sql_stmt, 0), MEDIA_SVC_UUID_SIZE+1);
919
920         SQLITE3_FINALIZE(sql_stmt);
921
922         if (!STRING_VALID(folder_id)) {
923                 media_svc_error("Not found valid storage id [%s]", path);
924                 ret = MS_MEDIA_ERR_INVALID_PARAMETER;
925         }
926
927         return ret;
928 }
929