blob: fe3b2bb462810f1e026329c96ea686b53e25a627 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001
2/*
3 * Copyright (C) 2008 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include <fcntl.h>
19#include <errno.h>
20
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <sys/mount.h>
24
25#include <linux/ext2_fs.h>
26#include <linux/ext3_fs.h>
27
28#include "vold.h"
29#include "volmgr.h"
30#include "volmgr_ext3.h"
31#include "logwrapper.h"
32
33
34#define EXT_DEBUG 0
35
36static char E2FSCK_PATH[] = "/system/bin/e2fsck";
37
38int ext_identify(blkdev_t *dev)
39{
40 int rc = -1;
41 int fd;
42 struct ext3_super_block sb;
43 char *devpath;
44
45#if EXT_DEBUG
46 LOG_VOL("ext_identify(%d:%d):", dev-major, dev->minor);
47#endif
48
49 devpath = blkdev_get_devpath(dev);
50
51 if ((fd = open(devpath, O_RDWR)) < 0) {
52 LOGE("Unable to open device '%s' (%s)", devpath,
53 strerror(errno));
54 free(devpath);
55 return -errno;
56 }
57
58 if (lseek(fd, 1024, SEEK_SET) < 0) {
59 LOGE("Unable to lseek to get superblock (%s)", strerror(errno));
60 rc = -errno;
61 goto out;
62 }
63
64 if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) {
65 LOGE("Unable to read superblock (%s)", strerror(errno));
66 rc = -errno;
67 goto out;
68 }
69
70 if (sb.s_magic == EXT2_SUPER_MAGIC ||
71 sb.s_magic == EXT3_SUPER_MAGIC)
72 rc = 0;
73 else
74 rc = -ENODATA;
75
76 out:
77#if EXT_DEBUG
78 LOG_VOL("ext_identify(%s): rc = %d", devpath, rc);
79#endif
80 free(devpath);
81 close(fd);
82 return rc;
83}
84
85int ext_check(blkdev_t *dev)
86{
87 char *devpath;
88
89#if EXT_DEBUG
90 LOG_VOL("ext_check(%s):", dev->dev_fspath);
91#endif
92
93 devpath = blkdev_get_devpath(dev);
94
95 if (access(E2FSCK_PATH, X_OK)) {
96 LOGE("ext_check(%s): %s not found (skipping checks)",
97 devpath, E2FSCK_PATH);
98 free(devpath);
99 return 0;
100 }
101
102 char *args[5];
103
104 args[0] = E2FSCK_PATH;
105 args[1] = "-v";
106 args[2] = "-p";
107 args[3] = devpath;
108 args[4] = NULL;
109
San Mehat825c27d2009-06-12 07:39:52 -0700110 int rc = logwrap(4, args, 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800111
112 if (rc == 0) {
113 LOG_VOL("filesystem '%s' had no errors", devpath);
114 } else if (rc == 1) {
115 LOG_VOL("filesystem '%s' had corrected errors", devpath);
116 rc = 0;
117 } else if (rc == 2) {
118 LOGE("VOL volume '%s' had corrected errors (system should be rebooted)", devpath);
119 rc = -EIO;
120 } else if (rc == 4) {
121 LOGE("VOL volume '%s' had uncorrectable errors", devpath);
122 rc = -EIO;
123 } else if (rc == 8) {
124 LOGE("Operational error while checking volume '%s'", devpath);
125 rc = -EIO;
126 } else {
127 LOGE("Unknown e2fsck exit code (%d)", rc);
128 rc = -EIO;
129 }
130 free(devpath);
131 return rc;
132}
133
134int ext_mount(blkdev_t *dev, volume_t *vol, boolean safe_mode)
135{
136#if EXT_DEBUG
137 LOG_VOL("ext_mount(%s, %s, %d):", dev->dev_fspath, vol->mount_point, safe_mode);
138#endif
139
140 char *fs[] = { "ext3", "ext2", NULL };
141 char *devpath;
142
143 devpath = blkdev_get_devpath(dev);
144
145 int flags, rc = 0;
146
147 flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_NOATIME | MS_NODIRATIME;
148
149 if (safe_mode)
150 flags |= MS_SYNCHRONOUS;
151
152 if (vol->state == volstate_mounted) {
153 LOG_VOL("Remounting %s on %s, safe mode %d", devpath,
154 vol->mount_point, safe_mode);
155 flags |= MS_REMOUNT;
156 }
157
158 char **f;
159 for (f = fs; *f != NULL; f++) {
160 rc = mount(devpath, vol->mount_point, *f, flags, NULL);
161 if (rc && errno == EROFS) {
162 LOGE("ext_mount(%s, %s): Read only filesystem - retrying mount RO",
163 devpath, vol->mount_point);
164 flags |= MS_RDONLY;
165 rc = mount(devpath, vol->mount_point, *f, flags, NULL);
166 }
167#if EXT_DEBUG
168 LOG_VOL("ext_mount(%s, %s): %s mount rc = %d", devpath, *f,
169 vol->mount_point, rc);
170#endif
171 if (!rc)
172 break;
173 }
174 free(devpath);
175
176 // Chmod the mount point so that its a free-for-all.
177 // (required for consistency with VFAT.. sigh)
178 if (chmod(vol->mount_point, 0777) < 0) {
179 LOGE("Failed to chmod %s (%s)", vol->mount_point, strerror(errno));
180 return -errno;
181 }
182
183 return rc;
184}