Replace 'readdir_r' with 'readdir'
[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 mmc_path[FILENAME_MAX] = { 0, };
552         char application_path[FILENAME_MAX] = { 0, };
553         char loopback_device[FILENAME_MAX] = { 0, };
554         char *sdpath = NULL;
555         char *encoded_id = NULL;
556         FILE *fp = NULL;
557         int mmc_present = 1;
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         /* check whether MMC is present or not */
568         ret = _app2sd_check_mmc_status(&sdpath);
569         if (ret) {
570                 _W("MMC not present OR Not ready (%d)", ret);
571                 mmc_present = 0;
572         }
573         snprintf(mmc_path, FILENAME_MAX - 1, "%s", sdpath);
574         free(sdpath);
575
576         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
577         if (encoded_id == NULL)
578                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
579
580         /* check app entry is there in sd card or not. */
581         if (_is_global(uid)) {
582                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
583                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
584                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
585                         mmc_path, EXTIMG_DIR, encoded_id);
586         } else {
587                 tzplatform_set_user(uid);
588                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
589                         tzplatform_getenv(TZ_USER_APP), pkgid);
590                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
591                         mmc_path, EXTIMG_DIR, encoded_id);
592                 tzplatform_reset_user();
593         }
594         free(encoded_id);
595
596         if (mmc_present) {
597                 fp = fopen(loopback_device, "r+");
598                 if (fp == NULL) {
599                         _E("app entry is not present in SD Card");
600                         return APP2EXT_ERROR_INVALID_PACKAGE;
601                 }
602                 fclose(fp);
603         }
604
605         ret = __app2sd_finalize_device_setup(pkgid, loopback_device,
606                 application_path, uid);
607         if (ret) {
608                 _E("failed to finalize device setup");
609                 return ret;
610         }
611
612         return ret;
613 }
614
615 int app2sd_usr_pre_app_uninstall(const char *pkgid, uid_t uid)
616 {
617         int ret = APP2EXT_SUCCESS;
618         char mmc_path[FILENAME_MAX] = { 0, };
619         char application_path[FILENAME_MAX] = { 0, };
620         char loopback_device[FILENAME_MAX] = { 0, };
621         char *sdpath = NULL;
622         char *encoded_id = NULL;
623         char *device_node = NULL;
624         FILE *fp = NULL;
625
626         /* validate the function parameter recieved */
627         if (pkgid == NULL) {
628                 _E("invalid function arguments to app launch setup");
629                 ret = APP2EXT_ERROR_INVALID_ARGUMENTS;
630                 goto END;
631         }
632
633         /* check whether MMC is present or not */
634         ret = _app2sd_check_mmc_status(&sdpath);
635         if (ret) {
636                 _E("MMC not present OR Not ready (%d)", ret);
637                 ret = APP2EXT_ERROR_MMC_STATUS;
638                 goto END;
639         }
640         snprintf(mmc_path, FILENAME_MAX - 1, "%s", sdpath);
641         free(sdpath);
642         sync();
643
644         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
645         if (encoded_id == NULL)
646                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
647
648         if (_is_global(uid)) {
649                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
650                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
651                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
652                         mmc_path, EXTIMG_DIR, encoded_id);
653         } else {
654                 tzplatform_set_user(uid);
655                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
656                         tzplatform_getenv(TZ_USER_APP), pkgid);
657                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
658                         mmc_path, EXTIMG_DIR, encoded_id);
659                 tzplatform_reset_user();
660         }
661         free(encoded_id);
662
663         /* check app entry is there in sd card or not. */
664         fp = fopen(loopback_device, "r+");
665         if (fp == NULL) {
666                 _E("app entry is not present in SD Card");
667                 ret = APP2EXT_ERROR_INVALID_PACKAGE;
668                 goto END;
669         }
670         fclose(fp);
671
672         /* get the associated device node for SD card applicationer */
673 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
674         device_node =
675                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
676 #else
677         device_node = _app2sd_find_associated_device_node(loopback_device);
678 #endif
679         if (NULL == device_node) {
680                 /* do loopback setup */
681 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
682                 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
683                         false, uid, &device_node);
684                 if (ret) {
685                         _E("dmcrypt open device error(%d)", ret);
686                         return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
687                 }
688 #else
689                 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
690                         loopback_device, uid);
691                 if (device_node == NULL) {
692                         _E("loopback encryption setup failed");
693                         ret = APP2EXT_ERROR_DO_LOSETUP;
694                         goto END;
695                 }
696 #endif
697                 /* do mounting */
698                 ret = _app2sd_mount_app_content(application_path, pkgid,
699                         device_node, MOUNT_TYPE_RW, NULL,
700                         APP2SD_PRE_UNINSTALL, uid);
701                 if (ret) {
702                         _E("mount failed");
703                         if (device_node) {
704                                 free(device_node);
705                                 device_node = NULL;
706                         }
707                         ret = APP2EXT_ERROR_MOUNT_PATH;
708                         goto END;
709                 }
710         } else {
711                 /* do re-mounting */
712                 ret = _app2sd_mount_app_content(application_path, pkgid,
713                         device_node, MOUNT_TYPE_RW_REMOUNT, NULL,
714                         APP2SD_PRE_UNINSTALL, uid);
715                 if (ret) {
716                         _E("remount failed");
717                         if (device_node) {
718                                 free(device_node);
719                                 device_node = NULL;
720                         }
721                         ret = APP2EXT_ERROR_MOUNT_PATH;
722                         goto END;
723                 }
724         }
725         if (device_node) {
726                 free(device_node);
727                 device_node = NULL;
728         }
729
730 END:
731         sync();
732         return ret;
733 }
734
735 int app2sd_usr_post_app_uninstall(const char *pkgid, uid_t uid)
736 {
737         char mmc_path[FILENAME_MAX] = { 0, };
738         char application_path[FILENAME_MAX] = { 0, };
739         char application_mmc_path[FILENAME_MAX] = { 0, };
740         char loopback_device[FILENAME_MAX] = { 0, };
741         char *sdpath = NULL;
742         char *encoded_id = NULL;
743         int ret = APP2EXT_SUCCESS;
744
745         /* validate the function parameter recieved */
746         if (pkgid == NULL) {
747                 _E("invalid function arguments");
748                 ret = APP2EXT_ERROR_INVALID_ARGUMENTS;
749                 goto END;
750         }
751
752         /* check whether MMC is present or not */
753         ret = _app2sd_check_mmc_status(&sdpath);
754         if (ret) {
755                 _E("MMC not present OR Not ready (%d)", ret);
756                 ret = APP2EXT_ERROR_MMC_STATUS;
757                 goto END;
758         }
759         snprintf(mmc_path, FILENAME_MAX - 1, "%s", sdpath);
760         free(sdpath);
761         sync();
762
763         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
764         if (encoded_id == NULL)
765                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
766
767         if (_is_global(uid)) {
768                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
769                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
770                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
771                         mmc_path, EXTIMG_DIR, encoded_id);
772         } else {
773                 tzplatform_set_user(uid);
774                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
775                         tzplatform_getenv(TZ_USER_APP), pkgid);
776                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
777                         mmc_path, EXTIMG_DIR, encoded_id);
778                 tzplatform_reset_user();
779         }
780         free(encoded_id);
781
782         ret = __app2sd_finalize_device_setup(pkgid, loopback_device,
783                 application_path, uid);
784         if (ret) {
785                 _E("failed to finalize device setup");
786                 return ret;
787         }
788
789         /* delete the loopback device from the SD card */
790         ret = _app2sd_delete_loopback_device(loopback_device);
791         if (ret) {
792                 _E("unable to delete the " \
793                         "loopback device from the SD Card");
794                 ret =  APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
795                 goto END;
796         }
797
798         snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
799                 application_path);
800         ret = _app2sd_delete_directory(application_mmc_path);
801         if (ret) {
802                 _E("unable to delete the directory (%s)",
803                 application_path);
804                 goto END;
805         }
806
807         /* remove encryption password from DB */
808         ret = _app2sd_initialize_db();
809         if (ret) {
810                 _E("app2sd db initialize failed");
811                 ret = APP2EXT_ERROR_SQLITE_REGISTRY;
812                 goto END;
813         }
814
815         ret = _app2sd_remove_info_from_db(pkgid, uid);
816         if (ret) {
817                 _E("cannot remove info from db");
818                 ret = APP2EXT_ERROR_SQLITE_REGISTRY;
819                 goto END;
820         }
821
822 END:
823         sync();
824         return ret;
825 }
826
827 int app2sd_usr_pre_move_installed_app(const char *pkgid,
828                 GList *dir_list, app2ext_move_type move_type, uid_t uid)
829 {
830         int ret = 0;
831         int pkgmgr_ret = 0;
832         char *sdpath = NULL;
833         char *image_path = NULL;
834         char mmc_path[FILENAME_MAX] = { 0, };
835
836         /* validate function arguments */
837         if (pkgid == NULL || dir_list == NULL
838                 || move_type < APP2EXT_MOVE_TO_EXT
839                 || move_type > APP2EXT_MOVE_TO_PHONE) {
840                 _E("invalid function arguments");
841                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
842         }
843
844         /* check whether MMC is present or not */
845         ret = _app2sd_check_mmc_status(&sdpath);
846         if (ret) {
847                 _E("MMC not present OR Not ready(%d)", ret);
848                 return APP2EXT_ERROR_MMC_STATUS;
849         }
850         snprintf(mmc_path, FILENAME_MAX - 1, "%s", sdpath);
851         free(sdpath);
852         sync();
853
854         ret = __app2sd_create_app2sd_directories(uid, mmc_path);
855         if (ret) {
856                 _E("failed to create app2sd dirs");
857                 return ret;
858         }
859
860         ret = _app2sd_usr_move_app(pkgid, move_type, dir_list, uid, mmc_path, &image_path);
861         if (ret) {
862                 _D("unable to move application");
863                 return ret;
864         }
865
866         /* if move is completed, then update installed storage to pkgmgr_parser db */
867         if (move_type == APP2EXT_MOVE_TO_EXT) {
868                 if (!image_path) {
869                         _E("image_path is NULL");
870                         return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
871                 }
872                 pkgmgr_ret = pkgmgrinfo_pkginfo_set_usr_installed_storage(pkgid,
873                                 INSTALL_EXTERNAL, image_path, uid);
874                 if (pkgmgr_ret < 0) {
875                         _E("failed to update installed location to db " \
876                                 "[%s, %s] of uid(%d), pkgmgr_ret(%d)",
877                                 pkgid, INSTALL_EXTERNAL, uid, pkgmgr_ret);
878                         return APP2EXT_ERROR_PKGMGR_ERROR;
879                 }
880         } else {
881                 pkgmgr_ret = pkgmgrinfo_pkginfo_set_usr_installed_storage(pkgid,
882                                 INSTALL_INTERNAL, image_path, uid);
883                 if (pkgmgr_ret < 0) {
884                         _E("failed to update installed location to db " \
885                                 "[%s, %s] of uid(%d), pkgmgr_ret(%d)",
886                                 pkgid, INSTALL_INTERNAL, uid, pkgmgr_ret);
887                         return APP2EXT_ERROR_PKGMGR_ERROR;
888                 }
889         }
890
891         if (image_path)
892                 free(image_path);
893
894         sync();
895         return APP2EXT_SUCCESS;
896 }
897
898 int app2sd_usr_post_move_installed_app(const char *pkgid,
899                 app2ext_move_type move_type, uid_t uid)
900 {
901         int ret = 0;
902         char mmc_path[FILENAME_MAX] = { 0, };
903         char application_path[FILENAME_MAX] = { 0, };
904         char loopback_device[FILENAME_MAX] = { 0, };
905         char *sdpath = NULL;
906         char *encoded_id = NULL;
907
908         /* validate function arguments */
909         if (pkgid == NULL || move_type < APP2EXT_MOVE_TO_EXT
910                 || move_type > APP2EXT_MOVE_TO_PHONE) {
911                 _E("invalid function arguments");
912                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
913         }
914
915         if (move_type == APP2EXT_MOVE_TO_PHONE)
916                 return APP2EXT_SUCCESS;
917
918         /* check whether MMC is present or not */
919         ret = _app2sd_check_mmc_status(&sdpath);
920         if (ret) {
921                 _E("MMC not present OR Not ready(%d)", ret);
922                 return APP2EXT_ERROR_MMC_STATUS;
923         }
924         snprintf(mmc_path, FILENAME_MAX - 1, "%s", sdpath);
925         free(sdpath);
926         sync();
927
928         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
929         if (encoded_id == NULL)
930                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
931
932         snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
933                         mmc_path, EXTIMG_DIR, encoded_id);
934         free(encoded_id);
935         if (_is_global(uid)) {
936                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
937                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
938         } else {
939                 tzplatform_set_user(uid);
940                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
941                         tzplatform_getenv(TZ_USER_APP), pkgid);
942                 tzplatform_reset_user();
943         }
944
945         ret = __app2sd_finalize_device_setup(pkgid, loopback_device,
946                 application_path, uid);
947         if (ret) {
948                 _E("failed to finalize device setup");
949                 return ret;
950         }
951
952         sync();
953         return APP2EXT_SUCCESS;
954 }
955
956 int app2sd_usr_pre_app_upgrade(const char *pkgid, GList *dir_list,
957                 int size, uid_t uid)
958 {
959         int ret = APP2EXT_SUCCESS;
960         char app2sd_path[FILENAME_MAX] = { 0, };
961         char loopback_device[FILENAME_MAX] = { 0, };
962         char application_path[FILENAME_MAX] = { 0, };
963         char temp_uid[32] = { 0, };
964         char *sdpath = NULL;
965         char *temp_pkgid = NULL;
966         char *temp_loopback_device = NULL;
967         char *temp_application_path = NULL;
968         char *device_node = NULL;
969         char *encoded_id = NULL;
970         char *temp_encoded_id = NULL;
971         int len = 0;
972         unsigned long long curr_size = 0;
973         FILE *fp = NULL;
974         int reqd_disk_size = size + ceil(size * 0.2);
975
976         /* validate function arguments*/
977         if (pkgid == NULL || dir_list == NULL || size <= 0) {
978                 _E("invalid function arguments");
979                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
980         }
981
982         /* check whether MMC is present or not */
983         ret = _app2sd_check_mmc_status(&sdpath);
984         if (ret) {
985                 _E("MMC not present OR Not ready (%d)", ret);
986                 return APP2EXT_ERROR_MMC_STATUS;
987         }
988         snprintf(app2sd_path, FILENAME_MAX - 1, "%s/%s",
989                         sdpath, EXTIMG_DIR);
990         free(sdpath);
991         sync();
992
993         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
994         if (encoded_id == NULL)
995                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
996
997         if (_is_global(uid)) {
998                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
999                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1000                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1001                         app2sd_path, encoded_id);
1002         } else {
1003                 tzplatform_set_user(uid);
1004                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1005                         tzplatform_getenv(TZ_USER_APP), pkgid);
1006                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1007                         app2sd_path, encoded_id);
1008                 tzplatform_reset_user();
1009         }
1010         free(encoded_id);
1011
1012         /* check app entry is there in sd card or not. */
1013         fp = fopen(loopback_device, "r+");
1014         if (fp == NULL) {
1015                 _E("app entry is not present in SD Card");
1016                 return APP2EXT_ERROR_INVALID_PACKAGE;
1017         }
1018         fclose(fp);
1019
1020         /* get installed app size*/
1021         curr_size = _app2sd_calculate_file_size(loopback_device);
1022         curr_size = (curr_size) / (1024 * 1024);
1023         if (curr_size == 0) {
1024                 _E("app entry is not present in SD Card");
1025                 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
1026         }
1027         if ((int)curr_size < reqd_disk_size) {
1028                 len = strlen(pkgid) + strlen(".new");
1029                 temp_pkgid = calloc(len + 1, sizeof(char));
1030                 if (temp_pkgid == NULL) {
1031                         _E("memory alloc failed");
1032                         return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1033                 }
1034                 snprintf(temp_pkgid, len + 1, "%s.new", pkgid);
1035
1036                 if (_is_global(uid)) {
1037                         len = strlen(tzplatform_getenv(TZ_SYS_RW_APP)) + strlen(temp_pkgid) + 1;
1038                         temp_application_path = calloc(len + 1, sizeof(char));
1039                         if (temp_application_path == NULL) {
1040                                 _E("memory alloc failed");
1041                                 free(temp_pkgid);
1042                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1043                         }
1044                         snprintf(temp_application_path, len + 1, "%s/%s",
1045                                 tzplatform_getenv(TZ_SYS_RW_APP), temp_pkgid);
1046
1047                         temp_encoded_id = _app2sd_get_encoded_name((const char *)temp_pkgid, uid);
1048                         if (temp_encoded_id == NULL) {
1049                                 free(temp_pkgid);
1050                                 free(temp_application_path);
1051                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1052                         }
1053                         len = strlen(app2sd_path) + strlen(temp_encoded_id) + 1;
1054                         temp_loopback_device = calloc(len + 1, sizeof(char));
1055                         if (temp_loopback_device == NULL) {
1056                                 _E("memory alloc failed");
1057                                 free(temp_pkgid);
1058                                 free(temp_application_path);
1059                                 free(temp_encoded_id);
1060                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1061                         }
1062                         snprintf(temp_loopback_device, len + 1, "%s/%s",
1063                                 app2sd_path, temp_encoded_id);
1064                         free(temp_encoded_id);
1065                 } else {
1066                         tzplatform_set_user(uid);
1067                         len = strlen(tzplatform_getenv(TZ_USER_APP)) + strlen(temp_pkgid) + 1;
1068                         temp_application_path = calloc(len + 1, sizeof(char));
1069                         if (temp_application_path == NULL) {
1070                                 _E("memory alloc failed");
1071                                 free(temp_pkgid);
1072                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1073                         }
1074                         snprintf(temp_application_path, len + 1, "%s/%s",
1075                                 tzplatform_getenv(TZ_USER_APP), temp_pkgid);
1076
1077                         temp_encoded_id = _app2sd_get_encoded_name((const char *)temp_pkgid, uid);
1078                         if (temp_encoded_id == NULL) {
1079                                 free(temp_pkgid);
1080                                 free(temp_application_path);
1081                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1082                         }
1083                         snprintf(temp_uid, 32, "%d", uid);
1084                         len = strlen(app2sd_path) + strlen(temp_uid) + strlen(temp_encoded_id) + 2;
1085                         temp_loopback_device = calloc(len + 1, sizeof(char));
1086                         if (temp_loopback_device == NULL) {
1087                                 _E("memory alloc failed");
1088                                 free(temp_pkgid);
1089                                 free(temp_application_path);
1090                                 free(temp_encoded_id);
1091                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1092                         }
1093                         snprintf(temp_loopback_device, len + 1, "%s/%s",
1094                                 app2sd_path, temp_encoded_id);
1095                         free(temp_encoded_id);
1096                         tzplatform_reset_user();
1097                 }
1098                 ret = _app2sd_update_loopback_device_size(pkgid,
1099                         loopback_device, application_path, temp_pkgid,
1100                         temp_loopback_device, temp_application_path,
1101                         reqd_disk_size, dir_list, uid);
1102                 free(temp_pkgid);
1103                 free(temp_application_path);
1104                 free(temp_loopback_device);
1105                 if (APP2EXT_SUCCESS != ret) {
1106                         _E("failed to update loopback device size");
1107                         return ret;
1108                 }
1109         }
1110
1111         /* get the associated device node for SD card applicationer */
1112 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1113         device_node =
1114                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1115 #else
1116         device_node = _app2sd_find_associated_device_node(loopback_device);
1117 #endif
1118         if (NULL == device_node) {
1119                 /* do loopback setup */
1120 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1121                 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1122                         false, uid, &device_node);
1123                 if (ret) {
1124                         _E("dmcrypt open device error");
1125                         return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1126                 }
1127 #else
1128                 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1129                         loopback_device, uid);
1130                 if (device_node == NULL) {
1131                         _E("loopback encryption setup failed");
1132                         return APP2EXT_ERROR_DO_LOSETUP;
1133                 }
1134 #endif
1135
1136                 /* do mounting */
1137                 ret = _app2sd_mount_app_content(application_path, pkgid,
1138                         device_node, MOUNT_TYPE_RW, dir_list,
1139                         APP2SD_PRE_UPGRADE, uid);
1140                 if (ret) {
1141                         _E("mount failed");
1142                         if (device_node) {
1143                                 free(device_node);
1144                                 device_node = NULL;
1145                         }
1146                         return APP2EXT_ERROR_MOUNT_PATH;
1147                 }
1148         } else {
1149                 /* do re-mounting */
1150                 ret = _app2sd_mount_app_content(application_path, pkgid,
1151                         device_node, MOUNT_TYPE_RW_REMOUNT, NULL,
1152                         APP2SD_PRE_UPGRADE, uid);
1153                 if (ret) {
1154                         _E("remount failed");
1155                         if (device_node) {
1156                                 free(device_node);
1157                                 device_node = NULL;
1158                         }
1159                         return APP2EXT_ERROR_MOUNT_PATH;
1160                 }
1161         }
1162
1163         if (device_node) {
1164                 free(device_node);
1165                 device_node = NULL;
1166         }
1167
1168         sync();
1169         return ret;
1170 }
1171
1172 int app2sd_usr_post_app_upgrade(const char *pkgid,
1173                 app2ext_status install_status, uid_t uid)
1174 {
1175         char mmc_path[FILENAME_MAX] = { 0, };
1176         char loopback_device[FILENAME_MAX] = { 0, };
1177         char application_path[FILENAME_MAX] = { 0, };
1178         char *sdpath = NULL;
1179         char *encoded_id = NULL;
1180         int ret = APP2EXT_SUCCESS;
1181         int pkgmgr_ret = 0;
1182
1183         /* validate the function parameter recieved */
1184         if (pkgid == NULL || install_status < APP2EXT_STATUS_FAILED
1185                 || install_status > APP2EXT_STATUS_SUCCESS) {
1186                 _E("invalid func parameters");
1187                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1188         }
1189
1190         /* check whether MMC is present or not */
1191         ret = _app2sd_check_mmc_status(&sdpath);
1192         if (ret) {
1193                 _E("MMC not present OR Not ready (%d)", ret);
1194                 return APP2EXT_ERROR_MMC_STATUS;
1195         }
1196         snprintf(mmc_path, FILENAME_MAX - 1, "%s", sdpath);
1197         free(sdpath);
1198         sync();
1199
1200         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
1201         if (encoded_id == NULL)
1202                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1203
1204         if (_is_global(uid)) {
1205                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1206                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1207                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
1208                         mmc_path, EXTIMG_DIR, encoded_id);
1209         } else {
1210                 tzplatform_set_user(uid);
1211                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1212                         tzplatform_getenv(TZ_USER_APP), pkgid);
1213                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
1214                         mmc_path, EXTIMG_DIR, encoded_id);
1215                 tzplatform_reset_user();
1216         }
1217         free(encoded_id);
1218
1219         ret = __app2sd_finalize_device_setup(pkgid, loopback_device,
1220                 application_path, uid);
1221         if (ret) {
1222                 _E("failed to finalize device setup");
1223                 return ret;
1224         }
1225
1226         pkgmgr_ret = pkgmgrinfo_pkginfo_set_usr_installed_storage(pkgid,
1227                 INSTALL_EXTERNAL, loopback_device, uid);
1228         if (pkgmgr_ret < 0) {
1229                 _E("fail to update installed location " \
1230                         "to db[%s, %d] of uid(%d), pkgmgr ret(%d)",
1231                         pkgid, INSTALL_EXTERNAL, uid, pkgmgr_ret);
1232                 return APP2EXT_ERROR_PKGMGR_ERROR;
1233         }
1234
1235         sync();
1236         return ret;
1237 }
1238
1239 int app2sd_usr_force_clean(const char *pkgid, uid_t uid)
1240 {
1241         char mmc_path[FILENAME_MAX] = { 0, };
1242         char loopback_device[FILENAME_MAX] = { 0, };
1243         char application_path[FILENAME_MAX] = { 0, };
1244         char *sdpath = NULL;
1245         char *encoded_id = NULL;
1246         int ret = APP2EXT_SUCCESS;
1247
1248         /* validate the function parameter recieved */
1249         if (pkgid == NULL) {
1250                 _E("invalid func parameters");
1251                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1252         }
1253
1254         /* check whether MMC is present or not */
1255         ret = _app2sd_check_mmc_status(&sdpath);
1256         if (ret) {
1257                 _E("MMC not present OR Not ready (%d)", ret);
1258                 return APP2EXT_ERROR_MMC_STATUS;
1259         }
1260         snprintf(mmc_path, FILENAME_MAX - 1, "%s", sdpath);
1261         free(sdpath);
1262         sync();
1263
1264         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
1265         if (encoded_id == NULL)
1266                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1267
1268         if (_is_global(uid)) {
1269                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1270                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1271                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
1272                         mmc_path, EXTIMG_DIR, encoded_id);
1273         } else {
1274                 tzplatform_set_user(uid);
1275                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1276                         tzplatform_getenv(TZ_USER_APP), pkgid);
1277                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
1278                         mmc_path, EXTIMG_DIR, encoded_id);
1279                 tzplatform_reset_user();
1280         }
1281         free(encoded_id);
1282
1283         ret = _app2sd_force_clean(pkgid, application_path, loopback_device, uid);
1284
1285         sync();
1286         return ret;
1287 }
1288
1289 int app2sd_enable_full_pkg(void)
1290 {
1291         int ret = APP2EXT_SUCCESS;
1292         char buf[FILENAME_MAX] = { 0, };
1293         char app2sd_path[FILENAME_MAX] = { 0, };
1294         char loopback_device[FILENAME_MAX] = { 0, };
1295         char *sdpath = NULL;
1296         char *pkgid = NULL;
1297         DIR *dir = NULL;
1298         struct dirent *entry = NULL;
1299         uid_t uid = 0;
1300
1301         /* check whether MMC is present or not */
1302         ret = _app2sd_check_mmc_status(&sdpath);
1303         if (ret) {
1304                 _E("MMC not present OR Not ready (%d)", ret);
1305                 return APP2EXT_ERROR_MMC_STATUS;
1306         }
1307         snprintf(app2sd_path, FILENAME_MAX - 1, "%s/%s",
1308                         sdpath, EXTIMG_DIR);
1309         free(sdpath);
1310
1311         dir = opendir(app2sd_path);
1312         if (!dir) {
1313                 strerror_r(errno, buf, sizeof(buf));
1314                 _E("failed to opendir (%s)", buf);
1315                 return APP2EXT_ERROR_OPEN_DIR;
1316         }
1317
1318         ret = _app2sd_initialize_db();
1319         if (ret) {
1320                 _E("app2sd db initialize failed");
1321                 closedir(dir);
1322                 return APP2EXT_ERROR_SQLITE_REGISTRY;
1323         }
1324
1325         while ((entry = readdir(dir)) != NULL) {
1326                 if (strcmp(entry->d_name, ".") == 0 ||
1327                         strcmp(entry->d_name, "..") == 0)
1328                         continue;
1329                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1330                         app2sd_path, entry->d_name);
1331                 ret = _app2sd_get_info_from_db(loopback_device,
1332                         &pkgid, &uid);
1333                 if (ret) {
1334                         _W("failed to get info from db, continue");
1335                         continue;
1336                 }
1337                 if (pkgid) {
1338                         _D("pkgid(%s), uid(%d)", pkgid, uid);
1339                         ret = app2sd_usr_on_demand_setup_init(pkgid, uid);
1340                         if (ret) {
1341                                 _E("error(%d)", ret);
1342                                 continue;
1343                         }
1344                         free(pkgid);
1345                         pkgid = NULL;
1346                 }
1347         }
1348
1349         if (pkgid) {
1350                 free(pkgid);
1351                 pkgid = NULL;
1352         }
1353         closedir(dir);
1354
1355         sync();
1356         return ret;
1357 }
1358
1359 static int _app2sd_info_cb_func(const char *pkgid, uid_t uid)
1360 {
1361         int ret = APP2EXT_SUCCESS;
1362
1363         if (pkgid) {
1364                 _D("pkgid(%s), uid(%d)", pkgid, uid);
1365                 ret = app2sd_usr_on_demand_setup_exit(pkgid, uid);
1366                 if (ret)
1367                         _E("error(%d)", ret);
1368         }
1369
1370         return ret;
1371 }
1372
1373 int app2sd_disable_full_pkg(void)
1374 {
1375         int ret = APP2EXT_SUCCESS;
1376
1377         ret = _app2sd_initialize_db();
1378         if (ret) {
1379                 _E("app2sd db initialize failed");
1380                 return APP2EXT_ERROR_SQLITE_REGISTRY;
1381         }
1382
1383         ret = _app2sd_get_foreach_info_from_db((app2sd_info_cb)_app2sd_info_cb_func);
1384         if (ret)
1385                 _E("disable full pkg error(%d)", ret);
1386
1387         sync();
1388         return ret;
1389 }
1390
1391 static int _app2sd_migrate_legacy_image(const char *pkgid, const char *passwd,
1392                 const char *mmc_path, uid_t uid)
1393 {
1394         int ret = 0;
1395         char *device_node = NULL;
1396         char *encoded_id = NULL;
1397         char new_image[FILENAME_MAX] = { 0, };
1398         char legacy_image[FILENAME_MAX] = { 0, };
1399         char application_path[FILENAME_MAX] = { 0, };
1400         uid_t default_uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
1401
1402         if (_is_global(uid)) {
1403                 snprintf(application_path, sizeof(application_path), "%s/%s",
1404                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1405         } else {
1406                 tzplatform_set_user(uid);
1407                 snprintf(application_path, sizeof(application_path), "%s/%s",
1408                         tzplatform_getenv(TZ_USER_APP), pkgid);
1409                 tzplatform_reset_user();
1410         }
1411
1412         /* make the information and insert to DB */
1413         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
1414         if (encoded_id == NULL)
1415                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1416         snprintf(new_image, sizeof(new_image), "%s/%s",
1417                 mmc_path, encoded_id);
1418         free(encoded_id);
1419
1420         snprintf(legacy_image, sizeof(legacy_image), "%s/%s",
1421                 mmc_path, pkgid);
1422
1423         ret = _app2sd_rename_dir(legacy_image, new_image);
1424         if (ret) {
1425                 _E("unable to rename (%s)", legacy_image);
1426                 return APP2EXT_ERROR_ACCESS_FILE;
1427         }
1428
1429         ret = pkgmgrinfo_pkginfo_set_usr_installed_storage(pkgid,
1430                 INSTALL_EXTERNAL, new_image, uid);
1431         if (ret < 0) {
1432                 _E("fail to update installed location " \
1433                         "to db[%s, %d] of uid(%d), ret(%d)",
1434                         pkgid, INSTALL_EXTERNAL, uid, ret);
1435                 return APP2EXT_ERROR_PKGMGR_ERROR;
1436         }
1437
1438         /* update app2sd db */
1439         if (_is_global(uid)) {
1440                 ret = _app2sd_remove_info_from_db(pkgid, default_uid);
1441                 if (ret) {
1442                         _E("cannot remove info from db");
1443                         return APP2EXT_ERROR_SQLITE_REGISTRY;
1444                 }
1445         }
1446         ret = _app2sd_set_info_in_db(pkgid, passwd, new_image, uid);
1447         if (ret) {
1448                 _E("unable to save info");
1449                 return APP2EXT_ERROR_SQLITE_REGISTRY;
1450         }
1451
1452 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1453         device_node =
1454                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1455         if (device_node) {
1456                 _E("device_node(%s_%d) already associated", pkgid, uid);
1457                 return APP2EXT_ERROR_ALREADY_MOUNTED;
1458         }
1459
1460         ret = _app2sd_dmcrypt_open_device(pkgid, new_image, false,
1461                 uid, &device_node);
1462         if (ret) {
1463                 _E("dmcrypt open device error(%d)", ret);
1464                 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1465         }
1466 #else
1467         result = (char *)_app2sd_find_associated_device(new_image);
1468         /* process the string */
1469         if ((result != NULL) && strstr(result, "/dev") != NULL) {
1470                 _E("already associated");
1471                 free(result);
1472                 result = NULL;
1473                 return APP2EXT_ERROR_ALREADY_MOUNTED;
1474         }
1475
1476         /* do loopback setup */
1477         device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1478                 new_image, uid);
1479         if (device_node == NULL) {
1480                 _E("loopback encryption setup failed");
1481                 return APP2EXT_ERROR_DO_LOSETUP;
1482         }
1483 #endif
1484
1485         /* do mounting */
1486         ret = _app2sd_mount_app_content(application_path, pkgid,
1487                 device_node, MOUNT_TYPE_RW, NULL,
1488                 APP2SD_MIGRATE_LEGACY, uid);
1489         if (ret) {
1490                 _E("mount failed");
1491                 if (device_node) {
1492                         free(device_node);
1493                         device_node = NULL;
1494                 }
1495                 return APP2EXT_ERROR_MOUNT_PATH;
1496         }
1497
1498         if (device_node) {
1499                 free(device_node);
1500                 device_node = NULL;
1501         }
1502
1503         sync();
1504         return APP2EXT_SUCCESS;
1505 }
1506
1507 int app2sd_pre_migrate_legacy(const char *pkgid, uid_t uid)
1508 {
1509         int ret = APP2EXT_SUCCESS;
1510         char *passwd = NULL;
1511         char *sdpath = NULL;
1512         char mmc_path[FILENAME_MAX] = { 0, };
1513         char file_path[FILENAME_MAX] = { 0, };
1514         uid_t default_uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
1515
1516         /* check whether MMC is present or not */
1517         ret = _app2sd_check_mmc_status(&sdpath);
1518         if (ret) {
1519                 _E("MMC not present OR Not ready (%d)", ret);
1520                 return APP2EXT_ERROR_MMC_STATUS;
1521         }
1522         snprintf(mmc_path, sizeof(mmc_path), "%s/%s", sdpath, EXTIMG_DIR);
1523         free(sdpath);
1524         snprintf(file_path, sizeof(file_path), "%s/%s", mmc_path, pkgid);
1525
1526         ret = _app2sd_initialize_db();
1527         if (ret) {
1528                 _E("app2sd db initialize failed");
1529                 return APP2EXT_ERROR_SQLITE_REGISTRY;
1530         }
1531
1532         /* In the upgrade script, the information
1533          * of legacy image are filled with default user-id,
1534          * pkgid(from old db), passwd(from old db) and
1535          * empty filename in app2sd db. */
1536         if (!_app2sd_get_filename_from_db(pkgid, default_uid)) {
1537                 passwd = _app2sd_get_password_from_db(pkgid, default_uid);
1538                 if (passwd) {
1539                         ret = _app2sd_migrate_legacy_image(pkgid, passwd,
1540                                 mmc_path, uid);
1541                         free(passwd);
1542                         passwd = NULL;
1543                 } else {
1544                         _E("invalid package info");
1545                         return APP2EXT_ERROR_INVALID_PACKAGE;
1546                 }
1547         } else {
1548                 _W("same pkg exists, remove legacy file (%s)", file_path);
1549                 ret = remove(file_path);
1550                 if (ret < 0)
1551                         _E("failed to remove, errno(%d)", errno);
1552                 return APP2EXT_ERROR_PKG_EXISTS;
1553         }
1554
1555         return ret;
1556 }
1557
1558 int app2sd_post_migrate_legacy(const char *pkgid, uid_t uid)
1559 {
1560         int ret = APP2EXT_SUCCESS;
1561         char *sdpath = NULL;
1562         char *encoded_id = NULL;
1563         char mmc_path[FILENAME_MAX] = { 0, };
1564         char application_path[FILENAME_MAX] = { 0, };
1565         char loopback_device[FILENAME_MAX] = { 0, };
1566
1567         /* check whether MMC is present or not */
1568         ret = _app2sd_check_mmc_status(&sdpath);
1569         if (ret) {
1570                 _E("MMC not present OR Not ready (%d)", ret);
1571                 return APP2EXT_ERROR_MMC_STATUS;
1572         }
1573         snprintf(mmc_path, sizeof(mmc_path), "%s/%s",
1574                 sdpath, EXTIMG_DIR);
1575         free(sdpath);
1576
1577         if (_is_global(uid)) {
1578                 snprintf(application_path, sizeof(application_path), "%s/%s",
1579                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1580         } else {
1581                 tzplatform_set_user(uid);
1582                 snprintf(application_path, sizeof(application_path), "%s/%s",
1583                         tzplatform_getenv(TZ_USER_APP), pkgid);
1584                 tzplatform_reset_user();
1585         }
1586
1587         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
1588         if (encoded_id == NULL) {
1589                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1590         }
1591         snprintf(loopback_device, sizeof(loopback_device), "%s/%s",
1592                 mmc_path, encoded_id);
1593         free(encoded_id);
1594
1595         ret = __app2sd_finalize_device_setup(pkgid, loopback_device,
1596                 application_path, uid);
1597         if (ret) {
1598                 _E("failed to finalize device setup");
1599                 return ret;
1600         }
1601
1602         return APP2EXT_SUCCESS;
1603 }
1604
1605 /* this function is called when sdcard is inserted */
1606 int app2sd_migrate_legacy_all(void)
1607 {
1608         int ret = APP2EXT_SUCCESS;
1609         int rc = 0;
1610         char buf[FILENAME_MAX] = { 0, };
1611         char app2sd_path[FILENAME_MAX] = { 0, };
1612         char loopback_device[FILENAME_MAX] = { 0, };
1613         char *sdpath = NULL;
1614         DIR *dir = NULL;
1615         struct dirent entry;
1616         struct dirent *result = NULL;
1617         uid_t default_uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
1618         pkgmgr_client *pc;
1619
1620         /* check whether MMC is present or not */
1621         ret = _app2sd_check_mmc_status(&sdpath);
1622         if (ret) {
1623                 _E("MMC not present OR Not ready (%d)", ret);
1624                 return APP2EXT_ERROR_MMC_STATUS;
1625         }
1626         snprintf(app2sd_path, sizeof(app2sd_path), "%s/%s",
1627                 sdpath, EXTIMG_DIR);
1628         free(sdpath);
1629
1630         dir = opendir(app2sd_path);
1631         if (!dir) {
1632                 strerror_r(errno, buf, sizeof(buf));
1633                 _E("failed to opendir (%s)", buf);
1634                 return APP2EXT_ERROR_OPEN_DIR;
1635         }
1636
1637         pc = pkgmgr_client_new(PC_REQUEST);
1638         if (pc == NULL) {
1639                 _E("failed to create pkgmgr client");
1640                 return APP2EXT_ERROR_PKGMGR_ERROR;
1641         }
1642
1643         for (rc = readdir_r(dir, &entry, &result);
1644                 rc == 0 && result != NULL;
1645                 rc = readdir_r(dir, &entry, &result)) {
1646                 if (strcmp(entry.d_name, ".") == 0 ||
1647                         strcmp(entry.d_name, "..") == 0)
1648                         continue;
1649                 snprintf(loopback_device, sizeof(loopback_device), "%s/%s",
1650                         app2sd_path, entry.d_name);
1651                 /* check losetup image */
1652                 if (_app2sd_check_is_luks_device(loopback_device) == 0) {
1653                         /* call installer backend
1654                          * to change access-rule and broadcast this update */
1655                         ret = pkgmgr_client_usr_migrate_external_image(pc,
1656                                 entry.d_name, default_uid);
1657                         if (ret < 0)
1658                                 _E("failed to request migration, ret(%d)", ret);
1659                 }
1660         }
1661
1662         pkgmgr_client_free(pc);
1663         closedir(dir);
1664
1665         return ret;
1666 }
1667