1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-01-03 01:17:45 +03:00

Merge pull request #21275 from keszybz/makefs-quiet

Makefs quiet output
This commit is contained in:
Lennart Poettering 2021-11-16 16:55:47 +01:00 committed by GitHub
commit 67d0c6744f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 211 additions and 37 deletions

View File

@ -52,7 +52,12 @@
systems and swap devices, and after checking that the block device does not already systems and swap devices, and after checking that the block device does not already
contain a file system or other content, it will execute binaries specific to contain a file system or other content, it will execute binaries specific to
each filesystem type (<filename>/sbin/mkfs.<replaceable>type</replaceable></filename> each filesystem type (<filename>/sbin/mkfs.<replaceable>type</replaceable></filename>
or <filename>/sbin/mkswap</filename>).</para> or <filename>/sbin/mkswap</filename>). For certain file system types (currently
ext2/ext3/<citerefentry project='man-pages'><refentrytitle>ext4</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry project='url'><refentrytitle url='https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)'>btrfs</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>xfs</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
f2fs, vfat) and for swap devices, it will configure reasonable defaults and set
the file system label and UUID based on the device name.</para>
<para><filename>systemd-growfs</filename> knows very little about specific file <para><filename>systemd-growfs</filename> knows very little about specific file
systems and swap devices, and will instruct the kernel to grow the mounted systems and swap devices, and will instruct the kernel to grow the mounted

View File

@ -124,11 +124,9 @@ int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar) {
} }
bool utf8_is_printable_newline(const char* str, size_t length, bool allow_newline) { bool utf8_is_printable_newline(const char* str, size_t length, bool allow_newline) {
const char *p;
assert(str); assert(str);
for (p = str; length > 0;) { for (const char *p = str; length > 0;) {
int encoded_len, r; int encoded_len, r;
char32_t val; char32_t val;
@ -289,14 +287,12 @@ char *utf8_escape_non_printable_full(const char *str, size_t console_width, bool
} }
char *ascii_is_valid(const char *str) { char *ascii_is_valid(const char *str) {
const char *p;
/* Check whether the string consists of valid ASCII bytes, /* Check whether the string consists of valid ASCII bytes,
* i.e values between 0 and 127, inclusive. */ * i.e values between 0 and 127, inclusive. */
assert(str); assert(str);
for (p = str; *p; p++) for (const char *p = str; *p; p++)
if ((unsigned char) *p >= 128) if ((unsigned char) *p >= 128)
return NULL; return NULL;
@ -316,6 +312,37 @@ char *ascii_is_valid_n(const char *str, size_t len) {
return (char*) str; return (char*) str;
} }
int utf8_to_ascii(const char *str, char replacement_char, char **ret) {
/* Convert to a string that has only ASCII chars, replacing anything that is not ASCII
* by replacement_char. */
_cleanup_free_ char *ans = new(char, strlen(str) + 1);
if (!ans)
return -ENOMEM;
char *q = ans;
for (const char *p = str; *p; q++) {
int l;
l = utf8_encoded_valid_unichar(p, SIZE_MAX);
if (l < 0) /* Non-UTF-8, let's not even try to propagate the garbage */
return l;
if (l == 1)
*q = *p;
else
/* non-ASCII, we need to replace it */
*q = replacement_char;
p += l;
}
*q = '\0';
*ret = TAKE_PTR(ans);
return 0;
}
/** /**
* utf8_encode_unichar() - Encode single UCS-4 character as UTF-8 * utf8_encode_unichar() - Encode single UCS-4 character as UTF-8
* @out_utf8: output buffer of at least 4 bytes or NULL * @out_utf8: output buffer of at least 4 bytes or NULL

View File

@ -21,6 +21,8 @@ static inline char *utf8_is_valid(const char *s) {
char *ascii_is_valid(const char *s) _pure_; char *ascii_is_valid(const char *s) _pure_;
char *ascii_is_valid_n(const char *str, size_t len); char *ascii_is_valid_n(const char *str, size_t len);
int utf8_to_ascii(const char *str, char replacement_char, char **ret);
bool utf8_is_printable_newline(const char* str, size_t length, bool allow_newline) _pure_; bool utf8_is_printable_newline(const char* str, size_t length, bool allow_newline) _pure_;
#define utf8_is_printable(str, length) utf8_is_printable_newline(str, length, true) #define utf8_is_printable(str, length) utf8_is_printable_newline(str, length, true)

View File

@ -49,7 +49,7 @@ static int run(int argc, char *argv[]) {
if (lock_fd < 0) if (lock_fd < 0)
return log_error_errno(lock_fd, "Failed to lock whole block device of \"%s\": %m", device); return log_error_errno(lock_fd, "Failed to lock whole block device of \"%s\": %m", device);
} else } else
log_info("%s is not a block device.", device); log_debug("%s is not a block device, no need to lock.", device);
r = probe_filesystem(device, &detected); r = probe_filesystem(device, &detected);
if (r == -EUCLEAN) if (r == -EUCLEAN)

View File

@ -8,6 +8,7 @@
#include "process-util.h" #include "process-util.h"
#include "stdio-util.h" #include "stdio-util.h"
#include "string-util.h" #include "string-util.h"
#include "utf8.h"
int mkfs_exists(const char *fstype) { int mkfs_exists(const char *fstype) {
const char *mkfs; const char *mkfs;
@ -31,6 +32,60 @@ int mkfs_exists(const char *fstype) {
return true; return true;
} }
static int mangle_linux_fs_label(const char *s, size_t max_len, char **ret) {
/* Not more than max_len bytes (12 or 16) */
assert(s);
assert(max_len > 0);
assert(ret);
const char *q;
char *ans;
for (q = s; *q;) {
int l;
l = utf8_encoded_valid_unichar(q, SIZE_MAX);
if (l < 0)
return l;
if ((size_t) (q - s + l) > max_len)
break;
q += l;
}
ans = memdup_suffix0(s, q - s);
if (!ans)
return -ENOMEM;
*ret = ans;
return 0;
}
static int mangle_fat_label(const char *s, char **ret) {
assert(s);
_cleanup_free_ char *q = NULL;
int r;
r = utf8_to_ascii(s, '_', &q);
if (r < 0)
return r;
/* Classic FAT only allows 11 character uppercase labels */
strshorten(q, 11);
ascii_strupper(q);
/* mkfs.vfat: Labels with characters *?.,;:/\|+=<>[]" are not allowed.
* Let's also replace any control chars. */
for (char *p = q; *p; p++)
if (strchr("*?.,;:/\\|+=<>[]\"", *p) || char_is_cc(*p))
*p = '_';
*ret = TAKE_PTR(q);
return 0;
}
int make_filesystem( int make_filesystem(
const char *node, const char *node,
const char *fstype, const char *fstype,
@ -38,7 +93,8 @@ int make_filesystem(
sd_id128_t uuid, sd_id128_t uuid,
bool discard) { bool discard) {
_cleanup_free_ char *mkfs = NULL; _cleanup_free_ char *mkfs = NULL, *mangled_label = NULL;
char vol_id[CONST_MAX(ID128_UUID_STRING_MAX, 8 + 1)] = {};
int r; int r;
assert(node); assert(node);
@ -63,64 +119,113 @@ int make_filesystem(
return log_oom(); return log_oom();
} }
if (STR_IN_SET(fstype, "ext2", "ext3", "ext4", "xfs", "swap")) {
size_t max_len =
streq(fstype, "xfs") ? 12 :
streq(fstype, "swap") ? 15 :
16;
r = mangle_linux_fs_label(label, max_len, &mangled_label);
if (r < 0)
return log_error_errno(r, "Failed to determine volume label from string \"%s\": %m", label);
label = mangled_label;
} else if (streq(fstype, "vfat")) {
r = mangle_fat_label(label, &mangled_label);
if (r < 0)
return log_error_errno(r, "Failed to determine FAT label from string \"%s\": %m", label);
label = mangled_label;
xsprintf(vol_id, "%08" PRIx32,
((uint32_t) uuid.bytes[0] << 24) |
((uint32_t) uuid.bytes[1] << 16) |
((uint32_t) uuid.bytes[2] << 8) |
((uint32_t) uuid.bytes[3])); /* Take first 32 bytes of UUID */
}
if (isempty(vol_id))
id128_to_uuid_string(uuid, vol_id);
r = safe_fork("(mkfs)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR, NULL); r = safe_fork("(mkfs)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR, NULL);
if (r < 0) if (r < 0)
return r; return r;
if (r == 0) { if (r == 0) {
/* Child */ /* Child */
if (streq(fstype, "ext4"))
/* When changing this conditional, also adjust the log statement below. */
if (streq(fstype, "ext2"))
(void) execlp(mkfs, mkfs, (void) execlp(mkfs, mkfs,
"-q",
"-L", label, "-L", label,
"-U", ID128_TO_UUID_STRING(uuid), "-U", vol_id,
"-I", "256",
"-m", "0",
"-E", discard ? "discard,lazy_itable_init=1" : "nodiscard,lazy_itable_init=1",
node, NULL);
else if (STR_IN_SET(fstype, "ext3", "ext4"))
(void) execlp(mkfs, mkfs,
"-q",
"-L", label,
"-U", vol_id,
"-I", "256", "-I", "256",
"-O", "has_journal", "-O", "has_journal",
"-m", "0", "-m", "0",
"-E", discard ? "lazy_itable_init=1,discard" : "lazy_itable_init=1,nodiscard", "-E", discard ? "discard,lazy_itable_init=1" : "nodiscard,lazy_itable_init=1",
node, NULL); node, NULL);
else if (streq(fstype, "btrfs")) { else if (streq(fstype, "btrfs")) {
if (discard) (void) execlp(mkfs, mkfs,
(void) execlp(mkfs, mkfs, "-L", label, "-U", ID128_TO_UUID_STRING(uuid), node, NULL); "-q",
else "-L", label,
(void) execlp(mkfs, mkfs, "-L", label, "-U", ID128_TO_UUID_STRING(uuid), "--nodiscard", node, NULL); "-U", vol_id,
node,
discard ? NULL : "--nodiscard",
NULL);
} else if (streq(fstype, "f2fs")) {
(void) execlp(mkfs, mkfs,
"-q",
"-g", /* "default options" */
"-f", /* force override, without this it doesn't seem to want to write to an empty partition */
"-l", label,
"-U", vol_id,
"-t", one_zero(discard),
node,
NULL);
} else if (streq(fstype, "xfs")) { } else if (streq(fstype, "xfs")) {
const char *j; const char *j;
j = strjoina("uuid=", ID128_TO_UUID_STRING(uuid)); j = strjoina("uuid=", vol_id);
if (discard)
(void) execlp(mkfs, mkfs, "-L", label, "-m", j, "-m", "reflink=1", node, NULL);
else
(void) execlp(mkfs, mkfs, "-L", label, "-m", j, "-m", "reflink=1", "-K", node, NULL);
} else if (streq(fstype, "vfat")) { (void) execlp(mkfs, mkfs,
char mangled_label[8 + 3 + 1], vol_id[8 + 1]; "-q",
"-L", label,
"-m", j,
"-m", "reflink=1",
node,
discard ? NULL : "-K",
NULL);
/* Classic FAT only allows 11 character uppercase labels */ } else if (streq(fstype, "vfat"))
strncpy(mangled_label, label, sizeof(mangled_label)-1);
mangled_label[sizeof(mangled_label)-1] = 0;
ascii_strupper(mangled_label);
xsprintf(vol_id, "%08" PRIx32,
((uint32_t) uuid.bytes[0] << 24) |
((uint32_t) uuid.bytes[1] << 16) |
((uint32_t) uuid.bytes[2] << 8) |
((uint32_t) uuid.bytes[3])); /* Take first 32 byte of UUID */
(void) execlp(mkfs, mkfs, (void) execlp(mkfs, mkfs,
"-i", vol_id, "-i", vol_id,
"-n", mangled_label, "-n", label,
"-F", "32", /* yes, we force FAT32 here */ "-F", "32", /* yes, we force FAT32 here */
node, NULL); node, NULL);
} else if (streq(fstype, "swap")) { else if (streq(fstype, "swap"))
/* TODO: add --quiet here if
* https://github.com/util-linux/util-linux/issues/1499 resolved. */
(void) execlp(mkfs, mkfs, (void) execlp(mkfs, mkfs,
"-L", label, "-L", label,
"-U", ID128_TO_UUID_STRING(uuid), "-U", vol_id,
node, NULL); node, NULL);
} else else
/* Generic fallback for all other file systems */ /* Generic fallback for all other file systems */
(void) execlp(mkfs, mkfs, node, NULL); (void) execlp(mkfs, mkfs, node, NULL);
@ -129,5 +234,12 @@ int make_filesystem(
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} }
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);
else
log_info("%s successfully formatted as %s (no label or uuid specified)",
node, fstype);
return 0; return 0;
} }

View File

@ -66,6 +66,33 @@ static void test_ascii_is_valid_n(void) {
assert_se( ascii_is_valid_n("\342\204\242", 0)); assert_se( ascii_is_valid_n("\342\204\242", 0));
} }
static void test_utf8_to_ascii_one(const char *s, int r_expected, const char *expected) {
_cleanup_free_ char *ans = NULL;
int r;
r = utf8_to_ascii(s, '*', &ans);
log_debug("\"%s\" → %d/\"%s\" (expected %d/\"%s\")", s, r, strnull(ans), r_expected, strnull(expected));
assert_se(r == r_expected);
assert_se(streq_ptr(ans, expected));
}
static void test_utf8_to_ascii(void) {
log_info("/* %s */", __func__);
test_utf8_to_ascii_one("asdf", 0, "asdf");
test_utf8_to_ascii_one("dąb", 0, "d*b");
test_utf8_to_ascii_one("żęśłą óźń", 0, "***** ***");
test_utf8_to_ascii_one("\342\204\242", 0, "*");
test_utf8_to_ascii_one("\342\204", -EINVAL, NULL); /* truncated */
test_utf8_to_ascii_one("\342", -EINVAL, NULL); /* truncated */
test_utf8_to_ascii_one("\302\256", 0, "*");
test_utf8_to_ascii_one("", 0, "");
test_utf8_to_ascii_one(" ", 0, " ");
test_utf8_to_ascii_one("\t", 0, "\t");
test_utf8_to_ascii_one("", 0, "*");
test_utf8_to_ascii_one("…👊🔪💐…", 0, "*****");
}
static void test_utf8_encoded_valid_unichar(void) { static void test_utf8_encoded_valid_unichar(void) {
log_info("/* %s */", __func__); log_info("/* %s */", __func__);
@ -241,6 +268,7 @@ int main(int argc, char *argv[]) {
test_utf8_is_printable(); test_utf8_is_printable();
test_ascii_is_valid(); test_ascii_is_valid();
test_ascii_is_valid_n(); test_ascii_is_valid_n();
test_utf8_to_ascii();
test_utf8_encoded_valid_unichar(); test_utf8_encoded_valid_unichar();
test_utf8_escape_invalid(); test_utf8_escape_invalid();
test_utf8_escape_non_printable(); test_utf8_escape_non_printable();