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