Fix invalid log format
[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 #define _GNU_SOURCE
25 #include <dirent.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), errno(%d)", path, errno);
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, sizeof(dev), "%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, sizeof(dev_path), "/dev/loop%d", count);
149                 while ((fp = fopen(dev_path, "r+")) != NULL) {
150                         count = count + 1;
151                         snprintf(dev_path, sizeof(dev_path), "/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();
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();
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, sizeof(dmcrypt_setup_cmd),
401                 "/bin/echo '%s' | /sbin/cryptsetup -q -i %d " \
402                 "-c aes-cbc-lmk -s %d --align-payload=8 luksFormat %s",
403                 passwd, DMCRYPT_ITER_TIME, DMCRYPT_KEY_LEN, loopback_device);
404
405         ret = system(dmcrypt_setup_cmd);
406         if (ret) {
407                 strerror_r(errno, err_buf, sizeof(err_buf));
408                 _E("Error setting up dmcrypt on app2sd file, " \
409                         "error(%s), ret(%d)", err_buf, ret);
410                 if (passwd) {
411                         free(passwd);
412                         passwd = NULL;
413                 }
414                 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
415         }
416
417         if (passwd) {
418                 free(passwd);
419                 passwd = NULL;
420         }
421
422         return ret;
423 }
424
425 int _app2sd_dmcrypt_open_device(const char *pkgid, const char *loopback_device,
426                 bool is_dup, uid_t uid, char **dev_node)
427 {
428         int ret = APP2EXT_SUCCESS;
429         char *passwd;
430         char dmcrypt_open_cmd[BUF_SIZE] = { 0, };
431         char dev_name[BUF_SIZE] = { 0, };
432         char buf[BUF_SIZE] = { 0, };
433         int len = 0;
434
435         if (pkgid == NULL || loopback_device == NULL) {
436                 _E("invalid argument");
437                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
438         }
439
440         if (is_dup)
441                 snprintf(dev_name, sizeof(dev_name), "%s.new_%d", pkgid, uid);
442         else
443                 snprintf(dev_name, sizeof(dev_name), "%s_%d", pkgid, uid);
444
445         /* get password for dmcrypt encryption */
446         ret = _app2sd_initialize_db();
447         if (ret) {
448                 _E("app2sd db initialize failed");
449                 return APP2EXT_ERROR_DB_INITIALIZE;
450         }
451
452         passwd = _app2sd_get_password_from_db(pkgid, uid);
453         if (passwd == NULL) {
454                 _E("no password found for [%s]", pkgid);
455                 return APP2EXT_ERROR_SQLITE_REGISTRY;
456         }
457
458         if (_app2sd_check_is_luks_device(loopback_device) == 0) {
459                 _W("legacy image format!");
460                 snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
461                         "/bin/echo '%s' | /sbin/cryptsetup " \
462                         "-M plain -c aes-cbc-plain -h plain open %s %s",
463                         passwd, loopback_device, dev_name);
464         } else {
465                 snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
466                         "/bin/echo '%s' | /sbin/cryptsetup -q luksOpen %s %s",
467                         passwd, loopback_device, dev_name);
468         }
469         free(passwd);
470
471         ret = system(dmcrypt_open_cmd);
472         if (ret) {
473                 strerror_r(errno, buf, sizeof(buf));
474                 _E("error opening dmcrypt device, error: [%s]", buf);
475                 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
476         }
477
478         snprintf(buf, sizeof(buf), "/dev/mapper/%s", dev_name);
479         len = strlen(buf);
480         *dev_node = (char *)calloc(len + 1, sizeof(char));
481         if (*dev_node == NULL) {
482                 _E("memory alloc failed");
483                 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
484         }
485         snprintf(*dev_node, len + 1, "%s", buf);
486
487         return ret;
488 }
489
490 int _app2sd_dmcrypt_close_device(const char *pkgid, uid_t uid)
491 {
492         int ret = APP2EXT_SUCCESS;
493         char dev_node[BUF_SIZE] = { '\0' };
494         char dmcrypt_close_cmd[BUF_SIZE] = { '\0' };
495         char err_buf[BUF_SIZE] = { '\0' };
496         char *t_dev_node = NULL;
497
498         if (pkgid == NULL) {
499                 _E("invalid argument\n");
500                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
501         }
502
503         t_dev_node = _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
504         if (!t_dev_node) {
505                 _W("no associated device node(%s_%d) found", pkgid, uid);
506                 return APP2EXT_ERROR_DMCRYPT_DEVICE_UNAVAILABLE;
507         }
508
509         free(t_dev_node);
510         t_dev_node = NULL;
511
512         snprintf(dev_node, sizeof(dev_node), "/dev/mapper/%s_%d", pkgid, uid);
513         snprintf(dmcrypt_close_cmd, sizeof(dmcrypt_close_cmd),
514                 "/sbin/cryptsetup -q luksClose %s", dev_node);
515         ret = system(dmcrypt_close_cmd);
516         if (ret) {
517                 strerror_r(errno, err_buf, sizeof(err_buf));
518                 _E("error closing dmcrypt on app2sd file,"\
519                         " error: [%s]", err_buf);
520                 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
521         }
522
523         return ret;
524 }
525
526 char *_app2sd_find_associated_dmcrypt_device_node(const char *pkgid, uid_t uid)
527 {
528         char *dev_node = NULL;
529         char buf[BUF_SIZE] = { 0, };
530         int len = 0;
531
532         snprintf(buf, sizeof(buf), "/dev/mapper/%s_%d", pkgid, uid);
533         len = strlen(buf);
534         dev_node = (char *)calloc(len + 1, sizeof(char));
535         if (dev_node == NULL) {
536                 _E("memory alloc failed");
537                 return NULL;
538         }
539         snprintf(dev_node, len + 1, "%s", buf);
540
541         if (access(dev_node, F_OK) == 0) {
542                 _D("device_node: (%s)", dev_node);
543                 return dev_node;
544         }
545         _D("can not access dev_node(%s), errno(%d)", dev_node, errno);
546
547         free(dev_node);
548         dev_node = NULL;
549
550         return NULL;
551 }
552
553 char *_app2sd_dmcrypt_duplicate_encryption_setup(const char *pkgid,
554                 const char *temp_loopback_device, uid_t uid)
555 {
556         int ret = APP2EXT_SUCCESS;
557         char *device_node = NULL;
558
559         if (pkgid == NULL || temp_loopback_device == NULL) {
560                 _E("invalid argument\n");
561                 return NULL;
562         }
563
564         ret = _app2sd_dmcrypt_setup_device(pkgid, temp_loopback_device, true, uid);
565         if (ret) {
566                 _E("dmcrypt setup device error(%d)", ret);
567                 return NULL;
568         }
569
570         ret = _app2sd_dmcrypt_open_device(pkgid, temp_loopback_device, true,
571                 uid, &device_node);
572         if (ret) {
573                 _E("dmcrypt open device error");
574                 return NULL;
575         }
576
577         return device_node;
578 }
579 #endif
580
581 int _app2sd_create_loopback_device(const char *pkgid,
582                 const char *loopback_device, int size)
583 {
584         int ret = APP2EXT_SUCCESS;
585         char command[FILENAME_MAX] = { 0, };
586         char buff[BUF_SIZE] = { 0, };
587         FILE *fp = NULL;
588
589         if (NULL == pkgid || size <= 0) {
590                 _E("invalid argument");
591                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
592         }
593         snprintf(command, sizeof(command), "of=%s", loopback_device);
594         snprintf(buff, sizeof(buff), "count=%d", size);
595
596         const char *argv1[] = { "/bin/dd", "if=/dev/zero",
597                 command, "bs=1M", buff, NULL };
598
599         if ((fp = fopen(loopback_device, "r+")) != NULL) {
600                 _W("encrypted file already exists (%s)",
601                         loopback_device);
602                 fclose(fp);
603                 return APP2EXT_ERROR_PKG_EXISTS;
604         }
605
606         ret = _xsystem(argv1);
607         if (ret)
608                 _E("command (%s) failed, ret(%d), errno(%d)", command, ret, errno);
609
610         return ret;
611 }
612
613 int _app2sd_delete_loopback_device(const char *loopback_device)
614 {
615         int ret = APP2EXT_SUCCESS;
616
617         ret = unlink(loopback_device);
618         if (ret) {
619                 if (errno == ENOENT) {
620                         _W("unable to access file (%s)", loopback_device);
621                 } else {
622                         _E("unable to delete (%s)", loopback_device);
623                         return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
624                 }
625         }
626
627         return APP2EXT_SUCCESS;
628 }
629
630 int _app2sd_create_file_system(const char *device_path)
631 {
632         int ret = APP2EXT_SUCCESS;
633         FILE *fp = NULL;
634         char err_buf[1024] = {0,};
635
636         if (device_path == NULL) {
637                 _E("invalid param");
638                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
639         }
640
641         /* Format the filesystem [create a filesystem]*/
642         const char *argv[] = { "/sbin/mkfs.ext4", device_path, NULL };
643         fp = fopen(device_path, "r+");
644         if (fp == NULL) {
645                 strerror_r(errno, err_buf, sizeof(err_buf));
646                 _E("unable to access (%s) error is (%d, %s)",
647                      device_path, errno, err_buf);
648                 return APP2EXT_ERROR_ACCESS_FILE;
649         } else {
650                 fclose(fp);
651         }
652         ret = _xsystem(argv);
653         if (ret) {
654                 strerror_r(errno, err_buf, sizeof(err_buf));
655                 _E("creating file system failed, error is (%s)",
656                      err_buf);
657                 return APP2EXT_ERROR_CREATE_FS;
658         }
659         return ret;
660 }
661
662 static int _app2sd_create_dir_with_link(const char *application_path,
663                 const char *pkgid, const char *dir_name, uid_t uid)
664 {
665         int ret = APP2EXT_SUCCESS;
666         char app_dir_mmc_path[FILENAME_MAX] = { 0, };
667         char app_dir_path[FILENAME_MAX] = { 0, };
668
669         snprintf(app_dir_mmc_path, sizeof(app_dir_mmc_path), "%s/.mmc/%s",
670                 application_path, dir_name);
671         snprintf(app_dir_path, sizeof(app_dir_path), "%s/%s",
672                 application_path, dir_name);
673
674         ret = _app2sd_make_directory(app_dir_mmc_path, uid);
675         if (ret) {
676                 _E("create directory failed");
677                 return APP2EXT_ERROR_CREATE_DIRECTORY;
678         }
679
680         if ((ret = symlink(app_dir_mmc_path,
681                 app_dir_path)) < 0) {
682                 if (errno == EEXIST) {
683                         _D("file with symlink name present (%s)",
684                                 app_dir_path);
685                 } else {
686                         _E("symbolic link creation "
687                                 "failed, error no is (%d)", errno);
688                         return APP2EXT_ERROR_CREATE_SYMLINK;
689                 }
690         }
691
692         return APP2EXT_SUCCESS;
693 }
694
695 static int _app2sd_create_directory_entry(const char *application_path,
696                 const char *pkgid, GList *dir_list, uid_t uid)
697 {
698         int ret = APP2EXT_SUCCESS;
699         GList *list = NULL;
700         app2ext_dir_details *dir_detail = NULL;
701
702         list = g_list_first(dir_list);
703         while (list) {
704                 dir_detail = (app2ext_dir_details *)list->data;
705                 if (dir_detail && dir_detail->name
706                         && dir_detail->type == APP2EXT_DIR_RO) {
707                         ret = _app2sd_create_dir_with_link(application_path,
708                                 pkgid, dir_detail->name, uid);
709                         if (ret)
710                                 return ret;
711                 }
712                 list = g_list_next(list);
713         }
714         return APP2EXT_SUCCESS;
715 }
716
717 int _app2sd_mount_app_content(const char *application_path, const char *pkgid,
718                 const char *dev, int mount_type, GList *dir_list,
719                 app2sd_cmd cmd, uid_t uid)
720 {
721         int ret = APP2EXT_SUCCESS;
722         int fd = -1;
723         char app_mmc_path[FILENAME_MAX] = { 0, };
724         char temp_path[FILENAME_MAX] = { 0, };
725         char err_buf[1024] = {0,};
726         struct timespec time = {
727                 .tv_sec = 0,
728                 .tv_nsec = 1000 * 1000 * 200
729         };
730
731         if (NULL == dev) {
732                 _E("input param is NULL (%s)",
733                              dev);
734                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
735         }
736
737         /* check directory existence */
738         fd = open(application_path, O_RDONLY|O_DIRECTORY);
739         if (fd < 0) {
740                 _E("path(%s) error(%d)", application_path, errno);
741                 return APP2EXT_ERROR_OPEN_DIR;
742         }
743         close(fd);
744
745         snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
746                 application_path);
747         fd = open(app_mmc_path, O_RDONLY|O_DIRECTORY);
748         if (fd < 0) {
749                 _E("path(%s) error(%d)", app_mmc_path, errno);
750                 return APP2EXT_ERROR_OPEN_DIR;
751         }
752         close(fd);
753
754         nanosleep(&time, NULL); /* 200ms sleep */
755         _D("give a delay for mount");
756
757         switch (mount_type) {
758         case MOUNT_TYPE_RD:
759                 if ((ret = mount(dev, app_mmc_path, FS_TYPE,
760                         MS_MGC_VAL | MS_RDONLY | MS_NOSUID, NULL)) < 0) {
761                         _E("read only mount failed, " \
762                                 "errono is (%d), " \
763                                 "dev is (%s) path is (%s)",
764                                 errno, dev, app_mmc_path);
765                         ret = APP2EXT_ERROR_MOUNT;
766                 }
767                 break;
768         case MOUNT_TYPE_RW:
769                 if ((ret = mount(dev, app_mmc_path, FS_TYPE,
770                         MS_MGC_VAL | MS_NOSUID, NULL)) < 0) {
771                         _E("read write mount failed, " \
772                                 "errono is (%d)", errno);
773                         ret = APP2EXT_ERROR_MOUNT;
774                 }
775                 break;
776         case MOUNT_TYPE_RW_NOEXEC:
777                 if ((ret = mount(dev, app_mmc_path, FS_TYPE,
778                         MS_MGC_VAL | MS_NOEXEC | MS_NOSUID, NULL)) < 0) {
779                         _E("rwnx mount failed " \
780                                 "errono is (%d)", errno);
781                         ret = APP2EXT_ERROR_MOUNT;
782                 }
783                 break;
784         case MOUNT_TYPE_RD_REMOUNT:
785                 if ((ret = mount(dev, app_mmc_path, FS_TYPE,
786                         MS_MGC_VAL | MS_RDONLY | MS_REMOUNT | MS_NOSUID,
787                         NULL)) < 0) {
788                         _E("read remount failed "
789                                 "errono is (%d)", errno);
790                         ret = APP2EXT_ERROR_MOUNT;
791                 }
792                 break;
793         case MOUNT_TYPE_RW_REMOUNT:
794                 if ((ret = mount(dev, app_mmc_path, FS_TYPE,
795                         MS_MGC_VAL | MS_REMOUNT | MS_NOSUID, NULL)) < 0) {
796                         _E("read write remount failed "
797                                 "errono(%d), errstr(%s)", errno,
798                                 strerror_r(errno, err_buf, sizeof(err_buf)));
799                                 ret = APP2EXT_ERROR_MOUNT;
800                 }
801                 break;
802         default:
803                 _E("invalid mount type");
804                 break;
805         }
806
807         if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC ||
808                 cmd == APP2SD_PRE_UPGRADE) {
809                 ret = _app2sd_create_directory_entry(application_path,
810                         pkgid, dir_list, uid);
811         }
812
813         if (mount_type != MOUNT_TYPE_RD &&
814                 mount_type != MOUNT_TYPE_RD_REMOUNT) {
815                 /* change lost+found permission */
816                 snprintf(temp_path, sizeof(temp_path), "%s/lost+found",
817                                 app_mmc_path);
818                 ret = _app2sd_make_directory(temp_path, uid);
819                 if (ret) {
820                         _E("create directory(%s) failed", temp_path);
821                         return APP2EXT_ERROR_CREATE_DIRECTORY;
822                 }
823         }
824
825         return ret;
826 }
827
828 int _app2sd_unmount_app_content(const char *application_path)
829 {
830         int ret = APP2EXT_SUCCESS;
831         char app_mmc_path[FILENAME_MAX] = { 0, };
832         char err_buf[1024] = {0,};
833
834         snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
835                 application_path);
836         if ((ret = umount(app_mmc_path)) < 0) {
837                 strerror_r(errno, err_buf, sizeof(err_buf));
838                 _D("unable to umount the dir, ret(%d) error(%d, %s)",
839                         ret, errno, err_buf);
840         }
841
842         return ret;
843 }
844
845 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
846 {
847         int ret = APP2EXT_SUCCESS;
848
849         ret = _app2sd_copy_dir(src_path, arch_path);
850         if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
851                 char err_buf[1024] = {0,};
852                 strerror_r(errno, err_buf, sizeof(err_buf));
853                 _E("unable to copy from (%s) to (%s), err is (%s)",
854                         src_path, arch_path, err_buf);
855                 return APP2EXT_ERROR_MOVE;
856         }
857
858         ret = _app2sd_delete_directory((char *)src_path);
859         if (ret) {
860                 _E("unable to delete (%s)", src_path);
861                 return APP2EXT_ERROR_DELETE_DIRECTORY;
862         }
863
864         return ret;
865 }
866
867 static int _app2sd_move_app_to_external(const char *pkgid, GList *dir_list,
868                 uid_t uid, char *mmc_path, char **image_path)
869 {
870         int ret = APP2EXT_SUCCESS;
871         mode_t mode = DIR_PERMS;
872         char temp_dir_path[FILENAME_MAX] = { 0, };
873         char app_mmc_path[FILENAME_MAX] = { 0, };
874         char app_archive_path[FILENAME_MAX] = { 0, };
875         char application_path[FILENAME_MAX] = { 0, };
876         char loopback_device[FILENAME_MAX] = { 0, };
877         unsigned long long total_size = 0;
878         int reqd_size = 0;
879         int reqd_disk_size = 0;
880         char *device_node = NULL;
881 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
882         char *devi = NULL;
883 #endif
884         int free_mmc_mem = 0;
885         FILE *fp = NULL;
886         GList *list = NULL;
887         app2ext_dir_details *dir_detail = NULL;
888         char err_buf[1024] = { 0,};
889         char *encoded_id = NULL;
890
891         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
892         if (encoded_id == NULL)
893                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
894
895         snprintf(loopback_device, sizeof(loopback_device), "%s/%s/%s",
896                         mmc_path, EXTIMG_DIR, encoded_id);
897         free(encoded_id);
898         _app2sd_set_application_path(pkgid, uid, application_path,
899                 sizeof(application_path));
900
901         /* check whether application is in external memory or not */
902         fp = fopen(loopback_device, "r+");
903         if (fp != NULL) {
904                 _W("Already %s entry is present in the SD Card, " \
905                         "delete entry and go on without return", pkgid);
906                 fclose(fp);
907                 _app2sd_force_clean(pkgid, application_path, loopback_device, uid);
908         }
909
910         snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
911                 application_path);
912         snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
913                 application_path);
914
915         ret = mkdir(app_mmc_path, mode);
916         if (ret) {
917                 if (errno != EEXIST) {
918                         _E("unable to create directory for archiving," \
919                                 " error(%d)", errno);
920                         return APP2EXT_ERROR_CREATE_DIRECTORY;
921                 }
922         }
923
924         ret = mkdir(app_archive_path, mode);
925         if (ret) {
926                 if (errno != EEXIST) {
927                         _E("unable to create directory for archiving," \
928                                 " error(%d)", errno);
929                         return APP2EXT_ERROR_CREATE_DIRECTORY;
930                 }
931         }
932
933         list = g_list_first(dir_list);
934         while (list) {
935                 dir_detail = (app2ext_dir_details *)list->data;
936                 if (dir_detail && dir_detail->name
937                         && dir_detail->type == APP2EXT_DIR_RO) {
938                         memset(temp_dir_path, '\0', sizeof(temp_dir_path));
939                         snprintf(temp_dir_path, sizeof(temp_dir_path),
940                                  "%s/%s", application_path,
941                                  dir_detail->name);
942                         _D("cal size of app dirs, temp_dir_path(%s)",
943                                 temp_dir_path);
944                         total_size +=
945                             _app2sd_calculate_dir_size(temp_dir_path);
946                 }
947                 list = g_list_next(list);
948         }
949
950         reqd_size = ((total_size) / (1024 * 1024)) + 2;
951         reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
952
953         /* find avialable free memory in the MMC card */
954         ret = _app2sd_get_available_free_memory(mmc_path, &free_mmc_mem);
955         if (ret) {
956                 _E("unable to get available free memory in MMC (%d)", ret);
957                 return APP2EXT_ERROR_MMC_STATUS;
958         }
959         /* if avaialalbe free memory in MMC is less than
960          * required size + 5MB, return error
961          */
962         if (reqd_disk_size > free_mmc_mem) {
963                 _E("insufficient memory in MMC for application installation (%d)",
964                         ret);
965                 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
966         }
967         /* create a loopback device */
968         ret = _app2sd_create_loopback_device(pkgid, loopback_device,
969                 (reqd_disk_size + PKG_BUF_SIZE));
970         if (ret) {
971                 _E("loopback node creation failed");
972                 return ret;
973         }
974
975 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
976         ret = _app2sd_dmcrypt_setup_device(pkgid, loopback_device, false, uid);
977         if (ret) {
978                 _E("dmcrypt setup device error(%d)", ret);
979                 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
980         }
981
982         ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device, false,
983                 uid, &device_node);
984         if (ret) {
985                 _E("dmcrypt open device error");
986                 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
987         }
988 #else
989         /* perform loopback encryption setup */
990         device_node = _app2sd_do_loopback_encryption_setup(pkgid,
991                 loopback_device, uid);
992         if (!device_node) {
993                 _E("loopback encryption setup failed");
994                 return APP2EXT_ERROR_DO_LOSETUP;
995         }
996         _D("device_node (%s)", device_node);
997         /* check whether loopback device is associated with device node or not */
998         devi = _app2sd_find_associated_device_node(loopback_device);
999         if (devi == NULL) {
1000                 _E("finding associated device node failed");
1001                 ret = APP2EXT_ERROR_DO_LOSETUP;
1002                 goto ERR;
1003         } else {
1004                 free(devi);
1005                 devi = NULL;
1006         }
1007 #endif
1008         /* format the loopback file system */
1009         ret = _app2sd_create_file_system(device_node);
1010         if (ret) {
1011                 _E("create ext4 filesystem failed");
1012                 ret = APP2EXT_ERROR_CREATE_FS;
1013                 goto ERR;
1014         }
1015
1016         list = g_list_first(dir_list);
1017         while (list) {
1018                 dir_detail = (app2ext_dir_details *)list->data;
1019                 if (dir_detail && dir_detail->name
1020                         && dir_detail->type == APP2EXT_DIR_RO) {
1021                         memset(temp_dir_path, '\0', FILENAME_MAX);
1022                         snprintf(temp_dir_path, sizeof(temp_dir_path),
1023                                  "%s/%s", application_path,
1024                                 dir_detail->name);
1025                         _D("app2archive, temp_dir_path(%s)",
1026                                 temp_dir_path);
1027                         ret = _app2sd_move_to_archive(temp_dir_path,
1028                                 app_archive_path);
1029                         if (ret) {
1030                                 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1031                                         _E("unable to access (%s)",
1032                                                 temp_dir_path);
1033                                 } else {
1034                                         _E("unable to copy from (%s) to (%s)",
1035                                              temp_dir_path,
1036                                              app_archive_path);
1037                                 }
1038                                 goto ERR;
1039                         }
1040                 }
1041                 list = g_list_next(list);
1042         }
1043
1044         /* mount the loopback encrypted pseudo device on application installation path
1045          * as with Read Write permission
1046          */
1047         ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
1048                 MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
1049         if (ret) {
1050                 _E("mount failed");
1051                 goto ERR;
1052         }
1053
1054         list = g_list_first(dir_list);
1055         while (list) {
1056                 dir_detail = (app2ext_dir_details *)list->data;
1057                 if (dir_detail && dir_detail->name
1058                         && dir_detail->type == APP2EXT_DIR_RO) {
1059                         memset(temp_dir_path, '\0', sizeof(temp_dir_path));
1060                         snprintf(temp_dir_path, sizeof(temp_dir_path),
1061                                 "%s/%s", app_archive_path,
1062                                 dir_detail->name);
1063                         _D("archive2mmc, temp_dir_path(%s)",
1064                                 temp_dir_path);
1065                         ret = _app2sd_copy_dir(temp_dir_path,
1066                                 app_mmc_path);
1067                         if (ret) {
1068                                 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1069                                         _E("unable to access (%s)",
1070                                                 temp_dir_path);
1071                                 } else {
1072                                         strerror_r(errno,
1073                                                 err_buf, sizeof(err_buf));
1074                                         _E("unable to copy from (%s) to (%s)," \
1075                                                 " error is (%s)",
1076                                                 temp_dir_path,
1077                                                 app_mmc_path, err_buf);
1078                                 }
1079                                 goto ERR;
1080                         }
1081                         ret = _app2sd_delete_directory(temp_dir_path);
1082                         if (ret) {
1083                                 _E("unable to delete (%s)", temp_dir_path);
1084                                 goto ERR;
1085                         }
1086                 }
1087                 list = g_list_next(list);
1088         }
1089
1090         ret = _app2sd_delete_directory(app_archive_path);
1091         if (ret) {
1092                 _E("unable to delete (%s)", app_archive_path);
1093                 ret = APP2EXT_ERROR_DELETE_DIRECTORY;
1094                 goto ERR;
1095         }
1096
1097         *image_path = strdup(loopback_device);
1098         return APP2EXT_SUCCESS;
1099
1100 ERR:
1101         if (device_node) {
1102                 free(device_node);
1103                 device_node = NULL;
1104         }
1105
1106         *image_path = NULL;
1107         return ret;
1108 }
1109
1110 static int _app2sd_move_app_to_internal(const char *pkgid, GList *dir_list,
1111                 uid_t uid, char *mmc_path)
1112 {
1113         int ret = APP2EXT_SUCCESS;
1114         mode_t mode = DIR_PERMS;
1115         char temp_dir_path[FILENAME_MAX] = { 0, };
1116         char app_mmc_path[FILENAME_MAX] = { 0, };
1117         char app_archive_path[FILENAME_MAX] = { 0, };
1118         char application_path[FILENAME_MAX] = { 0, };
1119         char loopback_device[FILENAME_MAX] = { 0, };
1120         char *device_node = NULL;
1121         FILE *fp = NULL;
1122         GList *list = NULL;
1123         app2ext_dir_details *dir_detail = NULL;
1124         int reqd_size = 0;
1125         int free_internal_mem = 0;
1126         unsigned long long temp = 0;
1127         char err_buf[1024] = {0,};
1128         char *encoded_id = NULL;
1129
1130         encoded_id = _app2sd_get_encoded_name(pkgid, uid);
1131         if (encoded_id == NULL)
1132                 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1133
1134         snprintf(loopback_device, sizeof(loopback_device), "%s/%s/%s",
1135                         mmc_path, EXTIMG_DIR, encoded_id);
1136         free(encoded_id);
1137         _app2sd_set_application_path(pkgid, uid, application_path,
1138                 sizeof(application_path));
1139
1140         /* check whether application is in external memory or not */
1141         fp = fopen(loopback_device, "r+");
1142         if (fp == NULL) {
1143                 _E("application (%s) is not installed on SD Card",
1144                      pkgid);
1145                 return APP2EXT_ERROR_FILE_ABSENT;
1146         } else {
1147                 fclose(fp);
1148                 fp = NULL;
1149         }
1150
1151         /* find avialable free memory in the internal storage */
1152         ret = _app2sd_get_available_free_memory(INTERNAL_STORAGE_PATH,
1153                 &free_internal_mem);
1154         if (ret) {
1155                 _E("unable to get available free memory in internal (%d)",
1156                         ret);
1157                 return APP2EXT_ERROR_MMC_STATUS;
1158         }
1159
1160         fp = fopen(loopback_device, "r+");
1161         if (fp == NULL) {
1162                 _E("app entry is not present in SD card");
1163                 return APP2EXT_ERROR_INVALID_PACKAGE;
1164         }
1165         fclose(fp);
1166
1167         /* get installed app size*/
1168         temp = _app2sd_calculate_file_size(loopback_device);
1169         reqd_size = (int)((temp) / (1024 * 1024));
1170         _D("reqd size is (%d)", reqd_size);
1171
1172         if (reqd_size == 0) {
1173                 _E("app entry is not present in SD Card");
1174                 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
1175         }
1176
1177         _I("reqd size: (%d)MB, free internal mem: (%d)MB",
1178                 reqd_size, free_internal_mem);
1179
1180         /* if avaialalbe free memory in internal storage is
1181          * less than required size, return error
1182          */
1183         if (reqd_size > free_internal_mem) {
1184                 _E("innsufficient memory in internal storage" \
1185                         " for application installation (%d)", ret);
1186                 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
1187         }
1188
1189 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1190         device_node =
1191                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1192 #else
1193         device_node = _app2sd_find_associated_device_node(loopback_device);
1194 #endif
1195         if (NULL == device_node) {
1196                 /* do loopback setup */
1197 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1198                 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1199                         false, uid, &device_node);
1200                 if (ret) {
1201                         _E("dmcrypt open device error(%d)", ret);
1202                         return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1203                 }
1204 #else
1205                 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1206                         loopback_device, uid);
1207                 if (device_node == NULL) {
1208                         _E("loopback encryption setup failed");
1209                         return APP2EXT_ERROR_DO_LOSETUP;
1210                 }
1211 #endif
1212                 /* do mounting */
1213                 ret = _app2sd_mount_app_content(application_path,
1214                         pkgid, device_node, MOUNT_TYPE_RW,
1215                         dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1216                 if (ret) {
1217                         _E("mount failed");
1218                         ret = APP2EXT_ERROR_MOUNT_PATH;
1219                         goto ERR;
1220                 }
1221         } else {
1222                 /* do re-mounting */
1223                 ret = _app2sd_mount_app_content(application_path,
1224                         pkgid, device_node, MOUNT_TYPE_RW_REMOUNT,
1225                         dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1226                 if (ret) {
1227                         _E("re-mount failed");
1228                         ret = APP2EXT_ERROR_MOUNT_PATH;
1229                         goto ERR;
1230                 }
1231         }
1232
1233         snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
1234                 application_path);
1235         snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
1236                 application_path);
1237
1238         ret = mkdir(app_archive_path, mode);
1239         if (ret) {
1240                 if (errno != EEXIST) {
1241                         _E("unable to create directory for archiving," \
1242                                 " error(%d)", errno);
1243                         ret = APP2EXT_ERROR_CREATE_DIRECTORY;
1244                         goto ERR;
1245                 }
1246         }
1247
1248         list = g_list_first(dir_list);
1249         while (list) {
1250                 dir_detail = (app2ext_dir_details *)list->data;
1251                 if (dir_detail && dir_detail->name
1252                         && dir_detail->type == APP2EXT_DIR_RO) {
1253                         /* archiving code */
1254                         memset(temp_dir_path, '\0', sizeof(temp_dir_path));
1255                         snprintf(temp_dir_path, sizeof(temp_dir_path),
1256                                  "%s/%s", app_mmc_path,
1257                                  dir_detail->name);
1258                         _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
1259                         ret = _app2sd_copy_dir(temp_dir_path,
1260                                      app_archive_path);
1261                         if (ret) {
1262                                 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1263                                         _E("unable to access (%s)",
1264                                                 temp_dir_path);
1265                                 } else {
1266                                         strerror_r(errno,
1267                                                 err_buf, sizeof(err_buf));
1268                                         _E("unable to copy from (%s) to (%s),"
1269                                                 " error is (%s)",
1270                                                 temp_dir_path,
1271                                                 app_archive_path, err_buf);
1272                                 }
1273                                 goto ERR;
1274                         }
1275
1276                         /* delete the symbolic link files [bin, lib, res]*/
1277                         memset(temp_dir_path, '\0', sizeof(temp_dir_path));
1278                         snprintf(temp_dir_path, sizeof(temp_dir_path),
1279                                  "%s/%s", application_path,
1280                                  dir_detail->name);
1281                         _D("unlink, temp_dir_path(%s)", temp_dir_path);
1282                         ret = unlink(temp_dir_path);
1283                         if (ret) {
1284                                 if (errno == ENOENT) {
1285                                         _W("directory (%s) does not exist",
1286                                                 temp_dir_path);
1287                                 } else {
1288                                         _E("unable to remove the symbolic link file (%s)," \
1289                                                 " it is already unlinked",
1290                                                 temp_dir_path);
1291                                         goto ERR;
1292                                 }
1293                         }
1294
1295                         /* Copy content to destination */
1296                         memset(temp_dir_path, '\0', sizeof(temp_dir_path));
1297                         snprintf(temp_dir_path, sizeof(temp_dir_path),
1298                                 "%s/%s", app_archive_path,
1299                                 dir_detail->name);
1300                         _D("archive2app, temp_dir_path(%s)", temp_dir_path);
1301                         ret = _app2sd_copy_dir(temp_dir_path, application_path);
1302                         if (ret) {
1303                                 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1304                                         _E("unable to access (%s)",
1305                                                 temp_dir_path);
1306                                 } else {
1307                                         strerror_r(errno,
1308                                                 err_buf, sizeof(err_buf));
1309                                         _E("unable to copy from (%s) to (%s) " \
1310                                                 ", error is (%s)",
1311                                                 temp_dir_path,
1312                                                 application_path, err_buf);
1313                                 }
1314                                 goto ERR;
1315                         }
1316                 }
1317                 list = g_list_next(list);
1318         }
1319
1320         _D("copying file completed");
1321         ret = _app2sd_unmount_app_content(application_path);
1322         if (ret)
1323                 _E("unable to unmount SD directory for app (%s)",
1324                      pkgid);
1325
1326 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1327         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1328         if (ret)
1329                 _E("close dmcrypt device error(%d)", ret);
1330 #else
1331         ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1332         if (ret)
1333                 _E("unable to detach loopback setup for (%s)",
1334                      pkgid);
1335 #endif
1336
1337         ret = _app2sd_delete_loopback_device(loopback_device);
1338         if (ret)
1339                 _E("unable to delete the loopback device for (%s)",
1340                      pkgid);
1341
1342         ret = _app2sd_delete_directory(app_mmc_path);
1343         if (ret)
1344                 _E("unable to delete (%s)", app_mmc_path);
1345
1346         ret = _app2sd_delete_directory(app_archive_path);
1347         if (ret)
1348                 _E("unable to delete (%s)", app_archive_path);
1349
1350         /* remove passwrd from DB */
1351         ret = _app2sd_initialize_db();
1352         if (ret)
1353                 _E("app2sd db initialize failed");
1354
1355         ret = _app2sd_remove_info_from_db(pkgid, uid);
1356         if (ret)
1357                 _E("cannot remove info from db");
1358
1359         return APP2EXT_SUCCESS;
1360
1361 ERR:
1362         if (device_node) {
1363                 free(device_node);
1364                 device_node = NULL;
1365         }
1366
1367         return ret;
1368 }
1369
1370 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
1371                 GList *dir_list, uid_t uid, char *mmc_path, char **image_path)
1372 {
1373         int ret = APP2EXT_SUCCESS;
1374
1375         switch (move_type) {
1376         case APP2EXT_MOVE_TO_EXT:
1377                 ret = _app2sd_move_app_to_external(pkgid, dir_list,
1378                         uid, mmc_path, image_path);
1379                 if (ret) {
1380                         _E("move app to external memory failed(%d)", ret);
1381                         return ret;
1382                 }
1383                 break;
1384         case APP2EXT_MOVE_TO_PHONE:
1385                 ret = _app2sd_move_app_to_internal(pkgid, dir_list,
1386                         uid, mmc_path);
1387                 if (ret) {
1388                         _E("move app to internal memory failed(%d)", ret);
1389                         return ret;
1390                 }
1391                 break;
1392         default:
1393                 _E("invalid argument");
1394                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1395         }
1396
1397         return ret;
1398 }
1399
1400 int _app2sd_copy_ro_content(const char *src, const char *dest, GList *dir_list)
1401 {
1402         char path[FILENAME_MAX] = { 0, };
1403         int ret = APP2EXT_SUCCESS;
1404         GList *list = NULL;
1405         app2ext_dir_details *dir_detail = NULL;
1406
1407         list = g_list_first(dir_list);
1408         while (list) {
1409                 dir_detail = (app2ext_dir_details *)list->data;
1410                 if (dir_detail && dir_detail->name
1411                         && dir_detail->type == APP2EXT_DIR_RO) {
1412                         memset((void *)&path, '\0', sizeof(path));
1413                         snprintf(path, sizeof(path), "%s/%s", src,
1414                                  dir_detail->name);
1415                         ret = _app2sd_copy_dir(path, dest);
1416                         if (ret) {
1417                                 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1418                                         _E("unable to access (%s)", path);
1419                                 } else {
1420                                         _E("unable to copy from (%s) " \
1421                                                 "to (%s), errno is (%d)",
1422                                                 path, dest, errno);
1423                                         return APP2EXT_ERROR_MOVE;
1424                                 }
1425                         }
1426                 }
1427                 list = g_list_next(list);
1428         }
1429
1430         return APP2EXT_SUCCESS;
1431 }
1432
1433 int _app2sd_duplicate_device(const char *pkgid,
1434                 const char *loopback_device,
1435                 const char *temp_pkgid,
1436                 const char *temp_application_path,
1437                 const char *temp_loopback_device,
1438                 GList *dir_list, char *dev_node, int size,
1439                 uid_t uid)
1440 {
1441         int ret = 0;
1442         int err_res = 0;
1443 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
1444         char *devi = NULL;
1445         char *result = NULL;
1446         char *passwd = NULL;
1447 #endif
1448
1449         /* create a new loopback device */
1450         ret = _app2sd_create_loopback_device(temp_pkgid,
1451                 temp_loopback_device, (size + PKG_BUF_SIZE));
1452         if (ret) {
1453                 _E("package already present");
1454                 return ret;
1455         }
1456
1457         /* perform loopback encryption setup */
1458 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1459         dev_node = _app2sd_dmcrypt_duplicate_encryption_setup(pkgid,
1460                 temp_loopback_device, uid);
1461         if (!dev_node) {
1462                 _E("dmcrypt duplicate encryption setup failed");
1463                 _app2sd_delete_loopback_device(temp_loopback_device);
1464                 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
1465         }
1466 #else
1467         /* get password for loopback encryption */
1468         ret = _app2sd_initialize_db();
1469         if (ret) {
1470                 _E("app2sd db initialize failed");
1471                 return APP2EXT_ERROR_DB_INITIALIZE;
1472         }
1473
1474         if ((passwd = _app2sd_get_password_from_db(pkgid, uid)) == NULL) {
1475                 passwd = (char *)_app2sd_generate_password();
1476                 if (NULL == passwd) {
1477                         _E("unable to generate password");
1478                         return APP2EXT_ERROR_PASSWD_GENERATION;
1479                 } else {
1480                         if ((ret = _app2sd_set_info_in_db(pkgid,
1481                                 passwd, loopback_device, uid)) < 0) {
1482                                 _E("unable to save info");
1483                                 free(passwd);
1484                                 passwd = NULL;
1485                                 return APP2EXT_ERROR_SQLITE_REGISTRY;
1486                         }
1487                 }
1488         }
1489
1490         dev_node = _app2sd_do_loopback_duplicate_encryption_setup(pkgid,
1491                 temp_pkgid, temp_loopback_device, passwd, uid);
1492         if (!dev_node) {
1493                 _E("losetup failed, device node is (%s)", dev_node);
1494                 _app2sd_delete_loopback_device(temp_loopback_device);
1495                 free(passwd);
1496                 passwd = NULL;
1497                 return APP2EXT_ERROR_DO_LOSETUP;
1498         }
1499         free(passwd);
1500         passwd = NULL;
1501         _D("duplicate setup SUCCESS");
1502
1503         /* check whether loopback device is associated with
1504          * device node or not
1505          */
1506         devi = _app2sd_find_associated_device_node(temp_loopback_device);
1507         if (devi == NULL) {
1508                 _E("finding associated device node failed");
1509                 err_res = APP2EXT_ERROR_DO_LOSETUP;
1510                 goto FINISH_OFF;
1511         }
1512         _D("losetup SUCCESS");
1513 #endif
1514
1515         /* format the loopback file system */
1516         ret = _app2sd_create_file_system(dev_node);
1517         if (ret) {
1518                 _E("creating fs failed");
1519                 err_res = APP2EXT_ERROR_CREATE_FS;
1520                 goto FINISH_OFF;
1521         }
1522         _D("create filesystem SUCCESS");
1523
1524         /* do mounting for new dev*/
1525         ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1526                 dev_node, MOUNT_TYPE_RW, dir_list,
1527                 APP2SD_PRE_UPGRADE, uid);
1528         if (ret) {
1529                 _E("remount failed");
1530                 err_res = APP2EXT_ERROR_MOUNT_PATH;
1531                 goto FINISH_OFF;
1532         }
1533
1534 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
1535         if (devi) {
1536                 free(devi);
1537                 devi = NULL;
1538         }
1539 #endif
1540
1541         return APP2EXT_SUCCESS;
1542
1543 FINISH_OFF:
1544         if (dev_node) {
1545 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1546                 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1547                 if (ret)
1548                         _E("close dmcrypt device error(%d)", ret);
1549 #else
1550                 result = _app2sd_detach_loop_device(dev_node);
1551                 if (result) {
1552                         free(result);
1553                         result = NULL;
1554                 }
1555 #endif
1556                 _app2sd_delete_loopback_device(temp_loopback_device);
1557                 free(dev_node);
1558                 dev_node = NULL;
1559         }
1560
1561         return err_res;
1562 }
1563
1564 int _app2sd_update_loopback_device_size(const char *pkgid,
1565                 const char *loopback_device,
1566                 const char *application_path,
1567                 const char *temp_pkgid,
1568                 const char *temp_loopback_device,
1569                 const char *temp_application_path,
1570                 int size, GList *dir_list,
1571                 uid_t uid)
1572 {
1573         int ret = 0;
1574         char *device_node = NULL;
1575         char *old_device_node = NULL;
1576         int err_res = 0;
1577         char app_mmc_path[FILENAME_MAX] = { 0, };
1578         char temp_app_mmc_path[FILENAME_MAX] = { 0, };
1579
1580         ret = _app2sd_duplicate_device(pkgid, loopback_device,
1581                 temp_pkgid, temp_application_path, temp_loopback_device,
1582                 dir_list, device_node, size, uid);
1583         if (ret) {
1584                 _E("creating duplicate device failed");
1585                 return ret;
1586         }
1587
1588         /* get the associated device node for SD card applicatione */
1589 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1590         old_device_node =
1591                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1592 #else
1593         old_device_node = _app2sd_find_associated_device_node(loopback_device);
1594 #endif
1595         if (NULL == old_device_node) {
1596                 /* do loopback setup */
1597 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1598                 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1599                         false, uid, &old_device_node);
1600                 if (ret) {
1601                         _E("dmcrypt open device error");
1602                         err_res = APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1603                         goto FINISH_OFF;
1604                 }
1605 #else
1606                 old_device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1607                         loopback_device, uid);
1608                 if (old_device_node == NULL) {
1609                         _E("loopback encryption setup failed");
1610                         err_res = APP2EXT_ERROR_DO_LOSETUP;
1611                         goto FINISH_OFF;
1612                 }
1613 #endif
1614                 /* do mounting */
1615                 ret = _app2sd_mount_app_content(application_path, pkgid,
1616                         old_device_node, MOUNT_TYPE_RW, dir_list,
1617                         APP2SD_PRE_UPGRADE, uid);
1618                 if (ret) {
1619                         _E("remount failed");
1620                         err_res = APP2EXT_ERROR_MOUNT_PATH;
1621                 }
1622         } else {
1623                 /* do re-mounting */
1624                 ret = _app2sd_mount_app_content(application_path, pkgid,
1625                         old_device_node, MOUNT_TYPE_RW_REMOUNT, dir_list,
1626                         APP2SD_PRE_UPGRADE, uid);
1627                 if (ret) {
1628                         _E("remount failed");
1629                         err_res = APP2EXT_ERROR_MOUNT_PATH;
1630                 }
1631         }
1632
1633         snprintf(app_mmc_path, sizeof(app_mmc_path),
1634                  "%s/.mmc", application_path);
1635         snprintf(temp_app_mmc_path, sizeof(temp_app_mmc_path),
1636                 "%s/.mmc", temp_application_path);
1637
1638         ret = _app2sd_copy_ro_content(app_mmc_path,
1639                 temp_app_mmc_path, dir_list);
1640         if (ret) {
1641                 _E("copy ro content failed");
1642                 err_res = ret;
1643         }
1644
1645         ret = _app2sd_unmount_app_content(application_path);
1646         if (ret) {
1647                 _E("unable to unmount the SD application");
1648                 err_res = APP2EXT_ERROR_UNMOUNT;
1649         }
1650
1651         ret = _app2sd_unmount_app_content(temp_application_path);
1652         if (ret) {
1653                 _E("unable to unmount the SD application");
1654                 err_res = APP2EXT_ERROR_UNMOUNT;
1655                 goto FINISH_OFF;
1656         }
1657
1658 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1659         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1660         if (ret) {
1661                 _E("close dmcrypt device error(%d)", ret);
1662                 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1663                 goto FINISH_OFF;
1664         }
1665
1666         ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1667         if (ret) {
1668                 _E("close dmcrypt device error(%d)", ret);
1669                 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1670                 goto FINISH_OFF;
1671         }
1672 #else
1673         ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1674         if (ret) {
1675                 _E("unable to remove loopback setup");
1676                 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1677         }
1678
1679         ret = _app2sd_remove_loopback_encryption_setup(temp_loopback_device);
1680         if (ret) {
1681                 _E("unable to remove loopback setup");
1682                 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1683                 goto FINISH_OFF;
1684         }
1685 #endif
1686
1687         ret = _app2sd_delete_directory(loopback_device);
1688         if (ret) {
1689                 _E("unable to delete (%s)", loopback_device);
1690                 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1691                 goto FINISH_OFF;
1692         }
1693
1694         ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1695         if (ret) {
1696                 _E("unable to rename (%s)", temp_loopback_device);
1697                 err_res = APP2EXT_ERROR_MOVE;
1698                 goto FINISH_OFF;
1699         }
1700
1701         ret = _app2sd_delete_directory(temp_application_path);
1702         if (ret) {
1703                 _E("unable to delete (%s)", temp_application_path);
1704                 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1705                 goto FINISH_OFF;
1706         }
1707
1708         return APP2EXT_SUCCESS;
1709
1710 FINISH_OFF:
1711         if (old_device_node) {
1712                 free(old_device_node);
1713                 old_device_node = NULL;
1714         }
1715
1716 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1717         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1718         if (ret)
1719                 _E("close dmcrypt device error(%d)", ret);
1720
1721         ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1722
1723         if (ret)
1724                 _E("close dmcrypt device error(%d)", ret);
1725 #else
1726         ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1727         if (ret)
1728                 _E("unable to remove loopback setup");
1729
1730         ret = _app2sd_remove_loopback_encryption_setup(temp_loopback_device);
1731         if (ret)
1732                 _E("unable to remove loopback setup");
1733 #endif
1734
1735         _app2sd_delete_loopback_device(temp_loopback_device);
1736
1737         ret = _app2sd_delete_directory(temp_application_path);
1738         if (ret)
1739                 _E("unable to delete (%s)", temp_application_path);
1740
1741         return err_res;
1742 }
1743
1744 int _app2sd_force_clean(const char *pkgid, const char *application_path,
1745                 const char *loopback_device, uid_t uid)
1746 {
1747         int ret = APP2EXT_SUCCESS;
1748
1749         /* unmount the loopback encrypted pseudo device from the application installation path */
1750         ret = _app2sd_unmount_app_content(application_path);
1751         if (ret)
1752                 _W("unable to unmount the app content (%d)", ret);
1753
1754         /* detach the loopback encryption setup for the application */
1755 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1756         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1757         if (ret)
1758                 _W("close dmcrypt device error (%d)", ret);
1759 #else
1760         ret = _app2sd_remove_all_loopback_encryption_setups(loopback_device);
1761         if (ret)
1762                 _W("unable to detach the loopback encryption setup for the application");
1763 #endif
1764
1765         /* delete the loopback device from the SD card */
1766         ret = _app2sd_delete_loopback_device(loopback_device);
1767         if (ret)
1768                 _W("unable to detach the loopback encryption setup for the application");
1769
1770         /* delete symlink */
1771         _app2sd_delete_symlink(application_path);
1772
1773         /* remove passwrd from DB */
1774         ret = _app2sd_initialize_db();
1775         if (ret)
1776                 _W("app2sd db initialize failed");
1777
1778         ret = _app2sd_remove_info_from_db(pkgid, uid);
1779         if (ret)
1780                 _W("cannot remove info from db");
1781
1782
1783         return ret;
1784 }