Fix error log
[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_crypt.h"
30 #include "app2sd_internals.h"
31
32 #define DMCRYPT_ITER_TIME       50
33 #define DMCRYPT_KEY_LEN         128
34
35 static int _app2sd_make_directory(const char *path, uid_t uid)
36 {
37         int ret;
38         int fd;
39         mode_t mode = DIR_PERMS;
40         struct passwd pwd;
41         struct passwd *pwd_result;
42         char buf[1024];
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, error is (%d)", errno);
62                         return APP2EXT_ERROR_CREATE_DIRECTORY;
63                 }
64         }
65
66         fd = open(path, O_RDONLY|O_DIRECTORY);
67         if (fd < 0) {
68                 _E("can't open path(%s)", path);
69                 return APP2EXT_ERROR_OPEN_DIR;
70         }
71
72         ret = fchmod(fd, 0755);
73         if (ret < 0) {
74                 _E("change file permission error");
75                 close(fd);
76                 return APP2EXT_ERROR_ACCESS_FILE;
77         }
78
79         ret = fchown(fd, uid, pwd.pw_gid);
80         if (ret < 0) {
81                 _E("change file owner error");
82                 close(fd);
83                 return APP2EXT_ERROR_ACCESS_FILE;
84         }
85
86         close(fd);
87
88         return APP2EXT_SUCCESS;
89 }
90
91 int _app2sd_dmcrypt_setup_device(const char *pkgid,
92                 const char *loopback_device, bool is_dup, uid_t uid)
93 {
94         int ret;
95         char *passwd;
96         char err_buf[BUF_SIZE];
97         const char *err_str;
98
99         if (pkgid == NULL || loopback_device == NULL) {
100                 _E("invalid argument");
101                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
102         }
103
104         /* get password for dmcrypt encryption */
105         ret = _app2sd_initialize_db();
106         if (ret) {
107                 _E("app2sd db initialize failed");
108                 return APP2EXT_ERROR_DB_INITIALIZE;
109         }
110
111         passwd = _app2sd_get_password_from_db(pkgid, uid);
112         if (passwd == NULL) {
113                 if (is_dup) {
114                         _E("no password found for (%s)", pkgid);
115                         return APP2EXT_ERROR_SQLITE_REGISTRY;
116                 }
117                 passwd = _app2sd_generate_password();
118                 if (passwd == NULL) {
119                         _E("unable to generate password");
120                         return APP2EXT_ERROR_PASSWD_GENERATION;
121                 }
122
123                 ret = _app2sd_set_info_in_db(pkgid, passwd, loopback_device,
124                                 uid);
125                 if (ret < 0) {
126                         _E("unable to save password");
127                         free(passwd);
128                         return APP2EXT_ERROR_SQLITE_REGISTRY;
129                 }
130         }
131
132         ret = _app2sd_crypt_luks_format(loopback_device, passwd);
133         memset(passwd, 0, strlen(passwd));
134         free(passwd);
135         if (ret) {
136                 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
137                 _E("Error setting up dmcrypt on app2sd file, error:%s, ret:%d",
138                                 err_str, ret);
139                 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
140         }
141
142         return ret;
143 }
144
145 int _app2sd_dmcrypt_open_device(const char *pkgid, const char *loopback_device,
146                 bool is_dup, uid_t uid, char **dev_node)
147 {
148         int ret;
149         char *passwd;
150         char dev_name[BUF_SIZE];
151         char buf[BUF_SIZE];
152
153         if (pkgid == NULL || loopback_device == NULL) {
154                 _E("invalid argument");
155                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
156         }
157
158         if (is_dup)
159                 snprintf(dev_name, sizeof(dev_name), "%s.new_%d", pkgid, uid);
160         else
161                 snprintf(dev_name, sizeof(dev_name), "%s_%d", pkgid, uid);
162
163         /* get password for dmcrypt encryption */
164         ret = _app2sd_initialize_db();
165         if (ret) {
166                 _E("app2sd db initialize failed");
167                 return APP2EXT_ERROR_DB_INITIALIZE;
168         }
169
170         passwd = _app2sd_get_password_from_db(pkgid, uid);
171         if (passwd == NULL) {
172                 _E("no password found for [%s]", pkgid);
173                 return APP2EXT_ERROR_SQLITE_REGISTRY;
174         }
175
176         if (_app2sd_crypt_is_luks(loopback_device) == 0) {
177                 _W("legacy image format!");
178                 ret = _app2sd_crypt_plain_open(loopback_device, passwd,
179                                 dev_name);
180         } else {
181                 ret = _app2sd_crypt_luks_open(loopback_device, passwd,
182                                 dev_name);
183         }
184         free(passwd);
185         if (ret) {
186                 _E("error opening dmcrypt device");
187                 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
188         }
189
190         snprintf(buf, sizeof(buf), "/dev/mapper/%s", dev_name);
191         *dev_node = strdup(buf);
192         if (*dev_node == NULL) {
193                 _E("memory alloc failed");
194                 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
195         }
196
197         return ret;
198 }
199
200 int _app2sd_dmcrypt_close_device(const char *pkgid, uid_t uid)
201 {
202         int ret;
203         char dev_node[BUF_SIZE];
204         char *t_dev_node;
205
206         if (pkgid == NULL) {
207                 _E("invalid argument");
208                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
209         }
210
211         t_dev_node = _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
212         if (!t_dev_node) {
213                 _W("no associated device node(%s_%d) found", pkgid, uid);
214                 return APP2EXT_ERROR_DMCRYPT_DEVICE_UNAVAILABLE;
215         }
216
217         free(t_dev_node);
218
219         snprintf(dev_node, sizeof(dev_node), "/dev/mapper/%s_%d", pkgid, uid);
220         ret = _app2sd_crypt_luks_close(dev_node);
221         if (ret) {
222                 _E("error closing dmcrypt on app2sd file: %s", dev_node);
223                 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
224         }
225
226         return ret;
227 }
228
229 char *_app2sd_find_associated_dmcrypt_device_node(const char *pkgid, uid_t uid)
230 {
231         char *dev_node;
232         char buf[BUF_SIZE];
233
234         snprintf(buf, sizeof(buf), "/dev/mapper/%s_%d", pkgid, uid);
235         if (access(buf, F_OK) == 0) {
236                 dev_node = strdup(buf);
237                 if (dev_node == NULL) {
238                         _E("memory alloc failed");
239                         return NULL;
240                 }
241                 _D("device_node: (%s)", dev_node);
242                 return dev_node;
243         }
244         _D("can not access dev_node(%s), errno(%d)", buf, errno);
245
246         return NULL;
247 }
248
249 char *_app2sd_dmcrypt_duplicate_encryption_setup(const char *pkgid,
250                 const char *temp_loopback_device, uid_t uid)
251 {
252         int ret;
253         char *device_node;
254
255         if (pkgid == NULL || temp_loopback_device == NULL) {
256                 _E("invalid argument");
257                 return NULL;
258         }
259
260         ret = _app2sd_dmcrypt_setup_device(pkgid, temp_loopback_device, true,
261                         uid);
262         if (ret) {
263                 _E("dmcrypt setup device error(%d)", ret);
264                 return NULL;
265         }
266
267         ret = _app2sd_dmcrypt_open_device(pkgid, temp_loopback_device, true,
268                         uid, &device_node);
269         if (ret) {
270                 _E("dmcrypt open device error");
271                 return NULL;
272         }
273
274         return device_node;
275 }
276
277 int _app2sd_create_loopback_device(const char *pkgid,
278                 const char *loopback_device, int size)
279 {
280         int ret;
281         char command[FILENAME_MAX];
282         char buff[BUF_SIZE];
283         FILE *fp;
284         const char *argv[] = { "/bin/dd", "if=/dev/zero", command,
285                 "bs=1M", buff, NULL };
286
287         if (pkgid == NULL || size <= 0) {
288                 _E("invalid argument");
289                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
290         }
291
292         fp = fopen(loopback_device, "r+");
293         if (fp != NULL) {
294                 _W("encrypted file already exists (%s)", loopback_device);
295                 fclose(fp);
296                 return APP2EXT_ERROR_PKG_EXISTS;
297         }
298
299         snprintf(command, sizeof(command), "of=%s", loopback_device);
300         snprintf(buff, sizeof(buff), "count=%d", size);
301
302         ret = _xsystem(argv);
303         if (ret)
304                 _E("command (%s) failed, ret(%d), errno(%d)",
305                                 command, ret, errno);
306
307         return ret;
308 }
309
310 int _app2sd_delete_loopback_device(const char *loopback_device)
311 {
312         int ret;
313
314         ret = unlink(loopback_device);
315         if (ret) {
316                 if (errno == ENOENT) {
317                         _W("unable to access file (%s)", loopback_device);
318                 } else {
319                         _E("unable to delete (%s)", loopback_device);
320                         return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
321                 }
322         }
323
324         return APP2EXT_SUCCESS;
325 }
326
327 int _app2sd_create_file_system(const char *device_path)
328 {
329         int ret;
330         FILE *fp;
331         char err_buf[1024];
332         const char *err_str;
333         const char *argv[] = { "/sbin/mkfs.ext4", device_path, NULL };
334
335         if (device_path == NULL) {
336                 _E("invalid param");
337                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
338         }
339
340         /* Format the filesystem [create a filesystem]*/
341         fp = fopen(device_path, "r+");
342         if (fp == NULL) {
343                 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
344                 _E("unable to access (%s) error is (%d, %s)",
345                                 device_path, errno, err_str);
346                 return APP2EXT_ERROR_ACCESS_FILE;
347         }
348         fclose(fp);
349
350         ret = _xsystem(argv);
351         if (ret) {
352                 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
353                 _E("creating file system failed, error is (%s)", err_str);
354                 return APP2EXT_ERROR_CREATE_FS;
355         }
356         return ret;
357 }
358
359 static int _app2sd_create_dir_with_link(const char *application_path,
360                 const char *pkgid, const char *dir_name, uid_t uid)
361 {
362         int ret;
363         char app_dir_mmc_path[FILENAME_MAX];
364         char app_dir_path[FILENAME_MAX];
365
366         snprintf(app_dir_mmc_path, sizeof(app_dir_mmc_path), "%s/.mmc/%s",
367                         application_path, dir_name);
368         snprintf(app_dir_path, sizeof(app_dir_path), "%s/%s",
369                         application_path, dir_name);
370
371         ret = _app2sd_make_directory(app_dir_mmc_path, uid);
372         if (ret) {
373                 _E("create directory failed");
374                 return APP2EXT_ERROR_CREATE_DIRECTORY;
375         }
376
377         ret = symlink(app_dir_mmc_path, app_dir_path);
378         if (ret < 0) {
379                 if (errno == EEXIST) {
380                         _D("file with symlink name present (%s)", app_dir_path);
381                 } else {
382                         _E("symbolic link creation failed, error: %d", errno);
383                         return APP2EXT_ERROR_CREATE_SYMLINK;
384                 }
385         }
386
387         return APP2EXT_SUCCESS;
388 }
389
390 static int _app2sd_create_directory_entry(const char *application_path,
391                 const char *pkgid, GList *dir_list, uid_t uid)
392 {
393         int ret;
394         GList *list;
395         app2ext_dir_details *dir_detail;
396
397         for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
398                 dir_detail = (app2ext_dir_details *)list->data;
399                 if (dir_detail == NULL || dir_detail->name == NULL ||
400                                 dir_detail->type != APP2EXT_DIR_RO)
401                         continue;
402                 ret = _app2sd_create_dir_with_link(application_path,
403                                 pkgid, dir_detail->name, uid);
404                 if (ret)
405                         return ret;
406         }
407         return APP2EXT_SUCCESS;
408 }
409
410 int _app2sd_mount_app_content(const char *application_path, const char *pkgid,
411                 const char *dev, int mount_type, GList *dir_list,
412                 app2sd_cmd cmd, uid_t uid)
413 {
414         int ret;
415         int fd;
416         char app_mmc_path[FILENAME_MAX];
417         char temp_path[FILENAME_MAX];
418         char err_buf[1024];
419         const char *err_str;
420         struct timespec time = {
421                 .tv_sec = 0,
422                 .tv_nsec = 1000 * 1000 * 200
423         };
424         char mountflags_str[BUF_SIZE];
425         const char *argv_mount[] = { "/bin/app2sd-mount-helper", dev,
426                 app_mmc_path, FS_TYPE, mountflags_str, NULL };
427
428         if (dev == NULL) {
429                 _E("input param is NULL (%s)", dev);
430                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
431         }
432
433         /* check directory existence */
434         fd = open(application_path, O_RDONLY | O_DIRECTORY);
435         if (fd < 0) {
436                 _E("path(%s) error(%d)", application_path, errno);
437                 return APP2EXT_ERROR_OPEN_DIR;
438         }
439         close(fd);
440
441         snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
442                         application_path);
443         fd = open(app_mmc_path, O_RDONLY | O_DIRECTORY);
444         if (fd < 0) {
445                 _E("path(%s) error(%d)", app_mmc_path, errno);
446                 return APP2EXT_ERROR_OPEN_DIR;
447         }
448         close(fd);
449
450         nanosleep(&time, NULL); /* 200ms sleep */
451         _D("give a delay for mount");
452
453         switch (mount_type) {
454         case MOUNT_TYPE_RD:
455                 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
456                                 MS_MGC_VAL | MS_RDONLY | MS_NOSUID);
457                 ret = _xsystem(argv_mount);
458                 if (ret) {
459                         _E("read only mount failed, errono is (%d), "
460                                         "dev is (%s) path is (%s)",
461                                         ret, dev, app_mmc_path);
462                         ret = APP2EXT_ERROR_MOUNT;
463                 }
464                 break;
465         case MOUNT_TYPE_RW:
466                 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
467                                 MS_MGC_VAL | MS_NOSUID);
468                 ret = _xsystem(argv_mount);
469                 if (ret) {
470                         _E("read write mount failed, errno is (%d)", ret);
471                         ret = APP2EXT_ERROR_MOUNT;
472                 }
473                 break;
474         case MOUNT_TYPE_RW_NOEXEC:
475                 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
476                                 MS_MGC_VAL | MS_NOEXEC | MS_NOSUID);
477                 ret = _xsystem(argv_mount);
478                 if (ret) {
479                         _E("rwnx mount failed errno is (%d)", ret);
480                         ret = APP2EXT_ERROR_MOUNT;
481                 }
482                 break;
483         case MOUNT_TYPE_RD_REMOUNT:
484                 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
485                                 MS_MGC_VAL | MS_RDONLY | MS_REMOUNT |
486                                 MS_NOSUID);
487                 ret = _xsystem(argv_mount);
488                 if (ret) {
489                         _E("read remount failed errno is (%d)", ret);
490                         ret = APP2EXT_ERROR_MOUNT;
491                 }
492                 break;
493         case MOUNT_TYPE_RW_REMOUNT:
494                 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
495                                 MS_MGC_VAL | MS_REMOUNT | MS_NOSUID);
496                 ret = _xsystem(argv_mount);
497                 err_str = strerror_r(ret, err_buf, sizeof(err_buf));
498                 if (ret) {
499                         _E("read write remount failed errno(%d), errstr(%s)",
500                                         ret, err_str);
501                         ret = APP2EXT_ERROR_MOUNT;
502                 }
503                 break;
504         default:
505                 _E("invalid mount type");
506                 break;
507         }
508
509         if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC ||
510                         cmd == APP2SD_PRE_UPGRADE) {
511                 ret = _app2sd_create_directory_entry(application_path,
512                                 pkgid, dir_list, uid);
513         }
514
515         if (mount_type != MOUNT_TYPE_RD &&
516                         mount_type != MOUNT_TYPE_RD_REMOUNT) {
517                 /* change lost+found permission */
518                 snprintf(temp_path, sizeof(temp_path), "%s/lost+found",
519                                 app_mmc_path);
520                 ret = _app2sd_make_directory(temp_path, uid);
521                 if (ret) {
522                         _E("create directory(%s) failed", temp_path);
523                         return APP2EXT_ERROR_CREATE_DIRECTORY;
524                 }
525         }
526
527         return ret;
528 }
529
530 int _app2sd_unmount_app_content(const char *application_path)
531 {
532         int ret;
533         char app_mmc_path[FILENAME_MAX];
534         char err_buf[1024];
535         const char *err_str;
536
537         snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
538                         application_path);
539         ret = umount(app_mmc_path);
540         if (ret < 0) {
541                 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
542                 _D("unable to umount the dir, ret(%d) error(%d, %s)",
543                                 ret, errno, err_str);
544         }
545
546         return ret;
547 }
548
549 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
550 {
551         int ret;
552         char err_buf[1024];
553         const char *err_str;
554
555         ret = _app2sd_copy_dir(src_path, arch_path);
556         if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
557                 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
558                 _E("unable to copy from (%s) to (%s), err is (%s)",
559                                 src_path, arch_path, err_str);
560                 return APP2EXT_ERROR_MOVE;
561         }
562
563         ret = _app2sd_delete_directory(src_path);
564         if (ret) {
565                 _E("unable to delete (%s)", src_path);
566                 return APP2EXT_ERROR_DELETE_DIRECTORY;
567         }
568
569         return ret;
570 }
571
572 static int _app2sd_move_app_to_external(const char *pkgid, GList *dir_list,
573                 uid_t uid, char *mmc_path, char **image_path)
574 {
575         int ret;
576         mode_t mode = DIR_PERMS;
577         char temp_dir_path[FILENAME_MAX];
578         char app_mmc_path[FILENAME_MAX];
579         char app_archive_path[FILENAME_MAX];
580         char application_path[FILENAME_MAX];
581         char loopback_device[FILENAME_MAX];
582         unsigned long long total_size = 0;
583         int reqd_size;
584         int reqd_disk_size;
585         char *device_node;
586         int free_mmc_mem;
587         FILE *fp;
588         GList *list;
589         app2ext_dir_details *dir_detail;
590         char err_buf[1024];
591         const char *err_str;
592
593         ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
594                         loopback_device, sizeof(loopback_device));
595         if (ret)
596                 return ret;
597
598         _app2sd_set_application_path(pkgid, uid, application_path,
599                         sizeof(application_path));
600
601         /* check whether application is in external memory or not */
602         fp = fopen(loopback_device, "r+");
603         if (fp != NULL) {
604                 _W("Already %s entry is present in the SD Card, "
605                                 "delete entry and go on without return", pkgid);
606                 fclose(fp);
607                 _app2sd_force_clean(pkgid, application_path, loopback_device,
608                                 uid);
609         }
610
611         snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
612                         application_path);
613         snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
614                         application_path);
615
616         ret = mkdir(app_mmc_path, mode);
617         if (ret) {
618                 if (errno != EEXIST) {
619                         _E("unable to create directory for archiving,"
620                                         " error(%d)", errno);
621                         return APP2EXT_ERROR_CREATE_DIRECTORY;
622                 }
623         }
624
625         ret = mkdir(app_archive_path, mode);
626         if (ret) {
627                 if (errno != EEXIST) {
628                         _E("unable to create directory for archiving,"
629                                         " error(%d)", errno);
630                         return APP2EXT_ERROR_CREATE_DIRECTORY;
631                 }
632         }
633
634         for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
635                 dir_detail = (app2ext_dir_details *)list->data;
636                 if (dir_detail == NULL || dir_detail->name == NULL ||
637                                 dir_detail->type != APP2EXT_DIR_RO)
638                         continue;
639                 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
640                                 application_path, dir_detail->name);
641                 _D("cal size of app dirs, temp_dir_path(%s)", temp_dir_path);
642                 total_size += _app2sd_calculate_dir_size(temp_dir_path);
643         }
644
645         reqd_size = ((total_size) / (1024 * 1024)) + 2;
646         reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
647
648         /* find avialable free memory in the MMC card */
649         ret = _app2sd_get_available_free_memory(mmc_path, &free_mmc_mem);
650         if (ret) {
651                 _E("unable to get available free memory in MMC (%d)", ret);
652                 return APP2EXT_ERROR_MMC_STATUS;
653         }
654         /* if avaialalbe free memory in MMC is less than
655          * required size + 5MB, return error
656          */
657         if (reqd_disk_size > free_mmc_mem) {
658                 _E("insufficient memory in MMC for "
659                                 "application installation (%d)", ret);
660                 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
661         }
662         /* create a loopback device */
663         ret = _app2sd_create_loopback_device(pkgid, loopback_device,
664                         (reqd_disk_size + PKG_BUF_SIZE));
665         if (ret) {
666                 _E("loopback node creation failed");
667                 return ret;
668         }
669
670         ret = _app2sd_dmcrypt_setup_device(pkgid, loopback_device, false, uid);
671         if (ret) {
672                 _E("dmcrypt setup device error(%d)", ret);
673                 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
674         }
675
676         ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device, false,
677                         uid, &device_node);
678         if (ret) {
679                 _E("dmcrypt open device error");
680                 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
681         }
682         /* format the loopback file system */
683         ret = _app2sd_create_file_system(device_node);
684         if (ret) {
685                 _E("create ext4 filesystem failed");
686                 ret = APP2EXT_ERROR_CREATE_FS;
687                 goto ERR;
688         }
689
690         for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
691                 dir_detail = (app2ext_dir_details *)list->data;
692                 if (dir_detail == NULL || dir_detail->name == NULL ||
693                                 dir_detail->type != APP2EXT_DIR_RO)
694                         continue;
695                 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
696                                 application_path, dir_detail->name);
697                 _D("app2archive, temp_dir_path(%s)", temp_dir_path);
698                 ret = _app2sd_move_to_archive(temp_dir_path, app_archive_path);
699                 if (ret) {
700                         _E("unable to copy from (%s) to (%s)",
701                                         temp_dir_path, app_archive_path);
702                         goto ERR;
703                 }
704         }
705
706         /* mount the loopback encrypted pseudo device on
707          * application installation path as with Read Write permission
708          */
709         ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
710                         MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
711         if (ret) {
712                 _E("mount failed");
713                 goto ERR;
714         }
715
716         for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
717                 dir_detail = (app2ext_dir_details *)list->data;
718                 if (dir_detail == NULL || dir_detail->name == NULL ||
719                                 dir_detail->type != APP2EXT_DIR_RO)
720                         continue;
721                 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
722                                 app_archive_path, dir_detail->name);
723                 _D("archive2mmc, temp_dir_path(%s)", temp_dir_path);
724                 ret = _app2sd_copy_dir(temp_dir_path, app_mmc_path);
725                 if (ret) {
726                         if (ret == APP2EXT_ERROR_ACCESS_FILE) {
727                                 _E("unable to access (%s)", temp_dir_path);
728                         } else {
729                                 err_str = strerror_r(errno, err_buf,
730                                                 sizeof(err_buf));
731                                 _E("unable to copy from (%s) to (%s),"
732                                                 " error is (%s)", temp_dir_path,
733                                                 app_mmc_path, err_str);
734                         }
735                         goto ERR;
736                 }
737                 ret = _app2sd_delete_directory(temp_dir_path);
738                 if (ret) {
739                         _E("unable to delete (%s)", temp_dir_path);
740                         goto ERR;
741                 }
742         }
743
744         ret = _app2sd_delete_directory(app_archive_path);
745         if (ret) {
746                 _E("unable to delete (%s)", app_archive_path);
747                 ret = APP2EXT_ERROR_DELETE_DIRECTORY;
748                 goto ERR;
749         }
750
751         *image_path = strdup(loopback_device);
752         return APP2EXT_SUCCESS;
753
754 ERR:
755         if (device_node)
756                 free(device_node);
757
758         *image_path = NULL;
759         return ret;
760 }
761
762 static int _app2sd_move_app_to_internal(const char *pkgid, GList *dir_list,
763                 uid_t uid, char *mmc_path)
764 {
765         int ret;
766         mode_t mode = DIR_PERMS;
767         char temp_dir_path[FILENAME_MAX];
768         char app_mmc_path[FILENAME_MAX];
769         char app_archive_path[FILENAME_MAX];
770         char application_path[FILENAME_MAX];
771         char loopback_device[FILENAME_MAX];
772         char *device_node;
773         FILE *fp;
774         GList *list;
775         app2ext_dir_details *dir_detail;
776         int reqd_size;
777         int free_internal_mem;
778         unsigned long long temp = 0;
779         char err_buf[1024];
780         const char *err_str;
781         int mount_type;
782
783         ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
784                         loopback_device, sizeof(loopback_device));
785         if (ret)
786                 return ret;
787
788         _app2sd_set_application_path(pkgid, uid, application_path,
789                 sizeof(application_path));
790
791         /* check whether application is in external memory or not */
792         fp = fopen(loopback_device, "r+");
793         if (fp == NULL) {
794                 _E("application (%s) is not installed on SD Card",
795                      pkgid);
796                 return APP2EXT_ERROR_FILE_ABSENT;
797         }
798         fclose(fp);
799
800         /* find avialable free memory in the internal storage */
801         ret = _app2sd_get_available_free_memory(INTERNAL_STORAGE_PATH,
802                         &free_internal_mem);
803         if (ret) {
804                 _E("unable to get available free memory in internal (%d)", ret);
805                 return APP2EXT_ERROR_MMC_STATUS;
806         }
807
808         fp = fopen(loopback_device, "r+");
809         if (fp == NULL) {
810                 _E("app entry is not present in SD card");
811                 return APP2EXT_ERROR_INVALID_PACKAGE;
812         }
813         fclose(fp);
814
815         /* get installed app size*/
816         temp = _app2sd_calculate_file_size(loopback_device);
817         reqd_size = (int)((temp) / (1024 * 1024));
818         _D("reqd size is (%d)", reqd_size);
819
820         if (reqd_size == 0) {
821                 _E("app entry is not present in SD Card");
822                 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
823         }
824
825         _I("reqd size: (%d)MB, free internal mem: (%d)MB",
826                         reqd_size, free_internal_mem);
827
828         /* if avaialalbe free memory in internal storage is
829          * less than required size, return error
830          */
831         if (reqd_size > free_internal_mem) {
832                 _E("innsufficient memory in internal storage"
833                         " for application installation (%d)", ret);
834                 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
835         }
836
837         device_node =
838                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
839         if (device_node == NULL) {
840                 /* do loopback setup */
841                 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
842                                 false, uid, &device_node);
843                 if (ret) {
844                         _E("dmcrypt open device error(%d)", ret);
845                         return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
846                 }
847                 mount_type = MOUNT_TYPE_RW;
848         } else {
849                 mount_type = MOUNT_TYPE_RW_REMOUNT;
850         }
851         /* do mounting */
852         ret = _app2sd_mount_app_content(application_path,
853                         pkgid, device_node, mount_type,
854                         dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
855         if (ret) {
856                 _E("mount failed");
857                 ret = APP2EXT_ERROR_MOUNT_PATH;
858                 goto ERR;
859         }
860
861         snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
862                         application_path);
863         snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
864                         application_path);
865
866         ret = mkdir(app_archive_path, mode);
867         if (ret) {
868                 if (errno != EEXIST) {
869                         _E("unable to create directory for archiving,"
870                                         " error(%d)", errno);
871                         ret = APP2EXT_ERROR_CREATE_DIRECTORY;
872                         goto ERR;
873                 }
874         }
875
876         for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
877                 dir_detail = (app2ext_dir_details *)list->data;
878                 if (dir_detail == NULL || dir_detail->name == NULL ||
879                                 dir_detail->type != APP2EXT_DIR_RO)
880                         continue;
881                 /* archiving code */
882                 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
883                                 app_mmc_path, dir_detail->name);
884                 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
885                 ret = _app2sd_copy_dir(temp_dir_path, app_archive_path);
886                 if (ret) {
887                         if (ret == APP2EXT_ERROR_ACCESS_FILE) {
888                                 _E("unable to access (%s)", temp_dir_path);
889                         } else {
890                                 err_str = strerror_r(errno, err_buf,
891                                                 sizeof(err_buf));
892                                 _E("unable to copy from (%s) to (%s),"
893                                                 "error is (%s)", temp_dir_path,
894                                                 app_archive_path, err_str);
895                         }
896                         goto ERR;
897                 }
898                 /* delete the symbolic link files [bin, lib, res]*/
899                 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
900                                 application_path, dir_detail->name);
901                 _D("unlink, temp_dir_path(%s)", temp_dir_path);
902                 ret = unlink(temp_dir_path);
903                 if (ret) {
904                         if (errno == ENOENT) {
905                                 _W("(%s) does not exist", temp_dir_path);
906                         } else {
907                                 _E("unable to remove the symbolic link file "
908                                                 "(%s), it is already unlinked",
909                                                 temp_dir_path);
910                                 goto ERR;
911                         }
912                 }
913                 /* Copy content to destination */
914                 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
915                                 app_archive_path, dir_detail->name);
916                 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
917                 ret = _app2sd_copy_dir(temp_dir_path, application_path);
918                 if (ret) {
919                         if (ret == APP2EXT_ERROR_ACCESS_FILE) {
920                                 _E("unable to access (%s)", temp_dir_path);
921                         } else {
922                                 err_str = strerror_r(errno, err_buf,
923                                                 sizeof(err_buf));
924                                 _E("unable to copy from (%s) to (%s), "
925                                                 "error is (%s)", temp_dir_path,
926                                                 application_path, err_str);
927                         }
928                         goto ERR;
929                 }
930         }
931
932         _D("copying file completed");
933         ret = _app2sd_unmount_app_content(application_path);
934         if (ret)
935                 _E("unable to unmount SD directory for app (%s)", pkgid);
936
937         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
938         if (ret)
939                 _E("close dmcrypt device error(%d)", ret);
940
941         ret = _app2sd_delete_loopback_device(loopback_device);
942         if (ret)
943                 _E("unable to delete the loopback device for (%s)", pkgid);
944
945         ret = _app2sd_delete_directory(app_mmc_path);
946         if (ret)
947                 _E("unable to delete (%s)", app_mmc_path);
948
949         ret = _app2sd_delete_directory(app_archive_path);
950         if (ret)
951                 _E("unable to delete (%s)", app_archive_path);
952
953         /* remove passwrd from DB */
954         ret = _app2sd_initialize_db();
955         if (ret)
956                 _E("app2sd db initialize failed");
957
958         ret = _app2sd_remove_info_from_db(pkgid, uid);
959         if (ret)
960                 _E("cannot remove info from db");
961
962         return APP2EXT_SUCCESS;
963
964 ERR:
965         if (device_node)
966                 free(device_node);
967
968         return ret;
969 }
970
971 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
972                 GList *dir_list, uid_t uid, char *mmc_path, char **image_path)
973 {
974         int ret;
975
976         switch (move_type) {
977         case APP2EXT_MOVE_TO_EXT:
978                 ret = _app2sd_move_app_to_external(pkgid, dir_list,
979                                 uid, mmc_path, image_path);
980                 if (ret) {
981                         _E("move app to external memory failed(%d)", ret);
982                         return ret;
983                 }
984                 break;
985         case APP2EXT_MOVE_TO_PHONE:
986                 ret = _app2sd_move_app_to_internal(pkgid, dir_list,
987                                 uid, mmc_path);
988                 if (ret) {
989                         _E("move app to internal memory failed(%d)", ret);
990                         return ret;
991                 }
992                 break;
993         default:
994                 _E("invalid argument");
995                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
996         }
997
998         return ret;
999 }
1000
1001 int _app2sd_copy_ro_content(const char *src, const char *dest, GList *dir_list)
1002 {
1003         char path[FILENAME_MAX];
1004         int ret;
1005         GList *list;
1006         app2ext_dir_details *dir_detail;
1007
1008         for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
1009                 dir_detail = (app2ext_dir_details *)list->data;
1010                 if (dir_detail == NULL || dir_detail->name == NULL ||
1011                                 dir_detail->type != APP2EXT_DIR_RO)
1012                         continue;
1013
1014                 snprintf(path, sizeof(path), "%s/%s", src, dir_detail->name);
1015                 ret = _app2sd_copy_dir(path, dest);
1016                 if (ret) {
1017                         if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1018                                 _E("unable to access (%s)", path);
1019                         } else {
1020                                 _E("unable to copy from (%s) "
1021                                                 "to (%s), errno is (%d)",
1022                                                 path, dest, errno);
1023                                 return APP2EXT_ERROR_MOVE;
1024                         }
1025                 }
1026         }
1027
1028         return APP2EXT_SUCCESS;
1029 }
1030
1031 int _app2sd_duplicate_device(const char *pkgid, const char *loopback_device,
1032                 const char *temp_pkgid, const char *temp_application_path,
1033                 const char *temp_loopback_device, GList *dir_list,
1034                 char *dev_node, int size, uid_t uid)
1035 {
1036         int ret;
1037         int err_res;
1038
1039         /* create a new loopback device */
1040         ret = _app2sd_create_loopback_device(temp_pkgid,
1041                         temp_loopback_device, (size + PKG_BUF_SIZE));
1042         if (ret) {
1043                 _E("package already present");
1044                 return ret;
1045         }
1046
1047         /* perform loopback encryption setup */
1048         dev_node = _app2sd_dmcrypt_duplicate_encryption_setup(pkgid,
1049                         temp_loopback_device, uid);
1050         if (!dev_node) {
1051                 _E("dmcrypt duplicate encryption setup failed");
1052                 _app2sd_delete_loopback_device(temp_loopback_device);
1053                 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
1054         }
1055
1056         /* format the loopback file system */
1057         ret = _app2sd_create_file_system(dev_node);
1058         if (ret) {
1059                 _E("creating fs failed");
1060                 err_res = APP2EXT_ERROR_CREATE_FS;
1061                 goto FINISH_OFF;
1062         }
1063         _D("create filesystem SUCCESS");
1064
1065         /* do mounting for new dev*/
1066         ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1067                         dev_node, MOUNT_TYPE_RW, dir_list,
1068                         APP2SD_PRE_UPGRADE, uid);
1069         if (ret) {
1070                 _E("remount failed");
1071                 err_res = APP2EXT_ERROR_MOUNT_PATH;
1072                 goto FINISH_OFF;
1073         }
1074
1075         return APP2EXT_SUCCESS;
1076
1077 FINISH_OFF:
1078         if (dev_node) {
1079                 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1080                 if (ret)
1081                         _E("close dmcrypt device error(%d)", ret);
1082                 _app2sd_delete_loopback_device(temp_loopback_device);
1083                 free(dev_node);
1084         }
1085
1086         return err_res;
1087 }
1088
1089 int _app2sd_update_loopback_device_size(const char *pkgid,
1090                 const char *loopback_device, const char *application_path,
1091                 const char *temp_pkgid, const char *temp_loopback_device,
1092                 const char *temp_application_path, int size, GList *dir_list,
1093                 uid_t uid)
1094 {
1095         int ret;
1096         char *old_device_node;
1097         int err_res;
1098         char app_mmc_path[FILENAME_MAX];
1099         char temp_app_mmc_path[FILENAME_MAX];
1100         int mount_type;
1101
1102         ret = _app2sd_duplicate_device(pkgid, loopback_device, temp_pkgid,
1103                         temp_application_path, temp_loopback_device,
1104                         dir_list, NULL, size, uid);
1105         if (ret) {
1106                 _E("creating duplicate device failed");
1107                 return ret;
1108         }
1109
1110         /* get the associated device node for SD card applicatione */
1111         old_device_node =
1112                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1113         if (old_device_node == NULL) {
1114                 /* do loopback setup */
1115                 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1116                         false, uid, &old_device_node);
1117                 if (ret) {
1118                         _E("dmcrypt open device error");
1119                         err_res = APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1120                         goto FINISH_OFF;
1121                 }
1122                 mount_type = MOUNT_TYPE_RW;
1123         } else {
1124                 mount_type = MOUNT_TYPE_RW_REMOUNT;
1125         }
1126
1127         /* do mounting */
1128         ret = _app2sd_mount_app_content(application_path, pkgid,
1129                         old_device_node, mount_type, dir_list,
1130                         APP2SD_PRE_UPGRADE, uid);
1131         if (ret) {
1132                 _E("remount failed");
1133                 err_res = APP2EXT_ERROR_MOUNT_PATH;
1134         }
1135         free(old_device_node);
1136
1137         snprintf(app_mmc_path, sizeof(app_mmc_path),
1138                         "%s/.mmc", application_path);
1139         snprintf(temp_app_mmc_path, sizeof(temp_app_mmc_path),
1140                         "%s/.mmc", temp_application_path);
1141
1142         ret = _app2sd_copy_ro_content(app_mmc_path,
1143                         temp_app_mmc_path, dir_list);
1144         if (ret) {
1145                 _E("copy ro content failed");
1146                 err_res = ret;
1147         }
1148
1149         ret = _app2sd_unmount_app_content(application_path);
1150         if (ret) {
1151                 _E("unable to unmount the SD application");
1152                 err_res = APP2EXT_ERROR_UNMOUNT;
1153         }
1154
1155         ret = _app2sd_unmount_app_content(temp_application_path);
1156         if (ret) {
1157                 _E("unable to unmount the SD application");
1158                 err_res = APP2EXT_ERROR_UNMOUNT;
1159                 goto FINISH_OFF;
1160         }
1161
1162         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1163         if (ret) {
1164                 _E("close dmcrypt device error(%d)", ret);
1165                 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1166                 goto FINISH_OFF;
1167         }
1168
1169         ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1170         if (ret) {
1171                 _E("close dmcrypt device error(%d)", ret);
1172                 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1173                 goto FINISH_OFF;
1174         }
1175
1176         ret = _app2sd_delete_directory(loopback_device);
1177         if (ret) {
1178                 _E("unable to delete (%s)", loopback_device);
1179                 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1180                 goto FINISH_OFF;
1181         }
1182
1183         ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1184         if (ret) {
1185                 _E("unable to rename (%s)", temp_loopback_device);
1186                 err_res = APP2EXT_ERROR_MOVE;
1187                 goto FINISH_OFF;
1188         }
1189
1190         ret = _app2sd_delete_directory(temp_application_path);
1191         if (ret) {
1192                 _E("unable to delete (%s)", temp_application_path);
1193                 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1194                 goto FINISH_OFF;
1195         }
1196
1197         return APP2EXT_SUCCESS;
1198
1199 FINISH_OFF:
1200         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1201         if (ret)
1202                 _E("close dmcrypt device error(%d)", ret);
1203
1204         ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1205         if (ret)
1206                 _E("close dmcrypt device error(%d)", ret);
1207
1208         _app2sd_delete_loopback_device(temp_loopback_device);
1209
1210         ret = _app2sd_delete_directory(temp_application_path);
1211         if (ret)
1212                 _E("unable to delete (%s)", temp_application_path);
1213
1214         return err_res;
1215 }
1216
1217 int _app2sd_force_clean(const char *pkgid, const char *application_path,
1218                 const char *loopback_device, uid_t uid)
1219 {
1220         int ret;
1221
1222         /* unmount the loopback encrypted pseudo device from
1223          * the application installation path
1224          */
1225         ret = _app2sd_unmount_app_content(application_path);
1226         if (ret)
1227                 _W("unable to unmount the app content (%d)", ret);
1228
1229         /* detach the loopback encryption setup for the application */
1230         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1231         if (ret)
1232                 _W("close dmcrypt device error (%d)", ret);
1233
1234         /* delete the loopback device from the SD card */
1235         ret = _app2sd_delete_loopback_device(loopback_device);
1236         if (ret)
1237                 _W("unable to detach the loopback encryption setup for "
1238                                 "the application");
1239
1240         /* delete symlink */
1241         _app2sd_delete_symlink(application_path);
1242
1243         /* remove passwrd from DB */
1244         ret = _app2sd_initialize_db();
1245         if (ret)
1246                 _W("app2sd db initialize failed");
1247
1248         ret = _app2sd_remove_info_from_db(pkgid, uid);
1249         if (ret)
1250                 _W("cannot remove info from db");
1251
1252         return ret;
1253 }