]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
c95f9a23 | 2 | |
3c9fbb99 ZJS |
3 | #include <unistd.h> |
4 | ||
c95f9a23 LP |
5 | #include "id128-util.h" |
6 | #include "mkfs-util.h" | |
7 | #include "path-util.h" | |
8 | #include "process-util.h" | |
0f2b2c48 | 9 | #include "stdio-util.h" |
c95f9a23 LP |
10 | #include "string-util.h" |
11 | ||
12 | int mkfs_exists(const char *fstype) { | |
13 | const char *mkfs; | |
14 | int r; | |
15 | ||
16 | assert(fstype); | |
17 | ||
18 | if (STR_IN_SET(fstype, "auto", "swap")) /* these aren't real file system types, refuse early */ | |
19 | return -EINVAL; | |
20 | ||
21 | mkfs = strjoina("mkfs.", fstype); | |
22 | if (!filename_is_valid(mkfs)) /* refuse file system types with slashes and similar */ | |
23 | return -EINVAL; | |
24 | ||
f7bc0c32 | 25 | r = find_executable(mkfs, NULL); |
c95f9a23 LP |
26 | if (r == -ENOENT) |
27 | return false; | |
28 | if (r < 0) | |
29 | return r; | |
30 | ||
31 | return true; | |
32 | } | |
33 | ||
34 | int make_filesystem( | |
35 | const char *node, | |
36 | const char *fstype, | |
37 | const char *label, | |
38 | sd_id128_t uuid, | |
39 | bool discard) { | |
40 | ||
41 | _cleanup_free_ char *mkfs = NULL; | |
4f05a11c ZJS |
42 | char mangled_label[8 + 3 + 1], |
43 | vol_id[CONST_MAX(ID128_UUID_STRING_MAX, 8 + 1)] = {}; | |
c95f9a23 LP |
44 | int r; |
45 | ||
46 | assert(node); | |
47 | assert(fstype); | |
48 | assert(label); | |
49 | ||
50 | if (streq(fstype, "swap")) { | |
f7bc0c32 | 51 | r = find_executable("mkswap", &mkfs); |
c95f9a23 LP |
52 | if (r == -ENOENT) |
53 | return log_error_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT), "mkswap binary not available."); | |
54 | if (r < 0) | |
55 | return log_error_errno(r, "Failed to determine whether mkswap binary exists: %m"); | |
56 | } else { | |
57 | r = mkfs_exists(fstype); | |
58 | if (r < 0) | |
59 | return log_error_errno(r, "Failed to determine whether mkfs binary for %s exists: %m", fstype); | |
60 | if (r == 0) | |
61 | return log_error_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT), "mkfs binary for %s is not available.", fstype); | |
62 | ||
63 | mkfs = strjoin("mkfs.", fstype); | |
64 | if (!mkfs) | |
65 | return log_oom(); | |
66 | } | |
67 | ||
4f05a11c ZJS |
68 | if (streq(fstype, "vfat")) { |
69 | /* Classic FAT only allows 11 character uppercase labels */ | |
70 | strncpy(mangled_label, label, sizeof(mangled_label)-1); | |
71 | mangled_label[sizeof(mangled_label)-1] = 0; | |
72 | ascii_strupper(mangled_label); | |
73 | label = mangled_label; | |
74 | ||
75 | xsprintf(vol_id, "%08" PRIx32, | |
76 | ((uint32_t) uuid.bytes[0] << 24) | | |
77 | ((uint32_t) uuid.bytes[1] << 16) | | |
78 | ((uint32_t) uuid.bytes[2] << 8) | | |
79 | ((uint32_t) uuid.bytes[3])); /* Take first 32 bytes of UUID */ | |
80 | } | |
81 | ||
82 | if (isempty(vol_id)) | |
83 | id128_to_uuid_string(uuid, vol_id); | |
84 | ||
c95f9a23 LP |
85 | r = safe_fork("(mkfs)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR, NULL); |
86 | if (r < 0) | |
87 | return r; | |
88 | if (r == 0) { | |
c95f9a23 | 89 | /* Child */ |
4f05a11c ZJS |
90 | |
91 | /* When changing this conditional, also adjust the log statement below. */ | |
8e93a614 ZJS |
92 | if (streq(fstype, "ext2")) |
93 | (void) execlp(mkfs, mkfs, | |
4f05a11c | 94 | "-q", |
8e93a614 | 95 | "-L", label, |
4f05a11c | 96 | "-U", vol_id, |
8e93a614 ZJS |
97 | "-I", "256", |
98 | "-m", "0", | |
99 | "-E", discard ? "discard,lazy_itable_init=1" : "nodiscard,lazy_itable_init=1", | |
100 | node, NULL); | |
101 | ||
102 | else if (STR_IN_SET(fstype, "ext3", "ext4")) | |
c95f9a23 | 103 | (void) execlp(mkfs, mkfs, |
4f05a11c | 104 | "-q", |
85b55869 | 105 | "-L", label, |
4f05a11c | 106 | "-U", vol_id, |
85b55869 LP |
107 | "-I", "256", |
108 | "-O", "has_journal", | |
109 | "-m", "0", | |
44cdeb6e | 110 | "-E", discard ? "discard,lazy_itable_init=1" : "nodiscard,lazy_itable_init=1", |
85b55869 | 111 | node, NULL); |
c95f9a23 LP |
112 | |
113 | else if (streq(fstype, "btrfs")) { | |
44cdeb6e | 114 | (void) execlp(mkfs, mkfs, |
4f05a11c | 115 | "-q", |
44cdeb6e | 116 | "-L", label, |
4f05a11c | 117 | "-U", vol_id, |
44cdeb6e ZJS |
118 | node, |
119 | discard ? NULL : "--nodiscard", | |
120 | NULL); | |
c95f9a23 LP |
121 | |
122 | } else if (streq(fstype, "xfs")) { | |
123 | const char *j; | |
124 | ||
4f05a11c | 125 | j = strjoina("uuid=", vol_id); |
44cdeb6e ZJS |
126 | |
127 | (void) execlp(mkfs, mkfs, | |
4f05a11c | 128 | "-q", |
44cdeb6e ZJS |
129 | "-L", label, |
130 | "-m", j, | |
131 | "-m", "reflink=1", | |
132 | node, | |
133 | discard ? NULL : "-K", | |
134 | NULL); | |
c95f9a23 | 135 | |
4f05a11c | 136 | } else if (streq(fstype, "vfat")) |
0f2b2c48 LP |
137 | |
138 | (void) execlp(mkfs, mkfs, | |
139 | "-i", vol_id, | |
4f05a11c | 140 | "-n", label, |
0f2b2c48 LP |
141 | "-F", "32", /* yes, we force FAT32 here */ |
142 | node, NULL); | |
143 | ||
4f05a11c ZJS |
144 | else if (streq(fstype, "swap")) |
145 | /* TODO: add --quiet here if | |
146 | * https://github.com/util-linux/util-linux/issues/1499 resolved. */ | |
c95f9a23 LP |
147 | |
148 | (void) execlp(mkfs, mkfs, | |
85b55869 | 149 | "-L", label, |
4f05a11c | 150 | "-U", vol_id, |
85b55869 | 151 | node, NULL); |
c95f9a23 | 152 | |
4f05a11c | 153 | else |
c95f9a23 LP |
154 | /* Generic fallback for all other file systems */ |
155 | (void) execlp(mkfs, mkfs, node, NULL); | |
156 | ||
157 | log_error_errno(errno, "Failed to execute %s: %m", mkfs); | |
158 | ||
159 | _exit(EXIT_FAILURE); | |
160 | } | |
161 | ||
4f05a11c ZJS |
162 | if (STR_IN_SET(fstype, "ext2", "ext3", "ext4", "btrfs", "xfs", "vfat", "swap")) |
163 | log_info("%s successfully formatted as %s (label \"%s\", uuid %s)", | |
164 | node, fstype, label, vol_id); | |
165 | else | |
166 | log_info("%s successfully formatted as %s (no label or uuid specified)", | |
167 | node, fstype); | |
168 | ||
c95f9a23 LP |
169 | return 0; |
170 | } |