Fix codes for setting certificate
[platform/core/appfw/pkgmgr-info.git] / src / pkginfo_internal.c
1 // copyright
2
3 #define _GNU_SOURCE
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <stdbool.h>
8 #include <unistd.h>
9 #include <ctype.h>
10 #include <sys/smack.h>
11 #include <linux/limits.h>
12 #include <libgen.h>
13 #include <sys/stat.h>
14
15 #include <sqlite3.h>
16 #include <glib.h>
17
18 #include "pkgmgrinfo_basic.h"
19 #include "pkgmgrinfo_private.h"
20 #include "pkgmgrinfo_debug.h"
21 #include "pkgmgr-info.h"
22
23 #define __BEGIN_TRANSACTION(db)                                                \
24 do {                                                                           \
25         if (sqlite3_exec(db, "BEGIN DEFERRED", NULL, NULL, NULL) !=            \
26                         SQLITE_OK) {                                           \
27                 _LOGE("begin transaction failed: %s", sqlite3_errmsg(db));     \
28                 return -1;                                                     \
29         }                                                                      \
30 } while (0)                                                                    \
31
32 #define __DO_TRANSACTION(db, func)                                             \
33 do {                                                                           \
34         if (func) {                                                            \
35                 _LOGE("transaction failed: %s, rollback", sqlite3_errmsg(db)); \
36                 if (sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL) !=          \
37                                 SQLITE_OK)                                     \
38                         _LOGE("roll back transaction failed: %s",              \
39                                         sqlite3_errmsg(db));                   \
40                 return -1;                                                     \
41         }                                                                      \
42 } while (0)                                                                    \
43
44 #define __END_TRANSACTION(db)                                                  \
45 do {                                                                           \
46         if (sqlite3_exec(db, "COMMIT", NULL, NULL, NULL) !=                    \
47                         SQLITE_OK) {                                           \
48                 _LOGE("commit failed: %s, rollback", sqlite3_errmsg(db));      \
49                 if (sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL) !=          \
50                                 SQLITE_OK)                                     \
51                         _LOGE("roll back transaction failed: %s",              \
52                                         sqlite3_errmsg(db));                   \
53                 return -1;                                                     \
54         }                                                                      \
55 } while (0)                                                                    \
56
57 static int __free_packages(gpointer key, gpointer value,
58                 gpointer user_data)
59 {
60         pkgmgrinfo_basic_free_package((package_x *)value);
61
62         return 0;
63 }
64
65 static const char join_localized_info[] =
66         " LEFT OUTER JOIN package_localized_info"
67         "  ON pi.package=package_localized_info.package"
68         "  AND package_localized_info.package_locale=?";
69 static const char join_privilege_info[] =
70         " LEFT OUTER JOIN package_privilege_info"
71         "  ON pi.package=package_privilege_info.package";
72
73 static int _get_filtered_query(pkgmgrinfo_filter_x *filter,
74                 const char *locale, uid_t uid, char **query, GList **bind_params)
75 {
76         int joined = 0;
77         int size;
78         char buf[MAX_QUERY_LEN] = { '\0' };
79         char buf2[MAX_QUERY_LEN] = { '\0' };
80         char *condition = NULL;
81         GSList *list = NULL;
82
83         if (filter == NULL)
84                 return PMINFO_R_OK;
85
86         snprintf(buf, sizeof(buf), "%s", " WHERE 1=1 ");
87         for (list = filter->list; list; list = list->next) {
88                 joined |= __get_filter_condition(list->data, uid, &condition,
89                                 bind_params);
90                 if (condition == NULL)
91                         continue;
92
93                 strncat(buf, " AND ", sizeof(buf) - strlen(buf) - 1);
94
95                 strncat(buf, condition, sizeof(buf) - strlen(buf) - 1);
96                 free(condition);
97                 condition = NULL;
98         }
99
100         if (joined & E_PMINFO_PKGINFO_JOIN_LOCALIZED_INFO) {
101                 strncat(buf2, join_localized_info, sizeof(buf2) - strlen(buf2) - 1);
102                 *bind_params = g_list_append(*bind_params, strdup(locale));
103         }
104         if (joined & E_PMINFO_PKGINFO_JOIN_PRIVILEGE_INFO)
105                 strncat(buf2, join_privilege_info, sizeof(buf2) - strlen(buf2) - 1);
106
107         size = strlen(buf2) + strlen(buf) + 1;
108         *query = (char *)calloc(1, size);
109         if (*query == NULL)
110                 return PMINFO_R_ERROR;
111         snprintf(*query, size, "%s%s", buf2, buf);
112
113         return PMINFO_R_OK;
114 }
115
116 static int __bind_params(sqlite3_stmt *stmt, GList *params)
117 {
118         GList *tmp_list = NULL;
119         int idx = 0;
120         int ret;
121
122         if (stmt == NULL || params == NULL)
123                 return PMINFO_R_EINVAL;
124
125         tmp_list = params;
126         while (tmp_list) {
127                 ret = sqlite3_bind_text(stmt, ++idx, (char *)tmp_list->data, -1, SQLITE_STATIC);
128                 if (ret != SQLITE_OK)
129                         return PMINFO_R_ERROR;
130                 tmp_list = tmp_list->next;
131         }
132
133         return PMINFO_R_OK;
134 }
135
136 static bool __check_package_storage_status(pkgmgrinfo_filter_x *tmp_filter)
137 {
138         GSList *tmp_list = NULL;
139         pkgmgrinfo_node_x *tmp_node = NULL;
140         int property = -1;
141
142         property = _pminfo_pkginfo_convert_to_prop_bool(PMINFO_PKGINFO_PROP_PACKAGE_CHECK_STORAGE);
143         for (tmp_list = tmp_filter->list; tmp_list != NULL;
144                         tmp_list = g_slist_next(tmp_list)) {
145                 tmp_node = (pkgmgrinfo_node_x *)tmp_list->data;
146                 if (property == tmp_node->prop) {
147                         if (strcmp(tmp_node->value, "true") == 0)
148                                 return true;
149                         else
150                                 return false;
151                 }
152         }
153         return true;
154 }
155
156 static int _pkginfo_add_description_info_into_list(const char *locale,
157                 char *record, GList **description)
158 {
159         description_x *info;
160
161         info = calloc(1, sizeof(description_x));
162         if (info == NULL) {
163                 LOGE("out of memory");
164                 return PMINFO_R_ERROR;
165         }
166         info->lang = strdup(locale);
167         info->text = record;
168         *description = g_list_prepend(*description, info);
169
170         return PMINFO_R_OK;
171 }
172
173 static int _pkginfo_get_plugin_execution_info(sqlite3 *db, const char *pkgid,
174                 GList **plugins)
175 {
176         static const char query_raw[] =
177                 "SELECT appid, plugin_type, plugin_name FROM package_plugin_info "
178                 "WHERE pkgid=%Q";
179         int ret;
180         char *query;
181         sqlite3_stmt *stmt;
182         plugin_x *plugin;
183
184         query = sqlite3_mprintf(query_raw, pkgid);
185         if (query == NULL) {
186                 LOGE("out of memory");
187                 return PMINFO_R_ERROR;
188         }
189
190         ret = sqlite3_prepare_v2(db, query, strlen(query),
191                         &stmt, NULL);
192         sqlite3_free(query);
193         if (ret != SQLITE_OK) {
194                 LOGE("prepare failed: %s", sqlite3_errmsg(db));
195                 return PMINFO_R_ERROR;
196         }
197
198         while (sqlite3_step(stmt) == SQLITE_ROW) {
199                 plugin = calloc(1, sizeof(plugin_x));
200                 if (!plugin) {
201                         LOGE("out of memory");
202                         sqlite3_finalize(stmt);
203                         return PMINFO_R_ERROR;
204                 }
205                 plugin->pkgid = strdup(pkgid);
206                 _save_column_str(stmt, 0, &plugin->appid);
207                 _save_column_str(stmt, 1, &plugin->plugin_type);
208                 _save_column_str(stmt, 2, &plugin->plugin_name);
209                 *plugins = g_list_prepend(*plugins,
210                                 (gpointer)plugin);
211         }
212
213         sqlite3_finalize(stmt);
214
215         return PMINFO_R_OK;
216 }
217
218 static int _pkginfo_get_privilege(sqlite3 *db, const char *pkgid,
219                 GList **privileges)
220 {
221         static const char query_raw[] =
222                 "SELECT DISTINCT privilege, type FROM package_privilege_info "
223                 "WHERE package=%Q";
224         int ret;
225         char *query;
226         sqlite3_stmt *stmt;
227         privilege_x *privilege;
228
229         query = sqlite3_mprintf(query_raw, pkgid);
230         if (query == NULL) {
231                 LOGE("out of memory");
232                 return PMINFO_R_ERROR;
233         }
234
235         ret = sqlite3_prepare_v2(db, query, strlen(query),
236                         &stmt, NULL);
237         sqlite3_free(query);
238         if (ret != SQLITE_OK) {
239                 LOGE("prepare failed: %s", sqlite3_errmsg(db));
240                 return PMINFO_R_ERROR;
241         }
242
243         while (sqlite3_step(stmt) == SQLITE_ROW) {
244                 privilege = calloc(1, sizeof(privilege_x));
245                 if (!privilege) {
246                         LOGE("failed to alloc memory");
247                         sqlite3_finalize(stmt);
248                         return PMINFO_R_ERROR;
249                 }
250                 _save_column_str(stmt, 0, &privilege->value);
251                 _save_column_str(stmt, 1, &privilege->type);
252                 *privileges = g_list_prepend(*privileges,
253                                 (gpointer)privilege);
254         }
255
256         sqlite3_finalize(stmt);
257
258         return PMINFO_R_OK;
259 }
260
261 static int _pkginfo_get_appdefined_privilege(sqlite3 *db, const char *pkgid,
262                 GList **privileges)
263 {
264         static const char query_raw[] =
265                 "SELECT DISTINCT privilege, license, type FROM "
266                 "package_appdefined_privilege_info WHERE package=%Q";
267         int ret;
268         char *query;
269         sqlite3_stmt *stmt;
270         appdefined_privilege_x *privilege;
271
272         query = sqlite3_mprintf(query_raw, pkgid);
273         if (query == NULL) {
274                 LOGE("out of memory");
275                 return PMINFO_R_ERROR;
276         }
277
278         ret = sqlite3_prepare_v2(db, query, strlen(query),
279                         &stmt, NULL);
280         sqlite3_free(query);
281         if (ret != SQLITE_OK) {
282                 LOGE("prepare failed: %s", sqlite3_errmsg(db));
283                 return PMINFO_R_ERROR;
284         }
285
286         while (sqlite3_step(stmt) == SQLITE_ROW) {
287                 privilege = calloc(1, sizeof(appdefined_privilege_x));
288                 if (!privilege) {
289                         LOGE("failed to alloc memory");
290                         sqlite3_finalize(stmt);
291                         return PMINFO_R_ERROR;
292                 }
293                 _save_column_str(stmt, 0, &privilege->value);
294                 _save_column_str(stmt, 1, &privilege->license);
295                 _save_column_str(stmt, 2, &privilege->type);
296                 *privileges = g_list_prepend(*privileges,
297                                 (gpointer)privilege);
298         }
299
300         sqlite3_finalize(stmt);
301
302         return PMINFO_R_OK;
303 }
304
305 static int _pkginfo_get_dependency(sqlite3 *db, const char *pkgid,
306                 GList **dependencies)
307 {
308         static const char query_raw[] =
309                 "SELECT DISTINCT depends_on, type, required_version "
310                 "FROM package_dependency_info WHERE package=%Q";
311         int ret;
312         char *query;
313         sqlite3_stmt *stmt;
314         dependency_x *dependency;
315
316         query = sqlite3_mprintf(query_raw, pkgid);
317         if (query == NULL) {
318                 LOGE("out of memory");
319                 return PMINFO_R_ERROR;
320         }
321
322         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
323         sqlite3_free(query);
324         if (ret != SQLITE_OK) {
325                 LOGE("prepare failed: %s", sqlite3_errmsg(db));
326                 return PMINFO_R_ERROR;
327         }
328
329         while (sqlite3_step(stmt) == SQLITE_ROW) {
330                 dependency = calloc(1, sizeof(dependency_x));
331                 if (!dependency) {
332                         LOGE("failed to alloc memory");
333                         sqlite3_finalize(stmt);
334                         return PMINFO_R_ERROR;
335                 }
336                 _save_column_str(stmt, 0, &dependency->depends_on);
337                 _save_column_str(stmt, 1, &dependency->type);
338                 _save_column_str(stmt, 2, &dependency->required_version);
339                 *dependencies = g_list_prepend(*dependencies,
340                                 (gpointer)dependency);
341         }
342
343         sqlite3_finalize(stmt);
344
345         return PMINFO_R_OK;
346 }
347
348 static int _pkginfo_get_packages(sqlite3 *db, uid_t uid, const char *locale,
349                 pkgmgrinfo_filter_x *filter, int flag, GHashTable *packages)
350 {
351         static const char query_raw[] =
352                 "SELECT DISTINCT pi.package, pi.installed_storage, pi.external_path";
353         static const char query_basic[] =
354                 ", pi.package_version, pi.install_location, "
355                 "pi.package_removable, pi.package_preload, pi.package_readonly, "
356                 "pi.package_update, pi.package_appsetting, pi.package_system, "
357                 "pi.package_type, pi.package_size, pi.installed_time, "
358                 "pi.storeclient_id, pi.mainapp_id, pi.package_url, pi.root_path, "
359                 "pi.csc_path, pi.package_nodisplay, pi.package_api_version, "
360                 "pi.package_support_disable, pi.package_tep_name, "
361                 "pi.package_zip_mount_file, pi.package_support_mode";
362         static const char query_author[] =
363                 ", pi.author_name, pi.author_email, pi.author_href";
364         static const char query_label[] =
365                 ", COALESCE("
366                 "(SELECT package_label FROM package_localized_info WHERE pi.package=package AND package_locale=?), "
367                 "(SELECT package_label FROM package_localized_info WHERE pi.package=package AND package_locale='No Locale'))";
368         static const char query_icon[] =
369                 ", COALESCE("
370                 "(SELECT package_icon FROM package_localized_info WHERE pi.package=package AND package_locale=?), "
371                 "(SELECT package_icon FROM package_localized_info WHERE pi.package=package AND package_locale='No Locale'))";
372         static const char query_description[] =
373                 ", COALESCE("
374                 "(SELECT package_description FROM package_localized_info WHERE pi.package=package AND package_locale=?), "
375                 "(SELECT package_description FROM package_localized_info WHERE pi.package=package AND package_locale='No Locale'))";
376         static const char query_from_clause[] = " FROM package_info as pi";
377         int ret = PMINFO_R_ERROR;
378         int idx = 0;
379         //char *dbpath;
380         char *tmp_record = NULL;
381         char *constraints = NULL;
382         char query[MAX_QUERY_LEN] = { '\0' };
383         package_x *info = NULL;
384         author_x *author = NULL;
385         GList *bind_params = NULL;
386         //sqlite3 *db;
387         sqlite3_stmt *stmt = NULL;
388         bool is_check_storage = true;
389         const uid_t global_user_uid = GLOBAL_USER;
390 #if 0
391         dbpath = getUserPkgParserDBPathUID(uid);
392         if (dbpath == NULL)
393                 return PMINFO_R_ERROR;
394
395         ret = __open_db(dbpath, &db, SQLITE_OPEN_READONLY);
396         if (ret != SQLITE_OK) {
397                 _LOGD("failed to open db(%s): %d", dbpath, ret);
398                 free(dbpath);
399                 return PMINFO_R_ERROR;
400         }
401         free(dbpath);
402 #endif
403         is_check_storage = __check_package_storage_status(filter);
404
405         snprintf(query, MAX_QUERY_LEN - 1, "%s", query_raw);
406         if (flag & PMINFO_APPINFO_GET_BASICINFO)
407                 strncat(query, query_basic, sizeof(query) - strlen(query) - 1);
408         if (flag & PMINFO_PKGINFO_GET_AUTHOR)
409                 strncat(query, query_author, sizeof(query) - strlen(query) - 1);
410         if (flag & PMINFO_PKGINFO_GET_LABEL) {
411                 strncat(query, query_label, sizeof(query) - strlen(query) - 1);
412                 bind_params = g_list_append(bind_params, strdup(locale));
413         }
414         if (flag & PMINFO_PKGINFO_GET_ICON) {
415                 strncat(query, query_icon, sizeof(query) - strlen(query) - 1);
416                 bind_params = g_list_append(bind_params, strdup(locale));
417         }
418         if (flag & PMINFO_PKGINFO_GET_DESCRIPTION) {
419                 strncat(query, query_description, sizeof(query) - strlen(query) - 1);
420                 bind_params = g_list_append(bind_params, strdup(locale));
421         }
422
423         strncat(query, query_from_clause, sizeof(query) - strlen(query) - 1);
424
425         ret = _get_filtered_query(filter, locale, uid, &constraints, &bind_params);
426         if (ret != PMINFO_R_OK) {
427                 LOGE("Failed to get WHERE clause");
428                 goto catch;
429         }
430
431         if (constraints)
432                 strncat(query, constraints, sizeof(query) - strlen(query) - 1);
433
434         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
435         if (ret != SQLITE_OK) {
436                 LOGE("prepare failed: %s", sqlite3_errmsg(db));
437                 ret = PMINFO_R_ERROR;
438                 goto catch;
439         }
440
441         ret = __bind_params(stmt, bind_params);
442         if (ret != SQLITE_OK) {
443                 LOGE("Failed to bind parameters");
444                 goto catch;
445         }
446
447         while (sqlite3_step(stmt) == SQLITE_ROW) {
448                 info = calloc(1, sizeof(package_x));
449                 if (info == NULL) {
450                         LOGE("out of memory");
451                         ret = PMINFO_R_ERROR;
452                         goto catch;
453                 }
454                 info->locale = strdup(locale);
455                 if (info->locale == NULL) {
456                         LOGE("Out of memory");
457                         ret = PMINFO_R_ERROR;
458                         goto catch;
459                 }
460
461                 idx = 0;
462                 _save_column_str(stmt, idx++, &info->package);
463                 _save_column_str(stmt, idx++, &info->installed_storage);
464                 _save_column_str(stmt, idx++, &info->external_path);
465
466                 if (flag & PMINFO_APPINFO_GET_BASICINFO) {
467                         _save_column_str(stmt, idx++, &info->version);
468                         _save_column_str(stmt, idx++, &info->installlocation);
469                         _save_column_str(stmt, idx++, &info->removable);
470                         _save_column_str(stmt, idx++, &info->preload);
471                         _save_column_str(stmt, idx++, &info->readonly);
472                         _save_column_str(stmt, idx++, &info->update);
473                         _save_column_str(stmt, idx++, &info->appsetting);
474                         _save_column_str(stmt, idx++, &info->system);
475                         _save_column_str(stmt, idx++, &info->type);
476                         _save_column_str(stmt, idx++, &info->package_size);
477                         _save_column_str(stmt, idx++, &info->installed_time);
478                         _save_column_str(stmt, idx++, &info->storeclient_id);
479                         _save_column_str(stmt, idx++, &info->mainapp_id);
480                         _save_column_str(stmt, idx++, &info->package_url);
481                         _save_column_str(stmt, idx++, &info->root_path);
482                         _save_column_str(stmt, idx++, &info->csc_path);
483                         _save_column_str(stmt, idx++, &info->nodisplay_setting);
484                         _save_column_str(stmt, idx++, &info->api_version);
485                         _save_column_str(stmt, idx++, &info->support_disable);
486                         _save_column_str(stmt, idx++, &info->tep_name);
487                         _save_column_str(stmt, idx++, &info->zip_mount_file);
488                         _save_column_str(stmt, idx++, &info->support_mode);
489                 }
490
491                 info->for_all_users =
492                         strdup((uid != global_user_uid) ? "false" : "true");
493
494                 if (_pkginfo_get_plugin_execution_info(db, info->package, &info->plugin)) {
495                         ret = PMINFO_R_ERROR;
496                         goto catch;
497                 }
498
499                 if (flag & PMINFO_PKGINFO_GET_AUTHOR) {
500                         /* TODO : author should be retrieved at package_localized_info */
501                         author = calloc(1, sizeof(author_x));
502                         if (author == NULL) {
503                                 ret = PMINFO_R_ERROR;
504                                 goto catch;
505                         }
506                         _save_column_str(stmt, idx++, &author->text);
507                         _save_column_str(stmt, idx++, &author->email);
508                         _save_column_str(stmt, idx++, &author->href);
509                         info->author = g_list_prepend(info->author, author);
510                 }
511
512                 if (flag & PMINFO_PKGINFO_GET_LABEL) {
513                         tmp_record = NULL;
514                         _save_column_str(stmt, idx++, &tmp_record);
515
516                         if (_add_label_info_into_list(locale, tmp_record, &info->label)) {
517                                 ret = PMINFO_R_ERROR;
518                                 goto catch;
519                         }
520                 }
521
522                 if (flag & PMINFO_PKGINFO_GET_ICON) {
523                         tmp_record = NULL;
524                         _save_column_str(stmt, idx++, &tmp_record);
525                         if (_add_icon_info_into_list(locale, tmp_record, &info->icon)) {
526                                 ret = PMINFO_R_ERROR;
527                                 goto catch;
528                         }
529                 }
530
531                 if (flag & PMINFO_PKGINFO_GET_DESCRIPTION) {
532                         tmp_record = NULL;
533                         _save_column_str(stmt, idx++, &tmp_record);
534                         if (_pkginfo_add_description_info_into_list(locale, tmp_record,
535                                         &info->description)) {
536                                 ret = PMINFO_R_ERROR;
537                                 goto catch;
538                         }
539                 }
540
541                 if (flag & PMINFO_PKGINFO_GET_PRIVILEGE) {
542                         if (_pkginfo_get_privilege(db, info->package,
543                                                 &info->privileges)) {
544                                 ret = PMINFO_R_ERROR;
545                                 goto catch;
546                         }
547                 }
548
549                 if (flag & PMINFO_PKGINFO_GET_APPDEFINED_PRIVILEGE) {
550                         if (_pkginfo_get_appdefined_privilege(db, info->package,
551                                                 &info->appdefined_privileges)) {
552                                 ret = PMINFO_R_ERROR;
553                                 goto catch;
554                         }
555                 }
556
557                 if (flag & PMINFO_PKGINFO_GET_DEPENDENCY) {
558                         if (_pkginfo_get_dependency(db, info->package,
559                                                 &info->dependencies)) {
560                                 ret = PMINFO_R_ERROR;
561                                 goto catch;
562                         }
563                 }
564
565                 if (is_check_storage &&
566                                 __pkginfo_check_installed_storage(info) != PMINFO_R_OK) {
567                         ret = PMINFO_R_ERROR;
568                         pkgmgrinfo_basic_free_package(info);
569                         info = NULL;
570                         continue;
571                 }
572
573                 g_hash_table_insert(packages, (gpointer)info->package,
574                                 (gpointer)info);
575         }
576
577         ret = PMINFO_R_OK;
578
579 catch:
580         sqlite3_finalize(stmt);
581
582         if (constraints)
583                 free(constraints);
584
585         if (ret != PMINFO_R_OK && info != NULL)
586                 pkgmgrinfo_basic_free_package(info);
587
588         g_list_free_full(bind_params, free);
589
590         return ret;
591 }
592
593 API int pkginfo_internal_filter_get_list(
594                 sqlite3 *db, pkgmgrinfo_pkginfo_filter_h filter,
595                 uid_t uid, const char *locale, GHashTable **pkginfo_list) {
596         GHashTable *list;
597         int ret;
598
599         if (filter == NULL || pkginfo_list == NULL) {
600                 // TODO: print error log
601                 return PMINFO_R_EINVAL;
602         }
603
604         list = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
605                         NULL);
606         if (list == NULL)
607                 return PMINFO_R_ERROR;
608
609         ret = _pkginfo_get_packages(db, uid, locale, filter,
610                         PMINFO_PKGINFO_GET_ALL, list);
611         if (ret == PMINFO_R_OK && uid != GLOBAL_USER)
612                 ret = _pkginfo_get_packages(db, GLOBAL_USER, locale, filter,
613                                 PMINFO_PKGINFO_GET_ALL, list);
614
615         if (ret != PMINFO_R_OK) {
616                 g_hash_table_foreach_remove(list, __free_packages, NULL);
617                 g_hash_table_destroy(list);
618                 return ret;
619         }
620
621         *pkginfo_list = list;
622         return PMINFO_R_OK;
623 }
624
625 API int get_query_result(sqlite3 *db, const char *query,
626                 GList **list, int *row, int *col) {
627         int ret = 0;
628         int col_cnt = 0;
629         int row_cnt = 0;
630         int idx = 0;
631         sqlite3_stmt *stmt = NULL;
632         char *result = NULL;
633
634         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
635         if (ret != SQLITE_OK) {
636                 LOGE("prepare failed: %s", sqlite3_errmsg(db));
637                 return PMINFO_R_ERROR;
638         }
639
640         col_cnt = sqlite3_column_count(stmt);
641
642         while (sqlite3_step(stmt) == SQLITE_ROW) {
643                 row_cnt++;
644                 for (idx = 0; idx < col_cnt; ++idx) {
645                         _save_column_str(stmt, idx, &result);
646                         *list = g_list_append(*list, result);
647                         result = NULL;
648                 }
649         }
650
651         *row = row_cnt;
652         *col = col_cnt;
653
654         sqlite3_finalize(stmt);
655
656         return PMINFO_R_OK;
657 }
658
659 static int _get_depends_on(sqlite3 *db, const char *pkgid, GQueue **queue,
660                 GHashTable **table, GList **pkg_list)
661 {
662         static const char query[] =
663                 "SELECT package, depends_on, type, required_version "
664                 "FROM package_dependency_info WHERE depends_on=?";
665         int ret;
666         sqlite3_stmt *stmt;
667         dependency_x *req;
668
669         /* already checked */
670         if (!g_hash_table_insert(*table, strdup(pkgid), GINT_TO_POINTER(1)))
671                 return PMINFO_R_OK;
672
673         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
674         if (ret != SQLITE_OK) {
675                 LOGE("prepare failed: %s", sqlite3_errmsg(db));
676                 return PMINFO_R_ERROR;
677         }
678
679         ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_STATIC);
680         if (ret != SQLITE_OK) {
681                 LOGE("bind failed: %s", sqlite3_errmsg(db));
682                 sqlite3_finalize(stmt);
683                 return PMINFO_R_ERROR;
684         }
685
686         while (sqlite3_step(stmt) == SQLITE_ROW) {
687                 req = calloc(1, sizeof(dependency_x));
688                 if (req == NULL) {
689                         LOGE("out of memory");
690                         sqlite3_finalize(stmt);
691                         return PMINFO_R_ERROR;
692                 }
693                 _save_column_str(stmt, 0, &req->pkgid);
694                 _save_column_str(stmt, 1, &req->depends_on);
695                 _save_column_str(stmt, 2, &req->type);
696                 _save_column_str(stmt, 3, &req->required_version);
697
698                 *pkg_list = g_list_prepend(*pkg_list, req);
699                 g_queue_push_tail(*queue, strdup(req->pkgid));
700         }
701
702         sqlite3_finalize(stmt);
703
704         return PMINFO_R_OK;
705 }
706
707 static void __free_depends_on(gpointer data)
708 {
709         struct dependency_x *dep = (struct dependency_x *)data;
710         free(dep->pkgid);
711         free(dep->depends_on);
712         free(dep->type);
713         free(dep->required_version);
714         free(dep);
715 }
716
717 API int pkginfo_internal_filter_get_depends_on(sqlite3 *db, const char *pkgid,
718                 GList **list) {
719         GQueue *queue;
720         GHashTable *table;
721         char *item;
722         int ret;
723
724         queue = g_queue_new();
725         if (queue == NULL) {
726                 LOGE("out of memory");
727                 return PMINFO_R_ERROR;
728         }
729         table = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
730
731         g_queue_push_tail(queue, strdup(pkgid));
732         while (!g_queue_is_empty(queue)) {
733                 item = g_queue_pop_head(queue);
734                 ret = _get_depends_on(db, item, &queue, &table, list);
735                 free(item);
736                 if (ret != PMINFO_R_OK) {
737                         LOGE("failed to get pkgs depends on %s", pkgid);
738                         g_hash_table_destroy(table);
739                         g_list_free_full(*list, __free_depends_on);
740                         g_queue_free_full(queue, free);
741                         return PMINFO_R_ERROR;
742                 }
743         }
744
745         g_hash_table_destroy(table);
746         g_queue_free_full(queue, free);
747         return PMINFO_R_OK;
748 }
749
750 static int __execute_query(sqlite3 *db, const char *query) {
751         int ret = 0;
752         sqlite3_stmt *stmt = NULL;
753
754         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
755         if (ret != SQLITE_OK) {
756                 LOGE("prepare failed: %s", sqlite3_errmsg(db));
757                 return -1;
758         }
759
760         ret = sqlite3_step(stmt);
761         if (ret != SQLITE_DONE) {
762                 LOGE("step failed: %s", sqlite3_errmsg(db));
763                 sqlite3_finalize(stmt);
764                 return -1;
765         }
766
767         sqlite3_finalize(stmt);
768
769         return 0;
770 }
771
772 API int execute_write_queries(sqlite3 *db, const char **queries, int len) {
773         int i;
774
775         __BEGIN_TRANSACTION(db);
776         for (i = 0; i < len; ++i) {
777                 __DO_TRANSACTION(db, __execute_query(db, queries[i]));
778         }
779         __END_TRANSACTION(db);
780
781         // Is db handel freed by AbstractDBHandler?
782         // sqlite3_close_v2(db);
783
784         return 0;
785 }