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