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