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