tizen 2.3 release
[apps/livebox/data-provider-master.git] / src / io.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <errno.h>
19 #include <sys/types.h>
20 #include <dirent.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <ctype.h>
25
26 #include <dlog.h>
27 #include <Eina.h>
28 #include <sqlite3.h>
29 #include <db-util.h>
30 #include <dynamicbox_errno.h>
31 #include <dynamicbox_service.h>
32 #include <dynamicbox_conf.h>
33
34 #include "debug.h"
35 #include "conf.h"
36 #include "parser.h"
37 #include "group.h"
38 #include "util.h"
39 #include "client_life.h"
40 #include "slave_life.h"
41 #include "package.h"
42 #include "abi.h"
43 #include "io.h"
44
45 int errno;
46
47 #define MAX_ABI         256
48 #define MAX_PKGNAME     512
49
50 static struct {
51         sqlite3 *handle;
52 } s_info = {
53         .handle = NULL,
54 };
55
56 static int load_abi_table(void)
57 {
58         FILE *fp;
59         int ch;
60         int idx = 0;
61         int tag_id = 0;
62         enum {
63                 INIT = 0x0,
64                 GROUP = 0x1,
65                 TAG = 0x02,
66                 VALUE = 0x03,
67                 ERROR = 0x05
68         } state;
69         enum {
70                 PKGNAME = 0x0,
71         };
72         static const char *field[] = {
73                 "package",
74                 NULL,
75         };
76         const char *ptr = NULL;
77
78         char group[MAX_ABI + 1];
79         char pkgname[MAX_PKGNAME + 1];
80
81         fp = fopen("/usr/share/"PACKAGE"/abi.ini", "rt");
82         if (!fp) {
83                 return DBOX_STATUS_ERROR_IO_ERROR;
84         }
85
86         state = INIT;
87         while ((ch = getc(fp)) != EOF && state != ERROR) {
88                 switch (state) {
89                 case INIT:
90                         if (isspace(ch)) {
91                                 continue;
92                         }
93                         if (ch == '[') {
94                                 state = GROUP;
95                                 idx = 0;
96                         } else {
97                                 state = ERROR;
98                         }
99                         break;
100                 case GROUP:
101                         if (ch == ']') {
102                                 if (idx == 0) {
103                                         state = ERROR;
104                                 } else {
105                                         group[idx] = '\0';
106                                         state = TAG;
107                                         idx = 0;
108                                         ptr = NULL;
109                                 }
110                         } else if (idx < MAX_ABI) {
111                                 group[idx++] = ch;
112                         } else {
113                                 ErrPrint("Overflow\n");
114                                 state = ERROR;
115                         }
116                         break;
117                 case TAG:
118                         if (ptr == NULL) {
119                                 if (idx == 0) {
120                                         if (isspace(ch)) {
121                                                 continue;
122                                         }
123
124                                         /* New group started */
125                                         if (ch == '[') {
126                                                 ungetc(ch, fp);
127                                                 state = INIT;
128                                                 continue;
129                                         }
130                                 }
131
132                                 ptr = field[idx];
133                         }
134
135                         if (ptr == NULL) {
136                                 ErrPrint("unknown tag\n");
137                                 state = ERROR;
138                                 continue;
139                         }
140
141                         if (*ptr == '\0' && ch == '=') {
142                                 /* MATCHED */
143                                 state = VALUE;
144                                 tag_id = idx;
145                                 idx = 0;
146                                 ptr = NULL;
147                         } else if (*ptr == ch) {
148                                 ptr++;
149                         } else {
150                                 ungetc(ch, fp);
151                                 ptr--;
152                                 while (ptr >= field[idx]) {
153                                         ungetc(*ptr, fp);
154                                         ptr--;
155                                 }
156                                 ptr = NULL;
157                                 idx++;
158                         }
159                         break;
160                 case VALUE:
161                         switch (tag_id) {
162                         case PKGNAME:
163                                 if (idx == 0) { /* LTRIM */
164                                         if (isspace(ch)) {
165                                                 continue;
166                                         }
167
168                                         pkgname[idx] = ch;
169                                         idx++;
170                                 } else if (isspace(ch)) {
171                                         int ret;
172                                         pkgname[idx] = '\0';
173
174                                         ret = abi_add_entry(group, pkgname);
175                                         if (ret != 0) {
176                                                 ErrPrint("Failed to add %s for %s\n", pkgname, group);
177                                         }
178
179                                         state = TAG;
180                                         idx = 0;
181                                 } else if (idx < MAX_PKGNAME) {
182                                         pkgname[idx] = ch;
183                                         idx++;
184                                 } else {
185                                         ErrPrint("Overflow\n");
186                                         state = ERROR;
187                                 }
188                                 break;
189                         default:
190                                 break;
191                         }
192                         break;
193                 case ERROR:
194                 default:
195                         break;
196                 }
197         }
198
199         if (state == VALUE) {
200                 switch (tag_id) {
201                 case PKGNAME:
202                         if (idx) {
203                                 int ret;
204                                 pkgname[idx] = '\0';
205                                 ret = abi_add_entry(group, pkgname);
206                                 if (ret != 0) {
207                                         ErrPrint("Failed to add %s for %s\n", pkgname, group);
208                                 }
209                         }
210                         break;
211                 default:
212                         break;
213                 }
214         }
215
216         if (fclose(fp) != 0) {
217                 ErrPrint("fclose: %s\n", strerror(errno));
218         }
219         return DBOX_STATUS_ERROR_NONE;
220 }
221
222 static inline int build_client_info(struct pkg_info *info)
223 {
224         static const char *dml = "SELECT auto_launch, gbar_size FROM client WHERE pkgid = ?";
225         sqlite3_stmt *stmt;
226         int width;
227         int height;
228         int ret;
229         const char *tmp;
230
231         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
232         if (ret != SQLITE_OK) {
233                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
234                 return DBOX_STATUS_ERROR_IO_ERROR;
235         }
236
237         ret = sqlite3_bind_text(stmt, 1, package_name(info), -1, SQLITE_TRANSIENT);
238         if (ret != SQLITE_OK) {
239                 ErrPrint("Failed to bind a pkgname %s\n", package_name(info));
240                 sqlite3_finalize(stmt);
241                 return DBOX_STATUS_ERROR_IO_ERROR;
242         }
243
244         if (sqlite3_step(stmt) != SQLITE_ROW) {
245                 ErrPrint("%s has no records (%s)\n", package_name(info), sqlite3_errmsg(s_info.handle));
246                 sqlite3_reset(stmt);
247                 sqlite3_clear_bindings(stmt);
248                 sqlite3_finalize(stmt);
249                 return DBOX_STATUS_ERROR_IO_ERROR;
250         }
251
252         package_set_auto_launch(info, (const char *)sqlite3_column_text(stmt, 0));
253
254         tmp = (const char *)sqlite3_column_text(stmt, 1);
255         if (tmp && strlen(tmp)) {
256                 if (sscanf(tmp, "%dx%d", &width, &height) != 2) {
257                         ErrPrint("Failed to get GBAR width and Height (%s)\n", tmp);
258                 } else {
259                         package_set_gbar_width(info, width);
260                         package_set_gbar_height(info, height);
261                 }
262         }
263
264         sqlite3_reset(stmt);
265         sqlite3_clear_bindings(stmt);
266         sqlite3_finalize(stmt);
267         return DBOX_STATUS_ERROR_NONE;
268 }
269
270 static inline int build_provider_info(struct pkg_info *info)
271 {
272         static const char *dml = "SELECT provider.network, provider.abi, provider.secured, provider.box_type, provider.box_src, provider.box_group, provider.gbar_type, provider.gbar_src, provider.gbar_group, provider.libexec, provider.timeout, provider.period, provider.script, provider.pinup, pkgmap.appid, provider.direct_input, provider.hw_acceleration FROM provider, pkgmap WHERE pkgmap.pkgid = ? AND provider.pkgid = ?";
273         sqlite3_stmt *stmt;
274         int ret;
275         const char *tmp;
276         const char *appid;
277
278         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
279         if (ret != SQLITE_OK) {
280                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
281                 return DBOX_STATUS_ERROR_IO_ERROR;
282         }
283
284         if (sqlite3_bind_text(stmt, 1, package_name(info), -1, SQLITE_TRANSIENT) != SQLITE_OK) {
285                 ErrPrint("Failed to bind a pkgname(%s) - %s\n", package_name(info), sqlite3_errmsg(s_info.handle));
286                 sqlite3_finalize(stmt);
287                 return DBOX_STATUS_ERROR_IO_ERROR;
288         }
289
290         if (sqlite3_bind_text(stmt, 2, package_name(info), -1, SQLITE_TRANSIENT) != SQLITE_OK) {
291                 ErrPrint("Failed to bind a pkgname(%s) - %s\n", package_name(info), sqlite3_errmsg(s_info.handle));
292                 sqlite3_finalize(stmt);
293                 return DBOX_STATUS_ERROR_IO_ERROR;
294         }
295
296         if (sqlite3_step(stmt) != SQLITE_ROW) {
297                 ErrPrint("%s has no record(%s)\n", package_name(info), sqlite3_errmsg(s_info.handle));
298                 sqlite3_reset(stmt);
299                 sqlite3_clear_bindings(stmt);
300                 sqlite3_finalize(stmt);
301                 return DBOX_STATUS_ERROR_IO_ERROR;
302         }
303
304         appid = (const char *)sqlite3_column_text(stmt, 14);
305         if (!appid || !strlen(appid)) {
306                 ErrPrint("Failed to execute the DML for %s\n", package_name(info));
307                 sqlite3_reset(stmt);
308                 sqlite3_clear_bindings(stmt);
309                 sqlite3_finalize(stmt);
310                 return DBOX_STATUS_ERROR_IO_ERROR;
311         }
312
313         package_set_network(info, sqlite3_column_int(stmt, 0));
314         package_set_secured(info, sqlite3_column_int(stmt, 2));
315
316         tmp = (const char *)sqlite3_column_text(stmt, 1);
317         if (tmp && strlen(tmp)) {
318                 package_set_abi(info, tmp);
319         }
320
321         package_set_dbox_type(info, sqlite3_column_int(stmt, 3));
322         tmp = (const char *)sqlite3_column_text(stmt, 4);
323         if (tmp && strlen(tmp)) {
324                 package_set_dbox_path(info, tmp);
325
326                 tmp = (const char *)sqlite3_column_text(stmt, 5);
327                 if (tmp && strlen(tmp)) {
328                         package_set_dbox_group(info, tmp);
329                 }
330         }
331
332         package_set_gbar_type(info, sqlite3_column_int(stmt, 6));
333         tmp = (const char *)sqlite3_column_text(stmt, 7);
334         if (tmp && strlen(tmp)) {
335                 package_set_gbar_path(info, tmp);
336
337                 tmp = (const char *)sqlite3_column_text(stmt, 8);
338                 if (tmp && strlen(tmp)) {
339                         package_set_gbar_group(info, tmp);
340                 }
341         }
342
343         tmp = (const char *)sqlite3_column_text(stmt, 9);
344         if (tmp && strlen(tmp)) {
345                 package_set_libexec(info, tmp);
346         }
347
348         package_set_timeout(info, sqlite3_column_int(stmt, 10));
349
350         tmp = (const char *)sqlite3_column_text(stmt, 11);
351         if (tmp && strlen(tmp)) {
352                 package_set_period(info, atof(tmp));
353         }
354
355         tmp = (const char *)sqlite3_column_text(stmt, 12);
356         if (tmp && strlen(tmp)) {
357                 package_set_script(info, tmp);
358         }
359
360         package_set_pinup(info, sqlite3_column_int(stmt, 13));
361         package_set_direct_input(info, sqlite3_column_int(stmt, 15));
362         package_set_hw_acceleration(info, (const char *)sqlite3_column_text(stmt, 16));
363
364         sqlite3_reset(stmt);
365         sqlite3_clear_bindings(stmt);
366         sqlite3_finalize(stmt);
367         return DBOX_STATUS_ERROR_NONE;
368 }
369
370 static inline int build_box_size_info(struct pkg_info *info)
371 {
372         static const char *dml = "SELECT size_type FROM box_size WHERE pkgid = ?";
373         sqlite3_stmt *stmt;
374         int ret;
375         unsigned int size_type;
376         unsigned int size_list;
377
378         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
379         if (ret != SQLITE_OK) {
380                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
381                 return DBOX_STATUS_ERROR_IO_ERROR;
382         }
383
384         if (sqlite3_bind_text(stmt, 1, package_name(info), -1, SQLITE_TRANSIENT) != SQLITE_OK) {
385                 ErrPrint("Failed to bind a pkgname(%s) - %s\n", package_name(info), sqlite3_errmsg(s_info.handle));
386                 sqlite3_finalize(stmt);
387                 return DBOX_STATUS_ERROR_IO_ERROR;
388         }
389
390         size_list = 0;
391         while (sqlite3_step(stmt) == SQLITE_ROW) {
392                 size_type = sqlite3_column_int(stmt, 0);
393                 size_list |= size_type;
394         }
395
396         package_set_size_list(info, size_list);
397
398         sqlite3_reset(stmt);
399         sqlite3_clear_bindings(stmt);
400         sqlite3_finalize(stmt);
401         return DBOX_STATUS_ERROR_NONE;
402 }
403
404 static inline int load_context_option(struct context_item *item, int id)
405 {
406         static const char *dml = "SELECT key, value FROM option WHERE option_id = ?";
407         sqlite3_stmt *stmt;
408         const char *key;
409         const char *value;
410         int ret;
411
412         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
413         if (ret != SQLITE_OK) {
414                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
415                 return DBOX_STATUS_ERROR_IO_ERROR;
416         }
417
418         ret = sqlite3_bind_int(stmt, 1, id);
419         if (ret != SQLITE_OK) {
420                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
421                 ret = DBOX_STATUS_ERROR_IO_ERROR;
422                 goto out;
423         }
424
425         ret = DBOX_STATUS_ERROR_NOT_EXIST;
426         while (sqlite3_step(stmt) == SQLITE_ROW) {
427                 key = (const char *)sqlite3_column_text(stmt, 0);
428                 if (!key || !strlen(key)) {
429                         ErrPrint("KEY is nil\n");
430                         continue;
431                 }
432
433                 value = (const char *)sqlite3_column_text(stmt, 1);
434                 if (!value || !strlen(value)) {
435                         ErrPrint("VALUE is nil\n");
436                         continue;
437                 }
438
439                 ret = group_add_option(item, key, value);
440                 if (ret < 0) {
441                         break;
442                 }
443         }
444
445 out:
446         sqlite3_reset(stmt);
447         sqlite3_clear_bindings(stmt);
448         sqlite3_finalize(stmt);
449         return ret;
450 }
451
452 static inline int load_context_item(struct context_info *info, int id)
453 {
454         static const char *dml = "SELECT ctx_item, option_id FROM groupmap WHERE id = ?";
455         struct context_item *item;
456         sqlite3_stmt *stmt;
457         const char *ctx_item;
458         int option_id;
459         int ret;
460
461         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
462         if (ret != SQLITE_OK) {
463                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
464                 return DBOX_STATUS_ERROR_IO_ERROR;
465         }
466
467         ret = sqlite3_bind_int(stmt, 1, id);
468         if (ret != SQLITE_OK) {
469                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
470                 ret = DBOX_STATUS_ERROR_IO_ERROR;
471                 goto out;
472         }
473
474         ret = DBOX_STATUS_ERROR_NOT_EXIST;
475         while (sqlite3_step(stmt) == SQLITE_ROW) {
476                 ctx_item = (const char *)sqlite3_column_text(stmt, 0);
477                 option_id = sqlite3_column_int(stmt, 1);
478
479                 item = group_add_context_item(info, ctx_item);
480                 if (!item) {
481                         ErrPrint("Failed to add a new context item\n");
482                         ret = DBOX_STATUS_ERROR_FAULT;
483                         break;
484                 }
485
486                 ret = load_context_option(item, option_id);
487                 if (ret < 0) {
488                         break;
489                 }
490         }
491
492 out:
493         sqlite3_reset(stmt);
494         sqlite3_clear_bindings(stmt);
495         sqlite3_finalize(stmt);
496         return ret;
497 }
498
499 static inline int build_group_info(struct pkg_info *info)
500 {
501         static const char *dml = "SELECT id, cluster, category FROM groupinfo WHERE pkgid = ?";
502         sqlite3_stmt *stmt;
503         int ret;
504         int id;
505         const char *cluster_name;
506         const char *category_name;
507         struct cluster *cluster;
508         struct category *category;
509         struct context_info *ctx_info;
510
511         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
512         if (ret != SQLITE_OK) {
513                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
514                 return DBOX_STATUS_ERROR_IO_ERROR;
515         }
516
517         ret = sqlite3_bind_text(stmt, 1, package_name(info), -1, SQLITE_TRANSIENT);
518         if (ret != SQLITE_OK) {
519                 ErrPrint("Failed to bind a package name(%s)\n", package_name(info));
520                 sqlite3_finalize(stmt);
521                 return DBOX_STATUS_ERROR_IO_ERROR;
522         }
523
524         while (sqlite3_step(stmt) == SQLITE_ROW) {
525                 id = sqlite3_column_int(stmt, 0);
526                 cluster_name = (const char *)sqlite3_column_text(stmt, 1);
527                 if (!cluster_name || !strlen(cluster_name)) {
528                         DbgPrint("Cluster name is not valid\n");
529                         continue;
530                 }
531
532                 category_name = (const char *)sqlite3_column_text(stmt, 2);
533                 if (!category_name || !strlen(category_name)) {
534                         DbgPrint("Category name is not valid\n");
535                         continue;
536                 }
537
538                 cluster = group_find_cluster(cluster_name);
539                 if (!cluster) {
540                         cluster = group_create_cluster(cluster_name);
541                         if (!cluster) {
542                                 ErrPrint("Failed to create a cluster(%s)\n", cluster_name);
543                                 continue;
544                         }
545                 }
546
547                 category = group_find_category(cluster, category_name);
548                 if (!category) {
549                         category = group_create_category(cluster, category_name);
550                         if (!category) {
551                                 ErrPrint("Failed to create a category(%s)\n", category_name);
552                                 continue;
553                         }
554                 }
555
556                 /*!
557                  * \TODO
558                  * Step 1. Get the list of the context item from the DB using 'id'
559                  *         {context_item, option_id}
560                  * Step 2. Get the list of the options from the DB using option_id
561                  *         key, value
562                  */
563                 ctx_info = group_create_context_info(category, package_name(info));
564                 if (ctx_info) {
565                         ret = load_context_item(ctx_info, id);
566                         if (ret < 0) {
567                                 if (ret == (int)DBOX_STATUS_ERROR_NOT_EXIST) {
568                                         DbgPrint("Has no specific context info\n");
569                                 } else {
570                                         DbgPrint("Context info is not valid\n");
571                                         group_destroy_context_info(ctx_info);
572                                         ctx_info = NULL;
573                                 }
574                         }
575
576                         if (ctx_info) {
577                                 package_add_ctx_info(info, ctx_info);
578                         }
579                 }
580         }
581
582         sqlite3_reset(stmt);
583         sqlite3_clear_bindings(stmt);
584         sqlite3_finalize(stmt);
585         return DBOX_STATUS_ERROR_NONE;
586 }
587
588 HAPI int io_is_exists(const char *lbid)
589 {
590         sqlite3_stmt *stmt;
591         int ret;
592
593         if (!s_info.handle) {
594                 ErrPrint("DB is not ready\n");
595                 return DBOX_STATUS_ERROR_IO_ERROR;
596         }
597
598         ret = sqlite3_prepare_v2(s_info.handle, "SELECT COUNT(pkgid) FROM pkgmap WHERE pkgid = ?", -1, &stmt, NULL);
599         if (ret != SQLITE_OK) {
600                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
601                 return DBOX_STATUS_ERROR_IO_ERROR;
602         }
603
604         ret = sqlite3_bind_text(stmt, 1, lbid, -1, SQLITE_TRANSIENT);
605         if (ret != SQLITE_OK) {
606                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
607                 ret = DBOX_STATUS_ERROR_IO_ERROR;
608                 goto out;
609         }
610
611         if (sqlite3_step(stmt) != SQLITE_ROW) {
612                 ErrPrint("%s has no record (%s)\n", lbid, sqlite3_errmsg(s_info.handle));
613                 ret = DBOX_STATUS_ERROR_IO_ERROR;
614                 goto out;
615         }
616
617         ret = sqlite3_column_int(stmt, 0);
618 out:
619         sqlite3_reset(stmt);
620         sqlite3_finalize(stmt);
621         return ret;
622 }
623
624 HAPI char *io_dynamicbox_pkgname(const char *pkgname)
625 {
626         sqlite3_stmt *stmt;
627         char *pkgid;
628         char *tmp;
629         int ret;
630
631         pkgid = NULL;
632
633         if (!s_info.handle) {
634                 ErrPrint("DB is not ready\n");
635                 return NULL;
636         }
637
638         ret = sqlite3_prepare_v2(s_info.handle, "SELECT pkgid FROM pkgmap WHERE (appid = ? AND prime = 1) OR pkgid = ?", -1, &stmt, NULL);
639         if (ret != SQLITE_OK) {
640                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
641                 return NULL;
642         }
643
644         ret = sqlite3_bind_text(stmt, 1, pkgname, -1, SQLITE_TRANSIENT);
645         if (ret != SQLITE_OK) {
646                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
647                 goto out;
648         }
649
650         ret = sqlite3_bind_text(stmt, 2, pkgname, -1, SQLITE_TRANSIENT);
651         if (ret != SQLITE_OK) {
652                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
653                 goto out;
654         }
655
656         if (sqlite3_step(stmt) != SQLITE_ROW) {
657                 ErrPrint("%s has no record (%s)\n", pkgname, sqlite3_errmsg(s_info.handle));
658                 goto out;
659         }
660
661         tmp = (char *)sqlite3_column_text(stmt, 0);
662         if (tmp && strlen(tmp)) {
663                 pkgid = strdup(tmp);
664                 if (!pkgid) {
665                         ErrPrint("Heap: %s\n", strerror(errno));
666                 }
667         }
668
669 out:
670         sqlite3_reset(stmt);
671         sqlite3_finalize(stmt);
672         return pkgid;
673 }
674
675 HAPI int io_crawling_dynamicboxes(int (*cb)(const char *pkgid, const char *lbid, int prime, void *data), void *data)
676 {
677         DIR *dir;
678
679         if (!s_info.handle) {
680                 ErrPrint("DB is not ready\n");
681         } else {
682                 int ret;
683                 sqlite3_stmt *stmt;
684
685                 ret = sqlite3_prepare_v2(s_info.handle, "SELECT appid, pkgid, prime FROM pkgmap", -1, &stmt, NULL);
686                 if (ret != SQLITE_OK) {
687                         ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
688                 } else {
689                         const char *lbid;
690                         const char *pkgid;
691                         int prime;
692
693                         while (sqlite3_step(stmt) == SQLITE_ROW) {
694                                 pkgid = (const char *)sqlite3_column_text(stmt, 0);
695                                 if (!pkgid || !strlen(pkgid)) {
696                                         continue;
697                                 }
698
699                                 lbid = (const char *)sqlite3_column_text(stmt, 1);
700                                 if (!lbid || !strlen(lbid)) {
701                                         continue;
702                                 }
703
704                                 prime = (int)sqlite3_column_int(stmt, 1);
705
706                                 if (cb(pkgid, lbid, prime, data) < 0) {
707                                         sqlite3_reset(stmt);
708                                         sqlite3_finalize(stmt);
709                                         return DBOX_STATUS_ERROR_CANCEL;
710                                 }
711                         }
712
713                         sqlite3_reset(stmt);
714                         sqlite3_finalize(stmt);
715                 }
716         }
717
718         dir = opendir(DYNAMICBOX_CONF_ROOT_PATH);
719         if (!dir) {
720                 ErrPrint("Error: %s\n", strerror(errno));
721         } else {
722                 struct dirent *ent;
723
724                 while ((ent = readdir(dir))) {
725                         if (ent->d_name[0] == '.') {
726                                 continue;
727                         }
728
729                         if (cb(ent->d_name, ent->d_name, -2, data) < 0) {
730                                 if (closedir(dir) < 0) {
731                                         ErrPrint("closedir: %s\n", strerror(errno));
732                                 }
733                                 return DBOX_STATUS_ERROR_CANCEL;
734                         }
735                 }
736
737                 if (closedir(dir) < 0) {
738                         ErrPrint("closedir: %s\n", strerror(errno));
739                 }
740         }
741
742         return DBOX_STATUS_ERROR_NONE;
743 }
744
745 HAPI int io_update_dynamicbox_package(const char *pkgid, int (*cb)(const char *pkgid, const char *lbid, int prime, void *data), void *data)
746 {
747         sqlite3_stmt *stmt;
748         char *lbid;
749         int prime;
750         int ret;
751
752         if (!cb || !pkgid) {
753                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
754         }
755
756         if (!s_info.handle) {
757                 ErrPrint("DB is not ready\n");
758                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
759         }
760
761         ret = sqlite3_prepare_v2(s_info.handle, "SELECT pkgid, prime FROM pkgmap WHERE appid = ?", -1, &stmt, NULL);
762         if (ret != SQLITE_OK) {
763                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
764                 return DBOX_STATUS_ERROR_FAULT;
765         }
766
767         ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT);
768         if (ret != SQLITE_OK) {
769                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
770                 ret = DBOX_STATUS_ERROR_FAULT;
771                 goto out;
772         }
773
774         ret = 0;
775         while (sqlite3_step(stmt) == SQLITE_ROW) {
776                 lbid = (char *)sqlite3_column_text(stmt, 0);
777                 if (!lbid || !strlen(lbid)) {
778                         continue;
779                 }
780
781                 prime = sqlite3_column_int(stmt, 1);
782
783                 if (cb(pkgid, lbid, prime, data) < 0) {
784                         DbgPrint("Callback canceled\n");
785                         break;
786                 }
787
788                 ret++;
789         }
790 out:
791         sqlite3_reset(stmt);
792         sqlite3_finalize(stmt);
793         return ret;
794 }
795
796 HAPI int io_load_package_db(struct pkg_info *info)
797 {
798         int ret;
799
800         if (!s_info.handle) {
801                 ErrPrint("DB is not ready\n");
802                 return DBOX_STATUS_ERROR_IO_ERROR;
803         }
804
805         ret = build_provider_info(info);
806         if (ret < 0) {
807                 return ret;
808         }
809
810         ret = build_client_info(info);
811         if (ret < 0) {
812                 return ret;
813         }
814
815         ret = build_box_size_info(info);
816         if (ret < 0) {
817                 return ret;
818         }
819
820         ret = build_group_info(info);
821         if (ret < 0) {
822                 return ret;
823         }
824
825         return DBOX_STATUS_ERROR_NONE;
826 }
827
828 static inline int db_init(void)
829 {
830         int ret;
831         struct stat stat;
832
833         ret = db_util_open_with_options(DYNAMICBOX_CONF_DBFILE, &s_info.handle, SQLITE_OPEN_READONLY, NULL);
834         if (ret != SQLITE_OK) {
835                 ErrPrint("Failed to open a DB\n");
836                 return DBOX_STATUS_ERROR_IO_ERROR;
837         }
838
839         if (lstat(DYNAMICBOX_CONF_DBFILE, &stat) < 0) {
840                 db_util_close(s_info.handle);
841                 s_info.handle = NULL;
842                 ErrPrint("%s\n", strerror(errno));
843                 return DBOX_STATUS_ERROR_IO_ERROR;
844         }
845
846         if (!S_ISREG(stat.st_mode)) {
847                 ErrPrint("Invalid file\n");
848                 db_util_close(s_info.handle);
849                 s_info.handle = NULL;
850                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
851         }
852
853         if (stat.st_size <= 0) {
854                 DbgPrint("Size is %d (But use this ;)\n", stat.st_size);
855         }
856
857         return DBOX_STATUS_ERROR_NONE;
858 }
859
860 static inline int db_fini(void)
861 {
862         if (!s_info.handle) {
863                 return DBOX_STATUS_ERROR_NONE;
864         }
865
866         db_util_close(s_info.handle);
867         s_info.handle = NULL;
868
869         return DBOX_STATUS_ERROR_NONE;
870 }
871
872 HAPI int io_init(void)
873 {
874         int ret;
875
876         ret = db_init();
877         if (ret < 0) {
878                 DbgPrint("DB initialized: %d\n", ret);
879         }
880
881         ret = load_abi_table();
882         if (ret < 0) {
883                 DbgPrint("ABI table is loaded: %d\n", ret);
884         }
885
886         return DBOX_STATUS_ERROR_NONE;
887 }
888
889 HAPI int io_fini(void)
890 {
891         int ret;
892
893         abi_del_all();
894
895         ret = db_fini();
896         if (ret < 0) {
897                 DbgPrint("DB finalized: %d\n", ret);
898         }
899         return DBOX_STATUS_ERROR_NONE;
900 }
901
902 /* End of a file */