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