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