diff options
author | Norbert Lange <nolange79@gmail.com> | 2023-07-03 23:58:03 +0200 |
---|---|---|
committer | Gao Xiang <hsiangkao@linux.alibaba.com> | 2023-07-10 10:08:30 +0800 |
commit | 5de439566bc5b5b7e78fc3eac2c79ceae9d27f62 (patch) | |
tree | 45dbe6c148a2ba564a6e5a120c0e5df1f0426aef | |
parent | 7a85ae84c0adcc6ed467bec052edd94f2ca3db7c (diff) | |
download | erofs-utils-5de439566bc5b5b7e78fc3eac2c79ceae9d27f62.tar.gz |
erofs-utils: Provide identical functionality without libuuid
The motivation is to have standalone (statically linked) erofs binaries
for simple initrd images, that are nevertheless able to (re)create
erofs images with a given UUID.
For this reason a few of libuuid functions have implementations added
directly in erofs-utils.
A header liberofs_uuid.h provides the new functions, which are
always available. A further sideeffect is that code can be simplified
which calls into this functionality.
The uuid_unparse function replacement is always a private
implementation and split into its own file, this further restricts
the (optional) dependency on libuuid only to the erofs-mkfs tool.
Signed-off-by: Norbert Lange <nolange79@gmail.com>
Link: https://lore.kernel.org/r/20230703215803.4476-1-nolange79@gmail.com
[ Gao Xiang: a getrandom() fix since it was added in glibc 2.25. ]
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | dump/Makefile.am | 2 | ||||
-rw-r--r-- | dump/main.c | 10 | ||||
-rw-r--r-- | fsck/Makefile.am | 4 | ||||
-rw-r--r-- | lib/Makefile.am | 4 | ||||
-rw-r--r-- | lib/liberofs_uuid.h | 9 | ||||
-rw-r--r-- | lib/uuid.c | 118 | ||||
-rw-r--r-- | lib/uuid_unparse.c | 21 | ||||
-rw-r--r-- | mkfs/Makefile.am | 6 | ||||
-rw-r--r-- | mkfs/main.c | 23 |
10 files changed, 165 insertions, 33 deletions
diff --git a/configure.ac b/configure.ac index cd6be4a..54608fb 100644 --- a/configure.ac +++ b/configure.ac @@ -178,6 +178,7 @@ AC_CHECK_HEADERS(m4_flatten([ string.h sys/ioctl.h sys/mman.h + sys/random.h sys/stat.h sys/sysmacros.h sys/time.h diff --git a/dump/Makefile.am b/dump/Makefile.am index c2bef6d..90227a5 100644 --- a/dump/Makefile.am +++ b/dump/Makefile.am @@ -7,4 +7,4 @@ AM_CPPFLAGS = ${libuuid_CFLAGS} dump_erofs_SOURCES = main.c dump_erofs_CFLAGS = -Wall -I$(top_srcdir)/include dump_erofs_LDADD = $(top_builddir)/lib/liberofs.la ${libselinux_LIBS} \ - ${libuuid_LIBS} ${liblz4_LIBS} ${liblzma_LIBS} + ${liblz4_LIBS} ${liblzma_LIBS} diff --git a/dump/main.c b/dump/main.c index ae1ffa0..7e75719 100644 --- a/dump/main.c +++ b/dump/main.c @@ -17,10 +17,8 @@ #include "erofs/compress.h" #include "erofs/fragments.h" #include "../lib/liberofs_private.h" +#include "../lib/liberofs_uuid.h" -#ifdef HAVE_LIBUUID -#include <uuid.h> -#endif struct erofsdump_cfg { unsigned int totalshow; @@ -593,7 +591,7 @@ static void erofsdump_print_statistic(void) static void erofsdump_show_superblock(void) { time_t time = sbi.build_time; - char uuid_str[37] = "not available"; + char uuid_str[37]; int i = 0; fprintf(stdout, "Filesystem magic number: 0x%04X\n", @@ -621,9 +619,7 @@ static void erofsdump_show_superblock(void) if (feat & feature_lists[i].flag) fprintf(stdout, "%s ", feature_lists[i].name); } -#ifdef HAVE_LIBUUID - uuid_unparse_lower(sbi.uuid, uuid_str); -#endif + erofs_uuid_unparse_lower(sbi.uuid, uuid_str); fprintf(stdout, "\nFilesystem UUID: %s\n", uuid_str); } diff --git a/fsck/Makefile.am b/fsck/Makefile.am index 9366a9d..369cb2f 100644 --- a/fsck/Makefile.am +++ b/fsck/Makefile.am @@ -7,7 +7,7 @@ AM_CPPFLAGS = ${libuuid_CFLAGS} fsck_erofs_SOURCES = main.c fsck_erofs_CFLAGS = -Wall -I$(top_srcdir)/include fsck_erofs_LDADD = $(top_builddir)/lib/liberofs.la ${libselinux_LIBS} \ - ${libuuid_LIBS} ${liblz4_LIBS} ${liblzma_LIBS} + ${liblz4_LIBS} ${liblzma_LIBS} if ENABLE_FUZZING noinst_PROGRAMS = fuzz_erofsfsck @@ -15,5 +15,5 @@ fuzz_erofsfsck_SOURCES = main.c fuzz_erofsfsck_CFLAGS = -Wall -I$(top_srcdir)/include -DFUZZING fuzz_erofsfsck_LDFLAGS = -fsanitize=address,fuzzer fuzz_erofsfsck_LDADD = $(top_builddir)/lib/liberofs.la ${libselinux_LIBS} \ - ${libuuid_LIBS} ${liblz4_LIBS} ${liblzma_LIBS} + ${liblz4_LIBS} ${liblzma_LIBS} endif diff --git a/lib/Makefile.am b/lib/Makefile.am index faa7311..e243c1c 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -29,9 +29,9 @@ noinst_HEADERS += compressor.h liberofs_la_SOURCES = config.c io.c cache.c super.c inode.c xattr.c exclude.c \ namei.c data.c compress.c compressor.c zmap.c decompress.c \ compress_hints.c hashmap.c sha256.c blobchunk.c dir.c \ - fragments.c rb_tree.c dedupe.c + fragments.c rb_tree.c dedupe.c uuid_unparse.c uuid.c -liberofs_la_CFLAGS = -Wall -I$(top_srcdir)/include +liberofs_la_CFLAGS = -Wall ${libuuid_CFLAGS} -I$(top_srcdir)/include if ENABLE_LZ4 liberofs_la_CFLAGS += ${LZ4_CFLAGS} liberofs_la_SOURCES += compressor_lz4.c diff --git a/lib/liberofs_uuid.h b/lib/liberofs_uuid.h new file mode 100644 index 0000000..63b358a --- /dev/null +++ b/lib/liberofs_uuid.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0 */ +#ifndef __EROFS_LIB_UUID_H +#define __EROFS_LIB_UUID_H + +void erofs_uuid_generate(unsigned char *out); +void erofs_uuid_unparse_lower(const unsigned char *buf, char *out); +int erofs_uuid_parse(const char *in, unsigned char *uu); + +#endif diff --git a/lib/uuid.c b/lib/uuid.c new file mode 100644 index 0000000..ec0f9d9 --- /dev/null +++ b/lib/uuid.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0 +/* + * Copyright (C) 2023 Norbert Lange <nolange79@gmail.com> + */ + +#include <string.h> +#include <errno.h> + +#include "erofs/config.h" +#include "erofs/defs.h" +#include "liberofs_uuid.h" + +#ifdef HAVE_LIBUUID +#include <uuid.h> +#else + +#include <stdlib.h> +#ifdef HAVE_SYS_RANDOM_H +#include <sys/random.h> +#else +#define _GNU_SOURCE +#include <unistd.h> +#include <sys/syscall.h> +#endif + +/* Flags to be used, will be modified if kernel does not support them */ +static unsigned int erofs_grnd_flag = +#ifdef GRND_INSECURE + GRND_INSECURE; +#else + 0x0004; +#endif + +static int s_getrandom(void *out, unsigned size, bool insecure) +{ + unsigned int kflags = erofs_grnd_flag; + unsigned int flags = insecure ? kflags : 0; + + for (;;) + { +#ifdef HAVE_SYS_RANDOM_H + ssize_t r = getrandom(out, size, flags); +#else + ssize_t r = (ssize_t)syscall(__NR_getrandom, out, size, flags); +#endif + int err; + + if (r == size) + break; + err = errno; + if (err != EINTR) { + if (err == EINVAL && kflags) { + // Kernel likely does not support GRND_INSECURE + erofs_grnd_flag = 0; + kflags = 0; + continue; + } + return -err; + } + } + return 0; +} +#endif + +void erofs_uuid_generate(unsigned char *out) +{ +#ifdef HAVE_LIBUUID + uuid_t new_uuid; + + do { + uuid_generate(new_uuid); + } while (uuid_is_null(new_uuid)); +#else + unsigned char new_uuid[16]; + int res __maybe_unused; + + res = s_getrandom(new_uuid, sizeof(new_uuid), true); + BUG_ON(res != 0); + + // UID type + version bits + new_uuid[0] = (new_uuid[4 + 2] & 0x0f) | 0x40; + new_uuid[1] = (new_uuid[4 + 2 + 2] & 0x3f) | 0x80; +#endif + memcpy(out, new_uuid, sizeof(new_uuid)); +} + +int erofs_uuid_parse(const char *in, unsigned char *uu) { +#ifdef HAVE_LIBUUID + return uuid_parse((char *)in, uu); +#else + unsigned char new_uuid[16]; + unsigned int hypens = ((1U << 3) | (1U << 5) | (1U << 7) | (1U << 9)); + int i; + + for (i = 0; i < sizeof(new_uuid); hypens >>= 1, i++) + { + char c[] = { in[0], in[1], '\0' }; + char* endptr = c; + unsigned long val = strtoul(c, &endptr, 16); + + if (endptr - c != 2) + return -EINVAL; + + in += 2; + + if ((hypens & 1U) != 0) { + if (*in++ != '-') + return -EINVAL; + } + new_uuid[i] = (unsigned char)val; + } + + if (*in != '\0') + return -EINVAL; + memcpy(uu, new_uuid, sizeof(new_uuid)); + return 0; +#endif +} diff --git a/lib/uuid_unparse.c b/lib/uuid_unparse.c new file mode 100644 index 0000000..3255c4b --- /dev/null +++ b/lib/uuid_unparse.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0 +/* + * Copyright (C) 2023 Norbert Lange <nolange79@gmail.com> + */ + +#include <stdio.h> + +#include "erofs/config.h" +#include "liberofs_uuid.h" + +void erofs_uuid_unparse_lower(const unsigned char *buf, char *out) { + sprintf(out, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x", + (buf[0] << 8) | buf[1], + (buf[2] << 8) | buf[3], + (buf[4] << 8) | buf[5], + (buf[6] << 8) | buf[7], + (buf[8] << 8) | buf[9], + (buf[10] << 8) | buf[11], + (buf[12] << 8) | buf[13], + (buf[14] << 8) | buf[15]); +} diff --git a/mkfs/Makefile.am b/mkfs/Makefile.am index 709d9bf..a08dc53 100644 --- a/mkfs/Makefile.am +++ b/mkfs/Makefile.am @@ -2,8 +2,8 @@ AUTOMAKE_OPTIONS = foreign bin_PROGRAMS = mkfs.erofs -AM_CPPFLAGS = ${libuuid_CFLAGS} ${libselinux_CFLAGS} +AM_CPPFLAGS = ${libselinux_CFLAGS} mkfs_erofs_SOURCES = main.c mkfs_erofs_CFLAGS = -Wall -I$(top_srcdir)/include -mkfs_erofs_LDADD = ${libuuid_LIBS} $(top_builddir)/lib/liberofs.la ${libselinux_LIBS} \ - ${liblz4_LIBS} ${liblzma_LIBS} +mkfs_erofs_LDADD = $(top_builddir)/lib/liberofs.la ${libselinux_LIBS} \ + ${libuuid_LIBS} ${liblz4_LIBS} ${liblzma_LIBS} diff --git a/mkfs/main.c b/mkfs/main.c index ac208e5..438bab8 100644 --- a/mkfs/main.c +++ b/mkfs/main.c @@ -26,10 +26,7 @@ #include "erofs/blobchunk.h" #include "erofs/fragments.h" #include "../lib/liberofs_private.h" - -#ifdef HAVE_LIBUUID -#include <uuid.h> -#endif +#include "../lib/liberofs_uuid.h" #define EROFS_SUPER_END (EROFS_SUPER_OFFSET + sizeof(struct erofs_super_block)) @@ -92,9 +89,7 @@ static void usage(void) " -EX[,...] X=extended options\n" " -L volume-label set the volume label (maximum 16)\n" " -T# set a fixed UNIX timestamp # to all files\n" -#ifdef HAVE_LIBUUID " -UX use a given filesystem UUID\n" -#endif " --all-root make all files owned by root\n" " --blobdev=X specify an extra device X to store chunked data\n" " --chunksize=# generate chunk-based files with #-byte chunks\n" @@ -336,14 +331,12 @@ static int mkfs_parse_options_cfg(int argc, char *argv[]) } cfg.c_timeinherit = TIMESTAMP_FIXED; break; -#ifdef HAVE_LIBUUID case 'U': - if (uuid_parse(optarg, sbi.uuid)) { + if (erofs_uuid_parse(optarg, sbi.uuid)) { erofs_err("invalid UUID %s", optarg); return -EINVAL; } break; -#endif case 2: opt = erofs_parse_exclude_path(optarg, false); if (opt) { @@ -676,11 +669,7 @@ static void erofs_mkfs_default_options(void) EROFS_FEATURE_COMPAT_MTIME; /* generate a default uuid first */ -#ifdef HAVE_LIBUUID - do { - uuid_generate(sbi.uuid); - } while (uuid_is_null(sbi.uuid)); -#endif + erofs_uuid_generate(sbi.uuid); } /* https://reproducible-builds.org/specs/source-date-epoch/ for more details */ @@ -725,7 +714,7 @@ int main(int argc, char **argv) struct stat st; erofs_blk_t nblocks; struct timeval t; - char uuid_str[37] = "not available"; + char uuid_str[37]; FILE *packedfile = NULL; erofs_init_configure(); @@ -869,9 +858,7 @@ int main(int argc, char **argv) erofs_strerror(err)); goto exit; } -#ifdef HAVE_LIBUUID - uuid_unparse_lower(sbi.uuid, uuid_str); -#endif + erofs_uuid_unparse_lower(sbi.uuid, uuid_str); erofs_info("filesystem UUID: %s", uuid_str); erofs_inode_manager_init(); |