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