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 #include "ext4_utils.h"
27 #include "ext4.h"
28 #include "make_ext4fs.h"
29 #include "fs_mgr_priv.h"
30 
31 extern struct fs_info info;     /* magic global from ext4_utils */
32 extern void reset_ext4fs_info();
33 
format_ext4(char * fs_blkdev,char * fs_mnt_point)34 static int format_ext4(char *fs_blkdev, char *fs_mnt_point)
35 {
36     unsigned int nr_sec;
37     int fd, rc = 0;
38 
39     if ((fd = open(fs_blkdev, O_WRONLY, 0644)) < 0) {
40         ERROR("Cannot open block device.  %s\n", strerror(errno));
41         return -1;
42     }
43 
44     if ((ioctl(fd, BLKGETSIZE, &nr_sec)) == -1) {
45         ERROR("Cannot get block device size.  %s\n", strerror(errno));
46         close(fd);
47         return -1;
48     }
49 
50     /* Format the partition using the calculated length */
51     reset_ext4fs_info();
52     info.len = ((off64_t)nr_sec * 512);
53 
54     /* Use make_ext4fs_internal to avoid wiping an already-wiped partition. */
55     rc = make_ext4fs_internal(fd, NULL, NULL, fs_mnt_point, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
56     if (rc) {
57         ERROR("make_ext4fs returned %d.\n", rc);
58     }
59     close(fd);
60 
61     return rc;
62 }
63 
format_f2fs(char * fs_blkdev)64 static int format_f2fs(char *fs_blkdev)
65 {
66     char * args[3];
67     int pid;
68     int rc = 0;
69 
70     args[0] = (char *)"/sbin/mkfs.f2fs";
71     args[1] = fs_blkdev;
72     args[2] = (char *)0;
73 
74     pid = fork();
75     if (pid < 0) {
76        return pid;
77     }
78     if (!pid) {
79         /* This doesn't return */
80         execv("/sbin/mkfs.f2fs", args);
81         exit(1);
82     }
83     for(;;) {
84         pid_t p = waitpid(pid, &rc, 0);
85         if (p != pid) {
86             ERROR("Error waiting for child process - %d\n", p);
87             rc = -1;
88             break;
89         }
90         if (WIFEXITED(rc)) {
91             rc = WEXITSTATUS(rc);
92             INFO("%s done, status %d\n", args[0], rc);
93             if (rc) {
94                 rc = -1;
95             }
96             break;
97         }
98         ERROR("Still waiting for %s...\n", args[0]);
99     }
100 
101     return rc;
102 }
103 
fs_mgr_do_format(struct fstab_rec * fstab)104 int fs_mgr_do_format(struct fstab_rec *fstab)
105 {
106     int rc = -EINVAL;
107 
108     ERROR("%s: Format %s as '%s'.\n", __func__, fstab->blk_device, fstab->fs_type);
109 
110     if (!strncmp(fstab->fs_type, "f2fs", 4)) {
111         rc = format_f2fs(fstab->blk_device);
112     } else if (!strncmp(fstab->fs_type, "ext4", 4)) {
113         rc = format_ext4(fstab->blk_device, fstab->mount_point);
114     } else {
115         ERROR("File system type '%s' is not supported\n", fstab->fs_type);
116     }
117 
118     return rc;
119 }
120