Refactor app2sd disable logic
[platform/core/appfw/app2sd.git] / plugin / app2sd / server / app2sd_interface.c
1 /*
2  * app2ext
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Garima Shrivastava<garima.s@samsung.com>
7  *      Jyotsna Dhumale <jyotsna.a@samsung.com>
8  *      Venkatesha Sarpangala <sarpangala.v@samsung.com>
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */
23
24 #include <pkgmgr-info.h>
25 #include <package-manager.h>
26 #include <aul.h>
27
28 #include "app2sd_internals.h"
29
30 static int __app2sd_create_app2sd_directories(uid_t uid, char *mmc_path)
31 {
32         int ret = 0;
33         char app2sd_path[FILENAME_MAX] = { 0, };
34         mode_t mode = DIR_PERMS;
35
36         snprintf(app2sd_path, FILENAME_MAX - 1, "%s/%s",
37                         mmc_path, EXTIMG_DIR);
38         ret = mkdir(app2sd_path, mode);
39         if (ret) {
40                 if (errno != EEXIST) {
41                         _E("create directory failed," \
42                                 " error no is (%d)", errno);
43                         return APP2EXT_ERROR_CREATE_DIRECTORY;
44                 }
45         }
46
47         return APP2EXT_SUCCESS;
48 }
49
50 static int __app2sd_finalize_device_setup(const char *pkgid,
51         const char *loopback_device, const char *application_path,
52         uid_t uid)
53 {
54         char *device_node = NULL;
55         int ret = APP2EXT_SUCCESS;
56
57 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
58         device_node =
59                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
60         if (!device_node) {
61                 _E("failed to find device node");
62                 return APP2EXT_ERROR_FIND_ASSOCIATED_DMCRYPT_DEVICE_NODE;
63         }
64 #else
65         device_node = _app2sd_find_associated_device_node(loopback_device);
66         if (NULL == device_node) {
67                 _E("failed to find device node");
68                 return APP2EXT_ERROR_FIND_ASSOCIATED_DEVICE_NODE;
69         }
70 #endif
71
72         ret = _app2sd_unmount_app_content(application_path);
73         if (ret) {
74                 if (device_node) {
75                         free(device_node);
76                         device_node = NULL;
77                 }
78                 _E("unable to unmount the app content (%d)", ret);
79                 return APP2EXT_ERROR_UNMOUNT;
80         }
81
82 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
83         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
84         if (ret) {
85                 if (device_node) {
86                         free(device_node);
87                         device_node = NULL;
88                 }
89                 _E("close dmcrypt device error(%d)", ret);
90                 return ret;
91         }
92 #else
93         ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
94         if (ret) {
95                 if (device_node) {
96                         free(device_node);
97                         device_node = NULL;
98                 }
99                 _E("unable to detach the loopback encryption setup" \
100                         " for the application");
101                 return APP2EXT_ERROR_UNMOUNT;
102         }
103 #endif
104
105         if (device_node) {
106                 free(device_node);
107                 device_node = NULL;
108         }
109
110         return ret;
111 }
112
113 int app2sd_usr_pre_app_install(const char *pkgid, GList *dir_list, int size, uid_t uid)
114 {
115         int ret = 0;
116         int free_mmc_mem = 0;
117         char *sdpath = NULL;
118         char *device_node = NULL;
119 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
120         char *devi = NULL;
121         char *result = NULL;
122 #endif
123         char mmc_path[FILENAME_MAX] = { 0, };
124         char application_path[FILENAME_MAX] = { 0, };
125         char loopback_device[FILENAME_MAX] = { 0, };
126         char *encoded_id = NULL;
127         int reqd_disk_size = size + ceil(size * 0.2);
128
129         /* validate the function parameter recieved */
130         if (pkgid == NULL || dir_list == NULL || size <= 0) {
131                 _E("invalid function arguments");
132                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
133         }
134
135         /* check whether MMC is present or not */
136         ret = _app2sd_check_mmc_status(&sdpath);
137         if (ret) {
138                 _E("MMC not present OR Not ready (%d)", ret);
139                 return APP2EXT_ERROR_MMC_STATUS;
140         }
141         snprintf(mmc_path, FILENAME_MAX - 1, "%s", sdpath);
142         free(sdpath);
143         sync();
144
145         /* find available free memory in the MMC card */
146         ret = _app2sd_get_available_free_memory(mmc_path, &free_mmc_mem);
147         if (ret) {
148                 _E("unable to get available free memory in MMC (%d)", ret);
149                 return APP2EXT_ERROR_MMC_STATUS;
150         }
151         _D("size details for application installation:" \
152                 " size=(%d)MB, reqd_disk_size=(%d)MB, free_mmc_size=(%d)MB",
153                 size, reqd_disk_size, free_mmc_mem);
154
155         /* if avaialalbe free memory in MMC is less than required size + 5MB,
156          * return error
157          */
158         if ((reqd_disk_size + PKG_BUF_SIZE + MEM_BUF_SIZE) > free_mmc_mem) {
159                 _E("insufficient memory in MMC for"
160                         " application installation (%d)", ret);
161                 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
162         }
163
164         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
165         if (encoded_id == NULL)
166                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
167
168         if (_is_global(uid)) {
169                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
170                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
171                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
172                         mmc_path, EXTIMG_DIR, encoded_id);
173         } else {
174                 tzplatform_set_user(uid);
175                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
176                         tzplatform_getenv(TZ_USER_APP), pkgid);
177                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
178                         mmc_path, EXTIMG_DIR, encoded_id);
179                 tzplatform_reset_user();
180         }
181         free(encoded_id);
182
183         ret = __app2sd_create_app2sd_directories(uid, mmc_path);
184         if (ret) {
185                 _E("failed to create app2sd dirs");
186                 return ret;
187         }
188
189         /* create a loopback device */
190         ret = _app2sd_create_loopback_device(pkgid, loopback_device,
191                 (reqd_disk_size + PKG_BUF_SIZE));
192
193 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
194         ret = _app2sd_dmcrypt_setup_device(pkgid, loopback_device, false, uid);
195         if (ret) {
196                 _E("dmcrypt setup device error");
197                 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
198         }
199
200         ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
201                 false, uid, &device_node);
202         if (ret) {
203                 _E("dmcrypt open device error");
204                 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
205         }
206 #else
207         /* perform loopback encryption setup */
208         device_node = _app2sd_do_loopback_encryption_setup(pkgid,
209                 loopback_device, uid);
210         if (!device_node) {
211                 _E("loopback encryption setup failed");
212                 _app2sd_delete_loopback_device(loopback_device);
213                 return APP2EXT_ERROR_DO_LOSETUP;
214         }
215
216         /* check whether loopback device is associated
217          * with device node or not
218          */
219         devi = _app2sd_find_associated_device_node(loopback_device);
220         if (devi == NULL) {
221                 _E("finding associated device node failed");
222                 ret = APP2EXT_ERROR_DO_LOSETUP;
223                 goto FINISH_OFF;
224         }
225 #endif
226
227         /* format the loopback file system */
228         ret = _app2sd_create_file_system(device_node);
229         if (ret) {
230                 _E("creating FS failed failed");
231                 ret = APP2EXT_ERROR_CREATE_FS;
232                 goto FINISH_OFF;
233         }
234
235         /* mount the loopback encrypted pseudo device on application
236          * installation path as with Read Write permission
237          */
238         ret = _app2sd_mount_app_content(application_path, pkgid,
239                 device_node, MOUNT_TYPE_RW, dir_list,
240                 APP2SD_PRE_INSTALL, uid);
241         if (ret) {
242                 _E("mounting dev path to app install path failed");
243                 ret = APP2EXT_ERROR_MOUNT_PATH;
244                 goto FINISH_OFF;
245         }
246
247         /* Success */
248         ret = APP2EXT_SUCCESS;
249         goto END;
250
251 FINISH_OFF:
252         if (device_node) {
253 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
254         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
255         if (ret)
256                 _E("close dmcrypt device error(%d)", ret);
257         _app2sd_delete_loopback_device(loopback_device);
258 #else
259                 result = _app2sd_detach_loop_device(device_node);
260                 if (result) {
261                         free(result);
262                         result = NULL;
263                 }
264                 _app2sd_delete_loopback_device(loopback_device);
265 #endif
266         }
267
268 END:
269         if (device_node) {
270                 free(device_node);
271                 device_node = NULL;
272         }
273
274 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
275         if (devi) {
276                 free(devi);
277                 devi = NULL;
278         }
279 #endif
280
281         sync();
282         return ret;
283 }
284
285 int app2sd_usr_post_app_install(const char *pkgid,
286                 app2ext_status install_status, uid_t uid)
287 {
288         char *sdpath = NULL;
289         char mmc_path[FILENAME_MAX] = { 0, };
290         char application_path[FILENAME_MAX] = { 0, };
291         char application_mmc_path[FILENAME_MAX] = { 0, };
292         char loopback_device[FILENAME_MAX] = { 0, };
293         char *encoded_id = NULL;
294         int ret = APP2EXT_SUCCESS;
295         int pkgmgr_ret = 0;
296
297         /* validate the function parameter recieved */
298         if (pkgid == NULL || install_status < APP2EXT_STATUS_FAILED
299                 || install_status > APP2EXT_STATUS_SUCCESS) {
300                 _E("invalid func parameters");
301                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
302         }
303
304         /* check whether MMC is present or not */
305         ret = _app2sd_check_mmc_status(&sdpath);
306         if (ret) {
307                 _E("MMC not present OR Not ready (%d)", ret);
308                 return APP2EXT_ERROR_MMC_STATUS;
309         }
310         snprintf(mmc_path, FILENAME_MAX - 1, "%s", sdpath);
311         free(sdpath);
312         sync();
313
314         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
315         if (encoded_id == NULL)
316                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
317
318         if (_is_global(uid)) {
319                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
320                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
321                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
322                         mmc_path, EXTIMG_DIR, encoded_id);
323         } else {
324                 tzplatform_set_user(uid);
325                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
326                         tzplatform_getenv(TZ_USER_APP), pkgid);
327                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
328                         mmc_path, EXTIMG_DIR, encoded_id);
329                 tzplatform_reset_user();
330         }
331         free(encoded_id);
332
333         ret = __app2sd_finalize_device_setup(pkgid, loopback_device,
334                 application_path, uid);
335         if (ret) {
336                 _E("failed to finalize device setup");
337                 return ret;
338         }
339
340         /* take appropriate action based on
341          * installation status of application package
342          */
343         if (install_status == APP2EXT_STATUS_FAILED) {
344                 /* delete the loopback device from the SD card */
345                 ret = _app2sd_delete_loopback_device(loopback_device);
346                 if (ret) {
347                         _E("unable to delete the loopback device from the SD Card");
348                         return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
349                 }
350                 ret = _app2sd_remove_info_from_db(pkgid, uid);
351                 if (ret)
352                         _E("unable to delete info");
353
354                 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
355                         application_path);
356                 ret = _app2sd_delete_directory(application_mmc_path);
357                 if (ret)
358                         _E("unable to delete the directory (%s)", application_path);
359         } else {
360                 /* if the status is success, then update installed storage
361                  * to pkgmgr_parser db
362                  */
363                 pkgmgr_ret = pkgmgrinfo_pkginfo_set_usr_installed_storage(pkgid,
364                         INSTALL_EXTERNAL, loopback_device, uid);
365                 if (pkgmgr_ret < 0) {
366                         _E("fail to update installed location " \
367                                 "to db[%s, %d] of uid(%d), pkgmgr ret(%d)",
368                                 pkgid, INSTALL_EXTERNAL, uid, pkgmgr_ret);
369                         return APP2EXT_ERROR_PKGMGR_ERROR;
370                 }
371         }
372
373         sync();
374         return ret;
375 }
376
377 int app2sd_usr_on_demand_setup_init(const char *pkgid, uid_t uid)
378 {
379         int ret = APP2EXT_SUCCESS;
380         char mmc_path[FILENAME_MAX] = { 0, };
381         char application_path[FILENAME_MAX] = { 0, };
382         char loopback_device[FILENAME_MAX] = { 0, };
383         char *sdpath = NULL;
384         char *encoded_id = NULL;
385         char *device_node = NULL;
386 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
387         char *result = NULL;
388 #endif
389         FILE *fp = NULL;
390
391         /* validate the function parameter recieved */
392         if (pkgid == NULL) {
393                 _E("invalid function arguments to app launch setup");
394                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
395         }
396
397         /* check whether MMC is present or not */
398         ret = _app2sd_check_mmc_status(&sdpath);
399         if (ret) {
400                 _E("MMC not present OR Not ready (%d)", ret);
401                 return APP2EXT_ERROR_MMC_STATUS;
402         }
403         snprintf(mmc_path, FILENAME_MAX - 1, "%s", sdpath);
404         free(sdpath);
405
406         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
407         if (encoded_id == NULL)
408                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
409
410         /* check app entry is there in sd card or not. */
411         if (_is_global(uid)) {
412                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
413                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
414                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
415                         mmc_path, EXTIMG_DIR, encoded_id);
416         } else {
417                 tzplatform_set_user(uid);
418                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
419                         tzplatform_getenv(TZ_USER_APP), pkgid);
420                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
421                         mmc_path, EXTIMG_DIR, encoded_id);
422                 tzplatform_reset_user();
423         }
424         free(encoded_id);
425
426         fp = fopen(loopback_device, "r+");
427         if (fp == NULL) {
428                 _E("app entry is not present in SD Card, (%s), errno(%d)",
429                         loopback_device, errno);
430                 return APP2EXT_ERROR_INVALID_PACKAGE;
431         }
432         fclose(fp);
433
434 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
435         device_node =
436                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
437         if (device_node) {
438                 _E("device_node(%s_%d) already associated", pkgid, uid);
439                 return APP2EXT_ERROR_ALREADY_MOUNTED;
440         }
441
442         ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
443                 false, uid, &device_node);
444         if (ret) {
445                 _E("dmcrypt open device error(%d)", ret);
446                 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
447         }
448 #else
449         result = (char *)_app2sd_find_associated_device(loopback_device);
450         /* process the string */
451         if ((result != NULL) && strstr(result, "/dev") != NULL) {
452                 _E("already associated");
453                 free(result);
454                 result = NULL;
455                 return APP2EXT_ERROR_ALREADY_MOUNTED;
456         }
457
458         /* do loopback setup */
459         device_node = _app2sd_do_loopback_encryption_setup(pkgid,
460                 loopback_device, uid);
461         if (device_node == NULL) {
462                 _E("loopback encryption setup failed");
463                 return APP2EXT_ERROR_DO_LOSETUP;
464         }
465 #endif
466
467         /* do mounting */
468         ret = _app2sd_mount_app_content(application_path, pkgid,
469                 device_node, MOUNT_TYPE_RD, NULL, APP2SD_APP_LAUNCH, uid);
470         if (ret) {
471                 _E("mount failed");
472                 if (device_node) {
473                         free(device_node);
474                         device_node = NULL;
475                 }
476                 return APP2EXT_ERROR_MOUNT_PATH;
477         }
478
479         if (device_node) {
480                 free(device_node);
481                 device_node = NULL;
482         }
483
484         return ret;
485 }
486
487 static int _app2sd_application_handler(const pkgmgrinfo_appinfo_h handle, void *data)
488 {
489         int ret = 0;
490         int pid = 0;
491         char *appid = NULL;
492         uid_t uid = *(uid_t *)data;
493
494         ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
495         if (ret < 0) {
496                 _E("failed to get appid");
497                 return APP2EXT_ERROR_PKGMGR_ERROR;
498         }
499
500         _D("appid(%s), uid(%d)", appid, uid);
501
502         ret = aul_app_is_running_for_uid(appid, uid);
503         if (ret == 0)
504                 return APP2EXT_SUCCESS;
505
506         pid = aul_app_get_pid_for_uid(appid, uid);
507         if (pid < 0) {
508                 _E("failed to get pid");
509                 return APP2EXT_ERROR_KILLAPP_ERROR;
510         }
511
512         ret = aul_terminate_pid_sync_without_restart_for_uid(pid, uid);
513         if (ret != AUL_R_OK) {
514                 _E("failed to kill app");
515                 return APP2EXT_ERROR_KILLAPP_ERROR;
516         }
517
518         return APP2EXT_SUCCESS;
519 }
520
521 static int _app2sd_kill_running_app(const char *pkgid, uid_t uid)
522 {
523         int ret = 0;
524         pkgmgrinfo_pkginfo_h handle;
525
526         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &handle);
527         if (ret < 0) {
528                 _E("failed to get pkginfo");
529                 return APP2EXT_ERROR_PKGMGR_ERROR;
530         }
531
532         ret = pkgmgrinfo_appinfo_get_usr_list(handle,
533                 PMINFO_ALL_APP, _app2sd_application_handler, &uid, uid);
534         if (ret < 0) {
535                 _E("failed to get appinfo");
536                 return APP2EXT_ERROR_PKGMGR_ERROR;
537         }
538
539         ret = pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
540         if (ret < 0) {
541                 _E("failed to destroy pkginfo");
542                 return APP2EXT_ERROR_PKGMGR_ERROR;
543         }
544
545         return APP2EXT_SUCCESS;
546 }
547
548 int app2sd_usr_on_demand_setup_exit(const char *pkgid, uid_t uid)
549 {
550         int ret = APP2EXT_SUCCESS;
551         char application_path[FILENAME_MAX] = { 0, };
552         char loopback_device[FILENAME_MAX] = { 0, };
553 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
554         char mmc_path[FILENAME_MAX] = { 0, };
555         char *sdpath = NULL;
556         char *encoded_id = NULL;
557 #endif
558
559         /* validate the function parameter recieved */
560         if (pkgid == NULL) {
561                 _E("invalid function arguments to app launch setup");
562                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
563         }
564
565         _app2sd_kill_running_app(pkgid, uid);
566
567 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
568         if (_is_global(uid)) {
569                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
570                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
571         } else {
572                 tzplatform_set_user(uid);
573                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
574                         tzplatform_getenv(TZ_USER_APP), pkgid);
575                 tzplatform_reset_user();
576         }
577 #else
578         /* check whether MMC is present or not */
579         ret = _app2sd_check_mmc_status(&sdpath);
580         if (ret)
581                 _W("MMC not present OR Not ready (%d)", ret);
582
583         snprintf(mmc_path, FILENAME_MAX - 1, "%s", sdpath);
584         free(sdpath);
585
586         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
587         if (encoded_id == NULL)
588                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
589
590         if (_is_global(uid)) {
591                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
592                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
593                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
594                         mmc_path, EXTIMG_DIR, encoded_id);
595         } else {
596                 tzplatform_set_user(uid);
597                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
598                         tzplatform_getenv(TZ_USER_APP), pkgid);
599                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
600                         mmc_path, EXTIMG_DIR, encoded_id);
601                 tzplatform_reset_user();
602         }
603         free(encoded_id);
604 #endif
605
606         ret = __app2sd_finalize_device_setup(pkgid, loopback_device,
607                 application_path, uid);
608         if (ret) {
609                 _E("failed to finalize device setup");
610                 return ret;
611         }
612
613         return ret;
614 }
615
616 int app2sd_usr_pre_app_uninstall(const char *pkgid, uid_t uid)
617 {
618         int ret = APP2EXT_SUCCESS;
619         char mmc_path[FILENAME_MAX] = { 0, };
620         char application_path[FILENAME_MAX] = { 0, };
621         char loopback_device[FILENAME_MAX] = { 0, };
622         char *sdpath = NULL;
623         char *encoded_id = NULL;
624         char *device_node = NULL;
625         FILE *fp = NULL;
626
627         /* validate the function parameter recieved */
628         if (pkgid == NULL) {
629                 _E("invalid function arguments to app launch setup");
630                 ret = APP2EXT_ERROR_INVALID_ARGUMENTS;
631                 goto END;
632         }
633
634         /* check whether MMC is present or not */
635         ret = _app2sd_check_mmc_status(&sdpath);
636         if (ret) {
637                 _E("MMC not present OR Not ready (%d)", ret);
638                 ret = APP2EXT_ERROR_MMC_STATUS;
639                 goto END;
640         }
641         snprintf(mmc_path, FILENAME_MAX - 1, "%s", sdpath);
642         free(sdpath);
643         sync();
644
645         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
646         if (encoded_id == NULL)
647                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
648
649         if (_is_global(uid)) {
650                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
651                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
652                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
653                         mmc_path, EXTIMG_DIR, encoded_id);
654         } else {
655                 tzplatform_set_user(uid);
656                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
657                         tzplatform_getenv(TZ_USER_APP), pkgid);
658                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
659                         mmc_path, EXTIMG_DIR, encoded_id);
660                 tzplatform_reset_user();
661         }
662         free(encoded_id);
663
664         /* check app entry is there in sd card or not. */
665         fp = fopen(loopback_device, "r+");
666         if (fp == NULL) {
667                 _E("app entry is not present in SD Card");
668                 ret = APP2EXT_ERROR_INVALID_PACKAGE;
669                 goto END;
670         }
671         fclose(fp);
672
673         /* get the associated device node for SD card applicationer */
674 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
675         device_node =
676                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
677 #else
678         device_node = _app2sd_find_associated_device_node(loopback_device);
679 #endif
680         if (NULL == device_node) {
681                 /* do loopback setup */
682 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
683                 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
684                         false, uid, &device_node);
685                 if (ret) {
686                         _E("dmcrypt open device error(%d)", ret);
687                         return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
688                 }
689 #else
690                 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
691                         loopback_device, uid);
692                 if (device_node == NULL) {
693                         _E("loopback encryption setup failed");
694                         ret = APP2EXT_ERROR_DO_LOSETUP;
695                         goto END;
696                 }
697 #endif
698                 /* do mounting */
699                 ret = _app2sd_mount_app_content(application_path, pkgid,
700                         device_node, MOUNT_TYPE_RW, NULL,
701                         APP2SD_PRE_UNINSTALL, uid);
702                 if (ret) {
703                         _E("mount failed");
704                         if (device_node) {
705                                 free(device_node);
706                                 device_node = NULL;
707                         }
708                         ret = APP2EXT_ERROR_MOUNT_PATH;
709                         goto END;
710                 }
711         } else {
712                 /* do re-mounting */
713                 ret = _app2sd_mount_app_content(application_path, pkgid,
714                         device_node, MOUNT_TYPE_RW_REMOUNT, NULL,
715                         APP2SD_PRE_UNINSTALL, uid);
716                 if (ret) {
717                         _E("remount failed");
718                         if (device_node) {
719                                 free(device_node);
720                                 device_node = NULL;
721                         }
722                         ret = APP2EXT_ERROR_MOUNT_PATH;
723                         goto END;
724                 }
725         }
726         if (device_node) {
727                 free(device_node);
728                 device_node = NULL;
729         }
730
731 END:
732         sync();
733         return ret;
734 }
735
736 int app2sd_usr_post_app_uninstall(const char *pkgid, uid_t uid)
737 {
738         char mmc_path[FILENAME_MAX] = { 0, };
739         char application_path[FILENAME_MAX] = { 0, };
740         char application_mmc_path[FILENAME_MAX] = { 0, };
741         char loopback_device[FILENAME_MAX] = { 0, };
742         char *sdpath = NULL;
743         char *encoded_id = NULL;
744         int ret = APP2EXT_SUCCESS;
745
746         /* validate the function parameter recieved */
747         if (pkgid == NULL) {
748                 _E("invalid function arguments");
749                 ret = APP2EXT_ERROR_INVALID_ARGUMENTS;
750                 goto END;
751         }
752
753         /* check whether MMC is present or not */
754         ret = _app2sd_check_mmc_status(&sdpath);
755         if (ret) {
756                 _E("MMC not present OR Not ready (%d)", ret);
757                 ret = APP2EXT_ERROR_MMC_STATUS;
758                 goto END;
759         }
760         snprintf(mmc_path, FILENAME_MAX - 1, "%s", sdpath);
761         free(sdpath);
762         sync();
763
764         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
765         if (encoded_id == NULL)
766                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
767
768         if (_is_global(uid)) {
769                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
770                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
771                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
772                         mmc_path, EXTIMG_DIR, encoded_id);
773         } else {
774                 tzplatform_set_user(uid);
775                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
776                         tzplatform_getenv(TZ_USER_APP), pkgid);
777                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
778                         mmc_path, EXTIMG_DIR, encoded_id);
779                 tzplatform_reset_user();
780         }
781         free(encoded_id);
782
783         ret = __app2sd_finalize_device_setup(pkgid, loopback_device,
784                 application_path, uid);
785         if (ret) {
786                 _E("failed to finalize device setup");
787                 return ret;
788         }
789
790         /* delete the loopback device from the SD card */
791         ret = _app2sd_delete_loopback_device(loopback_device);
792         if (ret) {
793                 _E("unable to delete the " \
794                         "loopback device from the SD Card");
795                 ret =  APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
796                 goto END;
797         }
798
799         snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
800                 application_path);
801         ret = _app2sd_delete_directory(application_mmc_path);
802         if (ret) {
803                 _E("unable to delete the directory (%s)",
804                 application_path);
805                 goto END;
806         }
807
808         /* remove encryption password from DB */
809         ret = _app2sd_initialize_db();
810         if (ret) {
811                 _E("app2sd db initialize failed");
812                 ret = APP2EXT_ERROR_SQLITE_REGISTRY;
813                 goto END;
814         }
815
816         ret = _app2sd_remove_info_from_db(pkgid, uid);
817         if (ret) {
818                 _E("cannot remove info from db");
819                 ret = APP2EXT_ERROR_SQLITE_REGISTRY;
820                 goto END;
821         }
822
823 END:
824         sync();
825         return ret;
826 }
827
828 int app2sd_usr_pre_move_installed_app(const char *pkgid,
829                 GList *dir_list, app2ext_move_type move_type, uid_t uid)
830 {
831         int ret = 0;
832         int pkgmgr_ret = 0;
833         char *sdpath = NULL;
834         char *image_path = NULL;
835         char mmc_path[FILENAME_MAX] = { 0, };
836
837         /* validate function arguments */
838         if (pkgid == NULL || dir_list == NULL
839                 || move_type < APP2EXT_MOVE_TO_EXT
840                 || move_type > APP2EXT_MOVE_TO_PHONE) {
841                 _E("invalid function arguments");
842                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
843         }
844
845         /* check whether MMC is present or not */
846         ret = _app2sd_check_mmc_status(&sdpath);
847         if (ret) {
848                 _E("MMC not present OR Not ready(%d)", ret);
849                 return APP2EXT_ERROR_MMC_STATUS;
850         }
851         snprintf(mmc_path, FILENAME_MAX - 1, "%s", sdpath);
852         free(sdpath);
853         sync();
854
855         ret = __app2sd_create_app2sd_directories(uid, mmc_path);
856         if (ret) {
857                 _E("failed to create app2sd dirs");
858                 return ret;
859         }
860
861         ret = _app2sd_usr_move_app(pkgid, move_type, dir_list, uid, mmc_path, &image_path);
862         if (ret) {
863                 _D("unable to move application");
864                 return ret;
865         }
866
867         /* if move is completed, then update installed storage to pkgmgr_parser db */
868         if (move_type == APP2EXT_MOVE_TO_EXT) {
869                 if (!image_path) {
870                         _E("image_path is NULL");
871                         return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
872                 }
873                 pkgmgr_ret = pkgmgrinfo_pkginfo_set_usr_installed_storage(pkgid,
874                                 INSTALL_EXTERNAL, image_path, uid);
875                 if (pkgmgr_ret < 0) {
876                         _E("failed to update installed location to db " \
877                                 "[%s, %s] of uid(%d), pkgmgr_ret(%d)",
878                                 pkgid, INSTALL_EXTERNAL, uid, pkgmgr_ret);
879                         return APP2EXT_ERROR_PKGMGR_ERROR;
880                 }
881         } else {
882                 pkgmgr_ret = pkgmgrinfo_pkginfo_set_usr_installed_storage(pkgid,
883                                 INSTALL_INTERNAL, image_path, uid);
884                 if (pkgmgr_ret < 0) {
885                         _E("failed to update installed location to db " \
886                                 "[%s, %s] of uid(%d), pkgmgr_ret(%d)",
887                                 pkgid, INSTALL_INTERNAL, uid, pkgmgr_ret);
888                         return APP2EXT_ERROR_PKGMGR_ERROR;
889                 }
890         }
891
892         if (image_path)
893                 free(image_path);
894
895         sync();
896         return APP2EXT_SUCCESS;
897 }
898
899 int app2sd_usr_post_move_installed_app(const char *pkgid,
900                 app2ext_move_type move_type, uid_t uid)
901 {
902         int ret = 0;
903         char mmc_path[FILENAME_MAX] = { 0, };
904         char application_path[FILENAME_MAX] = { 0, };
905         char loopback_device[FILENAME_MAX] = { 0, };
906         char *sdpath = NULL;
907         char *encoded_id = NULL;
908
909         /* validate function arguments */
910         if (pkgid == NULL || move_type < APP2EXT_MOVE_TO_EXT
911                 || move_type > APP2EXT_MOVE_TO_PHONE) {
912                 _E("invalid function arguments");
913                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
914         }
915
916         if (move_type == APP2EXT_MOVE_TO_PHONE)
917                 return APP2EXT_SUCCESS;
918
919         /* check whether MMC is present or not */
920         ret = _app2sd_check_mmc_status(&sdpath);
921         if (ret) {
922                 _E("MMC not present OR Not ready(%d)", ret);
923                 return APP2EXT_ERROR_MMC_STATUS;
924         }
925         snprintf(mmc_path, FILENAME_MAX - 1, "%s", sdpath);
926         free(sdpath);
927         sync();
928
929         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
930         if (encoded_id == NULL)
931                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
932
933         snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
934                         mmc_path, EXTIMG_DIR, encoded_id);
935         free(encoded_id);
936         if (_is_global(uid)) {
937                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
938                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
939         } else {
940                 tzplatform_set_user(uid);
941                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
942                         tzplatform_getenv(TZ_USER_APP), pkgid);
943                 tzplatform_reset_user();
944         }
945
946         ret = __app2sd_finalize_device_setup(pkgid, loopback_device,
947                 application_path, uid);
948         if (ret) {
949                 _E("failed to finalize device setup");
950                 return ret;
951         }
952
953         sync();
954         return APP2EXT_SUCCESS;
955 }
956
957 int app2sd_usr_pre_app_upgrade(const char *pkgid, GList *dir_list,
958                 int size, uid_t uid)
959 {
960         int ret = APP2EXT_SUCCESS;
961         char app2sd_path[FILENAME_MAX] = { 0, };
962         char loopback_device[FILENAME_MAX] = { 0, };
963         char application_path[FILENAME_MAX] = { 0, };
964         char temp_uid[32] = { 0, };
965         char *sdpath = NULL;
966         char *temp_pkgid = NULL;
967         char *temp_loopback_device = NULL;
968         char *temp_application_path = NULL;
969         char *device_node = NULL;
970         char *encoded_id = NULL;
971         char *temp_encoded_id = NULL;
972         int len = 0;
973         unsigned long long curr_size = 0;
974         FILE *fp = NULL;
975         int reqd_disk_size = size + ceil(size * 0.2);
976
977         /* validate function arguments*/
978         if (pkgid == NULL || dir_list == NULL || size <= 0) {
979                 _E("invalid function arguments");
980                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
981         }
982
983         /* check whether MMC is present or not */
984         ret = _app2sd_check_mmc_status(&sdpath);
985         if (ret) {
986                 _E("MMC not present OR Not ready (%d)", ret);
987                 return APP2EXT_ERROR_MMC_STATUS;
988         }
989         snprintf(app2sd_path, FILENAME_MAX - 1, "%s/%s",
990                         sdpath, EXTIMG_DIR);
991         free(sdpath);
992         sync();
993
994         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
995         if (encoded_id == NULL)
996                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
997
998         if (_is_global(uid)) {
999                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1000                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1001                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1002                         app2sd_path, encoded_id);
1003         } else {
1004                 tzplatform_set_user(uid);
1005                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1006                         tzplatform_getenv(TZ_USER_APP), pkgid);
1007                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1008                         app2sd_path, encoded_id);
1009                 tzplatform_reset_user();
1010         }
1011         free(encoded_id);
1012
1013         /* check app entry is there in sd card or not. */
1014         fp = fopen(loopback_device, "r+");
1015         if (fp == NULL) {
1016                 _E("app entry is not present in SD Card");
1017                 return APP2EXT_ERROR_INVALID_PACKAGE;
1018         }
1019         fclose(fp);
1020
1021         /* get installed app size*/
1022         curr_size = _app2sd_calculate_file_size(loopback_device);
1023         curr_size = (curr_size) / (1024 * 1024);
1024         if (curr_size == 0) {
1025                 _E("app entry is not present in SD Card");
1026                 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
1027         }
1028         if ((int)curr_size < reqd_disk_size) {
1029                 len = strlen(pkgid) + strlen(".new");
1030                 temp_pkgid = calloc(len + 1, sizeof(char));
1031                 if (temp_pkgid == NULL) {
1032                         _E("memory alloc failed");
1033                         return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1034                 }
1035                 snprintf(temp_pkgid, len + 1, "%s.new", pkgid);
1036
1037                 if (_is_global(uid)) {
1038                         len = strlen(tzplatform_getenv(TZ_SYS_RW_APP)) + strlen(temp_pkgid) + 1;
1039                         temp_application_path = calloc(len + 1, sizeof(char));
1040                         if (temp_application_path == NULL) {
1041                                 _E("memory alloc failed");
1042                                 free(temp_pkgid);
1043                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1044                         }
1045                         snprintf(temp_application_path, len + 1, "%s/%s",
1046                                 tzplatform_getenv(TZ_SYS_RW_APP), temp_pkgid);
1047
1048                         temp_encoded_id = _app2sd_get_encoded_name((const char *)temp_pkgid, uid);
1049                         if (temp_encoded_id == NULL) {
1050                                 free(temp_pkgid);
1051                                 free(temp_application_path);
1052                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1053                         }
1054                         len = strlen(app2sd_path) + strlen(temp_encoded_id) + 1;
1055                         temp_loopback_device = calloc(len + 1, sizeof(char));
1056                         if (temp_loopback_device == NULL) {
1057                                 _E("memory alloc failed");
1058                                 free(temp_pkgid);
1059                                 free(temp_application_path);
1060                                 free(temp_encoded_id);
1061                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1062                         }
1063                         snprintf(temp_loopback_device, len + 1, "%s/%s",
1064                                 app2sd_path, temp_encoded_id);
1065                         free(temp_encoded_id);
1066                 } else {
1067                         tzplatform_set_user(uid);
1068                         len = strlen(tzplatform_getenv(TZ_USER_APP)) + strlen(temp_pkgid) + 1;
1069                         temp_application_path = calloc(len + 1, sizeof(char));
1070                         if (temp_application_path == NULL) {
1071                                 _E("memory alloc failed");
1072                                 free(temp_pkgid);
1073                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1074                         }
1075                         snprintf(temp_application_path, len + 1, "%s/%s",
1076                                 tzplatform_getenv(TZ_USER_APP), temp_pkgid);
1077
1078                         temp_encoded_id = _app2sd_get_encoded_name((const char *)temp_pkgid, uid);
1079                         if (temp_encoded_id == NULL) {
1080                                 free(temp_pkgid);
1081                                 free(temp_application_path);
1082                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1083                         }
1084                         snprintf(temp_uid, 32, "%d", uid);
1085                         len = strlen(app2sd_path) + strlen(temp_uid) + strlen(temp_encoded_id) + 2;
1086                         temp_loopback_device = calloc(len + 1, sizeof(char));
1087                         if (temp_loopback_device == NULL) {
1088                                 _E("memory alloc failed");
1089                                 free(temp_pkgid);
1090                                 free(temp_application_path);
1091                                 free(temp_encoded_id);
1092                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1093                         }
1094                         snprintf(temp_loopback_device, len + 1, "%s/%s",
1095                                 app2sd_path, temp_encoded_id);
1096                         free(temp_encoded_id);
1097                         tzplatform_reset_user();
1098                 }
1099                 ret = _app2sd_update_loopback_device_size(pkgid,
1100                         loopback_device, application_path, temp_pkgid,
1101                         temp_loopback_device, temp_application_path,
1102                         reqd_disk_size, dir_list, uid);
1103                 free(temp_pkgid);
1104                 free(temp_application_path);
1105                 free(temp_loopback_device);
1106                 if (APP2EXT_SUCCESS != ret) {
1107                         _E("failed to update loopback device size");
1108                         return ret;
1109                 }
1110         }
1111
1112         /* get the associated device node for SD card applicationer */
1113 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1114         device_node =
1115                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1116 #else
1117         device_node = _app2sd_find_associated_device_node(loopback_device);
1118 #endif
1119         if (NULL == device_node) {
1120                 /* do loopback setup */
1121 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1122                 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1123                         false, uid, &device_node);
1124                 if (ret) {
1125                         _E("dmcrypt open device error");
1126                         return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1127                 }
1128 #else
1129                 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1130                         loopback_device, uid);
1131                 if (device_node == NULL) {
1132                         _E("loopback encryption setup failed");
1133                         return APP2EXT_ERROR_DO_LOSETUP;
1134                 }
1135 #endif
1136
1137                 /* do mounting */
1138                 ret = _app2sd_mount_app_content(application_path, pkgid,
1139                         device_node, MOUNT_TYPE_RW, dir_list,
1140                         APP2SD_PRE_UPGRADE, uid);
1141                 if (ret) {
1142                         _E("mount failed");
1143                         if (device_node) {
1144                                 free(device_node);
1145                                 device_node = NULL;
1146                         }
1147                         return APP2EXT_ERROR_MOUNT_PATH;
1148                 }
1149         } else {
1150                 /* do re-mounting */
1151                 ret = _app2sd_mount_app_content(application_path, pkgid,
1152                         device_node, MOUNT_TYPE_RW_REMOUNT, NULL,
1153                         APP2SD_PRE_UPGRADE, uid);
1154                 if (ret) {
1155                         _E("remount failed");
1156                         if (device_node) {
1157                                 free(device_node);
1158                                 device_node = NULL;
1159                         }
1160                         return APP2EXT_ERROR_MOUNT_PATH;
1161                 }
1162         }
1163
1164         if (device_node) {
1165                 free(device_node);
1166                 device_node = NULL;
1167         }
1168
1169         sync();
1170         return ret;
1171 }
1172
1173 int app2sd_usr_post_app_upgrade(const char *pkgid,
1174                 app2ext_status install_status, uid_t uid)
1175 {
1176         char mmc_path[FILENAME_MAX] = { 0, };
1177         char loopback_device[FILENAME_MAX] = { 0, };
1178         char application_path[FILENAME_MAX] = { 0, };
1179         char *sdpath = NULL;
1180         char *encoded_id = NULL;
1181         int ret = APP2EXT_SUCCESS;
1182         int pkgmgr_ret = 0;
1183
1184         /* validate the function parameter recieved */
1185         if (pkgid == NULL || install_status < APP2EXT_STATUS_FAILED
1186                 || install_status > APP2EXT_STATUS_SUCCESS) {
1187                 _E("invalid func parameters");
1188                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1189         }
1190
1191         /* check whether MMC is present or not */
1192         ret = _app2sd_check_mmc_status(&sdpath);
1193         if (ret) {
1194                 _E("MMC not present OR Not ready (%d)", ret);
1195                 return APP2EXT_ERROR_MMC_STATUS;
1196         }
1197         snprintf(mmc_path, FILENAME_MAX - 1, "%s", sdpath);
1198         free(sdpath);
1199         sync();
1200
1201         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
1202         if (encoded_id == NULL)
1203                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1204
1205         if (_is_global(uid)) {
1206                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1207                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1208                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
1209                         mmc_path, EXTIMG_DIR, encoded_id);
1210         } else {
1211                 tzplatform_set_user(uid);
1212                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1213                         tzplatform_getenv(TZ_USER_APP), pkgid);
1214                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
1215                         mmc_path, EXTIMG_DIR, encoded_id);
1216                 tzplatform_reset_user();
1217         }
1218         free(encoded_id);
1219
1220         ret = __app2sd_finalize_device_setup(pkgid, loopback_device,
1221                 application_path, uid);
1222         if (ret) {
1223                 _E("failed to finalize device setup");
1224                 return ret;
1225         }
1226
1227         pkgmgr_ret = pkgmgrinfo_pkginfo_set_usr_installed_storage(pkgid,
1228                 INSTALL_EXTERNAL, loopback_device, uid);
1229         if (pkgmgr_ret < 0) {
1230                 _E("fail to update installed location " \
1231                         "to db[%s, %d] of uid(%d), pkgmgr ret(%d)",
1232                         pkgid, INSTALL_EXTERNAL, uid, pkgmgr_ret);
1233                 return APP2EXT_ERROR_PKGMGR_ERROR;
1234         }
1235
1236         sync();
1237         return ret;
1238 }
1239
1240 int app2sd_usr_force_clean(const char *pkgid, uid_t uid)
1241 {
1242         char mmc_path[FILENAME_MAX] = { 0, };
1243         char loopback_device[FILENAME_MAX] = { 0, };
1244         char application_path[FILENAME_MAX] = { 0, };
1245         char *sdpath = NULL;
1246         char *encoded_id = NULL;
1247         int ret = APP2EXT_SUCCESS;
1248
1249         /* validate the function parameter recieved */
1250         if (pkgid == NULL) {
1251                 _E("invalid func parameters");
1252                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1253         }
1254
1255         /* check whether MMC is present or not */
1256         ret = _app2sd_check_mmc_status(&sdpath);
1257         if (ret) {
1258                 _E("MMC not present OR Not ready (%d)", ret);
1259                 return APP2EXT_ERROR_MMC_STATUS;
1260         }
1261         snprintf(mmc_path, FILENAME_MAX - 1, "%s", sdpath);
1262         free(sdpath);
1263         sync();
1264
1265         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
1266         if (encoded_id == NULL)
1267                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1268
1269         if (_is_global(uid)) {
1270                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1271                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1272                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
1273                         mmc_path, EXTIMG_DIR, encoded_id);
1274         } else {
1275                 tzplatform_set_user(uid);
1276                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1277                         tzplatform_getenv(TZ_USER_APP), pkgid);
1278                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
1279                         mmc_path, EXTIMG_DIR, encoded_id);
1280                 tzplatform_reset_user();
1281         }
1282         free(encoded_id);
1283
1284         ret = _app2sd_force_clean(pkgid, application_path, loopback_device, uid);
1285
1286         sync();
1287         return ret;
1288 }
1289
1290 int app2sd_enable_full_pkg(void)
1291 {
1292         int ret = APP2EXT_SUCCESS;
1293         char buf[FILENAME_MAX] = { 0, };
1294         char app2sd_path[FILENAME_MAX] = { 0, };
1295         char loopback_device[FILENAME_MAX] = { 0, };
1296         char *sdpath = NULL;
1297         char *pkgid = NULL;
1298         DIR *dir = NULL;
1299         struct dirent *entry = NULL;
1300         uid_t uid = 0;
1301
1302         /* check whether MMC is present or not */
1303         ret = _app2sd_check_mmc_status(&sdpath);
1304         if (ret) {
1305                 _E("MMC not present OR Not ready (%d)", ret);
1306                 return APP2EXT_ERROR_MMC_STATUS;
1307         }
1308         snprintf(app2sd_path, FILENAME_MAX - 1, "%s/%s",
1309                         sdpath, EXTIMG_DIR);
1310         free(sdpath);
1311
1312         dir = opendir(app2sd_path);
1313         if (!dir) {
1314                 strerror_r(errno, buf, sizeof(buf));
1315                 _E("failed to opendir (%s)", buf);
1316                 return APP2EXT_ERROR_OPEN_DIR;
1317         }
1318
1319         ret = _app2sd_initialize_db();
1320         if (ret) {
1321                 _E("app2sd db initialize failed");
1322                 closedir(dir);
1323                 return APP2EXT_ERROR_SQLITE_REGISTRY;
1324         }
1325
1326         while ((entry = readdir(dir)) != NULL) {
1327                 if (strcmp(entry->d_name, ".") == 0 ||
1328                         strcmp(entry->d_name, "..") == 0)
1329                         continue;
1330                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1331                         app2sd_path, entry->d_name);
1332                 ret = _app2sd_get_info_from_db(loopback_device,
1333                         &pkgid, &uid);
1334                 if (ret) {
1335                         _W("failed to get info from db, continue");
1336                         continue;
1337                 }
1338                 if (pkgid) {
1339                         _D("pkgid(%s), uid(%d)", pkgid, uid);
1340                         ret = app2sd_usr_on_demand_setup_init(pkgid, uid);
1341                         if (ret) {
1342                                 _E("error(%d)", ret);
1343                                 continue;
1344                         }
1345                         free(pkgid);
1346                         pkgid = NULL;
1347                 }
1348         }
1349
1350         if (pkgid) {
1351                 free(pkgid);
1352                 pkgid = NULL;
1353         }
1354         closedir(dir);
1355
1356         sync();
1357         return ret;
1358 }
1359
1360 static int _app2sd_info_cb_func(const char *pkgid, uid_t uid)
1361 {
1362         int ret = APP2EXT_SUCCESS;
1363
1364         if (pkgid) {
1365                 _D("pkgid(%s), uid(%d)", pkgid, uid);
1366                 ret = app2sd_usr_on_demand_setup_exit(pkgid, uid);
1367                 if (ret)
1368                         _E("error(%d)", ret);
1369         }
1370
1371         return ret;
1372 }
1373
1374 int app2sd_disable_full_pkg(void)
1375 {
1376         int ret = APP2EXT_SUCCESS;
1377
1378         ret = _app2sd_initialize_db();
1379         if (ret) {
1380                 _E("app2sd db initialize failed");
1381                 return APP2EXT_ERROR_SQLITE_REGISTRY;
1382         }
1383
1384         ret = _app2sd_get_foreach_info_from_db((app2sd_info_cb)_app2sd_info_cb_func);
1385         if (ret)
1386                 _E("disable full pkg error(%d)", ret);
1387
1388         sync();
1389         return ret;
1390 }
1391
1392 static int _app2sd_migrate_legacy_image(const char *pkgid, const char *passwd,
1393                 const char *mmc_path, uid_t uid)
1394 {
1395         int ret = 0;
1396         char *device_node = NULL;
1397         char *encoded_id = NULL;
1398         char new_image[FILENAME_MAX] = { 0, };
1399         char legacy_image[FILENAME_MAX] = { 0, };
1400         char application_path[FILENAME_MAX] = { 0, };
1401         uid_t default_uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
1402
1403         if (_is_global(uid)) {
1404                 snprintf(application_path, sizeof(application_path), "%s/%s",
1405                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1406         } else {
1407                 tzplatform_set_user(uid);
1408                 snprintf(application_path, sizeof(application_path), "%s/%s",
1409                         tzplatform_getenv(TZ_USER_APP), pkgid);
1410                 tzplatform_reset_user();
1411         }
1412
1413         /* make the information and insert to DB */
1414         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
1415         if (encoded_id == NULL)
1416                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1417         snprintf(new_image, sizeof(new_image), "%s/%s",
1418                 mmc_path, encoded_id);
1419         free(encoded_id);
1420
1421         snprintf(legacy_image, sizeof(legacy_image), "%s/%s",
1422                 mmc_path, pkgid);
1423
1424         ret = _app2sd_rename_dir(legacy_image, new_image);
1425         if (ret) {
1426                 _E("unable to rename (%s)", legacy_image);
1427                 return APP2EXT_ERROR_ACCESS_FILE;
1428         }
1429
1430         ret = pkgmgrinfo_pkginfo_set_usr_installed_storage(pkgid,
1431                 INSTALL_EXTERNAL, new_image, uid);
1432         if (ret < 0) {
1433                 _E("fail to update installed location " \
1434                         "to db[%s, %d] of uid(%d), ret(%d)",
1435                         pkgid, INSTALL_EXTERNAL, uid, ret);
1436                 return APP2EXT_ERROR_PKGMGR_ERROR;
1437         }
1438
1439         /* update app2sd db */
1440         if (_is_global(uid)) {
1441                 ret = _app2sd_remove_info_from_db(pkgid, default_uid);
1442                 if (ret) {
1443                         _E("cannot remove info from db");
1444                         return APP2EXT_ERROR_SQLITE_REGISTRY;
1445                 }
1446         }
1447         ret = _app2sd_set_info_in_db(pkgid, passwd, new_image, uid);
1448         if (ret) {
1449                 _E("unable to save info");
1450                 return APP2EXT_ERROR_SQLITE_REGISTRY;
1451         }
1452
1453 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1454         device_node =
1455                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1456         if (device_node) {
1457                 _E("device_node(%s_%d) already associated", pkgid, uid);
1458                 return APP2EXT_ERROR_ALREADY_MOUNTED;
1459         }
1460
1461         ret = _app2sd_dmcrypt_open_device(pkgid, new_image, false,
1462                 uid, &device_node);
1463         if (ret) {
1464                 _E("dmcrypt open device error(%d)", ret);
1465                 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1466         }
1467 #else
1468         result = (char *)_app2sd_find_associated_device(new_image);
1469         /* process the string */
1470         if ((result != NULL) && strstr(result, "/dev") != NULL) {
1471                 _E("already associated");
1472                 free(result);
1473                 result = NULL;
1474                 return APP2EXT_ERROR_ALREADY_MOUNTED;
1475         }
1476
1477         /* do loopback setup */
1478         device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1479                 new_image, uid);
1480         if (device_node == NULL) {
1481                 _E("loopback encryption setup failed");
1482                 return APP2EXT_ERROR_DO_LOSETUP;
1483         }
1484 #endif
1485
1486         /* do mounting */
1487         ret = _app2sd_mount_app_content(application_path, pkgid,
1488                 device_node, MOUNT_TYPE_RW, NULL,
1489                 APP2SD_MIGRATE_LEGACY, uid);
1490         if (ret) {
1491                 _E("mount failed");
1492                 if (device_node) {
1493                         free(device_node);
1494                         device_node = NULL;
1495                 }
1496                 return APP2EXT_ERROR_MOUNT_PATH;
1497         }
1498
1499         if (device_node) {
1500                 free(device_node);
1501                 device_node = NULL;
1502         }
1503
1504         sync();
1505         return APP2EXT_SUCCESS;
1506 }
1507
1508 int app2sd_pre_migrate_legacy(const char *pkgid, uid_t uid)
1509 {
1510         int ret = APP2EXT_SUCCESS;
1511         char *passwd = NULL;
1512         char *sdpath = NULL;
1513         char mmc_path[FILENAME_MAX] = { 0, };
1514         char file_path[FILENAME_MAX] = { 0, };
1515         uid_t default_uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
1516
1517         /* check whether MMC is present or not */
1518         ret = _app2sd_check_mmc_status(&sdpath);
1519         if (ret) {
1520                 _E("MMC not present OR Not ready (%d)", ret);
1521                 return APP2EXT_ERROR_MMC_STATUS;
1522         }
1523         snprintf(mmc_path, sizeof(mmc_path), "%s/%s", sdpath, EXTIMG_DIR);
1524         free(sdpath);
1525         snprintf(file_path, sizeof(file_path), "%s/%s", mmc_path, pkgid);
1526
1527         ret = _app2sd_initialize_db();
1528         if (ret) {
1529                 _E("app2sd db initialize failed");
1530                 return APP2EXT_ERROR_SQLITE_REGISTRY;
1531         }
1532
1533         /* In the upgrade script, the information
1534          * of legacy image are filled with default user-id,
1535          * pkgid(from old db), passwd(from old db) and
1536          * empty filename in app2sd db. */
1537         if (!_app2sd_get_filename_from_db(pkgid, default_uid)) {
1538                 passwd = _app2sd_get_password_from_db(pkgid, default_uid);
1539                 if (passwd) {
1540                         ret = _app2sd_migrate_legacy_image(pkgid, passwd,
1541                                 mmc_path, uid);
1542                         free(passwd);
1543                         passwd = NULL;
1544                 } else {
1545                         _E("invalid package info");
1546                         return APP2EXT_ERROR_INVALID_PACKAGE;
1547                 }
1548         } else {
1549                 _W("same pkg exists, remove legacy file (%s)", file_path);
1550                 ret = remove(file_path);
1551                 if (ret < 0)
1552                         _E("failed to remove, errno(%d)", errno);
1553                 return APP2EXT_ERROR_PKG_EXISTS;
1554         }
1555
1556         return ret;
1557 }
1558
1559 int app2sd_post_migrate_legacy(const char *pkgid, uid_t uid)
1560 {
1561         int ret = APP2EXT_SUCCESS;
1562         char *sdpath = NULL;
1563         char *encoded_id = NULL;
1564         char mmc_path[FILENAME_MAX] = { 0, };
1565         char application_path[FILENAME_MAX] = { 0, };
1566         char loopback_device[FILENAME_MAX] = { 0, };
1567
1568         /* check whether MMC is present or not */
1569         ret = _app2sd_check_mmc_status(&sdpath);
1570         if (ret) {
1571                 _E("MMC not present OR Not ready (%d)", ret);
1572                 return APP2EXT_ERROR_MMC_STATUS;
1573         }
1574         snprintf(mmc_path, sizeof(mmc_path), "%s/%s",
1575                 sdpath, EXTIMG_DIR);
1576         free(sdpath);
1577
1578         if (_is_global(uid)) {
1579                 snprintf(application_path, sizeof(application_path), "%s/%s",
1580                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1581         } else {
1582                 tzplatform_set_user(uid);
1583                 snprintf(application_path, sizeof(application_path), "%s/%s",
1584                         tzplatform_getenv(TZ_USER_APP), pkgid);
1585                 tzplatform_reset_user();
1586         }
1587
1588         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
1589         if (encoded_id == NULL) {
1590                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1591         }
1592         snprintf(loopback_device, sizeof(loopback_device), "%s/%s",
1593                 mmc_path, encoded_id);
1594         free(encoded_id);
1595
1596         ret = __app2sd_finalize_device_setup(pkgid, loopback_device,
1597                 application_path, uid);
1598         if (ret) {
1599                 _E("failed to finalize device setup");
1600                 return ret;
1601         }
1602
1603         return APP2EXT_SUCCESS;
1604 }
1605
1606 /* this function is called when sdcard is inserted */
1607 int app2sd_migrate_legacy_all(void)
1608 {
1609         int ret = APP2EXT_SUCCESS;
1610         int rc = 0;
1611         char buf[FILENAME_MAX] = { 0, };
1612         char app2sd_path[FILENAME_MAX] = { 0, };
1613         char loopback_device[FILENAME_MAX] = { 0, };
1614         char *sdpath = NULL;
1615         DIR *dir = NULL;
1616         struct dirent entry;
1617         struct dirent *result = NULL;
1618         uid_t default_uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
1619         pkgmgr_client *pc;
1620
1621         /* check whether MMC is present or not */
1622         ret = _app2sd_check_mmc_status(&sdpath);
1623         if (ret) {
1624                 _E("MMC not present OR Not ready (%d)", ret);
1625                 return APP2EXT_ERROR_MMC_STATUS;
1626         }
1627         snprintf(app2sd_path, sizeof(app2sd_path), "%s/%s",
1628                 sdpath, EXTIMG_DIR);
1629         free(sdpath);
1630
1631         dir = opendir(app2sd_path);
1632         if (!dir) {
1633                 strerror_r(errno, buf, sizeof(buf));
1634                 _E("failed to opendir (%s)", buf);
1635                 return APP2EXT_ERROR_OPEN_DIR;
1636         }
1637
1638         pc = pkgmgr_client_new(PC_REQUEST);
1639         if (pc == NULL) {
1640                 _E("failed to create pkgmgr client");
1641                 closedir(dir);
1642                 return APP2EXT_ERROR_PKGMGR_ERROR;
1643         }
1644
1645         for (rc = readdir_r(dir, &entry, &result);
1646                 rc == 0 && result != NULL;
1647                 rc = readdir_r(dir, &entry, &result)) {
1648                 if (strcmp(entry.d_name, ".") == 0 ||
1649                         strcmp(entry.d_name, "..") == 0)
1650                         continue;
1651                 snprintf(loopback_device, sizeof(loopback_device), "%s/%s",
1652                         app2sd_path, entry.d_name);
1653                 /* check losetup image */
1654                 if (_app2sd_check_is_luks_device(loopback_device) == 0) {
1655                         /* call installer backend
1656                          * to change access-rule and broadcast this update */
1657                         ret = pkgmgr_client_usr_migrate_external_image(pc,
1658                                 entry.d_name, default_uid);
1659                         if (ret < 0)
1660                                 _E("failed to request migration, ret(%d)", ret);
1661                 }
1662         }
1663
1664         pkgmgr_client_free(pc);
1665         closedir(dir);
1666
1667         return ret;
1668 }
1669