diff options
Diffstat (limited to 'vold/volmgr_ext3.c')
-rw-r--r-- | vold/volmgr_ext3.c | 162 |
1 files changed, 149 insertions, 13 deletions
diff --git a/vold/volmgr_ext3.c b/vold/volmgr_ext3.c index 2be07fb..680be21 100644 --- a/vold/volmgr_ext3.c +++ b/vold/volmgr_ext3.c @@ -15,34 +15,170 @@ * limitations under the License. */ +#include <fcntl.h> #include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mount.h> + +#include <linux/ext2_fs.h> +#include <linux/ext3_fs.h> + #include "vold.h" #include "volmgr.h" #include "volmgr_ext3.h" +#include "logwrapper.h" + + +#define EXT_DEBUG 0 -#define EXT3_DEBUG 0 +static char E2FSCK_PATH[] = "/system/bin/e2fsck"; -int ext3_identify(blkdev_t *dev) +int ext_identify(blkdev_t *dev) { -#if EXT3_DEBUG - LOG_VOL("ext3_identify(%s):\n", dev->dev_fspath); + int rc = -1; + int fd; + struct ext3_super_block sb; + char *devpath; + +#if EXT_DEBUG + LOG_VOL("ext_identify(%d:%d):", dev-major, dev->minor); +#endif + + devpath = blkdev_get_devpath(dev); + + if ((fd = open(devpath, O_RDWR)) < 0) { + LOGE("Unable to open device '%s' (%s)", devpath, + strerror(errno)); + free(devpath); + return -errno; + } + + if (lseek(fd, 1024, SEEK_SET) < 0) { + LOGE("Unable to lseek to get superblock (%s)", strerror(errno)); + rc = -errno; + goto out; + } + + if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) { + LOGE("Unable to read superblock (%s)", strerror(errno)); + rc = -errno; + goto out; + } + + if (sb.s_magic == EXT2_SUPER_MAGIC || + sb.s_magic == EXT3_SUPER_MAGIC) + rc = 0; + else + rc = -ENODATA; + + out: +#if EXT_DEBUG + LOG_VOL("ext_identify(%s): rc = %d", devpath, rc); #endif - return -ENOSYS; + free(devpath); + close(fd); + return rc; } -int ext3_check(blkdev_t *dev) +int ext_check(blkdev_t *dev) { -#if EXT3_DEBUG - LOG_VOL("ext3_check(%s):\n", dev->dev_fspath); + char *devpath; + +#if EXT_DEBUG + LOG_VOL("ext_check(%s):", dev->dev_fspath); #endif - return -ENOSYS; + + devpath = blkdev_get_devpath(dev); + + if (access(E2FSCK_PATH, X_OK)) { + LOGE("ext_check(%s): %s not found (skipping checks)", + devpath, E2FSCK_PATH); + free(devpath); + return 0; + } + + char *args[5]; + + args[0] = E2FSCK_PATH; + args[1] = "-v"; + args[2] = "-p"; + args[3] = devpath; + args[4] = NULL; + + int rc = logwrap(4, args); + + if (rc == 0) { + LOG_VOL("filesystem '%s' had no errors", devpath); + } else if (rc == 1) { + LOG_VOL("filesystem '%s' had corrected errors", devpath); + rc = 0; + } else if (rc == 2) { + LOGE("VOL volume '%s' had corrected errors (system should be rebooted)", devpath); + rc = -EIO; + } else if (rc == 4) { + LOGE("VOL volume '%s' had uncorrectable errors", devpath); + rc = -EIO; + } else if (rc == 8) { + LOGE("Operational error while checking volume '%s'", devpath); + rc = -EIO; + } else { + LOGE("Unknown e2fsck exit code (%d)", rc); + rc = -EIO; + } + free(devpath); + return rc; } -int ext3_mount(blkdev_t *dev, volume_t *vol) +int ext_mount(blkdev_t *dev, volume_t *vol, boolean safe_mode) { -#if EXT3_DEBUG - LOG_VOL("ext3_mount(%s, %s):\n", dev->dev_fspath, vol->mount_point); +#if EXT_DEBUG + LOG_VOL("ext_mount(%s, %s, %d):", dev->dev_fspath, vol->mount_point, safe_mode); #endif - return -ENOSYS; + + char *fs[] = { "ext3", "ext2", NULL }; + char *devpath; + + devpath = blkdev_get_devpath(dev); + + int flags, rc = 0; + + flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_NOATIME | MS_NODIRATIME; + + if (safe_mode) + flags |= MS_SYNCHRONOUS; + + if (vol->state == volstate_mounted) { + LOG_VOL("Remounting %s on %s, safe mode %d", devpath, + vol->mount_point, safe_mode); + flags |= MS_REMOUNT; + } + + char **f; + for (f = fs; *f != NULL; f++) { + rc = mount(devpath, vol->mount_point, *f, flags, NULL); + if (rc && errno == EROFS) { + LOGE("ext_mount(%s, %s): Read only filesystem - retrying mount RO", + devpath, vol->mount_point); + flags |= MS_RDONLY; + rc = mount(devpath, vol->mount_point, *f, flags, NULL); + } +#if EXT_DEBUG + LOG_VOL("ext_mount(%s, %s): %s mount rc = %d", devpath, *f, + vol->mount_point, rc); +#endif + if (!rc) + break; + } + free(devpath); + + // Chmod the mount point so that its a free-for-all. + // (required for consistency with VFAT.. sigh) + if (chmod(vol->mount_point, 0777) < 0) { + LOGE("Failed to chmod %s (%s)", vol->mount_point, strerror(errno)); + return -errno; + } + + return rc; } |