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