Fix static analyzer 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
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                         _E("unable to copy from (%s) to (%s)",
704                                         temp_dir_path, app_archive_path);
705                         goto ERR;
706                 }
707         }
708
709         /* mount the loopback encrypted pseudo device on
710          * application installation path as with Read Write permission
711          */
712         ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
713                         MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
714         if (ret) {
715                 _E("mount failed");
716                 goto ERR;
717         }
718
719         for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
720                 dir_detail = (app2ext_dir_details *)list->data;
721                 if (dir_detail == NULL || dir_detail->name == NULL ||
722                                 dir_detail->type != APP2EXT_DIR_RO)
723                         continue;
724                 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
725                                 app_archive_path, dir_detail->name);
726                 _D("archive2mmc, temp_dir_path(%s)", temp_dir_path);
727                 ret = _app2sd_copy_dir(temp_dir_path, app_mmc_path);
728                 if (ret) {
729                         if (ret == APP2EXT_ERROR_ACCESS_FILE) {
730                                 _E("unable to access (%s)", temp_dir_path);
731                         } else {
732                                 strerror_r(errno, err_buf, sizeof(err_buf));
733                                 _E("unable to copy from (%s) to (%s),"
734                                                 " error is (%s)", temp_dir_path,
735                                                 app_mmc_path, err_buf);
736                         }
737                         goto ERR;
738                 }
739                 ret = _app2sd_delete_directory(temp_dir_path);
740                 if (ret) {
741                         _E("unable to delete (%s)", temp_dir_path);
742                         goto ERR;
743                 }
744         }
745
746         ret = _app2sd_delete_directory(app_archive_path);
747         if (ret) {
748                 _E("unable to delete (%s)", app_archive_path);
749                 ret = APP2EXT_ERROR_DELETE_DIRECTORY;
750                 goto ERR;
751         }
752
753         *image_path = strdup(loopback_device);
754         return APP2EXT_SUCCESS;
755
756 ERR:
757         if (device_node)
758                 free(device_node);
759
760         *image_path = NULL;
761         return ret;
762 }
763
764 static int _app2sd_move_app_to_internal(const char *pkgid, GList *dir_list,
765                 uid_t uid, char *mmc_path)
766 {
767         int ret;
768         mode_t mode = DIR_PERMS;
769         char temp_dir_path[FILENAME_MAX];
770         char app_mmc_path[FILENAME_MAX];
771         char app_archive_path[FILENAME_MAX];
772         char application_path[FILENAME_MAX];
773         char loopback_device[FILENAME_MAX];
774         char *device_node;
775         FILE *fp;
776         GList *list;
777         app2ext_dir_details *dir_detail;
778         int reqd_size;
779         int free_internal_mem;
780         unsigned long long temp = 0;
781         char err_buf[1024];
782         int mount_type;
783
784         ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
785                         loopback_device, sizeof(loopback_device));
786         if (ret)
787                 return ret;
788
789         _app2sd_set_application_path(pkgid, uid, application_path,
790                 sizeof(application_path));
791
792         /* check whether application is in external memory or not */
793         fp = fopen(loopback_device, "r+");
794         if (fp == NULL) {
795                 _E("application (%s) is not installed on SD Card",
796                      pkgid);
797                 return APP2EXT_ERROR_FILE_ABSENT;
798         }
799         fclose(fp);
800
801         /* find avialable free memory in the internal storage */
802         ret = _app2sd_get_available_free_memory(INTERNAL_STORAGE_PATH,
803                         &free_internal_mem);
804         if (ret) {
805                 _E("unable to get available free memory in internal (%d)", ret);
806                 return APP2EXT_ERROR_MMC_STATUS;
807         }
808
809         fp = fopen(loopback_device, "r+");
810         if (fp == NULL) {
811                 _E("app entry is not present in SD card");
812                 return APP2EXT_ERROR_INVALID_PACKAGE;
813         }
814         fclose(fp);
815
816         /* get installed app size*/
817         temp = _app2sd_calculate_file_size(loopback_device);
818         reqd_size = (int)((temp) / (1024 * 1024));
819         _D("reqd size is (%d)", reqd_size);
820
821         if (reqd_size == 0) {
822                 _E("app entry is not present in SD Card");
823                 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
824         }
825
826         _I("reqd size: (%d)MB, free internal mem: (%d)MB",
827                         reqd_size, free_internal_mem);
828
829         /* if avaialalbe free memory in internal storage is
830          * less than required size, return error
831          */
832         if (reqd_size > free_internal_mem) {
833                 _E("innsufficient memory in internal storage"
834                         " for application installation (%d)", ret);
835                 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
836         }
837
838         device_node =
839                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
840         if (device_node == NULL) {
841                 /* do loopback setup */
842                 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
843                                 false, uid, &device_node);
844                 if (ret) {
845                         _E("dmcrypt open device error(%d)", ret);
846                         return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
847                 }
848                 mount_type = MOUNT_TYPE_RW;
849         } else {
850                 mount_type = MOUNT_TYPE_RW_REMOUNT;
851         }
852         /* do mounting */
853         ret = _app2sd_mount_app_content(application_path,
854                         pkgid, device_node, mount_type,
855                         dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
856         if (ret) {
857                 _E("mount failed");
858                 ret = APP2EXT_ERROR_MOUNT_PATH;
859                 goto ERR;
860         }
861
862         snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
863                         application_path);
864         snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
865                         application_path);
866
867         ret = mkdir(app_archive_path, mode);
868         if (ret) {
869                 if (errno != EEXIST) {
870                         _E("unable to create directory for archiving,"
871                                         " error(%d)", errno);
872                         ret = APP2EXT_ERROR_CREATE_DIRECTORY;
873                         goto ERR;
874                 }
875         }
876
877         for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
878                 dir_detail = (app2ext_dir_details *)list->data;
879                 if (dir_detail == NULL || dir_detail->name == NULL ||
880                                 dir_detail->type != APP2EXT_DIR_RO)
881                         continue;
882                 /* archiving code */
883                 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
884                                 app_mmc_path, dir_detail->name);
885                 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
886                 ret = _app2sd_copy_dir(temp_dir_path, app_archive_path);
887                 if (ret) {
888                         if (ret == APP2EXT_ERROR_ACCESS_FILE) {
889                                 _E("unable to access (%s)", temp_dir_path);
890                         } else {
891                                 strerror_r(errno, err_buf, sizeof(err_buf));
892                                 _E("unable to copy from (%s) to (%s),"
893                                                 "error is (%s)", temp_dir_path,
894                                                 app_archive_path, err_buf);
895                         }
896                         goto ERR;
897                 }
898                 /* delete the symbolic link files [bin, lib, res]*/
899                 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
900                                 application_path, dir_detail->name);
901                 _D("unlink, temp_dir_path(%s)", temp_dir_path);
902                 ret = unlink(temp_dir_path);
903                 if (ret) {
904                         if (errno == ENOENT) {
905                                 _W("(%s) does not exist", temp_dir_path);
906                         } else {
907                                 _E("unable to remove the symbolic link file "
908                                                 "(%s), it is already unlinked",
909                                                 temp_dir_path);
910                                 goto ERR;
911                         }
912                 }
913                 /* Copy content to destination */
914                 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
915                                 app_archive_path, dir_detail->name);
916                 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
917                 ret = _app2sd_copy_dir(temp_dir_path, application_path);
918                 if (ret) {
919                         if (ret == APP2EXT_ERROR_ACCESS_FILE) {
920                                 _E("unable to access (%s)", temp_dir_path);
921                         } else {
922                                 strerror_r(errno, err_buf, sizeof(err_buf));
923                                 _E("unable to copy from (%s) to (%s), "
924                                                 "error is (%s)", temp_dir_path,
925                                                 application_path, err_buf);
926                         }
927                         goto ERR;
928                 }
929         }
930
931         _D("copying file completed");
932         ret = _app2sd_unmount_app_content(application_path);
933         if (ret)
934                 _E("unable to unmount SD directory for app (%s)", pkgid);
935
936         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
937         if (ret)
938                 _E("close dmcrypt device error(%d)", ret);
939
940         ret = _app2sd_delete_loopback_device(loopback_device);
941         if (ret)
942                 _E("unable to delete the loopback device for (%s)", pkgid);
943
944         ret = _app2sd_delete_directory(app_mmc_path);
945         if (ret)
946                 _E("unable to delete (%s)", app_mmc_path);
947
948         ret = _app2sd_delete_directory(app_archive_path);
949         if (ret)
950                 _E("unable to delete (%s)", app_archive_path);
951
952         /* remove passwrd from DB */
953         ret = _app2sd_initialize_db();
954         if (ret)
955                 _E("app2sd db initialize failed");
956
957         ret = _app2sd_remove_info_from_db(pkgid, uid);
958         if (ret)
959                 _E("cannot remove info from db");
960
961         return APP2EXT_SUCCESS;
962
963 ERR:
964         if (device_node)
965                 free(device_node);
966
967         return ret;
968 }
969
970 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
971                 GList *dir_list, uid_t uid, char *mmc_path, char **image_path)
972 {
973         int ret;
974
975         switch (move_type) {
976         case APP2EXT_MOVE_TO_EXT:
977                 ret = _app2sd_move_app_to_external(pkgid, dir_list,
978                                 uid, mmc_path, image_path);
979                 if (ret) {
980                         _E("move app to external memory failed(%d)", ret);
981                         return ret;
982                 }
983                 break;
984         case APP2EXT_MOVE_TO_PHONE:
985                 ret = _app2sd_move_app_to_internal(pkgid, dir_list,
986                                 uid, mmc_path);
987                 if (ret) {
988                         _E("move app to internal memory failed(%d)", ret);
989                         return ret;
990                 }
991                 break;
992         default:
993                 _E("invalid argument");
994                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
995         }
996
997         return ret;
998 }
999
1000 int _app2sd_copy_ro_content(const char *src, const char *dest, GList *dir_list)
1001 {
1002         char path[FILENAME_MAX];
1003         int ret;
1004         GList *list;
1005         app2ext_dir_details *dir_detail;
1006
1007         for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
1008                 dir_detail = (app2ext_dir_details *)list->data;
1009                 if (dir_detail == NULL || dir_detail->name == NULL ||
1010                                 dir_detail->type != APP2EXT_DIR_RO)
1011                         continue;
1012
1013                 snprintf(path, sizeof(path), "%s/%s", src, dir_detail->name);
1014                 ret = _app2sd_copy_dir(path, dest);
1015                 if (ret) {
1016                         if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1017                                 _E("unable to access (%s)", path);
1018                         } else {
1019                                 _E("unable to copy from (%s) "
1020                                                 "to (%s), errno is (%d)",
1021                                                 path, dest, errno);
1022                                 return APP2EXT_ERROR_MOVE;
1023                         }
1024                 }
1025         }
1026
1027         return APP2EXT_SUCCESS;
1028 }
1029
1030 int _app2sd_duplicate_device(const char *pkgid, const char *loopback_device,
1031                 const char *temp_pkgid, const char *temp_application_path,
1032                 const char *temp_loopback_device, GList *dir_list,
1033                 char *dev_node, int size, uid_t uid)
1034 {
1035         int ret;
1036         int err_res;
1037
1038         /* create a new loopback device */
1039         ret = _app2sd_create_loopback_device(temp_pkgid,
1040                         temp_loopback_device, (size + PKG_BUF_SIZE));
1041         if (ret) {
1042                 _E("package already present");
1043                 return ret;
1044         }
1045
1046         /* perform loopback encryption setup */
1047         dev_node = _app2sd_dmcrypt_duplicate_encryption_setup(pkgid,
1048                         temp_loopback_device, uid);
1049         if (!dev_node) {
1050                 _E("dmcrypt duplicate encryption setup failed");
1051                 _app2sd_delete_loopback_device(temp_loopback_device);
1052                 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
1053         }
1054
1055         /* format the loopback file system */
1056         ret = _app2sd_create_file_system(dev_node);
1057         if (ret) {
1058                 _E("creating fs failed");
1059                 err_res = APP2EXT_ERROR_CREATE_FS;
1060                 goto FINISH_OFF;
1061         }
1062         _D("create filesystem SUCCESS");
1063
1064         /* do mounting for new dev*/
1065         ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1066                         dev_node, MOUNT_TYPE_RW, dir_list,
1067                         APP2SD_PRE_UPGRADE, uid);
1068         if (ret) {
1069                 _E("remount failed");
1070                 err_res = APP2EXT_ERROR_MOUNT_PATH;
1071                 goto FINISH_OFF;
1072         }
1073
1074         return APP2EXT_SUCCESS;
1075
1076 FINISH_OFF:
1077         if (dev_node) {
1078                 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1079                 if (ret)
1080                         _E("close dmcrypt device error(%d)", ret);
1081                 _app2sd_delete_loopback_device(temp_loopback_device);
1082                 free(dev_node);
1083         }
1084
1085         return err_res;
1086 }
1087
1088 int _app2sd_update_loopback_device_size(const char *pkgid,
1089                 const char *loopback_device, const char *application_path,
1090                 const char *temp_pkgid, const char *temp_loopback_device,
1091                 const char *temp_application_path, int size, GList *dir_list,
1092                 uid_t uid)
1093 {
1094         int ret;
1095         char *old_device_node;
1096         int err_res;
1097         char app_mmc_path[FILENAME_MAX];
1098         char temp_app_mmc_path[FILENAME_MAX];
1099         int mount_type;
1100
1101         ret = _app2sd_duplicate_device(pkgid, loopback_device, temp_pkgid,
1102                         temp_application_path, temp_loopback_device,
1103                         dir_list, NULL, size, uid);
1104         if (ret) {
1105                 _E("creating duplicate device failed");
1106                 return ret;
1107         }
1108
1109         /* get the associated device node for SD card applicatione */
1110         old_device_node =
1111                 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1112         if (old_device_node == NULL) {
1113                 /* do loopback setup */
1114                 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1115                         false, uid, &old_device_node);
1116                 if (ret) {
1117                         _E("dmcrypt open device error");
1118                         err_res = APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1119                         goto FINISH_OFF;
1120                 }
1121                 mount_type = MOUNT_TYPE_RW;
1122         } else {
1123                 mount_type = MOUNT_TYPE_RW_REMOUNT;
1124         }
1125
1126         /* do mounting */
1127         ret = _app2sd_mount_app_content(application_path, pkgid,
1128                         old_device_node, mount_type, dir_list,
1129                         APP2SD_PRE_UPGRADE, uid);
1130         if (ret) {
1131                 _E("remount failed");
1132                 err_res = APP2EXT_ERROR_MOUNT_PATH;
1133         }
1134
1135         snprintf(app_mmc_path, sizeof(app_mmc_path),
1136                         "%s/.mmc", application_path);
1137         snprintf(temp_app_mmc_path, sizeof(temp_app_mmc_path),
1138                         "%s/.mmc", temp_application_path);
1139
1140         ret = _app2sd_copy_ro_content(app_mmc_path,
1141                         temp_app_mmc_path, dir_list);
1142         if (ret) {
1143                 _E("copy ro content failed");
1144                 err_res = ret;
1145         }
1146
1147         ret = _app2sd_unmount_app_content(application_path);
1148         if (ret) {
1149                 _E("unable to unmount the SD application");
1150                 err_res = APP2EXT_ERROR_UNMOUNT;
1151         }
1152
1153         ret = _app2sd_unmount_app_content(temp_application_path);
1154         if (ret) {
1155                 _E("unable to unmount the SD application");
1156                 err_res = APP2EXT_ERROR_UNMOUNT;
1157                 goto FINISH_OFF;
1158         }
1159
1160         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1161         if (ret) {
1162                 _E("close dmcrypt device error(%d)", ret);
1163                 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1164                 goto FINISH_OFF;
1165         }
1166
1167         ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1168         if (ret) {
1169                 _E("close dmcrypt device error(%d)", ret);
1170                 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1171                 goto FINISH_OFF;
1172         }
1173
1174         ret = _app2sd_delete_directory(loopback_device);
1175         if (ret) {
1176                 _E("unable to delete (%s)", loopback_device);
1177                 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1178                 goto FINISH_OFF;
1179         }
1180
1181         ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1182         if (ret) {
1183                 _E("unable to rename (%s)", temp_loopback_device);
1184                 err_res = APP2EXT_ERROR_MOVE;
1185                 goto FINISH_OFF;
1186         }
1187
1188         ret = _app2sd_delete_directory(temp_application_path);
1189         if (ret) {
1190                 _E("unable to delete (%s)", temp_application_path);
1191                 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1192                 goto FINISH_OFF;
1193         }
1194
1195         return APP2EXT_SUCCESS;
1196
1197 FINISH_OFF:
1198         if (old_device_node)
1199                 free(old_device_node);
1200
1201         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1202         if (ret)
1203                 _E("close dmcrypt device error(%d)", ret);
1204
1205         ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1206         if (ret)
1207                 _E("close dmcrypt device error(%d)", ret);
1208
1209         _app2sd_delete_loopback_device(temp_loopback_device);
1210
1211         ret = _app2sd_delete_directory(temp_application_path);
1212         if (ret)
1213                 _E("unable to delete (%s)", temp_application_path);
1214
1215         return err_res;
1216 }
1217
1218 int _app2sd_force_clean(const char *pkgid, const char *application_path,
1219                 const char *loopback_device, uid_t uid)
1220 {
1221         int ret;
1222
1223         /* unmount the loopback encrypted pseudo device from
1224          * the application installation path
1225          */
1226         ret = _app2sd_unmount_app_content(application_path);
1227         if (ret)
1228                 _W("unable to unmount the app content (%d)", ret);
1229
1230         /* detach the loopback encryption setup for the application */
1231         ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1232         if (ret)
1233                 _W("close dmcrypt device error (%d)", ret);
1234
1235         /* delete the loopback device from the SD card */
1236         ret = _app2sd_delete_loopback_device(loopback_device);
1237         if (ret)
1238                 _W("unable to detach the loopback encryption setup for "
1239                                 "the application");
1240
1241         /* delete symlink */
1242         _app2sd_delete_symlink(application_path);
1243
1244         /* remove passwrd from DB */
1245         ret = _app2sd_initialize_db();
1246         if (ret)
1247                 _W("app2sd db initialize failed");
1248
1249         ret = _app2sd_remove_info_from_db(pkgid, uid);
1250         if (ret)
1251                 _W("cannot remove info from db");
1252
1253         return ret;
1254 }