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