blob: 63a8eaf3bbe3833e388f968e631dcc9c423ec971 [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>
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080024
Dees_Troy51a0e822012-09-05 15:24:24 -040025extern "C" {
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"
Dees_Troy51a0e822012-09-05 15:24:24 -040029}
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080030#include "roots.h"
31#include "common.h"
Doug Zongkerd4208f92010-09-20 12:16:13 -070032#include "make_ext4fs.h"
Dees_Troyc51f1f92012-09-20 15:32:13 -040033#include "partitions.hpp"
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080034
Ken Sumrallf35d1ce2013-02-13 12:59:35 -080035static struct fstab *fstab = NULL;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080036
Kenny Root41dda822012-03-30 20:48:34 -070037extern struct selabel_handle *sehandle;
Stephen Smalley779701d2012-02-09 14:13:23 -050038
Ken Sumrallf35d1ce2013-02-13 12:59:35 -080039void load_volume_table()
40{
41 int i;
42 int ret;
Doug Zongker2810ced2011-02-17 15:55:21 -080043
Ken Sumrallf35d1ce2013-02-13 12:59:35 -080044 fstab = fs_mgr_read_fstab("/etc/recovery.fstab");
45 if (!fstab) {
46 LOGE("failed to read /etc/recovery.fstab\n");
Doug Zongkerd4208f92010-09-20 12:16:13 -070047 return;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080048 }
Doug Zongkerd4208f92010-09-20 12:16:13 -070049
Ken Sumrallf35d1ce2013-02-13 12:59:35 -080050 ret = fs_mgr_add_entry(fstab, "/tmp", "ramdisk", "ramdisk", 0);
51 if (ret < 0 ) {
52 LOGE("failed to add /tmp entry to fstab\n");
53 fs_mgr_free_fstab(fstab);
54 fstab = NULL;
55 return;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080056 }
Doug Zongkerd4208f92010-09-20 12:16:13 -070057
Doug Zongkerd4208f92010-09-20 12:16:13 -070058 printf("recovery filesystem table\n");
59 printf("=========================\n");
Ken Sumrallf35d1ce2013-02-13 12:59:35 -080060 for (i = 0; i < fstab->num_entries; ++i) {
61 Volume* v = &fstab->recs[i];
62 printf(" %d %s %s %s %lld\n", i, v->mount_point, v->fs_type,
63 v->blk_device, v->length);
Doug Zongkerd4208f92010-09-20 12:16:13 -070064 }
65 printf("\n");
66}
67
68Volume* volume_for_path(const char* path) {
Ken Sumrallf35d1ce2013-02-13 12:59:35 -080069 return fs_mgr_get_entry_for_mount_point(fstab, path);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080070}
71
Doug Zongkerd4208f92010-09-20 12:16:13 -070072int ensure_path_mounted(const char* path) {
Dees_Troyc51f1f92012-09-20 15:32:13 -040073 if (PartitionManager.Mount_By_Path(path, true))
74 return 0;
75 else
76 return -1;
Doug Zongkerd4208f92010-09-20 12:16:13 -070077 Volume* v = volume_for_path(path);
78 if (v == NULL) {
79 LOGE("unknown volume for path [%s]\n", path);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080080 return -1;
81 }
Doug Zongkerc18eeb82010-09-21 16:49:26 -070082 if (strcmp(v->fs_type, "ramdisk") == 0) {
83 // the ramdisk is always mounted.
84 return 0;
85 }
Doug Zongkerd4208f92010-09-20 12:16:13 -070086
87 int result;
88 result = scan_mounted_volumes();
89 if (result < 0) {
90 LOGE("failed to scan mounted volumes\n");
91 return -1;
Doug Zongker23ceeea2010-07-08 17:27:55 -070092 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080093
Doug Zongkerd4208f92010-09-20 12:16:13 -070094 const MountedVolume* mv =
95 find_mounted_volume_by_mount_point(v->mount_point);
96 if (mv) {
97 // volume is already mounted
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080098 return 0;
99 }
Doug Zongkerd4208f92010-09-20 12:16:13 -0700100
101 mkdir(v->mount_point, 0755); // in case it doesn't already exist
102
103 if (strcmp(v->fs_type, "yaffs2") == 0) {
104 // mount an MTD partition as a YAFFS2 filesystem.
105 mtd_scan_partitions();
106 const MtdPartition* partition;
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800107 partition = mtd_find_partition_by_name(v->blk_device);
Doug Zongkerd4208f92010-09-20 12:16:13 -0700108 if (partition == NULL) {
109 LOGE("failed to find \"%s\" partition to mount at \"%s\"\n",
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800110 v->blk_device, v->mount_point);
Doug Zongkerd4208f92010-09-20 12:16:13 -0700111 return -1;
112 }
113 return mtd_mount_partition(partition, v->mount_point, v->fs_type, 0);
114 } else if (strcmp(v->fs_type, "ext4") == 0 ||
115 strcmp(v->fs_type, "vfat") == 0) {
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800116 result = mount(v->blk_device, v->mount_point, v->fs_type,
Doug Zongker469243e2011-04-12 09:28:10 -0700117 MS_NOATIME | MS_NODEV | MS_NODIRATIME, "");
Doug Zongkerd4208f92010-09-20 12:16:13 -0700118 if (result == 0) return 0;
119
Doug Zongkerd4208f92010-09-20 12:16:13 -0700120 LOGE("failed to mount %s (%s)\n", v->mount_point, strerror(errno));
121 return -1;
122 }
123
124 LOGE("unknown fs_type \"%s\" for %s\n", v->fs_type, v->mount_point);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800125 return -1;
126}
127
Doug Zongkerd4208f92010-09-20 12:16:13 -0700128int ensure_path_unmounted(const char* path) {
Dees_Troyc51f1f92012-09-20 15:32:13 -0400129 if (PartitionManager.UnMount_By_Path(path, true))
130 return 0;
131 else
132 return -1;
Doug Zongkerd4208f92010-09-20 12:16:13 -0700133 Volume* v = volume_for_path(path);
134 if (v == NULL) {
135 LOGE("unknown volume for path [%s]\n", path);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800136 return -1;
137 }
Doug Zongkerc18eeb82010-09-21 16:49:26 -0700138 if (strcmp(v->fs_type, "ramdisk") == 0) {
139 // the ramdisk is always mounted; you can't unmount it.
140 return -1;
141 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800142
Doug Zongkerd4208f92010-09-20 12:16:13 -0700143 int result;
144 result = scan_mounted_volumes();
145 if (result < 0) {
146 LOGE("failed to scan mounted volumes\n");
147 return -1;
148 }
149
150 const MountedVolume* mv =
151 find_mounted_volume_by_mount_point(v->mount_point);
152 if (mv == NULL) {
153 // volume is already unmounted
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800154 return 0;
155 }
156
Doug Zongkerd4208f92010-09-20 12:16:13 -0700157 return unmount_mounted_volume(mv);
158}
159
160int format_volume(const char* volume) {
Dees_Troyc51f1f92012-09-20 15:32:13 -0400161 if (PartitionManager.Wipe_By_Path(volume))
162 return 0;
163 else
164 return -1;
Doug Zongkerd4208f92010-09-20 12:16:13 -0700165 Volume* v = volume_for_path(volume);
166 if (v == NULL) {
167 LOGE("unknown volume \"%s\"\n", volume);
168 return -1;
169 }
Doug Zongkerc18eeb82010-09-21 16:49:26 -0700170 if (strcmp(v->fs_type, "ramdisk") == 0) {
171 // you can't format the ramdisk.
172 LOGE("can't format_volume \"%s\"", volume);
173 return -1;
174 }
Doug Zongkerd4208f92010-09-20 12:16:13 -0700175 if (strcmp(v->mount_point, volume) != 0) {
176 LOGE("can't give path \"%s\" to format_volume\n", volume);
177 return -1;
178 }
179
180 if (ensure_path_unmounted(volume) != 0) {
181 LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point);
182 return -1;
183 }
184
185 if (strcmp(v->fs_type, "yaffs2") == 0 || strcmp(v->fs_type, "mtd") == 0) {
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800186 mtd_scan_partitions();
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800187 const MtdPartition* partition = mtd_find_partition_by_name(v->blk_device);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800188 if (partition == NULL) {
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800189 LOGE("format_volume: no MTD partition \"%s\"\n", v->blk_device);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800190 return -1;
191 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800192
Doug Zongkerd4208f92010-09-20 12:16:13 -0700193 MtdWriteContext *write = mtd_write_partition(partition);
194 if (write == NULL) {
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800195 LOGW("format_volume: can't open MTD \"%s\"\n", v->blk_device);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800196 return -1;
Doug Zongkerd4208f92010-09-20 12:16:13 -0700197 } else if (mtd_erase_blocks(write, -1) == (off_t) -1) {
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800198 LOGW("format_volume: can't erase MTD \"%s\"\n", v->blk_device);
Doug Zongkerd4208f92010-09-20 12:16:13 -0700199 mtd_write_close(write);
200 return -1;
201 } else if (mtd_write_close(write)) {
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800202 LOGW("format_volume: can't close MTD \"%s\"\n", v->blk_device);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800203 return -1;
204 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800205 return 0;
206 }
207
Doug Zongkerd4208f92010-09-20 12:16:13 -0700208 if (strcmp(v->fs_type, "ext4") == 0) {
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800209 int result = make_ext4fs(v->blk_device, v->length, volume, sehandle);
Doug Zongkerd4208f92010-09-20 12:16:13 -0700210 if (result != 0) {
Ken Sumrallf35d1ce2013-02-13 12:59:35 -0800211 LOGE("format_volume: make_extf4fs failed on %s\n", v->blk_device);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800212 return -1;
213 }
Doug Zongkerd4208f92010-09-20 12:16:13 -0700214 return 0;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800215 }
Doug Zongkerd4208f92010-09-20 12:16:13 -0700216
217 LOGE("format_volume: fs_type \"%s\" unsupported\n", v->fs_type);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800218 return -1;
219}
Doug Zongker239ac6a2013-08-20 16:03:25 -0700220
221int setup_install_mounts() {
222 if (fstab == NULL) {
223 LOGE("can't set up install mounts: no fstab loaded\n");
224 return -1;
225 }
226 for (int i = 0; i < fstab->num_entries; ++i) {
227 Volume* v = fstab->recs + i;
228
229 if (strcmp(v->mount_point, "/tmp") == 0 ||
230 strcmp(v->mount_point, "/cache") == 0) {
231 if (ensure_path_mounted(v->mount_point) != 0) return -1;
232
233 } else {
234 if (ensure_path_unmounted(v->mount_point) != 0) return -1;
235 }
236 }
237 return 0;
238}