]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/partition/makefs.c
Merge pull request #15840 from Werkov/mkosi-opensuse
[thirdparty/systemd.git] / src / partition / makefs.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <fcntl.h>
4 #include <sys/prctl.h>
5 #include <sys/stat.h>
6 #include <sys/types.h>
7 #include <unistd.h>
8
9 #include "alloc-util.h"
10 #include "blockdev-util.h"
11 #include "dissect-image.h"
12 #include "fd-util.h"
13 #include "main-func.h"
14 #include "process-util.h"
15 #include "signal-util.h"
16 #include "string-util.h"
17
18 static int makefs(const char *type, const char *device) {
19 const char *mkfs;
20 pid_t pid;
21 int r;
22
23 if (streq(type, "swap"))
24 mkfs = "/sbin/mkswap";
25 else
26 mkfs = strjoina("/sbin/mkfs.", type);
27 if (access(mkfs, X_OK) != 0)
28 return log_error_errno(errno, "%s is not executable: %m", mkfs);
29
30 r = safe_fork("(mkfs)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
31 if (r < 0)
32 return r;
33 if (r == 0) {
34 const char *cmdline[3] = { mkfs, device, NULL };
35
36 /* Child */
37
38 execv(cmdline[0], (char**) cmdline);
39 _exit(EXIT_FAILURE);
40 }
41
42 return wait_for_terminate_and_check(mkfs, pid, WAIT_LOG);
43 }
44
45 static int run(int argc, char *argv[]) {
46 _cleanup_free_ char *device = NULL, *type = NULL, *detected = NULL;
47 _cleanup_close_ int lock_fd = -1;
48 struct stat st;
49 int r;
50
51 log_setup_service();
52
53 if (argc != 3)
54 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
55 "This program expects two arguments.");
56
57 /* type and device must be copied because makefs calls safe_fork, which clears argv[] */
58 type = strdup(argv[1]);
59 if (!type)
60 return log_oom();
61
62 device = strdup(argv[2]);
63 if (!device)
64 return log_oom();
65
66 if (stat(device, &st) < 0)
67 return log_error_errno(errno, "Failed to stat \"%s\": %m", device);
68
69 if (S_ISBLK(st.st_mode)) {
70 /* Lock the device so that udev doesn't interfere with our work */
71
72 lock_fd = lock_whole_block_device(st.st_rdev, LOCK_EX);
73 if (lock_fd < 0)
74 return log_error_errno(lock_fd, "Failed to lock whole block device of \"%s\": %m", device);
75 } else
76 log_info("%s is not a block device.", device);
77
78 r = probe_filesystem(device, &detected);
79 if (r == -EUCLEAN)
80 return log_error_errno(r, "Ambiguous results of probing for file system on \"%s\", refusing to proceed.", device);
81 if (r < 0)
82 return log_error_errno(r, "Failed to probe \"%s\": %m", device);
83 if (detected) {
84 log_info("'%s' is not empty (contains file system of type %s), exiting.", device, detected);
85 return 0;
86 }
87
88 return makefs(type, device);
89 }
90
91 DEFINE_MAIN_FUNCTION(run);