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