blob: 66481a3b915010284ae9203bd99df08e167ce861 [file] [log] [blame]
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <errno.h>
18#include <stdlib.h>
19#include <sys/mount.h>
20#include <sys/stat.h>
21#include <sys/types.h>
22#include <unistd.h>
Doug Zongkerd4208f92010-09-20 12:16:13 -070023#include <ctype.h>
Doug Zongkerf39989a2013-12-11 15:40:28 -080024#include <fcntl.h>
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080025
Ken Sumrallf35d1ce2013-02-13 12:59:35 -080026#include <fs_mgr.h>
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080027#include "mtdutils/mtdutils.h"
28#include "mtdutils/mounts.h"
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080029#include "roots.h"
30#include "common.h"
Doug Zongkerd4208f92010-09-20 12:16:13 -070031#include "make_ext4fs.h"
Doug Zongkerf39989a2013-12-11 15:40:28 -080032extern "C" {
33#include "wipe.h"
34#include "cryptfs.h"
35}
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080036
Ken Sumrallf35d1ce2013-02-13 12:59:35 -080037static struct fstab *fstab = NULL;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080038
Kenny Root41dda822012-03-30 20:48:34 -070039extern struct selabel_handle *sehandle;
Stephen Smalley779701d2012-02-09 14:13:23 -050040
Ken Sumrallf35d1ce2013-02-13 12:59:35 -080041void load_volume_table()
42{
43 int i;
44 int ret;
Doug Zongker2810ced2011-02-17 15:55:21 -080045
Ken Sumrallf35d1ce2013-02-13 12:59:35 -080046 fstab = fs_mgr_read_fstab("/etc/recovery.fstab");
47 if (!fstab) {
48 LOGE("failed to read /etc/recovery.fstab\n");
Doug Zongkerd4208f92010-09-20 12:16:13 -070049 return;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080050 }
Doug Zongkerd4208f92010-09-20 12:16:13 -070051
Sasha Levitskiy85ef47d2014-04-10 17:11:34 -070052 ret = fs_mgr_add_entry(fstab, "/tmp", "ramdisk", "ramdisk");
Ken Sumrallf35d1ce2013-02-13 12:59:35 -080053 if (ret < 0 ) {
54 LOGE("failed to add /tmp entry to fstab\n");
55 fs_mgr_free_fstab(fstab);
56 fstab = NULL;
57 return;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080058 }
Doug Zongkerd4208f92010-09-20 12:16:13 -070059
Doug Zongkerd4208f92010-09-20 12:16:13 -070060 printf("recovery filesystem table\n");
61 printf("=========================\n");
Ken Sumrallf35d1ce2013-02-13 12:59:35 -080062 for (i = 0; i < fstab->num_entries; ++i) {
63 Volume* v = &fstab->recs[i];
64 printf(" %d %s %s %s %lld\n", i, v->mount_point, v->fs_type,
65 v->blk_device, v->length);
Doug Zongkerd4208f92010-09-20 12:16:13 -070066 }
67 printf("\n");
68}
69
70Volume* volume_for_path(const char* path) {
Ken Sumrallf35d1ce2013-02-13 12:59:35 -080071 return fs_mgr_get_entry_for_mount_point(fstab, path);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080072}
73
Doug Zongkerd4208f92010-09-20 12:16:13 -070074int ensure_path_mounted(const char* path) {
75 Volume* v = volume_for_path(path);
76 if (v == NULL) {
77 LOGE("unknown volume for path [%s]\n", path);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080078 return -1;
79 }
Doug Zongkerc18eeb82010-09-21 16:49:26 -070080 if (strcmp(v->fs_type, "ramdisk") == 0) {
81 // the ramdisk is always mounted.
82 return 0;
83 }
Doug Zongkerd4208f92010-09-20 12:16:13 -070084
85 int result;
86 result = scan_mounted_volumes();
87 if (result < 0) {
88 LOGE("failed to scan mounted volumes\n");
89 return -1;
Doug Zongker23ceeea2010-07-08 17:27:55 -070090 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080091
Doug Zongkerd4208f92010-09-20 12:16:13 -070092 const MountedVolume* mv =
93 find_mounted_volume_by_mount_point(v->mount_point);
94 if (mv) {
95 // volume is already mounted
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080096 return 0;
97 }
Doug Zongkerd4208f92010-09-20 12:16:13 -070098
99 mkdir(v->mount_point, 0755); // in case it doesn't already exist
100
101 if (strcmp(v->fs_type, "yaffs2") == 0) {
102 // mount an MTD partition as a YAFFS2 filesystem.
103 mtd_scan_partitions();
104 const MtdPartition* partition;
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800105 partition = mtd_find_partition_by_name(v->blk_device);
Doug Zongkerd4208f92010-09-20 12:16:13 -0700106 if (partition == NULL) {
107 LOGE("failed to find \"%s\" partition to mount at \"%s\"\n",
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800108 v->blk_device, v->mount_point);
Doug Zongkerd4208f92010-09-20 12:16:13 -0700109 return -1;
110 }
111 return mtd_mount_partition(partition, v->mount_point, v->fs_type, 0);
112 } else if (strcmp(v->fs_type, "ext4") == 0 ||
113 strcmp(v->fs_type, "vfat") == 0) {
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800114 result = mount(v->blk_device, v->mount_point, v->fs_type,
Doug Zongker469243e2011-04-12 09:28:10 -0700115 MS_NOATIME | MS_NODEV | MS_NODIRATIME, "");
Doug Zongkerd4208f92010-09-20 12:16:13 -0700116 if (result == 0) return 0;
117
Doug Zongkerd4208f92010-09-20 12:16:13 -0700118 LOGE("failed to mount %s (%s)\n", v->mount_point, strerror(errno));
119 return -1;
120 }
121
122 LOGE("unknown fs_type \"%s\" for %s\n", v->fs_type, v->mount_point);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800123 return -1;
124}
125
Doug Zongkerd4208f92010-09-20 12:16:13 -0700126int ensure_path_unmounted(const char* path) {
127 Volume* v = volume_for_path(path);
128 if (v == NULL) {
129 LOGE("unknown volume for path [%s]\n", path);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800130 return -1;
131 }
Doug Zongkerc18eeb82010-09-21 16:49:26 -0700132 if (strcmp(v->fs_type, "ramdisk") == 0) {
133 // the ramdisk is always mounted; you can't unmount it.
134 return -1;
135 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800136
Doug Zongkerd4208f92010-09-20 12:16:13 -0700137 int result;
138 result = scan_mounted_volumes();
139 if (result < 0) {
140 LOGE("failed to scan mounted volumes\n");
141 return -1;
142 }
143
144 const MountedVolume* mv =
145 find_mounted_volume_by_mount_point(v->mount_point);
146 if (mv == NULL) {
147 // volume is already unmounted
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800148 return 0;
149 }
150
Doug Zongkerd4208f92010-09-20 12:16:13 -0700151 return unmount_mounted_volume(mv);
152}
153
154int format_volume(const char* volume) {
155 Volume* v = volume_for_path(volume);
156 if (v == NULL) {
157 LOGE("unknown volume \"%s\"\n", volume);
158 return -1;
159 }
Doug Zongkerc18eeb82010-09-21 16:49:26 -0700160 if (strcmp(v->fs_type, "ramdisk") == 0) {
161 // you can't format the ramdisk.
162 LOGE("can't format_volume \"%s\"", volume);
163 return -1;
164 }
Doug Zongkerd4208f92010-09-20 12:16:13 -0700165 if (strcmp(v->mount_point, volume) != 0) {
166 LOGE("can't give path \"%s\" to format_volume\n", volume);
167 return -1;
168 }
169
170 if (ensure_path_unmounted(volume) != 0) {
171 LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point);
172 return -1;
173 }
174
175 if (strcmp(v->fs_type, "yaffs2") == 0 || strcmp(v->fs_type, "mtd") == 0) {
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800176 mtd_scan_partitions();
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800177 const MtdPartition* partition = mtd_find_partition_by_name(v->blk_device);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800178 if (partition == NULL) {
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800179 LOGE("format_volume: no MTD partition \"%s\"\n", v->blk_device);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800180 return -1;
181 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800182
Doug Zongkerd4208f92010-09-20 12:16:13 -0700183 MtdWriteContext *write = mtd_write_partition(partition);
184 if (write == NULL) {
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800185 LOGW("format_volume: can't open MTD \"%s\"\n", v->blk_device);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800186 return -1;
Doug Zongkerd4208f92010-09-20 12:16:13 -0700187 } else if (mtd_erase_blocks(write, -1) == (off_t) -1) {
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800188 LOGW("format_volume: can't erase MTD \"%s\"\n", v->blk_device);
Doug Zongkerd4208f92010-09-20 12:16:13 -0700189 mtd_write_close(write);
190 return -1;
191 } else if (mtd_write_close(write)) {
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800192 LOGW("format_volume: can't close MTD \"%s\"\n", v->blk_device);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800193 return -1;
194 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800195 return 0;
196 }
197
Doug Zongkerd4208f92010-09-20 12:16:13 -0700198 if (strcmp(v->fs_type, "ext4") == 0) {
Doug Zongkerf39989a2013-12-11 15:40:28 -0800199 ssize_t length = 0;
200 if (v->length != 0) {
201 length = v->length;
202 } else if (v->key_loc != NULL && strcmp(v->key_loc, "footer") == 0) {
203 length = -CRYPT_FOOTER_OFFSET;
204 }
205 int result = make_ext4fs(v->blk_device, length, volume, sehandle);
Doug Zongkerd4208f92010-09-20 12:16:13 -0700206 if (result != 0) {
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800207 LOGE("format_volume: make_extf4fs failed on %s\n", v->blk_device);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800208 return -1;
209 }
Doug Zongkerf39989a2013-12-11 15:40:28 -0800210
211 // if there's a key_loc that looks like a path, it should be a
212 // block device for storing encryption metadata. wipe it too.
213 if (v->key_loc != NULL && v->key_loc[0] == '/') {
214 LOGI("wiping %s\n", v->key_loc);
215 int fd = open(v->key_loc, O_WRONLY | O_CREAT, 0644);
216 if (fd < 0) {
217 LOGE("format_volume: failed to open %s\n", v->key_loc);
218 return -1;
219 }
220 wipe_block_device(fd, get_file_size(fd));
221 close(fd);
222 }
223
Doug Zongkerd4208f92010-09-20 12:16:13 -0700224 return 0;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800225 }
Doug Zongkerd4208f92010-09-20 12:16:13 -0700226
227 LOGE("format_volume: fs_type \"%s\" unsupported\n", v->fs_type);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800228 return -1;
229}
Doug Zongker239ac6a2013-08-20 16:03:25 -0700230
231int setup_install_mounts() {
232 if (fstab == NULL) {
233 LOGE("can't set up install mounts: no fstab loaded\n");
234 return -1;
235 }
236 for (int i = 0; i < fstab->num_entries; ++i) {
237 Volume* v = fstab->recs + i;
238
239 if (strcmp(v->mount_point, "/tmp") == 0 ||
240 strcmp(v->mount_point, "/cache") == 0) {
Doug Zongker99916f02014-01-13 14:16:58 -0800241 if (ensure_path_mounted(v->mount_point) != 0) {
242 LOGE("failed to mount %s\n", v->mount_point);
243 return -1;
244 }
Doug Zongker239ac6a2013-08-20 16:03:25 -0700245
246 } else {
Doug Zongker99916f02014-01-13 14:16:58 -0800247 if (ensure_path_unmounted(v->mount_point) != 0) {
248 LOGE("failed to unmount %s\n", v->mount_point);
249 return -1;
250 }
Doug Zongker239ac6a2013-08-20 16:03:25 -0700251 }
252 }
253 return 0;
254}