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