8f990dbf4b83c84f7b72812874c447c5fda55efa
[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
750         /* check whether MMC is present or not */
751         ret = _app2sd_check_mmc_status();
752         if (ret) {
753                 _E("MMC not preset OR Not ready(%d)", ret);
754                 return APP2EXT_ERROR_MMC_STATUS;
755         }
756
757         if (_is_global(uid)) {
758                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
759                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
760                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
761                         APP2SD_PATH, pkgid);
762         } else {
763                 tzplatform_set_user(uid);
764                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
765                         tzplatform_getenv(TZ_USER_APP), pkgid);
766                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
767                         APP2SD_PATH, tzplatform_getenv(TZ_USER_NAME), pkgid);
768                 tzplatform_reset_user();
769         }
770         _D("application_path = (%s)", application_path);
771         _D("loopback_device = (%s)", loopback_device);
772
773         /* check whether application is in external memory or not */
774         fp = fopen(loopback_device, "r+");
775         if (fp != NULL) {
776                 _W("Already %s entry is present in the SD Card, " \
777                         "delete entry and go on without return", pkgid);
778                 fclose(fp);
779                 app2sd_usr_force_clean(pkgid, uid);
780         }
781
782         snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
783                 application_path);
784         snprintf(application_archive_path, FILENAME_MAX - 1, "%s/.archive",
785                 application_path);
786         _D("application_mmc_path = (%s)", application_mmc_path);
787         _D("application_archive_path = (%s)", application_archive_path);
788
789         ret = mkdir(application_archive_path, mode);
790         if (ret) {
791                 if (errno != EEXIST) {
792                         _E("unable to create directory for archiving," \
793                                 " error(%d)", errno);
794                         return APP2EXT_ERROR_CREATE_DIRECTORY;
795                 }
796         }
797
798         list = g_list_first(dir_list);
799         while (list) {
800                 dir_detail = (app2ext_dir_details *)list->data;
801                 if (dir_detail && dir_detail->name
802                         && dir_detail->type == APP2EXT_DIR_RO) {
803                         memset(temp_dir_path, '\0', FILENAME_MAX);
804                         snprintf(temp_dir_path, FILENAME_MAX,
805                                  "%s/%s", application_path,
806                                  dir_detail->name);
807                         _D("cal size of app dirs, temp_dir_path(%s)",
808                                 temp_dir_path);
809                         total_size +=
810                             _app2sd_calculate_dir_size(temp_dir_path);
811                 }
812                 list = g_list_next(list);
813         }
814
815         reqd_size = ((total_size) / ( 1024 * 1024)) + 2;
816         reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
817
818         /* find avialable free memory in the MMC card */
819         ret = _app2sd_get_available_free_memory(MMC_PATH, &free_mmc_mem);
820         if (ret) {
821                 _E("unable to get available free memory in MMC (%d)", ret);
822                 return APP2EXT_ERROR_MMC_STATUS;
823         }
824         /* if avaialalbe free memory in MMC is less than
825          * required size + 5MB, return error
826          */
827         if (reqd_disk_size > free_mmc_mem) {
828                 _E("insufficient memory in MMC for application installation (%d)",
829                         ret);
830                 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
831         }
832         /* create a loopback device */
833         ret = _app2sd_create_loopback_device(pkgid, loopback_device,
834                 (reqd_disk_size + PKG_BUF_SIZE));
835         if (ret) {
836                 _E("loopback node creation failed");
837                 return ret;
838         }
839         /* perform loopback encryption setup */
840         device_node = _app2sd_do_loopback_encryption_setup(pkgid,
841                 loopback_device, uid);
842         if (!device_node) {
843                 _E("loopback encryption setup failed");
844                 return APP2EXT_ERROR_DO_LOSETUP;
845         }
846         _D("device_node (%s)", device_node);
847         /* check whether loopback device is associated with device node or not */
848         devi = _app2sd_find_associated_device_node(loopback_device);
849         if (devi == NULL) {
850                 _E("finding associated device node failed");
851                 return APP2EXT_ERROR_DO_LOSETUP;
852         } else {
853                 free(devi);
854                 devi = NULL;
855         }
856         /* format the loopback file system */
857         ret = _app2sd_create_file_system(device_node);
858         if (ret) {
859                 _E("create ext4 filesystem failed");
860                 return APP2EXT_ERROR_CREATE_FS;
861         }
862
863         list = g_list_first(dir_list);
864         while (list) {
865                 dir_detail = (app2ext_dir_details *)list->data;
866                 if (dir_detail && dir_detail->name
867                         && dir_detail->type == APP2EXT_DIR_RO) {
868                         memset(temp_dir_path, '\0', FILENAME_MAX);
869                         snprintf(temp_dir_path, FILENAME_MAX,
870                                  "%s/%s", application_path,
871                                 dir_detail->name);
872                         _D("app2archive, temp_dir_path(%s)",
873                                 temp_dir_path);
874                         ret = _app2sd_move_to_archive(temp_dir_path,
875                                 application_archive_path);
876                         if (ret) {
877                                 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
878                                         _E("unable to access (%s)",
879                                                 temp_dir_path);
880                                 } else {
881                                         _E("unable to copy from (%s) to (%s)",
882                                              temp_dir_path,
883                                              application_archive_path);
884                                 }
885                                 return ret;
886                         }
887                 }
888                 list = g_list_next(list);
889         }
890
891         /* mount the loopback encrypted pseudo device on application installation path
892          * as with Read Write permission
893          */
894         ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
895                 MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
896         if (ret) {
897                 _E("mount failed");
898                 return ret;
899         }
900
901         list = g_list_first(dir_list);
902         while (list) {
903                 dir_detail = (app2ext_dir_details *)list->data;
904                 if (dir_detail && dir_detail->name
905                         && dir_detail->type == APP2EXT_DIR_RO) {
906                         memset(temp_dir_path, '\0', FILENAME_MAX);
907                         snprintf(temp_dir_path, FILENAME_MAX,
908                                 "%s/%s", application_archive_path,
909                                 dir_detail->name);
910                         _D("archive2mmc, temp_dir_path(%s)",
911                                 temp_dir_path);
912                         ret = _app2sd_copy_dir(temp_dir_path,
913                                 application_mmc_path);
914                         if (ret) {
915                                 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
916                                         _E("unable to access (%s)",
917                                                 temp_dir_path);
918                                 } else {
919                                         strerror_r(errno,
920                                                 err_buf, sizeof(err_buf));
921                                         _E("unable to copy from (%s) to (%s)," \
922                                                 " error is (%s)",
923                                                 temp_dir_path,
924                                                 application_mmc_path, err_buf);
925                                 }
926                                 return ret;
927                         }
928                         ret = _app2sd_delete_directory(temp_dir_path);
929                         if (ret) {
930                                 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
931                                         _E("unable to access (%s)",
932                                                 temp_dir_path);
933                                 } else {
934                                         _E("unable to delete (%s)",
935                                                 temp_dir_path);
936                                 }
937                                 return ret;
938                         }
939                 }
940                 list = g_list_next(list);
941         }
942
943         ret = _app2sd_delete_directory(application_archive_path);
944         if (ret) {
945                 _E("unable to delete (%s)", application_archive_path);
946                 return APP2EXT_ERROR_DELETE_DIRECTORY;
947         }
948
949         ret = _app2sd_apply_app_smack(application_path, pkgid, dir_list, uid);
950         if (ret) {
951                 _E("unable to apply app smack");
952                 return APP2EXT_ERROR_MOVE;
953         }
954
955         /* re-mount the loopback encrypted pseudo device on application installation path
956          * as with Read Only permission
957          */
958         ret = _app2sd_unmount_app_content(application_path);
959         if (ret) {
960                 _E("unmount error (%d)", ret);
961                 return APP2EXT_ERROR_UNMOUNT;
962         }
963         ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
964         if (ret) {
965                 _E("unable to detach loopback setup for (%s)",
966                         loopback_device);
967                 return APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
968         }
969
970         return APP2EXT_SUCCESS;
971 }
972
973 int _app2sd_move_app_to_internal(const char *pkgid, GList* dir_list, uid_t uid)
974 {
975         int ret = APP2EXT_SUCCESS;
976         mode_t mode = DIR_PERMS;
977         char temp_dir_path[FILENAME_MAX] = { 0, };
978         char application_mmc_path[FILENAME_MAX] = { 0, };
979         char application_archive_path[FILENAME_MAX] = { 0, };
980         char application_path[FILENAME_MAX] = { 0, };
981         char loopback_device[FILENAME_MAX] = { 0, };
982         char *device_node = NULL;
983         FILE *fp = NULL;
984         GList *list = NULL;
985         app2ext_dir_details* dir_detail = NULL;
986         int reqd_size = 0;
987         int free_internal_mem = 0;
988         struct statvfs buf = {0,};
989         unsigned long long temp = 0;
990         char err_buf[1024] = {0,};
991
992         /* check whether MMC is present or not */
993         ret = _app2sd_check_mmc_status();
994         if (ret) {
995                 _E("MMC not preset OR Not ready(%d)", ret);
996                 return APP2EXT_ERROR_MMC_STATUS;
997         }
998
999         if (_is_global(uid)) {
1000                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1001                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1002                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1003                         APP2SD_PATH, pkgid);
1004         } else {
1005                 tzplatform_set_user(uid);
1006                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1007                         tzplatform_getenv(TZ_USER_APP), pkgid);
1008                 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
1009                         APP2SD_PATH, tzplatform_getenv(TZ_USER_NAME), pkgid);
1010                 tzplatform_reset_user();
1011         }
1012         _D("application_path = (%s)", application_path);
1013         _D("loopback_device = (%s)", loopback_device);
1014
1015         /* check whether application is in external memory or not */
1016         fp = fopen(loopback_device, "r+");
1017         if (fp == NULL) {
1018                 _E("application (%s) is not installed on SD Card",
1019                      pkgid);
1020                 return APP2EXT_ERROR_FILE_ABSENT;
1021         } else {
1022                 fclose(fp);
1023                 fp = NULL;
1024         }
1025
1026         memset((void *)&buf, '\0', sizeof(struct statvfs));
1027         ret = statvfs(INTERNAL_STORAGE_PATH, &buf);
1028         if (0 == ret){
1029                 temp = (buf.f_bsize * buf.f_bavail) / (1024 * 1024);
1030                 free_internal_mem = (int)temp;
1031         } else {
1032                 _E("unable to get internal storage size");
1033                 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
1034         }
1035
1036         fp = fopen(loopback_device, "r+");
1037         if (fp == NULL) {
1038                 _E("app entry is not present in SD card");
1039                 return APP2EXT_ERROR_INVALID_PACKAGE;
1040         }
1041         fclose(fp);
1042
1043         /* get installed app size*/
1044         temp = _app2sd_calculate_file_size(loopback_device);
1045         reqd_size = (int)((temp) / (1024 * 1024));
1046         _D("reqd size is (%d)", reqd_size);
1047
1048         if (reqd_size == 0) {
1049                 _E("app entry is not present in SD Card");
1050                 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
1051         }
1052
1053         _D("reqd size: (%d)MB, free internal mem: (%d)MB",
1054                 reqd_size, free_internal_mem);
1055
1056         /* if avaialalbe free memory in internal storage is
1057          * less than required size, return error
1058          */
1059         if (reqd_size > free_internal_mem) {
1060                 _E("innsufficient memory in internal storage" \
1061                         " for application installation (%d)", ret);
1062                 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
1063         }
1064
1065         device_node = _app2sd_find_associated_device_node(loopback_device);
1066         if (NULL == device_node) {
1067                 /* do loopback setup */
1068                 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1069                         loopback_device, uid);
1070                 if (device_node == NULL) {
1071                         _E("loopback encryption setup failed");
1072                         return APP2EXT_ERROR_DO_LOSETUP;
1073                 }
1074                 /* do mounting */
1075                 ret = _app2sd_mount_app_content(application_path,
1076                         pkgid, device_node, MOUNT_TYPE_RW,
1077                         dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1078                 if (ret) {
1079                         _E("mount failed");
1080                         return APP2EXT_ERROR_MOUNT_PATH;
1081                 }
1082         } else {
1083                 /* do re-mounting */
1084                 ret = _app2sd_mount_app_content(application_path,
1085                         pkgid, device_node, MOUNT_TYPE_RW_REMOUNT,
1086                         dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1087                 if (ret) {
1088                         _E("re-mount failed");
1089                         return APP2EXT_ERROR_MOUNT_PATH;
1090                 }
1091         }
1092
1093         snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
1094                 application_path);
1095         snprintf(application_archive_path, FILENAME_MAX - 1, "%s/.archive",
1096                 application_path);
1097         _D("application_mmc_path = (%s)", application_mmc_path);
1098         _D("application_archive_path = (%s)", application_archive_path);
1099
1100         ret = mkdir(application_archive_path, mode);
1101         if (ret) {
1102                 if (errno != EEXIST) {
1103                         _E("unable to create directory for archiving," \
1104                                 " error(%d)", errno);
1105                         return APP2EXT_ERROR_CREATE_DIRECTORY;
1106                 }
1107         }
1108
1109         list = g_list_first(dir_list);
1110         while (list) {
1111                 dir_detail = (app2ext_dir_details *)list->data;
1112                 if (dir_detail && dir_detail->name
1113                         && dir_detail->type == APP2EXT_DIR_RO) {
1114                         /* archiving code */
1115                         memset(temp_dir_path, '\0', FILENAME_MAX);
1116                         snprintf(temp_dir_path, FILENAME_MAX,
1117                                  "%s/%s", application_mmc_path,
1118                                  dir_detail->name);
1119                         _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
1120                         ret = _app2sd_copy_dir(temp_dir_path,
1121                                      application_archive_path);
1122                         if (ret) {
1123                                 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1124                                         _E("unable to access (%s)",
1125                                                 temp_dir_path);
1126                                 } else {
1127                                         strerror_r(errno,
1128                                                 err_buf, sizeof(err_buf));
1129                                         _E("unable to copy from (%s) to (%s),"
1130                                                 " error is (%s)",
1131                                                 temp_dir_path,
1132                                                 application_archive_path, err_buf);
1133                                 }
1134                                 return ret;
1135                         }
1136
1137                         /* delete the symbolic link files [bin, lib, res]*/
1138                         memset(temp_dir_path, '\0', FILENAME_MAX);
1139                         snprintf(temp_dir_path, FILENAME_MAX,
1140                                  "%s/%s", application_path,
1141                                  dir_detail->name);
1142                         _D("unlink, temp_dir_path(%s)", temp_dir_path);
1143                         ret = unlink(temp_dir_path);
1144                         if (ret) {
1145                                 if (errno == ENOENT) {
1146                                         _E("directory (%s) does not exist",
1147                                                 temp_dir_path);
1148                                 } else {
1149                                         _E("unable to remove the symbolic link file (%s)," \
1150                                                 " it is already unlinked",
1151                                                 temp_dir_path);
1152                                 }
1153                                 return ret;
1154                         }
1155
1156                         /* Copy content to destination */
1157                         memset(temp_dir_path, '\0', FILENAME_MAX);
1158                         snprintf(temp_dir_path, FILENAME_MAX,
1159                                 "%s/%s", application_archive_path,
1160                                 dir_detail->name);
1161                         _D("archive2app, temp_dir_path(%s)", temp_dir_path);
1162                         ret = _app2sd_copy_dir(temp_dir_path, application_path);
1163                         if (ret) {
1164                                 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1165                                         _E("unable to access (%s)",
1166                                                 temp_dir_path);
1167                                 } else {
1168                                         strerror_r(errno,
1169                                                 err_buf, sizeof(err_buf));
1170                                         _E("unable to copy from (%s) to (%s) " \
1171                                                 ", error is (%s)",
1172                                                 temp_dir_path,
1173                                                 application_path, err_buf);
1174                                 }
1175                                 return ret;
1176                         }
1177                 }
1178                 list = g_list_next(list);
1179         }
1180
1181         _D("copying file completed");
1182         ret = _app2sd_unmount_app_content(application_path);
1183         if (ret) {
1184                 _E("unable to unmount SD directory for app (%s)",
1185                      pkgid);
1186                 return APP2EXT_ERROR_UNMOUNT;
1187         }
1188         ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1189         if (ret) {
1190                 _E("unable to detach loopback setup for (%s)",
1191                      pkgid);
1192                 return APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
1193         }
1194         ret = _app2sd_delete_loopback_device(loopback_device);
1195         if (ret) {
1196                 _E("unable to delete the loopback device for (%s)",
1197                      pkgid);
1198                 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1199         }
1200         ret = _app2sd_delete_directory(application_mmc_path);
1201         if (ret) {
1202                 _E("unable to delete (%s)", application_mmc_path);
1203                 return APP2EXT_ERROR_DELETE_DIRECTORY;
1204         }
1205         ret = _app2sd_delete_directory(application_archive_path);
1206         if (ret) {
1207                 _E("unable to delete (%s)", application_archive_path);
1208                 return APP2EXT_ERROR_DELETE_DIRECTORY;
1209         }
1210
1211         return APP2EXT_SUCCESS;
1212 }
1213
1214 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
1215                 GList* dir_list, uid_t uid)
1216 {
1217         int ret = APP2EXT_SUCCESS;
1218
1219         /* Check whether MMC is present or not */
1220         ret = _app2sd_check_mmc_status();
1221         if (ret) {
1222                 _E("MMC not preset OR Not ready(%d)", ret);
1223                 return APP2EXT_ERROR_MMC_STATUS;
1224         }
1225
1226         switch (move_type) {
1227         case APP2EXT_MOVE_TO_EXT:
1228                 ret = _app2sd_move_app_to_external(pkgid, dir_list, uid);
1229                 if (ret) {
1230                         _E("move app to external memory failed(%d)", ret);
1231                         return ret;
1232                 }
1233                 break;
1234         case APP2EXT_MOVE_TO_PHONE:
1235                 ret = _app2sd_move_app_to_internal(pkgid, dir_list, uid);
1236                 if (ret) {
1237                         _E("move app to internal memory failed(%d)", ret);
1238                         return ret;
1239                 }
1240                 break;
1241         default:
1242                 _E("invalid argument");
1243                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1244         }
1245
1246         return ret;
1247 }
1248
1249 int _app2sd_copy_ro_content(const char *src, const char *dest, GList* dir_list)
1250 {
1251         char path[FILENAME_MAX] = { 0, };
1252         int ret = APP2EXT_SUCCESS;
1253         GList *list = NULL;
1254         app2ext_dir_details* dir_detail = NULL;
1255
1256         list = g_list_first(dir_list);
1257         while (list) {
1258                 dir_detail = (app2ext_dir_details *)list->data;
1259                 if (dir_detail && dir_detail->name
1260                         && dir_detail->type == APP2EXT_DIR_RO) {
1261                         memset((void *)&path, '\0', FILENAME_MAX);
1262                         snprintf(path, FILENAME_MAX - 1, "%s/%s", src,
1263                                  dir_detail->name);
1264                         ret = _app2sd_copy_dir(path, dest);
1265                         if (ret) {
1266                                 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1267                                         _E("unable to access (%s)", path);
1268                                 } else {
1269                                         _E("unable to copy from (%s) " \
1270                                                 "to (%s), errno is (%d)",
1271                                                 path, dest, errno);
1272                                         return APP2EXT_ERROR_MOVE;
1273                                 }
1274                         }
1275                 }
1276                 list = g_list_next(list);
1277         }
1278
1279         return APP2EXT_SUCCESS;
1280 }
1281
1282 int _app2sd_duplicate_device(const char *pkgid,
1283                 const char *loopback_device,
1284                 const char *temp_pkgid,
1285                 const char *temp_application_path,
1286                 const char *temp_loopback_device,
1287                 GList* dir_list, char *dev_node, int size,
1288                 uid_t uid)
1289 {
1290         int ret = 0;
1291         char *devi = NULL;
1292         int err_res = 0;
1293         char *result = NULL;
1294
1295         /* create a new loopback device */
1296         ret = _app2sd_create_loopback_device(temp_pkgid,
1297                 temp_loopback_device, (size + PKG_BUF_SIZE));
1298         if (ret) {
1299                 _E("package already present");
1300                 return ret;
1301         }
1302
1303         /* perform loopback encryption setup */
1304         dev_node = _app2sd_do_loopback_duplicate_encryption_setup(pkgid,
1305                 temp_pkgid, temp_loopback_device, uid);
1306         if (!dev_node) {
1307                 _E("losetup failed, device node is (%s)", dev_node);
1308                 _app2sd_delete_loopback_device(loopback_device);
1309                 _E("create ext filesystem failed");
1310                 return APP2EXT_ERROR_DO_LOSETUP;
1311         }
1312         _D("duplicate setup SUCCESS");
1313
1314         /* check whether loopback device is associated with
1315          * device node or not
1316          */
1317         devi = _app2sd_find_associated_device_node(temp_loopback_device);
1318         if (devi == NULL) {
1319                 _E("finding associated device node failed");
1320                 err_res = APP2EXT_ERROR_DO_LOSETUP;
1321                 goto FINISH_OFF;
1322         }
1323         _D("losetup SUCCESS");
1324
1325         /* format the loopback file system */
1326         ret = _app2sd_create_file_system(dev_node);
1327         if (ret) {
1328                 _E("creating fs failed");
1329                 err_res = APP2EXT_ERROR_CREATE_FS;
1330                 goto FINISH_OFF;
1331         }
1332         _D("create filesystem SUCCESS");
1333
1334         /* do mounting for new dev*/
1335         ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1336                 dev_node, MOUNT_TYPE_RW, dir_list,
1337                 APP2SD_PRE_UPGRADE, uid);
1338         if (ret) {
1339                 _E("remount failed");
1340                 err_res = APP2EXT_ERROR_MOUNT_PATH;
1341                 goto FINISH_OFF;
1342         }
1343
1344         if (devi) {
1345                 free(devi);
1346                 devi = NULL;
1347         }
1348
1349         return APP2EXT_SUCCESS;
1350
1351 FINISH_OFF:
1352         if (dev_node) {
1353                 result = _app2sd_detach_loop_device(dev_node);
1354                 if (result) {
1355                         free(result);
1356                         result = NULL;
1357                 }
1358                 _app2sd_delete_loopback_device(loopback_device);
1359                 free(dev_node);
1360                 dev_node = NULL;
1361         }
1362
1363         if (devi) {
1364                 free(devi);
1365                 devi = NULL;
1366         }
1367         return err_res;
1368 }
1369
1370 int _app2sd_update_loopback_device_size(const char *pkgid,
1371                 const char *loopback_device,
1372                 const char *application_path,
1373                 const char *temp_pkgid,
1374                 const char *temp_loopback_device,
1375                 const char *temp_application_path,
1376                 int size, GList* dir_list,
1377                 uid_t uid)
1378 {
1379         int ret = 0;
1380         char *device_node = NULL;
1381         char *old_device_node = NULL;
1382         int err_res = 0;
1383         char application_mmc_path[FILENAME_MAX] = { 0, };
1384         char temp_application_mmc_path[FILENAME_MAX] = { 0, };
1385
1386         ret = _app2sd_duplicate_device(pkgid, loopback_device,
1387                 temp_pkgid, temp_application_path, temp_loopback_device,
1388                 dir_list, device_node, size, uid);
1389         if (ret) {
1390                 _E("creating duplicate device failed");
1391                 return ret;
1392         }
1393
1394         /* get the associated device node for SD card applicatione */
1395         old_device_node = _app2sd_find_associated_device_node(loopback_device);
1396         if (NULL == old_device_node) {
1397                 /* do loopback setup */
1398                 old_device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1399                         loopback_device, uid);
1400                 if (old_device_node == NULL) {
1401                         _E("loopback encryption setup failed");
1402                         err_res = APP2EXT_ERROR_DO_LOSETUP;
1403                         goto FINISH_OFF;
1404                 }
1405                 /* do mounting */
1406                 ret = _app2sd_mount_app_content(application_path, pkgid,
1407                         old_device_node, MOUNT_TYPE_RW, dir_list,
1408                         APP2SD_PRE_UPGRADE, uid);
1409                 if (ret) {
1410                         _E("remount failed");
1411                         err_res = APP2EXT_ERROR_MOUNT_PATH;
1412                 }
1413         } else {
1414                 /* do re-mounting */
1415                 ret = _app2sd_mount_app_content(application_path, pkgid,
1416                         old_device_node, MOUNT_TYPE_RW_REMOUNT, dir_list,
1417                         APP2SD_PRE_UPGRADE, uid);
1418                 if (ret) {
1419                         _E("remount failed");
1420                         err_res = APP2EXT_ERROR_MOUNT_PATH;
1421                 }
1422         }
1423
1424         snprintf(application_mmc_path, FILENAME_MAX - 1,
1425                  "%s/.mmc", application_path);
1426         snprintf(temp_application_mmc_path, FILENAME_MAX - 1,
1427                 "%s/.mmc", temp_application_path);
1428
1429         ret = _app2sd_copy_ro_content(application_mmc_path,
1430                 temp_application_mmc_path, dir_list);
1431         if (ret) {
1432                 _E("copy ro content failed");
1433                 err_res = ret;
1434         }
1435
1436         ret = _app2sd_unmount_app_content(application_path);
1437         if (ret) {
1438                 _E("unable to unmount the SD application");
1439                 err_res = APP2EXT_ERROR_UNMOUNT;
1440         }
1441
1442         ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1443         if (ret) {
1444                 _E("unable to remove loopback setup");
1445                 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1446         }
1447
1448         ret = _app2sd_unmount_app_content(temp_application_path);
1449         if (ret) {
1450                 _E("unable to unmount the SD application");
1451                 err_res = APP2EXT_ERROR_UNMOUNT;
1452                 goto FINISH_OFF;
1453         }
1454
1455         ret = _app2sd_remove_loopback_encryption_setup(temp_loopback_device);
1456         if (ret) {
1457                 _E("unable to remove loopback setup");
1458                 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1459                 goto FINISH_OFF;
1460         }
1461
1462         ret = _app2sd_delete_directory(loopback_device);
1463         if (ret) {
1464                 _E("unable to delete (%s)", loopback_device);
1465                 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1466                 goto FINISH_OFF;
1467         }
1468
1469         ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1470         if (ret) {
1471                 _E("unable to rename (%s)", temp_loopback_device);
1472                 err_res = APP2EXT_ERROR_MOVE;
1473                 goto FINISH_OFF;
1474         }
1475
1476         ret = _app2sd_delete_directory(temp_application_path);
1477         if (ret) {
1478                 _E("unable to delete (%s)", temp_application_path);
1479                 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1480                 goto FINISH_OFF;
1481         }
1482
1483         return APP2EXT_SUCCESS;
1484
1485 FINISH_OFF:
1486         if (old_device_node) {
1487                 free(old_device_node);
1488                 old_device_node = NULL;
1489         }
1490
1491         ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1492         if (ret) {
1493                 _E("unable to remove loopback setup");
1494                 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1495         }
1496
1497         return err_res;
1498 }