mirror of
https://github.com/systemd/systemd
synced 2024-09-06 00:41:36 +00:00
mkfs-util: Add support to populate vfat without mounting using mcopy
mkfs.vfat doesn't support specifying a root directory to bootstrap the filesystem from (see https://github.com/dosfstools/dosfstools/issues/183). Instead, we can use the mcopy tool from the mtools package to copy files into the vfat filesystem after creating it without needing to mount the vfat filesystem.
This commit is contained in:
parent
68665704dc
commit
bf3598beff
|
@ -21,6 +21,7 @@ Packages=
|
|||
coreutils
|
||||
diffutils
|
||||
dnsmasq
|
||||
dosfstools
|
||||
e2fsprogs
|
||||
findutils
|
||||
gcc # For sanitizer libraries
|
||||
|
@ -30,6 +31,7 @@ Packages=
|
|||
kexec-tools
|
||||
kmod
|
||||
less
|
||||
mtools
|
||||
nano
|
||||
nftables
|
||||
openssl
|
||||
|
|
|
@ -2,11 +2,14 @@
|
|||
|
||||
#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"
|
||||
|
@ -34,7 +37,7 @@ int mkfs_exists(const char *fstype) {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
@ -91,6 +94,59 @@ static int mangle_fat_label(const char *s, 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,
|
||||
|
@ -304,6 +360,12 @@ int make_filesystem(
|
|||
_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);
|
||||
|
|
|
@ -15,6 +15,7 @@ test_append_files() {
|
|||
if command -v openssl >/dev/null 2>&1; then
|
||||
inst_binary openssl
|
||||
fi
|
||||
inst_binary mcopy
|
||||
instmods dm_verity =md
|
||||
generate_module_dependencies
|
||||
image_install -o /sbin/mksquashfs
|
||||
|
|
|
@ -1310,6 +1310,11 @@ install_missing_libraries() {
|
|||
inst_simple "${path}/engines-3/capi.so" || true
|
||||
inst_simple "${path}/engines-3/loader_attic.so" || true
|
||||
inst_simple "${path}/engines-3/padlock.so" || true
|
||||
|
||||
# Binaries from mtools depend on the gconv modules to translate between codepages. Because there's no
|
||||
# pkg-config file for these, we copy every gconv/ directory we can find in /usr/lib and /usr/lib64.
|
||||
# shellcheck disable=SC2046
|
||||
inst_recursive $(find /usr/lib* -name gconv 2>/dev/null)
|
||||
}
|
||||
|
||||
cleanup_loopdev() {
|
||||
|
|
Loading…
Reference in a new issue