Release version 0.7.22
[platform/core/appfw/app2sd.git] / test / src / test_app2ext.c
1 /*
2  * test_app2ext
3  *
4  * Copyright (c) 2016 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 #include <stdio.h>
21 #include <assert.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <malloc.h>
25 #include <string.h>
26 #include <assert.h>
27 #include <errno.h>
28 #include <sys/wait.h>
29 #include <sys/types.h>
30 #include <getopt.h>
31 #include <unzip.h>
32 #include <storage-internal.h>
33 #include <tzplatform_config.h>
34
35 #include "app2ext_interface.h"
36
37 #define SUCCESS 0
38 #define FAIL 1
39 #define CMD_LEN 256
40 #define TEST_PKGNAME "org.example.basicuiapplication"
41 #define TEST_PKGNAME_PATH "/tmp/org.example.basicuiapplication-1.0.0-arm.tpk"
42 #define OWNER_ROOT 0
43 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
44
45 static app2ext_handle *handle = NULL;
46
47 static const char pkg_ro_content_rpm[3][5] = { "bin", "res", "lib" };
48
49 #define COUNT_OF_ERROR_LIST APP2EXT_ERROR_ENUM_MAX
50 static const char error_list[COUNT_OF_ERROR_LIST][100] = {
51         "SUCCESS",
52         "APP2EXT_ERROR_UNKNOWN",
53         "APP2EXT_ERROR_INVALID_ARGUMENTS",
54         "APP2EXT_ERROR_MOVE",
55         "APP2EXT_ERROR_PRE_UNINSTALL",
56         "APP2EXT_ERROR_MMC_STATUS",
57         "APP2EXT_ERROR_DB_INITIALIZE",
58         "APP2EXT_ERROR_SQLITE_REGISTRY",
59         "APP2EXT_ERROR_PASSWD_GENERATION",
60         "APP2EXT_ERROR_MMC_INFORMATION",
61         "APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY",
62         "APP2EXT_ERROR_DELETE_DIRECTORY",
63         "APP2EXT_ERROR_CREATE_SYMLINK",
64         "APP2EXT_ERROR_CREATE_DIRECTORY",
65         "APP2EXT_ERROR_DELETE_LINK_FILE",
66         "APP2EXT_ERROR_PKG_EXISTS",
67         "APP2EXT_ERROR_ACCESS_FILE",
68         "APP2EXT_ERROR_OPEN_DIR",
69         "APP2EXT_ERROR_ALREADY_FILE_PRESENT",
70         "APP2EXT_ERROR_FILE_ABSENT",
71         "APP2EXT_ERROR_STRCMP_FAILED",
72         "APP2EXT_ERROR_INVALID_PACKAGE",
73         "APP2EXT_ERROR_CREATE_DIR_ENTRY",
74         "APP2EXT_ERROR_COPY_DIRECTORY",
75         "APP2EXT_ERROR_INVALID_CASE",
76         "APP2EXT_ERROR_SYMLINK_ALREADY_EXISTS",
77         "APP2EXT_ERROR_APPEND_HASH_TO_FILE",
78         "APP2EXT_ERROR_CREATE_DEVICE",
79         "APP2EXT_ERROR_DO_LOSETUP",
80         "APP2EXT_ERROR_CREATE_FS",
81         "APP2EXT_ERROR_MOUNT_PATH",
82         "APP2EXT_ERROR_CLEANUP",
83         "APP2EXT_ERROR_MOUNT",
84         "APP2EXT_ERROR_REMOUNT",
85         "APP2EXT_ERROR_PIPE_CREATION",
86         "APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE",
87         "APP2EXT_ERROR_VCONF_REGISTRY",
88         "APP2EXT_ERROR_FIND_ASSOCIATED_DEVICE_NODE",
89         "APP2EXT_ERROR_UNMOUNT",
90         "APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE",
91         "APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE",
92         "APP2EXT_ERROR_ALREADY_MOUNTED",
93         "APP2EXT_ERROR_PLUGIN_INIT_FAILED",
94         "APP2EXT_ERROR_PLUGIN_DEINIT_FAILED",
95         "APP2EXT_ERROR_DBUS_FAILED",
96         "APP2EXT_ERROR_MEMORY_ALLOC_FAILED",
97         "APP2EXT_ERROR_OPERATION_NOT_PERMITTED",
98         "APP2EXT_ERROR_SAME_LOOPBACK_DEVICE_EXISTS",
99         "APP2EXT_ERROR_PKGMGR_ERROR",
100         "APP2EXT_ERROR_NOENTRY",
101         "APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE",
102         "APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE",
103         "APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE",
104         "APP2EXT_ERROR_FIND_ASSOCIATED_DMCRYPT_DEVICE_NODE",
105         "APP2EXT_ERROR_DMCRYPT_DEVICE_UNAVAILABLE",
106 };
107
108 static void usage(void)
109 {
110         printf("\n");
111         printf("*************************************************\n");
112         printf("App2sd test usage:\n");
113         printf("Pre-condition: /tmp/org.example.basicuiapplication-1.0.0-arm.tpk\n");
114         printf("All tests assume the target uid as default user.\n");
115         printf("\n");
116         printf("<INSTALL>\n");
117         printf("1.#test_app2ext --pre-install\n");
118         printf("2.#pkgcmd -it tpk {pkg-path}\n");
119         printf("3.#test_app2ext --post-install\n");
120         printf("------------------------------------------------\n");
121         printf("\n");
122         printf("<UPGRADE>\n");
123         printf("1.#test_app2ext --pre-upgrade\n");
124         printf("2.#pkgcmd -it tpk {pkg-path}\n");
125         printf("3.#test_app2ext --post-upgrade\n");
126         printf("------------------------------------------------\n");
127         printf("\n");
128         printf("<INSTALL>\n");
129         printf("1.#test_app2ext --pre-uninstall\n");
130         printf("2.#pkgcmd -un {pkg-id}\n");
131         printf("3.#test_app2ext --post-uninstall\n");
132         printf("------------------------------------------------\n");
133         printf("\n");
134         printf("<MOVE PKG TEST>\n");
135         printf("#test_app2ext --move-to-ext\n");
136         printf("#test_app2ext --move-to-int\n");
137         printf("------------------------------------------------\n");
138         printf("\n");
139         printf("<ENABLE(mount)/DISABLE(umount) TEST W/ Installed PKG>\n");
140         printf("#test_app2ext --enable\n");
141         printf("#test_app2ext --disable\n");
142         printf("#test_app2ext --enable-full\n");
143         printf("#test_app2ext --disable-full\n");
144         printf("------------------------------------------------\n");
145         printf("\n");
146         printf("<MIGRATION TRIGGER TEST>\n");
147         printf("Pre-condition: install test package and copy legacy image to app2sd.\n");
148         printf("#test_app2ext --migrate-all\n");
149         printf("------------------------------------------------\n");
150         printf("**************************************************\n");
151         printf("\n");
152 }
153
154 #define OPTVAL_PRE_INSTALL              1000
155 #define OPTVAL_POST_INSTALL             1001
156 #define OPTVAL_PRE_UNINSTALL            1002
157 #define OPTVAL_POST_UNINSTALL           1003
158 #define OPTVAL_PRE_UPGRADE              1004
159 #define OPTVAL_POST_UPGRADE             1005
160 #define OPTVAL_MOVE_TO_EXTERNAL         1006
161 #define OPTVAL_MOVE_TO_INTERNAL         1007
162 #define OPTVAL_ENABLE_APP               1008
163 #define OPTVAL_DISABLE_APP              1009
164 #define OPTVAL_ENABLE_FULL              1010
165 #define OPTVAL_DISABLE_FULL             1011
166 #define OPTVAL_MIGRATE_ALL              1012
167 #define OPTVAL_USAGE                    1013
168
169 /* Supported options */
170 const struct option long_opts[] = {
171         { "pre-install", 0, NULL, OPTVAL_PRE_INSTALL },
172         { "post-install", 0, NULL, OPTVAL_POST_INSTALL },
173         { "pre-uninstall", 0, NULL, OPTVAL_PRE_UNINSTALL },
174         { "post-uninstall", 0, NULL, OPTVAL_POST_UNINSTALL },
175         { "pre-upgrade", 0, NULL, OPTVAL_PRE_UPGRADE },
176         { "post-upgrade", 0, NULL, OPTVAL_POST_UPGRADE },
177         { "move-to-ext", 0, NULL, OPTVAL_MOVE_TO_EXTERNAL },
178         { "move-to-int", 0, NULL, OPTVAL_MOVE_TO_INTERNAL },
179         { "enable", 0, NULL, OPTVAL_ENABLE_APP },
180         { "disable", 0, NULL, OPTVAL_DISABLE_APP },
181         { "enable-full", 0, NULL, OPTVAL_ENABLE_FULL },
182         { "disable-full", 0, NULL, OPTVAL_DISABLE_FULL },
183         { "migrate-all", 0, NULL, OPTVAL_MIGRATE_ALL },
184         { "help", 0, NULL, OPTVAL_USAGE },
185         { "usage", 0, NULL, OPTVAL_USAGE },
186         { 0, 0, 0, 0 }  /* sentinel */
187 };
188
189 void clear_dir_list(GList *dir_list)
190 {
191         GList *list = NULL;
192         app2ext_dir_details *dir_detail = NULL;
193
194         if (dir_list) {
195                 list = g_list_first(dir_list);
196                 while (list) {
197                         dir_detail = (app2ext_dir_details *)list->data;
198                         if (dir_detail && dir_detail->name)
199                                 free(dir_detail->name);
200
201                         list = g_list_next(list);
202                 }
203                 g_list_free(dir_list);
204         }
205 }
206
207 GList *populate_dir_details()
208 {
209         GList *dir_list = NULL;
210         GList *list = NULL;
211         app2ext_dir_details *dir_detail = NULL;
212         int i;
213
214         for (i = 0; i < 3; i++) {
215                 dir_detail = (app2ext_dir_details *)calloc(1, sizeof(app2ext_dir_details));
216                 if (dir_detail == NULL) {
217                         printf("memory allocation failed\n");
218                         goto FINISH_OFF;
219                 }
220
221                 dir_detail->name = (char *)calloc(1, sizeof(char) * (strlen(pkg_ro_content_rpm[i]) + 2));
222                 if (dir_detail->name == NULL) {
223                         printf("memory allocation failed\n");
224                         free(dir_detail);
225                         goto FINISH_OFF;
226                 }
227                 snprintf(dir_detail->name, (strlen(pkg_ro_content_rpm[i]) + 1), "%s", pkg_ro_content_rpm[i]);
228                 dir_detail->type = APP2EXT_DIR_RO;
229                 dir_list = g_list_append(dir_list, dir_detail);
230         }
231
232         if (dir_list) {
233                 list = g_list_first(dir_list);
234                 while (list) {
235                         dir_detail = (app2ext_dir_details *)list->data;
236                         list = g_list_next(list);
237                 }
238         }
239
240         return dir_list;
241
242 FINISH_OFF:
243
244         clear_dir_list(dir_list);
245
246         return NULL;
247 }
248
249 static int get_unzip_size(const char *item, unsigned long long *size)
250 {
251         int ret = 0;
252         unzFile uzf = NULL;
253         char *filename = NULL;
254         unz_file_info fileInfo = { 0 };
255
256         if (!item || !size) {
257                 printf("get size : invalid argument\n");
258                 return -1;
259         }
260         uzf = unzOpen64(item);
261         if (uzf == NULL) {
262                 printf("get size : failed to open item : [%s]\n", item);
263                 *size = 0;
264                 return -1;
265         } else {
266                 ret = unzGoToFirstFile(uzf);
267                 if (ret != UNZ_OK) {
268                         printf("get size : error get first zip file\n");
269                         unzClose(uzf);
270                         *size = 0;
271                         return -1;
272                 } else {
273                         do {
274                                 ret = unzOpenCurrentFile(uzf);
275                                 if (ret != UNZ_OK) {
276                                         printf("get size : error unzOpenCurrentFile\n");
277                                         unzClose(uzf);
278                                         *size = 0;
279                                         return -1;
280                                 }
281
282                                 filename = (char *)calloc(1, 4096);
283                                 ret = unzGetCurrentFileInfo(uzf, &fileInfo, filename, (4096 - 1), NULL, 0, NULL, 0);
284                                 *size = (unsigned long long)fileInfo.uncompressed_size + *size;
285                                 if (ret != UNZ_OK) {
286                                         printf("get size : error get current file info\n");
287                                         unzCloseCurrentFile(uzf);
288                                         *size = 0;
289                                         free(filename);
290                                         filename = NULL;
291                                         break;
292                                 }
293
294                                 free(filename);
295                                 filename = NULL;
296                         } while (unzGoToNextFile(uzf) == UNZ_OK);
297                 }
298         }
299         unzClose(uzf);
300
301         return 0;
302 }
303
304 static void print_error_code(const char *func_name, int ret)
305 {
306         if (ret < 0 || ret > COUNT_OF_ERROR_LIST - 1)
307                 printf("%s failed : unknown error(%d)\n", func_name, ret);
308         else
309                 printf("%s return(%s)\n", func_name, error_list[ret]);
310 }
311
312 static int pre_app_install()
313 {
314         GList *dir_list = NULL;
315         int ret = -1;
316         unsigned long long size_byte = 0;
317         int size_mega = 0;
318
319         printf("pre_app_install for [%s]\n", TEST_PKGNAME_PATH);
320
321         dir_list = populate_dir_details();
322         if (dir_list == NULL) {
323                 printf("error in populating the directory list\n");
324                 return -1;
325         }
326
327         /* size : in MB */
328         ret = get_unzip_size(TEST_PKGNAME_PATH, &size_byte);
329         if (ret < 0 || size_byte == 0)
330                 printf("wrong pkg size, ret(%d), size_byte(%llu)\n", ret, size_byte);
331
332         size_mega = size_byte / (1024 * 1024) + 1;
333         printf("get pkg size : (%d)MB\n", size_mega);
334
335         ret = handle->interface.client_pre_install(TEST_PKGNAME,
336                 dir_list, size_mega);
337         print_error_code(__func__, ret);
338
339         clear_dir_list(dir_list);
340
341         return ret;
342 }
343
344 static int post_app_install()
345 {
346         int ret = -1;
347
348         ret = handle->interface.client_post_install(TEST_PKGNAME,
349                 APP2EXT_STATUS_SUCCESS);
350         print_error_code(__func__, ret);
351
352         return ret;
353 }
354
355 static int app_enable()
356 {
357         int ret = -1;
358
359         ret = handle->interface.client_enable(TEST_PKGNAME);
360         print_error_code(__func__, ret);
361
362         return ret;
363 }
364
365 static int app_disable()
366 {
367         int ret = -1;
368
369         ret = handle->interface.client_disable(TEST_PKGNAME);
370         print_error_code(__func__, ret);
371
372         return ret;
373 }
374
375 static int fullpkg_enable()
376 {
377         int ret = -1;
378
379         ret = handle->interface.client_enable_full_pkg();
380         print_error_code(__func__, ret);
381
382         return ret;
383 }
384
385 static int fullpkg_disable()
386 {
387         int ret = -1;
388
389         ret = handle->interface.client_disable_full_pkg();
390         print_error_code(__func__, ret);
391
392         return ret;
393 }
394
395 static int migrate_all()
396 {
397         int ret = -1;
398
399         ret = handle->interface.client_migrate_legacy_all();
400         print_error_code(__func__, ret);
401
402         return ret;
403 }
404
405 static int pre_app_uninstall()
406 {
407         int ret = -1;
408
409         printf("pre_app_uninstall for [%s]\n", TEST_PKGNAME);
410
411         ret = handle->interface.client_pre_uninstall(TEST_PKGNAME);
412         print_error_code(__func__, ret);
413
414         return ret;
415 }
416
417 static int post_app_uninstall()
418 {
419         int ret = -1;
420
421         ret = handle->interface.client_post_uninstall(TEST_PKGNAME);
422         print_error_code(__func__, ret);
423
424         return ret;
425 }
426
427 static int pre_app_upgrade()
428 {
429         GList *dir_list = NULL;
430         int ret = -1;
431         unsigned long long size_byte = 0;
432         int size_mega = 0;
433
434         printf("pre_app_upgrade for [%s]\n", TEST_PKGNAME);
435
436         dir_list = populate_dir_details();
437         if (dir_list == NULL) {
438                 printf("Error in populating the directory list\n");
439                 return -1;
440         }
441
442         /* size : in MB */
443         ret = get_unzip_size(TEST_PKGNAME_PATH, &size_byte);
444         if (ret < 0 || size_byte == 0)
445                 printf("wrong pkg size, ret(%d), size_byte(%llu)\n", ret, size_byte);
446
447         size_mega = size_byte / (1024 * 1024) + 1;
448         printf("get pkg size : (%d)MB\n", size_mega);
449
450         ret = handle->interface.client_pre_upgrade(TEST_PKGNAME, dir_list,
451                 size_mega);
452         print_error_code(__func__, ret);
453
454         clear_dir_list(dir_list);
455
456         return ret;
457 }
458
459 static int post_app_upgrade()
460 {
461         int ret = -1;
462
463         ret = handle->interface.client_post_upgrade(TEST_PKGNAME,
464                 APP2EXT_STATUS_SUCCESS);
465         print_error_code(__func__, ret);
466
467         return ret;
468 }
469
470 static int app_move_to_external()
471 {
472         GList *dir_list = NULL;
473         int ret = -1;
474
475         printf("app_move_to_external  %s\n", TEST_PKGNAME);
476
477         dir_list = populate_dir_details();
478         if (dir_list == NULL) {
479                 printf("Error in populating the directory list\n");
480                 return -1;
481         }
482
483         printf("pkg %s will be moved to sd card\n", TEST_PKGNAME);
484         ret = handle->interface.client_pre_move(TEST_PKGNAME,
485                 dir_list, APP2EXT_MOVE_TO_EXT);
486         print_error_code(__func__, ret);
487         ret = handle->interface.client_post_move(TEST_PKGNAME,
488                 APP2EXT_MOVE_TO_EXT);
489         print_error_code(__func__, ret);
490
491         clear_dir_list(dir_list);
492
493         return ret;
494 }
495
496 static int app_move_to_internal()
497 {
498         GList *dir_list = NULL;
499         int ret = -1;
500
501         printf("app_move_to_internal  %s\n", TEST_PKGNAME);
502
503         dir_list = populate_dir_details();
504         if (dir_list == NULL) {
505                 printf("Error in populating the directory list\n");
506                 return -1;
507         }
508
509         printf("pkg %s will be moved to internal memory\n", TEST_PKGNAME);
510         ret = handle->interface.client_pre_move(TEST_PKGNAME,
511                 dir_list, APP2EXT_MOVE_TO_PHONE);
512         print_error_code(__func__, ret);
513         ret = handle->interface.client_post_move(TEST_PKGNAME,
514                 APP2EXT_MOVE_TO_PHONE);
515         print_error_code(__func__, ret);
516
517         clear_dir_list(dir_list);
518
519         return ret;
520 }
521
522 int main(int argc, char **argv)
523 {
524         int ret = 0;
525         int opt_idx = 0;
526         int c;
527         int storage_id = 0;
528         char *sd_mount_path = NULL;
529         uid_t uid = getuid();
530
531         /* check user */
532         if (uid != OWNER_ROOT) {
533                 printf("only root user allowed\n");
534                 return 0;
535         }
536
537         /* check sdcard info */
538         ret = storage_get_primary_sdcard(&storage_id, &sd_mount_path);
539         if (ret != STORAGE_ERROR_NONE) {
540                 printf("failed to get primary sdcard (%d)\n", ret);
541                 if (sd_mount_path)
542                         free(sd_mount_path);
543                 return -1;
544         }
545         if (sd_mount_path) {
546                 printf("primary sdcard: id(%d), mount_path(%s)\n",
547                 storage_id, sd_mount_path);
548                 free(sd_mount_path);
549         } else {
550                 printf("there is no primary sdcard\n");
551         }
552
553         handle = app2ext_init(APP2EXT_SD_CARD);
554         if (handle == NULL) {
555                 ret = APP2EXT_ERROR_PLUGIN_INIT_FAILED;
556                 printf("app2ext_init failed (%s)\n", error_list[ret]);
557                 return -1;
558         }
559
560         /* Parse argv */
561         optind = 1;  /* Initialize optind to clear prev. index */
562         c = getopt_long(argc, argv, "", long_opts, &opt_idx);
563         if (-1 == c) {
564                 usage();
565                 app2ext_deinit(handle);
566                 return 0;  /* Parse is end */
567         }
568         switch (c) {
569         case OPTVAL_PRE_INSTALL:
570                 pre_app_install();
571                 break;
572         case OPTVAL_POST_INSTALL:
573                 post_app_install();
574                 break;
575         case OPTVAL_PRE_UNINSTALL:
576                 pre_app_uninstall();
577                 break;
578         case OPTVAL_POST_UNINSTALL:
579                 post_app_uninstall();
580                 break;
581         case OPTVAL_PRE_UPGRADE:
582                 pre_app_upgrade();
583                 break;
584         case OPTVAL_POST_UPGRADE:
585                 post_app_upgrade();
586                 break;
587         case OPTVAL_MOVE_TO_EXTERNAL:
588                 app_move_to_external();
589                 break;
590         case OPTVAL_MOVE_TO_INTERNAL:
591                 app_move_to_internal();
592                 break;
593         case OPTVAL_ENABLE_APP:
594                 app_enable();
595                 break;
596         case OPTVAL_DISABLE_APP:
597                 app_disable();
598                 break;
599         case OPTVAL_ENABLE_FULL:
600                 fullpkg_enable();
601                 break;
602         case OPTVAL_DISABLE_FULL:
603                 fullpkg_disable();
604                 break;
605         case OPTVAL_MIGRATE_ALL:
606                 migrate_all();
607                 break;
608         case OPTVAL_USAGE:
609         default:
610                 usage();
611                 break;
612         }
613
614         app2ext_deinit(handle);
615
616         return 0;
617 }