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_utils.h>
28 #include <ext4_utils/ext4.h>
29 #include <ext4_utils/make_ext4fs.h>
30 #include <selinux/selinux.h>
31 #include <selinux/label.h>
32 #include <selinux/android.h>
33 
34 #include "fs_mgr_priv.h"
35 #include "cryptfs.h"
36 
37 extern "C" {
38 extern struct fs_info info;     /* magic global from ext4_utils */
39 extern void reset_ext4fs_info();
40 }
41 
format_ext4(char * fs_blkdev,char * fs_mnt_point,bool crypt_footer)42 static int format_ext4(char *fs_blkdev, char *fs_mnt_point, bool crypt_footer)
43 {
44     uint64_t dev_sz;
45     int fd, rc = 0;
46 
47     if ((fd = open(fs_blkdev, O_WRONLY)) < 0) {
48         PERROR << "Cannot open block device";
49         return -1;
50     }
51 
52     if ((ioctl(fd, BLKGETSIZE64, &dev_sz)) == -1) {
53         PERROR << "Cannot get block device size";
54         close(fd);
55         return -1;
56     }
57 
58     struct selabel_handle *sehandle = selinux_android_file_context_handle();
59     if (!sehandle) {
60         /* libselinux logs specific error */
61         LERROR << "Cannot initialize android file_contexts";
62         close(fd);
63         return -1;
64     }
65 
66     /* Format the partition using the calculated length */
67     reset_ext4fs_info();
68     info.len = (off64_t)dev_sz;
69     if (crypt_footer) {
70         info.len -= CRYPT_FOOTER_OFFSET;
71     }
72 
73     /* Use make_ext4fs_internal to avoid wiping an already-wiped partition. */
74     rc = make_ext4fs_internal(fd, NULL, NULL, fs_mnt_point, 0, 0, 0, 0, 0, 0, sehandle, 0, 0, NULL, NULL, NULL);
75     if (rc) {
76         LERROR << "make_ext4fs returned " << rc;
77     }
78     close(fd);
79 
80     if (sehandle) {
81         selabel_close(sehandle);
82     }
83 
84     return rc;
85 }
86 
format_f2fs(char * fs_blkdev)87 static int format_f2fs(char *fs_blkdev)
88 {
89     char * args[3];
90     int pid;
91     int rc = 0;
92 
93     args[0] = (char *)"/sbin/mkfs.f2fs";
94     args[1] = fs_blkdev;
95     args[2] = (char *)0;
96 
97     pid = fork();
98     if (pid < 0) {
99        return pid;
100     }
101     if (!pid) {
102         /* This doesn't return */
103         execv("/sbin/mkfs.f2fs", args);
104         exit(1);
105     }
106     for(;;) {
107         pid_t p = waitpid(pid, &rc, 0);
108         if (p != pid) {
109             LERROR << "Error waiting for child process - " << p;
110             rc = -1;
111             break;
112         }
113         if (WIFEXITED(rc)) {
114             rc = WEXITSTATUS(rc);
115             LINFO << args[0] << " done, status " << rc;
116             if (rc) {
117                 rc = -1;
118             }
119             break;
120         }
121         LERROR << "Still waiting for " << args[0] << "...";
122     }
123 
124     return rc;
125 }
126 
fs_mgr_do_format(struct fstab_rec * fstab,bool crypt_footer)127 int fs_mgr_do_format(struct fstab_rec *fstab, bool crypt_footer)
128 {
129     int rc = -EINVAL;
130 
131     LERROR << __FUNCTION__ << ": Format " << fstab->blk_device
132            << " as '" << fstab->fs_type << "'";
133 
134     if (!strncmp(fstab->fs_type, "f2fs", 4)) {
135         rc = format_f2fs(fstab->blk_device);
136     } else if (!strncmp(fstab->fs_type, "ext4", 4)) {
137         rc = format_ext4(fstab->blk_device, fstab->mount_point, crypt_footer);
138     } else {
139         LERROR << "File system type '" << fstab->fs_type << "' is not supported";
140     }
141 
142     return rc;
143 }
144