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