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