diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/id.c | 116 | ||||
-rw-r--r-- | src/id.h | 22 | ||||
-rw-r--r-- | src/id.i | 3161 | ||||
-rw-r--r-- | src/load.c | 257 | ||||
-rw-r--r-- | src/main.c | 61 | ||||
-rw-r--r-- | src/musl-libgen-c.h | 5 | ||||
-rw-r--r-- | src/random-seed.c | 464 | ||||
-rw-r--r-- | src/random-seed.h | 25 | ||||
-rw-r--r-- | src/save.c | 230 | ||||
-rw-r--r-- | src/util.c | 62 | ||||
-rw-r--r-- | src/util.h | 25 |
11 files changed, 3881 insertions, 547 deletions
@@ -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; } } @@ -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; +} + @@ -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); @@ -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 |