Minor refactor in pkgmgr_upgrade.c
[platform/core/appfw/pkgmgr-tool.git] / src / pkg_upgrade / pkg_upgrade.c
1 /*
2  * pkg-fota
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #define _GNU_SOURCE
21
22 #include <fcntl.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <dirent.h>
27 #include <unistd.h>
28 #include <sys/smack.h>
29 #include <sys/stat.h>
30 #include <errno.h>
31 #include <iniparser.h>
32 #include <ctype.h>
33 #include <sys/types.h>
34 #include <sys/wait.h>
35 #include <sys/time.h>
36 #include <libxml/xmlreader.h>
37 #include <sqlite3.h>
38 #include <pwd.h>
39
40 #include <package-manager-types.h>
41 #include <package-manager.h>
42 #include <pkgmgr_parser.h>
43 #include <pkgmgr-info.h>
44 #include "include/pkg_upgrade.h"
45
46 #include <tzplatform_config.h>
47
48 #define USR_MANIFEST_DIRECTORY  tzplatform_getenv(TZ_SYS_RO_PACKAGES)
49 #define OPT_USR_MANIFEST_DIRECTORY      tzplatform_getenv(TZ_SYS_RW_PACKAGES)
50 #define RW_PKG_DIRECTORY        tzplatform_getenv(TZ_SYS_RW_APP)
51 #define SKEL_DIRECTORY  tzplatform_mkpath(TZ_SYS_ETC, "skel/apps_rw")
52
53 #define PKGMGR_FOTA_PATH        tzplatform_mkpath(TZ_SYS_GLOBALUSER_DATA, \
54         "pkgmgr/fota")
55 #define PKGID_LIST_FROM_DB_FILE tzplatform_mkpath(TZ_SYS_GLOBALUSER_DATA, \
56         "pkgmgr/fota/pkgid_list_from_db.txt")
57 #define PKGID_LIST_FROM_XML_FILE \
58         tzplatform_mkpath(TZ_SYS_GLOBALUSER_DATA, \
59         "pkgmgr/fota/pkgid_list_from_xml.txt")
60 #define PRELOAD_RW_PKG_LIST \
61         tzplatform_mkpath(TZ_SYS_GLOBALUSER_DATA, \
62         "pkgmgr/fota/.all_preload_rw_list")
63 #define DBPATH tzplatform_mkpath(TZ_SYS_DB, "/.pkgmgr_parser.db")
64 #define JOURNAL_DBPATH tzplatform_mkpath(TZ_SYS_DB, \
65         "/.pkgmgr_parser.db-journal")
66 #define CERT_DBPATH tzplatform_mkpath(TZ_SYS_DB, "/.pkgmgr_cert.db")
67 #define JOURNAL_CERT_DBPATH tzplatform_mkpath(TZ_SYS_DB, \
68         "/.pkgmgr_cert.db-journal")
69 #define OPT_ZIP_FILE                    "/usr/system/RestoreDir/opt.zip"
70 #define ALL_PRELOAD_RW_PKG_LIST "/opt/usr/share/.all_preload_rw_list"
71 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
72 #define APPFW_USER "app_fw"
73
74 struct pkginfo {
75         char *pkgid;
76         char *version;
77         char *type;
78 };
79
80 static char *unzip_path[BUF_SIZE] = {
81         "opt/usr/globalapps",
82         "opt/etc/skel/apps_rw",
83         NULL
84 };
85
86 static void __free_pkginfo(gpointer data)
87 {
88         struct pkginfo *info = (struct pkginfo *)data;
89         free(info->pkgid);
90         free(info->version);
91         free(info->type);
92         free(info);
93 }
94
95 float __get_elapsed_time()
96 {
97         static long start_time = 0;
98         long endtime = 0;
99         struct timeval tv;
100
101         if (start_time == 0) {
102                 gettimeofday(&tv, NULL);
103                 start_time = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
104         }
105
106         gettimeofday(&tv, NULL);
107         endtime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
108
109         return (endtime - start_time)/1000.0;
110 }
111
112 #define _LOG(fmt, arg...) do { \
113         int fd = 0; \
114         FILE *file = NULL; \
115         file = fopen(FOTA_RESULT_FILE, "a"); \
116         if (file == NULL) break; \
117         fprintf(file, "[PKG_FOTA][%5d][%10.3fs]  "fmt"", getpid(), \
118                 __get_elapsed_time(), ##arg); \
119         fflush(file); \
120         fd = fileno(file); \
121         fsync(fd); \
122         fclose(file); \
123         fprintf(stderr, "[PKG_FOTA][%5d][%10.3fs]  "fmt"", getpid(), \
124                 __get_elapsed_time(), ##arg); \
125 } while (0)
126
127 int remove_directory(const char *path)
128 {
129         DIR *dir;
130         struct dirent *entry;
131         size_t path_len = strlen(path);
132         int ret = 0;
133         int iterate_ret;
134         char buf[BUF_SIZE] = {0};
135         size_t len;
136         struct stat statbuf;
137
138         dir = opendir(path);
139         if (!dir)
140                 return -1;
141
142         while (!ret && (entry = readdir(dir))) {
143                 iterate_ret = -1;
144
145                 if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
146                         continue;
147
148                 len = path_len + strlen(entry->d_name) + 2;
149                 snprintf(buf, len, "%s/%s", path, entry->d_name);
150
151                 if (!stat(buf, &statbuf)) {
152                         if (S_ISDIR(statbuf.st_mode))
153                                 iterate_ret = remove_directory(buf);
154                         else
155                                 iterate_ret = unlink(buf);
156                 }
157                 ret = iterate_ret;
158         }
159
160         closedir(dir);
161         if (!ret)
162                 ret = rmdir(path);
163
164         return ret;
165 }
166
167 static void __iter_cb(gpointer key, gpointer value, gpointer user_data)
168 {
169
170         FILE *file;
171         char *pkgid;
172         char *version;
173         char *type;
174         char pkg_info[BUF_SIZE];
175         pkgmgrinfo_pkginfo_h info;
176
177         if (user_data == NULL || key == NULL)
178                 return;
179
180         file = user_data;
181         pkgid = key;
182
183         if (pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &info)) {
184                 _LOGE("failed to get pkginfo of %s\n", pkgid);
185                 return;
186         }
187
188         if (pkgmgrinfo_pkginfo_get_version(info, &version)) {
189                 pkgmgrinfo_pkginfo_destroy_pkginfo(info);
190                 return;
191         }
192
193         if (pkgmgrinfo_pkginfo_get_type(info, &type)) {
194                 pkgmgrinfo_pkginfo_destroy_pkginfo(info);
195                 return;
196         }
197
198         snprintf(pkg_info, BUF_SIZE,
199                         "package=\"%s\"\tversion=\"%s\"\ttype=\"%s\":\n",
200                         pkgid, version, type);
201         fwrite(pkg_info, 1, strlen(pkg_info), file);
202         pkgmgrinfo_pkginfo_destroy_pkginfo(info);
203 }
204
205 static void __make_preload_rw_list(GHashTable *preload_rw_table)
206 {
207         if (preload_rw_table == NULL) {
208                 _LOG("preload_rw_table is null\n");
209                 return;
210         }
211         FILE *file = NULL;
212
213         char buf[BUF_SIZE];
214         char tmp_path[BUF_SIZE];
215         snprintf(tmp_path, BUF_SIZE, "%s.tmp", ALL_PRELOAD_RW_PKG_LIST);
216
217         if (rename(ALL_PRELOAD_RW_PKG_LIST, tmp_path)) {
218                 if (errno != ENOENT)
219                         _LOG("can not backup preload rw pkg list: %d", errno);
220         }
221
222         file = fopen(ALL_PRELOAD_RW_PKG_LIST, "w");
223         if (file == NULL) {
224                 _LOG("can not open [%s]: %s\n", ALL_PRELOAD_RW_PKG_LIST,
225                                 strerror_r(errno, buf, sizeof(buf)));
226                 return;
227         }
228         g_hash_table_foreach(preload_rw_table, __iter_cb, file);
229         fsync(fileno(file));
230         fclose(file);
231         if (remove(tmp_path))
232                 _LOG("cannot remove backup file(%s): %d", tmp_path, errno);
233 }
234
235 static int __is_dir(const char *dirname)
236 {
237         struct stat stFileInfo;
238
239         retvm_if(dirname == NULL, -1, "dirname == NULL\n");
240         retvm_if(stat(dirname, &stFileInfo) < 0, -1,
241                 "stFileInfo is not enough\n");
242
243         if (S_ISDIR(stFileInfo.st_mode))
244                 return 0;
245         return -1;
246 }
247
248 static int __xsystem(const char *argv[])
249 {
250         int status = 0;
251         pid_t pid;
252         pid = fork();
253         switch (pid) {
254         case -1:
255                 perror("fork failed");
256                 return -1;
257         case 0:
258                 /* child */
259                 execvp(argv[0], (char *const *)argv);
260                 _exit(-1);
261         default:
262                 /* parent */
263                 break;
264         }
265         if (waitpid(pid, &status, 0) == -1) {
266                 perror("waitpid failed");
267                 return -1;
268         }
269         if (WIFSIGNALED(status)) {
270                 perror("signal");
271                 return -1;
272         }
273         if (!WIFEXITED(status)) {
274                 /* shouldn't happen */
275                 perror("should not happen");
276                 return -1;
277         }
278         return WEXITSTATUS(status);
279 }
280
281 static int __check_pkgmgr_fota_dir()
282 {
283         int ret = 0;
284
285         if (__is_dir(PKGMGR_FOTA_PATH) < 0) {
286                 const char *mkdir_argv[] =  { "/bin/mkdir",
287                         "-p", PKGMGR_FOTA_PATH, NULL };
288                 ret = __xsystem(mkdir_argv);
289                 retvm_if(ret != 0, -1, "mkdir_argv error [%d]\n", ret);
290         }
291
292         return 0;
293 }
294
295 static int __remove_pkgid_list()
296 {
297         int ret = 0;
298
299         if (access(FOTA_RESULT_FILE, R_OK) == 0) {
300                 ret = remove(FOTA_RESULT_FILE);
301                 err_if(ret < 0, "remove[%s] failed", FOTA_RESULT_FILE);
302         }
303
304         if (access(PKGID_LIST_FROM_DB_FILE, R_OK) == 0) {
305                 ret = remove(PKGID_LIST_FROM_DB_FILE);
306                 err_if(ret < 0, "remove[%s] failed", PKGID_LIST_FROM_DB_FILE);
307         }
308
309         if (access(PKGID_LIST_FROM_XML_FILE, R_OK) == 0) {
310                 ret = remove(PKGID_LIST_FROM_XML_FILE);
311                 err_if(ret < 0, "remove[%s] failed", PKGID_LIST_FROM_XML_FILE);
312         }
313
314         return 0;
315 }
316
317 static int __make_pkgid_list(const char *file_path, char *pkgid,
318                 char *version, char *type, bool is_update)
319 {
320         FILE *fp;
321
322         if (NULL == pkgid)
323                 return 0;
324
325         fp = fopen(file_path, "a+");
326         if (NULL == fp)
327                 return -1;
328
329         fprintf(fp, "%s\"%s\"   %s\"%s\"   %s\"%s\"   %s\"%s\":\n",
330                         TOKEN_PKGID_STR, pkgid,
331                         TOKEN_VERSION_STR, version,
332                         TOKEN_TYPE_STR, type,
333                         TOKEN_UPDATE_STR, (is_update) ? "true" : "false");
334
335         fclose(fp);
336
337         return 0;
338 }
339
340 static int __insert_preload_rw_table(GHashTable *preload_rw_table,
341                 const char *pkgid, const char *version, const char *type)
342 {
343         struct pkginfo *info;
344         char *package;
345
346         info = calloc(1, sizeof(struct pkginfo));
347         if (info == NULL) {
348                 _LOGE("out of memory");
349                 return -1;
350         }
351
352         info->pkgid = strdup(pkgid);
353         if (info->pkgid == NULL) {
354                 _LOGE("out of memory");
355                 __free_pkginfo((struct pkginfo *)info);
356                 return -1;
357         }
358
359         info->version = strdup(version);
360         if (info->version == NULL) {
361                 _LOGE("out of memory");
362                 __free_pkginfo((struct pkginfo *)info);
363                 return -1;
364         }
365
366         info->type = strdup(type);
367         if (info->type == NULL) {
368                 _LOGE("out of memory");
369                 __free_pkginfo((struct pkginfo *)info);
370                 return -1;
371         }
372
373         package = strdup(pkgid);
374         if (package == NULL) {
375                 _LOGE("out of memory");
376                 __free_pkginfo((struct pkginfo *)info);
377                 return -1;
378         }
379
380         g_hash_table_insert(preload_rw_table, package, info);
381         return 0;
382 }
383
384 static int __delete_preload_rw_table(GHashTable *preload_rw_table,
385                 const char *pkgid)
386 {
387         gboolean removed;
388         removed = g_hash_table_remove(preload_rw_table, pkgid);
389         return removed ? 0 : -1;
390 }
391
392 static int __pkgid_list_cb(const pkgmgrinfo_pkginfo_h handle, void *user_data)
393 {
394         int ret = -1;
395         char *pkgid = NULL;
396         char *version = NULL;
397         char *type = NULL;
398         bool is_update = false;
399
400         ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
401         err_if(ret < 0, "pkgmgrinfo_pkginfo_get_pkgid failed");
402
403         ret = pkgmgrinfo_pkginfo_get_version(handle, &version);
404         err_if(ret < 0, "pkgmgrinfo_pkginfo_get_version failed");
405
406         ret = pkgmgrinfo_pkginfo_get_type(handle, &type);
407         err_if(ret < 0, "pkgmgrinfo_pkginfo_get_type failed");
408
409         ret = pkgmgrinfo_pkginfo_is_update(handle, &is_update);
410         err_if(ret < 0, "pkgmgrinfo_pkginfo_is_update failed");
411
412         ret = __make_pkgid_list((char *)user_data, pkgid,
413                         version, type, is_update);
414         return ret;
415 }
416
417 static int __preload_rw_pkgid_list_cb(const pkgmgrinfo_pkginfo_h handle,
418                 void *user_data)
419 {
420         int ret;
421         char *pkgid;
422         char *version;
423         char *type;
424         GHashTable *preload_rw_table = (GHashTable *)user_data;
425
426         ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
427         if (ret < 0) {
428                 _LOGE("pkgmgrinfo_pkginfo_get_pkgid failed\n");
429                 return -1;
430         }
431
432         ret = pkgmgrinfo_pkginfo_get_version(handle, &version);
433         if (ret < 0) {
434                 _LOGE("pkgmgrinfo_pkginfo_get_version failed\n");
435                 return -1;
436         }
437
438         ret = pkgmgrinfo_pkginfo_get_type(handle, &type);
439         if (ret < 0) {
440                 _LOGE("pkgmgrinfo_pkginfo_get_type failed\n");
441                 return -1;
442         }
443
444         ret = __insert_preload_rw_table(preload_rw_table, pkgid, version, type);
445         if (ret < 0) {
446                 _LOGE("__insert_preload_rw_table failed\n");
447                 return -1;
448         }
449
450         return 0;
451 }
452
453 static void __str_trim(char *input)
454 {
455         char *trim_str = input;
456
457         if (input == NULL)
458                 return;
459
460         while (*input != 0) {
461                 if (!isspace(*input)) {
462                         *trim_str = *input;
463                         trim_str++;
464                 }
465                 input++;
466         }
467
468         *trim_str = 0;
469         return;
470 }
471
472 static char *__getvalue(const char *pBuf, const char *pKey, int depth)
473 {
474         const char *p = NULL;
475         const char *pStart = NULL;
476         const char *pEnd = NULL;
477
478         p = strstr(pBuf, pKey);
479         if (p == NULL)
480                 return NULL;
481
482         pStart = p + strlen(pKey) + depth;
483         pEnd = strchr(pStart, SEPERATOR_END);
484         if (pEnd == NULL) {
485                 pEnd = strchr(pStart, SEPERATOR_MID);
486                 if (pEnd == NULL)
487                         return NULL;
488         }
489
490         size_t len = pEnd - pStart;
491         if (len <= 0)
492                 return NULL;
493
494         char *pRes = (char *)malloc(len + 1);
495         if (pRes == NULL) {
496                 _LOG("malloc failed.\n");
497                 return NULL;
498         }
499         strncpy(pRes, pStart, len);
500         pRes[len] = 0;
501
502         return pRes;
503 }
504
505 static int __compare_pkgid(char *file_path, char *fota_pkgid,
506                 char *fota_version, bool *is_updated)
507 {
508         retvm_if(file_path == NULL, -1, "file_path is null.\n");
509         retvm_if(fota_pkgid == NULL, -1, "fota_pkgid is null.\n");
510         retvm_if(fota_version == NULL, -1, "fota_version is null.\n");
511
512         int ret = PKG_IS_NOT_EXIST;
513         FILE *fp = NULL;
514         char buf[BUF_SIZE] = {0};
515         char *pkgid = NULL;
516         char *version = NULL;
517         char *update = NULL;
518         int compare = PMINFO_VERSION_SAME;
519
520         fp = fopen(file_path, "r");
521         retvm_if(fp == NULL, -1, "Fail get : %s\n", file_path);
522
523         while (fgets(buf, BUF_SIZE, fp) != NULL) {
524                 __str_trim(buf);
525
526                 pkgid = __getvalue(buf, TOKEN_PKGID_STR, 1);
527                 if (pkgid == NULL) {
528                         _LOG("pkgid is null\n");
529                         continue;
530                 }
531
532                 version = __getvalue(buf, TOKEN_VERSION_STR, 1);
533                 if (version == NULL) {
534                         FREE_AND_NULL(pkgid);
535                         _LOG("compare_data is null\n");
536                         continue;
537                 }
538
539                 update = __getvalue(buf, TOKEN_UPDATE_STR, 1);
540                 if (update == NULL) {
541                         FREE_AND_NULL(pkgid);
542                         FREE_AND_NULL(version);
543                         _LOG("compare_data is null\n");
544                         continue;
545                 }
546                 if (!strncmp(update, "true", strlen("true")))
547                         *is_updated = true;
548                 else
549                         *is_updated = false;
550
551                 if (strcmp(pkgid, fota_pkgid) == 0) {
552                         ret = pkgmgrinfo_compare_package_version(version,
553                                 fota_version, &compare);
554                         if (compare == PMINFO_VERSION_NEW) {
555                                 _LOG("pkgid = %s, db version = %s, new package"
556                                         " version = %s\n", pkgid, version,
557                                                 fota_version);
558                                 _LOG("pkg is updated, need to upgrade\n");
559
560                                 ret = PKG_IS_UPDATED;
561                                 FREE_AND_NULL(pkgid);
562                                 FREE_AND_NULL(version);
563                                 FREE_AND_NULL(update);
564                                 break;
565                         } else if (compare == PMINFO_VERSION_OLD) {
566                                 ret = PKG_IS_OLD;
567                                 FREE_AND_NULL(pkgid);
568                                 FREE_AND_NULL(version);
569                                 FREE_AND_NULL(update);
570                                 break;
571                         }
572
573                         FREE_AND_NULL(pkgid);
574                         FREE_AND_NULL(version);
575                         FREE_AND_NULL(update);
576                         ret =  PKG_IS_SAME;
577                         break;
578                 }
579
580                 FREE_AND_NULL(pkgid);
581                 FREE_AND_NULL(version);
582                 FREE_AND_NULL(update);
583                 memset(buf, 0x00, BUF_SIZE);
584         }
585
586         if (fp != NULL)
587                 fclose(fp);
588
589         return ret;
590 }
591
592 static bool __check_deleted_pkg(GHashTable *preload_rw_table,
593                 const char *fota_pkgid)
594 {
595         if (g_hash_table_contains(preload_rw_table, fota_pkgid))
596                 return true;
597         return false;
598 }
599
600 char *__manifest_to_package(const char *manifest)
601 {
602         char *package;
603
604         if (manifest == NULL)
605                 return NULL;
606
607         package = strdup(manifest);
608         if (package == NULL)
609                 return NULL;
610
611         if (!strstr(package, ".xml")) {
612                 _LOG("%s is not a manifest file \n", manifest);
613                 free(package);
614                 return NULL;
615         }
616
617         return package;
618 }
619
620 static void __send_args_to_backend(const char *pkgid, const char *pkgtype,
621                 int operation)
622 {
623         int ret = 0;
624
625         long starttime;
626         long endtime;
627         struct timeval tv;
628         gettimeofday(&tv, NULL);
629         starttime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
630         char *query;
631         char backend_cmd[BUF_SIZE];
632         const char *new_pkgtype;
633         const char tpk_pkgtype[] = "tpk";
634
635         const char *preload_rw[] = { backend_cmd, "-y", pkgid,
636                                 "--preload-rw", NULL };
637         const char *install_ro[] = { backend_cmd, "-y", pkgid,
638                                 "--preload", "--partial-rw", NULL };
639         const char *uninstall_ro[] = { backend_cmd, "-d", pkgid,
640                                 "--preload", "--force-remove",
641                                 "--partial-rw", NULL };
642         const char *uninstall_ro_keeprwdata[] = { backend_cmd, "-d", pkgid,
643                                 "--preload", "--force-remove",
644                                 "--keep-rwdata", NULL };
645         const char *uninstall_ro_update[] = { backend_cmd, "-d",
646                                 pkgid, "--keep-rwdata", NULL };
647         const char *db_cmd[] = {"/usr/bin/sqlite3",
648                                 NULL, NULL, NULL};
649
650         if (operation == PKG_NEED_NOTHING)
651                 return;
652
653         if (!strcmp(pkgtype, "rpm"))
654                 new_pkgtype = tpk_pkgtype;
655         else
656                 new_pkgtype = pkgtype;
657
658         snprintf(backend_cmd, sizeof(backend_cmd), "/usr/bin/%s-backend",
659                         new_pkgtype);
660
661         switch (operation) {
662         case PKG_NEED_INSTALL:
663         case PKG_NEED_ROUPDATE:
664                 ret = __xsystem(install_ro);
665                 break;
666         case PKG_NEED_UNINSTALL:
667                 ret = __xsystem(uninstall_ro);
668                 break;
669         case PKG_NEED_UPDATE_TO_RW:
670                 query = sqlite3_mprintf(
671                                 "UPDATE package_info SET " \
672                                 "package_preload='false', " \
673                                 "package_system='false' "\
674                                 "WHERE package=%Q", pkgid);
675                 db_cmd[1] = strdup(DBPATH);
676                 db_cmd[2] = query;
677                 ret = __xsystem(db_cmd);
678                 FREE_AND_NULL(db_cmd[1]);
679                 sqlite3_free(query);
680                 break;
681         case PKG_NEED_RWUNINSTALL:
682         case PKG_NEED_UPDATE_TO_RO:
683                 ret = __xsystem(uninstall_ro_update);
684                 break;
685         case PKG_NEED_RO_DBREMOVE:
686                 query = sqlite3_mprintf(
687                                 "PRAGMA foreign_keys=on; " \
688                                 "DELETE FROM package_info " \
689                                 "WHERE package=%Q", pkgid);
690                 db_cmd[1] = strdup(DBPATH);
691                 db_cmd[2] = query;
692                 ret = __xsystem(db_cmd);
693                 FREE_AND_NULL(db_cmd[1]);
694                 sqlite3_free(query);
695                 break;
696         case PKG_NEED_PRELOADRW_INSTALL:
697                 ret = __xsystem(preload_rw);
698                 break;
699         case PKG_NEED_RO_UNINSTALL_KEEPRWDATA:
700                 ret = __xsystem(uninstall_ro_keeprwdata);
701                 break;
702         }
703
704         gettimeofday(&tv, NULL);
705         endtime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
706
707         _LOG("result[%ld ms, %d] \t Pkgid[%s]  \n",
708                 (endtime - starttime), ret, pkgid);
709 }
710
711 int __child_element(xmlTextReaderPtr reader, int depth)
712 {
713         int ret = xmlTextReaderRead(reader);
714         int cur = xmlTextReaderDepth(reader);
715         while (ret == 1) {
716                 switch (xmlTextReaderNodeType(reader)) {
717                 case XML_READER_TYPE_ELEMENT:
718                         if (cur == depth + 1)
719                                 return 1;
720                         break;
721                 case XML_READER_TYPE_TEXT:
722                         /*text is handled by each function separately*/
723                         if (cur == depth + 1)
724                                 return 0;
725                         break;
726                 case XML_READER_TYPE_END_ELEMENT:
727                         if (cur == depth)
728                                 return 0;
729                         break;
730                 default:
731                         if (cur <= depth)
732                                 return 0;
733                         break;
734                 }
735
736                 ret = xmlTextReaderRead(reader);
737                 cur = xmlTextReaderDepth(reader);
738         }
739         return ret;
740 }
741
742 char *__find_info_from_xml(const char *manifest, const char *find_info)
743 {
744         retvm_if(manifest == NULL, NULL, "manifest is null.\n");
745         retvm_if(find_info == NULL, NULL, "find_info is null.\n");
746
747         const xmlChar *node;
748         xmlTextReaderPtr reader;
749         char *info_val = NULL;
750         xmlChar *tmp = NULL;
751
752         reader = xmlReaderForFile(manifest, NULL, 0);
753
754         if (reader) {
755                 if (__child_element(reader, -1)) {
756                         node = xmlTextReaderConstName(reader);
757                         if (!node) {
758                                 printf("xmlTextReaderConstName value is NULL\n");
759                                 goto end;
760                         }
761
762                         if (!strcmp(ASCII(node), "manifest")) {
763                                 tmp = xmlTextReaderGetAttribute(reader,
764                                         XMLCHAR(find_info));
765                                 if (tmp) {
766                                         FREE_AND_STRDUP(ASCII(tmp), info_val);
767                                         if (info_val == NULL)
768                                                 printf("Malloc Failed\n");
769                                         FREE_AND_NULL(tmp);
770                                 }
771                         } else {
772                                 printf("Manifest Node is not found\n");
773                         }
774                 }
775         } else {
776                 printf("xmlReaderForFile value is NULL\n");
777         }
778
779 end:
780         if (reader)
781                 xmlFreeTextReader(reader);
782
783         return info_val;
784 }
785
786 static int __find_preload_pkgid_from_xml(const char *file_path,
787                 const char *xml_directory)
788 {
789         retvm_if(file_path == NULL, -1, "file_path is NULL.\n");
790         retvm_if(xml_directory == NULL, -1, "xml_directory is NULL.\n");
791
792         int ret = 0;
793         char buf[BUF_SIZE] = {0};
794         DIR *dir;
795         struct dirent *entry = NULL;
796
797         dir = opendir(xml_directory);
798         if (!dir) {
799                 if (strerror_r(errno, buf, sizeof(buf)) == 0)
800                         _LOG("Failed to access the [%s] because %s\n",
801                                 xml_directory, buf);
802                 return -1;
803         }
804
805         while ((entry = readdir(dir)) != NULL) {
806                 char *manifest = NULL;
807                 char *pkgid = NULL;
808                 char *version = NULL;
809                 char *type = NULL;
810
811                 if (entry->d_name[0] == '.') continue;
812
813                 manifest = __manifest_to_package(entry->d_name);
814                 if (!manifest) {
815                         _LOG("Failed to convert file to xml[%s]\n",
816                                 entry->d_name);
817                         continue;
818                 }
819
820                 snprintf(buf, sizeof(buf), "%s/%s", xml_directory, manifest);
821
822                 /*Get the package name from manifest file*/
823                 pkgid = __find_info_from_xml(buf, "package");
824                 if (pkgid == NULL) {
825                         FREE_AND_NULL(manifest);
826                         continue;
827                 }
828
829                 version = __find_info_from_xml(buf, "version");
830                 if (version == NULL)
831                         version = strdup("0.0.1");
832
833                 type = __find_info_from_xml(buf, "type");
834                 if (type == NULL)
835                         type = strdup("tpk");
836
837                 ret = __make_pkgid_list((char *)file_path, pkgid,
838                         version, type, false);
839                 if (ret < 0)
840                         _LOG("Make file Fail : %s => %s, %s\n",
841                                 buf, pkgid, version);
842
843                 FREE_AND_NULL(pkgid);
844                 FREE_AND_NULL(version);
845                 FREE_AND_NULL(manifest);
846                 FREE_AND_NULL(type);
847         }
848
849         closedir(dir);
850
851         return 0;
852 }
853
854 static int __find_preload_pkgid_from_db(const char *file_path)
855 {
856         retvm_if(file_path == NULL, -1, "file_path is NULL.\n");
857
858         int ret = 0;
859         pkgmgrinfo_pkginfo_filter_h handle = NULL;
860
861         ret = pkgmgrinfo_pkginfo_filter_create(&handle);
862         retvm_if(ret != PMINFO_R_OK, -1,
863                 "pkginfo filter handle create failed\n");
864
865         ret = pkgmgrinfo_pkginfo_filter_add_bool(handle,
866                 PMINFO_PKGINFO_PROP_PACKAGE_PRELOAD, 1);
867         tryvm_if(ret < 0, ret = -1, "pkgmgrinfo_pkginfo_filter_add_bool"
868                 "(PMINFO_PKGINFO_PROP_PACKAGE_PRELOAD) failed\n");
869
870         ret = pkgmgrinfo_pkginfo_filter_add_bool(handle,
871                 PMINFO_PKGINFO_PROP_PACKAGE_SYSTEM, 1);
872         tryvm_if(ret < 0, ret = -1, "pkgmgrinfo_pkginfo_filter_add_bool"
873                 "(PMINFO_PKGINFO_PROP_PACKAGE_SYSTEM) failed\n");
874
875         ret = pkgmgrinfo_pkginfo_filter_foreach_pkginfo(handle,
876                 __pkgid_list_cb, (void *)file_path);
877         err_if(ret < 0,
878                 "pkgmgrinfo_pkginfo_filter_foreach_pkginfo() failed\n");
879
880 catch:
881         pkgmgrinfo_pkginfo_filter_destroy(handle);
882         return ret;
883 }
884
885 static int __find_preload_rw_pkgid_from_db(GHashTable *preload_rw_table)
886 {
887         int ret;
888         pkgmgrinfo_pkginfo_filter_h handle;
889
890         ret = pkgmgrinfo_pkginfo_filter_create(&handle);
891         retvm_if(ret != PMINFO_R_OK, -1,
892                         "pkginfo filter handle create failed\n");
893
894         ret = pkgmgrinfo_pkginfo_filter_add_bool(handle,
895                 PMINFO_PKGINFO_PROP_PACKAGE_PRELOAD, 1);
896         tryvm_if(ret != PMINFO_R_OK, ret = -1, "pkgmgrinfo_pkginfo_filter_add_bool"
897                         "(PMINFO_PKGINFO_PROP_PACKAGE_PRELOAD) failed\n");
898
899         ret = pkgmgrinfo_pkginfo_filter_add_bool(handle,
900                 PMINFO_PKGINFO_PROP_PACKAGE_REMOVABLE, 1);
901         tryvm_if(ret != PMINFO_R_OK, ret = -1, "pkgmgrinfo_pkginfo_filter_add_bool"
902                         "(PMINFO_PKGINFO_PROP_PACKAGE_REMOVABLE) failed\n");
903
904         ret = pkgmgrinfo_pkginfo_filter_add_bool(handle,
905                 PMINFO_PKGINFO_PROP_PACKAGE_READONLY, 0);
906         tryvm_if(ret != PMINFO_R_OK, ret = -1, "pkgmgrinfo_pkginfo_filter_add_bool"
907                         "(PMINFO_PKGINFO_PROP_PACKAGE_READONLY) failed\n");
908
909         ret = pkgmgrinfo_pkginfo_filter_add_bool(handle,
910                 PMINFO_PKGINFO_PROP_PACKAGE_SYSTEM, 0);
911         tryvm_if(ret != PMINFO_R_OK, ret = -1, "pkgmgrinfo_pkginfo_filter_add_bool"
912                         "(PMINFO_PKGINFO_PROP_PACKAGE_SYSTEM) failed\n");
913
914         ret = pkgmgrinfo_pkginfo_filter_foreach_pkginfo(handle,
915                 __preload_rw_pkgid_list_cb, (void *)preload_rw_table);
916         err_if(ret != PMINFO_R_OK,
917                         "pkgmgrinfo_pkginfo_filter_foreach_pkginfo() failed\n");
918
919         ret = 0;
920 catch:
921         pkgmgrinfo_pkginfo_filter_destroy(handle);
922         return ret;
923 }
924
925 static int __find_matched_pkgid_from_list(const char *source_file,
926                 const char *target_file)
927 {
928         retvm_if(source_file == NULL, -1, "source_file is NULL.\n");
929         retvm_if(target_file == NULL, -1, "target_file is NULL.\n");
930
931         FILE *fp = NULL;
932         char buf[BUF_SIZE] = {0};
933         char *pkgid = NULL;
934         char *version = NULL;
935         char *pkgtype = NULL;
936
937         int same_pkg_cnt = 0;
938         int update_pkg_cnt = 0;
939         int insert_pkg_cnt = 0;
940         int total_pkg_cnt = 0;
941
942         int compare_result = 0;
943         int operation;
944
945         bool db_update;
946
947         fp = fopen(source_file, "r");
948         retvm_if(fp == NULL, -1, "Fail get : %s\n", source_file);
949
950         _LOG("Searching...... inserted  or  Updated package \n");
951
952         while (fgets(buf, BUF_SIZE, fp) != NULL) {
953                 __str_trim(buf);
954
955                 pkgid = __getvalue(buf, TOKEN_PKGID_STR, 1);
956                 if (pkgid == NULL)
957                         continue;
958
959                 version = __getvalue(buf, TOKEN_VERSION_STR, 1);
960                 if (version == NULL) {
961                         free(pkgid);
962                         continue;
963                 }
964                 pkgtype = __getvalue(buf, TOKEN_TYPE_STR, 1);
965                 if (pkgtype == NULL) {
966                         free(version);
967                         free(pkgid);
968                         continue;
969                 }
970
971                 operation = PKG_NEED_NOTHING;
972                 compare_result = __compare_pkgid((char *)target_file, pkgid,
973                                                 version, &db_update);
974                 if (compare_result == PKG_IS_NOT_EXIST) {
975                         _LOG("pkgid[%s] is installed, Start install\n", pkgid);
976                         operation = PKG_NEED_INSTALL;
977                         insert_pkg_cnt++;
978                 } else if (compare_result == PKG_IS_SAME) {
979                         if (db_update) {
980                                 operation = PKG_NEED_RWUNINSTALL;
981                                 update_pkg_cnt++;
982                         } else {
983                                 operation = PKG_NEED_NOTHING;
984                                 same_pkg_cnt++;
985                         }
986                 } else if (compare_result == PKG_IS_UPDATED) {
987                         if (db_update) {
988                                 operation = PKG_NEED_UPDATE_TO_RO;
989                         } else {
990                                 operation = PKG_NEED_ROUPDATE;
991                         }
992                         update_pkg_cnt++;
993                 }
994
995                 total_pkg_cnt++;
996                 __send_args_to_backend(pkgid, pkgtype, operation);
997
998                 memset(buf, 0x00, BUF_SIZE);
999                 FREE_AND_NULL(pkgid);
1000                 FREE_AND_NULL(version);
1001                 FREE_AND_NULL(pkgtype);
1002         }
1003
1004         _LOG("-------------------------------------------------------\n");
1005         _LOG("[Total pkg=%d, same pkg=%d, updated pkg=%d, "
1006                 "inserted package=%d]\n",
1007                 total_pkg_cnt, same_pkg_cnt, update_pkg_cnt, insert_pkg_cnt);
1008         _LOG("-------------------------------------------------------\n");
1009
1010         if (fp != NULL)
1011                 fclose(fp);
1012
1013         return 0;
1014 }
1015
1016 static bool __find_pkgid_from_rw_list(const char *pkgid)
1017 {
1018         if (pkgid == NULL)
1019                 return false;
1020
1021         bool ret = false;
1022         FILE *fp = NULL;
1023         char buf[BUF_SIZE] = {0};
1024         char *preload_rw_pkgid = NULL;
1025
1026         fp = fopen(PRELOAD_RW_PKG_LIST, "r");
1027         retvm_if(fp == NULL, -1, "Failed to open : %s\n", PRELOAD_RW_PKG_LIST);
1028
1029         while (fgets(buf, BUF_SIZE, fp) != NULL) {
1030                 __str_trim(buf);
1031
1032                 preload_rw_pkgid = __getvalue(buf, TOKEN_PKGID_STR, 1);
1033                 if (preload_rw_pkgid == NULL) {
1034                         _LOG("Failed to get pkgidstring[%s]\n", buf);
1035                         continue;
1036                 }
1037
1038                 if (strcmp(pkgid, preload_rw_pkgid) == 0) {
1039                         _LOG("pkgid[%s] is converted to preload rw pkg\n", pkgid);
1040                         FREE_AND_NULL(preload_rw_pkgid);
1041                         ret = true;
1042                         break;
1043                 }
1044                 FREE_AND_NULL(preload_rw_pkgid);
1045         }
1046
1047         fclose(fp);
1048         return ret;
1049 }
1050
1051 static int __unzip_file_only_to_path(char *dest_path, char *unzip_to)
1052 {
1053         const char *unzip_argv[] = { "/usr/bin/unzip", "-joXqq",
1054                         OPT_ZIP_FILE, dest_path, "-d", unzip_to, NULL };
1055         int ret = __xsystem(unzip_argv);
1056
1057         return ret;
1058 }
1059
1060 static int __unzip_files(char *dest_path)
1061 {
1062         const char *unzip_argv[] = { "/usr/bin/unzip", "-oXqq",
1063                         OPT_ZIP_FILE, dest_path, "-d", "/", NULL };
1064         int ret = __xsystem(unzip_argv);
1065
1066         return ret;
1067 }
1068
1069 static int __install_preload_rw(const char *pkgid, const char *version,
1070                 const char *pkgtype, GHashTable *preload_rw_table)
1071 {
1072         if (pkgid == NULL || version == NULL || pkgtype == NULL)
1073                 return -1;
1074
1075         int index;
1076         int ret;
1077         char buf[BUF_SIZE] = {0};
1078
1079         /* copy modified manifest */
1080         snprintf(buf, BUF_SIZE, "%s/%s.xml",
1081                         (tzplatform_getenv(TZ_SYS_RW_PACKAGES) + 1), pkgid);
1082         ret = __unzip_files(buf);
1083         if (ret != 0) {
1084                 _LOG("Failed to unzip file from backup[%s]\n", buf);
1085                 return ret;
1086         }
1087
1088         /* copy stored signature */
1089         snprintf(buf, BUF_SIZE, "%s/signatures/%s.txt",
1090                         (tzplatform_getenv(TZ_SYS_SHARE) + 1), pkgid);
1091         ret = __unzip_files(buf);
1092         if (ret != 0) {
1093                 _LOG("Failed to unzip file from backup[%s]\n", buf);
1094                 return ret;
1095         }
1096
1097         /* copy RO and RW components */
1098         for (index = 0; index < BUF_SIZE; index++) {
1099                 if (unzip_path[index] == NULL)
1100                         break;
1101
1102                 snprintf(buf, BUF_SIZE, "%s/%s/*", unzip_path[index], pkgid);
1103                 ret = __unzip_files(buf);
1104                 if (ret != 0) {
1105                         _LOG("Failed to unzip file from backup[%s]\n", buf);
1106                         return ret;
1107                 }
1108         }
1109
1110         ret = __insert_preload_rw_table(preload_rw_table, pkgid, version,
1111                         pkgtype);
1112         retvm_if(ret < 0, -1, "__insert_preload_rw_table fail\n");
1113
1114         __send_args_to_backend(pkgid, pkgtype, PKG_NEED_PRELOADRW_INSTALL);
1115         return ret;
1116 }
1117
1118 static void __convert_preload_to_rw(const char *pkgid, const char *version,
1119                 const char *pkgtype, GHashTable *preload_rw_table)
1120 {
1121         if (pkgid == NULL || version == NULL || pkgtype == NULL)
1122                 return;
1123         char buf[BUF_SIZE] = {0};
1124         int ret;
1125
1126         snprintf(buf, BUF_SIZE, "%s/skel/apps_rw/%s",
1127                         tzplatform_getenv(TZ_SYS_ETC), pkgid);
1128
1129         __send_args_to_backend(pkgid, pkgtype, PKG_NEED_RO_UNINSTALL_KEEPRWDATA);
1130         ret = remove_directory(buf);
1131         if (ret != 0)
1132                 _LOG("Failed to remove directory[%s]\n", buf);
1133
1134         ret = __install_preload_rw(pkgid, version, pkgtype, preload_rw_table);
1135         if (ret != 0) {
1136                 _LOG("Failed install preload rw pkg[%s]\n", pkgid);
1137                 return;
1138         }
1139 }
1140
1141 static int __find_deleted_pkgid_from_list(const char *source_file,
1142                 const char *target_file, GHashTable *preload_rw_table)
1143 {
1144         retvm_if(source_file == NULL, -1, "source_file is NULL.\n");
1145         retvm_if(target_file == NULL, -1, "target_file is NULL.\n");
1146
1147         FILE *fp = NULL;
1148         char buf[BUF_SIZE] = {0};
1149         char *pkgid;
1150         char *version;
1151         char *pkgtype = NULL;
1152         char *update = NULL;
1153         bool is_preload_rw_pkg;
1154         bool xml_update;
1155         int deleted_pkg_cnt = 0;
1156         int modified_pkg_cnt = 0;
1157         int total_pkg_cnt = 0;
1158         int compare_result = 0;
1159
1160         fp = fopen(source_file, "r");
1161         retvm_if(fp == NULL, -1, "Fail get : %s\n", source_file);
1162
1163         _LOG("Searching...... deleted package \n");
1164
1165         while (fgets(buf, BUF_SIZE, fp) != NULL) {
1166                 __str_trim(buf);
1167
1168                 pkgid = __getvalue(buf, TOKEN_PKGID_STR, 1);
1169                 version = __getvalue(buf, TOKEN_VERSION_STR, 1);
1170                 pkgtype = __getvalue(buf, TOKEN_TYPE_STR, 1);
1171                 if (pkgid == NULL || version == NULL || pkgtype == NULL) {
1172                         _LOG("Failed to get pkg info from string[%s]\n", buf);
1173                         FREE_AND_NULL(pkgid);
1174                         FREE_AND_NULL(version);
1175                         FREE_AND_NULL(pkgtype);
1176                         continue;
1177                 }
1178
1179                 compare_result = __compare_pkgid((char *)target_file, pkgid,
1180                                                 version, &xml_update);
1181                 if (compare_result == PKG_IS_NOT_EXIST) {
1182                         update = __getvalue(buf, TOKEN_UPDATE_STR, 1);
1183                         if (update == NULL) {
1184                                 FREE_AND_NULL(pkgid);
1185                                 FREE_AND_NULL(version);
1186                                 FREE_AND_NULL(pkgtype);
1187                                 continue;
1188                         }
1189
1190                         is_preload_rw_pkg = __find_pkgid_from_rw_list(pkgid);
1191
1192                         if (!strncmp(update, "false", strlen("false"))) {
1193                                 if (is_preload_rw_pkg) {
1194                                         __convert_preload_to_rw(pkgid, version,
1195                                                         pkgtype,
1196                                                         preload_rw_table);
1197                                         modified_pkg_cnt++;
1198                                 } else {
1199                                         __send_args_to_backend(pkgid, pkgtype,
1200                                                         PKG_NEED_UNINSTALL);
1201                                         deleted_pkg_cnt++;
1202                                 }
1203                         } else {
1204                                 __send_args_to_backend(pkgid, pkgtype,
1205                                                         PKG_NEED_UPDATE_TO_RW);
1206                                 modified_pkg_cnt++;
1207                                 if (is_preload_rw_pkg) {
1208                                         __send_args_to_backend(pkgid, pkgtype,
1209                                                         PKG_NEED_RWUNINSTALL);
1210                                         __install_preload_rw(pkgid, version,
1211                                                         pkgtype,
1212                                                         preload_rw_table);
1213                                 }
1214                         }
1215                 }
1216                 total_pkg_cnt++;
1217
1218                 memset(buf, 0x00, BUF_SIZE);
1219                 FREE_AND_NULL(pkgid);
1220                 FREE_AND_NULL(version);
1221                 FREE_AND_NULL(pkgtype);
1222                 FREE_AND_NULL(update);
1223         }
1224
1225         _LOG("-------------------------------------------------------\n");
1226         _LOG("[Total pkg=%d, deleted package=%d, modified package=%d]\n",
1227                 total_pkg_cnt, deleted_pkg_cnt, modified_pkg_cnt);
1228         _LOG("-------------------------------------------------------\n");
1229
1230         if (fp != NULL)
1231                 fclose(fp);
1232
1233         return 0;
1234
1235 }
1236
1237 static int __get_pkgid_list_from_db_and_xml()
1238 {
1239         _LOG("=======================================================\n");
1240         _LOG("RO preload package fota\n");
1241         _LOG("=======================================================\n");
1242
1243         int ret = 0;
1244         char updated_preload_rw_list[BUF_SIZE];
1245
1246         /*get pkg info on pkgmgr db, it means old version */
1247         ret = __find_preload_pkgid_from_db(PKGID_LIST_FROM_DB_FILE);
1248         retvm_if(ret < 0, -1, "__find_preload_pkgid_from_db fail.\n");
1249
1250         _LOG("Make pkgid list from db success!! \n");
1251
1252         /*get pkg info on xml, it means new version */
1253         ret = __find_preload_pkgid_from_xml(PKGID_LIST_FROM_XML_FILE,
1254                 USR_MANIFEST_DIRECTORY);
1255         retvm_if(ret < 0, -1, "__find_preload_pkgid_from_xml fail.\n");
1256
1257         _LOG("Make pkgid list from xml success!! \n");
1258
1259
1260         /*get preload rw pkg info on xml from opt.zip, it means new version */
1261         snprintf(updated_preload_rw_list, sizeof(updated_preload_rw_list), "%s",
1262                         ALL_PRELOAD_RW_PKG_LIST);
1263         ret = __unzip_file_only_to_path(updated_preload_rw_list + 1,
1264                         (char *)PKGMGR_FOTA_PATH);
1265         if (ret != 0) {
1266                 _LOG("Failed to unzip file from backup[%s]\n",
1267                                 updated_preload_rw_list);
1268                 return ret;
1269         }
1270
1271         _LOG("Make rw pkgid list from xml success!! \n");
1272
1273         return 0;
1274 }
1275
1276 static int __process_ro_fota(GHashTable *preload_rw_table)
1277 {
1278         int ret;
1279         long starttime;
1280         long endtime;
1281         struct timeval tv;
1282
1283         xmlInitParser();
1284
1285         gettimeofday(&tv, NULL);
1286         starttime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
1287
1288         /* find deleted pkgid */
1289         ret = __find_deleted_pkgid_from_list(PKGID_LIST_FROM_DB_FILE,
1290                 PKGID_LIST_FROM_XML_FILE, preload_rw_table);
1291         err_if(ret < 0, "__find_deleted_pkgid_from_list fail.\n");
1292
1293         /* find updated, inserted pkgid */
1294         ret = __find_matched_pkgid_from_list(PKGID_LIST_FROM_XML_FILE,
1295                 PKGID_LIST_FROM_DB_FILE);
1296         err_if(ret < 0, "__find_matched_pkgid_from_list fail.\n");
1297
1298         gettimeofday(&tv, NULL);
1299         endtime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
1300
1301         _LOG("=======================================================\n");
1302         _LOG("End RO process[time : %ld ms]\n", endtime - starttime);
1303         _LOG("=======================================================\n");
1304
1305         xmlCleanupParser();
1306
1307         return 0;
1308 }
1309
1310 static void __remove_pkg_directories(const char *pkgid)
1311 {
1312         int i;
1313         int ret;
1314         char buf[BUF_SIZE];
1315         const char *base_dirs[] = {
1316                 OPT_USR_MANIFEST_DIRECTORY,
1317                 RW_PKG_DIRECTORY,
1318                 SKEL_DIRECTORY,
1319                 NULL
1320         };
1321
1322         for (i = 0; base_dirs[i] != NULL; i++) {
1323                 ret = snprintf(buf, sizeof(buf), "%s/%s", base_dirs[i], pkgid);
1324                 if (ret < 0 || ret > sizeof(buf)) {
1325                         printf("snprintf fail\n");
1326                         continue;
1327                 }
1328                 if (!access(buf, F_OK)) {
1329                         if (remove_directory(buf))
1330                                 _LOGE("failed to remove directory: %s", buf);
1331                 }
1332         }
1333 }
1334
1335 static int __process_rw_fota(GHashTable *preload_rw_table)
1336 {
1337         FILE *fp = NULL;
1338         char buf[BUF_SIZE] = {0};
1339         int ret = -1;
1340         char *pkgid = NULL;
1341         char *list_version = NULL;
1342         char *db_stored_version = NULL;
1343         char *pkgtype = NULL;
1344         char *version = NULL;
1345         pkgmgrinfo_pkginfo_h handle = NULL;
1346         int compare = PMINFO_VERSION_SAME;
1347         long total_time = 0;
1348
1349         long starttime;
1350         long endtime;
1351         struct timeval tv;
1352         bool is_deleted_pkg;
1353
1354         _LOG("=======================================================\n");
1355         _LOG("RW preload package fota\n");
1356         _LOG("=======================================================\n");
1357
1358         fp = fopen(PRELOAD_RW_PKG_LIST, "r");
1359         retvm_if(fp == NULL, -1, "Fail get : %s\n", PRELOAD_RW_PKG_LIST);
1360
1361         while (fgets(buf, BUF_SIZE, fp) != NULL) {
1362                 __str_trim(buf);
1363
1364                 gettimeofday(&tv, NULL);
1365                 starttime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
1366
1367                 pkgid = __getvalue(buf, TOKEN_PKGID_STR, 1);
1368                 if (pkgid == NULL)
1369                         continue;
1370
1371                 ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle);
1372                 if (ret == PMINFO_R_OK) {
1373                         list_version = __getvalue(buf, TOKEN_VERSION_STR, 1);
1374                         if (list_version == NULL) {
1375                                 FREE_AND_NULL(pkgid);
1376                                 continue;
1377                         }
1378                         ret = pkgmgrinfo_pkginfo_get_version(handle, &db_stored_version);
1379                         ret = pkgmgrinfo_compare_package_version(db_stored_version,
1380                                         list_version, &compare);
1381                         if (ret != PMINFO_R_OK) {
1382                                 _LOG("can not compare pkg version[%s]\n", pkgid);
1383                                 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1384                                 handle = NULL;
1385                                 FREE_AND_NULL(pkgid);
1386                                 FREE_AND_NULL(list_version);
1387                                 continue;
1388                         }
1389
1390                         if (compare != PMINFO_VERSION_NEW) {
1391                                 /* package version is not update on FOTA. */
1392                                 _LOG("pkgid[%s] is not updated\n", pkgid);
1393                                 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1394                                 handle = NULL;
1395                                 FREE_AND_NULL(pkgid);
1396                                 FREE_AND_NULL(list_version);
1397                                 continue;
1398                         }
1399
1400                         _LOG("pkgid[%s] is updated, need to upgrade "
1401                                         "from version [%s] to [%s]\n",
1402                                         pkgid, db_stored_version, list_version);
1403                 } else {
1404                         is_deleted_pkg = __check_deleted_pkg(preload_rw_table, pkgid);
1405                         if (is_deleted_pkg) {
1406                                 _LOG("pkgid[%s] is deleted pkg\n", pkgid);
1407                                 __delete_preload_rw_table(preload_rw_table,
1408                                                 pkgid);
1409                                 /* maybe there are pkg directories which are
1410                                  * extracted from opt.zip by FOTA
1411                                  */
1412                                 __remove_pkg_directories(pkgid);
1413                                 FREE_AND_NULL(pkgid);
1414                                 continue;
1415                         }
1416                         _LOG("pkgid[%s] is new\n", pkgid);
1417                 }
1418
1419                 version = __getvalue(buf, TOKEN_VERSION_STR, 1);
1420                 pkgtype = __getvalue(buf, TOKEN_TYPE_STR, 1);
1421                 __install_preload_rw(pkgid, version, pkgtype, preload_rw_table);
1422
1423                 FREE_AND_NULL(pkgid);
1424                 FREE_AND_NULL(pkgtype);
1425                 FREE_AND_NULL(version);
1426
1427                 if (handle)
1428                         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1429
1430                 gettimeofday(&tv, NULL);
1431                 endtime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
1432                 total_time += (int)(endtime - starttime);
1433                 _LOG("finish request [time : %d ms]\n",
1434                         (int)(endtime - starttime));
1435         }
1436         fclose(fp);
1437
1438         return 0;
1439 }
1440
1441 static int __check_tmp_all_preload_rw_pkg_list()
1442 {
1443         char buf[BUF_SIZE];
1444         char tmp_path[BUF_SIZE];
1445         snprintf(tmp_path, BUF_SIZE, "%s.tmp", ALL_PRELOAD_RW_PKG_LIST);
1446         if (access(tmp_path, F_OK) == 0) {
1447                 if (rename(tmp_path, ALL_PRELOAD_RW_PKG_LIST)) {
1448                         _LOG("rename tmp all preload rw pkg list fail : %s\n",
1449                                         strerror_r(errno, buf, sizeof(buf)));
1450                         return -1;
1451                 }
1452         }
1453         return 0;
1454 }
1455
1456 static int __fill_preload_rw_table(GHashTable *preload_rw_table)
1457 {
1458         FILE *fp;
1459         char buf[BUF_SIZE];
1460         char *pkgid;
1461         char *version;
1462         char *type;
1463
1464         fp = fopen(ALL_PRELOAD_RW_PKG_LIST, "r");
1465         retvm_if(fp == NULL, -1, "Fail get : %s\n", ALL_PRELOAD_RW_PKG_LIST);
1466
1467         while (fgets(buf, BUF_SIZE, fp) != NULL) {
1468                 __str_trim(buf);
1469
1470                 pkgid = __getvalue(buf, TOKEN_PKGID_STR, 1);
1471                 if (pkgid == NULL) {
1472                         _LOG("pkgid is null\n");
1473                         continue;
1474                 }
1475
1476                 version = __getvalue(buf, TOKEN_VERSION_STR, 1);
1477                 if (version == NULL) {
1478                         _LOG("version is null\n");
1479                         version = strdup("");
1480                         if (version == NULL) {
1481                                 _LOGE("out of memory\n");
1482                                 FREE_AND_NULL(pkgid);
1483                                 continue;
1484                         }
1485                 }
1486
1487                 type = __getvalue(buf, TOKEN_TYPE_STR, 1);
1488                 if (type == NULL) {
1489                         _LOG("type is null\n");
1490                         type = strdup("");
1491                         if (type == NULL) {
1492                                 _LOGE("out of memory\n");
1493                                 FREE_AND_NULL(version);
1494                                 FREE_AND_NULL(pkgid);
1495                                 continue;
1496                         }
1497                 }
1498
1499                 __insert_preload_rw_table(preload_rw_table, pkgid, version,
1500                                 type);
1501                 FREE_AND_NULL(pkgid);
1502                 FREE_AND_NULL(version);
1503                 FREE_AND_NULL(type);
1504         }
1505         fclose(fp);
1506
1507         return 0;
1508 }
1509
1510 #define DB_LABEL "User::Home"
1511 #define SET_SMACK_LABEL(x)                                                     \
1512 do {                                                                           \
1513         if (smack_setlabel((x), DB_LABEL, SMACK_LABEL_ACCESS))                 \
1514                 _LOGE("failed chsmack -a %s %s", DB_LABEL, x);                 \
1515         else                                                                   \
1516                 _LOG("chsmack -a %s %s", DB_LABEL, x);                         \
1517 } while (0)
1518
1519 static int __set_db_permission(const char *path)
1520 {
1521         int fd;
1522         struct stat sb;
1523         mode_t mode;
1524         uid_t uid;
1525         struct passwd pwd;
1526         struct passwd *result;
1527         char buf[BUF_SIZE];
1528         int ret;
1529
1530         ret = getpwnam_r(APPFW_USER, &pwd, buf, sizeof(buf), &result);
1531         if (result == NULL) {
1532                 if (ret == 0)
1533                         _LOGE("no such user: %s", APPFW_USER);
1534                 else
1535                         _LOGE("getpwnam_r failed: %d", errno);
1536                 return -1;
1537         }
1538         uid = pwd.pw_uid;
1539
1540         ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
1541         if (result == NULL) {
1542                 if (ret == 0)
1543                         _LOGE("no such user: %d", uid);
1544                 else
1545                         _LOGE("getpwuid_r failed: %d", errno);
1546                 return -1;
1547         }
1548         fd = open(path, O_RDONLY);
1549         if (fd == -1) {
1550                 _LOGE("open %s failed: %d", path, errno);
1551                 return -1;
1552         }
1553         ret = fstat(fd, &sb);
1554         if (ret == -1) {
1555                 _LOGE("stat %s failed: %d", path, errno);
1556                 close(fd);
1557         return -1;
1558         }
1559         if (S_ISLNK(sb.st_mode)) {
1560                 _LOGE("%s is symlink!", path);
1561                 close(fd);
1562                 return -1;
1563         }
1564         ret = fchown(fd, uid, pwd.pw_gid);
1565         if (ret == -1) {
1566                 _LOGE("fchown %s failed: %d", path, errno);
1567                 close(fd);
1568                 return -1;
1569         }
1570
1571         mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
1572         if (strstr(path, CERT_DBPATH))
1573                 mode |= S_IWOTH;
1574         ret = fchmod(fd, mode);
1575         if (ret == -1) {
1576                 _LOGE("fchmod %s failed: %d", path, errno);
1577                 close(fd);
1578                 return -1;
1579         }
1580         fsync(fd);
1581         close(fd);
1582         SET_SMACK_LABEL(path);
1583
1584         return 0;
1585 }
1586
1587 static int __check_and_restore_backup(const char *origin_path) {
1588         char backup_path[BUF_SIZE];
1589         char buf[BUF_SIZE];
1590         snprintf(backup_path, BUF_SIZE, "%s.bck", origin_path);
1591
1592         if (access(backup_path, F_OK))
1593                 return 0;
1594
1595         if (access(origin_path, F_OK) == 0) {
1596                 if (remove(origin_path)) {
1597                         _LOG("cannot remove path(%s) : %s\n", origin_path,
1598                                         strerror_r(errno, buf, sizeof(buf)));
1599                         return -1;
1600                 }
1601         }
1602
1603         if (rename(backup_path, origin_path)) {
1604                 _LOG("fail to rename %s to %s : %s\n", backup_path, origin_path,
1605                                 strerror_r(errno, buf, sizeof(buf)));
1606                 return -1;
1607         }
1608
1609         return 0;
1610 }
1611
1612 static int __check_and_restore_backup_dbs() {
1613         if (__check_and_restore_backup(DBPATH))
1614                 return -1;
1615
1616         if (__check_and_restore_backup(JOURNAL_DBPATH))
1617                 return -1;
1618
1619         if (__check_and_restore_backup(CERT_DBPATH))
1620                 return -1;
1621
1622         if (__check_and_restore_backup(JOURNAL_CERT_DBPATH))
1623                 return -1;
1624
1625         return 0;
1626 }
1627
1628 static int __backup_file(const char *src_path, const char *dest_path)
1629 {
1630         int ret = 0;
1631         int rc;
1632         FILE *src = NULL;
1633         FILE *dest = NULL;
1634         char temp_buf[8192] = {'\0', };
1635         size_t size_of_char = sizeof(char);
1636         size_t size_of_temp_buf = sizeof(temp_buf);
1637
1638         retvm_if(src_path == NULL || dest_path == NULL,
1639                         -1, "Invalid parameters");
1640
1641         retvm_if(access(src_path, F_OK) != 0, -1,
1642                         "File(%s) is not exist", src_path);
1643
1644         retvm_if(access(dest_path, F_OK) == 0, -1,
1645                         "File(%s) is already exist", dest_path);
1646
1647         retvm_if(rename(src_path, dest_path) != 0, -1,
1648                         "Fail to move file %s to %s", src_path, dest_path);
1649
1650         src = fopen(dest_path, "r");
1651         tryvm_if(src == NULL, ret = -1, "Failed to open : %s\n", dest_path);
1652
1653         dest = fopen(src_path, "w");
1654         tryvm_if(dest == NULL, ret = -1, "Failed to open : %s\n", src_path);
1655
1656         while (!feof(src)) {
1657                 rc = fread(temp_buf, size_of_char, size_of_temp_buf, src);
1658                 fwrite(temp_buf, size_of_char, rc, dest);
1659         }
1660
1661         fsync(fileno(dest));
1662
1663 catch:
1664         if (src)
1665                 fclose(src);
1666
1667         if (dest)
1668                 fclose(dest);
1669
1670         return ret;
1671 }
1672
1673 static int __backup_db(const char *src_path, const char *dest_path) {
1674         if (__backup_file(src_path, dest_path) != 0)
1675                 return -1;
1676
1677         if (__set_db_permission(src_path) != 0)
1678                 return -1;
1679
1680         return 0;
1681 }
1682
1683 static int __make_backup_dbs() {
1684         int ret = 0;
1685         char parser_db_bck[BUF_SIZE];
1686         char parser_db_journal_bck[BUF_SIZE];
1687         char cert_db_bck[BUF_SIZE];
1688         char cert_db_journal_bck[BUF_SIZE];
1689
1690         snprintf(parser_db_bck, BUF_SIZE, "%s.bck", DBPATH);
1691         snprintf(parser_db_journal_bck, BUF_SIZE, "%s.bck", JOURNAL_DBPATH);
1692         snprintf(cert_db_bck, BUF_SIZE, "%s.bck", CERT_DBPATH);
1693         snprintf(cert_db_journal_bck, BUF_SIZE, "%s.bck", JOURNAL_CERT_DBPATH);
1694
1695         tryvm_if(__backup_db(DBPATH, parser_db_bck) == -1,
1696                         ret = -1, "Fail to backup [%s] to [%s]\n",
1697                         DBPATH, parser_db_bck);
1698
1699         tryvm_if(__backup_db(JOURNAL_DBPATH, parser_db_journal_bck) == -1,
1700                         ret = -1, "Fail to backup [%s] to [%s]\n",
1701                         JOURNAL_DBPATH, parser_db_journal_bck);
1702
1703         tryvm_if(__backup_db(CERT_DBPATH, cert_db_bck) == -1,
1704                         ret = -1, "Fail to backup [%s] to [%s]\n",
1705                         CERT_DBPATH, cert_db_bck);
1706
1707         tryvm_if(__backup_db(JOURNAL_CERT_DBPATH, cert_db_journal_bck) == -1,
1708                         ret = -1, "Fail to backup [%s] to [%s]\n",
1709                         JOURNAL_CERT_DBPATH, cert_db_journal_bck);
1710
1711         return 0;
1712
1713 catch:
1714         remove(parser_db_bck);
1715         remove(parser_db_journal_bck);
1716         remove(cert_db_bck);
1717         remove(cert_db_journal_bck);
1718
1719         return ret;
1720 }
1721
1722 static void __remove_backup_path(const char *origin_path) {
1723         char backup_path[BUF_SIZE];
1724
1725         snprintf(backup_path, BUF_SIZE, "%s.bck", origin_path);
1726
1727         if (remove(backup_path))
1728                 _LOG("cannot remove backup file(%s): %d", backup_path, errno);
1729 }
1730
1731 static void __remove_backup_dbs() {
1732         __remove_backup_path(DBPATH);
1733         __remove_backup_path(JOURNAL_DBPATH);
1734         __remove_backup_path(CERT_DBPATH);
1735         __remove_backup_path(JOURNAL_CERT_DBPATH);
1736 }
1737
1738 int main(int argc, char *argv[])
1739 {
1740         GHashTable *preload_rw_table;
1741         int ret = 0;
1742
1743         ret = __check_and_restore_backup_dbs();
1744         retvm_if(ret < 0, -1, "__check_and_restore_backup_dbs is failed.\n");
1745
1746         ret = __make_backup_dbs();
1747         retvm_if(ret < 0, -1, "__make_backup_dbs is failed.\n");
1748
1749         /* check pkgmgr-fota dir, if it is not, then exit */
1750         ret = __check_pkgmgr_fota_dir();
1751         retvm_if(ret < 0, -1, "__check_pkgmgr_fota_dir is failed.\n");
1752
1753         /* clean pkgid list file */
1754         ret = __remove_pkgid_list();
1755         err_if(ret < 0, "remove[%s] failed\n", FOTA_RESULT_FILE);
1756
1757         /* get pkgid from orginal pkgmgr db */
1758         ret = __get_pkgid_list_from_db_and_xml();
1759         retvm_if(ret < 0, -1, "__get_pkgid_list_from_db_and_xml is failed.\n");
1760
1761         //__get_pkginfo_from_opt();
1762
1763         ret = __check_tmp_all_preload_rw_pkg_list();
1764         retvm_if(ret < 0, -1,
1765                         "__check_tmp_all_preload_rw_pkg_list is failed.\n");
1766
1767         preload_rw_table = g_hash_table_new_full(
1768                                 g_str_hash, g_str_equal, free, __free_pkginfo);
1769         if (__fill_preload_rw_table(preload_rw_table) < 0) {
1770                 ret = __find_preload_rw_pkgid_from_db(preload_rw_table);
1771                 retvm_if(ret < 0, -1, "__find_preload_rw_pkgid_from_db is failed\n");
1772         }
1773
1774         if (argc == 1) {
1775                 ret = __process_ro_fota(preload_rw_table);
1776                 if (ret < 0) {
1777                         g_hash_table_destroy(preload_rw_table);
1778                         _LOGE("__process_ro_fota is failed.\n");
1779                         return EXIT_FAILURE;
1780                 }
1781                 ret = __process_rw_fota(preload_rw_table);
1782                 if (ret < 0) {
1783                         g_hash_table_destroy(preload_rw_table);
1784                         _LOGE("__process_rw_fota is failed.\n");
1785                         return EXIT_FAILURE;
1786                 }
1787         } else {
1788                 if (strcmp(argv[1], "-rof") == 0) {
1789                         ret = __process_ro_fota(preload_rw_table);
1790                         if (ret < 0) {
1791                                 g_hash_table_destroy(preload_rw_table);
1792                                 _LOGE("__process_ro_fota is failed.\n");
1793                                 return EXIT_FAILURE;
1794                         }
1795                 } else if (strcmp(argv[1], "-rwf") == 0) {
1796                         ret = __process_rw_fota(preload_rw_table);
1797                         if (ret < 0) {
1798                                 g_hash_table_destroy(preload_rw_table);
1799                                 _LOGE("__process_rw_fota is failed.\n");
1800                                 return EXIT_FAILURE;
1801                         }
1802                 } else {
1803                         fprintf(stderr, "not supported operand\n");
1804                 }
1805         }
1806         __make_preload_rw_list(preload_rw_table);
1807         g_hash_table_destroy(preload_rw_table);
1808         __remove_backup_dbs();
1809
1810         return EXIT_SUCCESS;
1811 }