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