summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/id.c116
-rw-r--r--src/id.h22
-rw-r--r--src/id.i3161
-rw-r--r--src/load.c257
-rw-r--r--src/main.c61
-rw-r--r--src/musl-libgen-c.h5
-rw-r--r--src/random-seed.c464
-rw-r--r--src/random-seed.h25
-rw-r--r--src/save.c230
-rw-r--r--src/util.c62
-rw-r--r--src/util.h25
11 files changed, 3881 insertions, 547 deletions
diff --git a/src/id.c b/src/id.c
index 6095ef6..0a37ba5 100644
--- a/src/id.c
+++ b/src/id.c
@@ -1,43 +1,114 @@
// SPDX-License-Identifier: BSD-3-Clause
+#include "config.h"
+
+#include "id.h"
+#include "random-seed.h"
+#include "sha2.h"
+#include "util.h"
+
#include <assert.h>
+#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <sys/statfs.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#include <sys/vfs.h>
+#include <unistd.h>
-#include "id.h"
-#include "util.h"
+#ifdef HAVE_LIBUDEV
+#include <libudev.h>
+#endif
+
+#ifdef HAVE_UTIL_LINUX
+#include <blkid.h>
+#include <libmount.h>
+#endif
+
+static const char *MACHINE_ID_PATHS[] = THE_MACHINE_ID_PATHS;
+
+bool ensure_rs_device(struct random_seed *rs, int fd) {
+ assert(!major(rs->dev));
+ struct stat statbuf;
+ if (fstat(fd, &statbuf) == -1) {
+ perror("warning: failed getting seed device");
+ return false;
+ }
+ memcpy(&rs->dev, &statbuf.st_dev, sizeof(dev_t));
+ return true;
+}
+
+#ifdef HAVE_LIBUDEV
+static struct udev *udev;
-#ifdef HAVE_UDEV
+bool ensure_udev_device(struct random_seed *rs) {
+ if (!udev)
+ udev = udev_new();
+ if (!udev) {
+ fputs("error initializing libudev\n", stderr);
+ return false;
+ }
+ if (!major(rs->dev)) {
+ assert(rs->file);
+ if (!ensure_rs_device(rs, fileno(rs->file)))
+ return false;
+ }
+ if (!rs->udev_dev)
+ rs->udev_dev = udev_device_new_from_devnum(udev, 'b', rs->dev);
+ return !!rs->udev_dev;
+}
+const char *get_fs_uuid_udev(struct random_seed *rs) {
+ if (!ensure_udev_device(rs))
+ return NULL;
+ return udev_device_get_property_value(rs->udev_dev, "ID_FS_UUID_ENC");
+}
+
+const char *get_drive_id(struct random_seed *rs) {
+ if (!ensure_udev_device(rs))
+ return NULL;
+ return udev_device_get_property_value(rs->udev_dev, "ID_SERIAL");
+}
#endif
#ifdef HAVE_UTIL_LINUX
+const char *get_fs_uuid_util_linux(struct random_seed *rs) {
+ return "fake uuid";
+}
+#endif
+#if defined(HAVE_LIBUDEV) && defined(HAVE_UTIL_LINUX)
+const char *get_fs_uuid(struct random_seed *rs) {
+ const char *rv = get_fs_uuid_udev(rs);
+ if (!rv)
+ rv = get_fs_uuid_util_linux(rs);
+ return rv;
+}
+#elif defined(HAVE_LIBUDEV)
+const char *get_fs_uuid(struct random_seed *rs) {
+ return get_fs_uuid_udev(rs);
+}
+#elif defined(HAVE_UTIL_LINUX)
+const char *get_fs_uuid(struct random_seed *rs) {
+ return get_fs_uuid_util_linux(rs);
+}
#endif
static char *really_get_machine_id() {
-#ifdef MACHINE_ID_PATH
- FILE *machine_id_file = fopen(MACHINE_ID_PATH, "r");
-#else
- const char *etc_machine_id = "/etc/machine-id";
- const char *var_lib_dbus_machine_id = "/var/lib/dbus/machine-id";
- FILE *machine_id_file = fopen(etc_machine_id, "r");
- if (!machine_id_file) {
- if (errno != ENOENT)
- fprintf(stderr, "error opening %s: %s, trying %s\n",
- etc_machine_id, strerror(errno), var_lib_dbus_machine_id);
- machine_id_file = fopen(var_lib_dbus_machine_id, "r");
+ FILE *machine_id_file;
+ for (size_t i = 0; i < ARRAY_SIZE(MACHINE_ID_PATHS); i++) {
+ machine_id_file = fopen(MACHINE_ID_PATHS[i], "r");
+ if (!machine_id_file)
+ fprintf(stderr, "warning: failed to open machine id %s: %s\n", MACHINE_ID_PATHS[i], strerror(errno));
}
-#endif
-
if (!machine_id_file) {
- perror("couldn't open any machine-id file, last error");
+ fputs("error: failed to open all machine id files\n", stderr);
return NULL;
}
@@ -52,15 +123,14 @@ static char *really_get_machine_id() {
return machine_id;
}
-size_t get_machine_id(char **machine_id) {
+const char *get_machine_id() {
static char *c_machine_id;
if (!c_machine_id)
c_machine_id = really_get_machine_id();
- *machine_id = c_machine_id;
- return strlen(*machine_id);
+ return c_machine_id;
}
-size_t get_fs_id(fsid_t *fs_id, int seed_fd) {
+bool get_fs_id(fsid_t *fs_id, int seed_fd) {
struct statfs statfs_buf;
if (fstatfs(seed_fd, &statfs_buf) == -1) {
perror("error: statfs seed file: %s");
@@ -75,10 +145,10 @@ size_t get_fs_id(fsid_t *fs_id, int seed_fd) {
case 0x52654973: // REISERFS_SUPER_MAGIC
case 0x24051905: // UBIFS_SUPER_MAGIC
memcpy(fs_id, &statfs_buf.f_fsid, sizeof(fsid_t));
- return sizeof(fsid_t);
+ return true;
default:
fprintf(stderr, "error: filesystem type 0x%08x does not have consistent f_fsid\n", (unsigned int)statfs_buf.f_type);
- return 0;
+ return false;
}
}
diff --git a/src/id.h b/src/id.h
index 7c45a64..ae1c788 100644
--- a/src/id.h
+++ b/src/id.h
@@ -1,20 +1,22 @@
// SPDX-License-Identifier: BSD-3-Clause
-#ifndef FSID_H
-#define FSID_H
+#pragma once
#include <sys/types.h>
+#include "random-seed.h"
#include "util.h"
-#if defined(HAVE_UDEV) || defined(HAVE_UTIL_LINUX)
-size_t get_fs_uuid(char **fs_uuid, int seed_fd);
+#if defined(HAVE_LIBUDEV) || defined(HAVE_UTIL_LINUX)
+#define HAVE_FS_UUID
+bool set_rs_device(struct random_seed *rs, int fd);
+const char *get_fs_uuid(struct random_seed *rs);
#endif
-#ifdef HAVE_UDEV
-size_t get_drive_id(char **drive_id, int seed_fd);
-#endif
-size_t get_machine_id(char **machine_id);
-size_t get_fs_id(fsid_t *fs_id, int seed_fd);
-void hash(const unsigned char salt[static SALT_LEN], unsigned char *out, const void *in, size_t size);
+#ifdef HAVE_LIBUDEV
+const char *get_drive_id(struct random_seed *rs);
#endif
+
+const char *get_machine_id();
+bool get_fs_id(fsid_t *fs_id, int fd);
+void hash(const unsigned char salt[static SALT_LEN], unsigned char *out, const void *in, size_t size);
diff --git a/src/id.i b/src/id.i
new file mode 100644
index 0000000..3db4978
--- /dev/null
+++ b/src/id.i
@@ -0,0 +1,3161 @@
+# 1 "src/id.c"
+# 1 "<built-in>"
+# 1 "<command-line>"
+# 1 "/usr/include/stdc-predef.h" 1 3 4
+# 1 "<command-line>" 2
+# 1 "src/id.c"
+
+
+# 1 "/usr/include/assert.h" 1 3 4
+# 35 "/usr/include/assert.h" 3 4
+# 1 "/usr/include/features.h" 1 3 4
+# 428 "/usr/include/features.h" 3 4
+# 1 "/usr/include/sys/cdefs.h" 1 3 4
+# 442 "/usr/include/sys/cdefs.h" 3 4
+# 1 "/usr/include/bits/wordsize.h" 1 3 4
+# 443 "/usr/include/sys/cdefs.h" 2 3 4
+# 1 "/usr/include/bits/long-double.h" 1 3 4
+# 444 "/usr/include/sys/cdefs.h" 2 3 4
+# 429 "/usr/include/features.h" 2 3 4
+# 452 "/usr/include/features.h" 3 4
+# 1 "/usr/include/gnu/stubs.h" 1 3 4
+# 10 "/usr/include/gnu/stubs.h" 3 4
+# 1 "/usr/include/gnu/stubs-64.h" 1 3 4
+# 11 "/usr/include/gnu/stubs.h" 2 3 4
+# 453 "/usr/include/features.h" 2 3 4
+# 36 "/usr/include/assert.h" 2 3 4
+# 64 "/usr/include/assert.h" 3 4
+
+
+
+
+# 67 "/usr/include/assert.h" 3 4
+extern void __assert_fail (const char *__assertion, const char *__file,
+ unsigned int __line, const char *__function)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__));
+
+
+extern void __assert_perror_fail (int __errnum, const char *__file,
+ unsigned int __line, const char *__function)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__));
+
+
+
+
+extern void __assert (const char *__assertion, const char *__file, int __line)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__));
+
+
+
+# 4 "src/id.c" 2
+# 1 "/usr/include/errno.h" 1 3 4
+# 28 "/usr/include/errno.h" 3 4
+# 1 "/usr/include/bits/errno.h" 1 3 4
+# 26 "/usr/include/bits/errno.h" 3 4
+# 1 "/usr/include/linux/errno.h" 1 3 4
+# 1 "/usr/include/asm/errno.h" 1 3 4
+# 1 "/usr/include/asm-generic/errno.h" 1 3 4
+
+
+
+
+# 1 "/usr/include/asm-generic/errno-base.h" 1 3 4
+# 6 "/usr/include/asm-generic/errno.h" 2 3 4
+# 1 "/usr/include/asm/errno.h" 2 3 4
+# 1 "/usr/include/linux/errno.h" 2 3 4
+# 27 "/usr/include/bits/errno.h" 2 3 4
+# 29 "/usr/include/errno.h" 2 3 4
+
+
+
+
+
+
+
+
+extern int *__errno_location (void) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__));
+
+
+
+
+
+
+
+extern char *program_invocation_name;
+extern char *program_invocation_short_name;
+
+# 1 "/usr/include/bits/types/error_t.h" 1 3 4
+# 22 "/usr/include/bits/types/error_t.h" 3 4
+typedef int error_t;
+# 49 "/usr/include/errno.h" 2 3 4
+
+
+
+
+# 5 "src/id.c" 2
+# 1 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include-fixed/limits.h" 1 3 4
+# 34 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include-fixed/limits.h" 3 4
+# 1 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include-fixed/syslimits.h" 1 3 4
+
+
+
+
+
+
+# 1 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include-fixed/limits.h" 1 3 4
+# 194 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include-fixed/limits.h" 3 4
+# 1 "/usr/include/limits.h" 1 3 4
+# 26 "/usr/include/limits.h" 3 4
+# 1 "/usr/include/bits/libc-header-start.h" 1 3 4
+# 27 "/usr/include/limits.h" 2 3 4
+# 183 "/usr/include/limits.h" 3 4
+# 1 "/usr/include/bits/posix1_lim.h" 1 3 4
+# 27 "/usr/include/bits/posix1_lim.h" 3 4
+# 1 "/usr/include/bits/wordsize.h" 1 3 4
+# 28 "/usr/include/bits/posix1_lim.h" 2 3 4
+# 161 "/usr/include/bits/posix1_lim.h" 3 4
+# 1 "/usr/include/bits/local_lim.h" 1 3 4
+# 38 "/usr/include/bits/local_lim.h" 3 4
+# 1 "/usr/include/linux/limits.h" 1 3 4
+# 39 "/usr/include/bits/local_lim.h" 2 3 4
+# 162 "/usr/include/bits/posix1_lim.h" 2 3 4
+# 184 "/usr/include/limits.h" 2 3 4
+
+
+
+# 1 "/usr/include/bits/posix2_lim.h" 1 3 4
+# 188 "/usr/include/limits.h" 2 3 4
+
+
+
+# 1 "/usr/include/bits/xopen_lim.h" 1 3 4
+# 64 "/usr/include/bits/xopen_lim.h" 3 4
+# 1 "/usr/include/bits/uio_lim.h" 1 3 4
+# 65 "/usr/include/bits/xopen_lim.h" 2 3 4
+# 192 "/usr/include/limits.h" 2 3 4
+# 195 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include-fixed/limits.h" 2 3 4
+# 8 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include-fixed/syslimits.h" 2 3 4
+# 35 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include-fixed/limits.h" 2 3 4
+# 6 "src/id.c" 2
+# 1 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/stdbool.h" 1 3 4
+# 7 "src/id.c" 2
+# 1 "/usr/include/stdio.h" 1 3 4
+# 27 "/usr/include/stdio.h" 3 4
+# 1 "/usr/include/bits/libc-header-start.h" 1 3 4
+# 28 "/usr/include/stdio.h" 2 3 4
+
+
+
+
+
+# 1 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/stddef.h" 1 3 4
+# 216 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/stddef.h" 3 4
+typedef long unsigned int size_t;
+# 34 "/usr/include/stdio.h" 2 3 4
+
+
+# 1 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/stdarg.h" 1 3 4
+# 40 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/stdarg.h" 3 4
+typedef __builtin_va_list __gnuc_va_list;
+# 37 "/usr/include/stdio.h" 2 3 4
+
+# 1 "/usr/include/bits/types.h" 1 3 4
+# 27 "/usr/include/bits/types.h" 3 4
+# 1 "/usr/include/bits/wordsize.h" 1 3 4
+# 28 "/usr/include/bits/types.h" 2 3 4
+
+
+typedef unsigned char __u_char;
+typedef unsigned short int __u_short;
+typedef unsigned int __u_int;
+typedef unsigned long int __u_long;
+
+
+typedef signed char __int8_t;
+typedef unsigned char __uint8_t;
+typedef signed short int __int16_t;
+typedef unsigned short int __uint16_t;
+typedef signed int __int32_t;
+typedef unsigned int __uint32_t;
+
+typedef signed long int __int64_t;
+typedef unsigned long int __uint64_t;
+
+
+
+
+
+
+typedef __int8_t __int_least8_t;
+typedef __uint8_t __uint_least8_t;
+typedef __int16_t __int_least16_t;
+typedef __uint16_t __uint_least16_t;
+typedef __int32_t __int_least32_t;
+typedef __uint32_t __uint_least32_t;
+typedef __int64_t __int_least64_t;
+typedef __uint64_t __uint_least64_t;
+
+
+
+typedef long int __quad_t;
+typedef unsigned long int __u_quad_t;
+
+
+
+
+
+
+
+typedef long int __intmax_t;
+typedef unsigned long int __uintmax_t;
+# 140 "/usr/include/bits/types.h" 3 4
+# 1 "/usr/include/bits/typesizes.h" 1 3 4
+# 141 "/usr/include/bits/types.h" 2 3 4
+
+
+typedef unsigned long int __dev_t;
+typedef unsigned int __uid_t;
+typedef unsigned int __gid_t;
+typedef unsigned long int __ino_t;
+typedef unsigned long int __ino64_t;
+typedef unsigned int __mode_t;
+typedef unsigned long int __nlink_t;
+typedef long int __off_t;
+typedef long int __off64_t;
+typedef int __pid_t;
+typedef struct { int __val[2]; } __fsid_t;
+typedef long int __clock_t;
+typedef unsigned long int __rlim_t;
+typedef unsigned long int __rlim64_t;
+typedef unsigned int __id_t;
+typedef long int __time_t;
+typedef unsigned int __useconds_t;
+typedef long int __suseconds_t;
+
+typedef int __daddr_t;
+typedef int __key_t;
+
+
+typedef int __clockid_t;
+
+
+typedef void * __timer_t;
+
+
+typedef long int __blksize_t;
+
+
+
+
+typedef long int __blkcnt_t;
+typedef long int __blkcnt64_t;
+
+
+typedef unsigned long int __fsblkcnt_t;
+typedef unsigned long int __fsblkcnt64_t;
+
+
+typedef unsigned long int __fsfilcnt_t;
+typedef unsigned long int __fsfilcnt64_t;
+
+
+typedef long int __fsword_t;
+
+typedef long int __ssize_t;
+
+
+typedef long int __syscall_slong_t;
+
+typedef unsigned long int __syscall_ulong_t;
+
+
+
+typedef __off64_t __loff_t;
+typedef char *__caddr_t;
+
+
+typedef long int __intptr_t;
+
+
+typedef unsigned int __socklen_t;
+
+
+
+
+typedef int __sig_atomic_t;
+# 39 "/usr/include/stdio.h" 2 3 4
+# 1 "/usr/include/bits/types/__fpos_t.h" 1 3 4
+
+
+
+
+# 1 "/usr/include/bits/types/__mbstate_t.h" 1 3 4
+# 13 "/usr/include/bits/types/__mbstate_t.h" 3 4
+typedef struct
+{
+ int __count;
+ union
+ {
+ unsigned int __wch;
+ char __wchb[4];
+ } __value;
+} __mbstate_t;
+# 6 "/usr/include/bits/types/__fpos_t.h" 2 3 4
+
+
+
+
+typedef struct _G_fpos_t
+{
+ __off_t __pos;
+ __mbstate_t __state;
+} __fpos_t;
+# 40 "/usr/include/stdio.h" 2 3 4
+# 1 "/usr/include/bits/types/__fpos64_t.h" 1 3 4
+# 10 "/usr/include/bits/types/__fpos64_t.h" 3 4
+typedef struct _G_fpos64_t
+{
+ __off64_t __pos;
+ __mbstate_t __state;
+} __fpos64_t;
+# 41 "/usr/include/stdio.h" 2 3 4
+# 1 "/usr/include/bits/types/__FILE.h" 1 3 4
+
+
+
+struct _IO_FILE;
+typedef struct _IO_FILE __FILE;
+# 42 "/usr/include/stdio.h" 2 3 4
+# 1 "/usr/include/bits/types/FILE.h" 1 3 4
+
+
+
+struct _IO_FILE;
+
+
+typedef struct _IO_FILE FILE;
+# 43 "/usr/include/stdio.h" 2 3 4
+# 1 "/usr/include/bits/types/struct_FILE.h" 1 3 4
+# 35 "/usr/include/bits/types/struct_FILE.h" 3 4
+struct _IO_FILE;
+struct _IO_marker;
+struct _IO_codecvt;
+struct _IO_wide_data;
+
+
+
+
+typedef void _IO_lock_t;
+
+
+
+
+
+struct _IO_FILE
+{
+ int _flags;
+
+
+ char *_IO_read_ptr;
+ char *_IO_read_end;
+ char *_IO_read_base;
+ char *_IO_write_base;
+ char *_IO_write_ptr;
+ char *_IO_write_end;
+ char *_IO_buf_base;
+ char *_IO_buf_end;
+
+
+ char *_IO_save_base;
+ char *_IO_backup_base;
+ char *_IO_save_end;
+
+ struct _IO_marker *_markers;
+
+ struct _IO_FILE *_chain;
+
+ int _fileno;
+ int _flags2;
+ __off_t _old_offset;
+
+
+ unsigned short _cur_column;
+ signed char _vtable_offset;
+ char _shortbuf[1];
+
+ _IO_lock_t *_lock;
+
+
+
+
+
+
+
+ __off64_t _offset;
+
+ struct _IO_codecvt *_codecvt;
+ struct _IO_wide_data *_wide_data;
+ struct _IO_FILE *_freeres_list;
+ void *_freeres_buf;
+ size_t __pad5;
+ int _mode;
+
+ char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
+};
+# 44 "/usr/include/stdio.h" 2 3 4
+
+
+# 1 "/usr/include/bits/types/cookie_io_functions_t.h" 1 3 4
+# 27 "/usr/include/bits/types/cookie_io_functions_t.h" 3 4
+typedef __ssize_t cookie_read_function_t (void *__cookie, char *__buf,
+ size_t __nbytes);
+
+
+
+
+
+
+
+typedef __ssize_t cookie_write_function_t (void *__cookie, const char *__buf,
+ size_t __nbytes);
+
+
+
+
+
+
+
+typedef int cookie_seek_function_t (void *__cookie, __off64_t *__pos, int __w);
+
+
+typedef int cookie_close_function_t (void *__cookie);
+
+
+
+
+
+
+typedef struct _IO_cookie_io_functions_t
+{
+ cookie_read_function_t *read;
+ cookie_write_function_t *write;
+ cookie_seek_function_t *seek;
+ cookie_close_function_t *close;
+} cookie_io_functions_t;
+# 47 "/usr/include/stdio.h" 2 3 4
+
+
+
+
+
+typedef __gnuc_va_list va_list;
+# 63 "/usr/include/stdio.h" 3 4
+typedef __off_t off_t;
+
+
+
+
+
+
+typedef __off64_t off64_t;
+
+
+
+
+
+
+typedef __ssize_t ssize_t;
+
+
+
+
+
+
+typedef __fpos_t fpos_t;
+
+
+
+
+typedef __fpos64_t fpos64_t;
+# 133 "/usr/include/stdio.h" 3 4
+# 1 "/usr/include/bits/stdio_lim.h" 1 3 4
+# 134 "/usr/include/stdio.h" 2 3 4
+
+
+
+extern FILE *stdin;
+extern FILE *stdout;
+extern FILE *stderr;
+
+
+
+
+
+
+extern int remove (const char *__filename) __attribute__ ((__nothrow__ , __leaf__));
+
+extern int rename (const char *__old, const char *__new) __attribute__ ((__nothrow__ , __leaf__));
+
+
+
+extern int renameat (int __oldfd, const char *__old, int __newfd,
+ const char *__new) __attribute__ ((__nothrow__ , __leaf__));
+# 164 "/usr/include/stdio.h" 3 4
+extern int renameat2 (int __oldfd, const char *__old, int __newfd,
+ const char *__new, unsigned int __flags) __attribute__ ((__nothrow__ , __leaf__));
+
+
+
+
+
+
+
+extern FILE *tmpfile (void) ;
+# 183 "/usr/include/stdio.h" 3 4
+extern FILE *tmpfile64 (void) ;
+
+
+
+extern char *tmpnam (char *__s) __attribute__ ((__nothrow__ , __leaf__)) ;
+
+
+
+
+extern char *tmpnam_r (char *__s) __attribute__ ((__nothrow__ , __leaf__)) ;
+# 204 "/usr/include/stdio.h" 3 4
+extern char *tempnam (const char *__dir, const char *__pfx)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ;
+
+
+
+
+
+
+
+extern int fclose (FILE *__stream);
+
+
+
+
+extern int fflush (FILE *__stream);
+# 227 "/usr/include/stdio.h" 3 4
+extern int fflush_unlocked (FILE *__stream);
+# 237 "/usr/include/stdio.h" 3 4
+extern int fcloseall (void);
+# 246 "/usr/include/stdio.h" 3 4
+extern FILE *fopen (const char *__restrict __filename,
+ const char *__restrict __modes) ;
+
+
+
+
+extern FILE *freopen (const char *__restrict __filename,
+ const char *__restrict __modes,
+ FILE *__restrict __stream) ;
+# 270 "/usr/include/stdio.h" 3 4
+extern FILE *fopen64 (const char *__restrict __filename,
+ const char *__restrict __modes) ;
+extern FILE *freopen64 (const char *__restrict __filename,
+ const char *__restrict __modes,
+ FILE *__restrict __stream) ;
+
+
+
+
+extern FILE *fdopen (int __fd, const char *__modes) __attribute__ ((__nothrow__ , __leaf__)) ;
+
+
+
+
+
+extern FILE *fopencookie (void *__restrict __magic_cookie,
+ const char *__restrict __modes,
+ cookie_io_functions_t __io_funcs) __attribute__ ((__nothrow__ , __leaf__)) ;
+
+
+
+
+extern FILE *fmemopen (void *__s, size_t __len, const char *__modes)
+ __attribute__ ((__nothrow__ , __leaf__)) ;
+
+
+
+
+extern FILE *open_memstream (char **__bufloc, size_t *__sizeloc) __attribute__ ((__nothrow__ , __leaf__)) ;
+
+
+
+
+
+extern void setbuf (FILE *__restrict __stream, char *__restrict __buf) __attribute__ ((__nothrow__ , __leaf__));
+
+
+
+extern int setvbuf (FILE *__restrict __stream, char *__restrict __buf,
+ int __modes, size_t __n) __attribute__ ((__nothrow__ , __leaf__));
+
+
+
+
+extern void setbuffer (FILE *__restrict __stream, char *__restrict __buf,
+ size_t __size) __attribute__ ((__nothrow__ , __leaf__));
+
+
+extern void setlinebuf (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
+
+
+
+
+
+
+
+extern int fprintf (FILE *__restrict __stream,
+ const char *__restrict __format, ...);
+
+
+
+
+extern int printf (const char *__restrict __format, ...);
+
+extern int sprintf (char *__restrict __s,
+ const char *__restrict __format, ...) __attribute__ ((__nothrow__));
+
+
+
+
+
+extern int vfprintf (FILE *__restrict __s, const char *__restrict __format,
+ __gnuc_va_list __arg);
+
+
+
+
+extern int vprintf (const char *__restrict __format, __gnuc_va_list __arg);
+
+extern int vsprintf (char *__restrict __s, const char *__restrict __format,
+ __gnuc_va_list __arg) __attribute__ ((__nothrow__));
+
+
+
+extern int snprintf (char *__restrict __s, size_t __maxlen,
+ const char *__restrict __format, ...)
+ __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 4)));
+
+extern int vsnprintf (char *__restrict __s, size_t __maxlen,
+ const char *__restrict __format, __gnuc_va_list __arg)
+ __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 0)));
+
+
+
+
+
+extern int vasprintf (char **__restrict __ptr, const char *__restrict __f,
+ __gnuc_va_list __arg)
+ __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 2, 0))) ;
+extern int __asprintf (char **__restrict __ptr,
+ const char *__restrict __fmt, ...)
+ __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 2, 3))) ;
+extern int asprintf (char **__restrict __ptr,
+ const char *__restrict __fmt, ...)
+ __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 2, 3))) ;
+
+
+
+
+extern int vdprintf (int __fd, const char *__restrict __fmt,
+ __gnuc_va_list __arg)
+ __attribute__ ((__format__ (__printf__, 2, 0)));
+extern int dprintf (int __fd, const char *__restrict __fmt, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+
+
+
+
+
+
+
+extern int fscanf (FILE *__restrict __stream,
+ const char *__restrict __format, ...) ;
+
+
+
+
+extern int scanf (const char *__restrict __format, ...) ;
+
+extern int sscanf (const char *__restrict __s,
+ const char *__restrict __format, ...) __attribute__ ((__nothrow__ , __leaf__));
+# 434 "/usr/include/stdio.h" 3 4
+extern int vfscanf (FILE *__restrict __s, const char *__restrict __format,
+ __gnuc_va_list __arg)
+ __attribute__ ((__format__ (__scanf__, 2, 0))) ;
+
+
+
+
+
+extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg)
+ __attribute__ ((__format__ (__scanf__, 1, 0))) ;
+
+
+extern int vsscanf (const char *__restrict __s,
+ const char *__restrict __format, __gnuc_va_list __arg)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__format__ (__scanf__, 2, 0)));
+# 491 "/usr/include/stdio.h" 3 4
+extern int fgetc (FILE *__stream);
+extern int getc (FILE *__stream);
+
+
+
+
+
+extern int getchar (void);
+
+
+
+
+
+
+extern int getc_unlocked (FILE *__stream);
+extern int getchar_unlocked (void);
+# 516 "/usr/include/stdio.h" 3 4
+extern int fgetc_unlocked (FILE *__stream);
+# 527 "/usr/include/stdio.h" 3 4
+extern int fputc (int __c, FILE *__stream);
+extern int putc (int __c, FILE *__stream);
+
+
+
+
+
+extern int putchar (int __c);
+# 543 "/usr/include/stdio.h" 3 4
+extern int fputc_unlocked (int __c, FILE *__stream);
+
+
+
+
+
+
+
+extern int putc_unlocked (int __c, FILE *__stream);
+extern int putchar_unlocked (int __c);
+
+
+
+
+
+
+extern int getw (FILE *__stream);
+
+
+extern int putw (int __w, FILE *__stream);
+
+
+
+
+
+
+
+extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
+ ;
+# 593 "/usr/include/stdio.h" 3 4
+extern char *fgets_unlocked (char *__restrict __s, int __n,
+ FILE *__restrict __stream) ;
+# 609 "/usr/include/stdio.h" 3 4
+extern __ssize_t __getdelim (char **__restrict __lineptr,
+ size_t *__restrict __n, int __delimiter,
+ FILE *__restrict __stream) ;
+extern __ssize_t getdelim (char **__restrict __lineptr,
+ size_t *__restrict __n, int __delimiter,
+ FILE *__restrict __stream) ;
+
+
+
+
+
+
+
+extern __ssize_t getline (char **__restrict __lineptr,
+ size_t *__restrict __n,
+ FILE *__restrict __stream) ;
+
+
+
+
+
+
+
+extern int fputs (const char *__restrict __s, FILE *__restrict __stream);
+
+
+
+
+
+extern int puts (const char *__s);
+
+
+
+
+
+
+extern int ungetc (int __c, FILE *__stream);
+
+
+
+
+
+
+extern size_t fread (void *__restrict __ptr, size_t __size,
+ size_t __n, FILE *__restrict __stream) ;
+
+
+
+
+extern size_t fwrite (const void *__restrict __ptr, size_t __size,
+ size_t __n, FILE *__restrict __s);
+# 668 "/usr/include/stdio.h" 3 4
+extern int fputs_unlocked (const char *__restrict __s,
+ FILE *__restrict __stream);
+# 679 "/usr/include/stdio.h" 3 4
+extern size_t fread_unlocked (void *__restrict __ptr, size_t __size,
+ size_t __n, FILE *__restrict __stream) ;
+extern size_t fwrite_unlocked (const void *__restrict __ptr, size_t __size,
+ size_t __n, FILE *__restrict __stream);
+
+
+
+
+
+
+
+extern int fseek (FILE *__stream, long int __off, int __whence);
+
+
+
+
+extern long int ftell (FILE *__stream) ;
+
+
+
+
+extern void rewind (FILE *__stream);
+# 713 "/usr/include/stdio.h" 3 4
+extern int fseeko (FILE *__stream, __off_t __off, int __whence);
+
+
+
+
+extern __off_t ftello (FILE *__stream) ;
+# 737 "/usr/include/stdio.h" 3 4
+extern int fgetpos (FILE *__restrict __stream, fpos_t *__restrict __pos);
+
+
+
+
+extern int fsetpos (FILE *__stream, const fpos_t *__pos);
+# 756 "/usr/include/stdio.h" 3 4
+extern int fseeko64 (FILE *__stream, __off64_t __off, int __whence);
+extern __off64_t ftello64 (FILE *__stream) ;
+extern int fgetpos64 (FILE *__restrict __stream, fpos64_t *__restrict __pos);
+extern int fsetpos64 (FILE *__stream, const fpos64_t *__pos);
+
+
+
+extern void clearerr (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
+
+extern int feof (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
+
+extern int ferror (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
+
+
+
+extern void clearerr_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
+extern int feof_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
+extern int ferror_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
+
+
+
+
+
+
+
+extern void perror (const char *__s);
+
+
+
+
+
+# 1 "/usr/include/bits/sys_errlist.h" 1 3 4
+# 26 "/usr/include/bits/sys_errlist.h" 3 4
+extern int sys_nerr;
+extern const char *const sys_errlist[];
+
+
+extern int _sys_nerr;
+extern const char *const _sys_errlist[];
+# 788 "/usr/include/stdio.h" 2 3 4
+
+
+
+
+extern int fileno (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
+
+
+
+
+extern int fileno_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
+# 806 "/usr/include/stdio.h" 3 4
+extern FILE *popen (const char *__command, const char *__modes) ;
+
+
+
+
+
+extern int pclose (FILE *__stream);
+
+
+
+
+
+extern char *ctermid (char *__s) __attribute__ ((__nothrow__ , __leaf__));
+
+
+
+
+
+extern char *cuserid (char *__s);
+
+
+
+
+struct obstack;
+
+
+extern int obstack_printf (struct obstack *__restrict __obstack,
+ const char *__restrict __format, ...)
+ __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 2, 3)));
+extern int obstack_vprintf (struct obstack *__restrict __obstack,
+ const char *__restrict __format,
+ __gnuc_va_list __args)
+ __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 2, 0)));
+
+
+
+
+
+
+
+extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
+
+
+
+extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
+
+
+extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
+# 864 "/usr/include/stdio.h" 3 4
+extern int __uflow (FILE *);
+extern int __overflow (FILE *, int);
+
+
+
+
+# 1 "/usr/include/bits/stdio.h" 1 3 4
+# 38 "/usr/include/bits/stdio.h" 3 4
+extern __inline __attribute__ ((__gnu_inline__)) int
+vprintf (const char *__restrict __fmt, __gnuc_va_list __arg)
+{
+ return vfprintf (stdout, __fmt, __arg);
+}
+
+
+
+extern __inline __attribute__ ((__gnu_inline__)) int
+getchar (void)
+{
+ return getc (stdin);
+}
+
+
+
+
+extern __inline __attribute__ ((__gnu_inline__)) int
+fgetc_unlocked (FILE *__fp)
+{
+ return (__builtin_expect (((__fp)->_IO_read_ptr >= (__fp)->_IO_read_end), 0) ? __uflow (__fp) : *(unsigned char *) (__fp)->_IO_read_ptr++);
+}
+
+
+
+
+
+extern __inline __attribute__ ((__gnu_inline__)) int
+getc_unlocked (FILE *__fp)
+{
+ return (__builtin_expect (((__fp)->_IO_read_ptr >= (__fp)->_IO_read_end), 0) ? __uflow (__fp) : *(unsigned char *) (__fp)->_IO_read_ptr++);
+}
+
+
+extern __inline __attribute__ ((__gnu_inline__)) int
+getchar_unlocked (void)
+{
+ return (__builtin_expect (((stdin)->_IO_read_ptr >= (stdin)->_IO_read_end), 0) ? __uflow (stdin) : *(unsigned char *) (stdin)->_IO_read_ptr++);
+}
+
+
+
+
+extern __inline __attribute__ ((__gnu_inline__)) int
+putchar (int __c)
+{
+ return putc (__c, stdout);
+}
+
+
+
+
+extern __inline __attribute__ ((__gnu_inline__)) int
+fputc_unlocked (int __c, FILE *__stream)
+{
+ return (__builtin_expect (((__stream)->_IO_write_ptr >= (__stream)->_IO_write_end), 0) ? __overflow (__stream, (unsigned char) (__c)) : (unsigned char) (*(__stream)->_IO_write_ptr++ = (__c)));
+}
+
+
+
+
+
+extern __inline __attribute__ ((__gnu_inline__)) int
+putc_unlocked (int __c, FILE *__stream)
+{
+ return (__builtin_expect (((__stream)->_IO_write_ptr >= (__stream)->_IO_write_end), 0) ? __overflow (__stream, (unsigned char) (__c)) : (unsigned char) (*(__stream)->_IO_write_ptr++ = (__c)));
+}
+
+
+extern __inline __attribute__ ((__gnu_inline__)) int
+putchar_unlocked (int __c)
+{
+ return (__builtin_expect (((stdout)->_IO_write_ptr >= (stdout)->_IO_write_end), 0) ? __overflow (stdout, (unsigned char) (__c)) : (unsigned char) (*(stdout)->_IO_write_ptr++ = (__c)));
+}
+
+
+
+
+
+extern __inline __attribute__ ((__gnu_inline__)) __ssize_t
+getline (char **__lineptr, size_t *__n, FILE *__stream)
+{
+ return __getdelim (__lineptr, __n, '\n', __stream);
+}
+
+
+
+
+
+extern __inline __attribute__ ((__gnu_inline__)) int
+__attribute__ ((__nothrow__ , __leaf__)) feof_unlocked (FILE *__stream)
+{
+ return (((__stream)->_flags & 0x0010) != 0);
+}
+
+
+extern __inline __attribute__ ((__gnu_inline__)) int
+__attribute__ ((__nothrow__ , __leaf__)) ferror_unlocked (FILE *__stream)
+{
+ return (((__stream)->_flags & 0x0020) != 0);
+}
+# 871 "/usr/include/stdio.h" 2 3 4
+# 879 "/usr/include/stdio.h" 3 4
+
+# 8 "src/id.c" 2
+# 1 "/usr/include/stdlib.h" 1 3 4
+# 25 "/usr/include/stdlib.h" 3 4
+# 1 "/usr/include/bits/libc-header-start.h" 1 3 4
+# 26 "/usr/include/stdlib.h" 2 3 4
+
+
+
+
+
+# 1 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/stddef.h" 1 3 4
+# 328 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/stddef.h" 3 4
+typedef int wchar_t;
+# 32 "/usr/include/stdlib.h" 2 3 4
+
+
+
+
+
+
+
+# 1 "/usr/include/bits/waitflags.h" 1 3 4
+# 40 "/usr/include/stdlib.h" 2 3 4
+# 1 "/usr/include/bits/waitstatus.h" 1 3 4
+# 41 "/usr/include/stdlib.h" 2 3 4
+# 55 "/usr/include/stdlib.h" 3 4
+# 1 "/usr/include/bits/floatn.h" 1 3 4
+# 119 "/usr/include/bits/floatn.h" 3 4
+# 1 "/usr/include/bits/floatn-common.h" 1 3 4
+# 24 "/usr/include/bits/floatn-common.h" 3 4
+# 1 "/usr/include/bits/long-double.h" 1 3 4
+# 25 "/usr/include/bits/floatn-common.h" 2 3 4
+# 120 "/usr/include/bits/floatn.h" 2 3 4
+# 56 "/usr/include/stdlib.h" 2 3 4
+
+
+typedef struct
+ {
+ int quot;
+ int rem;
+ } div_t;
+
+
+
+typedef struct
+ {
+ long int quot;
+ long int rem;
+ } ldiv_t;
+
+
+
+
+
+__extension__ typedef struct
+ {
+ long long int quot;
+ long long int rem;
+ } lldiv_t;
+# 97 "/usr/include/stdlib.h" 3 4
+extern size_t __ctype_get_mb_cur_max (void) __attribute__ ((__nothrow__ , __leaf__)) ;
+
+
+
+extern double atof (const char *__nptr)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ;
+
+extern int atoi (const char *__nptr)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ;
+
+extern long int atol (const char *__nptr)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ;
+
+
+
+__extension__ extern long long int atoll (const char *__nptr)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ;
+
+
+
+extern double strtod (const char *__restrict __nptr,
+ char **__restrict __endptr)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+extern float strtof (const char *__restrict __nptr,
+ char **__restrict __endptr) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+extern long double strtold (const char *__restrict __nptr,
+ char **__restrict __endptr)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+# 140 "/usr/include/stdlib.h" 3 4
+extern _Float32 strtof32 (const char *__restrict __nptr,
+ char **__restrict __endptr)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+extern _Float64 strtof64 (const char *__restrict __nptr,
+ char **__restrict __endptr)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+extern _Float128 strtof128 (const char *__restrict __nptr,
+ char **__restrict __endptr)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+extern _Float32x strtof32x (const char *__restrict __nptr,
+ char **__restrict __endptr)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+extern _Float64x strtof64x (const char *__restrict __nptr,
+ char **__restrict __endptr)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+# 176 "/usr/include/stdlib.h" 3 4
+extern long int strtol (const char *__restrict __nptr,
+ char **__restrict __endptr, int __base)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+extern unsigned long int strtoul (const char *__restrict __nptr,
+ char **__restrict __endptr, int __base)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+__extension__
+extern long long int strtoq (const char *__restrict __nptr,
+ char **__restrict __endptr, int __base)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+__extension__
+extern unsigned long long int strtouq (const char *__restrict __nptr,
+ char **__restrict __endptr, int __base)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+
+__extension__
+extern long long int strtoll (const char *__restrict __nptr,
+ char **__restrict __endptr, int __base)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+__extension__
+extern unsigned long long int strtoull (const char *__restrict __nptr,
+ char **__restrict __endptr, int __base)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+
+extern int strfromd (char *__dest, size_t __size, const char *__format,
+ double __f)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3)));
+
+extern int strfromf (char *__dest, size_t __size, const char *__format,
+ float __f)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3)));
+
+extern int strfroml (char *__dest, size_t __size, const char *__format,
+ long double __f)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3)));
+# 232 "/usr/include/stdlib.h" 3 4
+extern int strfromf32 (char *__dest, size_t __size, const char * __format,
+ _Float32 __f)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3)));
+
+
+
+extern int strfromf64 (char *__dest, size_t __size, const char * __format,
+ _Float64 __f)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3)));
+
+
+
+extern int strfromf128 (char *__dest, size_t __size, const char * __format,
+ _Float128 __f)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3)));
+
+
+
+extern int strfromf32x (char *__dest, size_t __size, const char * __format,
+ _Float32x __f)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3)));
+
+
+
+extern int strfromf64x (char *__dest, size_t __size, const char * __format,
+ _Float64x __f)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3)));
+# 272 "/usr/include/stdlib.h" 3 4
+# 1 "/usr/include/bits/types/locale_t.h" 1 3 4
+# 22 "/usr/include/bits/types/locale_t.h" 3 4
+# 1 "/usr/include/bits/types/__locale_t.h" 1 3 4
+# 28 "/usr/include/bits/types/__locale_t.h" 3 4
+struct __locale_struct
+{
+
+ struct __locale_data *__locales[13];
+
+
+ const unsigned short int *__ctype_b;
+ const int *__ctype_tolower;
+ const int *__ctype_toupper;
+
+
+ const char *__names[13];
+};
+
+typedef struct __locale_struct *__locale_t;
+# 23 "/usr/include/bits/types/locale_t.h" 2 3 4
+
+typedef __locale_t locale_t;
+# 273 "/usr/include/stdlib.h" 2 3 4
+
+extern long int strtol_l (const char *__restrict __nptr,
+ char **__restrict __endptr, int __base,
+ locale_t __loc) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 4)));
+
+extern unsigned long int strtoul_l (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base, locale_t __loc)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 4)));
+
+__extension__
+extern long long int strtoll_l (const char *__restrict __nptr,
+ char **__restrict __endptr, int __base,
+ locale_t __loc)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 4)));
+
+__extension__
+extern unsigned long long int strtoull_l (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __base, locale_t __loc)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 4)));
+
+extern double strtod_l (const char *__restrict __nptr,
+ char **__restrict __endptr, locale_t __loc)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 3)));
+
+extern float strtof_l (const char *__restrict __nptr,
+ char **__restrict __endptr, locale_t __loc)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 3)));
+
+extern long double strtold_l (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ locale_t __loc)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 3)));
+# 316 "/usr/include/stdlib.h" 3 4
+extern _Float32 strtof32_l (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ locale_t __loc)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 3)));
+
+
+
+extern _Float64 strtof64_l (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ locale_t __loc)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 3)));
+
+
+
+extern _Float128 strtof128_l (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ locale_t __loc)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 3)));
+
+
+
+extern _Float32x strtof32x_l (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ locale_t __loc)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 3)));
+
+
+
+extern _Float64x strtof64x_l (const char *__restrict __nptr,
+ char **__restrict __endptr,
+ locale_t __loc)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 3)));
+# 360 "/usr/include/stdlib.h" 3 4
+extern __inline __attribute__ ((__gnu_inline__)) int
+__attribute__ ((__nothrow__ , __leaf__)) atoi (const char *__nptr)
+{
+ return (int) strtol (__nptr, (char **) ((void *)0), 10);
+}
+extern __inline __attribute__ ((__gnu_inline__)) long int
+__attribute__ ((__nothrow__ , __leaf__)) atol (const char *__nptr)
+{
+ return strtol (__nptr, (char **) ((void *)0), 10);
+}
+
+
+__extension__ extern __inline __attribute__ ((__gnu_inline__)) long long int
+__attribute__ ((__nothrow__ , __leaf__)) atoll (const char *__nptr)
+{
+ return strtoll (__nptr, (char **) ((void *)0), 10);
+}
+# 385 "/usr/include/stdlib.h" 3 4
+extern char *l64a (long int __n) __attribute__ ((__nothrow__ , __leaf__)) ;
+
+
+extern long int a64l (const char *__s)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))) ;
+
+
+
+
+# 1 "/usr/include/sys/types.h" 1 3 4
+# 27 "/usr/include/sys/types.h" 3 4
+
+
+
+
+
+
+typedef __u_char u_char;
+typedef __u_short u_short;
+typedef __u_int u_int;
+typedef __u_long u_long;
+typedef __quad_t quad_t;
+typedef __u_quad_t u_quad_t;
+typedef __fsid_t fsid_t;
+
+
+typedef __loff_t loff_t;
+
+
+
+
+typedef __ino_t ino_t;
+
+
+
+
+
+
+typedef __ino64_t ino64_t;
+
+
+
+
+typedef __dev_t dev_t;
+
+
+
+
+typedef __gid_t gid_t;
+
+
+
+
+typedef __mode_t mode_t;
+
+
+
+
+typedef __nlink_t nlink_t;
+
+
+
+
+typedef __uid_t uid_t;
+# 97 "/usr/include/sys/types.h" 3 4
+typedef __pid_t pid_t;
+
+
+
+
+
+typedef __id_t id_t;
+# 114 "/usr/include/sys/types.h" 3 4
+typedef __daddr_t daddr_t;
+typedef __caddr_t caddr_t;
+
+
+
+
+
+typedef __key_t key_t;
+
+
+
+
+# 1 "/usr/include/bits/types/clock_t.h" 1 3 4
+
+
+
+
+
+
+typedef __clock_t clock_t;
+# 127 "/usr/include/sys/types.h" 2 3 4
+
+# 1 "/usr/include/bits/types/clockid_t.h" 1 3 4
+
+
+
+
+
+
+typedef __clockid_t clockid_t;
+# 129 "/usr/include/sys/types.h" 2 3 4
+# 1 "/usr/include/bits/types/time_t.h" 1 3 4
+
+
+
+
+
+
+typedef __time_t time_t;
+# 130 "/usr/include/sys/types.h" 2 3 4
+# 1 "/usr/include/bits/types/timer_t.h" 1 3 4
+
+
+
+
+
+
+typedef __timer_t timer_t;
+# 131 "/usr/include/sys/types.h" 2 3 4
+
+
+
+typedef __useconds_t useconds_t;
+
+
+
+typedef __suseconds_t suseconds_t;
+
+
+
+
+
+# 1 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/stddef.h" 1 3 4
+# 145 "/usr/include/sys/types.h" 2 3 4
+
+
+
+typedef unsigned long int ulong;
+typedef unsigned short int ushort;
+typedef unsigned int uint;
+
+
+
+
+# 1 "/usr/include/bits/stdint-intn.h" 1 3 4
+# 24 "/usr/include/bits/stdint-intn.h" 3 4
+typedef __int8_t int8_t;
+typedef __int16_t int16_t;
+typedef __int32_t int32_t;
+typedef __int64_t int64_t;
+# 156 "/usr/include/sys/types.h" 2 3 4
+# 177 "/usr/include/sys/types.h" 3 4
+typedef unsigned int u_int8_t __attribute__ ((__mode__ (__QI__)));
+typedef unsigned int u_int16_t __attribute__ ((__mode__ (__HI__)));
+typedef unsigned int u_int32_t __attribute__ ((__mode__ (__SI__)));
+typedef unsigned int u_int64_t __attribute__ ((__mode__ (__DI__)));
+
+typedef int register_t __attribute__ ((__mode__ (__word__)));
+# 193 "/usr/include/sys/types.h" 3 4
+# 1 "/usr/include/endian.h" 1 3 4
+# 36 "/usr/include/endian.h" 3 4
+# 1 "/usr/include/bits/endian.h" 1 3 4
+# 37 "/usr/include/endian.h" 2 3 4
+# 60 "/usr/include/endian.h" 3 4
+# 1 "/usr/include/bits/byteswap.h" 1 3 4
+# 33 "/usr/include/bits/byteswap.h" 3 4
+static __inline __uint16_t
+__bswap_16 (__uint16_t __bsx)
+{
+
+ return __builtin_bswap16 (__bsx);
+
+
+
+}
+
+
+
+
+
+
+static __inline __uint32_t
+__bswap_32 (__uint32_t __bsx)
+{
+
+ return __builtin_bswap32 (__bsx);
+
+
+
+}
+# 69 "/usr/include/bits/byteswap.h" 3 4
+__extension__ static __inline __uint64_t
+__bswap_64 (__uint64_t __bsx)
+{
+
+ return __builtin_bswap64 (__bsx);
+
+
+
+}
+# 61 "/usr/include/endian.h" 2 3 4
+# 1 "/usr/include/bits/uintn-identity.h" 1 3 4
+# 32 "/usr/include/bits/uintn-identity.h" 3 4
+static __inline __uint16_t
+__uint16_identity (__uint16_t __x)
+{
+ return __x;
+}
+
+static __inline __uint32_t
+__uint32_identity (__uint32_t __x)
+{
+ return __x;
+}
+
+static __inline __uint64_t
+__uint64_identity (__uint64_t __x)
+{
+ return __x;
+}
+# 62 "/usr/include/endian.h" 2 3 4
+# 194 "/usr/include/sys/types.h" 2 3 4
+
+
+# 1 "/usr/include/sys/select.h" 1 3 4
+# 30 "/usr/include/sys/select.h" 3 4
+# 1 "/usr/include/bits/select.h" 1 3 4
+# 22 "/usr/include/bits/select.h" 3 4
+# 1 "/usr/include/bits/wordsize.h" 1 3 4
+# 23 "/usr/include/bits/select.h" 2 3 4
+# 31 "/usr/include/sys/select.h" 2 3 4
+
+
+# 1 "/usr/include/bits/types/sigset_t.h" 1 3 4
+
+
+
+# 1 "/usr/include/bits/types/__sigset_t.h" 1 3 4
+
+
+
+
+typedef struct
+{
+ unsigned long int __val[(1024 / (8 * sizeof (unsigned long int)))];
+} __sigset_t;
+# 5 "/usr/include/bits/types/sigset_t.h" 2 3 4
+
+
+typedef __sigset_t sigset_t;
+# 34 "/usr/include/sys/select.h" 2 3 4
+
+
+
+# 1 "/usr/include/bits/types/struct_timeval.h" 1 3 4
+
+
+
+
+
+
+
+struct timeval
+{
+ __time_t tv_sec;
+ __suseconds_t tv_usec;
+};
+# 38 "/usr/include/sys/select.h" 2 3 4
+
+# 1 "/usr/include/bits/types/struct_timespec.h" 1 3 4
+# 9 "/usr/include/bits/types/struct_timespec.h" 3 4
+struct timespec
+{
+ __time_t tv_sec;
+ __syscall_slong_t tv_nsec;
+};
+# 40 "/usr/include/sys/select.h" 2 3 4
+# 49 "/usr/include/sys/select.h" 3 4
+typedef long int __fd_mask;
+# 59 "/usr/include/sys/select.h" 3 4
+typedef struct
+ {
+
+
+
+ __fd_mask fds_bits[1024 / (8 * (int) sizeof (__fd_mask))];
+
+
+
+
+
+ } fd_set;
+
+
+
+
+
+
+typedef __fd_mask fd_mask;
+# 91 "/usr/include/sys/select.h" 3 4
+
+# 101 "/usr/include/sys/select.h" 3 4
+extern int select (int __nfds, fd_set *__restrict __readfds,
+ fd_set *__restrict __writefds,
+ fd_set *__restrict __exceptfds,
+ struct timeval *__restrict __timeout);
+# 113 "/usr/include/sys/select.h" 3 4
+extern int pselect (int __nfds, fd_set *__restrict __readfds,
+ fd_set *__restrict __writefds,
+ fd_set *__restrict __exceptfds,
+ const struct timespec *__restrict __timeout,
+ const __sigset_t *__restrict __sigmask);
+# 126 "/usr/include/sys/select.h" 3 4
+
+# 197 "/usr/include/sys/types.h" 2 3 4
+
+
+
+
+
+typedef __blksize_t blksize_t;
+
+
+
+
+
+
+typedef __blkcnt_t blkcnt_t;
+
+
+
+typedef __fsblkcnt_t fsblkcnt_t;
+
+
+
+typedef __fsfilcnt_t fsfilcnt_t;
+# 236 "/usr/include/sys/types.h" 3 4
+typedef __blkcnt64_t blkcnt64_t;
+typedef __fsblkcnt64_t fsblkcnt64_t;
+typedef __fsfilcnt64_t fsfilcnt64_t;
+
+
+
+
+
+# 1 "/usr/include/bits/pthreadtypes.h" 1 3 4
+# 23 "/usr/include/bits/pthreadtypes.h" 3 4
+# 1 "/usr/include/bits/thread-shared-types.h" 1 3 4
+# 77 "/usr/include/bits/thread-shared-types.h" 3 4
+# 1 "/usr/include/bits/pthreadtypes-arch.h" 1 3 4
+# 21 "/usr/include/bits/pthreadtypes-arch.h" 3 4
+# 1 "/usr/include/bits/wordsize.h" 1 3 4
+# 22 "/usr/include/bits/pthreadtypes-arch.h" 2 3 4
+# 65 "/usr/include/bits/pthreadtypes-arch.h" 3 4
+struct __pthread_rwlock_arch_t
+{
+ unsigned int __readers;
+ unsigned int __writers;
+ unsigned int __wrphase_futex;
+ unsigned int __writers_futex;
+ unsigned int __pad3;
+ unsigned int __pad4;
+
+ int __cur_writer;
+ int __shared;
+ signed char __rwelision;
+
+
+
+
+ unsigned char __pad1[7];
+
+
+ unsigned long int __pad2;
+
+
+ unsigned int __flags;
+# 99 "/usr/include/bits/pthreadtypes-arch.h" 3 4
+};
+# 78 "/usr/include/bits/thread-shared-types.h" 2 3 4
+
+
+
+
+typedef struct __pthread_internal_list
+{
+ struct __pthread_internal_list *__prev;
+ struct __pthread_internal_list *__next;
+} __pthread_list_t;
+# 118 "/usr/include/bits/thread-shared-types.h" 3 4
+struct __pthread_mutex_s
+{
+ int __lock ;
+ unsigned int __count;
+ int __owner;
+
+ unsigned int __nusers;
+
+
+
+ int __kind;
+
+
+
+
+
+ short __spins; short __elision;
+ __pthread_list_t __list;
+# 145 "/usr/include/bits/thread-shared-types.h" 3 4
+
+};
+
+
+
+
+struct __pthread_cond_s
+{
+ __extension__ union
+ {
+ __extension__ unsigned long long int __wseq;
+ struct
+ {
+ unsigned int __low;
+ unsigned int __high;
+ } __wseq32;
+ };
+ __extension__ union
+ {
+ __extension__ unsigned long long int __g1_start;
+ struct
+ {
+ unsigned int __low;
+ unsigned int __high;
+ } __g1_start32;
+ };
+ unsigned int __g_refs[2] ;
+ unsigned int __g_size[2];
+ unsigned int __g1_orig_size;
+ unsigned int __wrefs;
+ unsigned int __g_signals[2];
+};
+# 24 "/usr/include/bits/pthreadtypes.h" 2 3 4
+
+
+
+typedef unsigned long int pthread_t;
+
+
+
+
+typedef union
+{
+ char __size[4];
+ int __align;
+} pthread_mutexattr_t;
+
+
+
+
+typedef union
+{
+ char __size[4];
+ int __align;
+} pthread_condattr_t;
+
+
+
+typedef unsigned int pthread_key_t;
+
+
+
+typedef int pthread_once_t;
+
+
+union pthread_attr_t
+{
+ char __size[56];
+ long int __align;
+};
+
+typedef union pthread_attr_t pthread_attr_t;
+
+
+
+
+typedef union
+{
+ struct __pthread_mutex_s __data;
+ char __size[40];
+ long int __align;
+} pthread_mutex_t;
+
+
+typedef union
+{
+ struct __pthread_cond_s __data;
+ char __size[48];
+ __extension__ long long int __align;
+} pthread_cond_t;
+
+
+
+
+
+typedef union
+{
+ struct __pthread_rwlock_arch_t __data;
+ char __size[56];
+ long int __align;
+} pthread_rwlock_t;
+
+typedef union
+{
+ char __size[8];
+ long int __align;
+} pthread_rwlockattr_t;
+
+
+
+
+
+typedef volatile int pthread_spinlock_t;
+
+
+
+
+typedef union
+{
+ char __size[32];
+ long int __align;
+} pthread_barrier_t;
+
+typedef union
+{
+ char __size[4];
+ int __align;
+} pthread_barrierattr_t;
+# 245 "/usr/include/sys/types.h" 2 3 4
+
+
+
+# 395 "/usr/include/stdlib.h" 2 3 4
+
+
+
+
+
+
+extern long int random (void) __attribute__ ((__nothrow__ , __leaf__));
+
+
+extern void srandom (unsigned int __seed) __attribute__ ((__nothrow__ , __leaf__));
+
+
+
+
+
+extern char *initstate (unsigned int __seed, char *__statebuf,
+ size_t __statelen) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2)));
+
+
+
+extern char *setstate (char *__statebuf) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+
+
+
+
+struct random_data
+ {
+ int32_t *fptr;
+ int32_t *rptr;
+ int32_t *state;
+ int rand_type;
+ int rand_deg;
+ int rand_sep;
+ int32_t *end_ptr;
+ };
+
+extern int random_r (struct random_data *__restrict __buf,
+ int32_t *__restrict __result) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+extern int srandom_r (unsigned int __seed, struct random_data *__buf)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2)));
+
+extern int initstate_r (unsigned int __seed, char *__restrict __statebuf,
+ size_t __statelen,
+ struct random_data *__restrict __buf)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2, 4)));
+
+extern int setstate_r (char *__restrict __statebuf,
+ struct random_data *__restrict __buf)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+
+
+
+extern int rand (void) __attribute__ ((__nothrow__ , __leaf__));
+
+extern void srand (unsigned int __seed) __attribute__ ((__nothrow__ , __leaf__));
+
+
+
+extern int rand_r (unsigned int *__seed) __attribute__ ((__nothrow__ , __leaf__));
+
+
+
+
+
+
+
+extern double drand48 (void) __attribute__ ((__nothrow__ , __leaf__));
+extern double erand48 (unsigned short int __xsubi[3]) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+extern long int lrand48 (void) __attribute__ ((__nothrow__ , __leaf__));
+extern long int nrand48 (unsigned short int __xsubi[3])
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+extern long int mrand48 (void) __attribute__ ((__nothrow__ , __leaf__));
+extern long int jrand48 (unsigned short int __xsubi[3])
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+extern void srand48 (long int __seedval) __attribute__ ((__nothrow__ , __leaf__));
+extern unsigned short int *seed48 (unsigned short int __seed16v[3])
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+extern void lcong48 (unsigned short int __param[7]) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+
+
+struct drand48_data
+ {
+ unsigned short int __x[3];
+ unsigned short int __old_x[3];
+ unsigned short int __c;
+ unsigned short int __init;
+ __extension__ unsigned long long int __a;
+
+ };
+
+
+extern int drand48_r (struct drand48_data *__restrict __buffer,
+ double *__restrict __result) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+extern int erand48_r (unsigned short int __xsubi[3],
+ struct drand48_data *__restrict __buffer,
+ double *__restrict __result) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+extern int lrand48_r (struct drand48_data *__restrict __buffer,
+ long int *__restrict __result)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+extern int nrand48_r (unsigned short int __xsubi[3],
+ struct drand48_data *__restrict __buffer,
+ long int *__restrict __result)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+extern int mrand48_r (struct drand48_data *__restrict __buffer,
+ long int *__restrict __result)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+extern int jrand48_r (unsigned short int __xsubi[3],
+ struct drand48_data *__restrict __buffer,
+ long int *__restrict __result)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+extern int srand48_r (long int __seedval, struct drand48_data *__buffer)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2)));
+
+extern int seed48_r (unsigned short int __seed16v[3],
+ struct drand48_data *__buffer) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+extern int lcong48_r (unsigned short int __param[7],
+ struct drand48_data *__buffer)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+
+
+extern void *malloc (size_t __size) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ;
+
+extern void *calloc (size_t __nmemb, size_t __size)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ;
+
+
+
+
+
+
+extern void *realloc (void *__ptr, size_t __size)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__warn_unused_result__));
+
+
+
+
+
+
+
+extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__warn_unused_result__));
+
+
+
+extern void free (void *__ptr) __attribute__ ((__nothrow__ , __leaf__));
+
+
+# 1 "/usr/include/alloca.h" 1 3 4
+# 24 "/usr/include/alloca.h" 3 4
+# 1 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/stddef.h" 1 3 4
+# 25 "/usr/include/alloca.h" 2 3 4
+
+
+
+
+
+
+
+extern void *alloca (size_t __size) __attribute__ ((__nothrow__ , __leaf__));
+
+
+
+
+
+
+# 567 "/usr/include/stdlib.h" 2 3 4
+
+
+
+
+
+extern void *valloc (size_t __size) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ;
+
+
+
+
+extern int posix_memalign (void **__memptr, size_t __alignment, size_t __size)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))) ;
+
+
+
+
+extern void *aligned_alloc (size_t __alignment, size_t __size)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) __attribute__ ((__alloc_size__ (2))) ;
+
+
+
+extern void abort (void) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__));
+
+
+
+extern int atexit (void (*__func) (void)) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+
+
+
+
+extern int at_quick_exit (void (*__func) (void)) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+
+
+
+extern int on_exit (void (*__func) (int __status, void *__arg), void *__arg)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+
+
+extern void exit (int __status) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__));
+
+
+
+
+
+extern void quick_exit (int __status) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__));
+
+
+
+
+
+extern void _Exit (int __status) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__));
+
+
+
+
+extern char *getenv (const char *__name) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))) ;
+
+
+
+
+extern char *secure_getenv (const char *__name)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))) ;
+
+
+
+
+
+
+extern int putenv (char *__string) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+
+
+extern int setenv (const char *__name, const char *__value, int __replace)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2)));
+
+
+extern int unsetenv (const char *__name) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+
+
+
+extern int clearenv (void) __attribute__ ((__nothrow__ , __leaf__));
+# 672 "/usr/include/stdlib.h" 3 4
+extern char *mktemp (char *__template) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+# 685 "/usr/include/stdlib.h" 3 4
+extern int mkstemp (char *__template) __attribute__ ((__nonnull__ (1))) ;
+# 695 "/usr/include/stdlib.h" 3 4
+extern int mkstemp64 (char *__template) __attribute__ ((__nonnull__ (1))) ;
+# 707 "/usr/include/stdlib.h" 3 4
+extern int mkstemps (char *__template, int __suffixlen) __attribute__ ((__nonnull__ (1))) ;
+# 717 "/usr/include/stdlib.h" 3 4
+extern int mkstemps64 (char *__template, int __suffixlen)
+ __attribute__ ((__nonnull__ (1))) ;
+# 728 "/usr/include/stdlib.h" 3 4
+extern char *mkdtemp (char *__template) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))) ;
+# 739 "/usr/include/stdlib.h" 3 4
+extern int mkostemp (char *__template, int __flags) __attribute__ ((__nonnull__ (1))) ;
+# 749 "/usr/include/stdlib.h" 3 4
+extern int mkostemp64 (char *__template, int __flags) __attribute__ ((__nonnull__ (1))) ;
+# 759 "/usr/include/stdlib.h" 3 4
+extern int mkostemps (char *__template, int __suffixlen, int __flags)
+ __attribute__ ((__nonnull__ (1))) ;
+# 771 "/usr/include/stdlib.h" 3 4
+extern int mkostemps64 (char *__template, int __suffixlen, int __flags)
+ __attribute__ ((__nonnull__ (1))) ;
+# 781 "/usr/include/stdlib.h" 3 4
+extern int system (const char *__command) ;
+
+
+
+
+
+extern char *canonicalize_file_name (const char *__name)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))) ;
+# 797 "/usr/include/stdlib.h" 3 4
+extern char *realpath (const char *__restrict __name,
+ char *__restrict __resolved) __attribute__ ((__nothrow__ , __leaf__)) ;
+
+
+
+
+
+
+typedef int (*__compar_fn_t) (const void *, const void *);
+
+
+typedef __compar_fn_t comparison_fn_t;
+
+
+
+typedef int (*__compar_d_fn_t) (const void *, const void *, void *);
+
+
+
+
+extern void *bsearch (const void *__key, const void *__base,
+ size_t __nmemb, size_t __size, __compar_fn_t __compar)
+ __attribute__ ((__nonnull__ (1, 2, 5))) ;
+
+
+# 1 "/usr/include/bits/stdlib-bsearch.h" 1 3 4
+# 19 "/usr/include/bits/stdlib-bsearch.h" 3 4
+extern __inline __attribute__ ((__gnu_inline__)) void *
+bsearch (const void *__key, const void *__base, size_t __nmemb, size_t __size,
+ __compar_fn_t __compar)
+{
+ size_t __l, __u, __idx;
+ const void *__p;
+ int __comparison;
+
+ __l = 0;
+ __u = __nmemb;
+ while (__l < __u)
+ {
+ __idx = (__l + __u) / 2;
+ __p = (void *) (((const char *) __base) + (__idx * __size));
+ __comparison = (*__compar) (__key, __p);
+ if (__comparison < 0)
+ __u = __idx;
+ else if (__comparison > 0)
+ __l = __idx + 1;
+ else
+ return (void *) __p;
+ }
+
+ return ((void *)0);
+}
+# 823 "/usr/include/stdlib.h" 2 3 4
+
+
+
+
+extern void qsort (void *__base, size_t __nmemb, size_t __size,
+ __compar_fn_t __compar) __attribute__ ((__nonnull__ (1, 4)));
+
+extern void qsort_r (void *__base, size_t __nmemb, size_t __size,
+ __compar_d_fn_t __compar, void *__arg)
+ __attribute__ ((__nonnull__ (1, 4)));
+
+
+
+
+extern int abs (int __x) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ;
+extern long int labs (long int __x) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ;
+
+
+__extension__ extern long long int llabs (long long int __x)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ;
+
+
+
+
+
+
+extern div_t div (int __numer, int __denom)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ;
+extern ldiv_t ldiv (long int __numer, long int __denom)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ;
+
+
+__extension__ extern lldiv_t lldiv (long long int __numer,
+ long long int __denom)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__)) ;
+# 869 "/usr/include/stdlib.h" 3 4
+extern char *ecvt (double __value, int __ndigit, int *__restrict __decpt,
+ int *__restrict __sign) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4))) ;
+
+
+
+
+extern char *fcvt (double __value, int __ndigit, int *__restrict __decpt,
+ int *__restrict __sign) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4))) ;
+
+
+
+
+extern char *gcvt (double __value, int __ndigit, char *__buf)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3))) ;
+
+
+
+
+extern char *qecvt (long double __value, int __ndigit,
+ int *__restrict __decpt, int *__restrict __sign)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4))) ;
+extern char *qfcvt (long double __value, int __ndigit,
+ int *__restrict __decpt, int *__restrict __sign)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4))) ;
+extern char *qgcvt (long double __value, int __ndigit, char *__buf)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3))) ;
+
+
+
+
+extern int ecvt_r (double __value, int __ndigit, int *__restrict __decpt,
+ int *__restrict __sign, char *__restrict __buf,
+ size_t __len) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4, 5)));
+extern int fcvt_r (double __value, int __ndigit, int *__restrict __decpt,
+ int *__restrict __sign, char *__restrict __buf,
+ size_t __len) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4, 5)));
+
+extern int qecvt_r (long double __value, int __ndigit,
+ int *__restrict __decpt, int *__restrict __sign,
+ char *__restrict __buf, size_t __len)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4, 5)));
+extern int qfcvt_r (long double __value, int __ndigit,
+ int *__restrict __decpt, int *__restrict __sign,
+ char *__restrict __buf, size_t __len)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (3, 4, 5)));
+
+
+
+
+
+extern int mblen (const char *__s, size_t __n) __attribute__ ((__nothrow__ , __leaf__));
+
+
+extern int mbtowc (wchar_t *__restrict __pwc,
+ const char *__restrict __s, size_t __n) __attribute__ ((__nothrow__ , __leaf__));
+
+
+extern int wctomb (char *__s, wchar_t __wchar) __attribute__ ((__nothrow__ , __leaf__));
+
+
+
+extern size_t mbstowcs (wchar_t *__restrict __pwcs,
+ const char *__restrict __s, size_t __n) __attribute__ ((__nothrow__ , __leaf__));
+
+extern size_t wcstombs (char *__restrict __s,
+ const wchar_t *__restrict __pwcs, size_t __n)
+ __attribute__ ((__nothrow__ , __leaf__));
+
+
+
+
+
+
+
+extern int rpmatch (const char *__response) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1))) ;
+# 954 "/usr/include/stdlib.h" 3 4
+extern int getsubopt (char **__restrict __optionp,
+ char *const *__restrict __tokens,
+ char **__restrict __valuep)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2, 3))) ;
+
+
+
+
+
+
+
+extern int posix_openpt (int __oflag) ;
+
+
+
+
+
+
+
+extern int grantpt (int __fd) __attribute__ ((__nothrow__ , __leaf__));
+
+
+
+extern int unlockpt (int __fd) __attribute__ ((__nothrow__ , __leaf__));
+
+
+
+
+extern char *ptsname (int __fd) __attribute__ ((__nothrow__ , __leaf__)) ;
+
+
+
+
+
+
+extern int ptsname_r (int __fd, char *__buf, size_t __buflen)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2)));
+
+
+extern int getpt (void);
+
+
+
+
+
+
+extern int getloadavg (double __loadavg[], int __nelem)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+# 1010 "/usr/include/stdlib.h" 3 4
+# 1 "/usr/include/bits/stdlib-float.h" 1 3 4
+# 24 "/usr/include/bits/stdlib-float.h" 3 4
+extern __inline __attribute__ ((__gnu_inline__)) double
+__attribute__ ((__nothrow__ , __leaf__)) atof (const char *__nptr)
+{
+ return strtod (__nptr, (char **) ((void *)0));
+}
+# 1011 "/usr/include/stdlib.h" 2 3 4
+# 1020 "/usr/include/stdlib.h" 3 4
+
+# 9 "src/id.c" 2
+# 1 "/usr/include/string.h" 1 3 4
+# 26 "/usr/include/string.h" 3 4
+# 1 "/usr/include/bits/libc-header-start.h" 1 3 4
+# 27 "/usr/include/string.h" 2 3 4
+
+
+
+
+
+
+# 1 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/stddef.h" 1 3 4
+# 34 "/usr/include/string.h" 2 3 4
+# 42 "/usr/include/string.h" 3 4
+extern void *memcpy (void *__restrict __dest, const void *__restrict __src,
+ size_t __n) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+extern void *memmove (void *__dest, const void *__src, size_t __n)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+
+
+
+extern void *memccpy (void *__restrict __dest, const void *__restrict __src,
+ int __c, size_t __n)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+
+
+extern void *memset (void *__s, int __c, size_t __n) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+extern int memcmp (const void *__s1, const void *__s2, size_t __n)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
+# 90 "/usr/include/string.h" 3 4
+extern void *memchr (const void *__s, int __c, size_t __n)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
+# 103 "/usr/include/string.h" 3 4
+extern void *rawmemchr (const void *__s, int __c)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
+# 114 "/usr/include/string.h" 3 4
+extern void *memrchr (const void *__s, int __c, size_t __n)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+
+
+extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+extern char *strncpy (char *__restrict __dest,
+ const char *__restrict __src, size_t __n)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+extern char *strcat (char *__restrict __dest, const char *__restrict __src)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+extern char *strncat (char *__restrict __dest, const char *__restrict __src,
+ size_t __n) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+extern int strcmp (const char *__s1, const char *__s2)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
+
+extern int strncmp (const char *__s1, const char *__s2, size_t __n)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+extern int strcoll (const char *__s1, const char *__s2)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
+
+extern size_t strxfrm (char *__restrict __dest,
+ const char *__restrict __src, size_t __n)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2)));
+
+
+
+
+
+
+extern int strcoll_l (const char *__s1, const char *__s2, locale_t __l)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2, 3)));
+
+
+extern size_t strxfrm_l (char *__dest, const char *__src, size_t __n,
+ locale_t __l) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2, 4)));
+
+
+
+
+
+extern char *strdup (const char *__s)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+
+
+
+extern char *strndup (const char *__string, size_t __n)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) __attribute__ ((__nonnull__ (1)));
+# 225 "/usr/include/string.h" 3 4
+extern char *strchr (const char *__s, int __c)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
+# 252 "/usr/include/string.h" 3 4
+extern char *strrchr (const char *__s, int __c)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
+# 265 "/usr/include/string.h" 3 4
+extern char *strchrnul (const char *__s, int __c)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+
+
+extern size_t strcspn (const char *__s, const char *__reject)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+extern size_t strspn (const char *__s, const char *__accept)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
+# 302 "/usr/include/string.h" 3 4
+extern char *strpbrk (const char *__s, const char *__accept)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
+# 329 "/usr/include/string.h" 3 4
+extern char *strstr (const char *__haystack, const char *__needle)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+
+
+extern char *strtok (char *__restrict __s, const char *__restrict __delim)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2)));
+
+
+
+extern char *__strtok_r (char *__restrict __s,
+ const char *__restrict __delim,
+ char **__restrict __save_ptr)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2, 3)));
+
+extern char *strtok_r (char *__restrict __s, const char *__restrict __delim,
+ char **__restrict __save_ptr)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2, 3)));
+# 359 "/usr/include/string.h" 3 4
+extern char *strcasestr (const char *__haystack, const char *__needle)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+
+
+
+
+
+extern void *memmem (const void *__haystack, size_t __haystacklen,
+ const void *__needle, size_t __needlelen)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 3)));
+
+
+
+extern void *__mempcpy (void *__restrict __dest,
+ const void *__restrict __src, size_t __n)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+extern void *mempcpy (void *__restrict __dest,
+ const void *__restrict __src, size_t __n)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+
+
+extern size_t strlen (const char *__s)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+
+extern size_t strnlen (const char *__string, size_t __maxlen)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+
+extern char *strerror (int __errnum) __attribute__ ((__nothrow__ , __leaf__));
+# 420 "/usr/include/string.h" 3 4
+extern char *strerror_r (int __errnum, char *__buf, size_t __buflen)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2))) ;
+
+
+
+
+
+extern char *strerror_l (int __errnum, locale_t __l) __attribute__ ((__nothrow__ , __leaf__));
+
+
+
+# 1 "/usr/include/strings.h" 1 3 4
+# 23 "/usr/include/strings.h" 3 4
+# 1 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/stddef.h" 1 3 4
+# 24 "/usr/include/strings.h" 2 3 4
+
+
+
+
+
+
+
+
+
+
+extern int bcmp (const void *__s1, const void *__s2, size_t __n)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+extern void bcopy (const void *__src, void *__dest, size_t __n)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+extern void bzero (void *__s, size_t __n) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+# 68 "/usr/include/strings.h" 3 4
+extern char *index (const char *__s, int __c)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
+# 96 "/usr/include/strings.h" 3 4
+extern char *rindex (const char *__s, int __c)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+
+
+
+extern int ffs (int __i) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__));
+
+
+
+
+
+extern int ffsl (long int __l) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__));
+__extension__ extern int ffsll (long long int __ll)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__));
+
+
+
+extern int strcasecmp (const char *__s1, const char *__s2)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+extern int strncasecmp (const char *__s1, const char *__s2, size_t __n)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+
+
+
+
+extern int strcasecmp_l (const char *__s1, const char *__s2, locale_t __loc)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2, 3)));
+
+
+
+extern int strncasecmp_l (const char *__s1, const char *__s2,
+ size_t __n, locale_t __loc)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2, 4)));
+
+
+
+# 432 "/usr/include/string.h" 2 3 4
+
+
+
+extern void explicit_bzero (void *__s, size_t __n) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+
+extern char *strsep (char **__restrict __stringp,
+ const char *__restrict __delim)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+
+
+extern char *strsignal (int __sig) __attribute__ ((__nothrow__ , __leaf__));
+
+
+extern char *__stpcpy (char *__restrict __dest, const char *__restrict __src)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+extern char *stpcpy (char *__restrict __dest, const char *__restrict __src)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+
+extern char *__stpncpy (char *__restrict __dest,
+ const char *__restrict __src, size_t __n)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+extern char *stpncpy (char *__restrict __dest,
+ const char *__restrict __src, size_t __n)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+
+
+extern int strverscmp (const char *__s1, const char *__s2)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+extern char *strfry (char *__string) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+
+
+extern void *memfrob (void *__s, size_t __n) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+# 486 "/usr/include/string.h" 3 4
+extern char *basename (const char *__filename) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));
+# 498 "/usr/include/string.h" 3 4
+
+# 10 "src/id.c" 2
+# 1 "/usr/include/sys/statfs.h" 1 3 4
+# 25 "/usr/include/sys/statfs.h" 3 4
+# 1 "/usr/include/bits/statfs.h" 1 3 4
+# 24 "/usr/include/bits/statfs.h" 3 4
+struct statfs
+ {
+ __fsword_t f_type;
+ __fsword_t f_bsize;
+
+ __fsblkcnt_t f_blocks;
+ __fsblkcnt_t f_bfree;
+ __fsblkcnt_t f_bavail;
+ __fsfilcnt_t f_files;
+ __fsfilcnt_t f_ffree;
+
+
+
+
+
+
+
+ __fsid_t f_fsid;
+ __fsword_t f_namelen;
+ __fsword_t f_frsize;
+ __fsword_t f_flags;
+ __fsword_t f_spare[4];
+ };
+
+
+struct statfs64
+ {
+ __fsword_t f_type;
+ __fsword_t f_bsize;
+ __fsblkcnt64_t f_blocks;
+ __fsblkcnt64_t f_bfree;
+ __fsblkcnt64_t f_bavail;
+ __fsfilcnt64_t f_files;
+ __fsfilcnt64_t f_ffree;
+ __fsid_t f_fsid;
+ __fsword_t f_namelen;
+ __fsword_t f_frsize;
+ __fsword_t f_flags;
+ __fsword_t f_spare[4];
+ };
+# 26 "/usr/include/sys/statfs.h" 2 3 4
+
+
+
+
+
+extern int statfs (const char *__file, struct statfs *__buf)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+# 43 "/usr/include/sys/statfs.h" 3 4
+extern int statfs64 (const char *__file, struct statfs64 *__buf)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1, 2)));
+
+
+
+
+
+extern int fstatfs (int __fildes, struct statfs *__buf)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2)));
+# 61 "/usr/include/sys/statfs.h" 3 4
+extern int fstatfs64 (int __fildes, struct statfs64 *__buf)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2)));
+
+
+
+# 11 "src/id.c" 2
+
+# 1 "/usr/include/sys/vfs.h" 1 3 4
+# 13 "src/id.c" 2
+# 23 "src/id.c"
+# 1 "/home/alex/random-seed/config.h" 1
+# 24 "src/id.c" 2
+# 1 "src/id.h" 1
+
+
+
+
+
+
+
+# 1 "src/sha2.h" 1
+# 39 "src/sha2.h"
+# 1 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/stdint.h" 1 3 4
+# 9 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/stdint.h" 3 4
+# 1 "/usr/include/stdint.h" 1 3 4
+# 26 "/usr/include/stdint.h" 3 4
+# 1 "/usr/include/bits/libc-header-start.h" 1 3 4
+# 27 "/usr/include/stdint.h" 2 3 4
+
+# 1 "/usr/include/bits/wchar.h" 1 3 4
+# 29 "/usr/include/stdint.h" 2 3 4
+# 1 "/usr/include/bits/wordsize.h" 1 3 4
+# 30 "/usr/include/stdint.h" 2 3 4
+
+
+
+
+
+
+
+# 1 "/usr/include/bits/stdint-uintn.h" 1 3 4
+# 24 "/usr/include/bits/stdint-uintn.h" 3 4
+typedef __uint8_t uint8_t;
+typedef __uint16_t uint16_t;
+typedef __uint32_t uint32_t;
+typedef __uint64_t uint64_t;
+# 38 "/usr/include/stdint.h" 2 3 4
+
+
+
+
+
+typedef __int_least8_t int_least8_t;
+typedef __int_least16_t int_least16_t;
+typedef __int_least32_t int_least32_t;
+typedef __int_least64_t int_least64_t;
+
+
+typedef __uint_least8_t uint_least8_t;
+typedef __uint_least16_t uint_least16_t;
+typedef __uint_least32_t uint_least32_t;
+typedef __uint_least64_t uint_least64_t;
+
+
+
+
+
+typedef signed char int_fast8_t;
+
+typedef long int int_fast16_t;
+typedef long int int_fast32_t;
+typedef long int int_fast64_t;
+# 71 "/usr/include/stdint.h" 3 4
+typedef unsigned char uint_fast8_t;
+
+typedef unsigned long int uint_fast16_t;
+typedef unsigned long int uint_fast32_t;
+typedef unsigned long int uint_fast64_t;
+# 87 "/usr/include/stdint.h" 3 4
+typedef long int intptr_t;
+
+
+typedef unsigned long int uintptr_t;
+# 101 "/usr/include/stdint.h" 3 4
+typedef __intmax_t intmax_t;
+typedef __uintmax_t uintmax_t;
+# 10 "/usr/lib/gcc/x86_64-pc-linux-gnu/8.2.0/include/stdint.h" 2 3 4
+# 40 "src/sha2.h" 2
+# 54 "src/sha2.h"
+
+# 54 "src/sha2.h"
+typedef struct {
+ unsigned int tot_len;
+ unsigned int len;
+ unsigned char block[2 * ( 512 / 8)];
+ uint32_t h[8];
+} sha256_ctx;
+
+extern uint32_t sha256_k[64];
+
+void sha256_init(sha256_ctx * ctx);
+void sha256_update(sha256_ctx *ctx, const unsigned char *message,
+ unsigned int len);
+void sha256_final(sha256_ctx *ctx, unsigned char *digest);
+void sha256(const unsigned char *message, unsigned int len,
+ unsigned char *digest);
+# 9 "src/id.h" 2
+# 1 "src/util.h" 1
+# 19 "src/util.h"
+static inline
+# 19 "src/util.h" 3 4
+ _Bool
+# 19 "src/util.h"
+ streq(const char *s1, const char *s2) {
+ return !strcmp(s1, s2);
+}
+# 10 "src/id.h" 2
+
+
+
+char *get_fs_uuid(int seed_fd);
+
+
+
+char *get_drive_id(int seed_fd);
+
+
+char *get_machine_id();
+
+# 21 "src/id.h" 3 4
+_Bool
+# 21 "src/id.h"
+ get_fs_id(fsid_t *fs_id, int seed_fd);
+void hash(const unsigned char salt[static 512], unsigned char *out, const void *in, size_t size);
+# 25 "src/id.c" 2
+
+
+static const char *MACHINE_ID_PATHS[] = {"/etc/machine-id", "/var/lib/dbus/machine-id"};
+
+
+char *get_fs_uuid_udev(dev_t dev) {
+ struct udev *udev = udev_new();
+ if (!udev) {
+ fputs("error: failed to allocate udev context\n",
+# 33 "src/id.c" 3 4
+ stderr
+# 33 "src/id.c"
+ );
+ return
+# 34 "src/id.c" 3 4
+ ((void *)0)
+# 34 "src/id.c"
+ ;
+ }
+
+ struct udev_device *udev_dev = udev_device_new_from_devnum(udev, 'b', dev);
+ if (!udev_dev) {
+ perror("warning: failed to get seed file udev device\n",
+# 39 "src/id.c" 3 4
+ stderr
+# 39 "src/id.c"
+ );
+ return
+# 40 "src/id.c" 3 4
+ ((void *)0)
+# 40 "src/id.c"
+ ;
+ }
+
+ return
+# 43 "src/id.c" 3 4
+ ((void *)0)
+# 43 "src/id.c"
+ ;
+}
+
+char *get_drive_id(dev_t dev) {
+ return strdup("TODO: implement");
+}
+
+
+
+char *get_fs_uuid_util_linux(dev_t dev) {
+ return strdup("TODO: implement");
+}
+
+
+
+char *get_fs_uuid(dev_t dev) {
+ char *rv = get_fs_uuid_udev(seed_fd);
+ if (!rv)
+ rv = get_fs_uuid_util_linux(seed_fd);
+ return rv;
+}
+# 74 "src/id.c"
+static char *really_get_machine_id() {
+ FILE *machine_id_file;
+ for (size_t i = 0; i < (sizeof(MACHINE_ID_PATHS)/sizeof(MACHINE_ID_PATHS[0])); i++) {
+ machine_id_file = fopen(MACHINE_ID_PATHS[i], "r");
+ if (!machine_id_file)
+ fprintf(
+# 79 "src/id.c" 3 4
+ stderr
+# 79 "src/id.c"
+ , "warning: failed to open machine id %s: %s\n", MACHINE_ID_PATHS[i], strerror(
+# 79 "src/id.c" 3 4
+ (*__errno_location ())
+# 79 "src/id.c"
+ ));
+ }
+ if (!machine_id_file) {
+ fputs("error: failed to open all machine id files\n",
+# 82 "src/id.c" 3 4
+ stderr
+# 82 "src/id.c"
+ );
+ return
+# 83 "src/id.c" 3 4
+ ((void *)0)
+# 83 "src/id.c"
+ ;
+ }
+
+ char *machine_id =
+# 86 "src/id.c" 3 4
+ ((void *)0)
+# 86 "src/id.c"
+ ;
+ size_t machine_id_len = 0;
+ if (getdelim(&machine_id, &machine_id_len, '\0', machine_id_file) == -1) {
+ fputs("error reading machine id file\n",
+# 89 "src/id.c" 3 4
+ stderr
+# 89 "src/id.c"
+ );
+ free(machine_id);
+ return
+# 91 "src/id.c" 3 4
+ ((void *)0)
+# 91 "src/id.c"
+ ;
+ }
+
+ return machine_id;
+}
+
+const char *get_machine_id() {
+ static char *c_machine_id;
+ if (!c_machine_id)
+ c_machine_id = really_get_machine_id();
+ return c_machine_id;
+}
+
+
+# 104 "src/id.c" 3 4
+_Bool
+# 104 "src/id.c"
+ get_fs_id(fsid_t *fs_id, int seed_fd) {
+ struct statfs statfs_buf;
+ if (fstatfs(seed_fd, &statfs_buf) == -1) {
+ perror("error: statfs seed file: %s");
+ return
+# 108 "src/id.c" 3 4
+ 0
+# 108 "src/id.c"
+ ;
+ }
+
+ switch (statfs_buf.f_type) {
+ case 0x9123683e:
+ case 0xef53:
+ case 0x3153464a:
+ case 0x5346544e:
+ case 0x52654973:
+ case 0x24051905:
+ memcpy(fs_id, &statfs_buf.f_fsid, sizeof(fsid_t));
+ return
+# 119 "src/id.c" 3 4
+ 1
+# 119 "src/id.c"
+ ;
+ default:
+ fprintf(
+# 121 "src/id.c" 3 4
+ stderr
+# 121 "src/id.c"
+ , "error: filesystem type 0x%08x does not have consistent f_fsid\n", (unsigned int)statfs_buf.f_type);
+ return
+# 122 "src/id.c" 3 4
+ 0
+# 122 "src/id.c"
+ ;
+ }
+}
+
+void hash(const unsigned char salt[static 512], unsigned char out[static 32], const void *in, size_t size) {
+
+# 127 "src/id.c" 3 4
+ ((void) sizeof ((
+# 127 "src/id.c"
+ size < 0x7fffffff - 512 - 100
+# 127 "src/id.c" 3 4
+ ) ? 1 : 0), __extension__ ({ if (
+# 127 "src/id.c"
+ size < 0x7fffffff - 512 - 100
+# 127 "src/id.c" 3 4
+ ) ; else __assert_fail (
+# 127 "src/id.c"
+ "size < INT_MAX - SALT_LEN - 100"
+# 127 "src/id.c" 3 4
+ , "src/id.c", 127, __extension__ __PRETTY_FUNCTION__); }))
+# 127 "src/id.c"
+ ;
+ sha256_ctx ctx;
+ sha256_init(&ctx);
+ sha256_update(&ctx, salt, 512);
+ sha256_update(&ctx, in, (unsigned int)size);
+ sha256_final(&ctx, out);
+}
diff --git a/src/load.c b/src/load.c
new file mode 100644
index 0000000..e04f5e4
--- /dev/null
+++ b/src/load.c
@@ -0,0 +1,257 @@
+#include "config.h"
+
+#include "id.h"
+#include "util.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#define RNDADDENTROPY _IOW( 'R', 0x03, int [2] )
+
+/* random pool is always the same size, so use a fixed size array */
+struct rand_pool_info_ {
+ int entropy_count;
+ int buf_size;
+ uint32_t buf[RAND_POOL_SIZE / sizeof(uint32_t)];
+};
+
+bool noperms;
+
+static inline signed char hexchr2int(char c) {
+ /* No, nobody uses EBCDIC anymore. */
+ return (c >= '0' && c <= '9') ? (c - '0') :
+ (c >= 'a' && c <= 'f') ? (c - 'a' + 10) :
+ (c >= 'A' && c <= 'F') ? (c - 'A' + 10) :
+ -1;
+}
+
+/**
+ * Decode hex.
+ *
+ * \param dest where to store the decoded data
+ * \param size the maximum number of bytes to decode
+ * \param src the hex-encoded data
+ *
+ * \return 0 if an error occurred, otherwise size
+ */
+static size_t hex2mem(unsigned char *dest, size_t size, const char *src) {
+ size_t i;
+ for (i = 0; i < size; i++) {
+ int n1 = hexchr2int(src[2*i]);
+ if (n1 < 0) return 0;
+ int n2 = hexchr2int(src[2*i+1]);
+ if (n2 < 0) return 0;
+ dest[i] = (unsigned char)(n1 << 4 | n2);
+ }
+ return i;
+}
+
+static bool match_cmd_with_arg(const char *cmd, const char *my_cmd, char **arg) {
+ if (!streq(cmd, my_cmd))
+ return false;
+
+ *arg = strtok(NULL, " \t");
+ if (!arg) {
+ fprintf(stderr, "error parsing seed file: expected argument to '%s'\n", my_cmd);
+ return false;
+ }
+
+ return true;
+}
+
+static bool hash_match(const unsigned char salt[static SALT_LEN], const void *buf, size_t buflen, const char theirhash[static HASH_STR_LEN]) {
+ if (streq(theirhash, "none")) {
+ return buf == NULL;
+ }
+ if (!buf)
+ return false;
+ unsigned char mydigest[HASH_LEN];
+ hash(salt, mydigest, buf, buflen);
+ unsigned char theirdigest[HASH_LEN];
+ if (hex2mem(theirdigest, HASH_LEN, theirhash) != HASH_LEN) {
+ fputs("error decoding hex hash\n", stderr);
+ return false;
+ }
+ if (memcmp(mydigest, theirdigest, HASH_LEN)) {
+ fputs("hash does not match\n", stderr);
+ return false;
+ }
+ return true;
+}
+
+bool load(const char *seed_path) {
+ struct random_seed rs = {0};
+
+ if (streq(seed_path, "-")) {
+ rs.file = stdin;
+ } else {
+ rs.file = fopen(seed_path, "r");
+ if (!rs.file) {
+ perror("error opening seed file");
+ exit(1);
+ }
+ }
+
+ bool credit_entropy = true;
+
+ struct rand_pool_info_ rpi = {
+ .entropy_count = RAND_POOL_SIZE * CHAR_BIT,
+ .buf_size = RAND_POOL_SIZE,
+ .buf = { 0 }
+ };
+
+ uint64_t linenum = 0;
+ char *line = NULL;
+ size_t n = 0;
+ bool done = false;
+
+ if (fread(&rpi.buf, 1, RAND_POOL_SIZE, rs.file) != RAND_POOL_SIZE) {
+ if (feof(rs.file)) {
+ fputs("premature EOF on seed file\n", stderr);
+ } else if (ferror(rs.file)) {
+ fputs("error reading from seed file\n", stderr);
+ }
+ // else: we got signalled, so return to main loop to quit or whatever
+ return false;
+ }
+
+ unsigned char *salt = (unsigned char *)rpi.buf;
+
+ while (1) {
+ errno = 0;
+ ssize_t line_length = getline(&line, &n, rs.file);
+ if (line_length == -1) {
+ if (errno) {
+ perror("error reading from seed file");
+ credit_entropy = false;
+ }
+ break;
+ }
+
+ linenum++;
+
+ if (linenum == 1) {
+ if (streq(line, MAGIC)) {
+ continue;
+ } else {
+ fputs("error parsing seed file: invalid magic\n", stderr);
+ credit_entropy = false;
+ break;
+ }
+ }
+
+ char *nul = memchr(line, '\0', (size_t)line_length);
+ if (nul) {
+ fprintf(stderr, "error parsing seed file: encountered NUL byte in commands line %zu char %zu\n", linenum, nul - line + 1);
+ credit_entropy = false;
+ break;
+ }
+
+ char *cmd = strtok(line, " \t\n");
+ if (!cmd)
+ /* empty line */
+ continue;
+
+ if (streq(cmd, "done")) {
+ done = true;
+ break;
+ }
+
+ char *arg;
+
+ if (match_cmd_with_arg(cmd, "machine-id", &arg)) {
+ const char *machine_id = get_machine_id(&machine_id);
+ if (!machine_id) {
+ credit_entropy = false;
+ break;
+ }
+ return hash_match(salt, machine_id, strlen(machine_id), arg);
+ }
+
+ if (match_cmd_with_arg(cmd, "fs-id", &arg)) {
+ fsid_t fs_id;
+ credit_entropy = hash_match(
+ salt,
+ get_fs_id(&fs_id, fileno(rs.file)) ? &fs_id : NULL,
+ sizeof(fs_id),
+ arg
+ );
+ break;
+ }
+
+#if defined(HAVE_LIBUDEV) || defined(HAVE_UTIL_LINUX)
+ if (match_cmd_with_arg(cmd, "fs-uuid", &arg)) {
+ const char *fs_uuid = get_fs_uuid(&rs);
+ credit_entropy = hash_match(salt, fs_uuid, fs_uuid ? strlen(fs_uuid) : 0, arg);
+ break;
+ }
+#else
+ if (streq(cmd, "fs-uuid")) {
+ fputs("error: fs-uuid disabled at compile time\n", stderr);
+ credit_entropy = false;
+ break;
+ }
+#endif
+
+#ifdef HAVE_LIBUDEV
+ if (match_cmd_with_arg(cmd, "drive-id", &arg)) {
+ const char *drive_id = get_drive_id(&rs);
+ credit_entropy = hash_match(salt, drive_id, drive_id ? strlen(drive_id) : 0, arg);
+ break;
+ }
+#else
+ if (streq(cmd, "drive-id")) {
+ fputs("error: drive-id disabled at compile time\n", stderr);
+ credit_entropy = false;
+ break;
+ }
+#endif
+
+ fprintf(stderr, "error parsing seed file: unsupported command: %s\n", cmd);
+ credit_entropy = false;
+ break;
+ }
+
+ if (!linenum) {
+ fputs("seed file has no commands, assuming legacy format. disabling entropy credit\n", stderr);
+ credit_entropy = false;
+ }
+
+ if (credit_entropy && !done) {
+ fputs("missing done command, random seed file probably truncated. disabling entropy credit\n", stderr);
+ credit_entropy = false;
+ }
+
+ int random_fd = open("/dev/random", O_RDWR, 0);
+ if (random_fd == -1) {
+ perror("error opening /dev/random");
+ exit(1);
+ }
+
+ if (credit_entropy) {
+ if (ioctl(random_fd, RNDADDENTROPY, &rpi) == -1) {
+ perror("ioctl(RNDADDENTROPY)");
+ if (errno == EPERM) {
+ fputs("Continuing without crediting entropy.\n", stderr);
+ noperms = true;
+ }
+ credit_entropy = false;
+ }
+ }
+
+ if (!credit_entropy) {
+ if (write(random_fd, &rpi.buf, RAND_POOL_SIZE) != RAND_POOL_SIZE) {
+ fputs("error writing entropy to /dev/random\n", stderr);
+ exit(1);
+ }
+ }
+
+ return credit_entropy;
+}
+
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..6914de0
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,61 @@
+#include "config.h"
+
+#include "random-seed.h"
+#include "util.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+
+static inline void usage() {
+ puts("usage: random-seed MODE FILE");
+ puts("see random-seed(8) for more information.");
+}
+
+static inline void caprlimit(int resource, rlim_t rlimit) {
+ struct rlimit rlim;
+ if (getrlimit(resource, &rlim) == -1) {
+ perror("warning: couldn't get resource limit");
+ return;
+ }
+ if (rlim.rlim_cur > rlimit) {
+ rlim.rlim_cur = rlimit;
+ if (setrlimit(resource, &rlim) == -1) {
+ perror("warning: couldn't set resource limit");
+ return;
+ }
+ }
+}
+
+int main(int argc, char *argv[]) {
+ char *mode, *seed_path;
+
+ switch (argc) {
+ case 2:
+ if (streq(argv[1], "-h") || streq(argv[1], "--help")) {
+ usage();
+ exit(0);
+ }
+ if (streq(argv[1], "-V") || streq(argv[1], "--version")) {
+ printf("random-seed %s\n", PACKAGE_VERSION);
+ exit(0);
+ }
+ mode = argv[1];
+ seed_path = DEFAULT_SEED_PATH;
+ break;
+ case 3:
+ mode = argv[1];
+ seed_path = argv[2];
+ break;
+ default:
+ fprintf(stderr, "error: invalid arguments\n");
+ usage();
+ exit(2);
+ }
+
+ umask(0);
+ caprlimit(RLIMIT_DATA, 32*1024*1024);
+ caprlimit(RLIMIT_FSIZE, 1*1024*1024);
+ run(mode, seed_path);
+}
diff --git a/src/musl-libgen-c.h b/src/musl-libgen-c.h
index d947197..963d535 100644
--- a/src/musl-libgen-c.h
+++ b/src/musl-libgen-c.h
@@ -24,8 +24,7 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef MUSL_LIBGEN_H
-#define MUSL_LIBGEN_H
+#pragma once
#include <string.h>
@@ -50,5 +49,3 @@ static inline char *mydirname(char *s)
s[i+1] = 0;
return s;
}
-
-#endif
diff --git a/src/random-seed.c b/src/random-seed.c
index dd1c447..9b04b9b 100644
--- a/src/random-seed.c
+++ b/src/random-seed.c
@@ -1,442 +1,63 @@
// SPDX-License-Identifier: BSD-3-Clause
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdnoreturn.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-
#include "config.h"
-#include "id.h"
-#include "musl-libgen-c.h"
+#include "random-seed.h"
#include "util.h"
-// musl forbids include/linux
-#define RNDADDENTROPY _IOW( 'R', 0x03, int [2] )
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
/* 3 hours */
#define DAEMONIZE_SLEEP_TIME (3*60*60)
-/* random pool is always the same size, so use a fixed size array */
-struct rand_pool_info_ {
- int entropy_count;
- int buf_size;
- uint32_t buf[RAND_POOL_SIZE / sizeof(uint32_t)];
-};
-
-static const char MAGIC[] = "RANDOM SEED FILE VERSION 1\n";
-
static sig_atomic_t sigint = 0;
static sig_atomic_t sigterm = 0;
-static bool noperms = false;
-
-static inline void usage() {
- puts("usage: random-seed MODE FILE");
- puts("see random-seed(8) for more information.");
-}
-
-static bool run_seed_file_cmd(const char *cmd, const unsigned char *salt, FILE *seed_file) {
-#define HASH_ID_CMD(my_cmd, type, fn, data_accessor, ...) \
- do { \
- if (!streq(cmd, my_cmd)) \
- break; \
- char *arg = strtok(NULL, " \t"); \
- if (!arg) { \
- fputs("error parsing seed file: expected argument " \
- "to '" my_cmd "'\n", stderr); \
- return false; \
- } \
- type fn ## _buf; \
- unsigned char fn ## _hash[HASH_LEN]; \
- size_t sz = fn(&fn ## _buf, ##__VA_ARGS__); \
- if (sz == 0) { \
- fputs("error getting " my_cmd " hash\n", stderr); \
- return false; \
- } \
- hash(salt, fn ## _hash, data_accessor fn ## _buf, sz); \
- unsigned char theirdigest[HASH_LEN]; \
- if (hex2mem(theirdigest, HASH_LEN, arg) == 0) { \
- fputs("error decoding hex hash\n", stderr); \
- exit(1); \
- } \
- if (memcmp(fn ## _hash, theirdigest, HASH_LEN)) { \
- fputs(my_cmd " hash does not match\n", stderr); \
- return false; \
- } \
- return true; \
- } while (0)
-
- HASH_ID_CMD("machine-id", char *, get_machine_id, );
- HASH_ID_CMD("fs-id", fsid_t, get_fs_id, &, fileno(seed_file));
-#if defined(HAVE_LIBUDEV) || defined(HAVE_UTIL_LINUX)
- HASH_ID_CMD("fs-uuid", char *, get_fs_uuid, fileno(seed_file));
-#else
- if (streq(cmd, "fs-uuid")) {
- fputs("error: fs-uuid not supported by this random-seed\n", stderr);
- return false;
- }
-#endif
-#ifdef HAVE_LIBUDEV
- HASH_ID_CMD("drive-id", char *, get_drive_id, fileno(seed_file));
-#else
- if (streq(cmd, "drive-id")) {
- fputs("error: drive-id not supported by this random-seed\n", stderr);
- return false;
- }
-#endif
- fprintf(stderr, "error parsing seed file: unsupported command: %s\n", cmd);
- return false;
-}
-
-static bool load(FILE *seed_file) {
- bool credit_entropy = true;
-
- struct rand_pool_info_ rpi = {
- .entropy_count = RAND_POOL_SIZE * CHAR_BIT,
- .buf_size = RAND_POOL_SIZE,
- .buf = { 0 }
- };
-
- uint64_t linenum = 0;
- char *line = NULL;
- size_t n = 0;
- bool done = false;
-
- if (fread(&rpi.buf, 1, RAND_POOL_SIZE, seed_file) != RAND_POOL_SIZE) {
- if (feof(seed_file)) {
- fputs("premature EOF on seed file\n", stderr);
- } else if (ferror(seed_file)) {
- fputs("error reading from seed file\n", stderr);
- }
- // else: we got signalled, so return to main loop to quit or whatever
- return false;
- }
-
- unsigned char *salt = (unsigned char *)rpi.buf;
-
- while (1) {
- errno = 0;
- ssize_t line_length = getline(&line, &n, seed_file);
- if (line_length == -1) {
- if (errno) {
- perror("error reading from seed file");
- credit_entropy = false;
- }
- break;
- }
-
- linenum++;
-
- if (linenum == 1) {
- if (streq(line, MAGIC)) {
- continue;
- } else {
- fputs("error parsing seed file: invalid magic\n", stderr);
- credit_entropy = false;
- break;
- }
- }
-
- char *nul = memchr(line, '\0', (size_t)line_length);
- if (nul) {
- fprintf(stderr, "error parsing seed file: encountered NUL byte in commands line %zu char %zu\n", linenum, nul - line + 1);
- credit_entropy = false;
- break;
- }
-
- char *cmd = strtok(line, " \t\n");
- if (!cmd)
- continue;
-
-#ifdef DEBUG
- fprintf(stderr, "executing command: %s\n", cmd);
-#endif
-
- if (streq(cmd, "done")) {
- done = true;
- continue;
- }
-
- if (!run_seed_file_cmd(cmd, salt, seed_file)) {
- credit_entropy = false;
- break;
- }
- }
-
- if (!linenum) {
- fputs("seed file has no commands, assuming legacy format. disabling entropy credit\n", stderr);
- credit_entropy = false;
- }
-
- if (credit_entropy && !done) {
- fputs("missing done command, random seed file probably truncated. disabling entropy credit\n", stderr);
- credit_entropy = false;
- }
-
- int random_fd = open("/dev/random", O_RDWR, 0);
- if (random_fd == -1) {
- perror("error opening /dev/random");
- exit(1);
- }
-
- if (credit_entropy) {
- if (ioctl(random_fd, RNDADDENTROPY, &rpi) == -1) {
- perror("ioctl(RNDADDENTROPY)");
- if (errno == EPERM) {
- fputs("Continuing without crediting entropy.\n", stderr);
- noperms = true;
- }
- credit_entropy = false;
- }
- }
-
- if (!credit_entropy) {
- if (write(random_fd, &rpi.buf, RAND_POOL_SIZE) != RAND_POOL_SIZE) {
- fputs("error writing entropy to /dev/random\n", stderr);
- exit(1);
- }
- }
-
- return credit_entropy;
-}
-
-static bool get_rand_pool(unsigned char *buf) {
- size_t rand_bytes_gotten = 0;
-
- do {
- long this_rand_bytes_gotten = random_get(buf + rand_bytes_gotten, RAND_POOL_SIZE - rand_bytes_gotten, 0);
- if (this_rand_bytes_gotten == -1) {
- switch (errno) {
- case EAGAIN: continue;
- case EINTR: return false;
- default:
- perror("getrandom");
- exit(1);
- }
- } else {
- rand_bytes_gotten += (size_t)this_rand_bytes_gotten;
- }
- } while (rand_bytes_gotten < RAND_POOL_SIZE);
-
- return true;
-}
-
-/**
- * Save entropy to disk.
- *
- * \param seed_path the seed file path
- * \param random_buf the random buffer. if NULL, get our own entropy.
- * \return true means saved successfully, false means received EINTR
- */
-static bool save(const char *seed_path, unsigned char *random_buf) {
- assert(seed_path);
-
- bool rv = false;
-
- unsigned char *random_ptr;
- if (random_buf) {
- random_ptr = random_buf;
- } else {
- random_ptr = alloca(RAND_POOL_SIZE);
- if (!get_rand_pool(random_ptr))
- return false;
- }
-
-#define GET_HASH_STR(type, hash_access, name, ...) \
- char name ## _hash[HASH_STR_LEN]; \
- do { \
- type name ## _buf; \
- size_t name ## _len = get_ ## name(&name ## _buf, ##__VA_ARGS__); \
- if (!name ## _len) { \
- fputs("error obtaining " #name " \n", stderr); \
- return false; \
- } \
- unsigned char name ## _digest[HASH_LEN]; \
- hash(random_ptr, name ## _digest, hash_access name ## _buf, name ## _len); \
- mem2hex(name ## _hash, name ## _digest, HASH_LEN); \
- } while (0)
-
- GET_HASH_STR(char *, , machine_id);
-
- int seed_dir_fd = -1;
- int seed_fd = -1;
- FILE *seed_file = NULL;
-
- char *seed_path_tmp = strdup(seed_path);
- const char *seed_dir, *seed_name;
- char *seed_path_last_slash = strrchr(seed_path_tmp, '/');
- if (seed_path_last_slash) {
- *seed_path_last_slash = '\0';
- seed_dir = seed_path_tmp;
- seed_name = seed_path_last_slash + 1;
- } else {
- free(seed_path_tmp);
- seed_path_tmp = NULL;
- seed_dir = ".";
- seed_name = seed_path;
- }
- char *seed_name_new = NULL;
-
- if (asprintf(&seed_name_new, ".%s.new", seed_name) == -1) {
- fputs("out of memory\n", stderr);
- goto out;
- }
-
- seed_dir_fd = open(seed_dir, O_RDONLY | O_DIRECTORY);
- if (seed_dir_fd == -1) {
- perror("error opening seed directory");
- goto out;
- }
-
- GET_HASH_STR(fsid_t, &, fs_id, seed_dir_fd);
-#ifdef HAVE_LIBUDEV
- GET_HASH_STR(char *, , drive_id, seed_dir_fd);
-#endif
-#if defined(HAVE_LIBUDEV) || defined(HAVE_UTIL_LINUX)
- GET_HASH_STR(char *, , fs_uuid, seed_dir_fd);
-#endif
-
- seed_fd = openat(seed_dir_fd, seed_name_new, O_WRONLY | O_CREAT | O_TRUNC, 0600);
- if (seed_fd == -1) {
- perror("error opening new seed file");
- goto err;
- }
- seed_file = fdopen(seed_fd, "w");
- if (!seed_file) {
- perror("error converting seed file fd to stream");
- goto err;
- }
-
- if (fwrite(random_ptr, 1, RAND_POOL_SIZE, seed_file) != RAND_POOL_SIZE
- || fputs(MAGIC, seed_file) == EOF
- || fputs("machine-id ", seed_file) == EOF
- || fputs(machine_id_hash, seed_file) == EOF
- || fputs("\nfs-id ", seed_file) == EOF
- || fputs(fs_id_hash, seed_file) == EOF
- || fputs("\ndone\n", seed_file) == EOF) {
- fputs("error writing new seed file\n", stderr);
- goto err;
- }
-
- if (fflush(seed_file) == EOF) {
- perror("error flushing new seed file");
- goto err;
- }
- if (fsync(seed_fd) == -1) {
- perror("error syncing new seed file");
- goto err;
- }
- if (renameat(seed_dir_fd, seed_name_new, seed_dir_fd, seed_name) == -1) {
- perror("error installing new seed file");
- goto err;
- }
- if (fclose(seed_file) == EOF) {
- perror("error closing new seed file");
- goto err;
- }
- if (fsync(seed_dir_fd) == -1) {
- perror("error syncing seed directory");
- goto out;
- }
-
- rv = true;
- goto out;
-
-err:
- if (seed_file) {
- fclose(seed_file);
- if (unlinkat(seed_dir_fd, seed_name_new, 0) == -1) {
- perror("error removing temporary seed file");
- rv = false;
- }
- }
-
-out:
- if (seed_dir_fd != -1) {
- if (close(seed_dir_fd) == -1) {
- perror("error closing seed directory");
- rv = false;
- }
- }
-
- free(seed_path_tmp);
- free(seed_name_new);
-
- return rv;
-}
-
static void sighandler(int signum) {
switch (signum) {
- case SIGHUP:
- // do nothing; we just needed to interrupt sleep
- break;
- case SIGINT:
- sigint = 1;
- break;
- case SIGTERM:
- sigterm = 1;
- break;
- default:
- abort();
+ case SIGHUP: /* do nothing; we just needed to interrupt sleep */ break;
+ case SIGINT: sigint = 1; break;
+ case SIGTERM: sigterm = 1; break;
+ default: abort();
}
}
-noreturn static void run(const char *mode, const char *seed_path) {
- FILE *seed_file;
+void run(const char *mode, const char *seed_path) {
int exit_status = 0;
if (streq(mode, "load")) {
- bool refresh_seed = true;
-
- if (streq(seed_path, "-")) {
- fputs("warning: cannot refresh stdin seed\n", stderr);
- seed_file = stdin;
- refresh_seed = false;
- } else {
- seed_file = fopen(seed_path, "r");
- }
- if (!seed_file) {
- perror("error opening seed file");
- exit(1);
- }
- if (!load(seed_file)) {
+ if (!load(seed_path)) {
if (noperms)
exit_status = 15;
else
exit_status = 1;
}
- if (refresh_seed) {
+ if (streq(seed_path, "-")) {
+ fputs("warning: cannot refresh stdin seed\n", stderr);
+ } else {
unsigned char random_buf[RAND_POOL_SIZE];
unsigned char *random_ptr = random_buf;
switch (random_get(random_buf, RAND_POOL_SIZE, GRND_NONBLOCK)) {
case RAND_POOL_SIZE:
- goto save;
+ break;
case -1:
if (errno != EAGAIN) {
perror("getrandom");
exit(1);
}
+ FALLS_THROUGH;
+ default:
+ if (daemon(0, 1) == -1) {
+ perror("error daemonizing, continuing without");
+ }
+ close(0);
+ close(1);
+ random_ptr = NULL;
}
- if (daemon(0, 1) == -1) {
- perror("error daemonizing, continuing without");
- }
- close(0);
- close(1);
- random_ptr = NULL;
-save: if (!save(seed_path, random_ptr))
+ if (!save(seed_path, random_ptr))
exit_status = 1;
}
exit(exit_status);
@@ -447,12 +68,7 @@ save: if (!save(seed_path, random_ptr))
fputs("error: seed_path cannot be - for daemonize\n", stderr);
exit(2);
}
- seed_file = fopen(seed_path, "r");
- if (!seed_file) {
- perror("error opening seed file");
- exit(3);
- }
- if (!load(seed_file))
+ if (!load(seed_path))
fputs("warning: failed to load initial entropy\n", stderr);
struct sigaction sa;
@@ -490,33 +106,3 @@ save: if (!save(seed_path, random_ptr))
exit(2);
}
}
-
-int main(int argc, char *argv[]) {
- char *mode, *seed_path;
-
- switch (argc) {
- case 2:
- if (streq(argv[1], "-h") || streq(argv[1], "--help")) {
- usage();
- exit(0);
- }
- if (streq(argv[1], "-V") || streq(argv[1], "--version")) {
- printf("random-seed %s\n", PACKAGE_VERSION);
- exit(0);
- }
- mode = argv[1];
- seed_path = DEFAULT_SEED_PATH;
- break;
- case 3:
- mode = argv[1];
- seed_path = argv[2];
- break;
- default:
- fprintf(stderr, "error: invalid arguments\n");
- usage();
- exit(2);
- }
-
- umask(0);
- run(mode, seed_path);
-}
diff --git a/src/random-seed.h b/src/random-seed.h
new file mode 100644
index 0000000..baea582
--- /dev/null
+++ b/src/random-seed.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#define MAGIC "RANDOM SEED FILE VERSION 1\n"
+
+extern bool noperms;
+
+struct random_seed {
+ FILE *file;
+#ifdef HAVE_UTIL_LINUX
+ dev_t dev;
+#endif
+#ifdef HAVE_LIBUDEV
+ struct udev_device *udev_dev;
+#endif
+};
+
+bool load(const char *seed_path);
+bool save(const char *seed_path, const unsigned char *random_buf);
+
+/* defining noreturn in C99 is too hard */
+void run(const char *mode, const char *seed_path);
diff --git a/src/save.c b/src/save.c
new file mode 100644
index 0000000..533afff
--- /dev/null
+++ b/src/save.c
@@ -0,0 +1,230 @@
+#include "id.h"
+#include "musl-libgen-c.h"
+#include "random-seed.h"
+#include "util.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static const char *HEX_CHARS = "0123456789abcdef";
+
+/** Encode hex.
+ *
+ * \param dest where to store the encoded data (must have at least size*2+1 bytes)
+ * \param src the data to encode
+ * \param size the number of bytes to encode
+ */
+static void mem2hex(char *dest, const void *src, size_t size) {
+ size_t i;
+ for (i = 0; i < size; i++) {
+ unsigned char c = *((const unsigned char *)src + i);
+ dest[2*i] = HEX_CHARS[c >> 4];
+ dest[2*i+1] = HEX_CHARS[c & 0xf];
+ }
+ dest[2*i] = '\0';
+}
+
+static bool get_rand_pool(unsigned char *buf) {
+ size_t rand_bytes_gotten = 0;
+
+ do {
+ long this_rand_bytes_gotten = random_get(buf + rand_bytes_gotten, RAND_POOL_SIZE - rand_bytes_gotten, 0);
+ if (this_rand_bytes_gotten == -1) {
+ switch (errno) {
+ case EAGAIN: continue;
+ case EINTR: return false;
+ default:
+ perror("getrandom");
+ exit(1);
+ }
+ } else {
+ rand_bytes_gotten += (size_t)this_rand_bytes_gotten;
+ }
+ } while (rand_bytes_gotten < RAND_POOL_SIZE);
+
+ return true;
+}
+
+static void hash_str(const unsigned char salt[static SALT_LEN], char hash_out[static HASH_STR_LEN], const void *buf, size_t buflen) {
+ unsigned char digest[HASH_LEN];
+ hash(salt, digest, buf, buflen);
+ mem2hex(hash_out, digest, HASH_LEN);
+}
+
+/**
+ * Save entropy to disk.
+ *
+ * \param seed_path the seed file path
+ * \param random_buf the random buffer. if NULL, get our own entropy.
+ * \return true means saved successfully, false means received EINTR
+ */
+bool save(const char *seed_path, const unsigned char *random_ptr) {
+ assert(seed_path);
+
+ bool rv = false;
+
+ unsigned char random_buf[RAND_POOL_SIZE];
+ if (!random_ptr) {
+ if (!get_rand_pool(random_buf))
+ return false;
+ random_ptr = random_buf;
+ }
+
+ const char *machine_id = get_machine_id(&machine_id);
+ if (!machine_id)
+ return false;
+ char machine_id_hash[HASH_STR_LEN];
+ hash_str(random_ptr, machine_id_hash, machine_id, strlen(machine_id));
+
+ struct random_seed rs = {0};
+
+ char *seed_path_tmp = strdup(seed_path);
+ const char *seed_dir, *seed_name;
+ char *seed_path_last_slash = strrchr(seed_path_tmp, '/');
+ if (seed_path_last_slash) {
+ *seed_path_last_slash = '\0';
+ seed_dir = seed_path_tmp;
+ seed_name = seed_path_last_slash + 1;
+ } else {
+ free(seed_path_tmp);
+ seed_path_tmp = NULL;
+ seed_dir = ".";
+ seed_name = seed_path;
+ }
+ char *seed_name_new = NULL;
+
+ if (asprintf(&seed_name_new, ".%s.new", seed_name) == -1) {
+ fputs("out of memory\n", stderr);
+ goto out;
+ }
+
+ int seed_dir_fd = open(seed_dir, O_RDONLY | O_DIRECTORY);
+ if (seed_dir_fd == -1) {
+ perror("error opening seed directory");
+ goto out;
+ }
+
+ fsid_t fs_id;
+ bool have_fs_id = get_fs_id(&fs_id, seed_dir_fd);
+#ifdef HAVE_FS_UUID
+ (void)have_fs_id;
+#else
+ if (!have_fs_id) {
+ fputs("error getting fs id\n", stderr);
+ return false;
+ }
+#endif
+ char fs_id_hash[HASH_STR_LEN];
+ hash_str(random_ptr, fs_id_hash, &fs_id, sizeof(fs_id));
+
+#ifdef HAVE_FS_UUID
+ ensure_rs_device(&rs, seed_dir_fd);
+ char fs_uuid_hash[HASH_STR_LEN];
+ {
+ const char *fs_uuid = get_fs_uuid(&rs);
+ if (!fs_uuid) {
+ fputs("error getting fs uuid\n", stderr);
+ return false;
+ }
+ hash_str(random_ptr, fs_uuid_hash, fs_uuid, strlen(fs_uuid));
+ }
+#endif
+
+#ifdef HAVE_LIBUDEV
+ bool have_drive_id = false;
+ char drive_id_hash[HASH_STR_LEN];
+ {
+ const char *drive_id = get_drive_id(&rs);
+ if (drive_id) {
+ have_drive_id = true;
+ hash_str(random_ptr, drive_id_hash, drive_id, strlen(drive_id));
+ }
+ }
+#endif
+
+ {
+ int seed_fd = openat(seed_dir_fd, seed_name_new, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ if (seed_fd == -1) {
+ perror("error opening new seed file");
+ goto err;
+ }
+ rs.file = fdopen(seed_fd, "w");
+ if (!rs.file) {
+ perror("error converting seed file fd to stream");
+ goto err;
+ }
+ }
+
+ if (fwrite(random_ptr, 1, RAND_POOL_SIZE, rs.file) != RAND_POOL_SIZE
+ || fputs(MAGIC, rs.file) == EOF
+ || fputs("machine-id ", rs.file) == EOF
+ || fputs(machine_id_hash, rs.file) == EOF
+#ifdef HAVE_FS_UUID
+ || fputs("\nfs-uuid ", rs.file) == EOF
+ || fputs(fs_uuid_hash, rs.file) == EOF
+ || fputs("\nfs-id ", rs.file) == EOF
+ || fputs(fs_id_hash, rs.file) == EOF
+#else
+ || (have_fs_id ? fputs("\nfs-id ", rs.file) == EOF : 0)
+ || (have_fs_id ? fputs(fs_id_hash, rs.file) == EOF : 0)
+#endif
+#ifdef HAVE_LIBUDEV
+ || (have_drive_id ? fputs("\ndrive-id ", rs.file) == EOF : 0)
+ || (have_drive_id ? fputs(drive_id_hash, rs.file) == EOF : 0)
+#endif
+ || fputs("\ndone\n", rs.file) == EOF) {
+ fputs("error writing new seed file\n", stderr);
+ goto err;
+ }
+
+ if (fflush(rs.file) == EOF) {
+ perror("error flushing new seed file");
+ goto err;
+ }
+ if (fsync(fileno(rs.file)) == -1) {
+ perror("error syncing new seed file");
+ goto err;
+ }
+ if (renameat(seed_dir_fd, seed_name_new, seed_dir_fd, seed_name) == -1) {
+ perror("error installing new seed file");
+ goto err;
+ }
+ if (fclose(rs.file) == EOF) {
+ perror("error closing new seed file");
+ goto err;
+ }
+ if (fsync(seed_dir_fd) == -1) {
+ perror("error syncing seed directory");
+ goto out;
+ }
+
+ rv = true;
+ goto out;
+
+err:
+ if (rs.file) {
+ fclose(rs.file);
+ if (unlinkat(seed_dir_fd, seed_name_new, 0) == -1) {
+ perror("error removing temporary seed file");
+ rv = false;
+ }
+ }
+
+out:
+ if (seed_dir_fd != -1) {
+ if (close(seed_dir_fd) == -1) {
+ perror("error closing seed directory");
+ rv = false;
+ }
+ }
+
+ free(seed_path_tmp);
+ free(seed_name_new);
+
+ return rv;
+}
+
diff --git a/src/util.c b/src/util.c
index b552afc..bd2c9a7 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1,63 +1,11 @@
-// SPDX-License-Identifier: BSD-3-Clause
+#include "util.h"
-#include <assert.h>
-#include <limits.h>
-#include <stddef.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-
-#include "util.h"
-
-static inline signed char hexchr2int(char c) {
- /* No, nobody uses EBCDIC anymore. */
- return (c >= '0' && c <= '9') ? (c - '0') :
- (c >= 'a' && c <= 'f') ? (c - 'a' + 10) :
- (c >= 'A' && c <= 'F') ? (c - 'A' + 10) :
- -1;
-}
-
-/**
- * Decode hex.
- *
- * \param dest where to store the decoded data
- * \param size the maximum number of bytes to decode
- * \param src the hex-encoded data
- *
- * \return 0 if an error occurred, otherwise the number of bytes written to
- * dest
- */
-size_t hex2mem(unsigned char *dest, size_t size, const char *src) {
-#ifdef DEBUG
- fprintf(stderr, "hex decoding %zu bytes\n", size);
-#endif
- size_t i;
- for (i = 0; i < size; i++) {
- int n1 = hexchr2int(src[2*i]);
- if (n1 < 0) return 0;
- int n2 = hexchr2int(src[2*i+1]);
- if (n2 < 0) return 0;
- dest[i] = (unsigned char)(n1 << 4 | n2);
- }
- return i;
-}
-
-static const char *HEX_CHARS = "0123456789abcdef";
-
-/** Encode hex.
- *
- * \param dest where to store the encoded data (must have at least size*2+1 bytes)
- * \param src the data to encode
- * \param size the number of bytes to encode
- */
-void mem2hex(char *dest, const void *src, size_t size) {
- size_t i;
- for (i = 0; i < size; i++) {
- unsigned char c = *((const unsigned char *)src + i);
- dest[2*i] = HEX_CHARS[c >> 4];
- dest[2*i+1] = HEX_CHARS[c & 0xf];
- }
- dest[2*i] = '\0';
-}
+#include <string.h>
+#include <sys/syscall.h>
+#include <unistd.h>
ssize_t random_get(void *buf, size_t buflen, unsigned int flags) {
memset(buf, 0, buflen);
diff --git a/src/util.h b/src/util.h
index 11cf369..41a49f9 100644
--- a/src/util.h
+++ b/src/util.h
@@ -1,19 +1,17 @@
// SPDX-License-Identifier: BSD-3-Clause
-#ifndef RANDOM_SEED_UTIL_H
-#define RANDOM_SEED_UTIL_H
+#pragma once
-#include <errno.h>
+#include <sys/types.h>
#include <stdbool.h>
-#include <stddef.h>
#include <string.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-#include "sha2.h"
-
-#define GRND_NONBLOCK 0x01
-#define GRND_RANDOM 0x02
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+#ifdef HAVE_FUNC_ATTRIBUTE_FALLTHROUGH
+#define FALLS_THROUGH __attribute__((fallthrough))
+#else
+#define FALLS_THROUGH (void)0
+#endif
/* The pool size is fixed at 4096 bits since Linux 2.6. */
#define RAND_POOL_SIZE 512
@@ -23,12 +21,11 @@
/* The salt is the random data */
#define SALT_LEN RAND_POOL_SIZE
+#define GRND_NONBLOCK 0x01
+#define GRND_RANDOM 0x02
+
static inline bool streq(const char *s1, const char *s2) {
return !strcmp(s1, s2);
}
ssize_t random_get(void *buf, size_t buflen, unsigned int flags);
-size_t hex2mem(unsigned char *dest, size_t size, const char *src);
-void mem2hex(char *dest, const void *src, size_t size);
-
-#endif