Upgrade media.db 7 to 8
[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 static __thread GList *g_media_svc_insert_folder_query_list;
31
32 int _media_svc_get_folder_id_by_foldername(sqlite3 *handle, const char *storage_id, const char *folder_name, char *folder_id, uid_t uid)
33 {
34         int ret = MS_MEDIA_ERR_NONE;
35         sqlite3_stmt *sql_stmt = NULL;
36         char *sql = NULL;
37
38         sql = sqlite3_mprintf("SELECT folder_id FROM %q WHERE storage_uuid = '%q' AND folder_path = '%q';", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, folder_name);
39
40         ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
41         if (ret != MS_MEDIA_ERR_NONE) {
42                 if (ret == MS_MEDIA_ERR_DB_NO_RECORD)
43                         media_svc_debug("there is no folder.");
44                 else
45                         media_svc_error("error when _media_svc_get_folder_id_by_foldername. err = [%d]", ret);
46
47                 return ret;
48         }
49
50         SAFE_STRLCPY(folder_id, (const char *)sqlite3_column_text(sql_stmt, 0), MEDIA_SVC_UUID_SIZE + 1);
51
52         SQLITE3_FINALIZE(sql_stmt);
53
54         return ret;
55 }
56
57 int _media_svc_get_folder_id_by_foldername_with_validity(sqlite3 *handle, const char *storage_id, const char *folder_name, char *folder_id, uid_t uid, int *validity)
58 {
59         int ret = MS_MEDIA_ERR_NONE;
60         sqlite3_stmt *sql_stmt = NULL;
61         char *sql = NULL;
62
63         sql = sqlite3_mprintf("SELECT folder_id, validity FROM %q WHERE storage_uuid='%q' AND folder_path='%q';", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, folder_name);
64
65         ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
66         if (ret != MS_MEDIA_ERR_NONE) {
67                 if (ret == MS_MEDIA_ERR_DB_NO_RECORD)
68                         media_svc_debug("there is no folder.");
69                 else
70                         media_svc_error("error when _media_svc_get_folder_id_by_foldername_with_validity. err = [%d]", ret);
71
72                 return ret;
73         }
74
75         SAFE_STRLCPY(folder_id, (const char *)sqlite3_column_text(sql_stmt, 0), MEDIA_SVC_UUID_SIZE + 1);
76         *validity = (int)sqlite3_column_int(sql_stmt, 1);
77
78         SQLITE3_FINALIZE(sql_stmt);
79
80         return ret;
81 }
82
83 static int __media_svc_append_folder(const char *storage_id, ms_user_storage_type_e storage_type,
84                         const char *folder_id, const char *folder_path, bool stack_query, uid_t uid)
85 {
86         int ret = MS_MEDIA_ERR_NONE;
87         char *folder_name = NULL;
88         int folder_modified_date = 0;
89
90         folder_name = g_path_get_basename(folder_path);
91         folder_modified_date = _media_svc_get_file_time(folder_path);
92
93         /*Update Pinyin If Support Pinyin*/
94         char *folder_name_pinyin = NULL;
95         if (_media_svc_check_pinyin_support())
96                 _media_svc_get_pinyin_str(folder_name, &folder_name_pinyin);
97         /* Sometime SQLITE3 returns NO_RECORD, so need to consider conflict case.. */
98         media_svc_debug("UNIQUE:path[%s], storage_uuid[%s]", folder_path, storage_id);
99         char *sql = sqlite3_mprintf("INSERT OR IGNORE INTO %q (folder_id, folder_path, folder_name, storage_uuid, folder_storage_type, folder_modified_time, folder_name_pinyin) values (%Q, %Q, %Q, %Q, '%d', '%d', %Q); ",
100                                 MEDIA_SVC_DB_TABLE_FOLDER, folder_id, folder_path, folder_name, storage_id, storage_type, folder_modified_date, folder_name_pinyin);
101
102         if (!stack_query) {
103                 ret = _media_svc_sql_query(sql, uid);
104                 SQLITE3_SAFE_FREE(sql);
105         } else {
106                 _media_svc_sql_query_add(&g_media_svc_insert_folder_query_list, &sql);
107         }
108
109         SAFE_FREE(folder_name);
110         SAFE_FREE(folder_name_pinyin);
111
112         return ret;
113 }
114
115 int _media_svc_update_folder_modified_time_by_folder_uuid(const char *folder_uuid, const char *folder_path, uid_t uid)
116 {
117         int ret = MS_MEDIA_ERR_NONE;
118         int modified_time = 0;
119
120         modified_time = _media_svc_get_file_time(folder_path);
121
122         char *sql = sqlite3_mprintf("UPDATE %q SET folder_modified_time=%d WHERE folder_id=%Q;", MEDIA_SVC_DB_TABLE_FOLDER, modified_time, folder_uuid);
123
124         ret = _media_svc_sql_query(sql, uid);
125         SQLITE3_SAFE_FREE(sql);
126
127         return ret;
128 }
129
130 static int __media_svc_get_and_append_parent_folder(sqlite3 *handle, const char *storage_id, const char *path, ms_user_storage_type_e storage_type, char *folder_id, uid_t uid)
131 {
132         int ret = MS_MEDIA_ERR_NONE;
133         unsigned int next_pos = 0;
134         char *next = NULL;
135         char *dir_path = NULL;
136         const char *token = "/";
137         char *folder_uuid = NULL;
138         char tmp_folder_uuid[MEDIA_SVC_UUID_SIZE + 1] = {0, };
139         bool folder_search_end = FALSE;
140         char *internal_path = NULL;
141
142         memset(tmp_folder_uuid, 0, sizeof(tmp_folder_uuid));
143         ret = ms_user_get_internal_root_path(uid, &internal_path);
144         media_svc_retvm_if(ret != MS_MEDIA_ERR_NONE, ret, "Fail to get root path");
145
146         if (STRING_VALID(internal_path) && (strncmp(path, internal_path, strlen(internal_path)) == 0))
147                 next_pos = strlen(internal_path);
148         else if (STRING_VALID(MEDIA_ROOT_PATH_SDCARD) && strncmp(path, MEDIA_ROOT_PATH_SDCARD, strlen(MEDIA_ROOT_PATH_SDCARD)) == 0)
149                 next_pos = strlen(MEDIA_ROOT_PATH_SDCARD);
150         else if (STRING_VALID(MEDIA_ROOT_PATH_EXTERNAL) && strncmp(path, MEDIA_ROOT_PATH_EXTERNAL, strlen(MEDIA_ROOT_PATH_EXTERNAL)) == 0)
151                 next_pos = strlen(MEDIA_ROOT_PATH_EXTERNAL);
152         else if (STRING_VALID(MEDIA_ROOT_PATH_DISC) && strncmp(path, MEDIA_ROOT_PATH_DISC, strlen(MEDIA_ROOT_PATH_DISC)) == 0)
153                 next_pos = strlen(MEDIA_ROOT_PATH_DISC);
154         else {
155                 media_svc_error("Invalid Path");
156                 media_svc_sec_error("Invalid Path [%s], internal_path [%s]", path, internal_path);
157                 SAFE_FREE(internal_path);
158                 return MS_MEDIA_ERR_INTERNAL;
159         }
160
161         SAFE_FREE(internal_path);
162
163         while (!folder_search_end) {
164                 next = strstr(path + next_pos, token);
165                 if (next != NULL) {
166                         next_pos = (next - path);
167                         dir_path = strndup(path, next_pos);
168                         next_pos++;
169                 } else {
170                         dir_path = strndup(path, strlen(path));
171                         folder_search_end = TRUE;
172                         media_svc_error("[No-Error] End Path [%s]", dir_path);
173                 }
174
175                 if (STRING_VALID(MEDIA_ROOT_PATH_EXTERNAL) && (g_strcmp0(dir_path, MEDIA_ROOT_PATH_EXTERNAL) == 0)) {
176                         /*To avoid insert MEDIA_ROOT_PATH_EXTERNAL path*/
177                         SAFE_FREE(dir_path);
178                         continue;
179                 }
180
181                 ret = _media_svc_get_folder_id_by_foldername(handle, storage_id, dir_path, tmp_folder_uuid, uid);
182                 if (ret == MS_MEDIA_ERR_DB_NO_RECORD) {
183                         folder_uuid = _media_info_generate_uuid();
184                         if (folder_uuid == NULL) {
185                                 media_svc_error("Invalid UUID");
186                                 SAFE_FREE(dir_path);
187                                 return MS_MEDIA_ERR_INTERNAL;
188                         }
189
190                         ret = __media_svc_append_folder(storage_id, storage_type, folder_uuid, dir_path, FALSE, uid);
191                         if (ret != MS_MEDIA_ERR_NONE)
192                                 media_svc_error("__media_svc_append_folder is failed");
193
194                         media_svc_error("[No-Error] New Appended folder path [%s], folder_uuid [%s]", dir_path, folder_uuid);
195                 } else {
196                         media_svc_error("EXIST dir path : %s", dir_path);
197                 }
198
199                 SAFE_FREE(dir_path);
200         }
201
202         if (STRING_VALID(folder_uuid)) {
203                 SAFE_STRLCPY(folder_id, folder_uuid, MEDIA_SVC_UUID_SIZE + 1);
204         } else {
205                 media_svc_error("Fail to get folder_uuid");
206                 return MS_MEDIA_ERR_INTERNAL;
207         }
208
209         return MS_MEDIA_ERR_NONE;
210 }
211
212 static int __media_svc_update_parent_folder_validity(sqlite3 *handle, const char *storage_id, const char *path, uid_t uid)
213 {
214         int ret = MS_MEDIA_ERR_NONE;
215         unsigned int next_pos = 0;
216         char *next = NULL;
217         char *dir_path = NULL;
218         const char *token = "/";
219         bool folder_search_end = FALSE;
220         char *internal_path = NULL;
221
222         ret = ms_user_get_internal_root_path(uid, &internal_path);
223         media_svc_retvm_if(ret != MS_MEDIA_ERR_NONE, ret, "Fail to get root path");
224
225         if (STRING_VALID(internal_path) && (strncmp(path, internal_path, strlen(internal_path)) == 0))
226                 next_pos = strlen(internal_path);
227         else if (STRING_VALID(MEDIA_ROOT_PATH_SDCARD) && strncmp(path, MEDIA_ROOT_PATH_SDCARD, strlen(MEDIA_ROOT_PATH_SDCARD)) == 0)
228                 next_pos = strlen(MEDIA_ROOT_PATH_SDCARD);
229         else if (STRING_VALID(MEDIA_ROOT_PATH_EXTERNAL) && strncmp(path, MEDIA_ROOT_PATH_EXTERNAL, strlen(MEDIA_ROOT_PATH_EXTERNAL)) == 0)
230                 next_pos = strlen(MEDIA_ROOT_PATH_EXTERNAL);
231         else if (STRING_VALID(MEDIA_ROOT_PATH_DISC) && strncmp(path, MEDIA_ROOT_PATH_DISC, strlen(MEDIA_ROOT_PATH_DISC)) == 0)
232                 next_pos = strlen(MEDIA_ROOT_PATH_DISC);
233         else {
234                 media_svc_error("Invalid Path");
235                 media_svc_sec_error("Invalid Path [%s], internal_path [%s]", path, internal_path);
236                 SAFE_FREE(internal_path);
237                 return MS_MEDIA_ERR_INTERNAL;
238         }
239
240         SAFE_FREE(internal_path);
241
242         while (!folder_search_end) {
243                 next = strstr(path + next_pos, token);
244                 if (next != NULL) {
245                         next_pos = (next - path);
246                         dir_path = strndup(path, next_pos);
247                         next_pos++;
248                 } else {
249                         dir_path = strndup(path, strlen(path));
250                         folder_search_end = TRUE;
251                         media_svc_error("[No-Error] End Path [%s]", dir_path);
252                 }
253
254                 if (STRING_VALID(MEDIA_ROOT_PATH_EXTERNAL) && (g_strcmp0(dir_path, MEDIA_ROOT_PATH_EXTERNAL) == 0)) {
255                         /*To avoid insert MEDIA_ROOT_PATH_EXTERNAL path*/
256                         SAFE_FREE(dir_path);
257                         continue;
258                 }
259
260                 ret = _media_svc_set_folder_validity(handle, storage_id, dir_path, 1, false, uid);
261                 SAFE_FREE(dir_path);
262                 media_svc_retvm_if(ret != MS_MEDIA_ERR_NONE, ret, "Fail to set folder validity");
263         }
264
265         return MS_MEDIA_ERR_NONE;
266 }
267
268 int _media_svc_get_and_append_folder(sqlite3 *handle, const char *storage_id, const char *path, ms_user_storage_type_e storage_type, char *folder_id, uid_t uid)
269 {
270         int ret = MS_MEDIA_ERR_NONE;
271         int validity = -1;
272
273         ret = _media_svc_get_folder_id_by_foldername_with_validity(handle, storage_id, path, folder_id, uid, &validity);
274
275         if (ret == MS_MEDIA_ERR_DB_NO_RECORD)
276                 ret = __media_svc_get_and_append_parent_folder(handle, storage_id, path, storage_type, folder_id, uid);
277         else if (ret == MS_MEDIA_ERR_NONE && validity == 0)
278                 ret = __media_svc_update_parent_folder_validity(handle, storage_id, path, uid);
279
280         return ret;
281 }
282
283 int _media_svc_get_and_append_folder_id_by_path(sqlite3 *handle, const char *storage_id, const char *path, ms_user_storage_type_e storage_type, char *folder_id, uid_t uid)
284 {
285         char *dir_path = NULL;
286         int ret = MS_MEDIA_ERR_NONE;
287
288         dir_path = g_path_get_dirname(path);
289
290         ret = _media_svc_get_and_append_folder(handle, storage_id, dir_path, storage_type, folder_id, uid);
291
292         SAFE_FREE(dir_path);
293
294         return ret;
295 }
296
297 int _media_svc_get_and_append_folder_id_by_folder_path(sqlite3 *handle, const char *storage_id, const char *path, ms_user_storage_type_e storage_type, char *folder_id, bool stack_query, uid_t uid)
298 {
299         char *path_name = NULL;
300         int ret = MS_MEDIA_ERR_NONE;
301         char *sql = NULL;
302
303         path_name = strdup(path);
304         if (path_name == NULL) {
305                 media_svc_error("out of memory");
306                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
307         }
308
309         ret = _media_svc_get_folder_id_by_foldername(handle, storage_id, path_name, folder_id, uid);
310         if (ret == MS_MEDIA_ERR_DB_NO_RECORD) {
311                 ret = __media_svc_get_and_append_parent_folder(handle, storage_id, path_name, storage_type, folder_id, uid);
312         } else {
313                 sql = sqlite3_mprintf("UPDATE %q SET validity=1 WHERE storage_uuid = '%q' AND folder_path = '%q';", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, path);
314                 if (!stack_query) {
315                         ret = _media_svc_sql_query(sql, uid);
316                         SQLITE3_SAFE_FREE(sql);
317                 } else {
318                         _media_svc_sql_query_add(&g_media_svc_insert_folder_query_list, &sql);
319                 }
320         }
321
322         SAFE_FREE(path_name);
323
324         return ret;
325 }
326
327 int _media_svc_set_folder_validity(sqlite3 *handle, const char *storage_id, const char *start_path, int validity, bool is_recursive, uid_t uid)
328 {
329         int ret = MS_MEDIA_ERR_NONE;
330         char *sql = NULL;
331         char start_path_id[MEDIA_SVC_UUID_SIZE+1] = {0,};
332
333         if (is_recursive) {
334                 ret = _media_svc_get_folder_id_by_foldername(handle, storage_id, start_path, start_path_id, uid);
335                 media_svc_retvm_if(ret != MS_MEDIA_ERR_NONE, ret, "_media_svc_get_folder_id_by_foldername fail");
336                 media_svc_retvm_if(!STRING_VALID(start_path_id), MS_MEDIA_ERR_INVALID_PARAMETER, "start_path_id is NULL");
337
338                 sql = sqlite3_mprintf("UPDATE %q SET validity = %d WHERE storage_uuid = '%q' AND (folder_path LIKE '%q/%%' OR folder_id='%q');",
339                                                 MEDIA_SVC_DB_TABLE_FOLDER, validity, storage_id, start_path, start_path_id);
340         } else {
341                 sql = sqlite3_mprintf("UPDATE %q SET validity = %d WHERE storage_uuid = '%q' AND folder_path='%q';",
342                                                 MEDIA_SVC_DB_TABLE_FOLDER, validity, storage_id, start_path);
343         }
344
345         ret = _media_svc_sql_query(sql, uid);
346
347         SQLITE3_SAFE_FREE(sql);
348
349         return ret;
350 }
351
352 GList **_media_svc_get_folder_list_ptr(void)
353 {
354         return &g_media_svc_insert_folder_query_list;
355 }
356
357 int _media_svc_count_folder_with_path(sqlite3 *handle, const char *storage_id, const char *path, int *count)
358 {
359         int ret = MS_MEDIA_ERR_NONE;
360         sqlite3_stmt *sql_stmt = NULL;
361         char *sql = NULL;
362
363         media_svc_retvm_if(!STRING_VALID(storage_id), MS_MEDIA_ERR_INVALID_PARAMETER, "storage_id is NULL");
364         media_svc_retvm_if(!STRING_VALID(path), MS_MEDIA_ERR_INVALID_PARAMETER, "path is NULL");
365
366         sql = sqlite3_mprintf("SELECT count(*) FROM %q WHERE (storage_uuid='%q' AND folder_path='%q')", MEDIA_SVC_DB_TABLE_FOLDER, storage_id, path);
367
368         ret = _media_svc_sql_prepare_to_step(handle, sql, &sql_stmt);
369
370         media_svc_retv_if(ret != MS_MEDIA_ERR_NONE, ret);
371
372         *count = sqlite3_column_int(sql_stmt, 0);
373
374         SQLITE3_FINALIZE(sql_stmt);
375
376         return MS_MEDIA_ERR_NONE;
377 }