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