aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNorbert Lange <nolange79@gmail.com>2023-07-03 23:58:03 +0200
committerGao Xiang <hsiangkao@linux.alibaba.com>2023-07-10 10:08:30 +0800
commit5de439566bc5b5b7e78fc3eac2c79ceae9d27f62 (patch)
tree45dbe6c148a2ba564a6e5a120c0e5df1f0426aef
parent7a85ae84c0adcc6ed467bec052edd94f2ca3db7c (diff)
downloaderofs-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.ac1
-rw-r--r--dump/Makefile.am2
-rw-r--r--dump/main.c10
-rw-r--r--fsck/Makefile.am4
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/liberofs_uuid.h9
-rw-r--r--lib/uuid.c118
-rw-r--r--lib/uuid_unparse.c21
-rw-r--r--mkfs/Makefile.am6
-rw-r--r--mkfs/main.c23
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();