dmcrypt feature
[platform/core/appfw/app2sd.git] / plugin / app2sd / src / 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
26 #include "app2sd_internals.h"
27
28 static int __app2sd_create_app2sd_directories(uid_t uid)
29 {
30         int ret = 0;
31         mode_t mode = DIR_PERMS;
32
33         ret = mkdir(APP2SD_PATH, mode);
34         if (ret) {
35                 if (errno != EEXIST) {
36                         _E("create directory failed," \
37                                 " error no is (%d)", errno);
38                         return APP2EXT_ERROR_CREATE_DIRECTORY;
39                 }
40         }
41
42         return APP2EXT_SUCCESS;
43 }
44
45 int app2sd_usr_pre_app_install(const char *pkgid, GList *dir_list, int size, uid_t uid)
46 {
47         int ret = 0;
48         int free_mmc_mem = 0;
49         char *device_node = NULL;
50 #if !defined(_APPFW_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
51         char *devi = NULL;
52 #endif
53         char *result = NULL;
54         char application_path[FILENAME_MAX] = { 0, };
55         char loopback_device[FILENAME_MAX] = { 0, };
56         char *encoded_id = NULL;
57         int reqd_disk_size = size + ceil(size * 0.2);
58
59         /* validate the function parameter recieved */
60         if (pkgid == NULL || dir_list == NULL || size <= 0) {
61                 _E("invalid function arguments");
62                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
63         }
64
65         /* check whether MMC is present or not */
66         ret = _app2sd_check_mmc_status();
67         if (ret) {
68                 _E("MMC not preset OR Not ready (%d)", ret);
69                 return APP2EXT_ERROR_MMC_STATUS;
70         }
71
72         /* find available free memory in the MMC card */
73         ret = _app2sd_get_available_free_memory(MMC_PATH, &free_mmc_mem);
74         if (ret) {
75                 _E("unable to get available free memory in MMC (%d)",
76                         ret);
77                 return APP2EXT_ERROR_MMC_STATUS;
78         }
79         _D("size details for application installation:" \
80                 " size=(%d)MB, reqd_disk_size=(%d)MB, free_mmc_size=(%d)MB",
81                 size, reqd_disk_size, free_mmc_mem);
82
83         /* if avaialalbe free memory in MMC is less than required size + 5MB,
84          * return error
85          */
86         if ((reqd_disk_size + PKG_BUF_SIZE + MEM_BUF_SIZE) > free_mmc_mem) {
87                 _E("insufficient memory in MMC for"
88                         " application installation (%d)", ret);
89                 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
90         }
91
92         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
93         if (encoded_id == NULL)
94                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
95
96         if (_is_global(uid)) {
97                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
98                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
99                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
100                         APP2SD_PATH, encoded_id);
101         } else {
102                 tzplatform_set_user(uid);
103                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
104                         tzplatform_getenv(TZ_USER_APP), pkgid);
105                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
106                         APP2SD_PATH, encoded_id);
107                 tzplatform_reset_user();
108         }
109         free(encoded_id);
110
111         ret = __app2sd_create_app2sd_directories(uid);
112         if (ret) {
113                 _E("failed to create app2sd dirs");
114                 return ret;
115         }
116
117         /* check same loopback_device existence */
118         result = (char *)_app2sd_find_associated_device(loopback_device);
119         if (result != NULL) {
120                 _E("there is same associated File (%s)", loopback_device);
121                 return APP2EXT_ERROR_SAME_LOOPBACK_DEVICE_EXISTS;
122         }
123
124         /* create a loopback device */
125         ret = _app2sd_create_loopback_device(pkgid, loopback_device,
126                 (reqd_disk_size + PKG_BUF_SIZE));
127
128 #ifdef _APPFW_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
129         ret = _app2sd_dmcrypt_setup_device(pkgid, loopback_device, false, uid);
130         if (ret) {
131                 _E("dmcrypt setup device error");
132                 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
133         }
134
135         ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
136                 false, uid, &device_node);
137         if (ret) {
138                 _E("dmcrypt open device error");
139                 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
140         }
141 #else
142         /* perform loopback encryption setup */
143         device_node = _app2sd_do_loopback_encryption_setup(pkgid,
144                 loopback_device, uid);
145         if (!device_node) {
146                 _E("loopback encryption setup failed");
147                 _app2sd_delete_loopback_device(loopback_device);
148                 return APP2EXT_ERROR_DO_LOSETUP;
149         }
150
151         /* check whether loopback device is associated
152          * with device node or not
153          */
154         devi = _app2sd_find_associated_device_node(loopback_device);
155         if (devi == NULL) {
156                 _E("finding associated device node failed");
157                 ret = APP2EXT_ERROR_DO_LOSETUP;
158                 goto FINISH_OFF;
159         }
160 #endif
161
162         /* format the loopback file system */
163         ret = _app2sd_create_file_system(device_node);
164         if (ret) {
165                 _E("creating FS failed failed");
166                 ret = APP2EXT_ERROR_CREATE_FS;
167                 goto FINISH_OFF;
168         }
169
170         /* mount the loopback encrypted pseudo device on application
171          * installation path as with Read Write permission
172          */
173         ret = _app2sd_mount_app_content(application_path, pkgid,
174                 device_node, MOUNT_TYPE_RW, dir_list,
175                 APP2SD_PRE_INSTALL, uid);
176         if (ret) {
177                 _E("mounting dev path to app install path failed");
178                 ret = APP2EXT_ERROR_MOUNT_PATH;
179                 goto FINISH_OFF;
180         }
181
182         /* Success */
183         ret = APP2EXT_SUCCESS;
184         goto END;
185
186 FINISH_OFF:
187         if (device_node) {
188 #ifdef _APPFW_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
189         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
190         if (ret)
191                 _E("close dmcrypt device error(%d)", ret);
192         _app2sd_delete_loopback_device(loopback_device);
193 #else
194                 result = _app2sd_detach_loop_device(device_node);
195                 if (result) {
196                         free(result);
197                         result = NULL;
198                 }
199                 _app2sd_delete_loopback_device(loopback_device);
200 #endif
201         }
202
203 END:
204         if (device_node) {
205                 free(device_node);
206                 device_node = NULL;
207         }
208
209 #if !defined(_APPFW_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
210         if (devi) {
211                 free(devi);
212                 devi = NULL;
213         }
214 #endif
215
216         return ret;
217 }
218
219 int app2sd_usr_post_app_install(const char *pkgid,
220                 app2ext_status install_status, uid_t uid)
221 {
222         char *device_name = NULL;
223         char application_path[FILENAME_MAX] = { 0, };
224         char loopback_device[FILENAME_MAX] = { 0, };
225         char *encoded_id = NULL;
226         int ret = APP2EXT_SUCCESS;
227         int pkgmgr_ret = 0;
228
229         /* validate the function parameter recieved */
230         if (pkgid == NULL || install_status < APP2EXT_STATUS_FAILED
231                 || install_status > APP2EXT_STATUS_SUCCESS) {
232                 _E("invalid func parameters");
233                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
234         }
235
236         /* check whether MMC is present or not */
237         ret = _app2sd_check_mmc_status();
238         if (ret) {
239                 _E("MMC not present OR Not ready (%d)", ret);
240                 return APP2EXT_ERROR_MMC_STATUS;
241         }
242         sync();
243
244         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
245         if (encoded_id == NULL)
246                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
247
248         if (_is_global(uid)) {
249                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
250                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
251                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
252                         APP2SD_PATH, encoded_id);
253         } else {
254                 tzplatform_set_user(uid);
255                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
256                         tzplatform_getenv(TZ_USER_APP), pkgid);
257                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
258                         APP2SD_PATH, encoded_id);
259                 tzplatform_reset_user();
260         }
261         free(encoded_id);
262
263         /* get the associated device node for SD card applicationer */
264 #ifdef _APPFW_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
265         device_name =
266                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
267         if (!device_name)
268                 return APP2EXT_ERROR_FIND_ASSOCIATED_DMCRYPT_DEVICE_NODE;
269 #else
270         device_name = _app2sd_find_associated_device_node(loopback_device);
271         if (NULL == device_name)
272                 return APP2EXT_ERROR_FIND_ASSOCIATED_DEVICE_NODE;
273 #endif
274
275         ret = _app2sd_unmount_app_content(application_path);
276         if (ret) {
277                 if (device_name) {
278                         free(device_name);
279                         device_name = NULL;
280                 }
281                 _E("unable to unmount the app content (%d)", ret);
282                 return APP2EXT_ERROR_UNMOUNT;
283         }
284
285 #ifdef _APPFW_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
286         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
287         if (ret) {
288                 if (device_name) {
289                         free(device_name);
290                         device_name = NULL;
291                 }
292                 _E("close dmcrypt device error(%d)", ret);
293                 return ret;
294         }
295 #else
296         ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
297         if (ret) {
298                 if (device_name) {
299                         free(device_name);
300                         device_name = NULL;
301                 }
302                 _E("unable to detach the loopback encryption setup" \
303                         " for the application");
304                 return APP2EXT_ERROR_UNMOUNT;
305         }
306 #endif
307
308         if (device_name) {
309                 free(device_name);
310                 device_name = NULL;
311         }
312
313         /* take appropriate action based on
314          * installation status of application package
315          */
316         if (install_status == APP2EXT_STATUS_FAILED) {
317                 /* delete the loopback device from the SD card */
318                 ret = _app2sd_delete_loopback_device(loopback_device);
319                 if (ret) {
320                         _E("unable to delete the loopback device from the SD Card");
321                         return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
322                 }
323                 ret = _app2sd_remove_info_from_db(pkgid, uid);
324                 if (ret)
325                         _E("unable to delete info");
326
327                 ret = _app2sd_delete_directory(application_path);
328                 if (ret)
329                         _E("unable to delete the directory (%s)", application_path);
330         } else {
331                 /* if the status is success, then update installed storage
332                  * to pkgmgr_parser db
333                  */
334                 pkgmgr_ret = pkgmgrinfo_pkginfo_set_usr_installed_storage(pkgid,
335                         INSTALL_EXTERNAL, uid);
336                 if (pkgmgr_ret < 0) {
337                         _E("fail to update installed location " \
338                                 "to db[%s, %d] of uid(%d), pkgmgr ret(%d)",
339                                 pkgid, INSTALL_EXTERNAL, uid, pkgmgr_ret);
340                         return APP2EXT_ERROR_PKGMGR_ERROR;
341                 }
342         }
343
344         return ret;
345 }
346
347 int app2sd_usr_on_demand_setup_init(const char *pkgid, uid_t uid)
348 {
349         int ret = APP2EXT_SUCCESS;
350         char application_path[FILENAME_MAX] = { 0, };
351         char loopback_device[FILENAME_MAX] = { 0, };
352         char *encoded_id = NULL;
353         char *device_node = NULL;
354 #if !defined(_APPFW_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
355         char *result = NULL;
356 #endif
357         FILE *fp = NULL;
358
359         /* validate the function parameter recieved */
360         if (pkgid == NULL) {
361                 _E("invalid function arguments to app launch setup");
362                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
363         }
364
365         /* check whether MMC is present or not */
366         ret = _app2sd_check_mmc_status();
367         if (ret) {
368                 _E("MMC not preset OR Not ready (%d)", ret);
369                 return APP2EXT_ERROR_MMC_STATUS;
370         }
371
372         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
373         if (encoded_id == NULL)
374                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
375
376         /* check app entry is there in sd card or not. */
377         if (_is_global(uid)) {
378                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
379                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
380                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
381                         APP2SD_PATH, encoded_id);
382         } else {
383                 tzplatform_set_user(uid);
384                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
385                         tzplatform_getenv(TZ_USER_APP), pkgid);
386                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
387                         APP2SD_PATH, encoded_id);
388                 tzplatform_reset_user();
389         }
390         free(encoded_id);
391
392         fp = fopen(loopback_device, "r+");
393         if (fp == NULL) {
394                 _E("app entry is not present in SD Card");
395                 return APP2EXT_ERROR_INVALID_PACKAGE;
396         }
397         fclose(fp);
398
399 #ifdef _APPFW_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
400         device_node =
401                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
402         if (device_node) {
403                 _E("device_node(%s_%d) already associated", pkgid, uid);
404                 return APP2EXT_ERROR_ALREADY_MOUNTED;
405         }
406
407         ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
408                 false, uid, &device_node);
409         if (ret) {
410                 _E("dmcrypt open device error(%d)", ret);
411                 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
412         }
413 #else
414         result = (char *)_app2sd_find_associated_device(loopback_device);
415         /* process the string */
416         if ((result != NULL) && strstr(result, "/dev") != NULL) {
417                 _E("already associated");
418                 free(result);
419                 result = NULL;
420                 return APP2EXT_ERROR_ALREADY_MOUNTED;
421         }
422
423         /* do loopback setup */
424         device_node = _app2sd_do_loopback_encryption_setup(pkgid,
425                 loopback_device, uid);
426         if (device_node == NULL) {
427                 _E("loopback encryption setup failed");
428                 return APP2EXT_ERROR_DO_LOSETUP;
429         }
430 #endif
431
432         /* do mounting */
433         ret = _app2sd_mount_app_content(application_path, pkgid,
434                 device_node, MOUNT_TYPE_RD, NULL, APP2SD_APP_LAUNCH, uid);
435         if (ret) {
436                 _E("mount failed");
437                 if (device_node) {
438                         free(device_node);
439                         device_node = NULL;
440                 }
441                 return APP2EXT_ERROR_MOUNT_PATH;
442         }
443
444         if (device_node) {
445                 free(device_node);
446                 device_node = NULL;
447         }
448
449         return ret;
450 }
451
452 int app2sd_usr_on_demand_setup_exit(const char *pkgid, uid_t uid)
453 {
454         int ret = APP2EXT_SUCCESS;
455         char application_path[FILENAME_MAX] = { 0, };
456         char loopback_device[FILENAME_MAX] = { 0, };
457         char *encoded_id = NULL;
458         FILE *fp = NULL;
459
460         /* validate the function parameter recieved */
461         if (pkgid == NULL) {
462                 _E("invalid function arguments to app launch setup");
463                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
464         }
465
466         /* check whether MMC is present or not */
467         ret = _app2sd_check_mmc_status();
468         if (ret) {
469                 _E("MMC not preset OR Not ready (%d)", ret);
470                 return APP2EXT_ERROR_MMC_STATUS;
471         }
472
473         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
474         if (encoded_id == NULL)
475                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
476
477         /* check app entry is there in sd card or not. */
478         if (_is_global(uid)) {
479                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
480                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
481                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
482                         APP2SD_PATH, encoded_id);
483         } else {
484                 tzplatform_set_user(uid);
485                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
486                         tzplatform_getenv(TZ_USER_APP), pkgid);
487                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
488                         APP2SD_PATH, encoded_id);
489                 tzplatform_reset_user();
490         }
491         free(encoded_id);
492
493         fp = fopen(loopback_device, "r+");
494         if (fp == NULL) {
495                 _E("app entry is not present in SD Card");
496                 return APP2EXT_ERROR_INVALID_PACKAGE;
497         }
498         fclose(fp);
499
500         ret = _app2sd_unmount_app_content(application_path);
501         if (ret) {
502                 _E("unable to unmount the SD application");
503                 return APP2EXT_ERROR_UNMOUNT;
504         }
505
506 #ifdef _APPFW_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
507         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
508         if (ret)
509                 _E("close dmcrypt device error(%d)", ret);
510 #else
511         ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
512         if (ret) {
513                 _E("unable to remove loopback setup");
514                 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
515         }
516 #endif
517
518         return ret;
519 }
520
521 int app2sd_usr_pre_app_uninstall(const char *pkgid, uid_t uid)
522 {
523         int ret = APP2EXT_SUCCESS;
524         char application_path[FILENAME_MAX] = { 0, };
525         char loopback_device[FILENAME_MAX] = { 0, };
526         char *encoded_id = NULL;
527         char *device_node = NULL;
528         FILE *fp = NULL;
529
530         /* validate the function parameter recieved */
531         if (pkgid == NULL) {
532                 _E("invalid function arguments to app launch setup");
533                 ret = APP2EXT_ERROR_INVALID_ARGUMENTS;
534                 goto END;
535         }
536
537         /* check whether MMC is present or not */
538         ret = _app2sd_check_mmc_status();
539         if (ret) {
540                 _E("MMC not preset OR Not ready (%d)", ret);
541                 ret = APP2EXT_ERROR_MMC_STATUS;
542                 goto END;
543         }
544
545         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
546         if (encoded_id == NULL)
547                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
548
549         if (_is_global(uid)) {
550                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
551                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
552                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
553                         APP2SD_PATH, encoded_id);
554         } else {
555                 tzplatform_set_user(uid);
556                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
557                         tzplatform_getenv(TZ_USER_APP), pkgid);
558                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
559                         APP2SD_PATH, encoded_id);
560                 tzplatform_reset_user();
561         }
562         free(encoded_id);
563
564         /* check app entry is there in sd card or not. */
565         fp = fopen(loopback_device, "r+");
566         if (fp == NULL) {
567                 _E("app entry is not present in SD Card");
568                 ret = APP2EXT_ERROR_INVALID_PACKAGE;
569                 goto END;
570         }
571         fclose(fp);
572
573         /* get the associated device node for SD card applicationer */
574 #ifdef _APPFW_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
575         device_node =
576                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
577 #else
578         device_node = _app2sd_find_associated_device_node(loopback_device);
579 #endif
580         if (NULL == device_node) {
581                 /* do loopback setup */
582 #ifdef _APPFW_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
583                 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
584                         false, uid, &device_node);
585                 if (ret) {
586                         _E("dmcrypt open device error(%d)", ret);
587                         return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
588                 }
589 #else
590                 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
591                         loopback_device, uid);
592                 if (device_node == NULL) {
593                         _E("loopback encryption setup failed");
594                         ret = APP2EXT_ERROR_DO_LOSETUP;
595                         goto END;
596                 }
597 #endif
598                 /* do mounting */
599                 ret = _app2sd_mount_app_content(application_path, pkgid,
600                         device_node, MOUNT_TYPE_RW, NULL,
601                         APP2SD_PRE_UNINSTALL, uid);
602                 if (ret) {
603                         _E("mount failed");
604                         if (device_node) {
605                                 free(device_node);
606                                 device_node = NULL;
607                         }
608                         ret = APP2EXT_ERROR_MOUNT_PATH;
609                         goto END;
610                 }
611         } else {
612                 /* do re-mounting */
613                 ret = _app2sd_mount_app_content(application_path, pkgid,
614                         device_node, MOUNT_TYPE_RW_REMOUNT, NULL,
615                         APP2SD_PRE_UNINSTALL, uid);
616                 if (ret) {
617                         _E("remount failed");
618                         if (device_node) {
619                                 free(device_node);
620                                 device_node = NULL;
621                         }
622                         ret = APP2EXT_ERROR_MOUNT_PATH;
623                         goto END;
624                 }
625         }
626         if (device_node) {
627                 free(device_node);
628                 device_node = NULL;
629         }
630
631 END:
632         return ret;
633 }
634
635 int app2sd_usr_post_app_uninstall(const char *pkgid, uid_t uid)
636 {
637         char application_path[FILENAME_MAX] = { 0, };
638         char loopback_device[FILENAME_MAX] = { 0, };
639         char *encoded_id = NULL;
640         int ret = APP2EXT_SUCCESS;
641
642         /* validate the function parameter recieved */
643         if (pkgid == NULL) {
644                 _E("invalid function arguments");
645                 ret = APP2EXT_ERROR_INVALID_ARGUMENTS;
646                 goto END;
647         }
648
649         /* check whether MMC is present or not */
650         ret = _app2sd_check_mmc_status();
651         if (ret) {
652                 _E("MMC not preset OR Not ready (%d)", ret);
653                 ret = APP2EXT_ERROR_MMC_STATUS;
654                 goto END;
655         }
656
657         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
658         if (encoded_id == NULL)
659                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
660
661         if (_is_global(uid)) {
662                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
663                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
664                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
665                         APP2SD_PATH, encoded_id);
666         } else {
667                 tzplatform_set_user(uid);
668                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
669                         tzplatform_getenv(TZ_USER_APP), pkgid);
670                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
671                         APP2SD_PATH, encoded_id);
672                 tzplatform_reset_user();
673         }
674         free(encoded_id);
675
676         /* unmount the loopback encrypted pseudo device from
677          * the application installation path
678          */
679         ret = _app2sd_unmount_app_content(application_path);
680         if (ret) {
681                 _E("unable to unmount the app content (%d)", ret);
682                 ret = APP2EXT_ERROR_UNMOUNT;
683                 goto END;
684         }
685         /* detach the loopback encryption setup for the application */
686 #ifdef _APPFW_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
687         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
688         if (ret) {
689                 _E("close dmcrypt device error(%d)", ret);
690                 goto END;
691         }
692 #else
693         ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
694         if (ret) {
695                 _E("unable to Detach the loopback encryption setup" \
696                         " for the application");
697                 ret = APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
698                 goto END;
699         }
700 #endif
701
702         /* delete the loopback device from the SD card */
703         ret = _app2sd_delete_loopback_device(loopback_device);
704         if (ret) {
705                 _E("unable to delete the " \
706                         "loopback device from the SD Card");
707                 ret =  APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
708                 goto END;
709         }
710
711         ret = _app2sd_delete_directory(application_path);
712         if (ret) {
713                 _E("unable to delete the directory (%s)",
714                 application_path);
715                 goto END;
716         }
717
718         /* remove encryption password from DB */
719         ret = _app2sd_initialize_db();
720         if (ret) {
721                 _E("app2sd db initialize failed");
722                 ret = APP2EXT_ERROR_SQLITE_REGISTRY;
723                 goto END;
724         }
725
726         ret = _app2sd_remove_info_from_db(pkgid, uid);
727         if (ret) {
728                 _E("cannot remove info from db");
729                 ret = APP2EXT_ERROR_SQLITE_REGISTRY;
730                 goto END;
731         }
732
733 END:
734         return ret;
735 }
736
737 int app2sd_usr_move_installed_app(const char *pkgid, GList *dir_list,
738                 app2ext_move_type move_type, uid_t uid)
739 {
740         int ret = 0;
741         int pkgmgr_ret = 0;
742
743         /* validate function arguments */
744         if (pkgid == NULL || dir_list == NULL
745                 || move_type < APP2EXT_MOVE_TO_EXT
746                 || move_type > APP2EXT_MOVE_TO_PHONE) {
747                 _E("invalid function arguments");
748                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
749         }
750
751         pkgmgrinfo_pkginfo_h info_handle = NULL;
752         pkgmgrinfo_installed_storage storage = PMINFO_INTERNAL_STORAGE;
753         pkgmgr_ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &info_handle);
754         if (pkgmgr_ret < 0) {
755                 _E("failed to get pkginfo for pkg(%s), uid(%d), pkgmgr_ret(%d)",
756                         pkgid, uid, pkgmgr_ret);
757                 return APP2EXT_ERROR_PKGMGR_ERROR;
758         }
759         pkgmgr_ret = pkgmgrinfo_pkginfo_get_installed_storage(info_handle, &storage);
760         if (pkgmgr_ret < 0) {
761                 _E("failed to get installed storage for pkg(%s) of uid(%d), pkgmgr_ret(%d)",
762                         pkgid, uid, pkgmgr_ret);
763                 pkgmgrinfo_pkginfo_destroy_pkginfo(info_handle);
764                 return APP2EXT_ERROR_PKGMGR_ERROR;
765         }
766
767         if ((move_type == APP2EXT_MOVE_TO_EXT && storage == PMINFO_EXTERNAL_STORAGE)
768                 || (move_type == APP2EXT_MOVE_TO_PHONE && storage == PMINFO_INTERNAL_STORAGE)) {
769                         _E("PKG_EXISTS in [%d] STORAGE", storage);
770                         pkgmgrinfo_pkginfo_destroy_pkginfo(info_handle);
771                         return APP2EXT_ERROR_PKG_EXISTS;
772         } else {
773                 _D("pkgid[%s] move to STORAGE [%d]", pkgid, storage);
774         }
775         pkgmgrinfo_pkginfo_destroy_pkginfo(info_handle);
776
777         ret = _app2sd_usr_move_app(pkgid, move_type, dir_list, uid);
778         if (ret) {
779                 _D("unable to move application");
780                 return ret;
781         }
782
783         /* if move is completed, then update installed storage to pkgmgr_parser db */
784         if (move_type == APP2EXT_MOVE_TO_EXT) {
785                 pkgmgr_ret = pkgmgrinfo_pkginfo_set_usr_installed_storage(pkgid,
786                                 INSTALL_EXTERNAL, uid);
787                 if (pkgmgr_ret < 0) {
788                         _E("failed to update installed location to db " \
789                                 "[%s, %s] of uid(%d), pkgmgr_ret(%d)",
790                                 pkgid, INSTALL_EXTERNAL, uid, pkgmgr_ret);
791                         return APP2EXT_ERROR_PKGMGR_ERROR;
792                 }
793         } else {
794                 pkgmgr_ret = pkgmgrinfo_pkginfo_set_usr_installed_storage(pkgid,
795                                 INSTALL_INTERNAL, uid);
796                 if (pkgmgr_ret < 0) {
797                         _E("failed to update installed location to db " \
798                                 "[%s, %s] of uid(%d), pkgmgr_ret(%d)",
799                                 pkgid, INSTALL_INTERNAL, uid, pkgmgr_ret);
800                         return APP2EXT_ERROR_PKGMGR_ERROR;
801                 }
802         }
803
804         return APP2EXT_SUCCESS;
805 }
806
807 int app2sd_usr_pre_app_upgrade(const char *pkgid, GList *dir_list,
808                 int size, uid_t uid)
809 {
810         int ret = APP2EXT_SUCCESS;
811         char loopback_device[FILENAME_MAX] = { 0, };
812         char application_path[FILENAME_MAX] = { 0, };
813         char temp_uid[32] = { 0, };
814         char *temp_pkgid = NULL;
815         char *temp_loopback_device = NULL;
816         char *temp_application_path = NULL;
817         char *device_node = NULL;
818         char *encoded_id = NULL;
819         char *temp_encoded_id = NULL;
820         int len = 0;
821         unsigned long long curr_size = 0;
822         FILE *fp = NULL;
823         int reqd_disk_size = size + ceil(size * 0.2);
824
825         /* validate function arguments*/
826         if (pkgid == NULL || dir_list == NULL || size <= 0) {
827                 _E("invalid function arguments");
828                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
829         }
830
831         /* check whether MMC is present or not */
832         ret = _app2sd_check_mmc_status();
833         if (ret) {
834                 _E("MMC not preset OR Not ready (%d)", ret);
835                 return APP2EXT_ERROR_MMC_STATUS;
836         }
837
838         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
839         if (encoded_id == NULL)
840                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
841
842         if (_is_global(uid)) {
843                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
844                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
845                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
846                         APP2SD_PATH, encoded_id);
847         } else {
848                 tzplatform_set_user(uid);
849                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
850                         tzplatform_getenv(TZ_USER_APP), pkgid);
851                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
852                         APP2SD_PATH, encoded_id);
853                 tzplatform_reset_user();
854         }
855         free(encoded_id);
856
857         /* check app entry is there in sd card or not. */
858         fp = fopen(loopback_device, "r+");
859         if (fp == NULL) {
860                 _E("app entry is not present in SD Card");
861                 return APP2EXT_ERROR_INVALID_PACKAGE;
862         }
863         fclose(fp);
864
865         /* get installed app size*/
866         curr_size = _app2sd_calculate_file_size(loopback_device);
867         curr_size = (curr_size) / (1024 * 1024);
868         if (curr_size == 0) {
869                 _E("app entry is not present in SD Card");
870                 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
871         }
872         if ((int)curr_size < reqd_disk_size) {
873                 len = strlen(pkgid) + strlen(".new");
874                 temp_pkgid = calloc(len + 1, sizeof(char));
875                 if (temp_pkgid == NULL) {
876                         _E("memory alloc failed");
877                         return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
878                 }
879                 snprintf(temp_pkgid, len + 1, "%s.new", pkgid);
880
881                 if (_is_global(uid)) {
882                         len = strlen(tzplatform_getenv(TZ_SYS_RW_APP)) + strlen(temp_pkgid) + 1;
883                         temp_application_path = calloc(len + 1, sizeof(char));
884                         if (temp_application_path == NULL) {
885                                 _E("memory alloc failed");
886                                 free(temp_pkgid);
887                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
888                         }
889                         snprintf(temp_application_path, len + 1, "%s/%s",
890                                 tzplatform_getenv(TZ_SYS_RW_APP), temp_pkgid);
891
892                         temp_encoded_id = _app2sd_get_encoded_name((const char *)temp_pkgid, uid);
893                         if (temp_encoded_id == NULL) {
894                                 free(temp_pkgid);
895                                 free(temp_application_path);
896                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
897                         }
898                         len = strlen(APP2SD_PATH) + strlen(temp_encoded_id) + 1;
899                         temp_loopback_device = calloc(len + 1, sizeof(char));
900                         if (temp_loopback_device == NULL) {
901                                 _E("memory alloc failed");
902                                 free(temp_pkgid);
903                                 free(temp_application_path);
904                                 free(temp_encoded_id);
905                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
906                         }
907                         snprintf(temp_loopback_device, len + 1, "%s/%s",
908                                 APP2SD_PATH, temp_encoded_id);
909                         free(temp_encoded_id);
910                 } else {
911                         tzplatform_set_user(uid);
912                         len = strlen(tzplatform_getenv(TZ_USER_APP)) + strlen(temp_pkgid) + 1;
913                         temp_application_path = calloc(len + 1, sizeof(char));
914                         if (temp_application_path == NULL) {
915                                 _E("memory alloc failed");
916                                 free(temp_pkgid);
917                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
918                         }
919                         snprintf(temp_application_path, len + 1, "%s/%s",
920                                 tzplatform_getenv(TZ_USER_APP), temp_pkgid);
921
922                         temp_encoded_id = _app2sd_get_encoded_name((const char *)temp_pkgid, uid);
923                         if (temp_encoded_id == NULL) {
924                                 free(temp_pkgid);
925                                 free(temp_application_path);
926                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
927                         }
928                         snprintf(temp_uid, 32, "%d", uid);
929                         len = strlen(APP2SD_PATH) + strlen(temp_uid) + strlen(temp_encoded_id) + 2;
930                         temp_loopback_device = calloc(len + 1, sizeof(char));
931                         if (temp_loopback_device == NULL) {
932                                 _E("memory alloc failed");
933                                 free(temp_pkgid);
934                                 free(temp_application_path);
935                                 free(temp_encoded_id);
936                                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
937                         }
938                         snprintf(temp_loopback_device, len + 1, "%s/%s",
939                                 APP2SD_PATH, temp_encoded_id);
940                         free(temp_encoded_id);
941                         tzplatform_reset_user();
942                 }
943                 ret = _app2sd_update_loopback_device_size(pkgid,
944                         loopback_device, application_path, temp_pkgid,
945                         temp_loopback_device, temp_application_path,
946                         reqd_disk_size, dir_list, uid);
947                 free(temp_pkgid);
948                 free(temp_application_path);
949                 free(temp_loopback_device);
950                 if (APP2EXT_SUCCESS != ret) {
951                         _E("failed to update loopback device size");
952                         return ret;
953                 }
954         }
955
956         /* get the associated device node for SD card applicationer */
957 #ifdef _APPFW_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
958         device_node =
959                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
960 #else
961         device_node = _app2sd_find_associated_device_node(loopback_device);
962 #endif
963         if (NULL == device_node) {
964                 /* do loopback setup */
965 #ifdef _APPFW_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
966                 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
967                         false, uid, &device_node);
968                 if (ret) {
969                         _E("dmcrypt open device error");
970                         return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
971                 }
972 #else
973                 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
974                         loopback_device, uid);
975                 if (device_node == NULL) {
976                         _E("loopback encryption setup failed");
977                         return APP2EXT_ERROR_DO_LOSETUP;
978                 }
979 #endif
980
981                 /* do mounting */
982                 ret = _app2sd_mount_app_content(application_path, pkgid,
983                         device_node, MOUNT_TYPE_RW, dir_list,
984                         APP2SD_PRE_UPGRADE, uid);
985                 if (ret) {
986                         _E("mount failed");
987                         if (device_node) {
988                                 free(device_node);
989                                 device_node = NULL;
990                         }
991                         return APP2EXT_ERROR_MOUNT_PATH;
992                 }
993         } else {
994                 /* do re-mounting */
995                 ret = _app2sd_mount_app_content(application_path, pkgid,
996                         device_node, MOUNT_TYPE_RW_REMOUNT, NULL,
997                         APP2SD_PRE_UPGRADE, uid);
998                 if (ret) {
999                         _E("remount failed");
1000                         if (device_node) {
1001                                 free(device_node);
1002                                 device_node = NULL;
1003                         }
1004                         return APP2EXT_ERROR_MOUNT_PATH;
1005                 }
1006         }
1007
1008         if (device_node) {
1009                 free(device_node);
1010                 device_node = NULL;
1011         }
1012         return ret;
1013 }
1014
1015 int app2sd_usr_post_app_upgrade(const char *pkgid,
1016                 app2ext_status install_status, uid_t uid)
1017 {
1018         char *device_name = NULL;
1019         char loopback_device[FILENAME_MAX] = { 0, };
1020         char application_path[FILENAME_MAX] = { 0, };
1021         char *encoded_id = NULL;
1022         int ret = APP2EXT_SUCCESS;
1023
1024         /* validate the function parameter recieved */
1025         if (pkgid == NULL || install_status < APP2EXT_STATUS_FAILED
1026                 || install_status > APP2EXT_STATUS_SUCCESS) {
1027                 _E("invalid func parameters");
1028                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1029         }
1030
1031         /* check whether MMC is present or not */
1032         ret = _app2sd_check_mmc_status();
1033         if (ret) {
1034                 _E("MMC not preset OR Not ready (%d)", ret);
1035                 return APP2EXT_ERROR_MMC_STATUS;
1036         }
1037
1038         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
1039         if (encoded_id == NULL)
1040                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1041
1042         if (_is_global(uid)) {
1043                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1044                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1045                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1046                         APP2SD_PATH, encoded_id);
1047         } else {
1048                 tzplatform_set_user(uid);
1049                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1050                         tzplatform_getenv(TZ_USER_APP), pkgid);
1051                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1052                         APP2SD_PATH, encoded_id);
1053                 tzplatform_reset_user();
1054         }
1055         free(encoded_id);
1056
1057         /* get the associated device node for SD card applicationer */
1058 #ifdef _APPFW_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1059         device_name =
1060                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1061         if (!device_name) {
1062                 _E("could not find associated dmcrypt device node" \
1063                         " (%s_%d)", pkgid, uid);
1064                 return APP2EXT_ERROR_FIND_ASSOCIATED_DMCRYPT_DEVICE_NODE;
1065         }
1066 #else
1067         device_name = _app2sd_find_associated_device_node(loopback_device);
1068         if (NULL == device_name)
1069                 return APP2EXT_ERROR_FIND_ASSOCIATED_DEVICE_NODE;
1070 #endif
1071
1072         ret = _app2sd_unmount_app_content(application_path);
1073         if (ret) {
1074                 if (device_name) {
1075                         free(device_name);
1076                         device_name = NULL;
1077                 }
1078                 _E("unable to unmount the app content (%d)", ret);
1079                 return APP2EXT_ERROR_UNMOUNT;
1080         }
1081
1082 #ifdef _APPFW_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1083         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1084         if (ret) {
1085                 if (device_name) {
1086                         free(device_name);
1087                         device_name = NULL;
1088                 }
1089                 _E("close dmcrypt device error(%d)", ret);
1090                 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1091         }
1092 #else
1093         ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1094         if (ret) {
1095                 if (device_name) {
1096                         free(device_name);
1097                         device_name = NULL;
1098                 }
1099                 _E("unable to detach the loopback encryption " \
1100                         "setup for the application");
1101                 return APP2EXT_ERROR_UNMOUNT;
1102         }
1103 #endif
1104
1105         if (device_name) {
1106                 free(device_name);
1107                 device_name = NULL;
1108         }
1109
1110         return ret;
1111 }
1112
1113 int app2sd_usr_force_clean(const char *pkgid, uid_t uid)
1114 {
1115         char loopback_device[FILENAME_MAX] = { 0, };
1116         char application_path[FILENAME_MAX] = { 0, };
1117         char *encoded_id = NULL;
1118         int ret = APP2EXT_SUCCESS;
1119
1120         /* validate the function parameter recieved */
1121         if (pkgid == NULL) {
1122                 _E("invalid func parameters");
1123                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1124         }
1125
1126         sync();
1127
1128         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
1129         if (encoded_id == NULL)
1130                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1131
1132         if (_is_global(uid)) {
1133                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1134                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1135                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1136                         APP2SD_PATH, encoded_id);
1137         } else {
1138                 tzplatform_set_user(uid);
1139                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1140                         tzplatform_getenv(TZ_USER_APP), pkgid);
1141                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1142                         APP2SD_PATH, encoded_id);
1143                 tzplatform_reset_user();
1144         }
1145         free(encoded_id);
1146
1147         ret = _app2sd_force_clean(pkgid, application_path, loopback_device, uid);
1148
1149         return ret;
1150 }
1151
1152 int app2sd_enable_full_pkg(void)
1153 {
1154         int ret = APP2EXT_SUCCESS;
1155         int rc = 0;
1156         char buf[FILENAME_MAX] = { 0, };
1157         char loopback_device[FILENAME_MAX] = { 0, };
1158         DIR *dir = NULL;
1159         struct dirent entry;
1160         struct dirent *result = NULL;
1161         char *pkgid = NULL;
1162         uid_t uid = 0;
1163
1164         dir = opendir(APP2SD_PATH);
1165         if (!dir) {
1166                 if (strerror_r(errno, buf, sizeof(buf)) == 0)
1167                         _E("failed to opendir (%s)", buf);
1168                 return APP2EXT_ERROR_OPEN_DIR;
1169         }
1170
1171         ret = _app2sd_initialize_db();
1172         if (ret) {
1173                 _E("app2sd db initialize failed");
1174                 closedir(dir);
1175                 return APP2EXT_ERROR_SQLITE_REGISTRY;
1176         }
1177
1178         for (rc = readdir_r(dir, &entry, &result);
1179                 rc == 0 && result != NULL;
1180                 rc = readdir_r(dir, &entry, &result)) {
1181                 if (strcmp(entry.d_name, ".") == 0 ||
1182                         strcmp(entry.d_name, "..") == 0)
1183                         continue;
1184                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1185                         APP2SD_PATH, entry.d_name);
1186                 ret = _app2sd_get_info_from_db(loopback_device,
1187                         &pkgid, &uid);
1188                 if (ret) {
1189                         _E("failed to get info from db");
1190                         break;;
1191                 }
1192                 if (pkgid && uid > 0) {
1193                         _D("pkgid(%s), uid(%d)", pkgid, uid);
1194                         ret = app2sd_usr_on_demand_setup_init(pkgid, uid);
1195                         if (ret) {
1196                                 _E("error(%d)", ret);
1197                                 break;
1198                         }
1199                 }
1200                 if (pkgid) {
1201                         free(pkgid);
1202                         pkgid = NULL;
1203                 }
1204         }
1205
1206         if (pkgid) {
1207                 free(pkgid);
1208                 pkgid = NULL;
1209         }
1210         closedir(dir);
1211
1212         return ret;
1213 }
1214
1215 int app2sd_disable_full_pkg(void)
1216 {
1217         int ret = APP2EXT_SUCCESS;
1218         int rc = 0;
1219         char buf[FILENAME_MAX] = { 0, };
1220         char loopback_device[FILENAME_MAX] = { 0, };
1221         DIR *dir = NULL;
1222         struct dirent entry;
1223         struct dirent *result = NULL;
1224         char *pkgid = NULL;
1225         uid_t uid = 0;
1226
1227         dir = opendir(APP2SD_PATH);
1228         if (!dir) {
1229                 if (strerror_r(errno, buf, sizeof(buf)) == 0)
1230                         _E("failed to opendir (%s)", buf);
1231                 return APP2EXT_ERROR_OPEN_DIR;
1232         }
1233
1234         ret = _app2sd_initialize_db();
1235         if (ret) {
1236                 _E("app2sd db initialize failed");
1237                 closedir(dir);
1238                 return APP2EXT_ERROR_SQLITE_REGISTRY;
1239         }
1240
1241         for (rc = readdir_r(dir, &entry, &result);
1242                 rc == 0 && result != NULL;
1243                 rc = readdir_r(dir, &entry, &result)) {
1244                 if (strcmp(entry.d_name, ".") == 0 ||
1245                         strcmp(entry.d_name, "..") == 0)
1246                         continue;
1247                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1248                         APP2SD_PATH, entry.d_name);
1249                 ret = _app2sd_get_info_from_db(loopback_device,
1250                         &pkgid, &uid);
1251                 if (ret) {
1252                         _E("failed to get info from db");
1253                         break;
1254                 }
1255                 if (pkgid && uid > 0) {
1256                         _D("pkgid(%s), uid(%d)", pkgid, uid);
1257                         ret = app2sd_usr_on_demand_setup_exit(pkgid, uid);
1258                         if (ret) {
1259                                 _E("error(%d)", ret);
1260                                 break;
1261                         }
1262                 }
1263                 if (pkgid) {
1264                         free(pkgid);
1265                         pkgid = NULL;
1266                 }
1267         }
1268
1269         if (pkgid) {
1270                 free(pkgid);
1271                 pkgid = NULL;
1272         }
1273         closedir(dir);
1274
1275         return ret;
1276 }