#include <unistd.h>
+#include "dirent-util.h"
+#include "fd-util.h"
#include "id128-util.h"
#include "mkfs-util.h"
#include "mountpoint-util.h"
#include "path-util.h"
#include "process-util.h"
+#include "stat-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "utf8.h"
}
int mkfs_supports_root_option(const char *fstype) {
- return fstype_is_ro(fstype) || STR_IN_SET(fstype, "ext2", "ext3", "ext4", "btrfs");
+ return fstype_is_ro(fstype) || STR_IN_SET(fstype, "ext2", "ext3", "ext4", "btrfs", "vfat");
}
static int mangle_linux_fs_label(const char *s, size_t max_len, char **ret) {
return 0;
}
+static int do_mcopy(const char *node, const char *root) {
+ _cleanup_strv_free_ char **argv = NULL;
+ _cleanup_closedir_ DIR *rootdir = NULL;
+ int r;
+
+ assert(node);
+ assert(root);
+
+ /* Return early if there's nothing to copy. */
+ if (dir_is_empty(root, /*ignore_hidden_or_backup=*/ false))
+ return 0;
+
+ argv = strv_new("mcopy", "-b", "-s", "-p", "-Q", "-n", "-m", "-i", node);
+ if (!argv)
+ return log_oom();
+
+ /* mcopy copies the top level directory instead of everything in it so we have to pass all
+ * the subdirectories to mcopy instead to end up with the correct directory structure. */
+
+ rootdir = opendir(root);
+ if (!rootdir)
+ return log_error_errno(errno, "Failed to open directory '%s'", root);
+
+ FOREACH_DIRENT(de, rootdir, return -errno) {
+ char *p = path_join(root, de->d_name);
+ if (!p)
+ return log_oom();
+
+ r = strv_consume(&argv, TAKE_PTR(p));
+ if (r < 0)
+ return log_oom();
+ }
+
+ r = strv_extend(&argv, "::");
+ if (r < 0)
+ return log_oom();
+
+ r = safe_fork("(mcopy)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR|FORK_NEW_USERNS, NULL);
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ /* Avoid failures caused by mismatch in expectations between mkfs.vfat and mcopy by disabling
+ * the stricter mcopy checks using MTOOLS_SKIP_CHECK. */
+ execvpe("mcopy", argv, STRV_MAKE("MTOOLS_SKIP_CHECK=1"));
+
+ log_error_errno(errno, "Failed to execute mcopy: %m");
+
+ _exit(EXIT_FAILURE);
+ }
+
+ return 0;
+}
+
int make_filesystem(
const char *node,
const char *fstype,
_exit(EXIT_FAILURE);
}
+ if (root && streq(fstype, "vfat")) {
+ r = do_mcopy(node, root);
+ if (r < 0)
+ return r;
+ }
+
if (STR_IN_SET(fstype, "ext2", "ext3", "ext4", "btrfs", "f2fs", "xfs", "vfat", "swap"))
log_info("%s successfully formatted as %s (label \"%s\", uuid %s)",
node, fstype, label, vol_id);