summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--include/Makemodule.am74
-rw-r--r--include/all-io.h114
-rw-r--r--include/bitops.h157
-rw-r--r--include/blkdev.h160
-rw-r--r--include/buffer.h44
-rw-r--r--include/c.h505
-rw-r--r--include/c_strtod.h6
-rw-r--r--include/canonicalize.h32
-rw-r--r--include/caputils.h34
-rw-r--r--include/carefulputc.h74
-rw-r--r--include/cctype.h325
-rw-r--r--include/closestream.h110
-rw-r--r--include/color-names.h44
-rw-r--r--include/colors.h73
-rw-r--r--include/cpuset.h99
-rw-r--r--include/crc32.h12
-rw-r--r--include/crc32c.h9
-rw-r--r--include/debug.h181
-rw-r--r--include/debugobj.h22
-rw-r--r--include/encode.h14
-rw-r--r--include/env.h35
-rw-r--r--include/exec_shell.h6
-rw-r--r--include/exitcodes.h25
-rw-r--r--include/fileeq.h53
-rw-r--r--include/fileutils.h103
-rw-r--r--include/fuzz.h9
-rw-r--r--include/idcache.h28
-rw-r--r--include/ismounted.h14
-rw-r--r--include/iso9660.h58
-rw-r--r--include/jsonwrt.h47
-rw-r--r--include/linux_version.h14
-rw-r--r--include/list.h380
-rw-r--r--include/loopdev.h222
-rw-r--r--include/mangle.h28
-rw-r--r--include/match.h12
-rw-r--r--include/mbsalign.h66
-rw-r--r--include/mbsedit.h32
-rw-r--r--include/md5.h24
-rw-r--r--include/meson.build3
-rw-r--r--include/minix.h85
-rw-r--r--include/monotonic.h22
-rw-r--r--include/namespace.h56
-rw-r--r--include/nls.h153
-rw-r--r--include/optutils.h107
-rw-r--r--include/pager.h9
-rw-r--r--include/partx.h63
-rw-r--r--include/path.h144
-rw-r--r--include/pathnames.h224
-rw-r--r--include/pidfd-utils.h28
-rw-r--r--include/plymouth-ctrl.h65
-rw-r--r--include/procfs.h63
-rw-r--r--include/pt-bsd.h156
-rw-r--r--include/pt-gpt-partnames.h271
-rw-r--r--include/pt-mbr-partnames.h113
-rw-r--r--include/pt-mbr.h210
-rw-r--r--include/pt-sgi.h115
-rw-r--r--include/pt-sun.h90
-rw-r--r--include/pty-session.h112
-rw-r--r--include/pwdutils.h14
-rw-r--r--include/randutils.h17
-rw-r--r--include/rpmatch.h13
-rw-r--r--include/selinux-utils.h8
-rw-r--r--include/sha1.h27
-rw-r--r--include/signames.h8
-rw-r--r--include/statfs_magic.h100
-rw-r--r--include/strutils.h397
-rw-r--r--include/strv.h58
-rw-r--r--include/swapheader.h23
-rw-r--r--include/swapprober.h9
-rw-r--r--include/sysfs.h115
-rw-r--r--include/timer.h22
-rw-r--r--include/timeutils.h92
-rw-r--r--include/ttyutils.h212
-rw-r--r--include/widechar.h47
-rw-r--r--include/xalloc.h139
75 files changed, 6635 insertions, 0 deletions
diff --git a/include/Makemodule.am b/include/Makemodule.am
new file mode 100644
index 0000000..3329b4f
--- /dev/null
+++ b/include/Makemodule.am
@@ -0,0 +1,74 @@
+
+dist_noinst_HEADERS += \
+ include/all-io.h \
+ include/bitops.h \
+ include/blkdev.h \
+ include/buffer.h \
+ include/canonicalize.h \
+ include/carefulputc.h \
+ include/cctype.h \
+ include/c.h \
+ include/caputils.h \
+ include/closestream.h \
+ include/colors.h \
+ include/color-names.h \
+ include/cpuset.h \
+ include/crc32.h \
+ include/crc32c.h \
+ include/c_strtod.h \
+ include/debug.h \
+ include/debugobj.h \
+ include/encode.h \
+ include/env.h \
+ include/exec_shell.h \
+ include/exitcodes.h \
+ include/fileeq.h \
+ include/fileutils.h \
+ include/fuzz.h \
+ include/idcache.h \
+ include/ismounted.h \
+ include/iso9660.h \
+ include/jsonwrt.h \
+ include/pwdutils.h \
+ include/linux_version.h \
+ include/list.h \
+ include/loopdev.h \
+ include/mangle.h \
+ include/match.h \
+ include/mbsalign.h \
+ include/mbsedit.h \
+ include/md5.h \
+ include/minix.h \
+ include/monotonic.h \
+ include/namespace.h \
+ include/nls.h \
+ include/optutils.h \
+ include/pager.h \
+ include/partx.h \
+ include/path.h \
+ include/pathnames.h \
+ include/pidfd-utils.h \
+ include/plymouth-ctrl.h \
+ include/procfs.h \
+ include/pt-bsd.h \
+ include/pt-mbr.h \
+ include/pt-mbr-partnames.h \
+ include/pt-gpt-partnames.h \
+ include/pt-sgi.h \
+ include/pt-sun.h \
+ include/randutils.h \
+ include/rpmatch.h \
+ include/sha1.h \
+ include/signames.h \
+ include/selinux-utils.h \
+ include/statfs_magic.h \
+ include/strutils.h \
+ include/strv.h \
+ include/swapheader.h \
+ include/swapprober.h \
+ include/sysfs.h \
+ include/timer.h \
+ include/timeutils.h \
+ include/ttyutils.h \
+ include/widechar.h \
+ include/xalloc.h
diff --git a/include/all-io.h b/include/all-io.h
new file mode 100644
index 0000000..e05e1e7
--- /dev/null
+++ b/include/all-io.h
@@ -0,0 +1,114 @@
+/*
+ * No copyright is claimed. This code is in the public domain; do with
+ * it what you wish.
+ *
+ * Written by Karel Zak <kzak@redhat.com>
+ * Petr Uzel <petr.uzel@suse.cz>
+ */
+
+#ifndef UTIL_LINUX_ALL_IO_H
+#define UTIL_LINUX_ALL_IO_H
+
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_SENDFILE_H
+# include <sys/sendfile.h>
+#endif
+
+#include "c.h"
+
+static inline int write_all(int fd, const void *buf, size_t count)
+{
+ while (count) {
+ ssize_t tmp;
+
+ errno = 0;
+ tmp = write(fd, buf, count);
+ if (tmp > 0) {
+ count -= tmp;
+ if (count)
+ buf = (const void *) ((const char *) buf + tmp);
+ } else if (errno != EINTR && errno != EAGAIN)
+ return -1;
+ if (errno == EAGAIN) /* Try later, *sigh* */
+ xusleep(250000);
+ }
+ return 0;
+}
+
+static inline int fwrite_all(const void *ptr, size_t size,
+ size_t nmemb, FILE *stream)
+{
+ while (nmemb) {
+ size_t tmp;
+
+ errno = 0;
+ tmp = fwrite(ptr, size, nmemb, stream);
+ if (tmp > 0) {
+ nmemb -= tmp;
+ if (nmemb)
+ ptr = (const void *) ((const char *) ptr + (tmp * size));
+ } else if (errno != EINTR && errno != EAGAIN)
+ return -1;
+ if (errno == EAGAIN) /* Try later, *sigh* */
+ xusleep(250000);
+ }
+ return 0;
+}
+
+static inline ssize_t read_all(int fd, char *buf, size_t count)
+{
+ ssize_t ret;
+ ssize_t c = 0;
+ int tries = 0;
+
+ memset(buf, 0, count);
+ while (count > 0) {
+ ret = read(fd, buf, count);
+ if (ret < 0) {
+ if ((errno == EAGAIN || errno == EINTR) && (tries++ < 5)) {
+ xusleep(250000);
+ continue;
+ }
+ return c ? c : -1;
+ }
+ if (ret == 0)
+ return c;
+ tries = 0;
+ count -= ret;
+ buf += ret;
+ c += ret;
+ }
+ return c;
+}
+
+static inline ssize_t sendfile_all(int out, int in, off_t *off, size_t count)
+{
+#if defined(HAVE_SENDFILE) && defined(__linux__)
+ ssize_t ret;
+ ssize_t c = 0;
+ int tries = 0;
+ while (count) {
+ ret = sendfile(out, in, off, count);
+ if (ret < 0) {
+ if ((errno == EAGAIN || errno == EINTR) && (tries++ < 5)) {
+ xusleep(250000);
+ continue;
+ }
+ return c ? c : -1;
+ }
+ if (ret == 0)
+ return c;
+ tries = 0;
+ count -= ret;
+ c += ret;
+ }
+ return c;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+#endif /* UTIL_LINUX_ALL_IO_H */
diff --git a/include/bitops.h b/include/bitops.h
new file mode 100644
index 0000000..72274de
--- /dev/null
+++ b/include/bitops.h
@@ -0,0 +1,157 @@
+/*
+ * No copyright is claimed. This code is in the public domain; do with
+ * it what you wish.
+ *
+ * Written by Karel Zak <kzak@redhat.com>
+ */
+#ifndef BITOPS_H
+#define BITOPS_H
+
+#include <stdint.h>
+#include <sys/param.h>
+
+#if defined(HAVE_BYTESWAP_H)
+# include <byteswap.h>
+#endif
+
+#if defined(HAVE_ENDIAN_H)
+# include <endian.h>
+#elif defined(HAVE_SYS_ENDIAN_H) /* BSDs have them here */
+# include <sys/endian.h>
+#endif
+
+#if !(defined(HAVE_BYTESWAP_H) && defined(HAVE_ENDIAN_H))
+/*
+ * When both byteswap.h and endian.h are preseent, the proper macros are defined
+ * as those files are glibc compatible. Otherwise, compensate for the slightly
+ * different interfaces between the different BSDs.
+ */
+#if defined(__OpenBSD__)
+# include <sys/types.h>
+# define be16toh(x) betoh16(x)
+# define be32toh(x) betoh32(x)
+# define be64toh(x) betoh64(x)
+#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
+# define bswap_16(x) bswap16(x)
+# define bswap_32(x) bswap32(x)
+# define bswap_64(x) bswap64(x)
+#elif defined(__APPLE__)
+# include <libkern/OSByteOrder.h>
+# define htobe16(x) OSSwapHostToBigInt16(x)
+# define htole16(x) OSSwapHostToLittleInt16(x)
+# define be16toh(x) OSSwapBigToHostInt16(x)
+# define le16toh(x) OSSwapLittleToHostInt16(x)
+# define htobe32(x) OSSwapHostToBigInt32(x)
+# define htole32(x) OSSwapHostToLittleInt32(x)
+# define be32toh(x) OSSwapBigToHostInt32(x)
+# define le32toh(x) OSSwapLittleToHostInt32(x)
+# define htobe64(x) OSSwapHostToBigInt64(x)
+# define htole64(x) OSSwapHostToLittleInt64(x)
+# define be64toh(x) OSSwapBigToHostInt64(x)
+# define le64toh(x) OSSwapLittleToHostInt64(x)
+# define bswap_16(x) OSSwapInt16(x)
+# define bswap_32(x) OSSwapInt32(x)
+# define bswap_64(x) OSSwapInt64(x)
+#endif
+#endif
+
+/*
+ * Fallbacks
+ * casts are necessary for constants, because we never know how for sure
+ * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way.
+ */
+#ifndef bswap_16
+# define bswap_16(x) ((uint16_t)( \
+ (((uint16_t)(x) & 0x00FF) << 8) | \
+ (((uint16_t)(x) & 0xFF00) >> 8)))
+#endif
+
+#ifndef bswap_32
+# define bswap_32(x) ((uint32_t)( \
+ (((uint32_t)(x) & 0x000000FF) << 24) | \
+ (((uint32_t)(x) & 0x0000FF00) << 8) | \
+ (((uint32_t)(x) & 0x00FF0000) >> 8) | \
+ (((uint32_t)(x) & 0xFF000000) >> 24)))
+#endif
+
+#ifndef bswap_64
+# define bswap_64(x) ((uint64_t)( \
+ (((uint64_t)(x) & 0x00000000000000FFULL) << 56) | \
+ (((uint64_t)(x) & 0x000000000000FF00ULL) << 40) | \
+ (((uint64_t)(x) & 0x0000000000FF0000ULL) << 24) | \
+ (((uint64_t)(x) & 0x00000000FF000000ULL) << 8) | \
+ (((uint64_t)(x) & 0x000000FF00000000ULL) >> 8) | \
+ (((uint64_t)(x) & 0x0000FF0000000000ULL) >> 24) | \
+ (((uint64_t)(x) & 0x00FF000000000000ULL) >> 40) | \
+ (((uint64_t)(x) & 0xFF00000000000000ULL) >> 56)))
+#endif
+
+#ifndef htobe16
+# if !defined(WORDS_BIGENDIAN)
+# define htobe16(x) bswap_16 (x)
+# define htole16(x) (x)
+# define be16toh(x) bswap_16 (x)
+# define le16toh(x) (x)
+# define htobe32(x) bswap_32 (x)
+# define htole32(x) (x)
+# define be32toh(x) bswap_32 (x)
+# define le32toh(x) (x)
+# define htobe64(x) bswap_64 (x)
+# define htole64(x) (x)
+# define be64toh(x) bswap_64 (x)
+# define le64toh(x) (x)
+# else
+# define htobe16(x) (x)
+# define htole16(x) bswap_16 (x)
+# define be16toh(x) (x)
+# define le16toh(x) bswap_16 (x)
+# define htobe32(x) (x)
+# define htole32(x) bswap_32 (x)
+# define be32toh(x) (x)
+# define le32toh(x) bswap_32 (x)
+# define htobe64(x) (x)
+# define htole64(x) bswap_64 (x)
+# define be64toh(x) (x)
+# define le64toh(x) bswap_64 (x)
+# endif
+#endif
+
+/*
+ * Byte swab macros (based on linux/byteorder/swab.h)
+ */
+#define swab16(x) bswap_16(x)
+#define swab32(x) bswap_32(x)
+#define swab64(x) bswap_64(x)
+
+#define cpu_to_le16(x) ((uint16_t) htole16(x))
+#define cpu_to_le32(x) ((uint32_t) htole32(x))
+#define cpu_to_le64(x) ((uint64_t) htole64(x))
+
+#define cpu_to_be16(x) ((uint16_t) htobe16(x))
+#define cpu_to_be32(x) ((uint32_t) htobe32(x))
+#define cpu_to_be64(x) ((uint64_t) htobe64(x))
+
+#define le16_to_cpu(x) ((uint16_t) le16toh(x))
+#define le32_to_cpu(x) ((uint32_t) le32toh(x))
+#define le64_to_cpu(x) ((uint64_t) le64toh(x))
+
+#define be16_to_cpu(x) ((uint16_t) be16toh(x))
+#define be32_to_cpu(x) ((uint32_t) be32toh(x))
+#define be64_to_cpu(x) ((uint64_t) be64toh(x))
+
+/*
+ * Bit map related macros. Usually provided by libc.
+ */
+#ifndef NBBY
+# define NBBY CHAR_BIT
+#endif
+
+#ifndef setbit
+# define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
+# define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
+# define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
+# define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
+#endif
+
+#endif /* BITOPS_H */
+
diff --git a/include/blkdev.h b/include/blkdev.h
new file mode 100644
index 0000000..43a5f52
--- /dev/null
+++ b/include/blkdev.h
@@ -0,0 +1,160 @@
+/*
+ * No copyright is claimed. This code is in the public domain; do with
+ * it what you wish.
+ *
+ * Written by Karel Zak <kzak@redhat.com>
+ */
+#ifndef BLKDEV_H
+#define BLKDEV_H
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_IOCCOM_H
+# include <sys/ioccom.h> /* for _IO macro on e.g. Solaris */
+#endif
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <stdint.h>
+
+#ifdef HAVE_SYS_MKDEV_H
+# include <sys/mkdev.h> /* major and minor on Solaris */
+#endif
+
+#define DEFAULT_SECTOR_SIZE 512
+
+#ifdef __linux__
+/* very basic ioctls, should be available everywhere */
+# ifndef BLKROSET
+# define BLKROSET _IO(0x12,93) /* set device read-only (0 = read-write) */
+# define BLKROGET _IO(0x12,94) /* get read-only status (0 = read_write) */
+# define BLKRRPART _IO(0x12,95) /* re-read partition table */
+# define BLKGETSIZE _IO(0x12,96) /* return device size /512 (long *arg) */
+# define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
+# define BLKRASET _IO(0x12,98) /* set read ahead for block device */
+# define BLKRAGET _IO(0x12,99) /* get current read ahead setting */
+# define BLKFRASET _IO(0x12,100) /* set filesystem (mm/filemap.c) read-ahead */
+# define BLKFRAGET _IO(0x12,101) /* get filesystem (mm/filemap.c) read-ahead */
+# define BLKSECTSET _IO(0x12,102) /* set max sectors per request (ll_rw_blk.c) */
+# define BLKSECTGET _IO(0x12,103) /* get max sectors per request (ll_rw_blk.c) */
+# define BLKSSZGET _IO(0x12,104) /* get block device sector size */
+
+/* ioctls introduced in 2.2.16, removed in 2.5.58 */
+# define BLKELVGET _IOR(0x12,106,size_t) /* elevator get */
+# define BLKELVSET _IOW(0x12,107,size_t) /* elevator set */
+
+# define BLKBSZGET _IOR(0x12,112,size_t)
+# define BLKBSZSET _IOW(0x12,113,size_t)
+# endif /* !BLKROSET */
+
+# ifndef BLKGETSIZE64
+# define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
+# endif
+
+/* block device topology ioctls, introduced in 2.6.32 (commit ac481c20) */
+# ifndef BLKIOMIN
+# define BLKIOMIN _IO(0x12,120)
+# define BLKIOOPT _IO(0x12,121)
+# define BLKALIGNOFF _IO(0x12,122)
+# define BLKPBSZGET _IO(0x12,123)
+# endif
+
+/* discard zeroes support, introduced in 2.6.33 (commit 98262f27) */
+# ifndef BLKDISCARDZEROES
+# define BLKDISCARDZEROES _IO(0x12,124)
+# endif
+
+/* filesystem freeze, introduced in 2.6.29 (commit fcccf502) */
+# ifndef FIFREEZE
+# define FIFREEZE _IOWR('X', 119, int) /* Freeze */
+# define FITHAW _IOWR('X', 120, int) /* Thaw */
+# endif
+
+/* uniform CD-ROM information */
+# ifndef CDROM_GET_CAPABILITY
+# define CDROM_GET_CAPABILITY 0x5331
+# endif
+
+#endif /* __linux */
+
+
+#ifdef APPLE_DARWIN
+# define BLKGETSIZE DKIOCGETBLOCKCOUNT32
+#endif
+
+#ifndef HDIO_GETGEO
+# ifdef __linux__
+# define HDIO_GETGEO 0x0301
+# endif
+
+struct hd_geometry {
+ unsigned char heads;
+ unsigned char sectors;
+ unsigned short cylinders; /* truncated */
+ unsigned long start;
+};
+#endif /* HDIO_GETGEO */
+
+
+/* are we working with block device? */
+int is_blkdev(int fd);
+
+/* open block device or file */
+int open_blkdev_or_file(const struct stat *st, const char *name, const int oflag);
+
+/* Determine size in bytes */
+off_t blkdev_find_size (int fd);
+
+/* get size in bytes */
+int blkdev_get_size(int fd, unsigned long long *bytes);
+
+/* get 512-byte sector count */
+int blkdev_get_sectors(int fd, unsigned long long *sectors);
+
+/* get hardware sector size */
+int blkdev_get_sector_size(int fd, int *sector_size);
+
+/* specifies whether or not the device is misaligned */
+int blkdev_is_misaligned(int fd);
+
+/* get physical block device size */
+int blkdev_get_physector_size(int fd, int *sector_size);
+
+/* is the device cdrom capable? */
+int blkdev_is_cdrom(int fd);
+
+/* get device's geometry - legacy */
+int blkdev_get_geometry(int fd, unsigned int *h, unsigned int *s);
+
+/* SCSI device types. Copied almost as-is from kernel header.
+ * http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/scsi/scsi.h */
+#define SCSI_TYPE_DISK 0x00
+#define SCSI_TYPE_TAPE 0x01
+#define SCSI_TYPE_PRINTER 0x02
+#define SCSI_TYPE_PROCESSOR 0x03 /* HP scanners use this */
+#define SCSI_TYPE_WORM 0x04 /* Treated as ROM by our system */
+#define SCSI_TYPE_ROM 0x05
+#define SCSI_TYPE_SCANNER 0x06
+#define SCSI_TYPE_MOD 0x07 /* Magneto-optical disk - treated as SCSI_TYPE_DISK */
+#define SCSI_TYPE_MEDIUM_CHANGER 0x08
+#define SCSI_TYPE_COMM 0x09 /* Communications device */
+#define SCSI_TYPE_RAID 0x0c
+#define SCSI_TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */
+#define SCSI_TYPE_RBC 0x0e
+#define SCSI_TYPE_OSD 0x11
+#define SCSI_TYPE_NO_LUN 0x7f
+
+/* convert scsi type code to name */
+const char *blkdev_scsi_type_to_name(int type);
+
+int blkdev_lock(int fd, const char *devname, const char *lockmode);
+#ifdef HAVE_LINUX_BLKZONED_H
+struct blk_zone_report *blkdev_get_zonereport(int fd, uint64_t sector, uint32_t nzones);
+#else
+static inline struct blk_zone_report *blkdev_get_zonereport(int fd, uint64_t sector, uint32_t nzones)
+{
+ return NULL;
+}
+#endif
+
+#endif /* BLKDEV_H */
diff --git a/include/buffer.h b/include/buffer.h
new file mode 100644
index 0000000..ca94531
--- /dev/null
+++ b/include/buffer.h
@@ -0,0 +1,44 @@
+#ifndef UTIL_LINUX_BUFFER
+#define UTIL_LINUX_BUFFER
+
+#include "c.h"
+
+struct ul_buffer {
+ char *begin; /* begin of the data */
+ char *end; /* current end of data */
+
+ size_t sz; /* allocated space for data */
+ size_t chunksize;
+
+ char *encoded; /* encoded data (from mbs_safe_encode_to_buffer)) */
+ size_t encoded_sz; /* space allocated for encoded data */
+
+ char **ptrs; /* saved pointers */
+ size_t nptrs; /* number of saved pointers */
+};
+
+#define UL_INIT_BUFFER { .begin = NULL }
+
+void ul_buffer_reset_data(struct ul_buffer *buf);
+void ul_buffer_free_data(struct ul_buffer *buf);
+int ul_buffer_is_empty(struct ul_buffer *buf);
+void ul_buffer_set_chunksize(struct ul_buffer *buf, size_t sz);
+void ul_buffer_refer_string(struct ul_buffer *buf, char *str);
+int ul_buffer_alloc_data(struct ul_buffer *buf, size_t sz);
+int ul_buffer_append_data(struct ul_buffer *buf, const char *data, size_t sz);
+int ul_buffer_append_string(struct ul_buffer *buf, const char *str);
+int ul_buffer_append_ntimes(struct ul_buffer *buf, size_t n, const char *str);
+int ul_buffer_set_data(struct ul_buffer *buf, const char *data, size_t sz);
+
+char *ul_buffer_get_data(struct ul_buffer *buf, size_t *sz, size_t *width);
+char *ul_buffer_get_safe_data(struct ul_buffer *buf, size_t *sz, size_t *width, const char *safechars);
+
+size_t ul_buffer_get_bufsiz(struct ul_buffer *buf);
+
+int ul_buffer_save_pointer(struct ul_buffer *buf, unsigned short ptr_idx);
+char *ul_buffer_get_pointer(struct ul_buffer *buf, unsigned short ptr_idx);
+size_t ul_buffer_get_pointer_length(struct ul_buffer *buf, unsigned short ptr_idx);
+size_t ul_buffer_get_safe_pointer_width(struct ul_buffer *buf, unsigned short ptr_idx);
+
+
+#endif /* UTIL_LINUX_BUFFER */
diff --git a/include/c.h b/include/c.h
new file mode 100644
index 0000000..db0c58b
--- /dev/null
+++ b/include/c.h
@@ -0,0 +1,505 @@
+/*
+ * Fundamental C definitions.
+ *
+ * No copyright is claimed. This code is in the public domain; do with
+ * it what you wish.
+ */
+#ifndef UTIL_LINUX_C_H
+#define UTIL_LINUX_C_H
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <grp.h>
+
+#include <assert.h>
+
+#ifdef HAVE_ERR_H
+# include <err.h>
+#endif
+
+#ifdef HAVE_SYS_SYSMACROS_H
+# include <sys/sysmacros.h> /* for major, minor */
+#endif
+
+#ifndef LOGIN_NAME_MAX
+# define LOGIN_NAME_MAX 256
+#endif
+
+#ifndef NAME_MAX
+# define NAME_MAX PATH_MAX
+#endif
+
+/*
+ * __GNUC_PREREQ is deprecated in favour of __has_attribute() and
+ * __has_feature(). The __has macros are supported by clang and gcc>=5.
+ */
+#ifndef __GNUC_PREREQ
+# if defined __GNUC__ && defined __GNUC_MINOR__
+# define __GNUC_PREREQ(maj, min) \
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+# else
+# define __GNUC_PREREQ(maj, min) 0
+# endif
+#endif
+
+#ifdef __GNUC__
+
+/* &a[0] degrades to a pointer: a different type from an array */
+# define __must_be_array(a) \
+ UL_BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(__typeof__(a), __typeof__(&a[0])))
+
+# define ignore_result(x) __extension__ ({ \
+ __typeof__(x) __dummy __attribute__((__unused__)) = (x); (void) __dummy; \
+})
+
+#else /* !__GNUC__ */
+# define __must_be_array(a) 0
+# define __attribute__(_arg_)
+# define ignore_result(x) ((void) (x))
+#endif /* !__GNUC__ */
+
+
+/* "restrict" keyword fallback */
+#if __STDC__ != 1
+# define restrict __restrict /* use implementation __ format */
+#else
+# ifndef __STDC_VERSION__
+# define restrict __restrict /* use implementation __ format */
+# else
+# if __STDC_VERSION__ < 199901L
+# define restrict __restrict /* use implementation __ format */
+# endif
+# endif
+#endif
+
+
+/*
+ * It evaluates to 1 if the attribute/feature is supported by the current
+ * compilation target. Fallback for old compilers.
+ */
+#ifndef __has_attribute
+ #define __has_attribute(x) 0
+#endif
+
+#ifndef __has_feature
+ #define __has_feature(x) 0
+#endif
+
+/*
+ * Function attributes
+ */
+#ifndef __ul_alloc_size
+# if (__has_attribute(alloc_size) && __has_attribute(warn_unused_result)) || __GNUC_PREREQ (4, 3)
+# define __ul_alloc_size(s) __attribute__((alloc_size(s), warn_unused_result))
+# else
+# define __ul_alloc_size(s)
+# endif
+#endif
+
+#ifndef __ul_calloc_size
+# if (__has_attribute(alloc_size) && __has_attribute(warn_unused_result)) || __GNUC_PREREQ (4, 3)
+# define __ul_calloc_size(n, s) __attribute__((alloc_size(n, s), warn_unused_result))
+# else
+# define __ul_calloc_size(n, s)
+# endif
+#endif
+
+#if __has_attribute(returns_nonnull) || __GNUC_PREREQ (4, 9)
+# define __ul_returns_nonnull __attribute__((returns_nonnull))
+#else
+# define __ul_returns_nonnull
+#endif
+
+/*
+ * Force a compilation error if condition is true, but also produce a
+ * result (of value 0 and type size_t), so the expression can be used
+ * e.g. in a structure initializer (or wherever else comma expressions
+ * aren't permitted).
+ */
+#define UL_BUILD_BUG_ON_ZERO(e) __extension__ (sizeof(struct { int:-!!(e); }))
+#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
+#endif
+
+#ifndef PATH_MAX
+# define PATH_MAX 4096
+#endif
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+#ifndef min
+# define min(x, y) __extension__ ({ \
+ __typeof__(x) _min1 = (x); \
+ __typeof__(y) _min2 = (y); \
+ (void) (&_min1 == &_min2); \
+ _min1 < _min2 ? _min1 : _min2; })
+#endif
+
+#ifndef max
+# define max(x, y) __extension__ ({ \
+ __typeof__(x) _max1 = (x); \
+ __typeof__(y) _max2 = (y); \
+ (void) (&_max1 == &_max2); \
+ _max1 > _max2 ? _max1 : _max2; })
+#endif
+
+#ifndef abs_diff
+# define abs_diff(x, y) __extension__ ({ \
+ __typeof__(x) _a = (x); \
+ __typeof__(y) _b = (y); \
+ (void) (&_a == &_b); \
+ _a > _b ? _a - _b : _b - _a; })
+#endif
+
+#ifndef cmp_numbers
+# define cmp_numbers(x, y) __extension__ ({ \
+ __typeof__(x) _a = (x); \
+ __typeof__(y) _b = (y); \
+ (void) (&_a == &_b); \
+ _a == _b ? 0 : _a > _b ? 1 : -1; })
+#endif
+
+
+#ifndef cmp_timespec
+# define cmp_timespec(a, b, CMP) \
+ (((a)->tv_sec == (b)->tv_sec) \
+ ? ((a)->tv_nsec CMP (b)->tv_nsec) \
+ : ((a)->tv_sec CMP (b)->tv_sec))
+#endif
+
+
+#ifndef cmp_stat_mtime
+# ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+# define cmp_stat_mtime(_a, _b, CMP) cmp_timespec(&(_a)->st_mtim, &(_b)->st_mtim, CMP)
+# else
+# define cmp_stat_mtime(_a, _b, CMP) ((_a)->st_mtime CMP (_b)->st_mtime)
+# endif
+#endif
+
+
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+/*
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
+ */
+#ifndef container_of
+#define container_of(ptr, type, member) __extension__ ({ \
+ const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+#endif
+
+#ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME
+# ifdef HAVE___PROGNAME
+extern char *__progname;
+# define program_invocation_short_name __progname
+# else
+# ifdef HAVE_GETEXECNAME
+# define program_invocation_short_name \
+ prog_inv_sh_nm_from_file(getexecname(), 0)
+# else
+# define program_invocation_short_name \
+ prog_inv_sh_nm_from_file(__FILE__, 1)
+# endif
+static char prog_inv_sh_nm_buf[256];
+static inline char *
+prog_inv_sh_nm_from_file(char *f, char stripext)
+{
+ char *t;
+
+ if ((t = strrchr(f, '/')) != NULL)
+ t++;
+ else
+ t = f;
+
+ strncpy(prog_inv_sh_nm_buf, t, sizeof(prog_inv_sh_nm_buf) - 1);
+ prog_inv_sh_nm_buf[sizeof(prog_inv_sh_nm_buf) - 1] = '\0';
+
+ if (stripext && (t = strrchr(prog_inv_sh_nm_buf, '.')) != NULL)
+ *t = '\0';
+
+ return prog_inv_sh_nm_buf;
+}
+# endif
+#endif
+
+
+#ifndef HAVE_ERR_H
+static inline void __attribute__ ((__format__ (__printf__, 4, 5)))
+errmsg(char doexit, int excode, char adderr, const char *fmt, ...)
+{
+ fprintf(stderr, "%s: ", program_invocation_short_name);
+ if (fmt != NULL) {
+ va_list argp;
+ va_start(argp, fmt);
+ vfprintf(stderr, fmt, argp);
+ va_end(argp);
+ if (adderr)
+ fprintf(stderr, ": ");
+ }
+ if (adderr)
+ fprintf(stderr, "%m");
+ fprintf(stderr, "\n");
+ if (doexit)
+ exit(excode);
+}
+
+#ifndef HAVE_ERR
+# define err(E, FMT...) errmsg(1, E, 1, FMT)
+#endif
+
+#ifndef HAVE_ERRX
+# define errx(E, FMT...) errmsg(1, E, 0, FMT)
+#endif
+
+#ifndef HAVE_WARN
+# define warn(FMT...) errmsg(0, 0, 1, FMT)
+#endif
+
+#ifndef HAVE_WARNX
+# define warnx(FMT...) errmsg(0, 0, 0, FMT)
+#endif
+#endif /* !HAVE_ERR_H */
+
+
+/* Don't use inline function to avoid '#include "nls.h"' in c.h
+ */
+#define errtryhelp(eval) __extension__ ({ \
+ fprintf(stderr, _("Try '%s --help' for more information.\n"), \
+ program_invocation_short_name); \
+ exit(eval); \
+})
+
+/* After failed execvp() */
+#define EX_EXEC_FAILED 126 /* Program located, but not usable. */
+#define EX_EXEC_ENOENT 127 /* Could not find program to exec. */
+#define errexec(name) err(errno == ENOENT ? EX_EXEC_ENOENT : EX_EXEC_FAILED, \
+ _("failed to execute %s"), name)
+
+
+static inline __attribute__((const)) int is_power_of_2(unsigned long num)
+{
+ return (num != 0 && ((num & (num - 1)) == 0));
+}
+
+#ifndef HAVE_LOFF_T
+typedef int64_t loff_t;
+#endif
+
+#if !defined(HAVE_DIRFD) && (!defined(HAVE_DECL_DIRFD) || HAVE_DECL_DIRFD == 0) && defined(HAVE_DIR_DD_FD)
+#include <sys/types.h>
+#include <dirent.h>
+static inline int dirfd(DIR *d)
+{
+ return d->dd_fd;
+}
+#endif
+
+/*
+ * Fallback defines for old versions of glibc
+ */
+#include <fcntl.h>
+
+#ifdef O_CLOEXEC
+#define UL_CLOEXECSTR "e"
+#else
+#define UL_CLOEXECSTR ""
+#endif
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
+#ifdef __FreeBSD_kernel__
+#ifndef F_DUPFD_CLOEXEC
+#define F_DUPFD_CLOEXEC 17 /* Like F_DUPFD, but FD_CLOEXEC is set */
+#endif
+#endif
+
+
+#ifndef AI_ADDRCONFIG
+#define AI_ADDRCONFIG 0x0020
+#endif
+
+#ifndef IUTF8
+#define IUTF8 0040000
+#endif
+
+/*
+ * MAXHOSTNAMELEN replacement
+ */
+static inline size_t get_hostname_max(void)
+{
+ long len = sysconf(_SC_HOST_NAME_MAX);
+
+ if (0 < len)
+ return len;
+
+#ifdef MAXHOSTNAMELEN
+ return MAXHOSTNAMELEN;
+#elif HOST_NAME_MAX
+ return HOST_NAME_MAX;
+#endif
+ return 64;
+}
+
+
+static inline int drop_permissions(void)
+{
+ errno = 0;
+
+ /* drop GID */
+ if (setgid(getgid()) < 0)
+ goto fail;
+
+ /* drop UID */
+ if (setuid(getuid()) < 0)
+ goto fail;
+
+ return 0;
+fail:
+ return errno ? -errno : -1;
+}
+
+/*
+ * The usleep function was marked obsolete in POSIX.1-2001 and was removed
+ * in POSIX.1-2008. It was replaced with nanosleep() that provides more
+ * advantages (like no interaction with signals and other timer functions).
+ */
+#include <time.h>
+
+static inline int xusleep(useconds_t usec)
+{
+#ifdef HAVE_NANOSLEEP
+ struct timespec waittime = {
+ .tv_sec = usec / 1000000L,
+ .tv_nsec = (usec % 1000000L) * 1000
+ };
+ return nanosleep(&waittime, NULL);
+#elif defined(HAVE_USLEEP)
+ return usleep(usec);
+#else
+# error "System with usleep() or nanosleep() required!"
+#endif
+}
+
+/*
+ * Constant strings for usage() functions. For more info see
+ * Documentation/{howto-usage-function.txt,boilerplate.c}
+ */
+#define USAGE_HEADER _("\nUsage:\n")
+#define USAGE_OPTIONS _("\nOptions:\n")
+#define USAGE_FUNCTIONS _("\nFunctions:\n")
+#define USAGE_COMMANDS _("\nCommands:\n")
+#define USAGE_ARGUMENTS _("\nArguments:\n")
+#define USAGE_COLUMNS _("\nAvailable output columns:\n")
+#define USAGE_SEPARATOR "\n"
+
+#define USAGE_OPTSTR_HELP _("display this help")
+#define USAGE_OPTSTR_VERSION _("display version")
+
+#define USAGE_HELP_OPTIONS(marg_dsc) \
+ "%-" #marg_dsc "s%s\n" \
+ "%-" #marg_dsc "s%s\n" \
+ , " -h, --help", USAGE_OPTSTR_HELP \
+ , " -V, --version", USAGE_OPTSTR_VERSION
+
+#define USAGE_ARG_SEPARATOR "\n"
+#define USAGE_ARG_SIZE(_name) \
+ _(" %s arguments may be followed by the suffixes for\n" \
+ " GiB, TiB, PiB, EiB, ZiB, and YiB (the \"iB\" is optional)\n"), _name
+
+#define USAGE_MAN_TAIL(_man) _("\nFor more details see %s.\n"), _man
+
+#define UTIL_LINUX_VERSION _("%s from %s\n"), program_invocation_short_name, PACKAGE_STRING
+
+#define print_version(eval) __extension__ ({ \
+ printf(UTIL_LINUX_VERSION); \
+ exit(eval); \
+})
+
+/*
+ * seek stuff
+ */
+#ifndef SEEK_DATA
+# define SEEK_DATA 3
+#endif
+#ifndef SEEK_HOLE
+# define SEEK_HOLE 4
+#endif
+
+
+/*
+ * Macros to convert #define'itions to strings, for example
+ * #define XYXXY 42
+ * printf ("%s=%s\n", stringify(XYXXY), stringify_value(XYXXY));
+ */
+#define stringify_value(s) stringify(s)
+#define stringify(s) #s
+
+/* Detect if we're compiled with Address Sanitizer
+ * - gcc (__SANITIZE_ADDRESS__)
+ * - clang (__has_feature(address_sanitizer))
+ */
+#if !defined(HAS_FEATURE_ADDRESS_SANITIZER)
+# ifdef __SANITIZE_ADDRESS__
+# define HAS_FEATURE_ADDRESS_SANITIZER 1
+# elif defined(__has_feature)
+# if __has_feature(address_sanitizer)
+# define HAS_FEATURE_ADDRESS_SANITIZER 1
+# endif
+# endif
+# if !defined(HAS_FEATURE_ADDRESS_SANITIZER)
+# define HAS_FEATURE_ADDRESS_SANITIZER 0
+# endif
+#endif
+
+/*
+ * UL_ASAN_BLACKLIST is a macro to tell AddressSanitizer (a compile-time
+ * instrumentation shipped with Clang and GCC) to not instrument the
+ * annotated function. Furthermore, it will prevent the compiler from
+ * inlining the function because inlining currently breaks the blacklisting
+ * mechanism of AddressSanitizer.
+ */
+#if __has_feature(address_sanitizer) && __has_attribute(no_sanitize_memory) && __has_attribute(no_sanitize_address)
+# define UL_ASAN_BLACKLIST __attribute__((noinline)) __attribute__((no_sanitize_memory)) __attribute__((no_sanitize_address))
+#else
+# define UL_ASAN_BLACKLIST /* nothing */
+#endif
+
+/*
+ * Note that sysconf(_SC_GETPW_R_SIZE_MAX) returns *initial* suggested size for
+ * pwd buffer and in some cases it is not large enough. See POSIX and
+ * getpwnam_r man page for more details.
+ */
+#define UL_GETPW_BUFSIZ (16 * 1024)
+
+/*
+ * Darwin or other BSDs may only have MAP_ANON. To get it on Darwin we must
+ * define _DARWIN_C_SOURCE before including sys/mman.h. We do this in config.h.
+ */
+#if !defined MAP_ANONYMOUS && defined MAP_ANON
+# define MAP_ANONYMOUS (MAP_ANON)
+#endif
+
+#endif /* UTIL_LINUX_C_H */
diff --git a/include/c_strtod.h b/include/c_strtod.h
new file mode 100644
index 0000000..eaa801c
--- /dev/null
+++ b/include/c_strtod.h
@@ -0,0 +1,6 @@
+#ifndef UTIL_LINUX_C_STRTOD_H
+#define UTIL_LINUX_C_STRTOD_H
+
+extern double c_strtod(char const *str, char **end);
+
+#endif
diff --git a/include/canonicalize.h b/include/canonicalize.h
new file mode 100644
index 0000000..ff6ef0d
--- /dev/null
+++ b/include/canonicalize.h
@@ -0,0 +1,32 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library Public License for more details.
+ */
+#ifndef CANONICALIZE_H
+#define CANONICALIZE_H
+
+#include "c.h" /* for PATH_MAX */
+#include "strutils.h"
+
+extern char *canonicalize_path(const char *path);
+extern char *canonicalize_path_restricted(const char *path);
+extern char *canonicalize_dm_name(const char *ptname);
+extern char *__canonicalize_dm_name(const char *prefix, const char *ptname);
+
+extern char *absolute_path(const char *path);
+
+static inline int is_relative_path(const char *path)
+{
+ if (!path || *path == '/')
+ return 0;
+ return 1;
+}
+
+#endif /* CANONICALIZE_H */
diff --git a/include/caputils.h b/include/caputils.h
new file mode 100644
index 0000000..852903a
--- /dev/null
+++ b/include/caputils.h
@@ -0,0 +1,34 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef CAPUTILS_H
+#define CAPUTILS_H
+
+#include <linux/capability.h>
+
+#ifndef PR_CAP_AMBIENT
+# define PR_CAP_AMBIENT 47
+# define PR_CAP_AMBIENT_IS_SET 1
+# define PR_CAP_AMBIENT_RAISE 2
+# define PR_CAP_AMBIENT_LOWER 3
+#endif
+
+extern int capset(cap_user_header_t header, cap_user_data_t data);
+extern int capget(cap_user_header_t header, const cap_user_data_t data);
+
+extern int cap_last_cap(void);
+
+#endif /* CAPUTILS_H */
diff --git a/include/carefulputc.h b/include/carefulputc.h
new file mode 100644
index 0000000..8860b12
--- /dev/null
+++ b/include/carefulputc.h
@@ -0,0 +1,74 @@
+#ifndef UTIL_LINUX_CAREFULPUTC_H
+#define UTIL_LINUX_CAREFULPUTC_H
+
+/*
+ * A putc() for use in write and wall (that sometimes are sgid tty).
+ * It avoids control characters in our locale, and also ASCII control
+ * characters. Note that the locale of the recipient is unknown.
+*/
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "cctype.h"
+
+static inline int fputc_careful(int c, FILE *fp, const char fail)
+{
+ int ret;
+
+ if (isprint(c) || c == '\a' || c == '\t' || c == '\r' || c == '\n')
+ ret = putc(c, fp);
+ else if (!c_isascii(c))
+ ret = fprintf(fp, "\\%3o", (unsigned char)c);
+ else {
+ ret = putc(fail, fp);
+ if (ret != EOF)
+ ret = putc(c ^ 0x40, fp);
+ }
+ return (ret < 0) ? EOF : 0;
+}
+
+static inline void fputs_quoted_case(const char *data, FILE *out, int dir)
+{
+ const char *p;
+
+ fputc('"', out);
+ for (p = data; p && *p; p++) {
+ if ((unsigned char) *p == 0x22 || /* " */
+ (unsigned char) *p == 0x5c || /* \ */
+ (unsigned char) *p == 0x60 || /* ` */
+ (unsigned char) *p == 0x24 || /* $ */
+ !isprint((unsigned char) *p) ||
+ iscntrl((unsigned char) *p)) {
+
+ fprintf(out, "\\x%02x", (unsigned char) *p);
+ } else
+ fputc(dir == 1 ? toupper(*p) :
+ dir == -1 ? tolower(*p) :
+ *p, out);
+ }
+ fputc('"', out);
+}
+
+#define fputs_quoted(_d, _o) fputs_quoted_case(_d, _o, 0)
+#define fputs_quoted_upper(_d, _o) fputs_quoted_case(_d, _o, 1)
+#define fputs_quoted_lower(_d, _o) fputs_quoted_case(_d, _o, -1)
+
+static inline void fputs_nonblank(const char *data, FILE *out)
+{
+ const char *p;
+
+ for (p = data; p && *p; p++) {
+ if (isblank((unsigned char) *p) ||
+ (unsigned char) *p == 0x5c || /* \ */
+ !isprint((unsigned char) *p) ||
+ iscntrl((unsigned char) *p)) {
+
+ fprintf(out, "\\x%02x", (unsigned char) *p);
+
+ } else
+ fputc(*p, out);
+ }
+}
+
+#endif /* _CAREFULPUTC_H */
diff --git a/include/cctype.h b/include/cctype.h
new file mode 100644
index 0000000..6ab644c
--- /dev/null
+++ b/include/cctype.h
@@ -0,0 +1,325 @@
+/**
+ * Character handling in C locale.
+ *
+ * This file is based on gnulib c-ctype.h-dd7a871 with the
+ * other gnulib dependencies removed for use in util-linux.
+ *
+ * These functions work like the corresponding functions in <ctype.h>,
+ * except that they have the C (POSIX) locale hardwired, whereas the
+ * <ctype.h> functions' behaviour depends on the current locale set via
+ * setlocale.
+ *
+ * Copyright (C) 2000-2003, 2006, 2008-2017 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UTIL_LINUX_CCTYPE_H
+#define UTIL_LINUX_CCTYPE_H
+
+/**
+ * The functions defined in this file assume the "C" locale and a character
+ * set without diacritics (ASCII-US or EBCDIC-US or something like that).
+ * Even if the "C" locale on a particular system is an extension of the ASCII
+ * character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it
+ * is ISO-8859-1), the functions in this file recognize only the ASCII
+ * characters.
+ */
+
+#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)
+
+/*
+ * The character set is ASCII or one of its variants or extensions, not EBCDIC.
+ * Testing the value of '\n' and '\r' is not relevant.
+ */
+# define C_CTYPE_ASCII 1
+#elif ! (' ' == '\x40' && '0' == '\xf0' \
+ && 'A' == '\xc1' && 'J' == '\xd1' && 'S' == '\xe2' \
+ && 'a' == '\x81' && 'j' == '\x91' && 's' == '\xa2')
+# error "Only ASCII and EBCDIC are supported"
+#endif
+
+#if 'A' < 0
+# error "EBCDIC and char is signed -- not supported"
+#endif
+
+/* Cases for control characters. */
+#define _C_CTYPE_CNTRL \
+ case '\a': case '\b': case '\f': case '\n': \
+ case '\r': case '\t': case '\v': \
+ _C_CTYPE_OTHER_CNTRL
+
+/* ASCII control characters other than those with \-letter escapes. */
+#if C_CTYPE_ASCII
+# define _C_CTYPE_OTHER_CNTRL \
+ case '\x00': case '\x01': case '\x02': case '\x03': \
+ case '\x04': case '\x05': case '\x06': case '\x0e': \
+ case '\x0f': case '\x10': case '\x11': case '\x12': \
+ case '\x13': case '\x14': case '\x15': case '\x16': \
+ case '\x17': case '\x18': case '\x19': case '\x1a': \
+ case '\x1b': case '\x1c': case '\x1d': case '\x1e': \
+ case '\x1f': case '\x7f'
+#else
+
+/*
+ * Use EBCDIC code page 1047's assignments for ASCII control chars;
+ * assume all EBCDIC code pages agree about these assignments.
+ */
+# define _C_CTYPE_OTHER_CNTRL \
+ case '\x00': case '\x01': case '\x02': case '\x03': \
+ case '\x07': case '\x0e': case '\x0f': case '\x10': \
+ case '\x11': case '\x12': case '\x13': case '\x18': \
+ case '\x19': case '\x1c': case '\x1d': case '\x1e': \
+ case '\x1f': case '\x26': case '\x27': case '\x2d': \
+ case '\x2e': case '\x32': case '\x37': case '\x3c': \
+ case '\x3d': case '\x3f'
+#endif
+
+/* Cases for lowercase hex letters, and lowercase letters, all offset by N. */
+#define _C_CTYPE_LOWER_A_THRU_F_N(N) \
+ case 'a' + (N): case 'b' + (N): case 'c' + (N): case 'd' + (N): \
+ case 'e' + (N): case 'f' + (N)
+#define _C_CTYPE_LOWER_N(N) \
+ _C_CTYPE_LOWER_A_THRU_F_N(N): \
+ case 'g' + (N): case 'h' + (N): case 'i' + (N): case 'j' + (N): \
+ case 'k' + (N): case 'l' + (N): case 'm' + (N): case 'n' + (N): \
+ case 'o' + (N): case 'p' + (N): case 'q' + (N): case 'r' + (N): \
+ case 's' + (N): case 't' + (N): case 'u' + (N): case 'v' + (N): \
+ case 'w' + (N): case 'x' + (N): case 'y' + (N): case 'z' + (N)
+
+/* Cases for hex letters, digits, lower, punct, and upper. */
+#define _C_CTYPE_A_THRU_F \
+ _C_CTYPE_LOWER_A_THRU_F_N (0): \
+ _C_CTYPE_LOWER_A_THRU_F_N ('A' - 'a')
+#define _C_CTYPE_DIGIT \
+ case '0': case '1': case '2': case '3': \
+ case '4': case '5': case '6': case '7': \
+ case '8': case '9'
+#define _C_CTYPE_LOWER _C_CTYPE_LOWER_N (0)
+#define _C_CTYPE_PUNCT \
+ case '!': case '"': case '#': case '$': \
+ case '%': case '&': case '\'': case '(': \
+ case ')': case '*': case '+': case ',': \
+ case '-': case '.': case '/': case ':': \
+ case ';': case '<': case '=': case '>': \
+ case '?': case '@': case '[': case '\\': \
+ case ']': case '^': case '_': case '`': \
+ case '{': case '|': case '}': case '~'
+#define _C_CTYPE_UPPER _C_CTYPE_LOWER_N ('A' - 'a')
+
+/**
+ * Function definitions.
+ *
+ * Unlike the functions in <ctype.h>, which require an argument in the range
+ * of the 'unsigned char' type, the functions here operate on values that are
+ * in the 'unsigned char' range or in the 'char' range. In other words,
+ * when you have a 'char' value, you need to cast it before using it as
+ * argument to a <ctype.h> function:
+ *
+ * const char *s = ...;
+ * if (isalpha ((unsigned char) *s)) ...
+ *
+ * but you don't need to cast it for the functions defined in this file:
+ *
+ * const char *s = ...;
+ * if (c_isalpha (*s)) ...
+ */
+
+static inline int c_isalnum (int c)
+{
+ switch (c) {
+ _C_CTYPE_DIGIT:
+ _C_CTYPE_LOWER:
+ _C_CTYPE_UPPER:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static inline int c_isalpha (int c)
+{
+ switch (c) {
+ _C_CTYPE_LOWER:
+ _C_CTYPE_UPPER:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* The function isascii is not locale dependent.
+ * Its use in EBCDIC is questionable.
+ */
+static inline int c_isascii (int c)
+{
+ switch (c) {
+ case ' ':
+ _C_CTYPE_CNTRL:
+ _C_CTYPE_DIGIT:
+ _C_CTYPE_LOWER:
+ _C_CTYPE_PUNCT:
+ _C_CTYPE_UPPER:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static inline int c_isblank (int c)
+{
+ return c == ' ' || c == '\t';
+}
+
+static inline int c_iscntrl (int c)
+{
+ switch (c) {
+ _C_CTYPE_CNTRL:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static inline int c_isdigit (int c)
+{
+ switch (c) {
+ _C_CTYPE_DIGIT:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static inline int c_isgraph (int c)
+{
+ switch (c) {
+ _C_CTYPE_DIGIT:
+ _C_CTYPE_LOWER:
+ _C_CTYPE_PUNCT:
+ _C_CTYPE_UPPER:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static inline int c_islower (int c)
+{
+ switch (c) {
+ _C_CTYPE_LOWER:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static inline int c_isprint (int c)
+{
+ switch (c) {
+ case ' ':
+ _C_CTYPE_DIGIT:
+ _C_CTYPE_LOWER:
+ _C_CTYPE_PUNCT:
+ _C_CTYPE_UPPER:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static inline int c_ispunct (int c)
+{
+ switch (c) {
+ _C_CTYPE_PUNCT:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static inline int c_isspace (int c)
+{
+ switch (c) {
+ case ' ': case '\t': case '\n': case '\v': case '\f': case '\r':
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static inline int c_isupper (int c)
+{
+ switch (c) {
+ _C_CTYPE_UPPER:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static inline int c_isxdigit (int c)
+{
+ switch (c) {
+ _C_CTYPE_DIGIT:
+ _C_CTYPE_A_THRU_F:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static inline int c_tolower (int c)
+{
+ switch (c) {
+ _C_CTYPE_UPPER:
+ return c - 'A' + 'a';
+ default:
+ return c;
+ }
+}
+
+static inline int c_toupper (int c)
+{
+ switch (c) {
+ _C_CTYPE_LOWER:
+ return c - 'a' + 'A';
+ default:
+ return c;
+ }
+}
+
+#endif /* UTIL_LINUX_CCTYPE_H */
diff --git a/include/closestream.h b/include/closestream.h
new file mode 100644
index 0000000..8e5d18d
--- /dev/null
+++ b/include/closestream.h
@@ -0,0 +1,110 @@
+#ifndef UTIL_LINUX_CLOSESTREAM_H
+#define UTIL_LINUX_CLOSESTREAM_H
+
+#include <stdio.h>
+#ifdef HAVE_STDIO_EXT_H
+#include <stdio_ext.h>
+#endif
+#include <unistd.h>
+
+#include "c.h"
+#include "nls.h"
+
+#ifndef CLOSE_EXIT_CODE
+# define CLOSE_EXIT_CODE EXIT_FAILURE
+#endif
+
+static inline int
+close_stream(FILE * stream)
+{
+#ifdef HAVE___FPENDING
+ const int some_pending = (__fpending(stream) != 0);
+#endif
+ const int prev_fail = (ferror(stream) != 0);
+ const int fclose_fail = (fclose(stream) != 0);
+
+ if (prev_fail || (fclose_fail && (
+#ifdef HAVE___FPENDING
+ some_pending ||
+#endif
+ errno != EBADF))) {
+ if (!fclose_fail && !(errno == EPIPE))
+ errno = 0;
+ return EOF;
+ }
+ return 0;
+}
+
+static inline int
+flush_standard_stream(FILE *stream)
+{
+ int fd;
+
+ errno = 0;
+
+ if (ferror(stream) != 0 || fflush(stream) != 0)
+ goto error;
+
+ /*
+ * Calling fflush is not sufficient on some filesystems
+ * like e.g. NFS, which may defer the actual flush until
+ * close. Calling fsync would help solve this, but would
+ * probably result in a performance hit. Thus, we work
+ * around this issue by calling close on a dup'd file
+ * descriptor from the stream.
+ */
+ if ((fd = fileno(stream)) < 0 || (fd = dup(fd)) < 0 || close(fd) != 0)
+ goto error;
+
+ return 0;
+error:
+ return (errno == EBADF) ? 0 : EOF;
+}
+
+/* Meant to be used atexit(close_stdout); */
+static inline void
+close_stdout(void)
+{
+ if (flush_standard_stream(stdout) != 0 && !(errno == EPIPE)) {
+ if (errno)
+ warn(_("write error"));
+ else
+ warnx(_("write error"));
+ _exit(CLOSE_EXIT_CODE);
+ }
+
+ if (flush_standard_stream(stderr) != 0)
+ _exit(CLOSE_EXIT_CODE);
+}
+
+static inline void
+close_stdout_atexit(void)
+{
+ /*
+ * Note that close stdout at exit disables ASAN to report memory leaks
+ */
+#if !HAS_FEATURE_ADDRESS_SANITIZER
+ atexit(close_stdout);
+#endif
+}
+
+#ifndef HAVE_FSYNC
+static inline int
+fsync(int fd __attribute__((__unused__)))
+{
+ return 0;
+}
+#endif
+
+static inline int
+close_fd(int fd)
+{
+ const int fsync_fail = (fsync(fd) != 0);
+ const int close_fail = (close(fd) != 0);
+
+ if (fsync_fail || close_fail)
+ return EOF;
+ return 0;
+}
+
+#endif /* UTIL_LINUX_CLOSESTREAM_H */
diff --git a/include/color-names.h b/include/color-names.h
new file mode 100644
index 0000000..42f6f8f
--- /dev/null
+++ b/include/color-names.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012-2015 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be distributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#ifndef UTIL_LINUX_COLOR_NAMES_H
+#define UTIL_LINUX_COLOR_NAMES_H
+
+#define UL_COLOR_RESET "\033[0m"
+#define UL_COLOR_BOLD "\033[1m"
+#define UL_COLOR_HALFBRIGHT "\033[2m"
+#define UL_COLOR_UNDERSCORE "\033[4m"
+#define UL_COLOR_BLINK "\033[5m"
+#define UL_COLOR_REVERSE "\033[7m"
+
+/* Standard colors */
+#define UL_COLOR_BLACK "\033[30m"
+#define UL_COLOR_RED "\033[31m"
+#define UL_COLOR_GREEN "\033[32m"
+#define UL_COLOR_BROWN "\033[33m" /* well, brown */
+#define UL_COLOR_BLUE "\033[34m"
+#define UL_COLOR_MAGENTA "\033[35m"
+#define UL_COLOR_CYAN "\033[36m"
+#define UL_COLOR_GRAY "\033[37m"
+
+/* Bold variants */
+#define UL_COLOR_DARK_GRAY "\033[1;30m"
+#define UL_COLOR_BOLD_RED "\033[1;31m"
+#define UL_COLOR_BOLD_GREEN "\033[1;32m"
+#define UL_COLOR_BOLD_YELLOW "\033[1;33m"
+#define UL_COLOR_BOLD_BLUE "\033[1;34m"
+#define UL_COLOR_BOLD_MAGENTA "\033[1;35m"
+#define UL_COLOR_BOLD_CYAN "\033[1;36m"
+
+#define UL_COLOR_WHITE "\033[1;37m"
+
+
+/* maximal length of human readable name of ESC seq. */
+#define UL_COLORNAME_MAXSZ 32
+
+extern const char *color_sequence_from_colorname(const char *str);
+
+#endif /* UTIL_LINUX_COLOR_NAMES_H */
diff --git a/include/colors.h b/include/colors.h
new file mode 100644
index 0000000..d4ae4e4
--- /dev/null
+++ b/include/colors.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2012 Ondrej Oprala <ooprala@redhat.com>
+ * Copyright (C) 2012-2014 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be distributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#ifndef UTIL_LINUX_COLORS_H
+#define UTIL_LINUX_COLORS_H
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include "color-names.h"
+
+/* --color[=WHEN] */
+enum colortmode {
+ UL_COLORMODE_AUTO = 0,
+ UL_COLORMODE_NEVER,
+ UL_COLORMODE_ALWAYS,
+ UL_COLORMODE_UNDEF,
+
+ __UL_NCOLORMODES /* last */
+};
+
+#ifdef USE_COLORS_BY_DEFAULT
+# define USAGE_COLORS_DEFAULT _("colors are enabled by default")
+#else
+# define USAGE_COLORS_DEFAULT _("colors are disabled by default")
+#endif
+
+extern int colormode_from_string(const char *str);
+extern int colormode_or_err(const char *str, const char *errmsg);
+
+/* Initialize the global variable UL_COLOR_TERM_OK */
+extern int colors_init(int mode, const char *util_name);
+
+/* Returns 1 or 0 */
+extern int colors_wanted(void);
+
+/* Returns UL_COLORMODE_* */
+extern int colors_mode(void);
+
+/* temporary enable/disable colors */
+extern void colors_off(void);
+extern void colors_on(void);
+
+
+/* Set the color */
+extern void color_fenable(const char *seq, FILE *f);
+
+extern void color_scheme_fenable(const char *name, const char *dflt, FILE *f);
+extern const char *color_scheme_get_sequence(const char *name, const char *dflt);
+
+static inline void color_enable(const char *seq)
+{
+ color_fenable(seq, stdout);
+}
+
+static inline void color_scheme_enable(const char *name, const char *dflt)
+{
+ color_scheme_fenable(name, dflt, stdout);
+}
+
+/* Reset colors to default */
+extern void color_fdisable(FILE *f);
+
+static inline void color_disable(void)
+{
+ color_fdisable(stdout);
+}
+
+#endif /* UTIL_LINUX_COLORS_H */
diff --git a/include/cpuset.h b/include/cpuset.h
new file mode 100644
index 0000000..5a531bf
--- /dev/null
+++ b/include/cpuset.h
@@ -0,0 +1,99 @@
+/*
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#ifndef UTIL_LINUX_CPUSET_H
+#define UTIL_LINUX_CPUSET_H
+
+#include <sched.h>
+
+/*
+ * Fallback for old or obscure libcs without dynamically allocated cpusets
+ *
+ * The following macros are based on code from glibc.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ */
+#if !HAVE_DECL_CPU_ALLOC
+
+# define CPU_ZERO_S(setsize, cpusetp) \
+ do { \
+ size_t __i; \
+ size_t __imax = (setsize) / sizeof (__cpu_mask); \
+ __cpu_mask *__bits = (cpusetp)->__bits; \
+ for (__i = 0; __i < __imax; ++__i) \
+ __bits[__i] = 0; \
+ } while (0)
+
+# define CPU_SET_S(cpu, setsize, cpusetp) \
+ ({ size_t __cpu = (cpu); \
+ __cpu < 8 * (setsize) \
+ ? (((__cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)] \
+ |= __CPUMASK (__cpu)) \
+ : 0; })
+
+# define CPU_ISSET_S(cpu, setsize, cpusetp) \
+ ({ size_t __cpu = (cpu); \
+ __cpu < 8 * (setsize) \
+ ? ((((__cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)] \
+ & __CPUMASK (__cpu))) != 0 \
+ : 0; })
+
+# define CPU_EQUAL_S(setsize, cpusetp1, cpusetp2) \
+ ({ __cpu_mask *__arr1 = (cpusetp1)->__bits; \
+ __cpu_mask *__arr2 = (cpusetp2)->__bits; \
+ size_t __imax = (setsize) / sizeof (__cpu_mask); \
+ size_t __i; \
+ for (__i = 0; __i < __imax; ++__i) \
+ if (__arr1[__i] != __arr2[__i]) \
+ break; \
+ __i == __imax; })
+
+extern int __cpuset_count_s(size_t setsize, const cpu_set_t *set);
+# define CPU_COUNT_S(setsize, cpusetp) __cpuset_count_s(setsize, cpusetp)
+
+# define CPU_ALLOC_SIZE(count) \
+ ((((count) + __NCPUBITS - 1) / __NCPUBITS) * sizeof (__cpu_mask))
+# define CPU_ALLOC(count) (malloc(CPU_ALLOC_SIZE(count)))
+# define CPU_FREE(cpuset) (free(cpuset))
+
+#endif /* !HAVE_DECL_CPU_ALLOC */
+
+
+#define cpuset_nbits(setsize) (8 * (setsize))
+
+/*
+ * The @idx parameter returns an index of the first mask from @ary array where
+ * the @cpu is set.
+ *
+ * Returns: 0 if found, otherwise 1.
+ */
+static inline int cpuset_ary_isset(size_t cpu, cpu_set_t **ary, size_t nmemb,
+ size_t setsize, size_t *idx)
+{
+ size_t i;
+
+ for (i = 0; i < nmemb; i++) {
+ if (CPU_ISSET_S(cpu, setsize, ary[i])) {
+ *idx = i;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+extern int get_max_number_of_cpus(void);
+
+extern cpu_set_t *cpuset_alloc(int ncpus, size_t *setsize, size_t *nbits);
+extern void cpuset_free(cpu_set_t *set);
+
+extern char *cpulist_create(char *str, size_t len, cpu_set_t *set, size_t setsize);
+extern int cpulist_parse(const char *str, cpu_set_t *set, size_t setsize, int fail);
+
+extern char *cpumask_create(char *str, size_t len, cpu_set_t *set, size_t setsize);
+extern int cpumask_parse(const char *str, cpu_set_t *set, size_t setsize);
+
+#endif /* UTIL_LINUX_CPUSET_H */
diff --git a/include/crc32.h b/include/crc32.h
new file mode 100644
index 0000000..2551f50
--- /dev/null
+++ b/include/crc32.h
@@ -0,0 +1,12 @@
+#ifndef UL_NG_CRC32_H
+#define UL_NG_CRC32_H
+
+#include <sys/types.h>
+#include <stdint.h>
+
+extern uint32_t ul_crc32(uint32_t seed, const unsigned char *buf, size_t len);
+extern uint32_t ul_crc32_exclude_offset(uint32_t seed, const unsigned char *buf, size_t len,
+ size_t exclude_off, size_t exclude_len);
+
+#endif
+
diff --git a/include/crc32c.h b/include/crc32c.h
new file mode 100644
index 0000000..1c50839
--- /dev/null
+++ b/include/crc32c.h
@@ -0,0 +1,9 @@
+#ifndef UL_NG_CRC32C_H
+#define UL_NG_CRC32C_H
+
+#include <sys/types.h>
+#include <stdint.h>
+
+extern uint32_t crc32c(uint32_t crc, const void *buf, size_t size);
+
+#endif /* UL_NG_CRC32C_H */
diff --git a/include/debug.h b/include/debug.h
new file mode 100644
index 0000000..39c21d5
--- /dev/null
+++ b/include/debug.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2014 Ondrej Oprala <ooprala@redhat.com>
+ * Copyright (C) 2014 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be distributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#ifndef UTIL_LINUX_DEBUG_H
+#define UTIL_LINUX_DEBUG_H
+
+
+/*
+ * util-linux debug macros
+ *
+ * The debug stuff is based on <name>_debug_mask that controls what outputs is
+ * expected. The mask is usually initialized by <NAME>_DEBUG= env.variable
+ *
+ * After successful initialization the flag <PREFIX>_DEBUG_INIT is always set
+ * to the mask (this flag is required). The <PREFIX> is usually library API
+ * prefix (e.g. MNT_) or program name (e.g. CFDISK_)
+ *
+ * In the code is possible to use
+ *
+ * DBG(FOO, ul_debug("this is output for foo"));
+ *
+ * where for the FOO has to be defined <PREFIX>_DEBUG_FOO.
+ *
+ * It's possible to initialize the mask by comma delimited strings with
+ * subsystem names (e.g. "LIBMOUNT_DEBUG=options,tab"). In this case is
+ * necessary to define mask names array. This functionality is optional.
+ *
+ * It's strongly recommended to use UL_* macros to define/declare/use
+ * the debug stuff.
+ *
+ * See disk-utils/cfdisk.c: cfdisk_init_debug() for programs debug
+ * or libmount/src/init.c: mnt_init_debug() for library debug
+ *
+ */
+
+#include <stdarg.h>
+#include <string.h>
+
+struct ul_debug_maskname {
+ const char *name;
+ int mask;
+ const char *help;
+};
+#define UL_DEBUG_EMPTY_MASKNAMES {{ NULL, 0, NULL }}
+#define UL_DEBUG_DEFINE_MASKNAMES(m) static const struct ul_debug_maskname m ## _masknames[]
+#define UL_DEBUG_MASKNAMES(m) m ## _masknames
+
+#define UL_DEBUG_MASK(m) m ## _debug_mask
+#define UL_DEBUG_DEFINE_MASK(m) int UL_DEBUG_MASK(m)
+#define UL_DEBUG_DECLARE_MASK(m) extern UL_DEBUG_DEFINE_MASK(m)
+
+/*
+ * Internal mask flags (above 0xffffff)
+ */
+#define __UL_DEBUG_FL_NOADDR (1 << 24) /* Don't print object address */
+
+
+/* l - library name, p - flag prefix, m - flag postfix, x - function */
+#define __UL_DBG(l, p, m, x) \
+ do { \
+ if ((p ## m) & l ## _debug_mask) { \
+ fprintf(stderr, "%d: %s: %8s: ", getpid(), # l, # m); \
+ x; \
+ } \
+ } while (0)
+
+#define __UL_DBG_CALL(l, p, m, x) \
+ do { \
+ if ((p ## m) & l ## _debug_mask) { \
+ x; \
+ } \
+ } while (0)
+
+#define __UL_DBG_FLUSH(l, p) \
+ do { \
+ if (l ## _debug_mask && \
+ l ## _debug_mask != p ## INIT) { \
+ fflush(stderr); \
+ } \
+ } while (0)
+
+#define __UL_INIT_DEBUG_FROM_STRING(lib, pref, mask, str) \
+ do { \
+ if (lib ## _debug_mask & pref ## INIT) \
+ ; \
+ else if (!mask && str) { \
+ lib ## _debug_mask = ul_debug_parse_mask(lib ## _masknames, str); \
+ } else \
+ lib ## _debug_mask = mask; \
+ if (lib ## _debug_mask) { \
+ if (getuid() != geteuid() || getgid() != getegid()) { \
+ lib ## _debug_mask |= __UL_DEBUG_FL_NOADDR; \
+ fprintf(stderr, "%d: %s: don't print memory addresses (SUID executable).\n", getpid(), # lib); \
+ } \
+ } \
+ lib ## _debug_mask |= pref ## INIT; \
+ } while (0)
+
+
+#define __UL_INIT_DEBUG_FROM_ENV(lib, pref, mask, env) \
+ do { \
+ const char *envstr = mask ? NULL : getenv(# env); \
+ __UL_INIT_DEBUG_FROM_STRING(lib, pref, mask, envstr); \
+ } while (0)
+
+
+
+static inline void __attribute__ ((__format__ (__printf__, 1, 2)))
+ul_debug(const char *mesg, ...)
+{
+ va_list ap;
+ va_start(ap, mesg);
+ vfprintf(stderr, mesg, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+}
+
+static inline int ul_debug_parse_mask(
+ const struct ul_debug_maskname flagnames[],
+ const char *mask)
+{
+ int res;
+ char *ptr;
+
+ /* let's check for a numeric mask first */
+ res = strtoul(mask, &ptr, 0);
+
+ /* perhaps it's a comma-separated string? */
+ if (ptr && *ptr && flagnames && flagnames[0].name) {
+ char *msbuf, *ms, *name;
+ res = 0;
+
+ ms = msbuf = strdup(mask);
+ if (!ms)
+ return res;
+
+ while ((name = strtok_r(ms, ",", &ptr))) {
+ const struct ul_debug_maskname *d;
+ ms = ptr;
+
+ for (d = flagnames; d && d->name; d++) {
+ if (strcmp(name, d->name) == 0) {
+ res |= d->mask;
+ break;
+ }
+ }
+ /* nothing else we can do by OR-ing the mask */
+ if (res == 0xffff)
+ break;
+ }
+ free(msbuf);
+ } else if (ptr && strcmp(ptr, "all") == 0)
+ res = 0xffff;
+
+ return res;
+}
+
+static inline void ul_debug_print_masks(
+ const char *env,
+ const struct ul_debug_maskname flagnames[])
+{
+ const struct ul_debug_maskname *d;
+
+ if (!flagnames)
+ return;
+
+ fprintf(stderr, "Available \"%s=<name>[,...]|<mask>\" debug masks:\n",
+ env);
+ for (d = flagnames; d && d->name; d++) {
+ if (!d->help)
+ continue;
+ fprintf(stderr, " %-8s [0x%04x] : %s\n",
+ d->name, d->mask, d->help);
+ }
+}
+
+#endif /* UTIL_LINUX_DEBUG_H */
diff --git a/include/debugobj.h b/include/debugobj.h
new file mode 100644
index 0000000..73b70b8
--- /dev/null
+++ b/include/debugobj.h
@@ -0,0 +1,22 @@
+#ifndef UTIL_LINUX_DEBUGOBJ_H
+#define UTIL_LINUX_DEBUGOBJ_H
+
+/*
+ * Include *after* debug.h and after UL_DEBUG_CURRENT_MASK define.
+ */
+
+static inline void __attribute__ ((__format__ (__printf__, 2, 3)))
+ul_debugobj(const void *handler, const char *mesg, ...)
+{
+ va_list ap;
+
+ if (handler && !(UL_DEBUG_CURRENT_MASK & __UL_DEBUG_FL_NOADDR))
+ fprintf(stderr, "[%p]: ", handler);
+
+ va_start(ap, mesg);
+ vfprintf(stderr, mesg, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+}
+
+#endif /* UTIL_LINUX_DEBUGOBJ_H */
diff --git a/include/encode.h b/include/encode.h
new file mode 100644
index 0000000..b259ab5
--- /dev/null
+++ b/include/encode.h
@@ -0,0 +1,14 @@
+#ifndef UTIL_LINUX_ENCODE_H
+#define UTIL_LINUX_ENCODE_H
+
+extern size_t ul_encode_to_utf8(int enc, unsigned char *dest, size_t len,
+ const unsigned char *src, size_t count)
+ __attribute__((nonnull));
+
+enum {
+ UL_ENCODE_UTF16BE = 0,
+ UL_ENCODE_UTF16LE,
+ UL_ENCODE_LATIN1
+};
+
+#endif
diff --git a/include/env.h b/include/env.h
new file mode 100644
index 0000000..c2caecb
--- /dev/null
+++ b/include/env.h
@@ -0,0 +1,35 @@
+#ifndef UTIL_LINUX_ENV_H
+#define UTIL_LINUX_ENV_H
+
+#include "c.h"
+#include "nls.h"
+
+struct ul_env_list;
+
+extern void sanitize_env(void);
+extern void __sanitize_env(struct ul_env_list **org);
+
+extern int env_list_setenv(struct ul_env_list *ls);
+extern void env_list_free(struct ul_env_list *ls);
+
+extern char *safe_getenv(const char *arg);
+
+
+#ifndef XSETENV_EXIT_CODE
+# define XSETENV_EXIT_CODE EXIT_FAILURE
+#endif
+
+static inline void xsetenv(char const *name, char const *val, int overwrite)
+{
+ if (setenv(name, val, overwrite) != 0)
+ err(XSETENV_EXIT_CODE, _("failed to set the %s environment variable"), name);
+}
+
+static inline int remote_entry(char **argv, int remove, int last)
+{
+ memmove(argv + remove, argv + remove + 1, sizeof(char *) * (last - remove));
+ return last - 1;
+}
+
+#endif /* UTIL_LINUX_ENV_H */
+
diff --git a/include/exec_shell.h b/include/exec_shell.h
new file mode 100644
index 0000000..04aa089
--- /dev/null
+++ b/include/exec_shell.h
@@ -0,0 +1,6 @@
+#ifndef UTIL_LINUX_EXEC_SHELL_H
+#define UTIL_LINUX_EXEC_SHELL_H
+
+extern void exec_shell(void) __attribute__((__noreturn__));
+
+#endif /* UTIL_LINUX_EXEC_SHELL_H */
diff --git a/include/exitcodes.h b/include/exitcodes.h
new file mode 100644
index 0000000..f28f68e
--- /dev/null
+++ b/include/exitcodes.h
@@ -0,0 +1,25 @@
+#ifndef UTIL_LINUX_EXITCODES_H
+#define UTIL_LINUX_EXITCODES_H
+/*
+ * BE CAREFUL
+ *
+ * These exit codes are part of the official interface for mount,
+ * fsck, mkfs, etc. wrappers.
+ */
+
+/* Exit codes used by mkfs-type programs */
+#define MKFS_EX_OK 0 /* No errors */
+#define MKFS_EX_ERROR 8 /* Operational error */
+#define MKFS_EX_USAGE 16 /* Usage or syntax error */
+
+/* Exit codes used by fsck-type programs */
+#define FSCK_EX_OK 0 /* No errors */
+#define FSCK_EX_NONDESTRUCT 1 /* File system errors corrected */
+#define FSCK_EX_REBOOT 2 /* System should be rebooted */
+#define FSCK_EX_DESTRUCT FSCK_EX_REBOOT /* Alias */
+#define FSCK_EX_UNCORRECTED 4 /* File system errors left uncorrected */
+#define FSCK_EX_ERROR 8 /* Operational error */
+#define FSCK_EX_USAGE 16 /* Usage or syntax error */
+#define FSCK_EX_LIBRARY 128 /* Shared library error */
+
+#endif /* UTIL_LINUX_EXITCODES_H */
diff --git a/include/fileeq.h b/include/fileeq.h
new file mode 100644
index 0000000..3988ed0
--- /dev/null
+++ b/include/fileeq.h
@@ -0,0 +1,53 @@
+#ifndef UTIL_LINUX_FILEEQ
+#define UTIL_LINUX_FILEEQ
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+/* Number of bytes from the beginning of the file we always
+ * compare by memcmp() */
+#define UL_FILEEQ_INTROSIZ 32
+
+struct ul_fileeq_data {
+ unsigned char intro[UL_FILEEQ_INTROSIZ];
+ unsigned char *blocks;
+ size_t nblocks;
+ size_t maxblocks;
+ int fd;
+ const char *name;
+ bool is_eof;
+};
+
+struct ul_fileeq {
+ int fd_api; /* Crypto socket */
+ int fd_cip; /* Cipher handler */
+
+ size_t readsiz;
+ uint64_t filesiz;
+ uint64_t blocksmax;
+ const struct ul_fileeq_method *method;
+
+ /* UL_FILEEQ_MEMCMP buffers */
+ unsigned char *buf_a;
+ unsigned char *buf_b;
+ unsigned char *buf_last;
+};
+
+extern int ul_fileeq_init(struct ul_fileeq *eq, const char *method);
+extern void ul_fileeq_deinit(struct ul_fileeq *eq);
+
+
+extern int ul_fileeq_data_associated(struct ul_fileeq_data *data);
+extern void ul_fileeq_data_close_file(struct ul_fileeq_data *data);
+extern void ul_fileeq_data_init(struct ul_fileeq_data *data);
+extern void ul_fileeq_data_deinit(struct ul_fileeq_data *data);
+extern void ul_fileeq_data_set_file(struct ul_fileeq_data *data,
+ const char *name);
+extern size_t ul_fileeq_set_size(struct ul_fileeq *eq, uint64_t filesiz,
+ size_t readsiz, size_t memsiz);
+
+extern int ul_fileeq(struct ul_fileeq *eq,
+ struct ul_fileeq_data *a, struct ul_fileeq_data *b);
+
+#endif /* UTIL_LINUX_FILEEQ */
diff --git a/include/fileutils.h b/include/fileutils.h
new file mode 100644
index 0000000..8722ed5
--- /dev/null
+++ b/include/fileutils.h
@@ -0,0 +1,103 @@
+#ifndef UTIL_LINUX_FILEUTILS
+#define UTIL_LINUX_FILEUTILS
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+#include "c.h"
+
+extern int mkstemp_cloexec(char *template);
+
+extern int xmkstemp(char **tmpname, const char *dir, const char *prefix);
+
+static inline FILE *xfmkstemp(char **tmpname, const char *dir, const char *prefix)
+{
+ int fd;
+ FILE *ret;
+
+ fd = xmkstemp(tmpname, dir, prefix);
+ if (fd == -1)
+ return NULL;
+
+ if (!(ret = fdopen(fd, "w+" UL_CLOEXECSTR))) {
+ close(fd);
+ return NULL;
+ }
+ return ret;
+}
+
+#ifdef HAVE_OPENAT
+static inline FILE *fopen_at(int dir, const char *filename,
+ int flags, const char *mode)
+{
+ int fd = openat(dir, filename, flags);
+ FILE *ret;
+
+ if (fd < 0)
+ return NULL;
+
+ ret = fdopen(fd, mode);
+ if (!ret)
+ close(fd);
+ return ret;
+}
+#endif
+
+static inline int is_same_inode(const int fd, const struct stat *st)
+{
+ struct stat f;
+
+ if (fstat(fd, &f) < 0)
+ return 0;
+ else if (f.st_dev != st->st_dev || f.st_ino != st->st_ino)
+ return 0;
+ return 1;
+}
+
+extern int dup_fd_cloexec(int oldfd, int lowfd);
+extern unsigned int get_fd_tabsize(void);
+
+extern int ul_mkdir_p(const char *path, mode_t mode);
+extern char *stripoff_last_component(char *path);
+
+/* This is readdir()-like function, but skips "." and ".." directory entries */
+static inline struct dirent *xreaddir(DIR *dp)
+{
+ struct dirent *d;
+
+ while ((d = readdir(dp))) {
+ if (!strcmp(d->d_name, ".") ||
+ !strcmp(d->d_name, ".."))
+ continue;
+ break;
+ }
+ return d;
+}
+
+#ifdef HAVE_SYS_SYSCALL_H
+# include <sys/syscall.h>
+# if defined(SYS_close_range)
+# include <sys/types.h>
+# ifndef HAVE_CLOSE_RANGE
+static inline int close_range(unsigned int first, unsigned int last, int flags)
+{
+ return syscall(SYS_close_range, first, last, flags);
+}
+# endif
+# define HAVE_CLOSE_RANGE 1
+# endif /* SYS_close_range */
+#endif /* HAVE_SYS_SYSCALL_H */
+
+extern void ul_close_all_fds(unsigned int first, unsigned int last);
+
+#define UL_COPY_READ_ERROR (-1)
+#define UL_COPY_WRITE_ERROR (-2)
+int ul_copy_file(int from, int to);
+
+
+extern int ul_reopen(int fd, int flags);
+
+#endif /* UTIL_LINUX_FILEUTILS */
diff --git a/include/fuzz.h b/include/fuzz.h
new file mode 100644
index 0000000..1b0dbd2
--- /dev/null
+++ b/include/fuzz.h
@@ -0,0 +1,9 @@
+#ifndef UTIL_LINUX_FUZZ_H
+#define UTIL_LINUX_FUZZ_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+#endif /* UTIL_LINUX_FUZZ_H */
diff --git a/include/idcache.h b/include/idcache.h
new file mode 100644
index 0000000..912edd5
--- /dev/null
+++ b/include/idcache.h
@@ -0,0 +1,28 @@
+#ifndef UTIL_LINUX_IDCACHE_H
+#define UTIL_LINUX_IDCACHE_H
+
+#include <sys/types.h>
+#include <pwd.h>
+
+#define IDCACHE_FLAGS_NAMELEN (1 << 1)
+
+struct identry {
+ unsigned long int id;
+ char *name;
+ struct identry *next;
+};
+
+struct idcache {
+ struct identry *ent; /* first entry */
+ int width; /* name width */
+};
+
+
+extern struct idcache *new_idcache(void);
+extern void add_gid(struct idcache *cache, unsigned long int id);
+extern void add_uid(struct idcache *cache, unsigned long int id);
+
+extern void free_idcache(struct idcache *ic);
+extern struct identry *get_id(struct idcache *ic, unsigned long int id);
+
+#endif /* UTIL_LINUX_IDCACHE_H */
diff --git a/include/ismounted.h b/include/ismounted.h
new file mode 100644
index 0000000..57918cb
--- /dev/null
+++ b/include/ismounted.h
@@ -0,0 +1,14 @@
+#ifndef IS_MOUNTED_H
+#define IS_MOUNTED_H
+
+#define MF_MOUNTED 1
+#define MF_ISROOT 2
+#define MF_READONLY 4
+#define MF_SWAP 8
+#define MF_BUSY 16
+
+extern int is_mounted(const char *file);
+extern int check_mount_point(const char *device, int *mount_flags,
+ char *mtpt, int mtlen);
+
+#endif /* IS_MOUNTED_H */
diff --git a/include/iso9660.h b/include/iso9660.h
new file mode 100644
index 0000000..73decd9
--- /dev/null
+++ b/include/iso9660.h
@@ -0,0 +1,58 @@
+#ifndef UTIL_LINUX_ISO_H
+#define UTIL_LINUX_ISO_H
+
+#include <stdbool.h>
+
+#include "c.h"
+
+static inline int isonum_721(unsigned char *p)
+{
+ return ((p[0] & 0xff)
+ | ((p[1] & 0xff) << 8));
+}
+
+static inline int isonum_722(unsigned char *p)
+{
+ return ((p[1] & 0xff)
+ | ((p[0] & 0xff) << 8));
+}
+
+static inline int isonum_723(unsigned char *p, bool check_match)
+{
+ int le = isonum_721(p);
+ int be = isonum_722(p + 2);
+
+ if (check_match && le != be)
+ /* translation is useless */
+ warnx("723error: le=%d be=%d", le, be);
+ return (le);
+}
+
+static inline int isonum_731(unsigned char *p)
+{
+ return ((p[0] & 0xff)
+ | ((p[1] & 0xff) << 8)
+ | ((p[2] & 0xff) << 16)
+ | ((p[3] & 0xff) << 24));
+}
+
+static inline int isonum_732(unsigned char *p)
+{
+ return ((p[3] & 0xff)
+ | ((p[2] & 0xff) << 8)
+ | ((p[1] & 0xff) << 16)
+ | ((p[0] & 0xff) << 24));
+}
+
+static inline int isonum_733(unsigned char *p, bool check_match)
+{
+ int le = isonum_731(p);
+ int be = isonum_732(p + 4);
+
+ if (check_match && le != be)
+ /* translation is useless */
+ warnx("733error: le=%d be=%d", le, be);
+ return(le);
+}
+
+#endif
diff --git a/include/jsonwrt.h b/include/jsonwrt.h
new file mode 100644
index 0000000..396765c
--- /dev/null
+++ b/include/jsonwrt.h
@@ -0,0 +1,47 @@
+#ifndef UTIL_LINUX_JSONWRT_H
+#define UTIL_LINUX_JSONWRT_H
+
+enum {
+ UL_JSON_OBJECT,
+ UL_JSON_ARRAY,
+ UL_JSON_VALUE
+};
+
+struct ul_jsonwrt {
+ FILE *out;
+ int indent;
+
+ unsigned int after_close :1;
+};
+
+void ul_jsonwrt_init(struct ul_jsonwrt *fmt, FILE *out, int indent);
+int ul_jsonwrt_is_ready(struct ul_jsonwrt *fmt);
+void ul_jsonwrt_indent(struct ul_jsonwrt *fmt);
+void ul_jsonwrt_open(struct ul_jsonwrt *fmt, const char *name, int type);
+void ul_jsonwrt_close(struct ul_jsonwrt *fmt, int type);
+
+#define ul_jsonwrt_root_open(_f) ul_jsonwrt_open(_f, NULL, UL_JSON_OBJECT)
+#define ul_jsonwrt_root_close(_f) ul_jsonwrt_close(_f, UL_JSON_OBJECT)
+
+#define ul_jsonwrt_array_open(_f, _n) ul_jsonwrt_open(_f, _n, UL_JSON_ARRAY)
+#define ul_jsonwrt_array_close(_f) ul_jsonwrt_close(_f, UL_JSON_ARRAY)
+
+#define ul_jsonwrt_object_open(_f, _n) ul_jsonwrt_open(_f, _n, UL_JSON_OBJECT)
+#define ul_jsonwrt_object_close(_f) ul_jsonwrt_close(_f, UL_JSON_OBJECT)
+
+#define ul_jsonwrt_value_open(_f, _n) ul_jsonwrt_open(_f, _n, UL_JSON_VALUE)
+#define ul_jsonwrt_value_close(_f) ul_jsonwrt_close(_f, UL_JSON_VALUE)
+
+
+void ul_jsonwrt_value_raw(struct ul_jsonwrt *fmt,
+ const char *name, const char *data);
+void ul_jsonwrt_value_s(struct ul_jsonwrt *fmt,
+ const char *name, const char *data);
+void ul_jsonwrt_value_u64(struct ul_jsonwrt *fmt,
+ const char *name, uint64_t data);
+void ul_jsonwrt_value_boolean(struct ul_jsonwrt *fmt,
+ const char *name, int data);
+void ul_jsonwrt_value_null(struct ul_jsonwrt *fmt,
+ const char *name);
+
+#endif /* UTIL_LINUX_JSONWRT_H */
diff --git a/include/linux_version.h b/include/linux_version.h
new file mode 100644
index 0000000..a6a1e99
--- /dev/null
+++ b/include/linux_version.h
@@ -0,0 +1,14 @@
+#ifndef LINUX_VERSION_H
+#define LINUX_VERSION_H
+
+#ifdef HAVE_LINUX_VERSION_H
+# include <linux/version.h>
+#endif
+
+#ifndef KERNEL_VERSION
+# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#endif
+
+int get_linux_version(void);
+
+#endif /* LINUX_VERSION_H */
diff --git a/include/list.h b/include/list.h
new file mode 100644
index 0000000..b6bbbdd
--- /dev/null
+++ b/include/list.h
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ * Copyright (C) 1999-2008 by Theodore Ts'o
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ *
+ * (based on list.h from e2fsprogs)
+ * Merge sort based on kernel's implementation.
+ */
+
+#ifndef UTIL_LINUX_LIST_H
+#define UTIL_LINUX_LIST_H
+
+#include "c.h"
+
+/* TODO: use AC_C_INLINE */
+#ifdef __GNUC__
+#define _INLINE_ static __inline__
+#else /* For Watcom C */
+#define _INLINE_ static inline
+#endif
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define INIT_LIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+_INLINE_ void __list_add(struct list_head * add,
+ struct list_head * prev,
+ struct list_head * next)
+{
+ next->prev = add;
+ add->next = next;
+ add->prev = prev;
+ prev->next = add;
+}
+
+/**
+ * list_add - add a new entry
+ * @add: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+_INLINE_ void list_add(struct list_head *add, struct list_head *head)
+{
+ __list_add(add, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @add: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+_INLINE_ void list_add_tail(struct list_head *add, struct list_head *head)
+{
+ __list_add(add, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+_INLINE_ void __list_del(struct list_head * prev,
+ struct list_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ *
+ * list_empty() on @entry does not return true after this, @entry is
+ * in an undefined state.
+ */
+_INLINE_ void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+_INLINE_ void list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+_INLINE_ int list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+/**
+ * list_entry_is_last - tests whether is entry last in the list
+ * @entry: the entry to test.
+ * @head: the list to test.
+ */
+_INLINE_ int list_entry_is_last(struct list_head *entry, struct list_head *head)
+{
+ return head->prev == entry;
+}
+
+/**
+ * list_entry_is_first - tests whether is entry first in the list
+ * @entry: the entry to test.
+ * @head: the list to test.
+ */
+_INLINE_ int list_entry_is_first(struct list_head *entry, struct list_head *head)
+{
+ return head->next == entry;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+_INLINE_ void list_splice(struct list_head *list, struct list_head *head)
+{
+ struct list_head *first = list->next;
+
+ if (first != list) {
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+ }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) container_of(ptr, type, member)
+
+#define list_first_entry(head, type, member) \
+ ((head) && (head)->next != (head) ? list_entry((head)->next, type, member) : NULL)
+
+#define list_last_entry(head, type, member) \
+ ((head) && (head)->prev != (head) ? list_entry((head)->prev, type, member) : NULL)
+
+/**
+ * list_for_each - iterate over elements in a list
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_backwardly - iterate over elements in a list in reverse
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each_backwardly(pos, head) \
+ for (pos = (head)->prev; pos != (head); pos = pos->prev)
+
+/**
+ * list_for_each_safe - iterate over elements in a list, but don't dereference
+ * pos after the body is done (in case it is freed)
+ * @pos: the &struct list_head to use as a loop counter.
+ * @pnext: the &struct list_head to use as a pointer to the next item.
+ * @head: the head for your list (not included in iteration).
+ */
+#define list_for_each_safe(pos, pnext, head) \
+ for (pos = (head)->next, pnext = pos->next; pos != (head); \
+ pos = pnext, pnext = pos->next)
+
+/**
+ * list_free - remove all entries from list and call freefunc()
+ * for each entry
+ * @head: the head for your list
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ * @freefunc: the list entry deallocator
+ */
+#define list_free(head, type, member, freefunc) \
+ do { \
+ struct list_head *__p, *__pnext; \
+ \
+ list_for_each_safe (__p, __pnext, (head)) { \
+ type *__elt = list_entry(__p, type, member); \
+ list_del(__p); \
+ freefunc(__elt); \
+ } \
+ } while (0)
+
+_INLINE_ size_t list_count_entries(struct list_head *head)
+{
+ struct list_head *pos;
+ size_t ct = 0;
+
+ list_for_each(pos, head)
+ ct++;
+
+ return ct;
+}
+
+#define MAX_LIST_LENGTH_BITS 20
+
+/*
+ * Returns a list organized in an intermediate format suited
+ * to chaining of merge() calls: null-terminated, no reserved or
+ * sentinel head node, "prev" links not maintained.
+ */
+_INLINE_ struct list_head *merge(int (*cmp)(struct list_head *a,
+ struct list_head *b,
+ void *data),
+ void *data,
+ struct list_head *a, struct list_head *b)
+{
+ struct list_head head, *tail = &head;
+
+ while (a && b) {
+ /* if equal, take 'a' -- important for sort stability */
+ if ((*cmp)(a, b, data) <= 0) {
+ tail->next = a;
+ a = a->next;
+ } else {
+ tail->next = b;
+ b = b->next;
+ }
+ tail = tail->next;
+ }
+ tail->next = a ? a : b;
+ return head.next;
+}
+
+/*
+ * Combine final list merge with restoration of standard doubly-linked
+ * list structure. This approach duplicates code from merge(), but
+ * runs faster than the tidier alternatives of either a separate final
+ * prev-link restoration pass, or maintaining the prev links
+ * throughout.
+ */
+_INLINE_ void merge_and_restore_back_links(int (*cmp)(struct list_head *a,
+ struct list_head *b,
+ void *data),
+ void *data,
+ struct list_head *head,
+ struct list_head *a, struct list_head *b)
+{
+ struct list_head *tail = head;
+
+ while (a && b) {
+ /* if equal, take 'a' -- important for sort stability */
+ if ((*cmp)(a, b, data) <= 0) {
+ tail->next = a;
+ a->prev = tail;
+ a = a->next;
+ } else {
+ tail->next = b;
+ b->prev = tail;
+ b = b->next;
+ }
+ tail = tail->next;
+ }
+ tail->next = a ? a : b;
+
+ do {
+ /*
+ * In worst cases this loop may run many iterations.
+ * Continue callbacks to the client even though no
+ * element comparison is needed, so the client's cmp()
+ * routine can invoke cond_resched() periodically.
+ */
+ (*cmp)(tail->next, tail->next, data);
+
+ tail->next->prev = tail;
+ tail = tail->next;
+ } while (tail->next);
+
+ tail->next = head;
+ head->prev = tail;
+}
+
+
+/**
+ * list_sort - sort a list
+ * @head: the list to sort
+ * @cmp: the elements comparison function
+ *
+ * This function implements "merge sort", which has O(nlog(n))
+ * complexity.
+ *
+ * The comparison function @cmp must return a negative value if @a
+ * should sort before @b, and a positive value if @a should sort after
+ * @b. If @a and @b are equivalent, and their original relative
+ * ordering is to be preserved, @cmp must return 0.
+ */
+_INLINE_ void list_sort(struct list_head *head,
+ int (*cmp)(struct list_head *a,
+ struct list_head *b,
+ void *data),
+ void *data)
+{
+ struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists
+ -- last slot is a sentinel */
+ size_t lev; /* index into part[] */
+ size_t max_lev = 0;
+ struct list_head *list;
+
+ if (list_empty(head))
+ return;
+
+ memset(part, 0, sizeof(part));
+
+ head->prev->next = NULL;
+ list = head->next;
+
+ while (list) {
+ struct list_head *cur = list;
+ list = list->next;
+ cur->next = NULL;
+
+ for (lev = 0; part[lev]; lev++) {
+ cur = merge(cmp, data, part[lev], cur);
+ part[lev] = NULL;
+ }
+ if (lev > max_lev) {
+ /* list passed to list_sort() too long for efficiency */
+ if (lev >= ARRAY_SIZE(part) - 1)
+ lev--;
+ max_lev = lev;
+ }
+ part[lev] = cur;
+ }
+
+ for (lev = 0; lev < max_lev; lev++)
+ if (part[lev])
+ list = merge(cmp, data, part[lev], list);
+
+ merge_and_restore_back_links(cmp, data, head, part[max_lev], list);
+}
+
+#undef _INLINE_
+
+#endif /* UTIL_LINUX_LIST_H */
diff --git a/include/loopdev.h b/include/loopdev.h
new file mode 100644
index 0000000..6d400d1
--- /dev/null
+++ b/include/loopdev.h
@@ -0,0 +1,222 @@
+#ifndef UTIL_LINUX_LOOPDEV_H
+#define UTIL_LINUX_LOOPDEV_H
+
+#include "sysfs.h"
+
+/*
+ * loop_info.lo_encrypt_type
+ */
+#define LO_CRYPT_NONE 0
+#define LO_CRYPT_XOR 1
+#define LO_CRYPT_DES 2
+#define LO_CRYPT_CRYPTOAPI 18
+
+#define LOOP_SET_FD 0x4C00
+#define LOOP_CLR_FD 0x4C01
+/*
+ * Obsolete (kernel < 2.6)
+ *
+ * #define LOOP_SET_STATUS 0x4C02
+ * #define LOOP_GET_STATUS 0x4C03
+ */
+#define LOOP_SET_STATUS64 0x4C04
+#define LOOP_GET_STATUS64 0x4C05
+/* #define LOOP_CHANGE_FD 0x4C06 */
+#define LOOP_SET_CAPACITY 0x4C07
+#define LOOP_SET_DIRECT_IO 0x4C08
+#define LOOP_SET_BLOCK_SIZE 0x4C09
+
+/* /dev/loop-control interface */
+#ifndef LOOP_CTL_ADD
+# define LOOP_CTL_ADD 0x4C80
+# define LOOP_CTL_REMOVE 0x4C81
+# define LOOP_CTL_GET_FREE 0x4C82
+#endif
+
+/*
+ * loop_info.lo_flags
+ */
+enum {
+ LO_FLAGS_READ_ONLY = 1,
+ LO_FLAGS_USE_AOPS = 2,
+ LO_FLAGS_AUTOCLEAR = 4, /* kernel >= 2.6.25 */
+ LO_FLAGS_PARTSCAN = 8, /* kernel >= 3.2 */
+ LO_FLAGS_DIRECT_IO = 16, /* kernel >= 4.2 */
+};
+
+#define LO_NAME_SIZE 64
+#define LO_KEY_SIZE 32
+
+/*
+ * Linux LOOP_{SET,GET}_STATUS64 ioctl struct
+ */
+struct loop_info64 {
+ uint64_t lo_device;
+ uint64_t lo_inode;
+ uint64_t lo_rdevice;
+ uint64_t lo_offset;
+ uint64_t lo_sizelimit; /* bytes, 0 == max available */
+ uint32_t lo_number;
+ uint32_t lo_encrypt_type;
+ uint32_t lo_encrypt_key_size;
+ uint32_t lo_flags;
+ uint8_t lo_file_name[LO_NAME_SIZE];
+ uint8_t lo_crypt_name[LO_NAME_SIZE];
+ uint8_t lo_encrypt_key[LO_KEY_SIZE];
+ uint64_t lo_init[2];
+};
+
+#ifndef LOOP_CONFIGURE
+/*
+ * Since Linux v5.8-rc1 (commit 3448914e8cc550ba792d4ccc74471d1ca4293aae)
+ */
+# define LOOP_CONFIGURE 0x4C0A
+struct loop_config {
+ uint32_t fd;
+ uint32_t block_size;
+ struct loop_info64 info;
+ uint64_t __reserved[8];
+};
+#endif
+
+#define LOOPDEV_MAJOR 7 /* loop major number */
+#define LOOPDEV_DEFAULT_NNODES 8 /* default number of loop devices */
+
+struct loopdev_iter {
+ FILE *proc; /* /proc/partitions */
+ DIR *sysblock; /* /sys/block */
+ int ncur; /* current position */
+ int *minors; /* ary of minor numbers (when scan whole /dev) */
+ int nminors; /* number of items in *minors */
+ int ct_perm; /* count permission problems */
+ int ct_succ; /* count number of detected devices */
+
+ unsigned int done:1; /* scanning done */
+ unsigned int default_check:1;/* check first LOOPDEV_NLOOPS */
+ int flags; /* LOOPITER_FL_* flags */
+};
+
+enum {
+ LOOPITER_FL_FREE = (1 << 0),
+ LOOPITER_FL_USED = (1 << 1)
+};
+
+/*
+ * handler for work with loop devices
+ */
+struct loopdev_cxt {
+ char device[128]; /* device path (e.g. /dev/loop<N>) */
+ char *filename; /* backing file for loopcxt_set_... */
+ int fd; /* open(/dev/looo<N>) */
+ int mode; /* fd mode O_{RDONLY,RDWR} */
+ uint64_t blocksize; /* used by loopcxt_setup_device() */
+
+ int flags; /* LOOPDEV_FL_* flags */
+ unsigned int has_info:1; /* .info contains data */
+ unsigned int extra_check:1; /* unusual stuff for iterator */
+ unsigned int info_failed:1; /* LOOP_GET_STATUS ioctl failed */
+ unsigned int control_ok:1; /* /dev/loop-control success */
+
+ struct path_cxt *sysfs; /* pointer to /sys/dev/block/<maj:min>/ */
+ struct loop_config config; /* for GET/SET ioctl */
+ struct loopdev_iter iter; /* scans /sys or /dev for used/free devices */
+};
+
+#define UL_LOOPDEVCXT_EMPTY { .fd = -1 }
+
+/*
+ * loopdev_cxt.flags
+ */
+enum {
+ LOOPDEV_FL_RDONLY = (1 << 0), /* open(/dev/loop) mode; default */
+ LOOPDEV_FL_RDWR = (1 << 1), /* necessary for loop setup only */
+ LOOPDEV_FL_OFFSET = (1 << 4),
+ LOOPDEV_FL_NOSYSFS = (1 << 5),
+ LOOPDEV_FL_NOIOCTL = (1 << 6),
+ LOOPDEV_FL_DEVSUBDIR = (1 << 7),
+ LOOPDEV_FL_CONTROL = (1 << 8), /* system with /dev/loop-control */
+ LOOPDEV_FL_SIZELIMIT = (1 << 9)
+};
+
+/*
+ * High-level
+ */
+extern int loopmod_supports_partscan(void);
+
+extern int is_loopdev(const char *device);
+extern int loopdev_is_autoclear(const char *device);
+
+extern char *loopdev_get_backing_file(const char *device);
+extern int loopdev_has_backing_file(const char *device);
+extern int loopdev_is_used(const char *device, const char *filename,
+ uint64_t offset, uint64_t sizelimit, int flags);
+extern char *loopdev_find_by_backing_file(const char *filename,
+ uint64_t offset, uint64_t sizelimit, int flags);
+extern int loopcxt_find_unused(struct loopdev_cxt *lc);
+extern int loopdev_delete(const char *device);
+extern int loopdev_count_by_backing_file(const char *filename, char **loopdev);
+
+/*
+ * Low-level
+ */
+extern int loopcxt_init(struct loopdev_cxt *lc, int flags)
+ __attribute__ ((warn_unused_result));
+extern void loopcxt_deinit(struct loopdev_cxt *lc);
+
+extern int loopcxt_set_device(struct loopdev_cxt *lc, const char *device)
+ __attribute__ ((warn_unused_result));
+extern int loopcxt_has_device(struct loopdev_cxt *lc);
+extern int loopcxt_add_device(struct loopdev_cxt *lc);
+extern char *loopcxt_strdup_device(struct loopdev_cxt *lc);
+extern const char *loopcxt_get_device(struct loopdev_cxt *lc);
+extern struct loop_info64 *loopcxt_get_info(struct loopdev_cxt *lc);
+
+extern int loopcxt_get_fd(struct loopdev_cxt *lc);
+extern int loopcxt_set_fd(struct loopdev_cxt *lc, int fd, int mode);
+
+extern int loopcxt_init_iterator(struct loopdev_cxt *lc, int flags);
+extern int loopcxt_deinit_iterator(struct loopdev_cxt *lc);
+extern int loopcxt_next(struct loopdev_cxt *lc);
+
+extern int loopcxt_setup_device(struct loopdev_cxt *lc);
+extern int loopcxt_delete_device(struct loopdev_cxt *lc);
+
+extern int loopcxt_ioctl_status(struct loopdev_cxt *lc);
+extern int loopcxt_ioctl_capacity(struct loopdev_cxt *lc);
+extern int loopcxt_ioctl_dio(struct loopdev_cxt *lc, unsigned long use_dio);
+extern int loopcxt_ioctl_blocksize(struct loopdev_cxt *lc, uint64_t blocksize);
+
+int loopcxt_set_offset(struct loopdev_cxt *lc, uint64_t offset);
+int loopcxt_set_sizelimit(struct loopdev_cxt *lc, uint64_t sizelimit);
+int loopcxt_set_blocksize(struct loopdev_cxt *lc, uint64_t blocksize);
+int loopcxt_set_flags(struct loopdev_cxt *lc, uint32_t flags);
+int loopcxt_set_backing_file(struct loopdev_cxt *lc, const char *filename);
+
+extern char *loopcxt_get_backing_file(struct loopdev_cxt *lc);
+extern int loopcxt_get_backing_devno(struct loopdev_cxt *lc, dev_t *devno);
+extern int loopcxt_get_backing_inode(struct loopdev_cxt *lc, ino_t *ino);
+extern int loopcxt_get_offset(struct loopdev_cxt *lc, uint64_t *offset);
+extern int loopcxt_get_blocksize(struct loopdev_cxt *lc, uint64_t *blocksize);
+extern int loopcxt_get_sizelimit(struct loopdev_cxt *lc, uint64_t *size);
+extern int loopcxt_get_encrypt_type(struct loopdev_cxt *lc, uint32_t *type);
+extern const char *loopcxt_get_crypt_name(struct loopdev_cxt *lc);
+extern int loopcxt_is_autoclear(struct loopdev_cxt *lc);
+extern int loopcxt_is_readonly(struct loopdev_cxt *lc);
+extern int loopcxt_is_dio(struct loopdev_cxt *lc);
+extern int loopcxt_is_partscan(struct loopdev_cxt *lc);
+extern int loopcxt_find_by_backing_file(struct loopdev_cxt *lc,
+ const char *filename,
+ uint64_t offset, uint64_t sizelimit,
+ int flags);
+extern int loopcxt_find_overlap(struct loopdev_cxt *lc,
+ const char *filename,
+ uint64_t offset, uint64_t sizelimit);
+
+extern int loopcxt_is_used(struct loopdev_cxt *lc,
+ struct stat *st,
+ const char *backing_file,
+ uint64_t offset,
+ uint64_t sizelimit,
+ int flags);
+
+#endif /* UTIL_LINUX_LOOPDEV_H */
diff --git a/include/mangle.h b/include/mangle.h
new file mode 100644
index 0000000..08c66cb
--- /dev/null
+++ b/include/mangle.h
@@ -0,0 +1,28 @@
+#ifndef UTIL_LINUX_MANGLE_H
+#define UTIL_LINUX_MANGLE_H
+
+/*
+ * Functions for \oct encoding used in mtab/fstab/swaps/etc.
+ */
+
+extern char *mangle(const char *s);
+
+extern void unmangle_to_buffer(const char *s, char *buf, size_t len);
+extern size_t unhexmangle_to_buffer(const char *s, char *buf, size_t len);
+
+extern char *unmangle(const char *s, const char **end);
+
+static inline void unmangle_string(char *s)
+{
+ if (s)
+ unmangle_to_buffer(s, s, strlen(s) + 1);
+}
+
+static inline void unhexmangle_string(char *s)
+{
+ if (s)
+ unhexmangle_to_buffer(s, s, strlen(s) + 1);
+}
+
+#endif /* UTIL_LINUX_MANGLE_H */
+
diff --git a/include/match.h b/include/match.h
new file mode 100644
index 0000000..94440c2
--- /dev/null
+++ b/include/match.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2011 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#ifndef UTIL_LINUX_MATCH_H
+#define UTIL_LINUX_MATCH_H
+
+extern int match_fstype(const char *type, const char *pattern);
+
+#endif /* UTIL_LINUX_MATCH_H */
diff --git a/include/mbsalign.h b/include/mbsalign.h
new file mode 100644
index 0000000..4f5add8
--- /dev/null
+++ b/include/mbsalign.h
@@ -0,0 +1,66 @@
+/* Align/Truncate a string in a given screen width
+ Copyright (C) 2009-2010 Free Software Foundation, Inc.
+ Copyright (C) 2010-2013 Karel Zak <kzak@redhat.com>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+#ifndef UTIL_LINUX_MBSALIGN_H
+# define UTIL_LINUX_MBSALIGN_H
+# include <stddef.h>
+
+typedef enum { MBS_ALIGN_LEFT, MBS_ALIGN_RIGHT, MBS_ALIGN_CENTER } mbs_align_t;
+
+enum {
+ /* Use unibyte mode for invalid multibyte strings or
+ or when heap memory is exhausted. */
+ MBA_UNIBYTE_FALLBACK = 0x0001,
+
+#if 0 /* Other possible options. */
+ /* Skip invalid multibyte chars rather than failing */
+ MBA_IGNORE_INVALID = 0x0002,
+
+ /* Align multibyte strings using "figure space" (\u2007) */
+ MBA_USE_FIGURE_SPACE = 0x0004,
+
+ /* Don't add any padding */
+ MBA_TRUNCATE_ONLY = 0x0008,
+
+ /* Don't truncate */
+ MBA_PAD_ONLY = 0x0010,
+#endif
+};
+
+extern size_t mbs_truncate(char *str, size_t *width);
+
+extern size_t mbsalign (const char *src, char *dest,
+ size_t dest_size, size_t *width,
+ mbs_align_t align, int flags);
+
+extern size_t mbsalign_with_padding (const char *src, char *dest, size_t dest_size,
+ size_t *width, mbs_align_t align, int flags,
+ int padchar);
+
+extern size_t mbs_safe_nwidth(const char *buf, size_t bufsz, size_t *sz);
+extern size_t mbs_safe_width(const char *s);
+
+extern size_t mbs_nwidth(const char *buf, size_t bufsz);
+extern size_t mbs_width(const char *s);
+
+extern char *mbs_safe_encode(const char *s, size_t *width);
+extern char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf, const char *safechars);
+extern size_t mbs_safe_encode_size(size_t bytes);
+
+extern char *mbs_invalid_encode(const char *s, size_t *width);
+extern char *mbs_invalid_encode_to_buffer(const char *s, size_t *width, char *buf);
+
+#endif /* UTIL_LINUX_MBSALIGN_H */
diff --git a/include/mbsedit.h b/include/mbsedit.h
new file mode 100644
index 0000000..8d1c6c2
--- /dev/null
+++ b/include/mbsedit.h
@@ -0,0 +1,32 @@
+#ifndef UTIL_LINUX_MBSEDIT_H
+# define UTIL_LINUX_MBSEDIT_H
+
+#include "mbsalign.h"
+#include "widechar.h"
+
+struct mbs_editor {
+ char *buf; /* buffer */
+ size_t max_bytes; /* size of the buffer */
+ size_t max_cells; /* maximal allowed number of cells */
+ size_t cur_cells; /* number of cells to print the buffer */
+ size_t cur_bytes; /* number of chars in bytes */
+ size_t cursor; /* cursor position in bytes */
+ size_t cursor_cells; /* cursor position in cells */
+};
+
+enum {
+ MBS_EDIT_LEFT,
+ MBS_EDIT_RIGHT,
+ MBS_EDIT_END,
+ MBS_EDIT_HOME
+};
+
+struct mbs_editor *mbs_new_edit(char *buf, size_t bufsz, size_t ncells);
+char *mbs_free_edit(struct mbs_editor *edit);
+
+int mbs_edit_goto(struct mbs_editor *edit, int where);
+int mbs_edit_delete(struct mbs_editor *edit);
+int mbs_edit_backspace(struct mbs_editor *edit);
+int mbs_edit_insert(struct mbs_editor *edit, wint_t c);
+
+#endif /* UTIL_LINUX_MBSEDIT_H */
diff --git a/include/md5.h b/include/md5.h
new file mode 100644
index 0000000..02e627b
--- /dev/null
+++ b/include/md5.h
@@ -0,0 +1,24 @@
+#ifndef UTIL_LINUX_MD5_H
+#define UTIL_LINUX_MD5_H
+
+#include <stdint.h>
+
+#define UL_MD5LENGTH 16
+
+struct UL_MD5Context {
+ uint32_t buf[4];
+ uint32_t bits[2];
+ unsigned char in[64];
+};
+
+void ul_MD5Init(struct UL_MD5Context *ctx);
+void ul_MD5Update(struct UL_MD5Context *ctx, unsigned char const *buf, unsigned len);
+void ul_MD5Final(unsigned char digest[UL_MD5LENGTH], struct UL_MD5Context *ctx);
+void ul_MD5Transform(uint32_t buf[4], uint32_t const in[16]);
+
+/*
+ * This is needed to make RSAREF happy on some MS-DOS compilers.
+ */
+typedef struct UL_MD5Context UL_MD5_CTX;
+
+#endif /* !UTIL_LINUX_MD5_H */
diff --git a/include/meson.build b/include/meson.build
new file mode 100644
index 0000000..6162ff0
--- /dev/null
+++ b/include/meson.build
@@ -0,0 +1,3 @@
+dir_include = include_directories('.')
+
+list_h = files('list.h')
diff --git a/include/minix.h b/include/minix.h
new file mode 100644
index 0000000..f28991c
--- /dev/null
+++ b/include/minix.h
@@ -0,0 +1,85 @@
+#ifndef UTIL_LINUX_MINIX_H
+#define UTIL_LINUX_MINIX_H
+
+#include <stdint.h>
+
+struct minix_inode {
+ uint16_t i_mode;
+ uint16_t i_uid;
+ uint32_t i_size;
+ uint32_t i_time;
+ uint8_t i_gid;
+ uint8_t i_nlinks;
+ uint16_t i_zone[9];
+};
+
+struct minix2_inode {
+ uint16_t i_mode;
+ uint16_t i_nlinks;
+ uint16_t i_uid;
+ uint16_t i_gid;
+ uint32_t i_size;
+ uint32_t i_atime;
+ uint32_t i_mtime;
+ uint32_t i_ctime;
+ uint32_t i_zone[10];
+};
+
+struct minix_super_block {
+ uint16_t s_ninodes;
+ uint16_t s_nzones;
+ uint16_t s_imap_blocks;
+ uint16_t s_zmap_blocks;
+ uint16_t s_firstdatazone;
+ uint16_t s_log_zone_size;
+ uint32_t s_max_size;
+ uint16_t s_magic;
+ uint16_t s_state;
+ uint32_t s_zones;
+};
+
+/* V3 minix super-block data on disk */
+struct minix3_super_block {
+ uint32_t s_ninodes;
+ uint16_t s_pad0;
+ uint16_t s_imap_blocks;
+ uint16_t s_zmap_blocks;
+ uint16_t s_firstdatazone;
+ uint16_t s_log_zone_size;
+ uint16_t s_pad1;
+ uint32_t s_max_size;
+ uint32_t s_zones;
+ uint16_t s_magic;
+ uint16_t s_pad2;
+ uint16_t s_blocksize;
+ uint8_t s_disk_version;
+};
+
+/*
+ * Minix subpartitions are always within primary dos partition.
+ */
+#define MINIX_MAXPARTITIONS 4
+
+#define MINIX_BLOCK_SIZE_BITS 10
+#define MINIX_BLOCK_SIZE (1 << MINIX_BLOCK_SIZE_BITS)
+
+#define MINIX_NAME_MAX 255 /* # chars in a file name */
+#define MINIX_MAX_INODES 65535
+
+#define MINIX_INODES_PER_BLOCK ((MINIX_BLOCK_SIZE)/(sizeof (struct minix_inode)))
+#define MINIX2_INODES_PER_BLOCK ((MINIX_BLOCK_SIZE)/(sizeof (struct minix2_inode)))
+
+/* minix_super_block.s_state */
+#define MINIX_VALID_FS 0x0001 /* Clean fs. */
+#define MINIX_ERROR_FS 0x0002 /* fs has errors. */
+
+
+#define MINIX_SUPER_MAGIC 0x137F /* minix V1 fs, 14 char names */
+#define MINIX_SUPER_MAGIC2 0x138F /* minix V1 fs, 30 char names */
+
+#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs, 14 char names */
+#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */
+
+#define MINIX3_SUPER_MAGIC 0x4d5a /* minix V3 fs (60 char names) */
+
+#endif /* UTIL_LINUX_MINIX_H */
diff --git a/include/monotonic.h b/include/monotonic.h
new file mode 100644
index 0000000..380e59c
--- /dev/null
+++ b/include/monotonic.h
@@ -0,0 +1,22 @@
+/*
+ * No copyright is claimed. This code is in the public domain; do with
+ * it what you wish.
+ */
+#ifndef UTIL_LINUX_MONOTONIC_H
+#define UTIL_LINUX_MONOTONIC_H
+
+# ifdef CLOCK_MONOTONIC_RAW
+# define UL_CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW
+# else
+# define UL_CLOCK_MONOTONIC CLOCK_MONOTONIC
+# endif
+
+#include <sys/time.h>
+
+extern int get_boot_time(struct timeval *boot_time);
+
+extern time_t get_suspended_time(void);
+
+extern int gettime_monotonic(struct timeval *tv);
+
+#endif /* UTIL_LINUX_MONOTONIC_H */
diff --git a/include/namespace.h b/include/namespace.h
new file mode 100644
index 0000000..2d0a56e
--- /dev/null
+++ b/include/namespace.h
@@ -0,0 +1,56 @@
+
+/*
+ * No copyright is claimed. This code is in the public domain; do with
+ * it what you wish.
+ *
+ * Compat code so unshare and setns can be used with older libcs
+ */
+#ifndef UTIL_LINUX_NAMESPACE_H
+# define UTIL_LINUX_NAMESPACE_H
+
+# include <sched.h>
+
+# ifndef CLONE_NEWNS
+# define CLONE_NEWNS 0x00020000
+# endif
+# ifndef CLONE_NEWCGROUP
+# define CLONE_NEWCGROUP 0x02000000
+# endif
+# ifndef CLONE_NEWUTS
+# define CLONE_NEWUTS 0x04000000
+# endif
+# ifndef CLONE_NEWIPC
+# define CLONE_NEWIPC 0x08000000
+# endif
+# ifndef CLONE_NEWNET
+# define CLONE_NEWNET 0x40000000
+# endif
+# ifndef CLONE_NEWUSER
+# define CLONE_NEWUSER 0x10000000
+# endif
+# ifndef CLONE_NEWPID
+# define CLONE_NEWPID 0x20000000
+# endif
+# ifndef CLONE_NEWTIME
+# define CLONE_NEWTIME 0x00000080
+# endif
+
+# if !defined(HAVE_UNSHARE) || !defined(HAVE_SETNS)
+# include <sys/syscall.h>
+# endif
+
+# if !defined(HAVE_UNSHARE) && defined(SYS_unshare)
+static inline int unshare(int flags)
+{
+ return syscall(SYS_unshare, flags);
+}
+# endif
+
+# if !defined(HAVE_SETNS) && defined(SYS_setns)
+static inline int setns(int fd, int nstype)
+{
+ return syscall(SYS_setns, fd, nstype);
+}
+# endif
+
+#endif /* UTIL_LINUX_NAMESPACE_H */
diff --git a/include/nls.h b/include/nls.h
new file mode 100644
index 0000000..5566908
--- /dev/null
+++ b/include/nls.h
@@ -0,0 +1,153 @@
+#ifndef UTIL_LINUX_NLS_H
+#define UTIL_LINUX_NLS_H
+
+#ifndef LOCALEDIR
+#define LOCALEDIR "/usr/share/locale"
+#endif
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#else
+# undef setlocale
+# define setlocale(Category, Locale) /* empty */
+struct lconv
+{
+ char *decimal_point;
+};
+# undef localeconv
+# define localeconv() NULL
+#endif
+
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+/*
+ * For NLS support in the public shared libraries we have to specify text
+ * domain name to be independent on the main program. For this purpose define
+ * UL_TEXTDOMAIN_EXPLICIT before you include nls.h to your shared library code.
+ */
+# ifdef UL_TEXTDOMAIN_EXPLICIT
+# define _(Text) dgettext (UL_TEXTDOMAIN_EXPLICIT, Text)
+# else
+# define _(Text) gettext (Text)
+# endif
+# ifdef gettext_noop
+# define N_(String) gettext_noop (String)
+# else
+# define N_(String) (String)
+# endif
+# define P_(Singular, Plural, n) ngettext (Singular, Plural, n)
+#else
+# undef bindtextdomain
+# define bindtextdomain(Domain, Directory) /* empty */
+# undef textdomain
+# define textdomain(Domain) /* empty */
+# define _(Text) (Text)
+# define N_(Text) (Text)
+# define P_(Singular, Plural, n) ((n) == 1 ? (Singular) : (Plural))
+#endif /* ENABLE_NLS */
+
+#ifdef HAVE_LANGINFO_H
+# include <langinfo.h>
+#else
+
+typedef int nl_item;
+extern char *langinfo_fallback(nl_item item);
+
+# define nl_langinfo langinfo_fallback
+
+enum {
+ CODESET = 1,
+ RADIXCHAR,
+ THOUSEP,
+ D_T_FMT,
+ D_FMT,
+ T_FMT,
+ T_FMT_AMPM,
+ AM_STR,
+ PM_STR,
+
+ DAY_1,
+ DAY_2,
+ DAY_3,
+ DAY_4,
+ DAY_5,
+ DAY_6,
+ DAY_7,
+
+ ABDAY_1,
+ ABDAY_2,
+ ABDAY_3,
+ ABDAY_4,
+ ABDAY_5,
+ ABDAY_6,
+ ABDAY_7,
+
+ MON_1,
+ MON_2,
+ MON_3,
+ MON_4,
+ MON_5,
+ MON_6,
+ MON_7,
+ MON_8,
+ MON_9,
+ MON_10,
+ MON_11,
+ MON_12,
+
+ ABMON_1,
+ ABMON_2,
+ ABMON_3,
+ ABMON_4,
+ ABMON_5,
+ ABMON_6,
+ ABMON_7,
+ ABMON_8,
+ ABMON_9,
+ ABMON_10,
+ ABMON_11,
+ ABMON_12,
+
+ ERA_D_FMT,
+ ERA_D_T_FMT,
+ ERA_T_FMT,
+ ALT_DIGITS,
+ CRNCYSTR,
+ YESEXPR,
+ NOEXPR
+};
+
+#endif /* !HAVE_LANGINFO_H */
+
+#ifndef HAVE_LANGINFO_ALTMON
+# define ALTMON_1 MON_1
+# define ALTMON_2 MON_2
+# define ALTMON_3 MON_3
+# define ALTMON_4 MON_4
+# define ALTMON_5 MON_5
+# define ALTMON_6 MON_6
+# define ALTMON_7 MON_7
+# define ALTMON_8 MON_8
+# define ALTMON_9 MON_9
+# define ALTMON_10 MON_10
+# define ALTMON_11 MON_11
+# define ALTMON_12 MON_12
+#endif /* !HAVE_LANGINFO_ALTMON */
+
+#ifndef HAVE_LANGINFO_NL_ABALTMON
+# define _NL_ABALTMON_1 ABMON_1
+# define _NL_ABALTMON_2 ABMON_2
+# define _NL_ABALTMON_3 ABMON_3
+# define _NL_ABALTMON_4 ABMON_4
+# define _NL_ABALTMON_5 ABMON_5
+# define _NL_ABALTMON_6 ABMON_6
+# define _NL_ABALTMON_7 ABMON_7
+# define _NL_ABALTMON_8 ABMON_8
+# define _NL_ABALTMON_9 ABMON_9
+# define _NL_ABALTMON_10 ABMON_10
+# define _NL_ABALTMON_11 ABMON_11
+# define _NL_ABALTMON_12 ABMON_12
+#endif /* !HAVE_LANGINFO_NL_ABALTMON */
+
+#endif /* UTIL_LINUX_NLS_H */
diff --git a/include/optutils.h b/include/optutils.h
new file mode 100644
index 0000000..0dc127b
--- /dev/null
+++ b/include/optutils.h
@@ -0,0 +1,107 @@
+#ifndef UTIL_LINUX_OPTUTILS_H
+#define UTIL_LINUX_OPTUTILS_H
+
+#include <assert.h>
+
+#include "c.h"
+#include "nls.h"
+#include "cctype.h"
+
+static inline const char *option_to_longopt(int c, const struct option *opts)
+{
+ const struct option *o;
+
+ assert(!(opts == NULL));
+ for (o = opts; o->name; o++)
+ if (o->val == c)
+ return o->name;
+ return NULL;
+}
+
+#ifndef OPTUTILS_EXIT_CODE
+# define OPTUTILS_EXIT_CODE EXIT_FAILURE
+#endif
+
+/*
+ * Check collisions between options.
+ *
+ * The conflicts between options are described in ul_excl_t array. The
+ * array contains groups of mutually exclusive options. For example
+ *
+ * static const ul_excl_t excl[] = {
+ * { 'Z','b','c' }, // first group
+ * { 'b','x' }, // second group
+ * { 0 }
+ * };
+ *
+ * int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
+ *
+ * while ((c = getopt_long(argc, argv, "Zbcx", longopts, NULL)) != -1) {
+ *
+ * err_exclusive_options(c, longopts, excl, excl_st);
+ *
+ * switch (c) {
+ * case 'Z':
+ * ....
+ * }
+ * }
+ *
+ * The array excl[] defines two groups of the mutually exclusive options. The
+ * option '-b' is in the both groups.
+ *
+ * Note that the options in the group have to be in ASCII order (ABC..abc..) and
+ * groups have to be also in ASCII order.
+ *
+ * The maximal number of the options in the group is 15 (size of the array is
+ * 16, last is zero).
+ *
+ * The current status of options is stored in excl_st array. The size of the array
+ * must be the same as number of the groups in the ul_excl_t array.
+ *
+ * If you're unsure then see sys-utils/mount.c or misc-utils/findmnt.c.
+ */
+#define UL_EXCL_STATUS_INIT { 0 }
+typedef int ul_excl_t[16];
+
+static inline void err_exclusive_options(
+ int c,
+ const struct option *opts,
+ const ul_excl_t *excl,
+ int *status)
+{
+ int e;
+
+ for (e = 0; excl[e][0] && excl[e][0] <= c; e++) {
+ const int *op = excl[e];
+
+ for (; *op && *op <= c; op++) {
+ if (*op != c)
+ continue;
+ if (status[e] == 0)
+ status[e] = c;
+ else if (status[e] != c) {
+ size_t ct = 0;
+
+ fprintf(stderr, _("%s: mutually exclusive "
+ "arguments:"),
+ program_invocation_short_name);
+
+ for (op = excl[e];
+ ct + 1 < ARRAY_SIZE(excl[0]) && *op;
+ op++, ct++) {
+ const char *n = option_to_longopt(*op, opts);
+ if (n)
+ fprintf(stderr, " --%s", n);
+ else if (c_isgraph(*op))
+ fprintf(stderr, " -%c", *op);
+ }
+ fputc('\n', stderr);
+ exit(OPTUTILS_EXIT_CODE);
+ }
+ break;
+ }
+ }
+}
+
+#endif
+
diff --git a/include/pager.h b/include/pager.h
new file mode 100644
index 0000000..0a7140d
--- /dev/null
+++ b/include/pager.h
@@ -0,0 +1,9 @@
+#ifndef UTIL_LINUX_PAGER
+#define UTIL_LINUX_PAGER
+
+void pager_redirect(void);
+
+void pager_open(void);
+void pager_close(void);
+
+#endif
diff --git a/include/partx.h b/include/partx.h
new file mode 100644
index 0000000..618a0a4
--- /dev/null
+++ b/include/partx.h
@@ -0,0 +1,63 @@
+#ifndef UTIL_LINUX_PARTX_H
+#define UTIL_LINUX_PARTX_H
+
+#include <sys/ioctl.h>
+#include <linux/blkpg.h>
+#include <stdint.h>
+
+#ifndef BLKPG_ADD_PARTITION
+# define BLKPG_ADD_PARTITION 1
+#endif
+
+#ifndef BLKPG_DEL_PARTITION
+# define BLKPG_DEL_PARTITION 2
+#endif
+
+#ifndef BLKPG_RESIZE_PARTITION
+# define BLKPG_RESIZE_PARTITION 3 /* since Linux 3.6 */
+#endif
+
+
+#define INIT_BLKPG_PARTITION(_partno, _start, _size) { \
+ .pno = (_partno), \
+ .start = (_start) << 9, \
+ .length = (_size) << 9, \
+ .devname[0] = 0, \
+ .volname[0] = 0 \
+}
+
+#define INIT_BLKPG_ARG(_action, _part) { \
+ .op = (_action), \
+ .flags = 0, \
+ .datalen = sizeof(*(_part)), \
+ .data = (_part) \
+}
+
+
+static inline int partx_del_partition(int fd, unsigned int partno)
+{
+ struct blkpg_partition p = INIT_BLKPG_PARTITION(partno, 0, 0);
+ struct blkpg_ioctl_arg a = INIT_BLKPG_ARG(BLKPG_DEL_PARTITION, &p);
+
+ return ioctl(fd, BLKPG, &a);
+}
+
+static inline int partx_add_partition(int fd, int partno,
+ uint64_t start, uint64_t size)
+{
+ struct blkpg_partition p = INIT_BLKPG_PARTITION(partno, start, size);
+ struct blkpg_ioctl_arg a = INIT_BLKPG_ARG(BLKPG_ADD_PARTITION, &p);
+
+ return ioctl(fd, BLKPG, &a);
+}
+
+static inline int partx_resize_partition(int fd, int partno,
+ uint64_t start, uint64_t size)
+{
+ struct blkpg_partition p = INIT_BLKPG_PARTITION(partno, start, size);
+ struct blkpg_ioctl_arg a = INIT_BLKPG_ARG(BLKPG_RESIZE_PARTITION, &p);
+
+ return ioctl(fd, BLKPG, &a);
+}
+
+#endif /* UTIL_LINUX_PARTX_H */
diff --git a/include/path.h b/include/path.h
new file mode 100644
index 0000000..22cd544
--- /dev/null
+++ b/include/path.h
@@ -0,0 +1,144 @@
+#ifndef UTIL_LINUX_PATH_H
+#define UTIL_LINUX_PATH_H
+
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#include "c.h"
+
+struct path_cxt {
+ int dir_fd;
+ char *dir_path;
+
+ int refcount;
+
+ char *prefix;
+ char path_buffer[PATH_MAX];
+
+ void *dialect;
+ void (*free_dialect)(struct path_cxt *);
+ int (*redirect_on_enoent)(struct path_cxt *, const char *, int *);
+};
+
+struct path_cxt *ul_new_path(const char *dir, ...)
+ __attribute__ ((__format__ (__printf__, 1, 2)));
+void ul_unref_path(struct path_cxt *pc);
+void ul_ref_path(struct path_cxt *pc);
+
+void ul_path_init_debug(void);
+
+int ul_path_set_prefix(struct path_cxt *pc, const char *prefix);
+const char *ul_path_get_prefix(struct path_cxt *pc);
+
+int ul_path_set_dir(struct path_cxt *pc, const char *dir);
+const char *ul_path_get_dir(struct path_cxt *pc);
+
+int ul_path_set_dialect(struct path_cxt *pc, void *data, void free_data(struct path_cxt *));
+void *ul_path_get_dialect(struct path_cxt *pc);
+
+int ul_path_set_enoent_redirect(struct path_cxt *pc, int (*func)(struct path_cxt *, const char *, int *));
+int ul_path_get_dirfd(struct path_cxt *pc);
+void ul_path_close_dirfd(struct path_cxt *pc);
+int ul_path_isopen_dirfd(struct path_cxt *pc);
+int ul_path_is_accessible(struct path_cxt *pc);
+
+char *ul_path_get_abspath(struct path_cxt *pc, char *buf, size_t bufsz, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 4, 5)));
+
+int ul_path_stat(struct path_cxt *pc, struct stat *sb, int flags, const char *path);
+int ul_path_access(struct path_cxt *pc, int mode, const char *path);
+int ul_path_accessf(struct path_cxt *pc, int mode, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+
+int ul_path_open(struct path_cxt *pc, int flags, const char *path);
+int ul_path_openf(struct path_cxt *pc, int flags, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+int ul_path_vopenf(struct path_cxt *pc, int flags, const char *path, va_list ap)
+ __attribute__ ((__format__ (__printf__, 3, 0)));
+
+FILE *ul_path_fopen(struct path_cxt *pc, const char *mode, const char *path);
+FILE *ul_path_fopenf(struct path_cxt *pc, const char *mode, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+FILE *ul_path_vfopenf(struct path_cxt *pc, const char *mode, const char *path, va_list ap)
+ __attribute__ ((__format__ (__printf__, 3, 0)));
+
+DIR *ul_path_opendir(struct path_cxt *pc, const char *path);
+DIR *ul_path_vopendirf(struct path_cxt *pc, const char *path, va_list ap)
+ __attribute__ ((__format__ (__printf__, 2, 0)));
+DIR *ul_path_opendirf(struct path_cxt *pc, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+
+ssize_t ul_path_readlink(struct path_cxt *pc, char *buf, size_t bufsiz, const char *path);
+ssize_t ul_path_readlinkf(struct path_cxt *pc, char *buf, size_t bufsiz, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 4, 5)));
+
+int ul_path_read(struct path_cxt *pc, char *buf, size_t len, const char *path);
+int ul_path_vreadf(struct path_cxt *pc, char *buf, size_t len, const char *path, va_list ap)
+ __attribute__ ((__format__ (__printf__, 4, 0)));
+int ul_path_readf(struct path_cxt *pc, char *buf, size_t len, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 4, 5)));
+
+int ul_path_read_string(struct path_cxt *pc, char **str, const char *path);
+int ul_path_readf_string(struct path_cxt *pc, char **str, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+
+int ul_path_read_buffer(struct path_cxt *pc, char *buf, size_t bufsz, const char *path);
+int ul_path_readf_buffer(struct path_cxt *pc, char *buf, size_t bufsz, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 4, 5)));
+
+int ul_path_scanf(struct path_cxt *pc, const char *path, const char *fmt, ...)
+ __attribute__ ((__format__ (__scanf__, 3, 4)));
+int ul_path_scanff(struct path_cxt *pc, const char *path, va_list ap, const char *fmt, ...)
+ __attribute__ ((__format__ (__printf__, 2, 0)))
+ __attribute__ ((__format__ (__scanf__, 4, 5)));
+
+int ul_path_read_majmin(struct path_cxt *pc, dev_t *res, const char *path);
+int ul_path_readf_majmin(struct path_cxt *pc, dev_t *res, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+
+int ul_path_read_u32(struct path_cxt *pc, uint32_t *res, const char *path);
+int ul_path_readf_u32(struct path_cxt *pc, uint32_t *res, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+
+int ul_path_read_s32(struct path_cxt *pc, int32_t *res, const char *path);
+int ul_path_readf_s32(struct path_cxt *pc, int32_t *res, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+
+int ul_path_read_u64(struct path_cxt *pc, uint64_t *res, const char *path);
+int ul_path_readf_u64(struct path_cxt *pc, uint64_t *res, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+
+int ul_path_read_s64(struct path_cxt *pc, int64_t *res, const char *path);
+int ul_path_readf_s64(struct path_cxt *pc, int64_t *res, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+
+int ul_path_write_string(struct path_cxt *pc, const char *str, const char *path);
+int ul_path_writef_string(struct path_cxt *pc, const char *str, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+
+int ul_path_write_s64(struct path_cxt *pc, int64_t num, const char *path);
+int ul_path_write_u64(struct path_cxt *pc, uint64_t num, const char *path);
+int ul_path_writef_u64(struct path_cxt *pc, uint64_t num, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+
+int ul_path_count_dirents(struct path_cxt *pc, const char *path);
+int ul_path_countf_dirents(struct path_cxt *pc, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+
+int ul_path_next_dirent(struct path_cxt *pc, DIR **sub, const char *dirname, struct dirent **d);
+
+FILE *ul_prefix_fopen(const char *prefix, const char *path, const char *mode);
+
+
+#ifdef HAVE_CPU_SET_T
+# include "cpuset.h"
+int ul_path_readf_cpuset(struct path_cxt *pc, cpu_set_t **set, int maxcpus, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 4, 5)));
+
+int ul_path_readf_cpulist(struct path_cxt *pc, cpu_set_t **set, int maxcpus, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 4, 5)));
+#endif /* HAVE_CPU_SET_T */
+#endif /* UTIL_LINUX_PATH_H */
diff --git a/include/pathnames.h b/include/pathnames.h
new file mode 100644
index 0000000..d86d9d5
--- /dev/null
+++ b/include/pathnames.h
@@ -0,0 +1,224 @@
+/*
+ * No copyright is claimed. This code is in the public domain; do with
+ * it what you wish.
+ */
+#ifndef PATHNAMES_H
+#define PATHNAMES_H
+
+#ifdef HAVE_PATHS_H
+# include <paths.h>
+#endif
+
+#ifndef __STDC__
+# error "we need an ANSI compiler"
+#endif
+
+/* used by kernel in /proc (e.g. /proc/swaps) for deleted files */
+#define PATH_DELETED_SUFFIX " (deleted)"
+
+/* DEFPATHs from <paths.h> don't include /usr/local */
+#undef _PATH_DEFPATH
+
+#ifdef USE_USRDIR_PATHS_ONLY
+# define _PATH_DEFPATH "/usr/local/bin:/usr/bin"
+#else
+# define _PATH_DEFPATH "/usr/local/bin:/bin:/usr/bin"
+#endif
+
+#undef _PATH_DEFPATH_ROOT
+
+#ifdef USE_USRDIR_PATHS_ONLY
+# define _PATH_DEFPATH_ROOT "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
+#else
+# define _PATH_DEFPATH_ROOT "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
+#endif
+
+#define _PATH_HUSHLOGIN ".hushlogin"
+#define _PATH_HUSHLOGINS "/etc/hushlogins"
+
+#define _PATH_NOLOGIN_TXT "/etc/nologin.txt"
+
+#ifndef _PATH_MAILDIR
+# define _PATH_MAILDIR "/var/spool/mail"
+#endif
+#define _PATH_MOTDFILE "/usr/share/misc/motd:/run/motd:/etc/motd"
+#ifndef _PATH_NOLOGIN
+# define _PATH_NOLOGIN "/etc/nologin"
+#endif
+#define _PATH_VAR_NOLOGIN "/var/run/nologin"
+
+#ifndef _PATH_LOGIN
+# define _PATH_LOGIN "/bin/login"
+#endif
+#define _PATH_SHUTDOWN "/sbin/shutdown"
+#define _PATH_POWEROFF "/sbin/poweroff"
+
+#define _PATH_TERMCOLORS_DIRNAME "terminal-colors.d"
+#define _PATH_TERMCOLORS_DIR "/etc/" _PATH_TERMCOLORS_DIRNAME
+
+/* login paths */
+#define _PATH_PASSWD "/etc/passwd"
+#define _PATH_GSHADOW "/etc/gshadow"
+#define _PATH_GROUP "/etc/group"
+#define _PATH_SHADOW_PASSWD "/etc/shadow"
+#define _PATH_SHELLS "/etc/shells"
+
+#ifndef _PATH_TMP
+# define _PATH_TMP "/tmp/"
+#endif
+
+#ifndef _PATH_BTMP
+# define _PATH_BTMP "/var/log/btmp"
+#endif
+
+#define _PATH_ISSUE_FILENAME "issue"
+#define _PATH_ISSUE_DIRNAME _PATH_ISSUE_FILENAME ".d"
+
+#define _PATH_ISSUE "/etc/" _PATH_ISSUE_FILENAME
+#define _PATH_ISSUEDIR "/etc/" _PATH_ISSUE_DIRNAME
+
+#define _PATH_OS_RELEASE_ETC "/etc/os-release"
+#define _PATH_OS_RELEASE_USR "/usr/lib/os-release"
+#define _PATH_NUMLOCK_ON _PATH_RUNSTATEDIR "/numlock-on"
+#define _PATH_LOGINDEFS "/etc/login.defs"
+
+#define _PATH_SD_UNITSLOAD _PATH_RUNSTATEDIR "/systemd/systemd-units-load"
+
+/* misc paths */
+#define _PATH_WORDS "/usr/share/dict/words"
+#define _PATH_WORDS_ALT "/usr/share/dict/web2"
+
+/* mount paths */
+#define _PATH_FILESYSTEMS "/etc/filesystems"
+#define _PATH_PROC "/proc"
+#define _PATH_PROC_SWAPS "/proc/swaps"
+#define _PATH_PROC_FILESYSTEMS "/proc/filesystems"
+#define _PATH_PROC_MOUNTS "/proc/mounts"
+#define _PATH_PROC_PARTITIONS "/proc/partitions"
+#define _PATH_PROC_DEVICES "/proc/devices"
+#define _PATH_PROC_MOUNTINFO "/proc/self/mountinfo"
+#define _PATH_PROC_LOCKS "/proc/locks"
+#define _PATH_PROC_CDROMINFO "/proc/sys/dev/cdrom/info"
+
+/* unshare paths */
+#define _PATH_SUBUID "/etc/subuid"
+#define _PATH_SUBGID "/etc/subgid"
+#define _PATH_PROC_UIDMAP "/proc/self/uid_map"
+#define _PATH_PROC_GIDMAP "/proc/self/gid_map"
+#define _PATH_PROC_SETGROUPS "/proc/self/setgroups"
+
+#define _PATH_PROC_FDDIR "/proc/self/fd"
+
+#define _PATH_PROC_ATTR_CURRENT "/proc/self/attr/current"
+#define _PATH_PROC_ATTR_EXEC "/proc/self/attr/exec"
+#define _PATH_PROC_CAPLASTCAP "/proc/sys/kernel/cap_last_cap"
+
+
+#define _PATH_SYS_BLOCK "/sys/block"
+#define _PATH_SYS_DEVBLOCK "/sys/dev/block"
+#define _PATH_SYS_DEVCHAR "/sys/dev/char"
+#define _PATH_SYS_CLASS "/sys/class"
+#define _PATH_SYS_SCSI "/sys/bus/scsi"
+
+#define _PATH_SYS_SELINUX "/sys/fs/selinux"
+#define _PATH_SYS_APPARMOR "/sys/kernel/security/apparmor"
+
+#ifndef _PATH_MOUNTED
+# ifdef MOUNTED /* deprecated */
+# define _PATH_MOUNTED MOUNTED
+# else
+# define _PATH_MOUNTED "/etc/mtab"
+# endif
+#endif
+
+#ifndef _PATH_MNTTAB
+# ifdef MNTTAB /* deprecated */
+# define _PATH_MNTTAB MNTTAB
+# else
+# define _PATH_MNTTAB "/etc/fstab"
+# endif
+#endif
+
+#ifndef _PATH_DEV
+ /*
+ * The tailing '/' in _PATH_DEV is there for compatibility with libc.
+ */
+# define _PATH_DEV "/dev/"
+#endif
+
+#define _PATH_DEV_MAPPER "/dev/mapper"
+
+#define _PATH_DEV_MEM "/dev/mem"
+
+#define _PATH_DEV_LOOP "/dev/loop"
+#define _PATH_DEV_LOOPCTL "/dev/loop-control"
+
+/* udev paths */
+#define _PATH_DEV_BYLABEL "/dev/disk/by-label"
+#define _PATH_DEV_BYUUID "/dev/disk/by-uuid"
+#define _PATH_DEV_BYID "/dev/disk/by-id"
+#define _PATH_DEV_BYPATH "/dev/disk/by-path"
+#define _PATH_DEV_BYPARTLABEL "/dev/disk/by-partlabel"
+#define _PATH_DEV_BYPARTUUID "/dev/disk/by-partuuid"
+
+/* hwclock paths */
+#ifdef CONFIG_ADJTIME_PATH
+# define _PATH_ADJTIME CONFIG_ADJTIME_PATH
+#else
+# define _PATH_ADJTIME "/etc/adjtime"
+#endif
+
+#ifdef __ia64__
+# define _PATH_RTC_DEV "/dev/efirtc"
+#else
+# define _PATH_RTC_DEV "/dev/rtc0"
+#endif
+
+/* raw paths*/
+#define _PATH_RAWDEVDIR "/dev/raw/"
+#define _PATH_RAWDEVCTL _PATH_RAWDEVDIR "rawctl"
+/* deprecated */
+#define _PATH_RAWDEVCTL_OLD "/dev/rawctl"
+
+#define _PATH_PROC_KERNEL "/proc/sys/kernel"
+
+/* ipc paths */
+#define _PATH_PROC_SYSV_MSG "/proc/sysvipc/msg"
+#define _PATH_PROC_SYSV_SEM "/proc/sysvipc/sem"
+#define _PATH_PROC_SYSV_SHM "/proc/sysvipc/shm"
+#define _PATH_PROC_IPC_MSGMAX _PATH_PROC_KERNEL "/msgmax"
+#define _PATH_PROC_IPC_MSGMNB _PATH_PROC_KERNEL "/msgmnb"
+#define _PATH_PROC_IPC_MSGMNI _PATH_PROC_KERNEL "/msgmni"
+#define _PATH_PROC_IPC_SEM _PATH_PROC_KERNEL "/sem"
+#define _PATH_PROC_IPC_SHMALL _PATH_PROC_KERNEL "/shmall"
+#define _PATH_PROC_IPC_SHMMAX _PATH_PROC_KERNEL "/shmmax"
+#define _PATH_PROC_IPC_SHMMNI _PATH_PROC_KERNEL "/shmmni"
+
+/* util clamp */
+#define _PATH_PROC_UCLAMP_MIN _PATH_PROC_KERNEL "/sched_util_clamp_min"
+#define _PATH_PROC_UCLAMP_MAX _PATH_PROC_KERNEL "/sched_util_clamp_max"
+
+/* irqtop paths */
+#define _PATH_PROC_INTERRUPTS "/proc/interrupts"
+#define _PATH_PROC_SOFTIRQS "/proc/softirqs"
+#define _PATH_PROC_UPTIME "/proc/uptime"
+
+/* kernel command line */
+#define _PATH_PROC_CMDLINE "/proc/cmdline"
+
+
+/* logger paths */
+#define _PATH_DEVLOG "/dev/log"
+
+/* ctrlaltdel paths */
+#define _PATH_PROC_CTRL_ALT_DEL "/proc/sys/kernel/ctrl-alt-del"
+
+/* lscpu paths */
+#define _PATH_PROC_CPUINFO "/proc/cpuinfo"
+
+/* rfkill paths */
+#define _PATH_DEV_RFKILL "/dev/rfkill"
+#define _PATH_SYS_RFKILL "/sys/class/rfkill"
+
+
+#endif /* PATHNAMES_H */
diff --git a/include/pidfd-utils.h b/include/pidfd-utils.h
new file mode 100644
index 0000000..eddede9
--- /dev/null
+++ b/include/pidfd-utils.h
@@ -0,0 +1,28 @@
+#ifndef UTIL_LINUX_PIDFD_UTILS
+#define UTIL_LINUX_PIDFD_UTILS
+
+#ifdef HAVE_SYS_SYSCALL_H
+# include <sys/syscall.h>
+# if defined(SYS_pidfd_send_signal) && defined(SYS_pidfd_open)
+# include <sys/types.h>
+
+# ifndef HAVE_PIDFD_SEND_SIGNAL
+static inline int pidfd_send_signal(int pidfd, int sig, siginfo_t *info,
+ unsigned int flags)
+{
+ return syscall(SYS_pidfd_send_signal, pidfd, sig, info, flags);
+}
+# endif
+
+# ifndef HAVE_PIDFD_OPEN
+static inline int pidfd_open(pid_t pid, unsigned int flags)
+{
+ return syscall(SYS_pidfd_open, pid, flags);
+}
+# endif
+
+# define UL_HAVE_PIDFD 1
+
+# endif /* SYS_pidfd_send_signal */
+#endif /* HAVE_SYS_SYSCALL_H */
+#endif /* UTIL_LINUX_PIDFD_UTILS */
diff --git a/include/plymouth-ctrl.h b/include/plymouth-ctrl.h
new file mode 100644
index 0000000..b6f1299
--- /dev/null
+++ b/include/plymouth-ctrl.h
@@ -0,0 +1,65 @@
+/*
+ * plymouth-ctrl.h Header file for communications with plymouthd
+ *
+ * Copyright (c) 2016 SUSE Linux GmbH, All rights reserved.
+ * Copyright (c) 2016 Werner Fink <werner@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING); if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * Author: Werner Fink <werner@suse.de>
+ */
+
+/*
+ * Taken from plymouth 0.9.0 src/ply-boot-protocol.h
+ */
+
+#ifndef UTIL_LINUX_PLYMOUTH_CTRL_H
+#define UTIL_LINUX_PLYMOUTH_CTRL_H
+
+#define PLYMOUTH_SOCKET_PATH "\0/org/freedesktop/plymouthd"
+#define ANSWER_TYP '\x2'
+#define ANSWER_ENQ '\x5'
+#define ANSWER_ACK '\x6'
+#define ANSWER_MLT '\t'
+#define ANSWER_NCK '\x15'
+
+#define MAGIC_PRG_STOP 'A'
+#define MAGIC_PRG_CONT 'a'
+#define MAGIC_UPDATE 'U'
+#define MAGIC_SYS_UPDATE 'u'
+#define MAGIC_SYS_INIT 'S'
+#define MAGIC_DEACTIVATE 'D'
+#define MAGIC_REACTIVATE 'r'
+#define MAGIC_SHOW_SPLASH '$'
+#define MAGIC_HIDE_SPLASH 'H'
+#define MAGIC_CHMOD 'C'
+#define MAGIC_CHROOT 'R'
+#define MAGIC_ACTIVE_VT 'V'
+#define MAGIC_QUESTION 'W'
+#define MAGIC_SHOW_MSG 'M'
+#define MAGIC_HIDE_MSG 'm'
+#define MAGIC_KEYSTROKE 'K'
+#define MAGIC_KEYSTROKE_RM 'L'
+#define MAGIC_PING 'P'
+#define MAGIC_QUIT 'Q'
+#define MAGIC_CACHED_PWD 'c'
+#define MAGIC_ASK_PWD '*'
+#define MAGIC_DETAILS '!'
+
+#define PLYMOUTH_TERMIOS_FLAGS_DELAY 30
+extern int plymouth_command(int cmd, ...);
+
+#endif /* UTIL_LINUX_PLYMOUTH_CTRL_H */
diff --git a/include/procfs.h b/include/procfs.h
new file mode 100644
index 0000000..5a730c9
--- /dev/null
+++ b/include/procfs.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 Karel Zak <kzak@redhat.com>
+ */
+#ifndef UTIL_LINUX_PROCFS_H
+#define UTIL_LINUX_PROCFS_H
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <inttypes.h>
+#include <dirent.h>
+
+#include "path.h"
+
+struct procfs_process {
+ pid_t pid;
+};
+
+extern void ul_procfs_init_debug(void);
+extern struct path_cxt *ul_new_procfs_path(pid_t pid, const char *prefix);
+extern int procfs_process_init_path(struct path_cxt *pc, pid_t pid);
+
+extern int procfs_process_get_uid(struct path_cxt *pc, uid_t *uid);
+extern ssize_t procfs_process_get_cmdline(struct path_cxt *pc, char *buf, size_t bufsz);
+extern ssize_t procfs_process_get_cmdname(struct path_cxt *pc, char *buf, size_t bufsz);
+extern ssize_t procfs_process_get_stat(struct path_cxt *pc, char *buf, size_t bufsz);
+
+
+static inline ssize_t procfs_process_get_exe(struct path_cxt *pc, char *buf, size_t bufsz)
+{
+ return ul_path_readlink(pc, buf, bufsz, "exe");
+}
+
+static inline ssize_t procfs_process_get_root(struct path_cxt *pc, char *buf, size_t bufsz)
+{
+ return ul_path_readlink(pc, buf, bufsz, "root");
+}
+
+static inline ssize_t procfs_process_get_cwd(struct path_cxt *pc, char *buf, size_t bufsz)
+{
+ return ul_path_readlink(pc, buf, bufsz, "cwd");
+}
+
+extern int procfs_process_next_tid(struct path_cxt *pc, DIR **sub, pid_t *tid);
+extern int procfs_process_next_fd(struct path_cxt *pc, DIR **sub, int *fd);
+
+extern int procfs_dirent_is_process(struct dirent *d);
+extern int procfs_dirent_get_pid(struct dirent *d, pid_t *pid);
+extern int procfs_dirent_get_uid(DIR *procfs, struct dirent *d, uid_t *uid);
+extern int procfs_dirent_match_uid(DIR *procfs, struct dirent *d, uid_t uid);
+extern int procfs_dirent_get_name(DIR *procfs, struct dirent *d, char *buf, size_t bufsz);
+extern int procfs_dirent_match_name(DIR *procfs, struct dirent *d, const char *name);
+
+extern int fd_is_procfs(int fd);
+extern char *pid_get_cmdname(pid_t pid);
+extern char *pid_get_cmdline(pid_t pid);
+
+#endif /* UTIL_LINUX_PROCFS_H */
diff --git a/include/pt-bsd.h b/include/pt-bsd.h
new file mode 100644
index 0000000..9bf47a5
--- /dev/null
+++ b/include/pt-bsd.h
@@ -0,0 +1,156 @@
+#ifndef UTIL_LINUX_PT_BSD_H
+#define UTIL_LINUX_PT_BSD_H
+
+#define BSD_MAXPARTITIONS 16
+#define BSD_FS_UNUSED 0
+
+#ifndef BSD_DISKMAGIC
+# define BSD_DISKMAGIC ((uint32_t) 0x82564557)
+#endif
+
+#define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
+
+#if defined (__alpha__) || defined (__powerpc__) || \
+ defined (__ia64__) || defined (__hppa__)
+# define BSD_LABELSECTOR 0
+# define BSD_LABELOFFSET 64
+#else
+# define BSD_LABELSECTOR 1
+# define BSD_LABELOFFSET 0
+#endif
+
+#define BSD_BBSIZE 8192 /* size of boot area, with label */
+#define BSD_SBSIZE 8192 /* max size of fs superblock */
+
+struct bsd_disklabel {
+ uint32_t d_magic; /* the magic number */
+ int16_t d_type; /* drive type */
+ int16_t d_subtype; /* controller/d_type specific */
+ char d_typename[16]; /* type name, e.g. "eagle" */
+ char d_packname[16]; /* pack identifier */
+
+ /* disk geometry: */
+ uint32_t d_secsize; /* # of bytes per sector */
+ uint32_t d_nsectors; /* # of data sectors per track */
+ uint32_t d_ntracks; /* # of tracks per cylinder */
+ uint32_t d_ncylinders; /* # of data cylinders per unit */
+ uint32_t d_secpercyl; /* # of data sectors per cylinder */
+ uint32_t d_secperunit; /* # of data sectors per unit */
+
+ /*
+ * Spares (bad sector replacements) below
+ * are not counted in d_nsectors or d_secpercyl.
+ * Spare sectors are assumed to be physical sectors
+ * which occupy space at the end of each track and/or cylinder.
+ */
+ uint16_t d_sparespertrack; /* # of spare sectors per track */
+ uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
+
+ /*
+ * Alternate cylinders include maintenance, replacement,
+ * configuration description areas, etc.
+ */
+ uint32_t d_acylinders; /* # of alt. cylinders per unit */
+
+ /* hardware characteristics: */
+ /*
+ * d_interleave, d_trackskew and d_cylskew describe perturbations
+ * in the media format used to compensate for a slow controller.
+ * Interleave is physical sector interleave, set up by the formatter
+ * or controller when formatting. When interleaving is in use,
+ * logically adjacent sectors are not physically contiguous,
+ * but instead are separated by some number of sectors.
+ * It is specified as the ratio of physical sectors traversed
+ * per logical sector. Thus an interleave of 1:1 implies contiguous
+ * layout, while 2:1 implies that logical sector 0 is separated
+ * by one sector from logical sector 1.
+ * d_trackskew is the offset of sector 0 on track N
+ * relative to sector 0 on track N-1 on the same cylinder.
+ * Finally, d_cylskew is the offset of sector 0 on cylinder N
+ * relative to sector 0 on cylinder N-1.
+ */
+ uint16_t d_rpm; /* rotational speed */
+ uint16_t d_interleave; /* hardware sector interleave */
+ uint16_t d_trackskew; /* sector 0 skew, per track */
+ uint16_t d_cylskew; /* sector 0 skew, per cylinder */
+ uint32_t d_headswitch; /* head switch time, usec */
+ uint32_t d_trkseek; /* track-to-track seek, usec */
+ uint32_t d_flags; /* generic flags */
+ uint32_t d_drivedata[5]; /* drive-type specific information */
+ uint32_t d_spare[5]; /* reserved for future use */
+ uint32_t d_magic2; /* the magic number (again) */
+ uint16_t d_checksum; /* xor of data incl. partitions */
+
+ /* filesystem and partition information: */
+ uint16_t d_npartitions; /* number of partitions in following */
+ uint32_t d_bbsize; /* size of boot area at sn0, bytes */
+ uint32_t d_sbsize; /* max size of fs superblock, bytes */
+
+ struct bsd_partition { /* the partition table */
+ uint32_t p_size; /* number of sectors in partition */
+ uint32_t p_offset; /* starting sector */
+ uint32_t p_fsize; /* filesystem basic fragment size */
+ uint8_t p_fstype; /* filesystem type, see below */
+ uint8_t p_frag; /* filesystem fragments per block */
+ uint16_t p_cpg; /* filesystem cylinders per group */
+ } __attribute__((packed)) d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
+} __attribute__((packed));
+
+
+/* d_type values: */
+#define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
+#define BSD_DTYPE_MSCP 2 /* MSCP */
+#define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
+#define BSD_DTYPE_SCSI 4 /* SCSI */
+#define BSD_DTYPE_ESDI 5 /* ESDI interface */
+#define BSD_DTYPE_ST506 6 /* ST506 etc. */
+#define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
+#define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
+#define BSD_DTYPE_FLOPPY 10 /* floppy */
+
+/* d_subtype values: */
+#define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
+#define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
+#define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
+
+/*
+ * Filesystem type and version.
+ * Used to interpret other filesystem-specific
+ * per-partition information.
+ */
+#define BSD_FS_UNUSED 0 /* unused */
+#define BSD_FS_SWAP 1 /* swap */
+#define BSD_FS_V6 2 /* Sixth Edition */
+#define BSD_FS_V7 3 /* Seventh Edition */
+#define BSD_FS_SYSV 4 /* System V */
+#define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
+#define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
+#define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
+#define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
+#define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
+#define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
+#define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
+#define BSD_FS_ISOFS BSD_FS_ISO9660
+#define BSD_FS_BOOT 13 /* partition contains bootstrap */
+#define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
+#define BSD_FS_HFS 15 /* Macintosh HFS */
+#define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
+
+/* this is annoying, but it's also the way it is :-( */
+#ifdef __alpha__
+#define BSD_FS_EXT2 8 /* ext2 file system */
+#else
+#define BSD_FS_MSDOS 8 /* MS-DOS file system */
+#endif
+
+/*
+ * flags shared by various drives:
+ */
+#define BSD_D_REMOVABLE 0x01 /* removable media */
+#define BSD_D_ECC 0x02 /* supports ECC */
+#define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
+#define BSD_D_RAMDISK 0x08 /* disk emulator */
+#define BSD_D_CHAIN 0x10 /* can do back-back transfers */
+#define BSD_D_DOSPART 0x20 /* within MSDOS partition */
+
+#endif /* UTIL_LINUX_PT_BSD_H */
diff --git a/include/pt-gpt-partnames.h b/include/pt-gpt-partnames.h
new file mode 100644
index 0000000..4b91568
--- /dev/null
+++ b/include/pt-gpt-partnames.h
@@ -0,0 +1,271 @@
+
+/*
+ * No copyright is claimed. This code is in the public domain; do with
+ * it what you wish.
+ *
+ * Written by Karel Zak <kzak@redhat.com>
+ *
+ * Probably the most complete list of the GUIDs are at:
+ * https://wikipedia.org/wiki/GUID_Partition_Table
+ *
+ * The macro DEF_GUID() has to be defined in your code according to array where
+ * you want to include this file.
+ */
+
+/* Generic OS */
+DEF_GUID("C12A7328-F81F-11D2-BA4B-00A0C93EC93B", N_("EFI System")),
+
+DEF_GUID("024DEE41-33E7-11D3-9D69-0008C781F39F", N_("MBR partition scheme")),
+DEF_GUID("D3BFE2DE-3DAF-11DF-BA40-E3A556D89593", N_("Intel Fast Flash")),
+
+/* Hah!IdontneedEFI */
+DEF_GUID("21686148-6449-6E6F-744E-656564454649", N_("BIOS boot")),
+
+/* NIH syndrome */
+DEF_GUID("F4019732-066E-4E12-8273-346C5641494F", N_("Sony boot partition")),
+DEF_GUID("BFBFAFE7-A34F-448A-9A5B-6213EB736C22", N_("Lenovo boot partition")),
+
+/* PowerPC reference platform boot partition */
+DEF_GUID("9E1A2D38-C612-4316-AA26-8B49521E5A8B", N_("PowerPC PReP boot")),
+
+/* Open Network Install Environment */
+DEF_GUID("7412F7D5-A156-4B13-81DC-867174929325", N_("ONIE boot")),
+DEF_GUID("D4E6E2CD-4469-46F3-B5CB-1BFF57AFC149", N_("ONIE config")),
+
+/* Windows */
+DEF_GUID("E3C9E316-0B5C-4DB8-817D-F92DF00215AE", N_("Microsoft reserved")),
+DEF_GUID("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", N_("Microsoft basic data")),
+DEF_GUID("5808C8AA-7E8F-42E0-85D2-E1E90434CFB3", N_("Microsoft LDM metadata")),
+DEF_GUID("AF9B60A0-1431-4F62-BC68-3311714A69AD", N_("Microsoft LDM data")),
+DEF_GUID("DE94BBA4-06D1-4D40-A16A-BFD50179D6AC", N_("Windows recovery environment")),
+DEF_GUID("37AFFC90-EF7D-4E96-91C3-2D7AE055B174", N_("IBM General Parallel Fs")),
+DEF_GUID("E75CAF8F-F680-4CEE-AFA3-B001E56EFC2D", N_("Microsoft Storage Spaces")),
+
+/* HP-UX */
+DEF_GUID("75894C1E-3AEB-11D3-B7C1-7B03A0000000", N_("HP-UX data")),
+DEF_GUID("E2A1E728-32E3-11D6-A682-7B03A0000000", N_("HP-UX service")),
+
+/* Linux (https://systemd.io/DISCOVERABLE_PARTITIONS/) */
+DEF_GUID("0657FD6D-A4AB-43C4-84E5-0933C84B4F4F", N_("Linux swap")),
+DEF_GUID("0FC63DAF-8483-4772-8E79-3D69D8477DE4", N_("Linux filesystem")),
+DEF_GUID("3B8F8425-20E0-4F3B-907F-1A25A76F98E8", N_("Linux server data")),
+DEF_GUID("44479540-F297-41B2-9AF7-D131D5F0458A", N_("Linux root (x86)")),
+DEF_GUID("4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709", N_("Linux root (x86-64)")),
+DEF_GUID("6523F8AE-3EB1-4E2A-A05A-18B695AE656F", N_("Linux root (Alpha)")),
+DEF_GUID("D27F46ED-2919-4CB8-BD25-9531F3C16534", N_("Linux root (ARC)")),
+DEF_GUID("69DAD710-2CE4-4E3C-B16C-21A1D49ABED3", N_("Linux root (ARM)")),
+DEF_GUID("B921B045-1DF0-41C3-AF44-4C6F280D3FAE", N_("Linux root (ARM-64)")),
+DEF_GUID("993D8D3D-F80E-4225-855A-9DAF8ED7EA97", N_("Linux root (IA-64)")),
+DEF_GUID("77055800-792C-4F94-B39A-98C91B762BB6", N_("Linux root (LoongArch-64)")),
+DEF_GUID("37C58C8A-D913-4156-A25F-48B1B64E07F0", N_("Linux root (MIPS-32 LE)")),
+DEF_GUID("700BDA43-7A34-4507-B179-EEB93D7A7CA3", N_("Linux root (MIPS-64 LE)")),
+DEF_GUID("1DE3F1EF-FA98-47B5-8DCD-4A860A654D78", N_("Linux root (PPC)")),
+DEF_GUID("912ADE1D-A839-4913-8964-A10EEE08FBD2", N_("Linux root (PPC64)")),
+DEF_GUID("C31C45E6-3F39-412E-80FB-4809C4980599", N_("Linux root (PPC64LE)")),
+DEF_GUID("60D5A7FE-8E7D-435C-B714-3DD8162144E1", N_("Linux root (RISC-V-32)")),
+DEF_GUID("72EC70A6-CF74-40E6-BD49-4BDA08E8F224", N_("Linux root (RISC-V-64)")),
+DEF_GUID("08A7ACEA-624C-4A20-91E8-6E0FA67D23F9", N_("Linux root (S390)")),
+DEF_GUID("5EEAD9A9-FE09-4A1E-A1D7-520D00531306", N_("Linux root (S390X)")),
+DEF_GUID("C50CDD70-3862-4CC3-90E1-809A8C93EE2C", N_("Linux root (TILE-Gx)")),
+DEF_GUID("8DA63339-0007-60C0-C436-083AC8230908", N_("Linux reserved")),
+DEF_GUID("933AC7E1-2EB4-4F13-B844-0E14E2AEF915", N_("Linux home")),
+DEF_GUID("A19D880F-05FC-4D3B-A006-743F0F84911E", N_("Linux RAID")),
+DEF_GUID("E6D6D379-F507-44C2-A23C-238F2A3DF928", N_("Linux LVM")),
+DEF_GUID("4D21B016-B534-45C2-A9FB-5C16E091FD2D", N_("Linux variable data")),
+DEF_GUID("7EC6F557-3BC5-4ACA-B293-16EF5DF639D1", N_("Linux temporary data")),
+DEF_GUID("75250D76-8CC6-458E-BD66-BD47CC81A812", N_("Linux /usr (x86)")),
+DEF_GUID("8484680C-9521-48C6-9C11-B0720656F69E", N_("Linux /usr (x86-64)")),
+DEF_GUID("E18CF08C-33EC-4C0D-8246-C6C6FB3DA024", N_("Linux /usr (Alpha)")),
+DEF_GUID("7978A683-6316-4922-BBEE-38BFF5A2FECC", N_("Linux /usr (ARC)")),
+DEF_GUID("7D0359A3-02B3-4F0A-865C-654403E70625", N_("Linux /usr (ARM)")),
+DEF_GUID("B0E01050-EE5F-4390-949A-9101B17104E9", N_("Linux /usr (ARM-64)")),
+DEF_GUID("4301D2A6-4E3B-4B2A-BB94-9E0B2C4225EA", N_("Linux /usr (IA-64)")),
+DEF_GUID("E611C702-575C-4CBE-9A46-434FA0BF7E3F", N_("Linux /usr (LoongArch-64)")),
+DEF_GUID("0F4868E9-9952-4706-979F-3ED3A473E947", N_("Linux /usr (MIPS-32 LE)")),
+DEF_GUID("C97C1F32-BA06-40B4-9F22-236061B08AA8", N_("Linux /usr (MIPS-64 LE)")),
+DEF_GUID("7D14FEC5-CC71-415D-9D6C-06BF0B3C3EAF", N_("Linux /usr (PPC)")),
+DEF_GUID("2C9739E2-F068-46B3-9FD0-01C5A9AFBCCA", N_("Linux /usr (PPC64)")),
+DEF_GUID("15BB03AF-77E7-4D4A-B12B-C0D084F7491C", N_("Linux /usr (PPC64LE)")),
+DEF_GUID("B933FB22-5C3F-4F91-AF90-E2BB0FA50702", N_("Linux /usr (RISC-V-32)")),
+DEF_GUID("BEAEC34B-8442-439B-A40B-984381ED097D", N_("Linux /usr (RISC-V-64)")),
+DEF_GUID("CD0F869B-D0FB-4CA0-B141-9EA87CC78D66", N_("Linux /usr (S390)")),
+DEF_GUID("8A4F5770-50AA-4ED3-874A-99B710DB6FEA", N_("Linux /usr (S390X)")),
+DEF_GUID("55497029-C7C1-44CC-AA39-815ED1558630", N_("Linux /usr (TILE-Gx)")),
+DEF_GUID("D13C5D3B-B5D1-422A-B29F-9454FDC89D76", N_("Linux root verity (x86)")),
+DEF_GUID("2C7357ED-EBD2-46D9-AEC1-23D437EC2BF5", N_("Linux root verity (x86-64)")),
+DEF_GUID("FC56D9E9-E6E5-4C06-BE32-E74407CE09A5", N_("Linux root verity (Alpha)")),
+DEF_GUID("24B2D975-0F97-4521-AFA1-CD531E421B8D", N_("Linux root verity (ARC)")),
+DEF_GUID("7386CDF2-203C-47A9-A498-F2ECCE45A2D6", N_("Linux root verity (ARM)")),
+DEF_GUID("DF3300CE-D69F-4C92-978C-9BFB0F38D820", N_("Linux root verity (ARM-64)")),
+DEF_GUID("86ED10D5-B607-45BB-8957-D350F23D0571", N_("Linux root verity (IA-64)")),
+DEF_GUID("F3393B22-E9AF-4613-A948-9D3BFBD0C535", N_("Linux root verity (LoongArch-64)")),
+DEF_GUID("D7D150D2-2A04-4A33-8F12-16651205FF7B", N_("Linux root verity (MIPS-32 LE)")),
+DEF_GUID("16B417F8-3E06-4F57-8DD2-9B5232F41AA6", N_("Linux root verity (MIPS-64 LE)")),
+DEF_GUID("98CFE649-1588-46DC-B2F0-ADD147424925", N_("Linux root verity (PPC)")),
+DEF_GUID("9225A9A3-3C19-4D89-B4F6-EEFF88F17631", N_("Linux root verity (PPC64)")),
+DEF_GUID("906BD944-4589-4AAE-A4E4-DD983917446A", N_("Linux root verity (PPC64LE)")),
+DEF_GUID("AE0253BE-1167-4007-AC68-43926C14C5DE", N_("Linux root verity (RISC-V-32)")),
+DEF_GUID("B6ED5582-440B-4209-B8DA-5FF7C419EA3D", N_("Linux root verity (RISC-V-64)")),
+DEF_GUID("7AC63B47-B25C-463B-8DF8-B4A94E6C90E1", N_("Linux root verity (S390)")),
+DEF_GUID("B325BFBE-C7BE-4AB8-8357-139E652D2F6B", N_("Linux root verity (S390X)")),
+DEF_GUID("966061EC-28E4-4B2E-B4A5-1F0A825A1D84", N_("Linux root verity (TILE-Gx)")),
+DEF_GUID("8F461B0D-14EE-4E81-9AA9-049B6FB97ABD", N_("Linux /usr verity (x86)")),
+DEF_GUID("77FF5F63-E7B6-4633-ACF4-1565B864C0E6", N_("Linux /usr verity (x86-64)")),
+DEF_GUID("8CCE0D25-C0D0-4A44-BD87-46331BF1DF67", N_("Linux /usr verity (Alpha)")),
+DEF_GUID("FCA0598C-D880-4591-8C16-4EDA05C7347C", N_("Linux /usr verity (ARC)")),
+DEF_GUID("C215D751-7BCD-4649-BE90-6627490A4C05", N_("Linux /usr verity (ARM)")),
+DEF_GUID("6E11A4E7-FBCA-4DED-B9E9-E1A512BB664E", N_("Linux /usr verity (ARM-64)")),
+DEF_GUID("6A491E03-3BE7-4545-8E38-83320E0EA880", N_("Linux /usr verity (IA-64)")),
+DEF_GUID("F46B2C26-59AE-48F0-9106-C50ED47F673D", N_("Linux /usr verity (LoongArch-64)")),
+DEF_GUID("46B98D8D-B55C-4E8F-AAB3-37FCA7F80752", N_("Linux /usr verity (MIPS-32 LE)")),
+DEF_GUID("3C3D61FE-B5F3-414D-BB71-8739A694A4EF", N_("Linux /usr verity (MIPS-64 LE)")),
+DEF_GUID("DF765D00-270E-49E5-BC75-F47BB2118B09", N_("Linux /usr verity (PPC)")),
+DEF_GUID("BDB528A5-A259-475F-A87D-DA53FA736A07", N_("Linux /usr verity (PPC64)")),
+DEF_GUID("EE2B9983-21E8-4153-86D9-B6901A54D1CE", N_("Linux /usr verity (PPC64LE)")),
+DEF_GUID("CB1EE4E3-8CD0-4136-A0A4-AA61A32E8730", N_("Linux /usr verity (RISC-V-32)")),
+DEF_GUID("8F1056BE-9B05-47C4-81D6-BE53128E5B54", N_("Linux /usr verity (RISC-V-64)")),
+DEF_GUID("B663C618-E7BC-4D6D-90AA-11B756BB1797", N_("Linux /usr verity (S390)")),
+DEF_GUID("31741CC4-1A2A-4111-A581-E00B447D2D06", N_("Linux /usr verity (S390X)")),
+DEF_GUID("2FB4BF56-07FA-42DA-8132-6B139F2026AE", N_("Linux /usr verity (TILE-Gx)")),
+DEF_GUID("5996FC05-109C-48DE-808B-23FA0830B676", N_("Linux root verity sign. (x86)")),
+DEF_GUID("41092B05-9FC8-4523-994F-2DEF0408B176", N_("Linux root verity sign. (x86-64)")),
+DEF_GUID("D46495B7-A053-414F-80F7-700C99921EF8", N_("Linux root verity sign. (Alpha)")),
+DEF_GUID("143A70BA-CBD3-4F06-919F-6C05683A78BC", N_("Linux root verity sign. (ARC)")),
+DEF_GUID("42B0455F-EB11-491D-98D3-56145BA9D037", N_("Linux root verity sign. (ARM)")),
+DEF_GUID("6DB69DE6-29F4-4758-A7A5-962190F00CE3", N_("Linux root verity sign. (ARM-64)")),
+DEF_GUID("E98B36EE-32BA-4882-9B12-0CE14655F46A", N_("Linux root verity sign. (IA-64)")),
+DEF_GUID("5AFB67EB-ECC8-4F85-AE8E-AC1E7C50E7D0", N_("Linux root verity sign. (LoongArch-64)")),
+DEF_GUID("C919CC1F-4456-4EFF-918C-F75E94525CA5", N_("Linux root verity sign. (MIPS-32 LE)")),
+DEF_GUID("904E58EF-5C65-4A31-9C57-6AF5FC7C5DE7", N_("Linux root verity sign. (MIPS-64 LE)")),
+DEF_GUID("1B31B5AA-ADD9-463A-B2ED-BD467FC857E7", N_("Linux root verity sign. (PPC)")),
+DEF_GUID("F5E2C20C-45B2-4FFA-BCE9-2A60737E1AAF", N_("Linux root verity sign. (PPC64)")),
+DEF_GUID("D4A236E7-E873-4C07-BF1D-BF6CF7F1C3C6", N_("Linux root verity sign. (PPC64LE)")),
+DEF_GUID("3A112A75-8729-4380-B4CF-764D79934448", N_("Linux root verity sign. (RISC-V-32)")),
+DEF_GUID("EFE0F087-EA8D-4469-821A-4C2A96A8386A", N_("Linux root verity sign. (RISC-V-64)")),
+DEF_GUID("3482388E-4254-435A-A241-766A065F9960", N_("Linux root verity sign. (S390)")),
+DEF_GUID("C80187A5-73A3-491A-901A-017C3FA953E9", N_("Linux root verity sign. (S390X)")),
+DEF_GUID("B3671439-97B0-4A53-90F7-2D5A8F3AD47B", N_("Linux root verity sign. (TILE-Gx)")),
+DEF_GUID("974A71C0-DE41-43C3-BE5D-5C5CCD1AD2C0", N_("Linux /usr verity sign. (x86)")),
+DEF_GUID("E7BB33FB-06CF-4E81-8273-E543B413E2E2", N_("Linux /usr verity sign. (x86-64)")),
+DEF_GUID("5C6E1C76-076A-457A-A0FE-F3B4CD21CE6E", N_("Linux /usr verity sign. (Alpha)")),
+DEF_GUID("94F9A9A1-9971-427A-A400-50CB297F0F35", N_("Linux /usr verity sign. (ARC)")),
+DEF_GUID("D7FF812F-37D1-4902-A810-D76BA57B975A", N_("Linux /usr verity sign. (ARM)")),
+DEF_GUID("C23CE4FF-44BD-4B00-B2D4-B41B3419E02A", N_("Linux /usr verity sign. (ARM-64)")),
+DEF_GUID("8DE58BC2-2A43-460D-B14E-A76E4A17B47F", N_("Linux /usr verity sign. (IA-64)")),
+DEF_GUID("B024F315-D330-444C-8461-44BBDE524E99", N_("Linux /usr verity sign. (LoongArch-64)")),
+DEF_GUID("3E23CA0B-A4BC-4B4E-8087-5AB6A26AA8A9", N_("Linux /usr verity sign. (MIPS-32 LE)")),
+DEF_GUID("F2C2C7EE-ADCC-4351-B5C6-EE9816B66E16", N_("Linux /usr verity sign. (MIPS-64 LE)")),
+DEF_GUID("7007891D-D371-4A80-86A4-5CB875B9302E", N_("Linux /usr verity sign. (PPC)")),
+DEF_GUID("0B888863-D7F8-4D9E-9766-239FCE4D58AF", N_("Linux /usr verity sign. (PPC64)")),
+DEF_GUID("C8BFBD1E-268E-4521-8BBA-BF314C399557", N_("Linux /usr verity sign. (PPC64LE)")),
+DEF_GUID("C3836A13-3137-45BA-B583-B16C50FE5EB4", N_("Linux /usr verity sign. (RISC-V-32)")),
+DEF_GUID("D2F9000A-7A18-453F-B5CD-4D32F77A7B32", N_("Linux /usr verity sign. (RISC-V-64)")),
+DEF_GUID("17440E4F-A8D0-467F-A46E-3912AE6EF2C5", N_("Linux /usr verity sign. (S390)")),
+DEF_GUID("3F324816-667B-46AE-86EE-9B0C0C6C11B4", N_("Linux /usr verity sign. (S390X)")),
+DEF_GUID("4EDE75E2-6CCC-4CC8-B9C7-70334B087510", N_("Linux /usr verity sign. (TILE-Gx)")),
+/* ... too crazy, ignore for now:
+DEF_GUID("7FFEC5C9-2D00-49B7-8941-3EA10A5586B7", N_("Linux plain dm-crypt")),
+DEF_GUID("CA7D7CCB-63ED-4C53-861C-1742536059CC", N_("Linux LUKS")),
+*/
+/* Linux https://systemd.io/BOOT_LOADER_SPECIFICATION/ */
+DEF_GUID("BC13C2FF-59E6-4262-A352-B275FD6F7172", N_("Linux extended boot")),
+
+/* Linux https://systemd.io/HOME_DIRECTORY/ */
+DEF_GUID("773f91ef-66d4-49b5-bd83-d683bf40ad16", N_("Linux user's home")),
+
+/* FreeBSD */
+DEF_GUID("516E7CB4-6ECF-11D6-8FF8-00022D09712B", N_("FreeBSD data")),
+DEF_GUID("83BD6B9D-7F41-11DC-BE0B-001560B84F0F", N_("FreeBSD boot")),
+DEF_GUID("516E7CB5-6ECF-11D6-8FF8-00022D09712B", N_("FreeBSD swap")),
+DEF_GUID("516E7CB6-6ECF-11D6-8FF8-00022D09712B", N_("FreeBSD UFS")),
+DEF_GUID("516E7CBA-6ECF-11D6-8FF8-00022D09712B", N_("FreeBSD ZFS")),
+DEF_GUID("516E7CB8-6ECF-11D6-8FF8-00022D09712B", N_("FreeBSD Vinum")),
+
+/* Apple OSX */
+DEF_GUID("48465300-0000-11AA-AA11-00306543ECAC", N_("Apple HFS/HFS+")),
+DEF_GUID("7C3457EF-0000-11AA-AA11-00306543ECAC", N_("Apple APFS")),
+DEF_GUID("55465300-0000-11AA-AA11-00306543ECAC", N_("Apple UFS")),
+DEF_GUID("52414944-0000-11AA-AA11-00306543ECAC", N_("Apple RAID")),
+DEF_GUID("52414944-5F4F-11AA-AA11-00306543ECAC", N_("Apple RAID offline")),
+DEF_GUID("426F6F74-0000-11AA-AA11-00306543ECAC", N_("Apple boot")),
+DEF_GUID("4C616265-6C00-11AA-AA11-00306543ECAC", N_("Apple label")),
+DEF_GUID("5265636F-7665-11AA-AA11-00306543ECAC", N_("Apple TV recovery")),
+DEF_GUID("53746F72-6167-11AA-AA11-00306543ECAC", N_("Apple Core storage")),
+DEF_GUID("69646961-6700-11AA-AA11-00306543ECAC", N_("Apple Silicon boot")),
+DEF_GUID("52637672-7900-11AA-AA11-00306543ECAC", N_("Apple Silicon recovery")),
+
+/* Solaris */
+DEF_GUID("6A82CB45-1DD2-11B2-99A6-080020736631", N_("Solaris boot")),
+DEF_GUID("6A85CF4D-1DD2-11B2-99A6-080020736631", N_("Solaris root")),
+/* same as Apple ZFS */
+DEF_GUID("6A898CC3-1DD2-11B2-99A6-080020736631", N_("Solaris /usr & Apple ZFS")),
+DEF_GUID("6A87C46F-1DD2-11B2-99A6-080020736631", N_("Solaris swap")),
+DEF_GUID("6A8B642B-1DD2-11B2-99A6-080020736631", N_("Solaris backup")),
+DEF_GUID("6A8EF2E9-1DD2-11B2-99A6-080020736631", N_("Solaris /var")),
+DEF_GUID("6A90BA39-1DD2-11B2-99A6-080020736631", N_("Solaris /home")),
+DEF_GUID("6A9283A5-1DD2-11B2-99A6-080020736631", N_("Solaris alternate sector")),
+DEF_GUID("6A945A3B-1DD2-11B2-99A6-080020736631", N_("Solaris reserved 1")),
+DEF_GUID("6A9630D1-1DD2-11B2-99A6-080020736631", N_("Solaris reserved 2")),
+DEF_GUID("6A980767-1DD2-11B2-99A6-080020736631", N_("Solaris reserved 3")),
+DEF_GUID("6A96237F-1DD2-11B2-99A6-080020736631", N_("Solaris reserved 4")),
+DEF_GUID("6A8D2AC7-1DD2-11B2-99A6-080020736631", N_("Solaris reserved 5")),
+
+/* NetBSD */
+/* References:
+ * Current: https://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/sys/sys/disklabel_gpt.h
+ * Release 9: https://ftp.netbsd.org/pub/NetBSD/NetBSD-release-9/src/sys/sys/disklabel_gpt.h
+ * Latest CVS: http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/sys/disklabel_gpt.h?rev=.&content-type=text/x-cvsweb-markup
+ */
+DEF_GUID("49F48D32-B10E-11DC-B99B-0019D1879648", N_("NetBSD swap")),
+DEF_GUID("49F48D5A-B10E-11DC-B99B-0019D1879648", N_("NetBSD FFS")),
+DEF_GUID("49F48D82-B10E-11DC-B99B-0019D1879648", N_("NetBSD LFS")),
+DEF_GUID("2DB519C4-B10F-11DC-B99B-0019D1879648", N_("NetBSD concatenated")),
+DEF_GUID("2DB519EC-B10F-11DC-B99B-0019D1879648", N_("NetBSD encrypted")),
+DEF_GUID("49F48DAA-B10E-11DC-B99B-0019D1879648", N_("NetBSD RAID")),
+
+/* ChromeOS */
+DEF_GUID("FE3A2A5D-4F32-41A7-B725-ACCC3285A309", N_("ChromeOS kernel")),
+DEF_GUID("3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC", N_("ChromeOS root fs")),
+DEF_GUID("2E0A753D-9E48-43B0-8337-B15192CB1B5E", N_("ChromeOS reserved")),
+
+/* MidnightBSD */
+DEF_GUID("85D5E45A-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD data")),
+DEF_GUID("85D5E45E-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD boot")),
+DEF_GUID("85D5E45B-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD swap")),
+DEF_GUID("0394EF8B-237E-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD UFS")),
+DEF_GUID("85D5E45D-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD ZFS")),
+DEF_GUID("85D5E45C-237C-11E1-B4B3-E89A8F7FC3A7", N_("MidnightBSD Vinum")),
+
+/* Ceph */
+DEF_GUID("45B0969E-9B03-4F30-B4C6-B4B80CEFF106", N_("Ceph Journal")),
+DEF_GUID("45B0969E-9B03-4F30-B4C6-5EC00CEFF106", N_("Ceph Encrypted Journal")),
+DEF_GUID("4FBD7E29-9D25-41B8-AFD0-062C0CEFF05D", N_("Ceph OSD")),
+DEF_GUID("4FBD7E29-9D25-41B8-AFD0-5EC00CEFF05D", N_("Ceph crypt OSD")),
+DEF_GUID("89C57F98-2FE5-4DC0-89C1-F3AD0CEFF2BE", N_("Ceph disk in creation")),
+DEF_GUID("89C57F98-2FE5-4DC0-89C1-5EC00CEFF2BE", N_("Ceph crypt disk in creation")),
+
+/* VMware */
+DEF_GUID("AA31E02A-400F-11DB-9590-000C2911D1B8", N_("VMware VMFS")),
+DEF_GUID("9D275380-40AD-11DB-BF97-000C2911D1B8", N_("VMware Diagnostic")),
+DEF_GUID("381CFCCC-7288-11E0-92EE-000C2911D0B2", N_("VMware Virtual SAN")),
+DEF_GUID("77719A0C-A4A0-11E3-A47E-000C29745A24", N_("VMware Virsto")),
+DEF_GUID("9198EFFC-31C0-11DB-8F78-000C2911D1B8", N_("VMware Reserved")),
+
+/* OpenBSD */
+DEF_GUID("824CC7A0-36A8-11E3-890A-952519AD3F61", N_("OpenBSD data")),
+
+/* QNX */
+DEF_GUID("CEF5A9AD-73BC-4601-89F3-CDEEEEE321A1", N_("QNX6 file system")),
+
+/* Plan 9 */
+DEF_GUID("C91818F9-8025-47AF-89D2-F030D7000C2C", N_("Plan 9 partition")),
+
+/* HiFive bootloaders */
+DEF_GUID("5B193300-FC78-40CD-8002-E86C45580B47", N_("HiFive FSBL")),
+DEF_GUID("2E54B353-1271-4842-806F-E436D6AF6985", N_("HiFive BBL")),
+
+/* Haiku */
+DEF_GUID("42465331-3BA3-10F1-802A-4861696B7521", N_("Haiku BFS")),
+
+/* Marvell */
+DEF_GUID("6828311A-BA55-42A4-BCDE-A89BB5EDECAE", N_("Marvell Armada 3700 Boot partition")),
diff --git a/include/pt-mbr-partnames.h b/include/pt-mbr-partnames.h
new file mode 100644
index 0000000..9304793
--- /dev/null
+++ b/include/pt-mbr-partnames.h
@@ -0,0 +1,113 @@
+ {0x00, N_("Empty")},
+ {0x01, N_("FAT12")},
+ {0x02, N_("XENIX root")},
+ {0x03, N_("XENIX usr")},
+ {0x04, N_("FAT16 <32M")},
+ {0x05, N_("Extended")}, /* DOS 3.3+ extended partition */
+ {0x06, N_("FAT16")}, /* DOS 16-bit >=32M */
+ {0x07, N_("HPFS/NTFS/exFAT")}, /* OS/2 IFS, eg, HPFS or NTFS or QNX or exFAT */
+ {0x08, N_("AIX")}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
+ {0x09, N_("AIX bootable")}, /* AIX data or Coherent */
+ {0x0a, N_("OS/2 Boot Manager")},/* OS/2 Boot Manager */
+ {0x0b, N_("W95 FAT32")},
+ {0x0c, N_("W95 FAT32 (LBA)")},/* LBA really is `Extended Int 13h' */
+ {0x0e, N_("W95 FAT16 (LBA)")},
+ {0x0f, N_("W95 Ext'd (LBA)")},
+ {0x10, N_("OPUS")},
+ {0x11, N_("Hidden FAT12")},
+ {0x12, N_("Compaq diagnostics")},
+ {0x14, N_("Hidden FAT16 <32M")},
+ {0x16, N_("Hidden FAT16")},
+ {0x17, N_("Hidden HPFS/NTFS")},
+ {0x18, N_("AST SmartSleep")},
+ {0x1b, N_("Hidden W95 FAT32")},
+ {0x1c, N_("Hidden W95 FAT32 (LBA)")},
+ {0x1e, N_("Hidden W95 FAT16 (LBA)")},
+ {0x24, N_("NEC DOS")},
+ {0x27, N_("Hidden NTFS WinRE")},
+ {0x39, N_("Plan 9")},
+ {0x3c, N_("PartitionMagic recovery")},
+ {0x40, N_("Venix 80286")},
+ {0x41, N_("PPC PReP Boot")},
+ {0x42, N_("SFS")},
+ {0x4d, N_("QNX4.x")},
+ {0x4e, N_("QNX4.x 2nd part")},
+ {0x4f, N_("QNX4.x 3rd part")},
+ {0x50, N_("OnTrack DM")},
+ {0x51, N_("OnTrack DM6 Aux1")}, /* (or Novell) */
+ {0x52, N_("CP/M")}, /* CP/M or Microport SysV/AT */
+ {0x53, N_("OnTrack DM6 Aux3")},
+ {0x54, N_("OnTrackDM6")},
+ {0x55, N_("EZ-Drive")},
+ {0x56, N_("Golden Bow")},
+ {0x5c, N_("Priam Edisk")},
+ {0x61, N_("SpeedStor")},
+ {0x63, N_("GNU HURD or SysV")}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
+ {0x64, N_("Novell Netware 286")},
+ {0x65, N_("Novell Netware 386")},
+ {0x70, N_("DiskSecure Multi-Boot")},
+ {0x75, N_("PC/IX")},
+ {0x80, N_("Old Minix")}, /* Minix 1.4a and earlier */
+ {0x81, N_("Minix / old Linux")},/* Minix 1.4b and later */
+ {0x82, N_("Linux swap / Solaris")},
+ {0x83, N_("Linux")},
+ {0x84, N_("OS/2 hidden or Intel hibernation")},/* OS/2 hidden C: drive,
+ hibernation type Microsoft APM
+ or hibernation Intel Rapid Start */
+ {0x85, N_("Linux extended")},
+ {0x86, N_("NTFS volume set")},
+ {0x87, N_("NTFS volume set")},
+ {0x88, N_("Linux plaintext")},
+ {0x8e, N_("Linux LVM")},
+ {0x93, N_("Amoeba")},
+ {0x94, N_("Amoeba BBT")}, /* (bad block table) */
+ {0x9f, N_("BSD/OS")}, /* BSDI */
+ {0xa0, N_("IBM Thinkpad hibernation")},
+ {0xa5, N_("FreeBSD")}, /* various BSD flavours */
+ {0xa6, N_("OpenBSD")},
+ {0xa7, N_("NeXTSTEP")},
+ {0xa8, N_("Darwin UFS")},
+ {0xa9, N_("NetBSD")},
+ {0xab, N_("Darwin boot")},
+ {0xaf, N_("HFS / HFS+")},
+ {0xb7, N_("BSDI fs")},
+ {0xb8, N_("BSDI swap")},
+ {0xbb, N_("Boot Wizard hidden")},
+ {0xbc, N_("Acronis FAT32 LBA")},/* hidden (+0xb0) Acronis Secure Zone (backup software) */
+ {0xbe, N_("Solaris boot")},
+ {0xbf, N_("Solaris")},
+ {0xc1, N_("DRDOS/sec (FAT-12)")},
+ {0xc4, N_("DRDOS/sec (FAT-16 < 32M)")},
+ {0xc6, N_("DRDOS/sec (FAT-16)")},
+ {0xc7, N_("Syrinx")},
+ {0xda, N_("Non-FS data")},
+ {0xdb, N_("CP/M / CTOS / ...")},/* CP/M or Concurrent CP/M or
+ Concurrent DOS or CTOS */
+ {0xde, N_("Dell Utility")}, /* Dell PowerEdge Server utilities */
+ {0xdf, N_("BootIt")}, /* BootIt EMBRM */
+ {0xe1, N_("DOS access")}, /* DOS access or SpeedStor 12-bit FAT
+ extended partition */
+ {0xe3, N_("DOS R/O")}, /* DOS R/O or SpeedStor */
+ {0xe4, N_("SpeedStor")}, /* SpeedStor 16-bit FAT extended
+ partition < 1024 cyl. */
+
+ /* Linux https://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/ */
+ {0xea, N_("Linux extended boot")},
+
+ {0xeb, N_("BeOS fs")},
+ {0xee, N_("GPT")}, /* Intel EFI GUID Partition Table */
+ {0xef, N_("EFI (FAT-12/16/32)")},/* Intel EFI System Partition */
+ {0xf0, N_("Linux/PA-RISC boot")},/* Linux/PA-RISC boot loader */
+ {0xf1, N_("SpeedStor")},
+ {0xf4, N_("SpeedStor")}, /* SpeedStor large partition */
+ {0xf2, N_("DOS secondary")}, /* DOS 3.3+ secondary */
+ {0xf8, N_("EBBR protective")}, /* Arm EBBR firmware protective partition */
+ {0xfb, N_("VMware VMFS")},
+ {0xfc, N_("VMware VMKCORE")}, /* VMware kernel dump partition */
+ {0xfd, N_("Linux raid autodetect")},/* Linux raid partition with
+ autodetect using persistent
+ superblock */
+ {0xfe, N_("LANstep")}, /* SpeedStor >1024 cyl. or LANstep */
+ {0xff, N_("BBT")}, /* Xenix Bad Block Table */
+
+ { 0, NULL }
diff --git a/include/pt-mbr.h b/include/pt-mbr.h
new file mode 100644
index 0000000..ff658f3
--- /dev/null
+++ b/include/pt-mbr.h
@@ -0,0 +1,210 @@
+#ifndef UTIL_LINUX_PT_MBR_H
+#define UTIL_LINUX_PT_MBR_H
+
+#include <assert.h>
+
+struct dos_partition {
+ unsigned char boot_ind; /* 0x80 - active */
+ unsigned char bh, bs, bc; /* begin CHS */
+ unsigned char sys_ind;
+ unsigned char eh, es, ec; /* end CHS */
+ unsigned char start_sect[4];
+ unsigned char nr_sects[4];
+} __attribute__((packed));
+
+#define MBR_PT_OFFSET 0x1be
+#define MBR_PT_BOOTBITS_SIZE 440
+
+static inline struct dos_partition *mbr_get_partition(unsigned char *mbr, int i)
+{
+ return (struct dos_partition *)
+ (mbr + MBR_PT_OFFSET + (i * sizeof(struct dos_partition)));
+}
+
+/* assemble badly aligned little endian integer */
+static inline uint32_t __dos_assemble_4le(const unsigned char *p)
+{
+ uint32_t last_byte = p[3];
+
+ return p[0] | (p[1] << 8) | (p[2] << 16) | (last_byte << 24);
+}
+
+static inline void __dos_store_4le(unsigned char *p, unsigned int val)
+{
+ assert(!(p == NULL));
+ p[0] = (val & 0xff);
+ p[1] = ((val >> 8) & 0xff);
+ p[2] = ((val >> 16) & 0xff);
+ p[3] = ((val >> 24) & 0xff);
+}
+
+static inline unsigned int dos_partition_get_start(struct dos_partition *p)
+{
+ return __dos_assemble_4le(&(p->start_sect[0]));
+}
+
+static inline void dos_partition_set_start(struct dos_partition *p, unsigned int n)
+{
+ __dos_store_4le(p->start_sect, n);
+}
+
+static inline unsigned int dos_partition_get_size(struct dos_partition *p)
+{
+ return __dos_assemble_4le(&(p->nr_sects[0]));
+}
+
+static inline void dos_partition_set_size(struct dos_partition *p, unsigned int n)
+{
+ __dos_store_4le(p->nr_sects, n);
+}
+
+static inline void dos_partition_sync_chs(struct dos_partition *p, unsigned long long int part_offset, unsigned int geom_sectors, unsigned int geom_heads)
+{
+ unsigned long long int start = part_offset + dos_partition_get_start(p);
+ unsigned long long int stop = start + dos_partition_get_size(p) - 1;
+ unsigned int spc = geom_heads * geom_sectors;
+
+ if (start / spc > 1023)
+ start = spc * 1024 - 1;
+ if (stop / spc > 1023)
+ stop = spc * 1024 - 1;
+
+ p->bc = (start / spc) & 0xff;
+ p->bh = (start / geom_sectors) % geom_heads;
+ p->bs = ((start % geom_sectors + 1) & 0x3f) |
+ (((start / spc) >> 2) & 0xc0);
+
+ p->ec = (stop / spc) & 0xff;
+ p->eh = (stop / geom_sectors) % geom_heads;
+ p->es = ((stop % geom_sectors + 1) & 0x3f) |
+ (((stop / spc) >> 2) & 0xc0);
+}
+
+static inline int mbr_is_valid_magic(const unsigned char *mbr)
+{
+ return mbr[510] == 0x55 && mbr[511] == 0xaa ? 1 : 0;
+}
+
+static inline void mbr_set_magic(unsigned char *b)
+{
+ b[510] = 0x55;
+ b[511] = 0xaa;
+}
+
+static inline unsigned int mbr_get_id(const unsigned char *mbr)
+{
+ return __dos_assemble_4le(&mbr[440]);
+}
+
+static inline void mbr_set_id(unsigned char *b, unsigned int id)
+{
+ __dos_store_4le(&b[440], id);
+}
+
+enum {
+ MBR_EMPTY_PARTITION = 0x00,
+ MBR_FAT12_PARTITION = 0x01,
+ MBR_XENIX_ROOT_PARTITION = 0x02,
+ MBR_XENIX_USR_PARTITION = 0x03,
+ MBR_FAT16_LESS32M_PARTITION = 0x04,
+ MBR_DOS_EXTENDED_PARTITION = 0x05,
+ MBR_FAT16_PARTITION = 0x06, /* DOS 16-bit >=32M */
+ MBR_HPFS_NTFS_PARTITION = 0x07, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
+ MBR_AIX_PARTITION = 0x08, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
+ MBR_AIX_BOOTABLE_PARTITION = 0x09, /* AIX data or Coherent */
+ MBR_OS2_BOOTMNGR_PARTITION = 0x0a, /* OS/2 Boot Manager */
+ MBR_W95_FAT32_PARTITION = 0x0b,
+ MBR_W95_FAT32_LBA_PARTITION = 0x0c, /* LBA really is `Extended Int 13h' */
+ MBR_W95_FAT16_LBA_PARTITION = 0x0e,
+ MBR_W95_EXTENDED_PARTITION = 0x0f,
+ MBR_OPUS_PARTITION = 0x10,
+ MBR_HIDDEN_FAT12_PARTITION = 0x11,
+ MBR_COMPAQ_DIAGNOSTICS_PARTITION = 0x12,
+ MBR_HIDDEN_FAT16_L32M_PARTITION = 0x14,
+ MBR_HIDDEN_FAT16_PARTITION = 0x16,
+ MBR_HIDDEN_HPFS_NTFS_PARTITION = 0x17,
+ MBR_AST_SMARTSLEEP_PARTITION = 0x18,
+ MBR_HIDDEN_W95_FAT32_PARTITION = 0x1b,
+ MBR_HIDDEN_W95_FAT32LBA_PARTITION = 0x1c,
+ MBR_HIDDEN_W95_FAT16LBA_PARTITION = 0x1e,
+ MBR_NEC_DOS_PARTITION = 0x24,
+ MBR_PLAN9_PARTITION = 0x39,
+ MBR_PARTITIONMAGIC_PARTITION = 0x3c,
+ MBR_VENIX80286_PARTITION = 0x40,
+ MBR_PPC_PREP_BOOT_PARTITION = 0x41,
+ MBR_SFS_PARTITION = 0x42,
+ MBR_QNX_4X_PARTITION = 0x4d,
+ MBR_QNX_4X_2ND_PARTITION = 0x4e,
+ MBR_QNX_4X_3RD_PARTITION = 0x4f,
+ MBR_DM_PARTITION = 0x50,
+ MBR_DM6_AUX1_PARTITION = 0x51, /* (or Novell) */
+ MBR_CPM_PARTITION = 0x52, /* CP/M or Microport SysV/AT */
+ MBR_DM6_AUX3_PARTITION = 0x53,
+ MBR_DM6_PARTITION = 0x54,
+ MBR_EZ_DRIVE_PARTITION = 0x55,
+ MBR_GOLDEN_BOW_PARTITION = 0x56,
+ MBR_PRIAM_EDISK_PARTITION = 0x5c,
+ MBR_SPEEDSTOR_PARTITION = 0x61,
+ MBR_GNU_HURD_PARTITION = 0x63, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
+ MBR_UNIXWARE_PARTITION = MBR_GNU_HURD_PARTITION,
+ MBR_NETWARE_286_PARTITION = 0x64,
+ MBR_NETWARE_386_PARTITION = 0x65,
+ MBR_DISKSECURE_MULTIBOOT_PARTITION = 0x70,
+ MBR_PC_IX_PARTITION = 0x75,
+ MBR_OLD_MINIX_PARTITION = 0x80, /* Minix 1.4a and earlier */
+ MBR_MINIX_PARTITION = 0x81, /* Minix 1.4b and later */
+ MBR_LINUX_SWAP_PARTITION = 0x82,
+ MBR_SOLARIS_X86_PARTITION = MBR_LINUX_SWAP_PARTITION,
+ MBR_LINUX_DATA_PARTITION = 0x83,
+ MBR_OS2_HIDDEN_DRIVE_PARTITION = 0x84, /* also hibernation MS APM, Intel Rapid Start */
+ MBR_INTEL_HIBERNATION_PARTITION = MBR_OS2_HIDDEN_DRIVE_PARTITION,
+ MBR_LINUX_EXTENDED_PARTITION = 0x85,
+ MBR_NTFS_VOL_SET1_PARTITION = 0x86,
+ MBR_NTFS_VOL_SET2_PARTITION = 0x87,
+ MBR_LINUX_PLAINTEXT_PARTITION = 0x88,
+ MBR_LINUX_LVM_PARTITION = 0x8e,
+ MBR_AMOEBA_PARTITION = 0x93,
+ MBR_AMOEBA_BBT_PARTITION = 0x94, /* (bad block table) */
+ MBR_BSD_OS_PARTITION = 0x9f, /* BSDI */
+ MBR_THINKPAD_HIBERNATION_PARTITION = 0xa0,
+ MBR_FREEBSD_PARTITION = 0xa5, /* various BSD flavours */
+ MBR_OPENBSD_PARTITION = 0xa6,
+ MBR_NEXTSTEP_PARTITION = 0xa7,
+ MBR_DARWIN_UFS_PARTITION = 0xa8,
+ MBR_NETBSD_PARTITION = 0xa9,
+ MBR_DARWIN_BOOT_PARTITION = 0xab,
+ MBR_HFS_HFS_PARTITION = 0xaf,
+ MBR_BSDI_FS_PARTITION = 0xb7,
+ MBR_BSDI_SWAP_PARTITION = 0xb8,
+ MBR_BOOTWIZARD_HIDDEN_PARTITION = 0xbb,
+ MBR_ACRONIS_FAT32LBA_PARTITION = 0xbc, /* Acronis Secure Zone with ipl for loader F11.SYS */
+ MBR_SOLARIS_BOOT_PARTITION = 0xbe,
+ MBR_SOLARIS_PARTITION = 0xbf,
+ MBR_DRDOS_FAT12_PARTITION = 0xc1,
+ MBR_DRDOS_FAT16_L32M_PARTITION = 0xc4,
+ MBR_DRDOS_FAT16_PARTITION = 0xc6,
+ MBR_SYRINX_PARTITION = 0xc7,
+ MBR_NONFS_DATA_PARTITION = 0xda,
+ MBR_CPM_CTOS_PARTITION = 0xdb, /* CP/M or Concurrent CP/M or Concurrent DOS or CTOS */
+ MBR_DELL_UTILITY_PARTITION = 0xde, /* Dell PowerEdge Server utilities */
+ MBR_BOOTIT_PARTITION = 0xdf, /* BootIt EMBRM */
+ MBR_DOS_ACCESS_PARTITION = 0xe1, /* DOS access or SpeedStor 12-bit FAT extended partition */
+ MBR_DOS_RO_PARTITION = 0xe3, /* DOS R/O or SpeedStor */
+ MBR_SPEEDSTOR_EXTENDED_PARTITION = 0xe4, /* SpeedStor 16-bit FAT extended partition < 1024 cyl. */
+ MBR_RUFUS_EXTRA_PARTITION = 0xea, /* Rufus extra partition for alignment */
+ MBR_BEOS_FS_PARTITION = 0xeb,
+ MBR_GPT_PARTITION = 0xee, /* Intel EFI GUID Partition Table */
+ MBR_EFI_SYSTEM_PARTITION = 0xef, /* Intel EFI System Partition */
+ MBR_LINUX_PARISC_BOOT_PARTITION = 0xf0, /* Linux/PA-RISC boot loader */
+ MBR_SPEEDSTOR1_PARTITION = 0xf1,
+ MBR_SPEEDSTOR2_PARTITION = 0xf4, /* SpeedStor large partition */
+ MBR_DOS_SECONDARY_PARTITION = 0xf2, /* DOS 3.3+ secondary */
+ MBR_EBBR_PROTECTIVE_PARTITION = 0xf8, /* Arm EBBR firmware protective partition */
+ MBR_VMWARE_VMFS_PARTITION = 0xfb,
+ MBR_VMWARE_VMKCORE_PARTITION = 0xfc, /* VMware kernel dump partition */
+ MBR_LINUX_RAID_PARTITION = 0xfd, /* Linux raid partition with autodetect using persistent superblock */
+ MBR_LANSTEP_PARTITION = 0xfe, /* SpeedStor >1024 cyl. or LANstep */
+ MBR_XENIX_BBT_PARTITION = 0xff, /* Xenix Bad Block Table */
+};
+
+#endif /* UTIL_LINUX_PT_MBR_H */
diff --git a/include/pt-sgi.h b/include/pt-sgi.h
new file mode 100644
index 0000000..6d512ee
--- /dev/null
+++ b/include/pt-sgi.h
@@ -0,0 +1,115 @@
+#ifndef UTIL_LINUX_PT_SGI_H
+#define UTIL_LINUX_PT_SGI_H
+
+#include <stdint.h>
+
+#define SGI_LABEL_MAGIC 0x0be5a941
+
+#define SGI_MAXPARTITIONS 16
+#define SGI_MAXVOLUMES 15
+
+/* partition types */
+enum {
+ SGI_TYPE_VOLHDR = 0x00,
+ SGI_TYPE_TRKREPL = 0x01,
+ SGI_TYPE_SECREPL = 0x02,
+ SGI_TYPE_SWAP = 0x03,
+ SGI_TYPE_BSD = 0x04,
+ SGI_TYPE_SYSV = 0x05,
+ SGI_TYPE_ENTIRE_DISK = 0x06,
+ SGI_TYPE_EFS = 0x07,
+ SGI_TYPE_LVOL = 0x08,
+ SGI_TYPE_RLVOL = 0x09,
+ SGI_TYPE_XFS = 0x0a,
+ SGI_TYPE_XFSLOG = 0x0b,
+ SGI_TYPE_XLV = 0x0c,
+ SGI_TYPE_XVM = 0x0d
+};
+
+struct sgi_device_parameter {
+ unsigned char skew;
+ unsigned char gap1;
+ unsigned char gap2;
+ unsigned char sparecyl;
+
+ uint16_t pcylcount;
+ uint16_t head_vol0;
+ uint16_t ntrks; /* tracks in cyl 0 or vol 0 */
+
+ unsigned char cmd_tag_queue_depth;
+ unsigned char unused0;
+
+ uint16_t unused1;
+ uint16_t nsect; /* sectors/tracks in cyl 0 or vol 0 */
+ uint16_t bytes;
+ uint16_t ilfact;
+ uint32_t flags; /* SGI_DEVPARAM_* controller flags */
+ uint32_t datarate;
+ uint32_t retries_on_error;
+ uint32_t ms_per_word;
+ uint16_t xylogics_gap1;
+ uint16_t xylogics_syncdelay;
+ uint16_t xylogics_readdelay;
+ uint16_t xylogics_gap2;
+ uint16_t xylogics_readgate;
+ uint16_t xylogics_writecont;
+} __attribute__((packed));
+
+enum {
+ SGI_DEVPARAM_SECTOR_SLIP = 0x01,
+ SGI_DEVPARAM_SECTOR_FWD = 0x02,
+ SGI_DEVPARAM_TRACK_FWD = 0x04,
+ SGI_DEVPARAM_TRACK_MULTIVOL = 0x08,
+ SGI_DEVPARAM_IGNORE_ERRORS = 0x10,
+ SGI_DEVPARAM_RESEEK = 0x20,
+ SGI_DEVPARAM_CMDTAGQ_ENABLE = 0x40
+};
+
+
+struct sgi_disklabel {
+ uint32_t magic; /* magic number */
+ uint16_t root_part_num; /* # root partition */
+ uint16_t swap_part_num; /* # swap partition */
+ unsigned char boot_file[16]; /* name of boot file */
+
+ struct sgi_device_parameter devparam; /* not used now */
+
+ struct sgi_volume {
+ unsigned char name[8]; /* name of volume */
+ uint32_t block_num; /* logical block number */
+ uint32_t num_bytes; /* how big, in bytes */
+ } __attribute__((packed)) volume[SGI_MAXVOLUMES];
+
+ struct sgi_partition {
+ uint32_t num_blocks; /* size in logical blocks */
+ uint32_t first_block; /* first logical block */
+ uint32_t type; /* type of this partition */
+ } __attribute__((packed)) partitions[SGI_MAXPARTITIONS];
+
+ /* checksum is the 32bit 2's complement sum of the disklabel */
+ uint32_t csum; /* disk label checksum */
+ uint32_t padding; /* padding */
+} __attribute__((packed));
+
+static inline uint32_t sgi_pt_checksum(struct sgi_disklabel *label)
+{
+ int count;
+ uint32_t sum = 0;
+ unsigned char *ptr = (unsigned char *) label;
+
+ count = sizeof(*label) / sizeof(uint32_t);
+ ptr += sizeof(uint32_t) * (count - 1);
+
+ while (count--) {
+ uint32_t val;
+
+ memcpy(&val, ptr, sizeof(uint32_t));
+ sum -= be32_to_cpu(val);
+
+ ptr -= sizeof(uint32_t);
+ }
+
+ return sum;
+}
+
+#endif /* UTIL_LINUX_PT_SGI_H */
diff --git a/include/pt-sun.h b/include/pt-sun.h
new file mode 100644
index 0000000..8bb5d95
--- /dev/null
+++ b/include/pt-sun.h
@@ -0,0 +1,90 @@
+#ifndef UTIL_LINUX_PT_SUN_H
+#define UTIL_LINUX_PT_SUN_H
+
+#include <stdint.h>
+
+#define SUN_LABEL_MAGIC 0xDABE
+
+/* Supported VTOC setting */
+#define SUN_VTOC_SANITY 0x600DDEEE /* magic number */
+#define SUN_VTOC_VERSION 1
+#define SUN_MAXPARTITIONS 8
+
+struct sun_disklabel {
+ unsigned char label_id[128]; /* Informative text string */
+
+ struct sun_vtoc {
+ uint32_t version; /* version */
+ char volume_id[8];/* volume name */
+ uint16_t nparts; /* num of partitions */
+
+ struct sun_info { /* partition information */
+ uint16_t id; /* SUN_TAG_* */
+ uint16_t flags; /* SUN_FLAG_* */
+ } __attribute__ ((packed)) infos[8];
+
+ uint16_t padding; /* padding */
+ uint32_t bootinfo[3]; /* info needed by mboot */
+ uint32_t sanity; /* magic number */
+ uint32_t reserved[10]; /* padding */
+ uint32_t timestamp[8]; /* partition timestamp */
+ } __attribute__ ((packed)) vtoc;
+
+ uint32_t write_reinstruct; /* sectors to skip, writes */
+ uint32_t read_reinstruct; /* sectors to skip, reads */
+ unsigned char spare[148]; /* padding */
+ uint16_t rpm; /* disk rotational speed */
+ uint16_t pcyl; /* physical cylinder count */
+ uint16_t apc; /* extra sects per cylinder */
+ uint16_t obs1;
+ uint16_t obs2;
+ uint16_t intrlv; /* interleave factor */
+ uint16_t ncyl; /* data cylinder count */
+ uint16_t acyl; /* alt. cylinder count */
+ uint16_t nhead; /* tracks per cylinder <---- */
+ uint16_t nsect; /* sectors per track <---- */
+ uint16_t obs3;
+ uint16_t obs4;
+
+ struct sun_partition { /* partitions */
+ uint32_t start_cylinder;
+ uint32_t num_sectors;
+ } __attribute__ ((packed)) partitions[8];
+
+ uint16_t magic; /* magic number */
+ uint16_t csum; /* label xor'd checksum */
+} __attribute__ ((packed));
+
+
+#define SUN_TAG_UNASSIGNED 0x00 /* Unassigned partition */
+#define SUN_TAG_BOOT 0x01 /* Boot partition */
+#define SUN_TAG_ROOT 0x02 /* Root filesystem */
+#define SUN_TAG_SWAP 0x03 /* Swap partition */
+#define SUN_TAG_USR 0x04 /* /usr filesystem */
+#define SUN_TAG_WHOLEDISK 0x05 /* Full-disk slice */
+#define SUN_TAG_STAND 0x06 /* Stand partition */
+#define SUN_TAG_VAR 0x07 /* /var filesystem */
+#define SUN_TAG_HOME 0x08 /* /home filesystem */
+#define SUN_TAG_ALTSCTR 0x09 /* Alt sector partition */
+#define SUN_TAG_CACHE 0x0a /* Cachefs partition */
+#define SUN_TAG_RESERVED 0x0b /* SMI reserved data */
+#define SUN_TAG_LINUX_SWAP 0x82 /* Linux SWAP */
+#define SUN_TAG_LINUX_NATIVE 0x83 /* Linux filesystem */
+#define SUN_TAG_LINUX_LVM 0x8e /* Linux LVM */
+#define SUN_TAG_LINUX_RAID 0xfd /* LInux RAID */
+
+#define SUN_FLAG_UNMNT 0x01 /* Unmountable partition*/
+#define SUN_FLAG_RONLY 0x10 /* Read only */
+
+static inline uint16_t sun_pt_checksum(const struct sun_disklabel *label)
+{
+ const uint16_t *ptr = ((const uint16_t *) (label + 1)) - 1;
+ uint16_t sum;
+
+ for (sum = 0; ptr >= ((const uint16_t *) label);)
+ sum ^= *ptr--;
+
+ return sum;
+}
+
+#endif /* UTIL_LINUX_PT_SUN_H */
diff --git a/include/pty-session.h b/include/pty-session.h
new file mode 100644
index 0000000..09eff43
--- /dev/null
+++ b/include/pty-session.h
@@ -0,0 +1,112 @@
+/*
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Written by Karel Zak <kzak@redhat.com> in Jul 2019
+ */
+#ifndef UTIL_LINUX_PTY_SESSION_H
+#define UTIL_LINUX_PTY_SESSION_H
+
+#include <pty.h>
+#include <termios.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#include <sys/signalfd.h>
+
+/*
+ * Callbacks -- the first argument is always callback data, see
+ * ul_pty_set_callback_data().
+ */
+struct ul_pty_callbacks {
+ /*
+ * Optional. Executed on SIGCHLD when ssi_code is EXITED, KILLED or
+ * DUMPED; The callback has to call ul_pty_set_child(pty, (pid_t) -1)
+ * if child is no more alive.
+ */
+ void (*child_wait)(void *, pid_t);
+
+ /*
+ * Used when child_wait() undefined to informa about child status
+ */
+ void (*child_die)(void *, pid_t, int);
+
+ /*
+ * Executed on SIGCHLD when ssi_status is SIGSTOP
+ */
+ void (*child_sigstop)(void *, pid_t);
+
+ /*
+ * Executed in master loop before ul_pty enter poll() and in time set by
+ * ul_pty_set_mainloop_time(). The callback is no used when time is not set.
+ */
+ int (*mainloop)(void *);
+
+ /*
+ * Executed on master or stdin activity, arguments:
+ * 2nd - file descriptor
+ * 3rd - buffer with data
+ * 4th - size of the data
+ */
+ int (*log_stream_activity)(void *, int, char *, size_t);
+
+ /*
+ * Executed on signal, arguments:
+ * 2nd - signal info
+ * 3rd - NULL or signal specific data (e.g. struct winsize on SIGWINCH
+ */
+ int (*log_signal)(void *, struct signalfd_siginfo *, void *);
+
+ /*
+ * Executed on SIGUSR1
+ */
+ int (*flush_logs)(void *);
+};
+
+struct ul_pty {
+ struct termios stdin_attrs; /* stdin and slave terminal runtime attributes */
+ int master; /* parent side */
+ int slave; /* child side */
+ int sigfd; /* signalfd() */
+ int poll_timeout;
+ struct winsize win; /* terminal window size */
+ sigset_t orgsig; /* original signal mask */
+
+ int delivered_signal;
+
+ struct ul_pty_callbacks callbacks;
+ void *callback_data;
+
+ pid_t child;
+
+ struct timeval next_callback_time;
+
+ unsigned int isterm:1, /* is stdin terminal? */
+ slave_echo:1; /* keep ECHO on pty slave */
+};
+
+void ul_pty_init_debug(int mask);
+struct ul_pty *ul_new_pty(int is_stdin_tty);
+void ul_free_pty(struct ul_pty *pty);
+
+void ul_pty_slave_echo(struct ul_pty *pty, int enable);
+int ul_pty_get_delivered_signal(struct ul_pty *pty);
+
+void ul_pty_set_callback_data(struct ul_pty *pty, void *data);
+void ul_pty_set_child(struct ul_pty *pty, pid_t child);
+
+struct ul_pty_callbacks *ul_pty_get_callbacks(struct ul_pty *pty);
+int ul_pty_is_running(struct ul_pty *pty);
+int ul_pty_setup(struct ul_pty *pty);
+void ul_pty_cleanup(struct ul_pty *pty);
+int ul_pty_chownmod_slave(struct ul_pty *pty, uid_t uid, gid_t gid, mode_t mode);
+void ul_pty_init_slave(struct ul_pty *pty);
+int ul_pty_proxy_master(struct ul_pty *pty);
+
+void ul_pty_set_mainloop_time(struct ul_pty *pty, struct timeval *tv);
+int ul_pty_get_childfd(struct ul_pty *pty);
+void ul_pty_wait_for_child(struct ul_pty *pty);
+pid_t ul_pty_get_child(struct ul_pty *pty);
+void ul_pty_write_eof_to_child(struct ul_pty *pty);
+
+#endif /* UTIL_LINUX_PTY_H */
diff --git a/include/pwdutils.h b/include/pwdutils.h
new file mode 100644
index 0000000..b58268d
--- /dev/null
+++ b/include/pwdutils.h
@@ -0,0 +1,14 @@
+#ifndef UTIL_LINUX_PWDUTILS_H
+#define UTIL_LINUX_PWDUTILS_H
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+
+extern struct passwd *xgetpwnam(const char *username, char **pwdbuf);
+extern struct group *xgetgrnam(const char *groupname, char **grpbuf);
+extern struct passwd *xgetpwuid(uid_t uid, char **pwdbuf);
+extern char *xgetlogin(void);
+
+#endif /* UTIL_LINUX_PWDUTILS_H */
+
diff --git a/include/randutils.h b/include/randutils.h
new file mode 100644
index 0000000..690bf5e
--- /dev/null
+++ b/include/randutils.h
@@ -0,0 +1,17 @@
+#ifndef UTIL_LINUX_RANDUTILS
+#define UTIL_LINUX_RANDUTILS
+
+#ifdef HAVE_SRANDOM
+#define srand(x) srandom(x)
+#define rand() random()
+#endif
+
+/* rand() based */
+extern int rand_get_number(int low_n, int high_n);
+
+/* /dev/urandom based with fallback to rand() */
+extern int random_get_fd(void);
+extern int ul_random_get_bytes(void *buf, size_t nbytes);
+extern const char *random_tell_source(void);
+
+#endif
diff --git a/include/rpmatch.h b/include/rpmatch.h
new file mode 100644
index 0000000..f64d52e
--- /dev/null
+++ b/include/rpmatch.h
@@ -0,0 +1,13 @@
+#ifndef UTIL_LINUX_RPMATCH_H
+#define UTIL_LINUX_RPMATCH_H
+
+#ifndef HAVE_RPMATCH
+#define rpmatch(r) \
+ (*r == 'y' || *r == 'Y' ? 1 : *r == 'n' || *r == 'N' ? 0 : -1)
+#endif
+
+#define RPMATCH_YES 1
+#define RPMATCH_NO 0
+#define RPMATCH_INVALID -1
+
+#endif /* UTIL_LINUX_RPMATCH_H */
diff --git a/include/selinux-utils.h b/include/selinux-utils.h
new file mode 100644
index 0000000..82c27c8
--- /dev/null
+++ b/include/selinux-utils.h
@@ -0,0 +1,8 @@
+#ifndef UTIL_LINUX_SELINUX_UTILS_H
+#define UTIL_LINUX_SELINUX_UTILS_H
+
+extern int ul_setfscreatecon_from_file(char *orig_file);
+extern int ul_selinux_has_access(const char *classstr, const char *perm, char **user_cxt);
+extern int ul_selinux_get_default_context(const char *path, int st_mode, char **cxt);
+
+#endif
diff --git a/include/sha1.h b/include/sha1.h
new file mode 100644
index 0000000..62af1da
--- /dev/null
+++ b/include/sha1.h
@@ -0,0 +1,27 @@
+#ifndef UTIL_LINUX_SHA1_H
+#define UTIL_LINUX_SHA1_H
+
+/*
+ SHA-1 in C
+ By Steve Reid <steve@edmweb.com>
+ 100% Public Domain
+ */
+
+#include "stdint.h"
+
+#define UL_SHA1LENGTH 20
+
+typedef struct
+{
+ uint32_t state[5];
+ uint32_t count[2];
+ unsigned char buffer[64];
+} UL_SHA1_CTX;
+
+void ul_SHA1Transform(uint32_t state[5], const unsigned char buffer[64]);
+void ul_SHA1Init(UL_SHA1_CTX *context);
+void ul_SHA1Update(UL_SHA1_CTX *context, const unsigned char *data, uint32_t len);
+void ul_SHA1Final(unsigned char digest[UL_SHA1LENGTH], UL_SHA1_CTX *context);
+void ul_SHA1(char *hash_out, const char *str, unsigned len);
+
+#endif /* UTIL_LINUX_SHA1_H */
diff --git a/include/signames.h b/include/signames.h
new file mode 100644
index 0000000..a4fd1bc
--- /dev/null
+++ b/include/signames.h
@@ -0,0 +1,8 @@
+#ifndef SIGNAMES_H
+#define SIGNAMES_H
+
+int signame_to_signum(const char *sig);
+const char *signum_to_signame(int signum);
+int get_signame_by_idx(size_t idx, const char **signame, int *signum);
+
+#endif /* SIGNAMES_H */
diff --git a/include/statfs_magic.h b/include/statfs_magic.h
new file mode 100644
index 0000000..b6b0225
--- /dev/null
+++ b/include/statfs_magic.h
@@ -0,0 +1,100 @@
+#ifndef UTIL_LINUX_STATFS_MAGIC_H
+#define UTIL_LINUX_STATFS_MAGIC_H
+
+#include <sys/statfs.h>
+
+/*
+ * If possible then don't depend on internal libc __SWORD_TYPE type.
+ */
+#ifdef __GNUC__
+#define F_TYPE_EQUAL(a, b) (a == (__typeof__(a)) b)
+#else
+#define F_TYPE_EQUAL(a, b) (a == (__SWORD_TYPE) b)
+#endif
+
+/*
+ * Unfortunately, Linux kernel header file <linux/magic.h> is incomplete
+ * mess and kernel returns by statfs f_type many numbers that are nowhere
+ * specified (in API).
+ *
+ * This is collection of the magic numbers.
+ */
+#define STATFS_ADFS_MAGIC 0xadf5
+#define STATFS_AFFS_MAGIC 0xadff
+#define STATFS_AFS_MAGIC 0x5346414F
+#define STATFS_AUTOFS_MAGIC 0x0187
+#define STATFS_BDEVFS_MAGIC 0x62646576
+#define STATFS_BEFS_MAGIC 0x42465331
+#define STATFS_BFS_MAGIC 0x1BADFACE
+#define STATFS_BINFMTFS_MAGIC 0x42494e4d
+#define STATFS_BTRFS_MAGIC 0x9123683E
+#define STATFS_CEPH_MAGIC 0x00c36400
+#define STATFS_CGROUP_MAGIC 0x27e0eb
+#define STATFS_CGROUP2_MAGIC 0x63677270
+#define STATFS_CIFS_MAGIC 0xff534d42
+#define STATFS_CODA_MAGIC 0x73757245
+#define STATFS_CONFIGFS_MAGIC 0x62656570
+#define STATFS_CRAMFS_MAGIC 0x28cd3d45
+#define STATFS_DEBUGFS_MAGIC 0x64626720
+#define STATFS_DEVPTS_MAGIC 0x1cd1
+#define STATFS_ECRYPTFS_MAGIC 0xf15f
+#define STATFS_EFIVARFS_MAGIC 0xde5e81e4
+#define STATFS_EFS_MAGIC 0x414A53
+#define STATFS_EXOFS_MAGIC 0x5DF5
+#define STATFS_EXT2_MAGIC 0xEF53
+#define STATFS_EXT3_MAGIC 0xEF53
+#define STATFS_EXT4_MAGIC 0xEF53
+#define STATFS_F2FS_MAGIC 0xF2F52010
+#define STATFS_FUSE_MAGIC 0x65735546
+#define STATFS_FUTEXFS_MAGIC 0xBAD1DEA
+#define STATFS_GFS2_MAGIC 0x01161970
+#define STATFS_HFSPLUS_MAGIC 0x482b
+#define STATFS_HOSTFS_MAGIC 0x00c0ffee
+#define STATFS_HPFS_MAGIC 0xf995e849
+#define STATFS_HPPFS_MAGIC 0xb00000ee
+#define STATFS_HUGETLBFS_MAGIC 0x958458f6
+#define STATFS_ISOFS_MAGIC 0x9660
+#define STATFS_JFFS2_MAGIC 0x72b6
+#define STATFS_JFS_MAGIC 0x3153464a
+#define STATFS_LOGFS_MAGIC 0xc97e8168
+#define STATFS_MINIX2_MAGIC 0x2468
+#define STATFS_MINIX2_MAGIC2 0x2478
+#define STATFS_MINIX3_MAGIC 0x4d5a
+#define STATFS_MINIX_MAGIC 0x137F
+#define STATFS_MINIX_MAGIC2 0x138F
+#define STATFS_MQUEUE_MAGIC 0x19800202
+#define STATFS_MSDOS_MAGIC 0x4d44
+#define STATFS_NCP_MAGIC 0x564c
+#define STATFS_NFS_MAGIC 0x6969
+#define STATFS_NILFS_MAGIC 0x3434
+#define STATFS_NTFS_MAGIC 0x5346544e
+#define STATFS_OCFS2_MAGIC 0x7461636f
+#define STATFS_OMFS_MAGIC 0xC2993D87
+#define STATFS_OPENPROMFS_MAGIC 0x9fa1
+#define STATFS_PIPEFS_MAGIC 0x50495045
+#define STATFS_PROC_MAGIC 0x9fa0
+#define STATFS_PSTOREFS_MAGIC 0x6165676C
+#define STATFS_QNX4_MAGIC 0x002f
+#define STATFS_QNX6_MAGIC 0x68191122
+#define STATFS_RAMFS_MAGIC 0x858458f6
+#define STATFS_REISERFS_MAGIC 0x52654973
+#define STATFS_ROMFS_MAGIC 0x7275
+#define STATFS_SECURITYFS_MAGIC 0x73636673
+#define STATFS_SELINUXFS_MAGIC 0xf97cff8c
+#define STATFS_SMACKFS_MAGIC 0x43415d53
+#define STATFS_SMB_MAGIC 0x517B
+#define STATFS_SOCKFS_MAGIC 0x534F434B
+#define STATFS_SQUASHFS_MAGIC 0x73717368
+#define STATFS_SYSFS_MAGIC 0x62656572
+#define STATFS_TMPFS_MAGIC 0x01021994
+#define STATFS_UBIFS_MAGIC 0x24051905
+#define STATFS_UDF_MAGIC 0x15013346
+#define STATFS_UFS2_MAGIC 0x19540119
+#define STATFS_UFS_MAGIC 0x00011954
+#define STATFS_V9FS_MAGIC 0x01021997
+#define STATFS_VXFS_MAGIC 0xa501FCF5
+#define STATFS_XENFS_MAGIC 0xabba1974
+#define STATFS_XFS_MAGIC 0x58465342
+
+#endif /* UTIL_LINUX_STATFS_MAGIC_H */
+
diff --git a/include/strutils.h b/include/strutils.h
new file mode 100644
index 0000000..ea10272
--- /dev/null
+++ b/include/strutils.h
@@ -0,0 +1,397 @@
+#ifndef UTIL_LINUX_STRUTILS
+#define UTIL_LINUX_STRUTILS
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <string.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+#include <time.h>
+
+#include "c.h"
+
+/* initialize a custom exit code for all *_or_err functions */
+extern void strutils_set_exitcode(int exit_code);
+
+extern int parse_size(const char *str, uintmax_t *res, int *power);
+extern int strtosize(const char *str, uintmax_t *res);
+extern uintmax_t strtosize_or_err(const char *str, const char *errmesg);
+
+extern int ul_strtos64(const char *str, int64_t *num, int base);
+extern int ul_strtou64(const char *str, uint64_t *num, int base);
+extern int ul_strtos32(const char *str, int32_t *num, int base);
+extern int ul_strtou32(const char *str, uint32_t *num, int base);
+
+extern int64_t str2num_or_err(const char *str, int base, const char *errmesg, int64_t low, int64_t up);
+extern uint64_t str2unum_or_err(const char *str, int base, const char *errmesg, uint64_t up);
+
+#define strtos64_or_err(_s, _e) str2num_or_err(_s, 10, _e, 0, 0)
+#define strtou64_or_err(_s, _e) str2unum_or_err(_s, 10, _e, 0)
+#define strtox64_or_err(_s, _e) str2unum_or_err(_s, 16, _e, 0)
+
+#define strtos32_or_err(_s, _e) (int32_t) str2num_or_err(_s, 10, _e, INT32_MIN, INT32_MAX)
+#define strtou32_or_err(_s, _e) (uint32_t) str2unum_or_err(_s, 10, _e, UINT32_MAX)
+#define strtox32_or_err(_s, _e) (uint32_t) str2unum_or_err(_s, 16, _e, UINT32_MAX)
+
+#define strtos16_or_err(_s, _e) (int16_t) str2num_or_err(_s, 10, _e, INT16_MIN, INT16_MAX)
+#define strtou16_or_err(_s, _e) (uint16_t) str2unum_or_err(_s, 10, _e, UINT16_MAX)
+#define strtox16_or_err(_s, _e) (uint16_t) str2unum_or_err(_s, 16, _e, UINT16_MAX)
+
+extern double strtod_or_err(const char *str, const char *errmesg);
+extern long double strtold_or_err(const char *str, const char *errmesg);
+
+extern long strtol_or_err(const char *str, const char *errmesg);
+extern unsigned long strtoul_or_err(const char *str, const char *errmesg);
+
+extern void strtotimeval_or_err(const char *str, struct timeval *tv,
+ const char *errmesg);
+extern time_t strtotime_or_err(const char *str, const char *errmesg);
+
+extern int isdigit_strend(const char *str, const char **end);
+#define isdigit_string(_s) isdigit_strend(_s, NULL)
+
+extern int isxdigit_strend(const char *str, const char **end);
+#define isxdigit_string(_s) isxdigit_strend(_s, NULL)
+
+
+extern int parse_switch(const char *arg, const char *errmesg, ...);
+
+#ifndef HAVE_MEMPCPY
+extern void *mempcpy(void *restrict dest, const void *restrict src, size_t n);
+#endif
+#ifndef HAVE_STRNLEN
+extern size_t strnlen(const char *s, size_t maxlen);
+#endif
+#ifndef HAVE_STRNDUP
+extern char *strndup(const char *s, size_t n);
+#endif
+#ifndef HAVE_STRNCHR
+extern char *strnchr(const char *s, size_t maxlen, int c);
+#endif
+
+/* caller guarantees n > 0 */
+static inline void xstrncpy(char *dest, const char *src, size_t n)
+{
+ size_t len = src ? strlen(src) : 0;
+
+ if (!len)
+ return;
+ len = min(len, n - 1);
+ memcpy(dest, src, len);
+ dest[len] = 0;
+}
+
+/* This is like strncpy(), but based on memcpy(), so compilers and static
+ * analyzers do not complain when sizeof(destination) is the same as 'n' and
+ * result is not terminated by zero.
+ *
+ * Use this function to copy string to logs with fixed sizes (wtmp/utmp. ...)
+ * where string terminator is optional.
+ */
+static inline void * __attribute__((nonnull (1)))
+str2memcpy(void *dest, const char *src, size_t n)
+{
+ size_t bytes = strlen(src) + 1;
+
+ if (bytes > n)
+ bytes = n;
+
+ memcpy(dest, src, bytes);
+ return dest;
+}
+
+static inline char * __attribute__((nonnull (1)))
+mem2strcpy(char *dest, const void *src, size_t n, size_t nmax)
+{
+ if (n + 1 > nmax)
+ n = nmax - 1;
+
+ memset(dest, '\0', nmax);
+ memcpy(dest, src, n);
+ return dest;
+}
+
+/* Reallocate @str according to @newstr and copy @newstr to @str; returns new @str.
+ * The @str is not modified if reallocation failed (like classic realloc()).
+ */
+static inline char * __attribute__((warn_unused_result))
+strrealloc(char *str, const char *newstr)
+{
+ size_t nsz, osz;
+
+ if (!str)
+ return newstr ? strdup(newstr) : NULL;
+ if (!newstr)
+ return NULL;
+
+ osz = strlen(str);
+ nsz = strlen(newstr);
+
+ if (nsz > osz)
+ str = realloc(str, nsz + 1);
+ if (str)
+ memcpy(str, newstr, nsz + 1);
+ return str;
+}
+
+/* Copy string @str to struct @stru to member addressed by @offset */
+static inline int strdup_to_offset(void *stru, size_t offset, const char *str)
+{
+ char **o;
+ char *p = NULL;
+
+ if (!stru)
+ return -EINVAL;
+
+ o = (char **) ((char *) stru + offset);
+ if (str) {
+ p = strdup(str);
+ if (!p)
+ return -ENOMEM;
+ }
+
+ free(*o);
+ *o = p;
+ return 0;
+}
+
+/* Copy string __str to struct member _m of the struct _s */
+#define strdup_to_struct_member(_s, _m, _str) \
+ strdup_to_offset((void *) _s, offsetof(__typeof__(*(_s)), _m), _str)
+
+/* Copy string addressed by @offset between two structs */
+static inline int strdup_between_offsets(void *stru_dst, void *stru_src, size_t offset)
+{
+ char **src;
+ char **dst;
+ char *p = NULL;
+
+ if (!stru_src || !stru_dst)
+ return -EINVAL;
+
+ src = (char **) ((char *) stru_src + offset);
+ dst = (char **) ((char *) stru_dst + offset);
+
+ if (*src) {
+ p = strdup(*src);
+ if (!p)
+ return -ENOMEM;
+ }
+
+ free(*dst);
+ *dst = p;
+ return 0;
+}
+
+/* Copy string addressed by struct member between two instances of the same
+ * struct type */
+#define strdup_between_structs(_dst, _src, _m) \
+ strdup_between_offsets((void *)_dst, (void *)_src, offsetof(__typeof__(*(_src)), _m))
+
+
+extern char *xstrmode(mode_t mode, char *str);
+
+/* Options for size_to_human_string() */
+enum
+{
+ SIZE_SUFFIX_1LETTER = 0,
+ SIZE_SUFFIX_3LETTER = (1 << 0),
+ SIZE_SUFFIX_SPACE = (1 << 1),
+ SIZE_DECIMAL_2DIGITS = (1 << 2)
+};
+
+extern char *size_to_human_string(int options, uint64_t bytes);
+
+extern int string_to_idarray(const char *list, int ary[], size_t arysz,
+ int (name2id)(const char *, size_t));
+extern int string_add_to_idarray(const char *list, int ary[],
+ size_t arysz, size_t *ary_pos,
+ int (name2id)(const char *, size_t));
+
+extern int string_to_bitarray(const char *list, char *ary,
+ int (*name2bit)(const char *, size_t));
+
+extern int string_to_bitmask(const char *list,
+ unsigned long *mask,
+ long (*name2flag)(const char *, size_t));
+extern int parse_range(const char *str, int *lower, int *upper, int def);
+
+extern int streq_paths(const char *a, const char *b);
+
+/*
+ * Match string beginning.
+ */
+static inline const char *startswith(const char *s, const char *prefix)
+{
+ size_t sz = prefix ? strlen(prefix) : 0;
+
+ if (s && sz && strncmp(s, prefix, sz) == 0)
+ return s + sz;
+ return NULL;
+}
+
+/*
+ * Case insensitive match string beginning.
+ */
+static inline const char *startswith_no_case(const char *s, const char *prefix)
+{
+ size_t sz = prefix ? strlen(prefix) : 0;
+
+ if (s && sz && strncasecmp(s, prefix, sz) == 0)
+ return s + sz;
+ return NULL;
+}
+
+/*
+ * Match string ending.
+ */
+static inline const char *endswith(const char *s, const char *postfix)
+{
+ size_t sl = s ? strlen(s) : 0;
+ size_t pl = postfix ? strlen(postfix) : 0;
+
+ if (pl == 0)
+ return s + sl;
+ if (sl < pl)
+ return NULL;
+ if (memcmp(s + sl - pl, postfix, pl) != 0)
+ return NULL;
+ return s + sl - pl;
+}
+
+/*
+ * Skip leading white space.
+ */
+static inline const char *skip_space(const char *p)
+{
+ while (isspace(*p))
+ ++p;
+ return p;
+}
+
+static inline const char *skip_blank(const char *p)
+{
+ while (isblank(*p))
+ ++p;
+ return p;
+}
+
+
+/* Removes whitespace from the right-hand side of a string (trailing
+ * whitespace).
+ *
+ * Returns size of the new string (without \0).
+ */
+static inline size_t rtrim_whitespace(unsigned char *str)
+{
+ size_t i;
+
+ if (!str)
+ return 0;
+ i = strlen((char *) str);
+ while (i) {
+ i--;
+ if (!isspace(str[i])) {
+ i++;
+ break;
+ }
+ }
+ str[i] = '\0';
+ return i;
+}
+
+/* Removes whitespace from the left-hand side of a string.
+ *
+ * Returns size of the new string (without \0).
+ */
+static inline size_t ltrim_whitespace(unsigned char *str)
+{
+ size_t len;
+ unsigned char *p;
+
+ if (!str)
+ return 0;
+ for (p = str; *p && isspace(*p); p++);
+
+ len = strlen((char *) p);
+
+ if (p > str)
+ memmove(str, p, len + 1);
+
+ return len;
+}
+
+/* Removes left-hand, right-hand and repeating whitespaces.
+ */
+static inline size_t __normalize_whitespace(
+ const unsigned char *src,
+ size_t sz,
+ unsigned char *dst,
+ size_t len)
+{
+ size_t i, x = 0;
+ int nsp = 0, intext = 0;
+
+ if (!sz)
+ goto done;
+
+ for (i = 0, x = 0; i < sz && x < len - 1; ) {
+ if (isspace(src[i]))
+ nsp++;
+ else
+ nsp = 0, intext = 1;
+
+ if (nsp > 1 || (nsp && !intext))
+ i++;
+ else
+ dst[x++] = src[i++];
+ }
+ if (nsp && x > 0) /* tailing space */
+ x--;
+done:
+ dst[x] = '\0';
+ return x;
+}
+
+static inline size_t normalize_whitespace(unsigned char *str)
+{
+ size_t sz = strlen((char *) str);
+ return __normalize_whitespace(str, sz, str, sz + 1);
+}
+
+static inline void strrep(char *s, int find, int replace)
+{
+ while (s && *s && (s = strchr(s, find)) != NULL)
+ *s++ = replace;
+}
+
+static inline void strrem(char *s, int rem)
+{
+ char *p;
+
+ if (!s)
+ return;
+ for (p = s; *s; s++) {
+ if (*s != rem)
+ *p++ = *s;
+ }
+ *p = '\0';
+}
+
+extern char *strnconcat(const char *s, const char *suffix, size_t b);
+extern char *strconcat(const char *s, const char *suffix);
+extern char *strfconcat(const char *s, const char *format, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+
+extern int strappend(char **a, const char *b);
+
+extern const char *split(const char **state, size_t *l, const char *separator, int quoted);
+
+extern char *ul_strchr_escaped(const char *s, int c);
+
+extern int skip_fline(FILE *fp);
+extern int ul_stralnumcmp(const char *p1, const char *p2);
+
+#endif
diff --git a/include/strv.h b/include/strv.h
new file mode 100644
index 0000000..6382532
--- /dev/null
+++ b/include/strv.h
@@ -0,0 +1,58 @@
+#ifndef UTIL_LINUX_STRV
+#define UTIL_LINUX_STRV
+
+#include <stdarg.h>
+
+#include "c.h"
+
+char **strv_free(char **l);
+void strv_clear(char **l);
+char **strv_copy(char * const *l);
+unsigned strv_length(char * const *l);
+
+int strv_extend_strv(char ***a, char **b);
+int strv_extend_strv_concat(char ***a, char **b, const char *suffix);
+int strv_extend(char ***l, const char *value);
+
+int strv_extendv(char ***l, const char *format, va_list ap)
+ __attribute__ ((__format__ (__printf__, 2, 0)));
+int strv_extendf(char ***l, const char *format, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+
+int strv_push(char ***l, char *value);
+int strv_push_prepend(char ***l, char *value);
+int strv_consume(char ***l, char *value);
+int strv_consume_prepend(char ***l, char *value);
+
+char **strv_remove(char **l, const char *s);
+
+char **strv_new(const char *x, ...);
+char **strv_new_ap(const char *x, va_list ap);
+
+static inline const char* STRV_IFNOTNULL(const char *x) {
+ return x ? x : (const char *) -1;
+}
+
+static inline int strv_isempty(char * const *l) {
+ return !l || !*l;
+}
+
+char **strv_split(const char *s, const char *separator);
+char *strv_join(char **l, const char *separator);
+
+#define STRV_FOREACH(s, l) \
+ for ((s) = (l); (s) && *(s); (s)++)
+
+#define STRV_FOREACH_BACKWARDS(s, l) \
+ STRV_FOREACH(s, l) \
+ ; \
+ for ((s)--; (l) && ((s) >= (l)); (s)--)
+
+
+#define STRV_MAKE_EMPTY ((char*[1]) { NULL })
+
+char **strv_reverse(char **l);
+
+#endif /* UTIL_LINUX_STRV */
+
+
diff --git a/include/swapheader.h b/include/swapheader.h
new file mode 100644
index 0000000..3fce0d0
--- /dev/null
+++ b/include/swapheader.h
@@ -0,0 +1,23 @@
+#ifndef _SWAPHEADER_H
+#define _SWAPHEADER_H
+
+#define SWAP_VERSION 1
+#define SWAP_UUID_LENGTH 16
+#define SWAP_LABEL_LENGTH 16
+#define SWAP_SIGNATURE "SWAPSPACE2"
+#define SWAP_SIGNATURE_SZ (sizeof(SWAP_SIGNATURE) - 1)
+
+#include <stdint.h>
+
+struct swap_header_v1_2 {
+ char bootbits[1024]; /* Space for disklabel etc. */
+ uint32_t version;
+ uint32_t last_page;
+ uint32_t nr_badpages;
+ unsigned char uuid[SWAP_UUID_LENGTH];
+ char volume_name[SWAP_LABEL_LENGTH];
+ uint32_t padding[117];
+ uint32_t badpages[1];
+};
+
+#endif /* _SWAPHEADER_H */
diff --git a/include/swapprober.h b/include/swapprober.h
new file mode 100644
index 0000000..5107700
--- /dev/null
+++ b/include/swapprober.h
@@ -0,0 +1,9 @@
+#ifndef UTIL_LINUX_SWAP_PROBER_H
+#define UTIL_LINUX_SWAP_PROBER_H
+
+#include <blkid.h>
+
+blkid_probe get_swap_prober(const char *devname);
+
+#endif /* UTIL_LINUX_SWAP_PROBER_H */
+
diff --git a/include/sysfs.h b/include/sysfs.h
new file mode 100644
index 0000000..a10e948
--- /dev/null
+++ b/include/sysfs.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2011 Karel Zak <kzak@redhat.com>
+ */
+#ifndef UTIL_LINUX_SYSFS_H
+#define UTIL_LINUX_SYSFS_H
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <inttypes.h>
+#include <dirent.h>
+
+#include "path.h"
+
+/**
+ * sysfs_devname_sys_to_dev:
+ * @name: devname to be converted in place
+ *
+ * Linux kernel linux/drivers/base/core.c: device_get_devnode()
+ * defines a replacement of '!' in the /sys device name by '/' in the
+ * /dev device name. This helper replaces all occurrences of '!' in
+ * @name by '/' to convert from /sys to /dev.
+ */
+static inline void sysfs_devname_sys_to_dev(char *name)
+{
+ char *c;
+
+ if (name)
+ while ((c = strchr(name, '!')))
+ c[0] = '/';
+}
+
+/**
+ * sysfs_devname_dev_to_sys:
+ * @name: devname to be converted in place
+ *
+ * See sysfs_devname_sys_to_dev().
+ */
+static inline void sysfs_devname_dev_to_sys(char *name)
+{
+ char *c;
+
+ if (name)
+ while ((c = strchr(name, '/')))
+ c[0] = '!';
+}
+
+struct sysfs_blkdev {
+ dev_t devno;
+ struct path_cxt *parent;
+
+ unsigned int scsi_host,
+ scsi_channel,
+ scsi_target,
+ scsi_lun;
+
+ unsigned int has_hctl : 1,
+ hctl_error : 1 ;
+};
+
+void ul_sysfs_init_debug(void);
+
+struct path_cxt *ul_new_sysfs_path(dev_t devno, struct path_cxt *parent, const char *prefix);
+int sysfs_blkdev_init_path(struct path_cxt *pc, dev_t devno, struct path_cxt *parent);
+
+int sysfs_blkdev_set_parent(struct path_cxt *pc, struct path_cxt *parent);
+struct path_cxt *sysfs_blkdev_get_parent(struct path_cxt *pc);
+
+char *sysfs_blkdev_get_name(struct path_cxt *pc, char *buf, size_t bufsiz);
+int sysfs_blkdev_is_partition_dirent(DIR *dir, struct dirent *d, const char *parent_name);
+int sysfs_blkdev_count_partitions(struct path_cxt *pc, const char *devname);
+dev_t sysfs_blkdev_partno_to_devno(struct path_cxt *pc, int partno);
+char *sysfs_blkdev_get_slave(struct path_cxt *pc);
+char *sysfs_blkdev_get_path(struct path_cxt *pc, char *buf, size_t bufsiz);
+dev_t sysfs_blkdev_get_devno(struct path_cxt *pc);
+
+char *sysfs_blkdev_get_devchain(struct path_cxt *pc, char *buf, size_t bufsz);
+int sysfs_blkdev_next_subsystem(struct path_cxt *pc __attribute__((unused)), char *devchain, char **subsys);
+
+int sysfs_blkdev_is_hotpluggable(struct path_cxt *pc);
+int sysfs_blkdev_get_wholedisk( struct path_cxt *pc,
+ char *diskname,
+ size_t len,
+ dev_t *diskdevno);
+
+int sysfs_devno_to_wholedisk(dev_t dev, char *diskname,
+ size_t len, dev_t *diskdevno);
+int sysfs_devno_is_dm_private(dev_t devno, char **uuid);
+int sysfs_devno_is_wholedisk(dev_t devno);
+
+dev_t sysfs_devname_to_devno(const char *name);
+dev_t __sysfs_devname_to_devno(const char *prefix, const char *name, const char *parent);
+int sysfs_devname_is_hidden(const char *prefix, const char *name);
+
+char *sysfs_devno_to_devpath(dev_t devno, char *buf, size_t bufsiz);
+char *sysfs_devno_to_devname(dev_t devno, char *buf, size_t bufsiz);
+int sysfs_devno_count_partitions(dev_t devno);
+
+int sysfs_blkdev_scsi_get_hctl(struct path_cxt *pc, int *h, int *c, int *t, int *l);
+char *sysfs_blkdev_scsi_host_strdup_attribute(struct path_cxt *pc,
+ const char *type, const char *attr);
+int sysfs_blkdev_scsi_host_is(struct path_cxt *pc, const char *type);
+int sysfs_blkdev_scsi_has_attribute(struct path_cxt *pc, const char *attr);
+int sysfs_blkdev_scsi_path_contains(struct path_cxt *pc, const char *pattern);
+
+char *sysfs_chrdev_devno_to_devname(dev_t devno, char *buf, size_t bufsiz);
+
+
+#endif /* UTIL_LINUX_SYSFS_H */
diff --git a/include/timer.h b/include/timer.h
new file mode 100644
index 0000000..70da1ba
--- /dev/null
+++ b/include/timer.h
@@ -0,0 +1,22 @@
+#ifndef UTIL_LINUX_TIMER_H
+#define UTIL_LINUX_TIMER_H
+
+#include <signal.h>
+#include <sys/time.h>
+
+#ifdef HAVE_TIMER_CREATE
+struct ul_timer {
+ timer_t t_id;
+};
+#else
+struct ul_timer {
+ struct itimerval old_timer;
+ struct sigaction old_sa;
+};
+#endif
+
+extern int setup_timer(struct ul_timer *timer, struct itimerval *timeout,
+ void (*timeout_handler)(int, siginfo_t *, void *));
+extern void cancel_timer(struct ul_timer *timer);
+
+#endif /* UTIL_LINUX_TIMER_H */
diff --git a/include/timeutils.h b/include/timeutils.h
new file mode 100644
index 0000000..e452e55
--- /dev/null
+++ b/include/timeutils.h
@@ -0,0 +1,92 @@
+/***
+ First set of functions in this file are part of systemd, and were
+ copied to util-linux at August 2013.
+
+ Copyright 2010 Lennart Poettering
+ Copyright (C) 2014 Karel Zak <kzak@redhat.com>
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+#ifndef UTIL_LINUX_TIME_UTIL_H
+#define UTIL_LINUX_TIME_UTIL_H
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <sys/time.h>
+
+typedef uint64_t usec_t;
+typedef uint64_t nsec_t;
+
+#define MSEC_PER_SEC 1000ULL
+#define USEC_PER_SEC 1000000ULL
+#define USEC_PER_MSEC 1000ULL
+#define NSEC_PER_SEC 1000000000ULL
+#define NSEC_PER_MSEC 1000000ULL
+#define NSEC_PER_USEC 1000ULL
+
+#define USEC_PER_MINUTE (60ULL*USEC_PER_SEC)
+#define NSEC_PER_MINUTE (60ULL*NSEC_PER_SEC)
+#define USEC_PER_HOUR (60ULL*USEC_PER_MINUTE)
+#define NSEC_PER_HOUR (60ULL*NSEC_PER_MINUTE)
+#define USEC_PER_DAY (24ULL*USEC_PER_HOUR)
+#define NSEC_PER_DAY (24ULL*NSEC_PER_HOUR)
+#define USEC_PER_WEEK (7ULL*USEC_PER_DAY)
+#define NSEC_PER_WEEK (7ULL*NSEC_PER_DAY)
+#define USEC_PER_MONTH (2629800ULL*USEC_PER_SEC)
+#define NSEC_PER_MONTH (2629800ULL*NSEC_PER_SEC)
+#define USEC_PER_YEAR (31557600ULL*USEC_PER_SEC)
+#define NSEC_PER_YEAR (31557600ULL*NSEC_PER_SEC)
+
+#define FORMAT_TIMESTAMP_MAX ((4*4+1)+11+9+4+1) /* weekdays can be unicode */
+#define FORMAT_TIMESTAMP_RELATIVE_MAX 256
+#define FORMAT_TIMESPAN_MAX 64
+
+int parse_timestamp(const char *t, usec_t *usec);
+int get_gmtoff(const struct tm *tp);
+
+/* flags and masks for strxxx_iso() functions */
+enum {
+ ISO_DATE = (1 << 0),
+ ISO_TIME = (1 << 1),
+ ISO_TIMEZONE = (1 << 2),
+ ISO_DOTUSEC = (1 << 3),
+ ISO_COMMAUSEC = (1 << 4),
+ ISO_T = (1 << 5),
+ ISO_GMTIME = (1 << 6),
+ ISO_TIMESTAMP = ISO_DATE | ISO_TIME | ISO_TIMEZONE,
+ ISO_TIMESTAMP_T = ISO_TIMESTAMP | ISO_T,
+ ISO_TIMESTAMP_DOT = ISO_TIMESTAMP | ISO_DOTUSEC,
+ ISO_TIMESTAMP_DOT_T = ISO_TIMESTAMP_DOT | ISO_T,
+ ISO_TIMESTAMP_COMMA = ISO_TIMESTAMP | ISO_COMMAUSEC,
+ ISO_TIMESTAMP_COMMA_T = ISO_TIMESTAMP_COMMA | ISO_T,
+ ISO_TIMESTAMP_COMMA_G = ISO_TIMESTAMP_COMMA | ISO_GMTIME,
+ ISO_TIMESTAMP_COMMA_GT = ISO_TIMESTAMP_COMMA_G | ISO_T
+};
+
+#define CTIME_BUFSIZ 26
+#define ISO_BUFSIZ 42
+
+int strtimeval_iso(struct timeval *tv, int flags, char *buf, size_t bufsz);
+int strtm_iso(struct tm *tm, int flags, char *buf, size_t bufsz);
+int strtime_iso(const time_t *t, int flags, char *buf, size_t bufsz);
+
+#define UL_SHORTTIME_THISYEAR_HHMM (1 << 1)
+
+int strtime_short(const time_t *t, struct timeval *now, int flags, char *buf, size_t bufsz);
+
+#ifndef HAVE_TIMEGM
+extern time_t timegm(struct tm *tm);
+#endif
+
+#endif /* UTIL_LINUX_TIME_UTIL_H */
diff --git a/include/ttyutils.h b/include/ttyutils.h
new file mode 100644
index 0000000..e28a2b0
--- /dev/null
+++ b/include/ttyutils.h
@@ -0,0 +1,212 @@
+/*
+ * No copyright is claimed. This code is in the public domain; do with
+ * it what you wish.
+ *
+ * Written by Karel Zak <kzak@redhat.com>
+ */
+#ifndef UTIL_LINUX_TTYUTILS_H
+#define UTIL_LINUX_TTYUTILS_H
+
+#include <stdlib.h>
+#include <termios.h>
+#include <limits.h>
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_TTYDEFAULTS_H
+#include <sys/ttydefaults.h>
+#endif
+
+#ifdef USE_TTY_GROUP
+# define TTY_MODE 0620
+#else
+# define TTY_MODE 0600
+#endif
+#define TTYGRPNAME "tty" /* name of group to own ttys */
+
+/* Some shorthands for control characters. */
+#define CTL(x) ((x) ^ 0100) /* Assumes ASCII dialect */
+#define CR CTL('M') /* carriage return */
+#define NL CTL('J') /* line feed */
+#define BS CTL('H') /* back space */
+#define DEL CTL('?') /* delete */
+
+/* Defaults for line-editing etc. characters; you may want to change these. */
+#define DEF_ERASE DEL /* default erase character */
+#define DEF_INTR CTL('C') /* default interrupt character */
+#define DEF_QUIT CTL('\\') /* default quit char */
+#define DEF_KILL CTL('U') /* default kill char */
+#define DEF_EOF CTL('D') /* default EOF char */
+#define DEF_EOL 0
+#define DEF_SWITCH 0 /* default switch char */
+
+/* Fallback for termios->c_cc[] */
+#ifndef CREPRINT
+# define CREPRINT ('r' & 037)
+#endif
+#ifndef CDISCARD
+# define CDISCARD ('o' & 037)
+#endif
+
+/* Default termios->iflag */
+#ifndef TTYDEF_IFLAG
+# define TTYDEF_IFLAG (BRKINT | ICRNL | IMAXBEL | IXON | IXANY)
+#endif
+
+/* Default termios->oflag */
+#ifndef TTYDEF_OFLAG
+# define TTYDEF_OFLAG (OPOST | ONLCR /*| OXTABS*/)
+#endif
+
+/* Default termios->lflag */
+#ifndef TTYDEF_LFLAG
+# define TTYDEF_LFLAG (ECHO | ICANON | ISIG | IEXTEN | ECHOE|ECHOKE|ECHOCTL)
+#endif
+
+/* Default termios->cflag */
+#ifndef TTYDEF_CFLAG
+# define TTYDEF_CFLAG (CREAD | CS8 | HUPCL)
+#endif
+
+/* Storage for things detected while the login name was read. */
+struct chardata {
+ int erase; /* erase character */
+ int kill; /* kill character */
+ int eol; /* end-of-line character */
+ int parity; /* what parity did we see */
+ int capslock; /* upper case without lower case */
+};
+
+#define INIT_CHARDATA(ptr) do { \
+ (ptr)->erase = DEF_ERASE; \
+ (ptr)->kill = DEF_KILL; \
+ (ptr)->eol = CR; \
+ (ptr)->parity = 0; \
+ (ptr)->capslock = 0; \
+ } while (0)
+
+extern int get_terminal_dimension(int *cols, int *lines);
+extern int get_terminal_width(int default_width);
+extern int get_terminal_type(const char **type);
+extern int get_terminal_stdfd(void);
+extern int get_terminal_name(const char **path, const char **name,
+ const char **number);
+
+#define UL_TTY_KEEPCFLAGS (1 << 1)
+#define UL_TTY_UTF8 (1 << 2)
+
+static inline void reset_virtual_console(struct termios *tp, int flags)
+{
+ /* Use defaults of <sys/ttydefaults.h> for base settings */
+ tp->c_iflag |= TTYDEF_IFLAG;
+ tp->c_oflag |= TTYDEF_OFLAG;
+ tp->c_lflag |= TTYDEF_LFLAG;
+
+ if ((flags & UL_TTY_KEEPCFLAGS) == 0) {
+#ifdef CBAUD
+ tp->c_lflag &= ~CBAUD;
+#endif
+ tp->c_cflag |= (B38400 | TTYDEF_CFLAG);
+ }
+
+ /* Sane setting, allow eight bit characters, no carriage return delay
+ * the same result as `stty sane cr0 pass8'
+ */
+#ifndef IUCLC
+# define IUCLC 0
+#endif
+#ifndef NL0
+# define NL0 0
+#endif
+#ifndef CR0
+# define CR0 0
+#endif
+#ifndef BS0
+# define BS0 0
+#endif
+#ifndef VT0
+# define VT0 0
+#endif
+#ifndef FF0
+# define FF0 0
+#endif
+#ifndef OLCUC
+# define OLCUC 0
+#endif
+#ifndef OFILL
+# define OFILL 0
+#endif
+#ifndef NLDLY
+# define NLDLY 0
+#endif
+#ifndef CRDLY
+# define CRDLY 0
+#endif
+#ifndef BSDLY
+# define BSDLY 0
+#endif
+#ifndef VTDLY
+# define VTDLY 0
+#endif
+#ifndef FFDLY
+# define FFDLY 0
+#endif
+#ifndef TAB0
+# define TAB0 0
+#endif
+#ifndef TABDLY
+# define TABDLY 0
+#endif
+
+ tp->c_iflag |= (BRKINT | ICRNL | IMAXBEL);
+ tp->c_iflag &= ~(IGNBRK | INLCR | IGNCR | IXOFF | IUCLC | IXANY | ISTRIP);
+ tp->c_oflag |= (OPOST | ONLCR | NL0 | CR0 | TAB0 | BS0 | VT0 | FF0);
+ tp->c_oflag &= ~(OLCUC | OCRNL | ONOCR | ONLRET | OFILL | \
+ NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
+ tp->c_lflag |= (ISIG | ICANON | IEXTEN | ECHO|ECHOE|ECHOK|ECHOKE|ECHOCTL);
+ tp->c_lflag &= ~(ECHONL|ECHOPRT | NOFLSH | TOSTOP);
+
+ if ((flags & UL_TTY_KEEPCFLAGS) == 0) {
+ tp->c_cflag |= (CREAD | CS8 | HUPCL);
+ tp->c_cflag &= ~(PARODD | PARENB);
+ }
+#ifdef OFDEL
+ tp->c_oflag &= ~OFDEL;
+#endif
+#ifdef XCASE
+ tp->c_lflag &= ~XCASE;
+#endif
+#ifdef IUTF8
+ if (flags & UL_TTY_UTF8)
+ tp->c_iflag |= IUTF8; /* Set UTF-8 input flag */
+ else
+ tp->c_iflag &= ~IUTF8;
+#endif
+ /* VTIME and VMIN can overlap with VEOF and VEOL since they are
+ * only used for non-canonical mode. We just set the at the
+ * beginning, so nothing bad should happen.
+ */
+ tp->c_cc[VTIME] = 0;
+ tp->c_cc[VMIN] = 1;
+ tp->c_cc[VINTR] = CINTR;
+ tp->c_cc[VQUIT] = CQUIT;
+ tp->c_cc[VERASE] = CERASE; /* ASCII DEL (0177) */
+ tp->c_cc[VKILL] = CKILL;
+ tp->c_cc[VEOF] = CEOF;
+#ifdef VSWTC
+ tp->c_cc[VSWTC] = _POSIX_VDISABLE;
+#elif defined(VSWTCH)
+ tp->c_cc[VSWTCH] = _POSIX_VDISABLE;
+#endif
+ tp->c_cc[VSTART] = CSTART;
+ tp->c_cc[VSTOP] = CSTOP;
+ tp->c_cc[VSUSP] = CSUSP;
+ tp->c_cc[VEOL] = _POSIX_VDISABLE;
+ tp->c_cc[VREPRINT] = CREPRINT;
+ tp->c_cc[VDISCARD] = CDISCARD;
+ tp->c_cc[VWERASE] = CWERASE;
+ tp->c_cc[VLNEXT] = CLNEXT;
+ tp->c_cc[VEOL2] = _POSIX_VDISABLE;
+}
+
+#endif /* UTIL_LINUX_TTYUTILS_H */
diff --git a/include/widechar.h b/include/widechar.h
new file mode 100644
index 0000000..c1f2cf2
--- /dev/null
+++ b/include/widechar.h
@@ -0,0 +1,47 @@
+/* Declarations for wide characters */
+/* This file must be included last because the redefinition of wchar_t may
+ cause conflicts when system include files were included after it. */
+
+#ifdef HAVE_WIDECHAR
+
+# include <wchar.h>
+# include <wctype.h>
+
+#else /* !HAVE_WIDECHAR */
+
+# include <ctype.h>
+ /* Fallback for types */
+# define wchar_t char
+# define wint_t int
+# ifndef WEOF
+# define WEOF EOF
+# endif
+
+ /* Fallback for input operations */
+# define fgetwc fgetc
+# define getwc getc
+# define getwchar getchar
+# define fgetws fgets
+
+ /* Fallback for output operations */
+# define fputwc fputc
+# define putwc putc
+# define putwchar putchar
+# define fputws fputs
+
+ /* Fallback for character classification */
+# define iswgraph isgraph
+# define iswprint isprint
+# define iswspace isspace
+
+ /* Fallback for string functions */
+# define wcschr strchr
+# define wcsdup strdup
+# define wcslen strlen
+# define wcspbrk strpbrk
+
+# define wcwidth(c) (1)
+# define wmemset memset
+# define ungetwc ungetc
+
+#endif /* HAVE_WIDECHAR */
diff --git a/include/xalloc.h b/include/xalloc.h
new file mode 100644
index 0000000..c4124cb
--- /dev/null
+++ b/include/xalloc.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2010 Davidlohr Bueso <dave@gnu.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ *
+ * General memory allocation wrappers for malloc, realloc, calloc and strdup
+ */
+
+#ifndef UTIL_LINUX_XALLOC_H
+#define UTIL_LINUX_XALLOC_H
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "c.h"
+
+#ifndef XALLOC_EXIT_CODE
+# define XALLOC_EXIT_CODE EXIT_FAILURE
+#endif
+
+static inline
+__attribute__((__noreturn__))
+void __err_oom(const char *file, unsigned int line)
+{
+ err(XALLOC_EXIT_CODE, "%s: %u: cannot allocate memory", file, line);
+}
+
+#define err_oom() __err_oom(__FILE__, __LINE__)
+
+static inline
+__ul_alloc_size(1)
+__ul_returns_nonnull
+void *xmalloc(const size_t size)
+{
+ void *ret = malloc(size);
+
+ if (!ret && size)
+ err(XALLOC_EXIT_CODE, "cannot allocate %zu bytes", size);
+ return ret;
+}
+
+static inline
+__ul_alloc_size(2)
+__ul_returns_nonnull
+void *xrealloc(void *ptr, const size_t size)
+{
+ void *ret = realloc(ptr, size);
+
+ if (!ret && size)
+ err(XALLOC_EXIT_CODE, "cannot allocate %zu bytes", size);
+ return ret;
+}
+
+static inline
+__ul_calloc_size(1, 2)
+__ul_returns_nonnull
+void *xcalloc(const size_t nelems, const size_t size)
+{
+ void *ret = calloc(nelems, size);
+
+ if (!ret && size && nelems)
+ err(XALLOC_EXIT_CODE, "cannot allocate %zu bytes", size);
+ return ret;
+}
+
+static inline
+__attribute__((warn_unused_result))
+__ul_returns_nonnull
+char *xstrdup(const char *str)
+{
+ char *ret;
+
+ assert(str);
+ ret = strdup(str);
+ if (!ret)
+ err(XALLOC_EXIT_CODE, "cannot duplicate string");
+ return ret;
+}
+
+static inline
+__attribute__((warn_unused_result))
+__ul_returns_nonnull
+char *xstrndup(const char *str, size_t size)
+{
+ char *ret;
+
+ assert(str);
+ ret = strndup(str, size);
+ if (!ret)
+ err(XALLOC_EXIT_CODE, "cannot duplicate string");
+ return ret;
+}
+
+
+static inline
+__attribute__((__format__(printf, 2, 3)))
+int xasprintf(char **strp, const char *fmt, ...)
+{
+ int ret;
+ va_list args;
+
+ va_start(args, fmt);
+ ret = vasprintf(&(*strp), fmt, args);
+ va_end(args);
+ if (ret < 0)
+ err(XALLOC_EXIT_CODE, "cannot allocate string");
+ return ret;
+}
+
+static inline
+__attribute__((__format__(printf, 2, 0)))
+int xvasprintf(char **strp, const char *fmt, va_list ap)
+{
+ int ret = vasprintf(&(*strp), fmt, ap);
+
+ if (ret < 0)
+ err(XALLOC_EXIT_CODE, "cannot allocate string");
+ return ret;
+}
+
+
+static inline
+__attribute__((warn_unused_result))
+char *xgethostname(void)
+{
+ char *name;
+ size_t sz = get_hostname_max() + 1;
+
+ name = xmalloc(sizeof(char) * sz);
+ if (gethostname(name, sz) != 0) {
+ free(name);
+ return NULL;
+ }
+ name[sz - 1] = '\0';
+ return name;
+}
+
+#endif