Revert "Use libcryptsetup API instead of using cryptsetup directly"
[platform/core/appfw/app2sd.git] / plugin / app2sd / server / app2sd_internals.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 #define _GNU_SOURCE
25 #include <dirent.h>
26 #include <time.h>
27 #include <pwd.h>
28
29 #include "app2sd_internals.h"
30
31 #define DMCRYPT_ITER_TIME       50
32 #define DMCRYPT_KEY_LEN         128
33
34 static int _app2sd_make_directory(const char *path, uid_t uid)
35 {
36         int ret;
37         int fd;
38         mode_t mode = DIR_PERMS;
39         struct passwd pwd;
40         struct passwd *pwd_result;
41         char buf[1024];
42
43         ret = _app2sd_delete_directory(path);
44         if (ret) {
45                 _E("unable to delete (%s), errno(%d)", path, errno);
46                 return APP2EXT_ERROR_DELETE_DIRECTORY;
47         }
48
49         ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwd_result);
50         if (ret != 0 || pwd_result == NULL) {
51                 _E("get uid failed(%d)", ret);
52                 return APP2EXT_ERROR_ACCESS_FILE;
53         }
54         _D("uid(%d), gid(%d)", uid, pwd.pw_gid);
55
56         /* create directory */
57         ret = mkdir(path, mode);
58         if (ret) {
59                 if (errno != EEXIST) {
60                         _E("create directory failed, error is (%d)", errno);
61                         return APP2EXT_ERROR_CREATE_DIRECTORY;
62                 }
63         }
64
65         fd = open(path, O_RDONLY|O_DIRECTORY);
66         if (fd < 0) {
67                 _E("can't open path(%s)", path);
68                 return APP2EXT_ERROR_OPEN_DIR;
69         }
70
71         ret = fchmod(fd, 0755);
72         if (ret < 0) {
73                 _E("change file permission error");
74                 close(fd);
75                 return APP2EXT_ERROR_ACCESS_FILE;
76         }
77
78         ret = fchown(fd, uid, pwd.pw_gid);
79         if (ret < 0) {
80                 _E("change file owner error");
81                 close(fd);
82                 return APP2EXT_ERROR_ACCESS_FILE;
83         }
84
85         close(fd);
86
87         return APP2EXT_SUCCESS;
88 }
89
90 int _app2sd_dmcrypt_setup_device(const char *pkgid,
91                 const char *loopback_device, bool is_dup, uid_t uid)
92 {
93         int ret;
94         char *passwd;
95         char dmcrypt_setup_cmd[BUF_SIZE];
96         char err_buf[BUF_SIZE];
97         const char *err_str;
98
99         if (pkgid == NULL || loopback_device == NULL) {
100                 _E("invalid argument");
101                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
102         }
103
104         /* get password for dmcrypt encryption */
105         ret = _app2sd_initialize_db();
106         if (ret) {
107                 _E("app2sd db initialize failed");
108                 return APP2EXT_ERROR_DB_INITIALIZE;
109         }
110
111         passwd = _app2sd_get_password_from_db(pkgid, uid);
112         if (passwd == NULL) {
113                 if (is_dup) {
114                         _E("no password found for (%s)", pkgid);
115                         return APP2EXT_ERROR_SQLITE_REGISTRY;
116                 }
117                 passwd = _app2sd_generate_password();
118                 if (passwd == NULL) {
119                         _E("unable to generate password");
120                         return APP2EXT_ERROR_PASSWD_GENERATION;
121                 }
122
123                 ret = _app2sd_set_info_in_db(pkgid, passwd, loopback_device,
124                                 uid);
125                 if (ret < 0) {
126                         _E("unable to save password");
127                         free(passwd);
128                         return APP2EXT_ERROR_SQLITE_REGISTRY;
129                 }
130         }
131
132         snprintf(dmcrypt_setup_cmd, sizeof(dmcrypt_setup_cmd),
133                         "/bin/echo '%s' | /sbin/cryptsetup -q -i %d "
134                         "-c aes-cbc-lmk -s %d --align-payload=8 luksFormat %s",
135                         passwd, DMCRYPT_ITER_TIME, DMCRYPT_KEY_LEN,
136                         loopback_device);
137         memset(passwd, 0, strlen(passwd));
138         free(passwd);
139         ret = system(dmcrypt_setup_cmd);
140         memset(dmcrypt_setup_cmd, 0, BUF_SIZE);
141         if (ret) {
142                 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
143                 _E("Error setting up dmcrypt on app2sd file, error:%s, ret:%d",
144                                 err_str, ret);
145                 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
146         }
147
148         return ret;
149 }
150
151 int _app2sd_dmcrypt_open_device(const char *pkgid, const char *loopback_device,
152                 bool is_dup, uid_t uid, char **dev_node)
153 {
154         int ret;
155         int size;
156         char *passwd;
157         char dmcrypt_open_cmd[BUF_SIZE];
158         char dev_name[BUF_SIZE];
159         char buf[BUF_SIZE];
160         const char *err_str;
161
162         if (pkgid == NULL || loopback_device == NULL) {
163                 _E("invalid argument");
164                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
165         }
166
167         if (is_dup)
168                 snprintf(dev_name, sizeof(dev_name), "%s.new_%d", pkgid, uid);
169         else
170                 snprintf(dev_name, sizeof(dev_name), "%s_%d", pkgid, uid);
171
172         /* get password for dmcrypt encryption */
173         ret = _app2sd_initialize_db();
174         if (ret) {
175                 _E("app2sd db initialize failed");
176                 return APP2EXT_ERROR_DB_INITIALIZE;
177         }
178
179         passwd = _app2sd_get_password_from_db(pkgid, uid);
180         if (passwd == NULL) {
181                 _E("no password found for [%s]", pkgid);
182                 return APP2EXT_ERROR_SQLITE_REGISTRY;
183         }
184
185         if (_app2sd_check_is_luks_device(loopback_device) == 0) {
186                 _W("legacy image format!");
187                 snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
188                                 "/bin/echo '%s' | /sbin/cryptsetup "
189                                 "-M plain -c aes-cbc-plain -h plain open %s %s",
190                                 passwd, loopback_device, dev_name);
191         } else {
192                 snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
193                                 "/bin/echo '%s' | /sbin/cryptsetup -q luksOpen "
194                                 "%s %s",
195                                 passwd, loopback_device, dev_name);
196         }
197         free(passwd);
198
199         ret = system(dmcrypt_open_cmd);
200         if (ret) {
201                 err_str = strerror_r(errno, buf, sizeof(buf));
202                 _E("error opening dmcrypt device, error: [%s]", err_str);
203                 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
204         }
205
206         size = strlen("/dev/mapper/%s") + strlen(dev_name) + 1;
207         *dev_node = (char *)malloc(size);
208         if (*dev_node == NULL) {
209                 _E("memory alloc failed");
210                 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
211         }
212         snprintf(*dev_node, size, "/dev/mapper/%s", dev_name);
213
214         return ret;
215 }
216
217 int _app2sd_dmcrypt_close_device(const char *pkgid, uid_t uid)
218 {
219         int ret;
220         char dev_node[BUF_SIZE];
221         char dmcrypt_close_cmd[BUF_SIZE];
222         char err_buf[BUF_SIZE];
223         const char *err_str;
224         char *t_dev_node;
225
226         if (pkgid == NULL) {
227                 _E("invalid argument");
228                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
229         }
230
231         t_dev_node = _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
232         if (!t_dev_node) {
233                 _W("no associated device node(%s_%d) found", pkgid, uid);
234                 return APP2EXT_ERROR_DMCRYPT_DEVICE_UNAVAILABLE;
235         }
236
237         free(t_dev_node);
238
239         snprintf(dev_node, sizeof(dev_node), "/dev/mapper/%s_%d", pkgid, uid);
240         snprintf(dmcrypt_close_cmd, sizeof(dmcrypt_close_cmd),
241                         "/sbin/cryptsetup -q luksClose %s", dev_node);
242         ret = system(dmcrypt_close_cmd);
243         if (ret) {
244                 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
245                 _E("error closing dmcrypt on app2sd file: %s", err_str);
246                 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
247         }
248
249         return ret;
250 }
251
252 char *_app2sd_find_associated_dmcrypt_device_node(const char *pkgid, uid_t uid)
253 {
254         char *dev_node;
255         char buf[BUF_SIZE];
256
257         snprintf(buf, sizeof(buf), "/dev/mapper/%s_%d", pkgid, uid);
258         if (access(buf, F_OK) == 0) {
259                 dev_node = strdup(buf);
260                 if (dev_node == NULL) {
261                         _E("memory alloc failed");
262                         return NULL;
263                 }
264                 _D("device_node: (%s)", dev_node);
265                 return dev_node;
266         }
267         _D("can not access dev_node(%s), errno(%d)", buf, errno);
268
269         return NULL;
270 }
271
272 char *_app2sd_dmcrypt_duplicate_encryption_setup(const char *pkgid,
273                 const char *temp_loopback_device, uid_t uid)
274 {
275         int ret;
276         char *device_node;
277
278         if (pkgid == NULL || temp_loopback_device == NULL) {
279                 _E("invalid argument");
280                 return NULL;
281         }
282
283         ret = _app2sd_dmcrypt_setup_device(pkgid, temp_loopback_device, true,
284                         uid);
285         if (ret) {
286                 _E("dmcrypt setup device error(%d)", ret);
287                 return NULL;
288         }
289
290         ret = _app2sd_dmcrypt_open_device(pkgid, temp_loopback_device, true,
291                         uid, &device_node);
292         if (ret) {
293                 _E("dmcrypt open device error");
294                 return NULL;
295         }
296
297         return device_node;
298 }
299
300 int _app2sd_create_loopback_device(const char *pkgid,
301                 const char *loopback_device, int size)
302 {
303         int ret;
304         char command[FILENAME_MAX];
305         char buff[BUF_SIZE];
306         FILE *fp;
307         const char *argv[] = { "/bin/dd", "if=/dev/zero", command,
308                 "bs=1M", buff, NULL };
309
310         if (pkgid == NULL || size <= 0) {
311                 _E("invalid argument");
312                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
313         }
314
315         fp = fopen(loopback_device, "r+");
316         if (fp != NULL) {
317                 _W("encrypted file already exists (%s)", loopback_device);
318                 fclose(fp);
319                 return APP2EXT_ERROR_PKG_EXISTS;
320         }
321
322         snprintf(command, sizeof(command), "of=%s", loopback_device);
323         snprintf(buff, sizeof(buff), "count=%d", size);
324
325         ret = _xsystem(argv);
326         if (ret)
327                 _E("command (%s) failed, ret(%d), errno(%d)",
328                                 command, ret, errno);
329
330         return ret;
331 }
332
333 int _app2sd_delete_loopback_device(const char *loopback_device)
334 {
335         int ret;
336
337         ret = unlink(loopback_device);
338         if (ret) {
339                 if (errno == ENOENT) {
340                         _W("unable to access file (%s)", loopback_device);
341                 } else {
342                         _E("unable to delete (%s)", loopback_device);
343                         return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
344                 }
345         }
346
347         return APP2EXT_SUCCESS;
348 }
349
350 int _app2sd_create_file_system(const char *device_path)
351 {
352         int ret;
353         FILE *fp;
354         char err_buf[1024];
355         const char *err_str;
356         const char *argv[] = { "/sbin/mkfs.ext4", device_path, NULL };
357
358         if (device_path == NULL) {
359                 _E("invalid param");
360                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
361         }
362
363         /* Format the filesystem [create a filesystem]*/
364         fp = fopen(device_path, "r+");
365         if (fp == NULL) {
366                 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
367                 _E("unable to access (%s) error is (%d, %s)",
368                                 device_path, errno, err_str);
369                 return APP2EXT_ERROR_ACCESS_FILE;
370         }
371         fclose(fp);
372
373         ret = _xsystem(argv);
374         if (ret) {
375                 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
376                 _E("creating file system failed, error is (%s)", err_str);
377                 return APP2EXT_ERROR_CREATE_FS;
378         }
379         return ret;
380 }
381
382 static int _app2sd_create_dir_with_link(const char *application_path,
383                 const char *pkgid, const char *dir_name, uid_t uid)
384 {
385         int ret;
386         char app_dir_mmc_path[FILENAME_MAX];
387         char app_dir_path[FILENAME_MAX];
388
389         snprintf(app_dir_mmc_path, sizeof(app_dir_mmc_path), "%s/.mmc/%s",
390                         application_path, dir_name);
391         snprintf(app_dir_path, sizeof(app_dir_path), "%s/%s",
392                         application_path, dir_name);
393
394         ret = _app2sd_make_directory(app_dir_mmc_path, uid);
395         if (ret) {
396                 _E("create directory failed");
397                 return APP2EXT_ERROR_CREATE_DIRECTORY;
398         }
399
400         ret = symlink(app_dir_mmc_path, app_dir_path);
401         if (ret < 0) {
402                 if (errno == EEXIST) {
403                         _D("file with symlink name present (%s)", app_dir_path);
404                 } else {
405                         _E("symbolic link creation failed, error: %d", errno);
406                         return APP2EXT_ERROR_CREATE_SYMLINK;
407                 }
408         }
409
410         return APP2EXT_SUCCESS;
411 }
412
413 static int _app2sd_create_directory_entry(const char *application_path,
414                 const char *pkgid, GList *dir_list, uid_t uid)
415 {
416         int ret;
417         GList *list;
418         app2ext_dir_details *dir_detail;
419
420         for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
421                 dir_detail = (app2ext_dir_details *)list->data;
422                 if (dir_detail == NULL || dir_detail->name == NULL ||
423                                 dir_detail->type != APP2EXT_DIR_RO)
424                         continue;
425                 ret = _app2sd_create_dir_with_link(application_path,
426                                 pkgid, dir_detail->name, uid);
427                 if (ret)
428                         return ret;
429         }
430         return APP2EXT_SUCCESS;
431 }
432
433 int _app2sd_mount_app_content(const char *application_path, const char *pkgid,
434                 const char *dev, int mount_type, GList *dir_list,
435                 app2sd_cmd cmd, uid_t uid)
436 {
437         int ret;
438         int fd;
439         char app_mmc_path[FILENAME_MAX];
440         char temp_path[FILENAME_MAX];
441         char err_buf[1024];
442         const char *err_str;
443         struct timespec time = {
444                 .tv_sec = 0,
445                 .tv_nsec = 1000 * 1000 * 200
446         };
447         char mountflags_str[BUF_SIZE];
448         const char *argv_mount[] = { "/bin/app2sd-mount-helper", dev,
449                 app_mmc_path, FS_TYPE, mountflags_str, NULL };
450
451         if (dev == NULL) {
452                 _E("input param is NULL (%s)", dev);
453                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
454         }
455
456         /* check directory existence */
457         fd = open(application_path, O_RDONLY | O_DIRECTORY);
458         if (fd < 0) {
459                 _E("path(%s) error(%d)", application_path, errno);
460                 return APP2EXT_ERROR_OPEN_DIR;
461         }
462         close(fd);
463
464         ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
465                         application_path);
466         if (ret < 0 || ret > sizeof(app_mmc_path)) {
467                 _E("snprintf fail");
468                 return APP2EXT_ERROR_OPEN_DIR;
469         }
470         fd = open(app_mmc_path, O_RDONLY | O_DIRECTORY);
471         if (fd < 0) {
472                 _E("path(%s) error(%d)", app_mmc_path, errno);
473                 return APP2EXT_ERROR_OPEN_DIR;
474         }
475         close(fd);
476
477         nanosleep(&time, NULL); /* 200ms sleep */
478         _D("give a delay for mount");
479
480         switch (mount_type) {
481         case MOUNT_TYPE_RD:
482                 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
483                                 MS_MGC_VAL | MS_RDONLY | MS_NOSUID);
484                 ret = _xsystem(argv_mount);
485                 if (ret) {
486                         _E("read only mount failed, errono is (%d), "
487                                         "dev is (%s) path is (%s)",
488                                         ret, dev, app_mmc_path);
489                         ret = APP2EXT_ERROR_MOUNT;
490                 }
491                 break;
492         case MOUNT_TYPE_RW:
493                 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
494                                 MS_MGC_VAL | MS_NOSUID);
495                 ret = _xsystem(argv_mount);
496                 if (ret) {
497                         _E("read write mount failed, errno is (%d)", ret);
498                         ret = APP2EXT_ERROR_MOUNT;
499                 }
500                 break;
501         case MOUNT_TYPE_RW_NOEXEC:
502                 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
503                                 MS_MGC_VAL | MS_NOEXEC | MS_NOSUID);
504                 ret = _xsystem(argv_mount);
505                 if (ret) {
506                         _E("rwnx mount failed errno is (%d)", ret);
507                         ret = APP2EXT_ERROR_MOUNT;
508                 }
509                 break;
510         case MOUNT_TYPE_RD_REMOUNT:
511                 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
512                                 MS_MGC_VAL | MS_RDONLY | MS_REMOUNT |
513                                 MS_NOSUID);
514                 ret = _xsystem(argv_mount);
515                 if (ret) {
516                         _E("read remount failed errno is (%d)", ret);
517                         ret = APP2EXT_ERROR_MOUNT;
518                 }
519                 break;
520         case MOUNT_TYPE_RW_REMOUNT:
521                 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
522                                 MS_MGC_VAL | MS_REMOUNT | MS_NOSUID);
523                 ret = _xsystem(argv_mount);
524                 err_str = strerror_r(ret, err_buf, sizeof(err_buf));
525                 if (ret) {
526                         _E("read write remount failed errno(%d), errstr(%s)",
527                                         ret, err_str);
528                         ret = APP2EXT_ERROR_MOUNT;
529                 }
530                 break;
531         default:
532                 _E("invalid mount type");
533                 break;
534         }
535
536         if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC ||
537                         cmd == APP2SD_PRE_UPGRADE) {
538                 ret = _app2sd_create_directory_entry(application_path,
539                                 pkgid, dir_list, uid);
540         }
541
542         if (mount_type != MOUNT_TYPE_RD &&
543                         mount_type != MOUNT_TYPE_RD_REMOUNT) {
544                 /* change lost+found permission */
545                 ret = snprintf(temp_path, sizeof(temp_path), "%s/lost+found",
546                                 app_mmc_path);
547                 if (ret < 0 || ret > sizeof(temp_path)) {
548                         _E("snprintf fail");
549                         return APP2EXT_ERROR_CREATE_DIRECTORY;
550                 }
551                 ret = _app2sd_make_directory(temp_path, uid);
552                 if (ret) {
553                         _E("create directory(%s) failed", temp_path);
554                         return APP2EXT_ERROR_CREATE_DIRECTORY;
555                 }
556         }
557
558         return ret;
559 }
560
561 int _app2sd_unmount_app_content(const char *application_path)
562 {
563         int ret;
564         char app_mmc_path[FILENAME_MAX];
565         char err_buf[1024];
566         const char *err_str;
567
568         snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
569                         application_path);
570         ret = umount(app_mmc_path);
571         if (ret < 0) {
572                 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
573                 _D("unable to umount the dir, ret(%d) error(%d, %s)",
574                                 ret, errno, err_str);
575         }
576
577         return ret;
578 }
579
580 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
581 {
582         int ret;
583         char err_buf[1024];
584         const char *err_str;
585
586         ret = _app2sd_copy_dir(src_path, arch_path);
587         if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
588                 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
589                 _E("unable to copy from (%s) to (%s), err is (%s)",
590                                 src_path, arch_path, err_str);
591                 return APP2EXT_ERROR_MOVE;
592         }
593
594         ret = _app2sd_delete_directory(src_path);
595         if (ret) {
596                 _E("unable to delete (%s)", src_path);
597                 return APP2EXT_ERROR_DELETE_DIRECTORY;
598         }
599
600         return ret;
601 }
602
603 static int _app2sd_move_app_to_external(const char *pkgid, GList *dir_list,
604                 uid_t uid, char *mmc_path, char **image_path)
605 {
606         int ret;
607         mode_t mode = DIR_PERMS;
608         char temp_dir_path[FILENAME_MAX];
609         char app_mmc_path[FILENAME_MAX];
610         char app_archive_path[FILENAME_MAX];
611         char application_path[FILENAME_MAX];
612         char loopback_device[FILENAME_MAX];
613         unsigned long long total_size = 0;
614         int reqd_size;
615         int reqd_disk_size;
616         char *device_node;
617         int free_mmc_mem;
618         FILE *fp;
619         GList *list;
620         app2ext_dir_details *dir_detail;
621         char err_buf[1024];
622         const char *err_str;
623
624         ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
625                         loopback_device, sizeof(loopback_device));
626         if (ret)
627                 return ret;
628
629         _app2sd_set_application_path(pkgid, uid, application_path,
630                         sizeof(application_path));
631
632         /* check whether application is in external memory or not */
633         fp = fopen(loopback_device, "r+");
634         if (fp != NULL) {
635                 _W("Already %s entry is present in the SD Card, "
636                                 "delete entry and go on without return", pkgid);
637                 fclose(fp);
638                 _app2sd_force_clean(pkgid, application_path, loopback_device,
639                                 uid);
640         }
641
642         ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
643                         application_path);
644         if (ret < 0 || ret > sizeof(app_mmc_path)) {
645                 _E("snprintf fail");
646                 return APP2EXT_ERROR_CREATE_DIRECTORY;
647         }
648         ret = snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
649                         application_path);
650         if (ret < 0 || ret > sizeof(app_archive_path)) {
651                 _E("snprintf fail");
652                 return APP2EXT_ERROR_CREATE_DIRECTORY;
653         }
654
655         ret = mkdir(app_mmc_path, mode);
656         if (ret) {
657                 if (errno != EEXIST) {
658                         _E("unable to create directory for archiving,"
659                                         " error(%d)", errno);
660                         return APP2EXT_ERROR_CREATE_DIRECTORY;
661                 }
662         }
663
664         ret = mkdir(app_archive_path, mode);
665         if (ret) {
666                 if (errno != EEXIST) {
667                         _E("unable to create directory for archiving,"
668                                         " error(%d)", errno);
669                         return APP2EXT_ERROR_CREATE_DIRECTORY;
670                 }
671         }
672
673         for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
674                 dir_detail = (app2ext_dir_details *)list->data;
675                 if (dir_detail == NULL || dir_detail->name == NULL ||
676                                 dir_detail->type != APP2EXT_DIR_RO)
677                         continue;
678                 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
679                                 application_path, dir_detail->name);
680                 if (ret < 0 || ret > sizeof(temp_dir_path)) {
681                         _E("snprintf fail");
682                         return APP2EXT_ERROR_MMC_STATUS;
683                 }
684                 _D("cal size of app dirs, temp_dir_path(%s)", temp_dir_path);
685                 total_size += _app2sd_calculate_dir_size(temp_dir_path);
686         }
687
688         reqd_size = ((total_size) / (1024 * 1024)) + 2;
689         reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
690
691         /* find avialable free memory in the MMC card */
692         ret = _app2sd_get_available_free_memory(mmc_path, &free_mmc_mem);
693         if (ret) {
694                 _E("unable to get available free memory in MMC (%d)", ret);
695                 return APP2EXT_ERROR_MMC_STATUS;
696         }
697         /* if avaialalbe free memory in MMC is less than
698          * required size + 5MB, return error
699          */
700         if (reqd_disk_size > free_mmc_mem) {
701                 _E("insufficient memory in MMC for "
702                                 "application installation (%d)", ret);
703                 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
704         }
705         /* create a loopback device */
706         ret = _app2sd_create_loopback_device(pkgid, loopback_device,
707                         (reqd_disk_size + PKG_BUF_SIZE));
708         if (ret) {
709                 _E("loopback node creation failed");
710                 return ret;
711         }
712
713         ret = _app2sd_dmcrypt_setup_device(pkgid, loopback_device, false, uid);
714         if (ret) {
715                 _E("dmcrypt setup device error(%d)", ret);
716                 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
717         }
718
719         ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device, false,
720                         uid, &device_node);
721         if (ret) {
722                 _E("dmcrypt open device error");
723                 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
724         }
725         /* format the loopback file system */
726         ret = _app2sd_create_file_system(device_node);
727         if (ret) {
728                 _E("create ext4 filesystem failed");
729                 ret = APP2EXT_ERROR_CREATE_FS;
730                 goto ERR;
731         }
732
733         for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
734                 dir_detail = (app2ext_dir_details *)list->data;
735                 if (dir_detail == NULL || dir_detail->name == NULL ||
736                                 dir_detail->type != APP2EXT_DIR_RO)
737                         continue;
738                 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
739                                 application_path, dir_detail->name);
740                 if (ret < 0 || ret > sizeof(temp_dir_path)) {
741                         _E("snprintf fail");
742                         ret = APP2EXT_ERROR_MOVE;
743                         goto ERR;
744                 }
745                 _D("app2archive, temp_dir_path(%s)", temp_dir_path);
746                 ret = _app2sd_move_to_archive(temp_dir_path, app_archive_path);
747                 if (ret) {
748                         _E("unable to copy from (%s) to (%s)",
749                                         temp_dir_path, app_archive_path);
750                         goto ERR;
751                 }
752         }
753
754         /* mount the loopback encrypted pseudo device on
755          * application installation path as with Read Write permission
756          */
757         ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
758                         MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
759         if (ret) {
760                 _E("mount failed");
761                 goto ERR;
762         }
763
764         for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
765                 dir_detail = (app2ext_dir_details *)list->data;
766                 if (dir_detail == NULL || dir_detail->name == NULL ||
767                                 dir_detail->type != APP2EXT_DIR_RO)
768                         continue;
769                 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
770                                 app_archive_path, dir_detail->name);
771                 if (ret < 0 || ret > sizeof(temp_dir_path)) {
772                         _E("snprintf fail");
773                         ret = APP2EXT_ERROR_COPY_DIRECTORY;
774                         goto ERR;
775                 }
776                 _D("archive2mmc, temp_dir_path(%s)", temp_dir_path);
777                 ret = _app2sd_copy_dir(temp_dir_path, app_mmc_path);
778                 if (ret) {
779                         if (ret == APP2EXT_ERROR_ACCESS_FILE) {
780                                 _E("unable to access (%s)", temp_dir_path);
781                         } else {
782                                 err_str = strerror_r(errno, err_buf,
783                                                 sizeof(err_buf));
784                                 _E("unable to copy from (%s) to (%s),"
785                                                 " error is (%s)", temp_dir_path,
786                                                 app_mmc_path, err_str);
787                         }
788                         goto ERR;
789                 }
790                 ret = _app2sd_delete_directory(temp_dir_path);
791                 if (ret) {
792                         _E("unable to delete (%s)", temp_dir_path);
793                         goto ERR;
794                 }
795         }
796
797         ret = _app2sd_delete_directory(app_archive_path);
798         if (ret) {
799                 _E("unable to delete (%s)", app_archive_path);
800                 ret = APP2EXT_ERROR_DELETE_DIRECTORY;
801                 goto ERR;
802         }
803
804         *image_path = strdup(loopback_device);
805         return APP2EXT_SUCCESS;
806
807 ERR:
808         if (device_node)
809                 free(device_node);
810
811         *image_path = NULL;
812         return ret;
813 }
814
815 static int _app2sd_move_app_to_internal(const char *pkgid, GList *dir_list,
816                 uid_t uid, char *mmc_path)
817 {
818         int ret;
819         mode_t mode = DIR_PERMS;
820         char temp_dir_path[FILENAME_MAX];
821         char app_mmc_path[FILENAME_MAX];
822         char app_archive_path[FILENAME_MAX];
823         char application_path[FILENAME_MAX];
824         char loopback_device[FILENAME_MAX];
825         char *device_node;
826         FILE *fp;
827         GList *list;
828         app2ext_dir_details *dir_detail;
829         int reqd_size;
830         int free_internal_mem;
831         unsigned long long temp = 0;
832         char err_buf[1024];
833         const char *err_str;
834         int mount_type;
835
836         ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
837                         loopback_device, sizeof(loopback_device));
838         if (ret)
839                 return ret;
840
841         _app2sd_set_application_path(pkgid, uid, application_path,
842                 sizeof(application_path));
843
844         /* check whether application is in external memory or not */
845         fp = fopen(loopback_device, "r+");
846         if (fp == NULL) {
847                 _E("application (%s) is not installed on SD Card",
848                      pkgid);
849                 return APP2EXT_ERROR_FILE_ABSENT;
850         }
851         fclose(fp);
852
853         /* find avialable free memory in the internal storage */
854         ret = _app2sd_get_available_free_memory(INTERNAL_STORAGE_PATH,
855                         &free_internal_mem);
856         if (ret) {
857                 _E("unable to get available free memory in internal (%d)", ret);
858                 return APP2EXT_ERROR_MMC_STATUS;
859         }
860
861         fp = fopen(loopback_device, "r+");
862         if (fp == NULL) {
863                 _E("app entry is not present in SD card");
864                 return APP2EXT_ERROR_INVALID_PACKAGE;
865         }
866         fclose(fp);
867
868         /* get installed app size*/
869         temp = _app2sd_calculate_file_size(loopback_device);
870         reqd_size = (int)((temp) / (1024 * 1024));
871         _D("reqd size is (%d)", reqd_size);
872
873         if (reqd_size == 0) {
874                 _E("app entry is not present in SD Card");
875                 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
876         }
877
878         _I("reqd size: (%d)MB, free internal mem: (%d)MB",
879                         reqd_size, free_internal_mem);
880
881         /* if avaialalbe free memory in internal storage is
882          * less than required size, return error
883          */
884         if (reqd_size > free_internal_mem) {
885                 _E("innsufficient memory in internal storage"
886                         " for application installation (%d)", ret);
887                 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
888         }
889
890         device_node =
891                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
892         if (device_node == NULL) {
893                 /* do loopback setup */
894                 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
895                                 false, uid, &device_node);
896                 if (ret) {
897                         _E("dmcrypt open device error(%d)", ret);
898                         return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
899                 }
900                 mount_type = MOUNT_TYPE_RW;
901         } else {
902                 mount_type = MOUNT_TYPE_RW_REMOUNT;
903         }
904         /* do mounting */
905         ret = _app2sd_mount_app_content(application_path,
906                         pkgid, device_node, mount_type,
907                         dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
908         if (ret) {
909                 _E("mount failed");
910                 ret = APP2EXT_ERROR_MOUNT_PATH;
911                 goto ERR;
912         }
913
914         ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
915                         application_path);
916         if (ret < 0 || ret > sizeof(app_mmc_path)) {
917                 _E("snprintf fail");
918                 ret = -1;
919                 goto ERR;
920         }
921         ret = snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
922                         application_path);
923         if (ret < 0 || ret > sizeof(app_archive_path)) {
924                 _E("snprintf fail");
925                 ret = -1;
926                 goto ERR;
927         }
928
929         ret = mkdir(app_archive_path, mode);
930         if (ret) {
931                 if (errno != EEXIST) {
932                         _E("unable to create directory for archiving,"
933                                         " error(%d)", errno);
934                         ret = APP2EXT_ERROR_CREATE_DIRECTORY;
935                         goto ERR;
936                 }
937         }
938
939         for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
940                 dir_detail = (app2ext_dir_details *)list->data;
941                 if (dir_detail == NULL || dir_detail->name == NULL ||
942                                 dir_detail->type != APP2EXT_DIR_RO)
943                         continue;
944                 /* archiving code */
945                 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
946                                 app_mmc_path, dir_detail->name);
947                 if (ret < 0 || ret > sizeof(temp_dir_path)) {
948                         _E("snprintf fail");
949                         ret = -1;
950                         goto ERR;
951                 }
952                 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
953                 ret = _app2sd_copy_dir(temp_dir_path, app_archive_path);
954                 if (ret) {
955                         if (ret == APP2EXT_ERROR_ACCESS_FILE) {
956                                 _E("unable to access (%s)", temp_dir_path);
957                         } else {
958                                 err_str = strerror_r(errno, err_buf,
959                                                 sizeof(err_buf));
960                                 _E("unable to copy from (%s) to (%s),"
961                                                 "error is (%s)", temp_dir_path,
962                                                 app_archive_path, err_str);
963                         }
964                         goto ERR;
965                 }
966                 /* delete the symbolic link files [bin, lib, res]*/
967                 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
968                                 application_path, dir_detail->name);
969                 if (ret < 0 || ret > sizeof(temp_dir_path)) {
970                         _E("snprintf fail");
971                         ret = -1;
972                         goto ERR;
973                 }
974                 _D("unlink, temp_dir_path(%s)", temp_dir_path);
975                 ret = unlink(temp_dir_path);
976                 if (ret) {
977                         if (errno == ENOENT) {
978                                 _W("(%s) does not exist", temp_dir_path);
979                         } else {
980                                 _E("unable to remove the symbolic link file "
981                                                 "(%s), it is already unlinked",
982                                                 temp_dir_path);
983                                 goto ERR;
984                         }
985                 }
986                 /* Copy content to destination */
987                 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
988                                 app_archive_path, dir_detail->name);
989                 if (ret < 0 || ret > sizeof(temp_dir_path)) {
990                         _E("snprintf fail");
991                         ret = -1;
992                         goto ERR;
993                 }
994                 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
995                 ret = _app2sd_copy_dir(temp_dir_path, application_path);
996                 if (ret) {
997                         if (ret == APP2EXT_ERROR_ACCESS_FILE) {
998                                 _E("unable to access (%s)", temp_dir_path);
999                         } else {
1000                                 err_str = strerror_r(errno, err_buf,
1001                                                 sizeof(err_buf));
1002                                 _E("unable to copy from (%s) to (%s), "
1003                                                 "error is (%s)", temp_dir_path,
1004                                                 application_path, err_str);
1005                         }
1006                         goto ERR;
1007                 }
1008         }
1009
1010         _D("copying file completed");
1011         ret = _app2sd_unmount_app_content(application_path);
1012         if (ret)
1013                 _E("unable to unmount SD directory for app (%s)", pkgid);
1014
1015         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1016         if (ret)
1017                 _E("close dmcrypt device error(%d)", ret);
1018
1019         ret = _app2sd_delete_loopback_device(loopback_device);
1020         if (ret)
1021                 _E("unable to delete the loopback device for (%s)", pkgid);
1022
1023         ret = _app2sd_delete_directory(app_mmc_path);
1024         if (ret)
1025                 _E("unable to delete (%s)", app_mmc_path);
1026
1027         ret = _app2sd_delete_directory(app_archive_path);
1028         if (ret)
1029                 _E("unable to delete (%s)", app_archive_path);
1030
1031         /* remove passwrd from DB */
1032         ret = _app2sd_initialize_db();
1033         if (ret)
1034                 _E("app2sd db initialize failed");
1035
1036         ret = _app2sd_remove_info_from_db(pkgid, uid);
1037         if (ret)
1038                 _E("cannot remove info from db");
1039
1040         return APP2EXT_SUCCESS;
1041
1042 ERR:
1043         if (device_node)
1044                 free(device_node);
1045
1046         return ret;
1047 }
1048
1049 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
1050                 GList *dir_list, uid_t uid, char *mmc_path, char **image_path)
1051 {
1052         int ret;
1053
1054         switch (move_type) {
1055         case APP2EXT_MOVE_TO_EXT:
1056                 ret = _app2sd_move_app_to_external(pkgid, dir_list,
1057                                 uid, mmc_path, image_path);
1058                 if (ret) {
1059                         _E("move app to external memory failed(%d)", ret);
1060                         return ret;
1061                 }
1062                 break;
1063         case APP2EXT_MOVE_TO_PHONE:
1064                 ret = _app2sd_move_app_to_internal(pkgid, dir_list,
1065                                 uid, mmc_path);
1066                 if (ret) {
1067                         _E("move app to internal memory failed(%d)", ret);
1068                         return ret;
1069                 }
1070                 break;
1071         default:
1072                 _E("invalid argument");
1073                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1074         }
1075
1076         return ret;
1077 }
1078
1079 int _app2sd_copy_ro_content(const char *src, const char *dest, GList *dir_list)
1080 {
1081         char path[FILENAME_MAX];
1082         int ret;
1083         GList *list;
1084         app2ext_dir_details *dir_detail;
1085
1086         for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
1087                 dir_detail = (app2ext_dir_details *)list->data;
1088                 if (dir_detail == NULL || dir_detail->name == NULL ||
1089                                 dir_detail->type != APP2EXT_DIR_RO)
1090                         continue;
1091
1092                 snprintf(path, sizeof(path), "%s/%s", src, dir_detail->name);
1093                 ret = _app2sd_copy_dir(path, dest);
1094                 if (ret) {
1095                         if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1096                                 _E("unable to access (%s)", path);
1097                         } else {
1098                                 _E("unable to copy from (%s) "
1099                                                 "to (%s), errno is (%d)",
1100                                                 path, dest, errno);
1101                                 return APP2EXT_ERROR_MOVE;
1102                         }
1103                 }
1104         }
1105
1106         return APP2EXT_SUCCESS;
1107 }
1108
1109 int _app2sd_duplicate_device(const char *pkgid, const char *loopback_device,
1110                 const char *temp_pkgid, const char *temp_application_path,
1111                 const char *temp_loopback_device, GList *dir_list,
1112                 char *dev_node, int size, uid_t uid)
1113 {
1114         int ret;
1115         int err_res;
1116
1117         /* create a new loopback device */
1118         ret = _app2sd_create_loopback_device(temp_pkgid,
1119                         temp_loopback_device, (size + PKG_BUF_SIZE));
1120         if (ret) {
1121                 _E("package already present");
1122                 return ret;
1123         }
1124
1125         /* perform loopback encryption setup */
1126         dev_node = _app2sd_dmcrypt_duplicate_encryption_setup(pkgid,
1127                         temp_loopback_device, uid);
1128         if (!dev_node) {
1129                 _E("dmcrypt duplicate encryption setup failed");
1130                 _app2sd_delete_loopback_device(temp_loopback_device);
1131                 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
1132         }
1133
1134         /* format the loopback file system */
1135         ret = _app2sd_create_file_system(dev_node);
1136         if (ret) {
1137                 _E("creating fs failed");
1138                 err_res = APP2EXT_ERROR_CREATE_FS;
1139                 goto FINISH_OFF;
1140         }
1141         _D("create filesystem SUCCESS");
1142
1143         /* do mounting for new dev*/
1144         ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1145                         dev_node, MOUNT_TYPE_RW, dir_list,
1146                         APP2SD_PRE_UPGRADE, uid);
1147         if (ret) {
1148                 _E("remount failed");
1149                 err_res = APP2EXT_ERROR_MOUNT_PATH;
1150                 goto FINISH_OFF;
1151         }
1152
1153         return APP2EXT_SUCCESS;
1154
1155 FINISH_OFF:
1156         if (dev_node) {
1157                 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1158                 if (ret)
1159                         _E("close dmcrypt device error(%d)", ret);
1160                 _app2sd_delete_loopback_device(temp_loopback_device);
1161                 free(dev_node);
1162         }
1163
1164         return err_res;
1165 }
1166
1167 int _app2sd_update_loopback_device_size(const char *pkgid,
1168                 const char *loopback_device, const char *application_path,
1169                 const char *temp_pkgid, const char *temp_loopback_device,
1170                 const char *temp_application_path, int size, GList *dir_list,
1171                 uid_t uid)
1172 {
1173         int ret;
1174         char *old_device_node;
1175         int err_res;
1176         char app_mmc_path[FILENAME_MAX];
1177         char temp_app_mmc_path[FILENAME_MAX];
1178         int mount_type;
1179
1180         ret = _app2sd_duplicate_device(pkgid, loopback_device, temp_pkgid,
1181                         temp_application_path, temp_loopback_device,
1182                         dir_list, NULL, size, uid);
1183         if (ret) {
1184                 _E("creating duplicate device failed");
1185                 return ret;
1186         }
1187
1188         /* get the associated device node for SD card applicatione */
1189         old_device_node =
1190                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1191         if (old_device_node == NULL) {
1192                 /* do loopback setup */
1193                 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1194                         false, uid, &old_device_node);
1195                 if (ret) {
1196                         _E("dmcrypt open device error");
1197                         err_res = APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1198                         goto FINISH_OFF;
1199                 }
1200                 mount_type = MOUNT_TYPE_RW;
1201         } else {
1202                 mount_type = MOUNT_TYPE_RW_REMOUNT;
1203         }
1204
1205         /* do mounting */
1206         ret = _app2sd_mount_app_content(application_path, pkgid,
1207                         old_device_node, mount_type, dir_list,
1208                         APP2SD_PRE_UPGRADE, uid);
1209         if (ret) {
1210                 _E("remount failed");
1211                 err_res = APP2EXT_ERROR_MOUNT_PATH;
1212         }
1213         free(old_device_node);
1214
1215         snprintf(app_mmc_path, sizeof(app_mmc_path),
1216                         "%s/.mmc", application_path);
1217         snprintf(temp_app_mmc_path, sizeof(temp_app_mmc_path),
1218                         "%s/.mmc", temp_application_path);
1219
1220         ret = _app2sd_copy_ro_content(app_mmc_path,
1221                         temp_app_mmc_path, dir_list);
1222         if (ret) {
1223                 _E("copy ro content failed");
1224                 err_res = ret;
1225         }
1226
1227         ret = _app2sd_unmount_app_content(application_path);
1228         if (ret) {
1229                 _E("unable to unmount the SD application");
1230                 err_res = APP2EXT_ERROR_UNMOUNT;
1231         }
1232
1233         ret = _app2sd_unmount_app_content(temp_application_path);
1234         if (ret) {
1235                 _E("unable to unmount the SD application");
1236                 err_res = APP2EXT_ERROR_UNMOUNT;
1237                 goto FINISH_OFF;
1238         }
1239
1240         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1241         if (ret) {
1242                 _E("close dmcrypt device error(%d)", ret);
1243                 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1244                 goto FINISH_OFF;
1245         }
1246
1247         ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1248         if (ret) {
1249                 _E("close dmcrypt device error(%d)", ret);
1250                 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1251                 goto FINISH_OFF;
1252         }
1253
1254         ret = _app2sd_delete_directory(loopback_device);
1255         if (ret) {
1256                 _E("unable to delete (%s)", loopback_device);
1257                 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1258                 goto FINISH_OFF;
1259         }
1260
1261         ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1262         if (ret) {
1263                 _E("unable to rename (%s)", temp_loopback_device);
1264                 err_res = APP2EXT_ERROR_MOVE;
1265                 goto FINISH_OFF;
1266         }
1267
1268         ret = _app2sd_delete_directory(temp_application_path);
1269         if (ret) {
1270                 _E("unable to delete (%s)", temp_application_path);
1271                 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1272                 goto FINISH_OFF;
1273         }
1274
1275         return APP2EXT_SUCCESS;
1276
1277 FINISH_OFF:
1278         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1279         if (ret)
1280                 _E("close dmcrypt device error(%d)", ret);
1281
1282         ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1283         if (ret)
1284                 _E("close dmcrypt device error(%d)", ret);
1285
1286         _app2sd_delete_loopback_device(temp_loopback_device);
1287
1288         ret = _app2sd_delete_directory(temp_application_path);
1289         if (ret)
1290                 _E("unable to delete (%s)", temp_application_path);
1291
1292         return err_res;
1293 }
1294
1295 int _app2sd_force_clean(const char *pkgid, const char *application_path,
1296                 const char *loopback_device, uid_t uid)
1297 {
1298         int ret;
1299
1300         /* unmount the loopback encrypted pseudo device from
1301          * the application installation path
1302          */
1303         ret = _app2sd_unmount_app_content(application_path);
1304         if (ret)
1305                 _W("unable to unmount the app content (%d)", ret);
1306
1307         /* detach the loopback encryption setup for the application */
1308         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1309         if (ret)
1310                 _W("close dmcrypt device error (%d)", ret);
1311
1312         /* delete the loopback device from the SD card */
1313         ret = _app2sd_delete_loopback_device(loopback_device);
1314         if (ret)
1315                 _W("unable to detach the loopback encryption setup for "
1316                                 "the application");
1317
1318         /* delete symlink */
1319         _app2sd_delete_symlink(application_path);
1320
1321         /* remove passwrd from DB */
1322         ret = _app2sd_initialize_db();
1323         if (ret)
1324                 _W("app2sd db initialize failed");
1325
1326         ret = _app2sd_remove_info_from_db(pkgid, uid);
1327         if (ret)
1328                 _W("cannot remove info from db");
1329
1330         return ret;
1331 }