]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/mkfs-util.c
ce10e60bb6b9f24d106ce42451adaf5c0bff8467
[thirdparty/systemd.git] / src / shared / mkfs-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "id128-util.h"
4 #include "mkfs-util.h"
5 #include "path-util.h"
6 #include "process-util.h"
7 #include "stdio-util.h"
8 #include "string-util.h"
9
10 int mkfs_exists(const char *fstype) {
11 const char *mkfs;
12 int r;
13
14 assert(fstype);
15
16 if (STR_IN_SET(fstype, "auto", "swap")) /* these aren't real file system types, refuse early */
17 return -EINVAL;
18
19 mkfs = strjoina("mkfs.", fstype);
20 if (!filename_is_valid(mkfs)) /* refuse file system types with slashes and similar */
21 return -EINVAL;
22
23 r = find_executable(mkfs, NULL);
24 if (r == -ENOENT)
25 return false;
26 if (r < 0)
27 return r;
28
29 return true;
30 }
31
32 int make_filesystem(
33 const char *node,
34 const char *fstype,
35 const char *label,
36 sd_id128_t uuid,
37 bool discard) {
38
39 _cleanup_free_ char *mkfs = NULL;
40 int r;
41
42 assert(node);
43 assert(fstype);
44 assert(label);
45
46 if (streq(fstype, "swap")) {
47 r = find_executable("mkswap", &mkfs);
48 if (r == -ENOENT)
49 return log_error_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT), "mkswap binary not available.");
50 if (r < 0)
51 return log_error_errno(r, "Failed to determine whether mkswap binary exists: %m");
52 } else {
53 r = mkfs_exists(fstype);
54 if (r < 0)
55 return log_error_errno(r, "Failed to determine whether mkfs binary for %s exists: %m", fstype);
56 if (r == 0)
57 return log_error_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT), "mkfs binary for %s is not available.", fstype);
58
59 mkfs = strjoin("mkfs.", fstype);
60 if (!mkfs)
61 return log_oom();
62 }
63
64 r = safe_fork("(mkfs)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR, NULL);
65 if (r < 0)
66 return r;
67 if (r == 0) {
68 char suuid[ID128_UUID_STRING_MAX];
69
70 /* Child */
71 id128_to_uuid_string(uuid, suuid);
72
73 if (streq(fstype, "ext4"))
74 (void) execlp(mkfs, mkfs,
75 "-L", label,
76 "-U", suuid,
77 "-I", "256",
78 "-O", "has_journal",
79 "-m", "0",
80 "-E", discard ? "lazy_itable_init=1,discard" : "lazy_itable_init=1,nodiscard",
81 node, NULL);
82
83 else if (streq(fstype, "btrfs")) {
84 if (discard)
85 (void) execlp(mkfs, mkfs, "-L", label, "-U", suuid, node, NULL);
86 else
87 (void) execlp(mkfs, mkfs, "-L", label, "-U", suuid, "--nodiscard", node, NULL);
88
89 } else if (streq(fstype, "xfs")) {
90 const char *j;
91
92 j = strjoina("uuid=", suuid);
93 if (discard)
94 (void) execlp(mkfs, mkfs, "-L", label, "-m", j, "-m", "reflink=1", node, NULL);
95 else
96 (void) execlp(mkfs, mkfs, "-L", label, "-m", j, "-m", "reflink=1", "-K", node, NULL);
97
98 } else if (streq(fstype, "vfat")) {
99 char mangled_label[8 + 3 + 1], vol_id[8 + 1];
100
101 /* Classic FAT only allows 11 character uppercase labels */
102 strncpy(mangled_label, label, sizeof(mangled_label)-1);
103 mangled_label[sizeof(mangled_label)-1] = 0;
104 ascii_strupper(mangled_label);
105
106 xsprintf(vol_id, "%08" PRIx32,
107 ((uint32_t) uuid.bytes[0] << 24) |
108 ((uint32_t) uuid.bytes[1] << 16) |
109 ((uint32_t) uuid.bytes[2] << 8) |
110 ((uint32_t) uuid.bytes[3])); /* Take first 32 byte of UUID */
111
112 (void) execlp(mkfs, mkfs,
113 "-i", vol_id,
114 "-n", mangled_label,
115 "-F", "32", /* yes, we force FAT32 here */
116 node, NULL);
117
118 } else if (streq(fstype, "swap")) {
119
120 (void) execlp(mkfs, mkfs,
121 "-L", label,
122 "-U", suuid,
123 node, NULL);
124
125 } else
126 /* Generic fallback for all other file systems */
127 (void) execlp(mkfs, mkfs, node, NULL);
128
129 log_error_errno(errno, "Failed to execute %s: %m", mkfs);
130
131 _exit(EXIT_FAILURE);
132 }
133
134 return 0;
135 }