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