1 /* 2 * Copyright (C) 2015 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 <unistd.h> 19 #include <sys/types.h> 20 #include <sys/stat.h> 21 #include <fcntl.h> 22 #include <sys/wait.h> 23 #include <errno.h> 24 #include <cutils/partition_utils.h> 25 #include <sys/mount.h> 26 27 #include <ext4_utils/ext4.h> 28 #include <ext4_utils/ext4_utils.h> 29 #include <logwrap/logwrap.h> 30 #include <selinux/android.h> 31 #include <selinux/label.h> 32 #include <selinux/selinux.h> 33 34 #include "fs_mgr_priv.h" 35 #include "cryptfs.h" 36 37 static int get_dev_sz(char *fs_blkdev, uint64_t *dev_sz) 38 { 39 int fd; 40 41 if ((fd = open(fs_blkdev, O_RDONLY)) < 0) { 42 PERROR << "Cannot open block device"; 43 return -1; 44 } 45 46 if ((ioctl(fd, BLKGETSIZE64, dev_sz)) == -1) { 47 PERROR << "Cannot get block device size"; 48 close(fd); 49 return -1; 50 } 51 52 close(fd); 53 return 0; 54 } 55 56 static int format_ext4(char *fs_blkdev, char *fs_mnt_point, bool crypt_footer) 57 { 58 uint64_t dev_sz; 59 int rc = 0; 60 int status; 61 62 rc = get_dev_sz(fs_blkdev, &dev_sz); 63 if (rc) { 64 return rc; 65 } 66 67 /* Format the partition using the calculated length */ 68 if (crypt_footer) { 69 dev_sz -= CRYPT_FOOTER_OFFSET; 70 } 71 72 std::string size_str = std::to_string(dev_sz / 4096); 73 const char* const mke2fs_args[] = { 74 "/system/bin/mke2fs", "-t", "ext4", "-b", "4096", fs_blkdev, size_str.c_str(), nullptr}; 75 76 rc = android_fork_execvp_ext(arraysize(mke2fs_args), const_cast<char**>(mke2fs_args), NULL, 77 true, LOG_KLOG, true, nullptr, nullptr, 0); 78 if (rc) { 79 LERROR << "mke2fs returned " << rc; 80 return rc; 81 } 82 83 const char* const e2fsdroid_args[] = { 84 "/system/bin/e2fsdroid", 85 "-e", 86 "-a", 87 fs_mnt_point, 88 fs_blkdev, 89 nullptr}; 90 91 rc = android_fork_execvp_ext(arraysize(e2fsdroid_args), const_cast<char**>(e2fsdroid_args), 92 NULL, true, LOG_KLOG, true, nullptr, nullptr, 0); 93 if (rc) { 94 LERROR << "e2fsdroid returned " << rc; 95 } 96 97 return rc; 98 } 99 100 static int format_f2fs(char *fs_blkdev, uint64_t dev_sz, bool crypt_footer) 101 { 102 int status; 103 104 if (!dev_sz) { 105 int rc = get_dev_sz(fs_blkdev, &dev_sz); 106 if (rc) { 107 return rc; 108 } 109 } 110 111 /* Format the partition using the calculated length */ 112 if (crypt_footer) { 113 dev_sz -= CRYPT_FOOTER_OFFSET; 114 } 115 116 std::string size_str = std::to_string(dev_sz / 4096); 117 // clang-format off 118 const char* const args[] = { 119 "/system/bin/make_f2fs", 120 "-d1", 121 "-f", 122 "-O", "encrypt", 123 "-O", "quota", 124 "-O", "verity", 125 "-w", "4096", 126 fs_blkdev, 127 size_str.c_str(), 128 nullptr 129 }; 130 // clang-format on 131 132 return android_fork_execvp_ext(arraysize(args), const_cast<char**>(args), NULL, true, 133 LOG_KLOG, true, nullptr, nullptr, 0); 134 } 135 136 int fs_mgr_do_format(struct fstab_rec *fstab, bool crypt_footer) 137 { 138 int rc = -EINVAL; 139 140 LERROR << __FUNCTION__ << ": Format " << fstab->blk_device 141 << " as '" << fstab->fs_type << "'"; 142 143 if (!strncmp(fstab->fs_type, "f2fs", 4)) { 144 rc = format_f2fs(fstab->blk_device, fstab->length, crypt_footer); 145 } else if (!strncmp(fstab->fs_type, "ext4", 4)) { 146 rc = format_ext4(fstab->blk_device, fstab->mount_point, crypt_footer); 147 } else { 148 LERROR << "File system type '" << fstab->fs_type << "' is not supported"; 149 } 150 151 return rc; 152 } 153