1 /* 2 * Copyright (C) 2012 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 <stdio.h> 18 #include <stdlib.h> 19 #include <fcntl.h> 20 #include <unistd.h> 21 #include <errno.h> 22 #include <string.h> 23 #include <dirent.h> 24 #include <errno.h> 25 #include <fcntl.h> 26 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <sys/types.h> 30 #include <sys/mman.h> 31 #include <sys/mount.h> 32 #include <sys/wait.h> 33 34 #include <linux/kdev_t.h> 35 36 #define LOG_TAG "Vold" 37 38 #include <cutils/log.h> 39 #include <cutils/properties.h> 40 41 #include <logwrap/logwrap.h> 42 43 #include "Ext4.h" 44 #include "VoldUtil.h" 45 46 #define MKEXT4FS_PATH "/system/bin/make_ext4fs" 47 #define RESIZE2FS_PATH "/system/bin/resize2fs" 48 49 int Ext4::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount, 50 bool executable) { 51 int rc; 52 unsigned long flags; 53 54 flags = MS_NOATIME | MS_NODEV | MS_NOSUID | MS_DIRSYNC; 55 56 flags |= (executable ? 0 : MS_NOEXEC); 57 flags |= (ro ? MS_RDONLY : 0); 58 flags |= (remount ? MS_REMOUNT : 0); 59 60 rc = mount(fsPath, mountPoint, "ext4", flags, NULL); 61 62 if (rc && errno == EROFS) { 63 SLOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath); 64 flags |= MS_RDONLY; 65 rc = mount(fsPath, mountPoint, "ext4", flags, NULL); 66 } 67 68 return rc; 69 } 70 71 int Ext4::resize(const char *fspath, unsigned int numSectors) { 72 const char *args[4]; 73 char* size_str; 74 int rc; 75 int status; 76 77 args[0] = RESIZE2FS_PATH; 78 args[1] = "-f"; 79 args[2] = fspath; 80 if (asprintf(&size_str, "%ds", numSectors) < 0) 81 { 82 SLOGE("Filesystem (ext4) resize failed to set size"); 83 return -1; 84 } 85 args[3] = size_str; 86 rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, 87 true); 88 free(size_str); 89 if (rc != 0) { 90 SLOGE("Filesystem (ext4) resize failed due to logwrap error"); 91 errno = EIO; 92 return -1; 93 } 94 95 if (!WIFEXITED(status)) { 96 SLOGE("Filesystem (ext4) resize did not exit properly"); 97 errno = EIO; 98 return -1; 99 } 100 101 status = WEXITSTATUS(status); 102 103 if (status == 0) { 104 SLOGI("Filesystem (ext4) resized OK"); 105 return 0; 106 } else { 107 SLOGE("Resize (ext4) failed (unknown exit code %d)", status); 108 errno = EIO; 109 return -1; 110 } 111 return 0; 112 } 113 114 int Ext4::format(const char *fsPath, unsigned int numSectors, const char *mountpoint) { 115 int fd; 116 const char *args[7]; 117 int rc; 118 int status; 119 120 args[0] = MKEXT4FS_PATH; 121 args[1] = "-J"; 122 args[2] = "-a"; 123 args[3] = mountpoint; 124 if (numSectors) { 125 char tmp[32]; 126 snprintf(tmp, sizeof(tmp), "%u", numSectors * 512); 127 const char *size = tmp; 128 args[4] = "-l"; 129 args[5] = size; 130 args[6] = fsPath; 131 rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, true); 132 } else { 133 args[4] = fsPath; 134 rc = android_fork_execvp(5, (char **)args, &status, false, true); 135 } 136 rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, 137 true); 138 if (rc != 0) { 139 SLOGE("Filesystem (ext4) format failed due to logwrap error"); 140 errno = EIO; 141 return -1; 142 } 143 144 if (!WIFEXITED(status)) { 145 SLOGE("Filesystem (ext4) format did not exit properly"); 146 errno = EIO; 147 return -1; 148 } 149 150 status = WEXITSTATUS(status); 151 152 if (status == 0) { 153 SLOGI("Filesystem (ext4) formatted OK"); 154 return 0; 155 } else { 156 SLOGE("Format (ext4) failed (unknown exit code %d)", status); 157 errno = EIO; 158 return -1; 159 } 160 return 0; 161 } 162