summaryrefslogtreecommitdiffstats
path: root/utils/lib
diff options
context:
space:
mode:
authorManuel Bentele2020-10-23 15:18:01 +0200
committerManuel Bentele2020-10-23 15:18:01 +0200
commitdbb41ce2b7f309d394054a6bd1e33afd578798a5 (patch)
tree6a31092063d9f2fb5ac5720ec6759040e793c3d5 /utils/lib
parentSet Linux kernel version to unknown if it is not detectable (diff)
downloadxloop-dbb41ce2b7f309d394054a6bd1e33afd578798a5.tar.gz
xloop-dbb41ce2b7f309d394054a6bd1e33afd578798a5.tar.xz
xloop-dbb41ce2b7f309d394054a6bd1e33afd578798a5.zip
Move the source code of all xloop components to the common 'src' directory
Diffstat (limited to 'utils/lib')
-rw-r--r--utils/lib/CMakeLists.txt44
-rw-r--r--utils/lib/blkdev.c452
-rw-r--r--utils/lib/canonicalize.c250
-rw-r--r--utils/lib/caputils.c45
-rw-r--r--utils/lib/color-names.c64
-rw-r--r--utils/lib/colors.c907
-rw-r--r--utils/lib/cpuset.c413
-rw-r--r--utils/lib/crc32.c142
-rw-r--r--utils/lib/crc32c.c102
-rw-r--r--utils/lib/encode.c79
-rw-r--r--utils/lib/env.c238
-rw-r--r--utils/lib/exec_shell.c51
-rw-r--r--utils/lib/fileutils.c246
-rw-r--r--utils/lib/idcache.c117
-rw-r--r--utils/lib/ismounted.c396
-rw-r--r--utils/lib/langinfo.c124
-rw-r--r--utils/lib/linux_version.c71
-rw-r--r--utils/lib/loopdev.c1914
-rw-r--r--utils/lib/mangle.c169
-rw-r--r--utils/lib/match.c53
-rw-r--r--utils/lib/mbsalign.c627
-rw-r--r--utils/lib/mbsedit.c225
-rw-r--r--utils/lib/md5.c257
-rw-r--r--utils/lib/monotonic.c81
-rw-r--r--utils/lib/pager.c317
-rw-r--r--utils/lib/path.c1248
-rw-r--r--utils/lib/plymouth-ctrl.c144
-rw-r--r--utils/lib/procutils.c308
-rw-r--r--utils/lib/pty-session.c725
-rw-r--r--utils/lib/pwdutils.c156
-rw-r--r--utils/lib/randutils.c238
-rw-r--r--utils/lib/setproctitle.c75
-rw-r--r--utils/lib/sha1.c256
-rw-r--r--utils/lib/signames.c204
-rw-r--r--utils/lib/strutils.c1135
-rw-r--r--utils/lib/strv.c403
-rw-r--r--utils/lib/sysfs.c1127
-rw-r--r--utils/lib/timer.c95
-rw-r--r--utils/lib/timeutils.c611
-rw-r--r--utils/lib/ttyutils.c152
40 files changed, 0 insertions, 14261 deletions
diff --git a/utils/lib/CMakeLists.txt b/utils/lib/CMakeLists.txt
deleted file mode 100644
index e5fa459..0000000
--- a/utils/lib/CMakeLists.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-cmake_minimum_required(VERSION 3.10)
-
-# set the project name
-project(xloop-utils-lib)
-
-add_library(libcommon STATIC ${CMAKE_CURRENT_SOURCE_DIR}/blkdev.c
- ${CMAKE_CURRENT_SOURCE_DIR}/canonicalize.c
- ${CMAKE_CURRENT_SOURCE_DIR}/caputils.c
- ${CMAKE_CURRENT_SOURCE_DIR}/color-names.c
- ${CMAKE_CURRENT_SOURCE_DIR}/colors.c
- ${CMAKE_CURRENT_SOURCE_DIR}/cpuset.c
- ${CMAKE_CURRENT_SOURCE_DIR}/crc32.c
- ${CMAKE_CURRENT_SOURCE_DIR}/crc32c.c
- ${CMAKE_CURRENT_SOURCE_DIR}/encode.c
- ${CMAKE_CURRENT_SOURCE_DIR}/env.c
- ${CMAKE_CURRENT_SOURCE_DIR}/exec_shell.c
- ${CMAKE_CURRENT_SOURCE_DIR}/fileutils.c
- ${CMAKE_CURRENT_SOURCE_DIR}/idcache.c
- ${CMAKE_CURRENT_SOURCE_DIR}/ismounted.c
- ${CMAKE_CURRENT_SOURCE_DIR}/langinfo.c
- ${CMAKE_CURRENT_SOURCE_DIR}/linux_version.c
- ${CMAKE_CURRENT_SOURCE_DIR}/loopdev.c
- ${CMAKE_CURRENT_SOURCE_DIR}/mangle.c
- ${CMAKE_CURRENT_SOURCE_DIR}/match.c
- ${CMAKE_CURRENT_SOURCE_DIR}/mbsalign.c
- ${CMAKE_CURRENT_SOURCE_DIR}/mbsedit.c
- ${CMAKE_CURRENT_SOURCE_DIR}/md5.c
- ${CMAKE_CURRENT_SOURCE_DIR}/monotonic.c
- ${CMAKE_CURRENT_SOURCE_DIR}/pager.c
- ${CMAKE_CURRENT_SOURCE_DIR}/path.c
- ${CMAKE_CURRENT_SOURCE_DIR}/plymouth-ctrl.c
- ${CMAKE_CURRENT_SOURCE_DIR}/procutils.c
- ${CMAKE_CURRENT_SOURCE_DIR}/pty-session.c
- ${CMAKE_CURRENT_SOURCE_DIR}/pwdutils.c
- ${CMAKE_CURRENT_SOURCE_DIR}/randutils.c
- ${CMAKE_CURRENT_SOURCE_DIR}/setproctitle.c
- ${CMAKE_CURRENT_SOURCE_DIR}/sha1.c
- ${CMAKE_CURRENT_SOURCE_DIR}/signames.c
- ${CMAKE_CURRENT_SOURCE_DIR}/strutils.c
- ${CMAKE_CURRENT_SOURCE_DIR}/strv.c
- ${CMAKE_CURRENT_SOURCE_DIR}/sysfs.c
- ${CMAKE_CURRENT_SOURCE_DIR}/timer.c
- ${CMAKE_CURRENT_SOURCE_DIR}/timeutils.c
- ${CMAKE_CURRENT_SOURCE_DIR}/ttyutils.c)
diff --git a/utils/lib/blkdev.c b/utils/lib/blkdev.c
deleted file mode 100644
index c22853d..0000000
--- a/utils/lib/blkdev.c
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * No copyright is claimed. This code is in the public domain; do with
- * it what you wish.
- *
- * Written by Karel Zak <kzak@redhat.com>
- */
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <stdint.h>
-
-#ifdef HAVE_LINUX_FD_H
-#include <linux/fd.h>
-#endif
-
-#ifdef HAVE_SYS_DISKLABEL_H
-#include <sys/disklabel.h>
-#endif
-
-#ifdef HAVE_SYS_DISK_H
-# include <sys/disk.h>
-#endif
-
-#ifndef EBADFD
-# define EBADFD 77 /* File descriptor in bad state */
-#endif
-
-#include "blkdev.h"
-#include "c.h"
-#include "linux_version.h"
-#include "fileutils.h"
-#include "nls.h"
-
-static long
-blkdev_valid_offset (int fd, off_t offset) {
- char ch;
-
- if (lseek (fd, offset, 0) < 0)
- return 0;
- if (read (fd, &ch, 1) < 1)
- return 0;
- return 1;
-}
-
-int is_blkdev(int fd)
-{
- struct stat st;
- return (fstat(fd, &st) == 0 && S_ISBLK(st.st_mode));
-}
-
-off_t
-blkdev_find_size (int fd) {
- uintmax_t high, low = 0;
-
- for (high = 1024; blkdev_valid_offset (fd, high); ) {
- if (high == UINTMAX_MAX)
- return -1;
-
- low = high;
-
- if (high >= UINTMAX_MAX/2)
- high = UINTMAX_MAX;
- else
- high *= 2;
- }
-
- while (low < high - 1)
- {
- uintmax_t mid = (low + high) / 2;
-
- if (blkdev_valid_offset (fd, mid))
- low = mid;
- else
- high = mid;
- }
- blkdev_valid_offset (fd, 0);
- return (low + 1);
-}
-
-/* get size in bytes */
-int
-blkdev_get_size(int fd, unsigned long long *bytes)
-{
-#ifdef DKIOCGETBLOCKCOUNT
- /* Apple Darwin */
- if (ioctl(fd, DKIOCGETBLOCKCOUNT, bytes) >= 0) {
- *bytes <<= 9;
- return 0;
- }
-#endif
-
-#ifdef BLKGETSIZE64
- if (ioctl(fd, BLKGETSIZE64, bytes) >= 0)
- return 0;
-#endif
-
-#ifdef BLKGETSIZE
- {
- unsigned long size;
-
- if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
- *bytes = ((unsigned long long)size << 9);
- return 0;
- }
- }
-
-#endif /* BLKGETSIZE */
-
-#ifdef DIOCGMEDIASIZE
- /* FreeBSD */
- if (ioctl(fd, DIOCGMEDIASIZE, bytes) >= 0)
- return 0;
-#endif
-
-#ifdef FDGETPRM
- {
- struct floppy_struct this_floppy;
-
- if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
- *bytes = ((unsigned long long) this_floppy.size) << 9;
- return 0;
- }
- }
-#endif /* FDGETPRM */
-
-#if defined(HAVE_SYS_DISKLABEL_H) && defined(DIOCGDINFO)
- {
- /*
- * This code works for FreeBSD 4.11 i386, except for the full device
- * (such as /dev/ad0). It doesn't work properly for newer FreeBSD
- * though. FreeBSD >= 5.0 should be covered by the DIOCGMEDIASIZE
- * above however.
- *
- * Note that FreeBSD >= 4.0 has disk devices as unbuffered (raw,
- * character) devices, so we need to check for S_ISCHR, too.
- */
- int part = -1;
- struct disklabel lab;
- struct partition *pp;
- struct stat st;
-
- if ((fstat(fd, &st) >= 0) &&
- (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)))
- part = st.st_rdev & 7;
-
- if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
- pp = &lab.d_partitions[part];
- if (pp->p_size) {
- *bytes = pp->p_size << 9;
- return 0;
- }
- }
- }
-#endif /* defined(HAVE_SYS_DISKLABEL_H) && defined(DIOCGDINFO) */
-
- {
- struct stat st;
-
- if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
- *bytes = st.st_size;
- return 0;
- }
- if (!S_ISBLK(st.st_mode))
- return -1;
- }
-
- *bytes = blkdev_find_size(fd);
- return 0;
-}
-
-/* get 512-byte sector count */
-int
-blkdev_get_sectors(int fd, unsigned long long *sectors)
-{
- unsigned long long bytes;
-
- if (blkdev_get_size(fd, &bytes) == 0) {
- *sectors = (bytes >> 9);
- return 0;
- }
-
- return -1;
-}
-
-/*
- * Get logical sector size.
- *
- * This is the smallest unit the storage device can
- * address. It is typically 512 bytes.
- */
-#ifdef BLKSSZGET
-int blkdev_get_sector_size(int fd, int *sector_size)
-{
- if (ioctl(fd, BLKSSZGET, sector_size) >= 0)
- return 0;
- return -1;
-}
-#else
-int blkdev_get_sector_size(int fd __attribute__((__unused__)), int *sector_size)
-{
- *sector_size = DEFAULT_SECTOR_SIZE;
- return 0;
-}
-#endif
-
-/*
- * Get physical block device size. The BLKPBSZGET is supported since Linux
- * 2.6.32. For old kernels is probably the best to assume that physical sector
- * size is the same as logical sector size.
- *
- * Example:
- *
- * rc = blkdev_get_physector_size(fd, &physec);
- * if (rc || physec == 0) {
- * rc = blkdev_get_sector_size(fd, &physec);
- * if (rc)
- * physec = DEFAULT_SECTOR_SIZE;
- * }
- */
-#ifdef BLKPBSZGET
-int blkdev_get_physector_size(int fd, int *sector_size)
-{
- if (ioctl(fd, BLKPBSZGET, &sector_size) >= 0)
- return 0;
- return -1;
-}
-#else
-int blkdev_get_physector_size(int fd __attribute__((__unused__)), int *sector_size)
-{
- *sector_size = DEFAULT_SECTOR_SIZE;
- return 0;
-}
-#endif
-
-/*
- * Return the alignment status of a device
- */
-#ifdef BLKALIGNOFF
-int blkdev_is_misaligned(int fd)
-{
- int aligned;
-
- if (ioctl(fd, BLKALIGNOFF, &aligned) < 0)
- return 0; /* probably kernel < 2.6.32 */
- /*
- * Note that kernel returns -1 as alignment offset if no compatible
- * sizes and alignments exist for stacked devices
- */
- return aligned != 0 ? 1 : 0;
-}
-#else
-int blkdev_is_misaligned(int fd __attribute__((__unused__)))
-{
- return 0;
-}
-#endif
-
-int open_blkdev_or_file(const struct stat *st, const char *name, const int oflag)
-{
- int fd;
-
- if (S_ISBLK(st->st_mode)) {
- fd = open(name, oflag | O_EXCL);
- } else
- fd = open(name, oflag);
- if (-1 < fd && !is_same_inode(fd, st)) {
- close(fd);
- errno = EBADFD;
- return -1;
- }
- if (-1 < fd && S_ISBLK(st->st_mode) && blkdev_is_misaligned(fd))
- warnx(_("warning: %s is misaligned"), name);
- return fd;
-}
-
-#ifdef CDROM_GET_CAPABILITY
-int blkdev_is_cdrom(int fd)
-{
- int ret;
-
- if ((ret = ioctl(fd, CDROM_GET_CAPABILITY, NULL)) < 0)
- return 0;
-
- return ret;
-}
-#else
-int blkdev_is_cdrom(int fd __attribute__((__unused__)))
-{
- return 0;
-}
-#endif
-
-/*
- * Get kernel's interpretation of the device's geometry.
- *
- * Returns the heads and sectors - but not cylinders
- * as it's truncated for disks with more than 65535 tracks.
- *
- * Note that this is deprecated in favor of LBA addressing.
- */
-#ifdef HDIO_GETGEO
-int blkdev_get_geometry(int fd, unsigned int *h, unsigned int *s)
-{
- struct hd_geometry geometry;
-
- if (ioctl(fd, HDIO_GETGEO, &geometry) == 0) {
- *h = geometry.heads;
- *s = geometry.sectors;
- return 0;
- }
-#else
-int blkdev_get_geometry(int fd __attribute__((__unused__)),
- unsigned int *h, unsigned int *s)
-{
- *h = 0;
- *s = 0;
-#endif
- return -1;
-}
-
-/*
- * Convert scsi type to human readable string.
- */
-const char *blkdev_scsi_type_to_name(int type)
-{
- switch (type) {
- case SCSI_TYPE_DISK:
- return "disk";
- case SCSI_TYPE_TAPE:
- return "tape";
- case SCSI_TYPE_PRINTER:
- return "printer";
- case SCSI_TYPE_PROCESSOR:
- return "processor";
- case SCSI_TYPE_WORM:
- return "worm";
- case SCSI_TYPE_ROM:
- return "rom";
- case SCSI_TYPE_SCANNER:
- return "scanner";
- case SCSI_TYPE_MOD:
- return "mo-disk";
- case SCSI_TYPE_MEDIUM_CHANGER:
- return "changer";
- case SCSI_TYPE_COMM:
- return "comm";
- case SCSI_TYPE_RAID:
- return "raid";
- case SCSI_TYPE_ENCLOSURE:
- return "enclosure";
- case SCSI_TYPE_RBC:
- return "rbc";
- case SCSI_TYPE_OSD:
- return "osd";
- case SCSI_TYPE_NO_LUN:
- return "no-lun";
- default:
- break;
- }
- return NULL;
-}
-
-/* return 0 on success */
-int blkdev_lock(int fd, const char *devname, const char *lockmode)
-{
- int oper, rc, msg = 0;
-
- if (!lockmode)
- lockmode = getenv("LOCK_BLOCK_DEVICE");
- if (!lockmode)
- return 0;
-
- if (strcasecmp(lockmode, "yes") == 0 ||
- strcmp(lockmode, "1") == 0)
- oper = LOCK_EX;
-
- else if (strcasecmp(lockmode, "nonblock") == 0)
- oper = LOCK_EX | LOCK_NB;
-
- else if (strcasecmp(lockmode, "no") == 0 ||
- strcmp(lockmode, "0") == 0)
- return 0;
- else {
- warnx(_("unsupported lock mode: %s"), lockmode);
- return -EINVAL;
- }
-
- if (!(oper & LOCK_NB)) {
- /* Try non-block first to provide message */
- rc = flock(fd, oper | LOCK_NB);
- if (rc == 0)
- return 0;
- if (rc != 0 && errno == EWOULDBLOCK) {
- fprintf(stderr, _("%s: %s: device already locked, waiting to get lock ... "),
- program_invocation_short_name, devname);
- msg = 1;
- }
- }
- rc = flock(fd, oper);
- if (rc != 0) {
- switch (errno) {
- case EWOULDBLOCK: /* LOCK_NB */
- warnx(_("%s: device already locked"), devname);
- break;
- default:
- warn(_("%s: failed to get lock"), devname);
- }
- } else if (msg)
- fprintf(stderr, _("OK\n"));
- return rc;
-}
-
-
-#ifdef TEST_PROGRAM_BLKDEV
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-int
-main(int argc, char **argv)
-{
- unsigned long long bytes;
- unsigned long long sectors;
- int sector_size, phy_sector_size;
- int fd;
-
- if (argc != 2) {
- fprintf(stderr, "usage: %s device\n", argv[0]);
- exit(EXIT_FAILURE);
- }
-
- if ((fd = open(argv[1], O_RDONLY|O_CLOEXEC)) < 0)
- err(EXIT_FAILURE, "open %s failed", argv[1]);
-
- if (blkdev_get_size(fd, &bytes) < 0)
- err(EXIT_FAILURE, "blkdev_get_size() failed");
- if (blkdev_get_sectors(fd, &sectors) < 0)
- err(EXIT_FAILURE, "blkdev_get_sectors() failed");
- if (blkdev_get_sector_size(fd, &sector_size) < 0)
- err(EXIT_FAILURE, "blkdev_get_sector_size() failed");
- if (blkdev_get_physector_size(fd, &phy_sector_size) < 0)
- err(EXIT_FAILURE, "blkdev_get_physector_size() failed");
-
- printf(" bytes: %llu\n", bytes);
- printf(" sectors: %llu\n", sectors);
- printf(" sector size: %d\n", sector_size);
- printf("phy-sector size: %d\n", phy_sector_size);
-
- return EXIT_SUCCESS;
-}
-#endif /* TEST_PROGRAM_BLKDEV */
diff --git a/utils/lib/canonicalize.c b/utils/lib/canonicalize.c
deleted file mode 100644
index e101c5b..0000000
--- a/utils/lib/canonicalize.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * canonicalize.c -- canonicalize pathname by removing symlinks
- *
- * This file may be distributed under the terms of the
- * GNU Lesser General Public License.
- *
- * Copyright (C) 2009-2013 Karel Zak <kzak@redhat.com>
- */
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-
-#include "canonicalize.h"
-#include "pathnames.h"
-#include "all-io.h"
-
-/*
- * Converts private "dm-N" names to "/dev/mapper/<name>"
- *
- * Since 2.6.29 (patch 784aae735d9b0bba3f8b9faef4c8b30df3bf0128) kernel sysfs
- * provides the real DM device names in /sys/block/<ptname>/dm/name
- */
-char *__canonicalize_dm_name(const char *prefix, const char *ptname)
-{
- FILE *f;
- size_t sz;
- char path[256], name[sizeof(path) - sizeof(_PATH_DEV_MAPPER)], *res = NULL;
-
- if (!ptname || !*ptname)
- return NULL;
-
- if (!prefix)
- prefix = "";
-
- snprintf(path, sizeof(path), "%s/sys/block/%s/dm/name", prefix, ptname);
- if (!(f = fopen(path, "r" UL_CLOEXECSTR)))
- return NULL;
-
- /* read "<name>\n" from sysfs */
- if (fgets(name, sizeof(name), f) && (sz = strlen(name)) > 1) {
- name[sz - 1] = '\0';
- snprintf(path, sizeof(path), _PATH_DEV_MAPPER "/%s", name);
-
- if ((prefix && *prefix) || access(path, F_OK) == 0)
- res = strdup(path);
- }
- fclose(f);
- return res;
-}
-
-char *canonicalize_dm_name(const char *ptname)
-{
- return __canonicalize_dm_name(NULL, ptname);
-}
-
-static int is_dm_devname(char *canonical, char **name)
-{
- struct stat sb;
- char *p = strrchr(canonical, '/');
-
- *name = NULL;
-
- if (!p
- || strncmp(p, "/dm-", 4) != 0
- || !isdigit(*(p + 4))
- || stat(canonical, &sb) != 0
- || !S_ISBLK(sb.st_mode))
- return 0;
-
- *name = p + 1;
- return 1;
-}
-
-/*
- * This function does not canonicalize the path! It just prepends CWD before a
- * relative path. If the path is no relative than returns NULL. The path does
- * not have to exist.
- */
-char *absolute_path(const char *path)
-{
- char cwd[PATH_MAX], *res, *p;
- size_t psz, csz;
-
- if (!is_relative_path(path)) {
- errno = EINVAL;
- return NULL;
- }
- if (!getcwd(cwd, sizeof(cwd)))
- return NULL;
-
- /* simple clean up */
- if (startswith(path, "./"))
- path += 2;
- else if (strcmp(path, ".") == 0)
- path = NULL;
-
- if (!path || !*path)
- return strdup(cwd);
-
- csz = strlen(cwd);
- psz = strlen(path);
-
- p = res = malloc(csz + 1 + psz + 1);
- if (!res)
- return NULL;
-
- memcpy(p, cwd, csz);
- p += csz;
- *p++ = '/';
- memcpy(p, path, psz + 1);
-
- return res;
-}
-
-char *canonicalize_path(const char *path)
-{
- char *canonical, *dmname;
-
- if (!path || !*path)
- return NULL;
-
- canonical = realpath(path, NULL);
- if (!canonical)
- return strdup(path);
-
- if (is_dm_devname(canonical, &dmname)) {
- char *dm = canonicalize_dm_name(dmname);
- if (dm) {
- free(canonical);
- return dm;
- }
- }
-
- return canonical;
-}
-
-char *canonicalize_path_restricted(const char *path)
-{
- char *canonical = NULL;
- int errsv = 0;
- int pipes[2];
- ssize_t len;
- pid_t pid;
-
- if (!path || !*path)
- return NULL;
-
- if (pipe(pipes) != 0)
- return NULL;
-
- /*
- * To accurately assume identity of getuid() we must use setuid()
- * but if we do that, we lose ability to reassume euid of 0, so
- * we fork to do the check to keep euid intact.
- */
- pid = fork();
- switch (pid) {
- case -1:
- close(pipes[0]);
- close(pipes[1]);
- return NULL; /* fork error */
- case 0:
- close(pipes[0]); /* close unused end */
- pipes[0] = -1;
- errno = 0;
-
- /* drop permissions */
- if (setgid(getgid()) < 0 || setuid(getuid()) < 0)
- canonical = NULL; /* failed */
- else {
- char *dmname = NULL;
-
- canonical = realpath(path, NULL);
- if (canonical && is_dm_devname(canonical, &dmname)) {
- char *dm = canonicalize_dm_name(dmname);
- if (dm) {
- free(canonical);
- canonical = dm;
- }
- }
- }
-
- len = canonical ? (ssize_t) strlen(canonical) :
- errno ? -errno : -EINVAL;
-
- /* send length or errno */
- write_all(pipes[1], (char *) &len, sizeof(len));
- if (canonical)
- write_all(pipes[1], canonical, len);
- exit(0);
- default:
- break;
- }
-
- close(pipes[1]); /* close unused end */
- pipes[1] = -1;
-
- /* read size or -errno */
- if (read_all(pipes[0], (char *) &len, sizeof(len)) != sizeof(len))
- goto done;
- if (len < 0) {
- errsv = -len;
- goto done;
- }
-
- canonical = malloc(len + 1);
- if (!canonical) {
- errsv = ENOMEM;
- goto done;
- }
- /* read path */
- if (read_all(pipes[0], canonical, len) != len) {
- errsv = errno;
- goto done;
- }
- canonical[len] = '\0';
-done:
- if (errsv) {
- free(canonical);
- canonical = NULL;
- }
- close(pipes[0]);
-
- /* We make a best effort to reap child */
- waitpid(pid, NULL, 0);
-
- errno = errsv;
- return canonical;
-}
-
-
-#ifdef TEST_PROGRAM_CANONICALIZE
-int main(int argc, char **argv)
-{
- if (argc < 2) {
- fprintf(stderr, "usage: %s <device>\n", argv[0]);
- exit(EXIT_FAILURE);
- }
-
- fprintf(stdout, "orig: %s\n", argv[1]);
- fprintf(stdout, "real: %s\n", canonicalize_path(argv[1]));
- exit(EXIT_SUCCESS);
-}
-#endif
diff --git a/utils/lib/caputils.c b/utils/lib/caputils.c
deleted file mode 100644
index 17e9c01..0000000
--- a/utils/lib/caputils.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.
- */
-
-#include <stdio.h>
-
-#include "caputils.h"
-#include "pathnames.h"
-
-int cap_last_cap(void)
-{
- /* CAP_LAST_CAP is untrustworthy. */
- static int ret = -1;
- int matched;
- FILE *f;
-
- if (ret != -1)
- return ret;
-
- f = fopen(_PATH_PROC_CAPLASTCAP, "r");
- if (!f) {
- ret = CAP_LAST_CAP; /* guess */
- return ret;
- }
-
- matched = fscanf(f, "%d", &ret);
- fclose(f);
-
- if (matched != 1)
- ret = CAP_LAST_CAP; /* guess */
-
- return ret;
-}
diff --git a/utils/lib/color-names.c b/utils/lib/color-names.c
deleted file mode 100644
index 9b1505e..0000000
--- a/utils/lib/color-names.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * No copyright is claimed. This code is in the public domain; do with
- * it what you wish.
- *
- * Written by Karel Zak <kzak@redhat.com>
- */
-#include "c.h"
-#include "color-names.h"
-
-struct ul_color_name {
- const char *name;
- const char *seq;
-};
-
-/*
- * qsort/bsearch buddy
- */
-static int cmp_color_name(const void *a0, const void *b0)
-{
- const struct ul_color_name
- *a = (const struct ul_color_name *) a0,
- *b = (const struct ul_color_name *) b0;
- return strcmp(a->name, b->name);
-}
-
-/*
- * Maintains human readable color names
- */
-const char *color_sequence_from_colorname(const char *str)
-{
- static const struct ul_color_name basic_schemes[] = {
- { "black", UL_COLOR_BLACK },
- { "blink", UL_COLOR_BLINK },
- { "blue", UL_COLOR_BLUE },
- { "bold", UL_COLOR_BOLD },
- { "brown", UL_COLOR_BROWN },
- { "cyan", UL_COLOR_CYAN },
- { "darkgray", UL_COLOR_DARK_GRAY },
- { "gray", UL_COLOR_GRAY },
- { "green", UL_COLOR_GREEN },
- { "halfbright", UL_COLOR_HALFBRIGHT },
- { "lightblue", UL_COLOR_BOLD_BLUE },
- { "lightcyan", UL_COLOR_BOLD_CYAN },
- { "lightgray,", UL_COLOR_GRAY },
- { "lightgreen", UL_COLOR_BOLD_GREEN },
- { "lightmagenta", UL_COLOR_BOLD_MAGENTA },
- { "lightred", UL_COLOR_BOLD_RED },
- { "magenta", UL_COLOR_MAGENTA },
- { "red", UL_COLOR_RED },
- { "reset", UL_COLOR_RESET, },
- { "reverse", UL_COLOR_REVERSE },
- { "yellow", UL_COLOR_BOLD_YELLOW },
- { "white", UL_COLOR_WHITE }
- };
- struct ul_color_name key = { .name = str }, *res;
-
- if (!str)
- return NULL;
-
- res = bsearch(&key, basic_schemes, ARRAY_SIZE(basic_schemes),
- sizeof(struct ul_color_name),
- cmp_color_name);
- return res ? res->seq : NULL;
-}
diff --git a/utils/lib/colors.c b/utils/lib/colors.c
deleted file mode 100644
index e317519..0000000
--- a/utils/lib/colors.c
+++ /dev/null
@@ -1,907 +0,0 @@
-/*
- * 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.
- */
-#include <assert.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <ctype.h>
-
-#if defined(HAVE_LIBNCURSES) || defined(HAVE_LIBNCURSESW)
-# if defined(HAVE_NCURSESW_NCURSES_H)
-# include <ncursesw/ncurses.h>
-# elif defined(HAVE_NCURSES_NCURSES_H)
-# include <ncurses/ncurses.h>
-# elif defined(HAVE_NCURSES_H)
-# include <ncurses.h>
-# endif
-# if defined(HAVE_NCURSESW_TERM_H)
-# include <ncursesw/term.h>
-# elif defined(HAVE_NCURSES_TERM_H)
-# include <ncurses/term.h>
-# elif defined(HAVE_TERM_H)
-# include <term.h>
-# endif
-#endif
-
-#include "c.h"
-#include "colors.h"
-#include "pathnames.h"
-#include "strutils.h"
-
-#include "debug.h"
-
-/*
- * Default behavior, may be overridden by terminal-colors.d/{enable,disable}.
- */
-#ifdef USE_COLORS_BY_DEFAULT
-# define UL_COLORMODE_DEFAULT UL_COLORMODE_AUTO /* check isatty() */
-#else
-# define UL_COLORMODE_DEFAULT UL_COLORMODE_NEVER /* no colors by default */
-#endif
-
-/*
- * terminal-colors.d debug stuff
- */
-static UL_DEBUG_DEFINE_MASK(termcolors);
-UL_DEBUG_DEFINE_MASKNAMES(termcolors) = UL_DEBUG_EMPTY_MASKNAMES;
-
-#define TERMCOLORS_DEBUG_INIT (1 << 1)
-#define TERMCOLORS_DEBUG_CONF (1 << 2)
-#define TERMCOLORS_DEBUG_SCHEME (1 << 3)
-#define TERMCOLORS_DEBUG_ALL 0xFFFF
-
-#define DBG(m, x) __UL_DBG(termcolors, TERMCOLORS_DEBUG_, m, x)
-#define ON_DBG(m, x) __UL_DBG_CALL(termcolors, TERMCOLORS_DEBUG_, m, x)
-
-/*
- * terminal-colors.d file types
- */
-enum {
- UL_COLORFILE_DISABLE, /* .disable */
- UL_COLORFILE_ENABLE, /* .enable */
- UL_COLORFILE_SCHEME, /* .scheme */
-
- __UL_COLORFILE_COUNT
-};
-
-struct ul_color_scheme {
- char *name;
- char *seq;
-};
-
-/*
- * Global colors control struct
- *
- * The terminal-colors.d/ evaluation is based on "scores":
- *
- * filename score
- * ---------------------------------------
- * type 1
- * @termname.type 10 + 1
- * utilname.type 20 + 1
- * utilname@termname.type 20 + 10 + 1
- *
- * the match with higher score wins. The score is per type.
- */
-struct ul_color_ctl {
- const char *utilname; /* util name */
- const char *termname; /* terminal name ($TERM) */
-
- char *sfile; /* path to scheme */
-
- struct ul_color_scheme *schemes; /* array with color schemes */
- size_t nschemes; /* number of the items */
- size_t schemes_sz; /* number of the allocated items */
-
- int mode; /* UL_COLORMODE_* */
- unsigned int has_colors : 1, /* based on mode and scores[] */
- disabled : 1, /* disable colors */
- cs_configured : 1, /* color schemes read */
- configured : 1; /* terminal-colors.d parsed */
-
- int scores[__UL_COLORFILE_COUNT]; /* the best match */
-};
-
-/*
- * Control struct, globally shared.
- */
-static struct ul_color_ctl ul_colors;
-
-static void colors_free_schemes(struct ul_color_ctl *cc);
-static int colors_read_schemes(struct ul_color_ctl *cc);
-
-/*
- * qsort/bsearch buddy
- */
-static int cmp_scheme_name(const void *a0, const void *b0)
-{
- const struct ul_color_scheme *a = (const struct ul_color_scheme *) a0,
- *b = (const struct ul_color_scheme *) b0;
- return strcmp(a->name, b->name);
-}
-
-/*
- * Resets control struct (note that we don't allocate the struct)
- */
-static void colors_reset(struct ul_color_ctl *cc)
-{
- if (!cc)
- return;
-
- colors_free_schemes(cc);
-
- free(cc->sfile);
-
- cc->sfile = NULL;
- cc->utilname = NULL;
- cc->termname = NULL;
- cc->mode = UL_COLORMODE_UNDEF;
-
- memset(cc->scores, 0, sizeof(cc->scores));
-}
-
-static void colors_debug(struct ul_color_ctl *cc)
-{
- size_t i;
-
- if (!cc)
- return;
-
- printf("Colors:\n");
- printf("\tutilname = '%s'\n", cc->utilname);
- printf("\ttermname = '%s'\n", cc->termname);
- printf("\tscheme file = '%s'\n", cc->sfile);
- printf("\tmode = %s\n",
- cc->mode == UL_COLORMODE_UNDEF ? "undefined" :
- cc->mode == UL_COLORMODE_AUTO ? "auto" :
- cc->mode == UL_COLORMODE_NEVER ? "never" :
- cc->mode == UL_COLORMODE_ALWAYS ? "always" : "???");
- printf("\thas_colors = %d\n", cc->has_colors);
- printf("\tdisabled = %d\n", cc->disabled);
- printf("\tconfigured = %d\n", cc->configured);
- printf("\tcs configured = %d\n", cc->cs_configured);
-
- fputc('\n', stdout);
-
- for (i = 0; i < ARRAY_SIZE(cc->scores); i++)
- printf("\tscore %s = %d\n",
- i == UL_COLORFILE_DISABLE ? "disable" :
- i == UL_COLORFILE_ENABLE ? "enable" :
- i == UL_COLORFILE_SCHEME ? "scheme" : "???",
- cc->scores[i]);
-
- fputc('\n', stdout);
-
- for (i = 0; i < cc->nschemes; i++) {
- printf("\tscheme #%02zu ", i);
- color_scheme_enable(cc->schemes[i].name, NULL);
- fputs(cc->schemes[i].name, stdout);
- color_disable();
- fputc('\n', stdout);
- }
- fputc('\n', stdout);
-}
-
-/*
- * Parses [[<utilname>][@<termname>].]<type>
- */
-static int filename_to_tokens(const char *str,
- const char **name, size_t *namesz,
- const char **term, size_t *termsz,
- int *filetype)
-{
- const char *type_start, *term_start, *p;
-
- if (!str || !*str || *str == '.' || strlen(str) > PATH_MAX)
- return -EINVAL;
-
- /* parse .type */
- p = strrchr(str, '.');
- type_start = p ? p + 1 : str;
-
- if (strcmp(type_start, "disable") == 0)
- *filetype = UL_COLORFILE_DISABLE;
- else if (strcmp(type_start, "enable") == 0)
- *filetype = UL_COLORFILE_ENABLE;
- else if (strcmp(type_start, "scheme") == 0)
- *filetype = UL_COLORFILE_SCHEME;
- else {
- DBG(CONF, ul_debug("unknown type '%s'", type_start));
- return 1; /* unknown type */
- }
-
- if (type_start == str)
- return 0; /* "type" only */
-
- /* parse @termname */
- p = strchr(str, '@');
- term_start = p ? p + 1 : NULL;
- if (term_start) {
- *term = term_start;
- *termsz = type_start - term_start - 1;
- if (term_start - 1 == str)
- return 0; /* "@termname.type" */
- }
-
- /* parse utilname */
- p = term_start ? term_start : type_start;
- *name = str;
- *namesz = p - str - 1;
-
- return 0;
-}
-
-/*
- * Scans @dirname and select the best matches for UL_COLORFILE_* types.
- * The result is stored to cc->scores. The path to the best "scheme"
- * file is stored to cc->scheme.
- */
-static int colors_readdir(struct ul_color_ctl *cc, const char *dirname)
-{
- DIR *dir;
- int rc = 0;
- struct dirent *d;
- char sfile[PATH_MAX] = { '\0' };
- size_t namesz, termsz;
-
- if (!dirname || !cc || !cc->utilname || !*cc->utilname)
- return -EINVAL;
-
- DBG(CONF, ul_debug("reading dir: '%s'", dirname));
-
- dir = opendir(dirname);
- if (!dir)
- return -errno;
-
- namesz = strlen(cc->utilname);
- termsz = cc->termname ? strlen(cc->termname) : 0;
-
- while ((d = readdir(dir))) {
- int type, score = 1;
- const char *tk_name = NULL, *tk_term = NULL;
- size_t tk_namesz = 0, tk_termsz = 0;
-
- if (*d->d_name == '.')
- continue;
-#ifdef _DIRENT_HAVE_D_TYPE
- if (d->d_type != DT_UNKNOWN && d->d_type != DT_LNK &&
- d->d_type != DT_REG)
- continue;
-#endif
- if (filename_to_tokens(d->d_name,
- &tk_name, &tk_namesz,
- &tk_term, &tk_termsz, &type) != 0)
- continue;
-
- /* count theoretical score before we check names to avoid
- * unnecessary strcmp() */
- if (tk_name)
- score += 20;
- if (tk_term)
- score += 10;
-
- DBG(CONF, ul_debug("item '%s': score=%d "
- "[cur: %d, name(%zu): %s, term(%zu): %s]",
- d->d_name, score, cc->scores[type],
- tk_namesz, tk_name,
- tk_termsz, tk_term));
-
-
- if (score < cc->scores[type])
- continue;
-
- /* filter out by names */
- if (tk_namesz && (tk_namesz != namesz ||
- strncmp(tk_name, cc->utilname, namesz) != 0))
- continue;
-
- if (tk_termsz && (termsz == 0 || tk_termsz != termsz ||
- strncmp(tk_term, cc->termname, termsz) != 0))
- continue;
-
- DBG(CONF, ul_debug("setting '%s' from %d -to-> %d",
- type == UL_COLORFILE_SCHEME ? "scheme" :
- type == UL_COLORFILE_DISABLE ? "disable" :
- type == UL_COLORFILE_ENABLE ? "enable" : "???",
- cc->scores[type], score));
- cc->scores[type] = score;
- if (type == UL_COLORFILE_SCHEME)
- strncpy(sfile, d->d_name, sizeof(sfile));
- }
-
- if (*sfile) {
- sfile[sizeof(sfile) - 1] = '\0';
- if (asprintf(&cc->sfile, "%s/%s", dirname, sfile) <= 0)
- rc = -ENOMEM;
- }
-
- closedir(dir);
- return rc;
-}
-
-/* atexit() wrapper */
-static void colors_deinit(void)
-{
- colors_reset(&ul_colors);
-}
-
-/*
- * Returns path to $XDG_CONFIG_HOME/terminal-colors.d
- */
-static char *colors_get_homedir(char *buf, size_t bufsz)
-{
- char *p = getenv("XDG_CONFIG_HOME");
-
- if (p) {
- snprintf(buf, bufsz, "%s/" _PATH_TERMCOLORS_DIRNAME, p);
- return buf;
- }
-
- p = getenv("HOME");
- if (p) {
- snprintf(buf, bufsz, "%s/.config/" _PATH_TERMCOLORS_DIRNAME, p);
- return buf;
- }
-
- return NULL;
-}
-
-/* canonicalize sequence */
-static int cn_sequence(const char *str, char **seq)
-{
- char *in, *out;
- int len;
-
- if (!str)
- return -EINVAL;
-
- *seq = NULL;
-
- /* convert logical names like "red" to the real sequence */
- if (*str != '\\' && isalpha(*str)) {
- const char *s = color_sequence_from_colorname(str);
- *seq = strdup(s ? s : str);
-
- return *seq ? 0 : -ENOMEM;
- }
-
- /* convert xx;yy sequences to "\033[xx;yy" */
- if ((len = asprintf(seq, "\033[%sm", str)) < 1)
- return -ENOMEM;
-
- for (in = *seq, out = *seq; in && *in; in++) {
- if (*in != '\\') {
- *out++ = *in;
- continue;
- }
- switch(*(in + 1)) {
- case 'a':
- *out++ = '\a'; /* Bell */
- break;
- case 'b':
- *out++ = '\b'; /* Backspace */
- break;
- case 'e':
- *out++ = '\033'; /* Escape */
- break;
- case 'f':
- *out++ = '\f'; /* Form Feed */
- break;
- case 'n':
- *out++ = '\n'; /* Newline */
- break;
- case 'r':
- *out++ = '\r'; /* Carriage Return */
- break;
- case 't':
- *out++ = '\t'; /* Tab */
- break;
- case 'v':
- *out++ = '\v'; /* Vertical Tab */
- break;
- case '\\':
- *out++ = '\\'; /* Backslash */
- break;
- case '_':
- *out++ = ' '; /* Space */
- break;
- case '#':
- *out++ = '#'; /* Hash mark */
- break;
- case '?':
- *out++ = '?'; /* Question mark */
- break;
- default:
- *out++ = *in;
- *out++ = *(in + 1);
- break;
- }
- in++;
- }
-
- if (out) {
- assert ((out - *seq) <= len);
- *out = '\0';
- }
-
- return 0;
-}
-
-
-/*
- * Adds one color sequence to array with color scheme.
- * When returning success (0) this function takes ownership of
- * @seq and @name, which have to be allocated strings.
- */
-static int colors_add_scheme(struct ul_color_ctl *cc,
- char *name,
- char *seq0)
-{
- struct ul_color_scheme *cs = NULL;
- char *seq = NULL;
- int rc;
-
- if (!cc || !name || !*name || !seq0 || !*seq0)
- return -EINVAL;
-
- DBG(SCHEME, ul_debug("add '%s'", name));
-
- rc = cn_sequence(seq0, &seq);
- if (rc)
- return rc;
-
- rc = -ENOMEM;
-
- /* convert logical name (e.g. "red") to real ESC code */
- if (isalpha(*seq)) {
- const char *s = color_sequence_from_colorname(seq);
- char *p;
-
- if (!s) {
- DBG(SCHEME, ul_debug("unknown logical name: %s", seq));
- rc = -EINVAL;
- goto err;
- }
-
- p = strdup(s);
- if (!p)
- goto err;
- free(seq);
- seq = p;
- }
-
- /* enlarge the array */
- if (cc->nschemes == cc->schemes_sz) {
- void *tmp = realloc(cc->schemes, (cc->nschemes + 10)
- * sizeof(struct ul_color_scheme));
- if (!tmp)
- goto err;
- cc->schemes = tmp;
- cc->schemes_sz = cc->nschemes + 10;
- }
-
- /* add a new item */
- cs = &cc->schemes[cc->nschemes];
- cs->seq = seq;
- cs->name = strdup(name);
- if (!cs->name)
- goto err;
-
- cc->nschemes++;
- return 0;
-err:
- if (cs) {
- free(cs->seq);
- free(cs->name);
- cs->seq = cs->name = NULL;
- } else
- free(seq);
- return rc;
-}
-
-/*
- * Deallocates all regards to color schemes
- */
-static void colors_free_schemes(struct ul_color_ctl *cc)
-{
- size_t i;
-
- DBG(SCHEME, ul_debug("free scheme"));
-
- for (i = 0; i < cc->nschemes; i++) {
- free(cc->schemes[i].name);
- free(cc->schemes[i].seq);
- }
-
- free(cc->schemes);
- cc->schemes = NULL;
- cc->nschemes = 0;
- cc->schemes_sz = 0;
-}
-
-/*
- * The scheme configuration has to be sorted for bsearch
- */
-static void colors_sort_schemes(struct ul_color_ctl *cc)
-{
- if (!cc->nschemes)
- return;
-
- DBG(SCHEME, ul_debug("sort scheme"));
-
- qsort(cc->schemes, cc->nschemes,
- sizeof(struct ul_color_scheme), cmp_scheme_name);
-}
-
-/*
- * Returns just one color scheme
- */
-static struct ul_color_scheme *colors_get_scheme(struct ul_color_ctl *cc,
- const char *name)
-{
- struct ul_color_scheme key = { .name = (char *) name}, *res;
-
- if (!cc || !name || !*name)
- return NULL;
-
- if (!cc->cs_configured) {
- int rc = colors_read_schemes(cc);
- if (rc)
- return NULL;
- }
- if (!cc->nschemes)
- return NULL;
-
- DBG(SCHEME, ul_debug("search '%s'", name));
-
- res = bsearch(&key, cc->schemes, cc->nschemes,
- sizeof(struct ul_color_scheme),
- cmp_scheme_name);
-
- return res && res->seq ? res : NULL;
-}
-
-/*
- * Parses filenames in terminal-colors.d
- */
-static int colors_read_configuration(struct ul_color_ctl *cc)
-{
- int rc = -ENOENT;
- char *dirname, buf[PATH_MAX];
-
- cc->termname = getenv("TERM");
-
- dirname = colors_get_homedir(buf, sizeof(buf));
- if (dirname)
- rc = colors_readdir(cc, dirname); /* ~/.config */
- if (rc == -EPERM || rc == -EACCES || rc == -ENOENT)
- rc = colors_readdir(cc, _PATH_TERMCOLORS_DIR); /* /etc */
-
- cc->configured = 1;
- return rc;
-}
-
-/*
- * Reads terminal-colors.d/ scheme file into array schemes
- */
-static int colors_read_schemes(struct ul_color_ctl *cc)
-{
- int rc = 0;
- FILE *f = NULL;
- char buf[BUFSIZ],
- cn[129], seq[129];
-
- if (!cc->configured)
- rc = colors_read_configuration(cc);
-
- cc->cs_configured = 1;
-
- if (rc || !cc->sfile)
- goto done;
-
- DBG(SCHEME, ul_debug("reading file '%s'", cc->sfile));
-
- f = fopen(cc->sfile, "r");
- if (!f) {
- rc = -errno;
- goto done;
- }
-
- while (fgets(buf, sizeof(buf), f)) {
- char *p = strchr(buf, '\n');
-
- if (!p) {
- if (feof(f))
- p = strchr(buf, '\0');
- else {
- rc = -errno;
- goto done;
- }
- }
- *p = '\0';
- p = (char *) skip_blank(buf);
- if (*p == '\0' || *p == '#')
- continue;
-
- rc = sscanf(p, "%128[^ ] %128[^\n ]", cn, seq);
- if (rc == 2 && *cn && *seq) {
- rc = colors_add_scheme(cc, cn, seq); /* set rc=0 on success */
- if (rc)
- goto done;
- }
- }
- rc = 0;
-
-done:
- if (f)
- fclose(f);
- colors_sort_schemes(cc);
-
- return rc;
-}
-
-
-static void termcolors_init_debug(void)
-{
- __UL_INIT_DEBUG_FROM_ENV(termcolors, TERMCOLORS_DEBUG_, 0, TERMINAL_COLORS_DEBUG);
-}
-
-static int colors_terminal_is_ready(void)
-{
- int ncolors = -1;
-
-#if defined(HAVE_LIBNCURSES) || defined(HAVE_LIBNCURSESW)
- {
- int ret;
-
- if (setupterm(NULL, STDOUT_FILENO, &ret) == 0 && ret == 1)
- ncolors = tigetnum("colors");
- }
-#endif
- if (1 < ncolors) {
- DBG(CONF, ul_debug("terminal is ready (supports %d colors)", ncolors));
- return 1;
- }
-
- DBG(CONF, ul_debug("terminal is NOT ready (no colors)"));
- return 0;
-}
-
-/**
- * colors_init:
- * @mode: UL_COLORMODE_*
- * @name: util argv[0]
- *
- * Initialize private color control struct and initialize the colors
- * status. The color schemes are parsed on demand by colors_get_scheme().
- *
- * Returns: >0 on success.
- */
-int colors_init(int mode, const char *name)
-{
- int ready = -1;
- struct ul_color_ctl *cc = &ul_colors;
-
- cc->utilname = name;
-
- termcolors_init_debug();
-
- if (mode != UL_COLORMODE_ALWAYS && !isatty(STDOUT_FILENO))
- cc->mode = UL_COLORMODE_NEVER;
- else
- cc->mode = mode;
-
- if (cc->mode == UL_COLORMODE_UNDEF
- && (ready = colors_terminal_is_ready())) {
- int rc = colors_read_configuration(cc);
- if (rc)
- cc->mode = UL_COLORMODE_DEFAULT;
- else {
-
- /* evaluate scores */
- if (cc->scores[UL_COLORFILE_DISABLE] >
- cc->scores[UL_COLORFILE_ENABLE])
- cc->mode = UL_COLORMODE_NEVER;
- else
- cc->mode = UL_COLORMODE_DEFAULT;
-
- atexit(colors_deinit);
- }
- }
-
- switch (cc->mode) {
- case UL_COLORMODE_AUTO:
- cc->has_colors = ready == -1 ? colors_terminal_is_ready() : ready;
- break;
- case UL_COLORMODE_ALWAYS:
- cc->has_colors = 1;
- break;
- case UL_COLORMODE_NEVER:
- default:
- cc->has_colors = 0;
- }
-
- ON_DBG(CONF, colors_debug(cc));
-
- return cc->has_colors;
-}
-
-/*
- * Temporary disable colors (this setting is independent on terminal-colors.d/)
- */
-void colors_off(void)
-{
- ul_colors.disabled = 1;
-}
-
-/*
- * Enable colors
- */
-void colors_on(void)
-{
- ul_colors.disabled = 0;
-}
-
-/*
- * Is terminal-colors.d/ configured to use colors?
- */
-int colors_wanted(void)
-{
- return ul_colors.has_colors;
-}
-
-/*
- * Returns mode
- */
-int colors_mode(void)
-{
- return ul_colors.mode;
-}
-
-/*
- * Enable @seq color
- */
-void color_fenable(const char *seq, FILE *f)
-{
- if (!ul_colors.disabled && ul_colors.has_colors && seq)
- fputs(seq, f);
-}
-
-/*
- * Returns escape sequence by logical @name, if undefined then returns @dflt.
- */
-const char *color_scheme_get_sequence(const char *name, const char *dflt)
-{
- struct ul_color_scheme *cs;
-
- if (ul_colors.disabled || !ul_colors.has_colors)
- return NULL;
-
- cs = colors_get_scheme(&ul_colors, name);
- return cs && cs->seq ? cs->seq : dflt;
-}
-
-/*
- * Enable color by logical @name, if undefined enable @dflt.
- */
-void color_scheme_fenable(const char *name, const char *dflt, FILE *f)
-{
- const char *seq = color_scheme_get_sequence(name, dflt);
-
- if (!seq)
- return;
- color_fenable(seq, f);
-}
-
-
-/*
- * Disable previously enabled color
- */
-void color_fdisable(FILE *f)
-{
- if (!ul_colors.disabled && ul_colors.has_colors)
- fputs(UL_COLOR_RESET, f);
-}
-
-/*
- * Parses @str to return UL_COLORMODE_*
- */
-int colormode_from_string(const char *str)
-{
- size_t i;
- static const char *modes[] = {
- [UL_COLORMODE_AUTO] = "auto",
- [UL_COLORMODE_NEVER] = "never",
- [UL_COLORMODE_ALWAYS] = "always",
- [UL_COLORMODE_UNDEF] = ""
- };
-
- if (!str || !*str)
- return -EINVAL;
-
- assert(ARRAY_SIZE(modes) == __UL_NCOLORMODES);
-
- for (i = 0; i < ARRAY_SIZE(modes); i++) {
- if (strcasecmp(str, modes[i]) == 0)
- return i;
- }
-
- return -EINVAL;
-}
-
-/*
- * Parses @str and exit(EXIT_FAILURE) on error
- */
-int colormode_or_err(const char *str, const char *errmsg)
-{
- const char *p = str && *str == '=' ? str + 1 : str;
- int colormode;
-
- colormode = colormode_from_string(p);
- if (colormode < 0)
- errx(EXIT_FAILURE, "%s: '%s'", errmsg, p);
-
- return colormode;
-}
-
-#ifdef TEST_PROGRAM_COLORS
-# include <getopt.h>
-int main(int argc, char *argv[])
-{
- static const struct option longopts[] = {
- { "mode", required_argument, NULL, 'm' },
- { "color", required_argument, NULL, 'c' },
- { "color-scheme", required_argument, NULL, 'C' },
- { "name", required_argument, NULL, 'n' },
- { NULL, 0, NULL, 0 }
- };
- int c, mode = UL_COLORMODE_UNDEF; /* default */
- const char *color = "red", *name = NULL, *color_scheme = NULL;
- const char *seq = NULL;
-
- while ((c = getopt_long(argc, argv, "C:c:m:n:", longopts, NULL)) != -1) {
- switch (c) {
- case 'c':
- color = optarg;
- break;
- case 'C':
- color_scheme = optarg;
- break;
- case 'm':
- mode = colormode_or_err(optarg, "unsupported color mode");
- break;
- case 'n':
- name = optarg;
- break;
- default:
- fprintf(stderr, "usage: %s [options]\n"
- " -m, --mode <auto|never|always> default is undefined\n"
- " -c, --color <red|blue|...> color for the test message\n"
- " -C, --color-scheme <name> color for the test message\n"
- " -n, --name <utilname> util name\n",
- program_invocation_short_name);
- return EXIT_FAILURE;
- }
- }
-
- colors_init(mode, name ? name : program_invocation_short_name);
-
- seq = color_sequence_from_colorname(color);
-
- if (color_scheme)
- color_scheme_enable(color_scheme, seq);
- else
- color_enable(seq);
- printf("Hello World!");
- color_disable();
- fputc('\n', stdout);
-
- return EXIT_SUCCESS;
-}
-#endif /* TEST_PROGRAM_COLORS */
-
diff --git a/utils/lib/cpuset.c b/utils/lib/cpuset.c
deleted file mode 100644
index 2847db8..0000000
--- a/utils/lib/cpuset.c
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- * Terminology:
- *
- * cpuset - (libc) cpu_set_t data structure represents set of CPUs
- * cpumask - string with hex mask (e.g. "0x00000001")
- * cpulist - string with CPU ranges (e.g. "0-3,5,7,8")
- *
- * Based on code from taskset.c and Linux kernel.
- *
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- *
- * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sched.h>
-#include <errno.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/syscall.h>
-
-#include "cpuset.h"
-#include "c.h"
-
-static inline int val_to_char(int v)
-{
- if (v >= 0 && v < 10)
- return '0' + v;
- if (v >= 10 && v < 16)
- return ('a' - 10) + v;
- return -1;
-}
-
-static inline int char_to_val(int c)
-{
- int cl;
-
- if (c >= '0' && c <= '9')
- return c - '0';
- cl = tolower(c);
- if (cl >= 'a' && cl <= 'f')
- return cl + (10 - 'a');
- return -1;
-}
-
-static const char *nexttoken(const char *q, int sep)
-{
- if (q)
- q = strchr(q, sep);
- if (q)
- q++;
- return q;
-}
-
-/*
- * Number of bits in a CPU bitmask on current system
- */
-int get_max_number_of_cpus(void)
-{
-#ifdef SYS_sched_getaffinity
- int n, cpus = 2048;
- size_t setsize;
- cpu_set_t *set = cpuset_alloc(cpus, &setsize, NULL);
-
- if (!set)
- return -1; /* error */
-
- for (;;) {
- CPU_ZERO_S(setsize, set);
-
- /* the library version does not return size of cpumask_t */
- n = syscall(SYS_sched_getaffinity, 0, setsize, set);
-
- if (n < 0 && errno == EINVAL && cpus < 1024 * 1024) {
- cpuset_free(set);
- cpus *= 2;
- set = cpuset_alloc(cpus, &setsize, NULL);
- if (!set)
- return -1; /* error */
- continue;
- }
- cpuset_free(set);
- return n * 8;
- }
-#endif
- return -1;
-}
-
-/*
- * Allocates a new set for ncpus and returns size in bytes and size in bits
- */
-cpu_set_t *cpuset_alloc(int ncpus, size_t *setsize, size_t *nbits)
-{
- cpu_set_t *set = CPU_ALLOC(ncpus);
-
- if (!set)
- return NULL;
- if (setsize)
- *setsize = CPU_ALLOC_SIZE(ncpus);
- if (nbits)
- *nbits = cpuset_nbits(CPU_ALLOC_SIZE(ncpus));
- return set;
-}
-
-void cpuset_free(cpu_set_t *set)
-{
- CPU_FREE(set);
-}
-
-#if !HAVE_DECL_CPU_ALLOC
-/* Please, use CPU_COUNT_S() macro. This is fallback */
-int __cpuset_count_s(size_t setsize, const cpu_set_t *set)
-{
- int s = 0;
- const __cpu_mask *p = set->__bits;
- const __cpu_mask *end = &set->__bits[setsize / sizeof (__cpu_mask)];
-
- while (p < end) {
- __cpu_mask l = *p++;
-
- if (l == 0)
- continue;
-# if LONG_BIT > 32
- l = (l & 0x5555555555555555ul) + ((l >> 1) & 0x5555555555555555ul);
- l = (l & 0x3333333333333333ul) + ((l >> 2) & 0x3333333333333333ul);
- l = (l & 0x0f0f0f0f0f0f0f0ful) + ((l >> 4) & 0x0f0f0f0f0f0f0f0ful);
- l = (l & 0x00ff00ff00ff00fful) + ((l >> 8) & 0x00ff00ff00ff00fful);
- l = (l & 0x0000ffff0000fffful) + ((l >> 16) & 0x0000ffff0000fffful);
- l = (l & 0x00000000fffffffful) + ((l >> 32) & 0x00000000fffffffful);
-# else
- l = (l & 0x55555555ul) + ((l >> 1) & 0x55555555ul);
- l = (l & 0x33333333ul) + ((l >> 2) & 0x33333333ul);
- l = (l & 0x0f0f0f0ful) + ((l >> 4) & 0x0f0f0f0ful);
- l = (l & 0x00ff00fful) + ((l >> 8) & 0x00ff00fful);
- l = (l & 0x0000fffful) + ((l >> 16) & 0x0000fffful);
-# endif
- s += l;
- }
- return s;
-}
-#endif
-
-/*
- * Returns human readable representation of the cpuset. The output format is
- * a list of CPUs with ranges (for example, "0,1,3-9").
- */
-char *cpulist_create(char *str, size_t len,
- cpu_set_t *set, size_t setsize)
-{
- size_t i;
- char *ptr = str;
- int entry_made = 0;
- size_t max = cpuset_nbits(setsize);
-
- for (i = 0; i < max; i++) {
- if (CPU_ISSET_S(i, setsize, set)) {
- int rlen;
- size_t j, run = 0;
- entry_made = 1;
- for (j = i + 1; j < max; j++) {
- if (CPU_ISSET_S(j, setsize, set))
- run++;
- else
- break;
- }
- if (!run)
- rlen = snprintf(ptr, len, "%zu,", i);
- else if (run == 1) {
- rlen = snprintf(ptr, len, "%zu,%zu,", i, i + 1);
- i++;
- } else {
- rlen = snprintf(ptr, len, "%zu-%zu,", i, i + run);
- i += run;
- }
- if (rlen < 0 || (size_t) rlen >= len)
- return NULL;
- ptr += rlen;
- len -= rlen;
- }
- }
- ptr -= entry_made;
- *ptr = '\0';
-
- return str;
-}
-
-/*
- * Returns string with CPU mask.
- */
-char *cpumask_create(char *str, size_t len,
- cpu_set_t *set, size_t setsize)
-{
- char *ptr = str;
- char *ret = NULL;
- int cpu;
-
- for (cpu = cpuset_nbits(setsize) - 4; cpu >= 0; cpu -= 4) {
- char val = 0;
-
- if (len == (size_t) (ptr - str))
- break;
-
- if (CPU_ISSET_S(cpu, setsize, set))
- val |= 1;
- if (CPU_ISSET_S(cpu + 1, setsize, set))
- val |= 2;
- if (CPU_ISSET_S(cpu + 2, setsize, set))
- val |= 4;
- if (CPU_ISSET_S(cpu + 3, setsize, set))
- val |= 8;
-
- if (!ret && val)
- ret = ptr;
- *ptr++ = val_to_char(val);
- }
- *ptr = '\0';
- return ret ? ret : ptr - 1;
-}
-
-/*
- * Parses string with CPUs mask.
- */
-int cpumask_parse(const char *str, cpu_set_t *set, size_t setsize)
-{
- int len = strlen(str);
- const char *ptr = str + len - 1;
- int cpu = 0;
-
- /* skip 0x, it's all hex anyway */
- if (len > 1 && !memcmp(str, "0x", 2L))
- str += 2;
-
- CPU_ZERO_S(setsize, set);
-
- while (ptr >= str) {
- char val;
-
- /* cpu masks in /sys uses comma as a separator */
- if (*ptr == ',')
- ptr--;
-
- val = char_to_val(*ptr);
- if (val == (char) -1)
- return -1;
- if (val & 1)
- CPU_SET_S(cpu, setsize, set);
- if (val & 2)
- CPU_SET_S(cpu + 1, setsize, set);
- if (val & 4)
- CPU_SET_S(cpu + 2, setsize, set);
- if (val & 8)
- CPU_SET_S(cpu + 3, setsize, set);
- ptr--;
- cpu += 4;
- }
-
- return 0;
-}
-
-static int nextnumber(const char *str, char **end, unsigned int *result)
-{
- errno = 0;
- if (str == NULL || *str == '\0' || !isdigit(*str))
- return -EINVAL;
- *result = (unsigned int) strtoul(str, end, 10);
- if (errno)
- return -errno;
- if (str == *end)
- return -EINVAL;
- return 0;
-}
-
-/*
- * Parses string with list of CPU ranges.
- * Returns 0 on success.
- * Returns 1 on error.
- * Returns 2 if fail is set and a cpu number passed in the list doesn't fit
- * into the cpu_set. If fail is not set cpu numbers that do not fit are
- * ignored and 0 is returned instead.
- */
-int cpulist_parse(const char *str, cpu_set_t *set, size_t setsize, int fail)
-{
- size_t max = cpuset_nbits(setsize);
- const char *p, *q;
- char *end = NULL;
-
- q = str;
- CPU_ZERO_S(setsize, set);
-
- while (p = q, q = nexttoken(q, ','), p) {
- unsigned int a; /* beginning of range */
- unsigned int b; /* end of range */
- unsigned int s; /* stride */
- const char *c1, *c2;
-
- if (nextnumber(p, &end, &a) != 0)
- return 1;
- b = a;
- s = 1;
- p = end;
-
- c1 = nexttoken(p, '-');
- c2 = nexttoken(p, ',');
-
- if (c1 != NULL && (c2 == NULL || c1 < c2)) {
- if (nextnumber(c1, &end, &b) != 0)
- return 1;
-
- c1 = end && *end ? nexttoken(end, ':') : NULL;
-
- if (c1 != NULL && (c2 == NULL || c1 < c2)) {
- if (nextnumber(c1, &end, &s) != 0)
- return 1;
- if (s == 0)
- return 1;
- }
- }
-
- if (!(a <= b))
- return 1;
- while (a <= b) {
- if (fail && (a >= max))
- return 2;
- CPU_SET_S(a, setsize, set);
- a += s;
- }
- }
-
- if (end && *end)
- return 1;
- return 0;
-}
-
-#ifdef TEST_PROGRAM_CPUSET
-
-#include <getopt.h>
-
-int main(int argc, char *argv[])
-{
- cpu_set_t *set;
- size_t setsize, buflen, nbits;
- char *buf, *mask = NULL, *range = NULL;
- int ncpus = 2048, rc, c;
-
- static const struct option longopts[] = {
- { "ncpus", 1, NULL, 'n' },
- { "mask", 1, NULL, 'm' },
- { "range", 1, NULL, 'r' },
- { NULL, 0, NULL, 0 }
- };
-
- while ((c = getopt_long(argc, argv, "n:m:r:", longopts, NULL)) != -1) {
- switch(c) {
- case 'n':
- ncpus = atoi(optarg);
- break;
- case 'm':
- mask = strdup(optarg);
- break;
- case 'r':
- range = strdup(optarg);
- break;
- default:
- goto usage_err;
- }
- }
-
- if (!mask && !range)
- goto usage_err;
-
- set = cpuset_alloc(ncpus, &setsize, &nbits);
- if (!set)
- err(EXIT_FAILURE, "failed to allocate cpu set");
-
- /*
- fprintf(stderr, "ncpus: %d, cpuset bits: %zd, cpuset bytes: %zd\n",
- ncpus, nbits, setsize);
- */
-
- buflen = 7 * nbits;
- buf = malloc(buflen);
- if (!buf)
- err(EXIT_FAILURE, "failed to allocate cpu set buffer");
-
- if (mask)
- rc = cpumask_parse(mask, set, setsize);
- else
- rc = cpulist_parse(range, set, setsize, 0);
-
- if (rc)
- errx(EXIT_FAILURE, "failed to parse string: %s", mask ? : range);
-
- printf("%-15s = %15s ", mask ? : range,
- cpumask_create(buf, buflen, set, setsize));
- printf("[%s]\n", cpulist_create(buf, buflen, set, setsize));
-
- free(buf);
- free(mask);
- free(range);
- cpuset_free(set);
-
- return EXIT_SUCCESS;
-
-usage_err:
- fprintf(stderr,
- "usage: %s [--ncpus <num>] --mask <mask> | --range <list>\n",
- program_invocation_short_name);
- exit(EXIT_FAILURE);
-}
-#endif
diff --git a/utils/lib/crc32.c b/utils/lib/crc32.c
deleted file mode 100644
index 824693d..0000000
--- a/utils/lib/crc32.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
- * code or tables extracted from it, as desired without restriction.
- *
- * First, the polynomial itself and its table of feedback terms. The
- * polynomial is
- * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
- *
- * Note that we take it "backwards" and put the highest-order term in
- * the lowest-order bit. The X^32 term is "implied"; the LSB is the
- * X^31 term, etc. The X^0 term (usually shown as "+1") results in
- * the MSB being 1.
- *
- * Note that the usual hardware shift register implementation, which
- * is what we're using (we're merely optimizing it by doing eight-bit
- * chunks at a time) shifts bits into the lowest-order term. In our
- * implementation, that means shifting towards the right. Why do we
- * do it this way? Because the calculated CRC must be transmitted in
- * order from highest-order term to lowest-order term. UARTs transmit
- * characters in order from LSB to MSB. By storing the CRC this way,
- * we hand it to the UART in the order low-byte to high-byte; the UART
- * sends each low-bit to high-bit; and the result is transmission bit
- * by bit from highest- to lowest-order term without requiring any bit
- * shuffling on our part. Reception works similarly.
- *
- * The feedback terms table consists of 256, 32-bit entries. Notes
- *
- * The table can be generated at runtime if desired; code to do so
- * is shown later. It might not be obvious, but the feedback
- * terms simply represent the results of eight shift/xor opera-
- * tions for all combinations of data and CRC register values.
- *
- * The values must be right-shifted by eight bits by the "updcrc"
- * logic; the shift must be unsigned (bring in zeroes). On some
- * hardware you could probably optimize the shift in assembler by
- * using byte-swap instructions.
- * polynomial $edb88320
- *
- */
-
-#include <stdio.h>
-
-#include "crc32.h"
-
-
-static const uint32_t crc32_tab[] = {
- 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
- 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
- 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
- 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
- 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
- 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
- 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
- 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
- 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
- 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
- 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
- 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
- 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
- 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
- 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
- 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
- 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
- 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
- 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
- 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
- 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
- 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
- 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
- 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
- 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
- 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
- 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
- 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
- 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
- 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
- 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
- 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
- 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
- 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
- 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
- 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
- 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
- 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
- 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
- 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
- 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
- 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
- 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
- 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
- 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
- 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
- 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
- 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
- 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
- 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
- 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
- 0x2d02ef8dL
-};
-
-static inline uint32_t crc32_add_char(uint32_t crc, unsigned char c)
-{
- return crc32_tab[(crc ^ c) & 0xff] ^ (crc >> 8);
-}
-
-/*
- * This a generic crc32() function, it takes seed as an argument,
- * and does __not__ xor at the end. Then individual users can do
- * whatever they need.
- */
-uint32_t ul_crc32(uint32_t seed, const unsigned char *buf, size_t len)
-{
- uint32_t crc = seed;
- const unsigned char *p = buf;
-
- while (len) {
- crc = crc32_add_char(crc, *p++);
- len--;
- }
-
- return crc;
-}
-
-uint32_t ul_crc32_exclude_offset(uint32_t seed, const unsigned char *buf, size_t len,
- size_t exclude_off, size_t exclude_len)
-{
- uint32_t crc = seed;
- const unsigned char *p = buf;
- size_t i;
-
- for (i = 0; i < len; i++) {
- unsigned char x = *p++;
-
- if (i >= exclude_off && i < exclude_off + exclude_len)
- x = 0;
-
- crc = crc32_add_char(crc, x);
- }
-
- return crc;
-}
-
diff --git a/utils/lib/crc32c.c b/utils/lib/crc32c.c
deleted file mode 100644
index 49e7543..0000000
--- a/utils/lib/crc32c.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * This code is from freebsd/sys/libkern/crc32.c
- *
- * Simplest table-based crc32c. Performance is not important
- * for checking crcs on superblocks
- */
-
-/*-
- * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
- * code or tables extracted from it, as desired without restriction.
- */
-
-#include "crc32c.h"
-
-static const uint32_t crc32Table[256] = {
- 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
- 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
- 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
- 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
- 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
- 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
- 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
- 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
- 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
- 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
- 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
- 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
- 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
- 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
- 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
- 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
- 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
- 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
- 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
- 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
- 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
- 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
- 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
- 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
- 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
- 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
- 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
- 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
- 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
- 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
- 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
- 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
- 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
- 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
- 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
- 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
- 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
- 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
- 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
- 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
- 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
- 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
- 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
- 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
- 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
- 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
- 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
- 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
- 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
- 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
- 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
- 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
- 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
- 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
- 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
- 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
- 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
- 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
- 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
- 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
- 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
- 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
- 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
- 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
-};
-
-/*
- *This was singletable_crc32c() in bsd
- *
- * If you will not be passing crc back into this function to process more bytes,
- * the answer is:
- *
- * crc = crc32c(~0L, buf, size);
- * [ crc = crc32c(crc, buf, size); ]
- * crc ^= ~0L
- *
- */
-uint32_t
-crc32c(uint32_t crc, const void *buf, size_t size)
-{
- const uint8_t *p = buf;
-
- while (size--)
- crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
-
- return crc;
-}
diff --git a/utils/lib/encode.c b/utils/lib/encode.c
deleted file mode 100644
index 10b5971..0000000
--- a/utils/lib/encode.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Based on code from libblkid,
- *
- * Copyright (C) 2008 Kay Sievers <kay.sievers@vrfy.org>
- * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
- * Copyright (C) 2020 Pali Rohár <pali.rohar@gmail.com>
- *
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- */
-#include "c.h"
-#include "encode.h"
-
-size_t ul_encode_to_utf8(int enc, unsigned char *dest, size_t len,
- const unsigned char *src, size_t count)
-{
- size_t i, j;
- uint32_t c;
- uint16_t c2;
-
- for (j = i = 0; i < count; i++) {
- if (enc == UL_ENCODE_UTF16LE) {
- if (i+2 > count)
- break;
- c = (src[i+1] << 8) | src[i];
- i++;
- } else if (enc == UL_ENCODE_UTF16BE) {
- if (i+2 > count)
- break;
- c = (src[i] << 8) | src[i+1];
- i++;
- } else if (enc == UL_ENCODE_LATIN1) {
- c = src[i];
- } else {
- return 0;
- }
- if ((enc == UL_ENCODE_UTF16LE || enc == UL_ENCODE_UTF16BE) &&
- c >= 0xD800 && c <= 0xDBFF && i+2 < count) {
- if (enc == UL_ENCODE_UTF16LE)
- c2 = (src[i+2] << 8) | src[i+1];
- else
- c2 = (src[i+1] << 8) | src[i+2];
- if (c2 >= 0xDC00 && c2 <= 0xDFFF) {
- c = 0x10000 + ((c - 0xD800) << 10) + (c2 - 0xDC00);
- i += 2;
- }
- }
- if (c == 0) {
- dest[j] = '\0';
- break;
- }
-
- if (c < 0x80) {
- if (j+1 >= len)
- break;
- dest[j++] = (uint8_t) c;
- } else if (c < 0x800) {
- if (j+2 >= len)
- break;
- dest[j++] = (uint8_t) (0xc0 | (c >> 6));
- dest[j++] = (uint8_t) (0x80 | (c & 0x3f));
- } else if (c < 0x10000) {
- if (j+3 >= len)
- break;
- dest[j++] = (uint8_t) (0xe0 | (c >> 12));
- dest[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f));
- dest[j++] = (uint8_t) (0x80 | (c & 0x3f));
- } else {
- if (j+4 >= len)
- break;
- dest[j++] = (uint8_t) (0xf0 | (c >> 18));
- dest[j++] = (uint8_t) (0x80 | ((c >> 12) & 0x3f));
- dest[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f));
- dest[j++] = (uint8_t) (0x80 | (c & 0x3f));
- }
- }
- dest[j] = '\0';
- return j;
-}
diff --git a/utils/lib/env.c b/utils/lib/env.c
deleted file mode 100644
index c26a5be..0000000
--- a/utils/lib/env.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Security checks of environment
- * Added from shadow-utils package
- * by Arkadiusz Miśkiewicz <misiek@pld.ORG.PL>
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_SYS_PRCTL_H
-#include <sys/prctl.h>
-#else
-#define PR_GET_DUMPABLE 3
-#endif
-#if (!defined(HAVE_PRCTL) && defined(linux))
-#include <sys/syscall.h>
-#endif
-#include <unistd.h>
-#include <sys/types.h>
-
-#include "env.h"
-
-#ifndef HAVE_ENVIRON_DECL
-extern char **environ;
-#endif
-
-static char * const forbid[] = {
- "BASH_ENV=", /* GNU creeping featurism strikes again... */
- "ENV=",
- "HOME=",
- "IFS=",
- "KRB_CONF=",
- "LD_", /* anything with the LD_ prefix */
- "LIBPATH=",
- "MAIL=",
- "NLSPATH=",
- "PATH=",
- "SHELL=",
- "SHLIB_PATH=",
- (char *) 0
-};
-
-/* these are allowed, but with no slashes inside
- (to work around security problems in GNU gettext) */
-static char * const noslash[] = {
- "LANG=",
- "LANGUAGE=",
- "LC_", /* anything with the LC_ prefix */
- (char *) 0
-};
-
-
-struct ul_env_list {
- char *env;
- struct ul_env_list *next;
-};
-
-/*
- * Saves @name env.varable to @ls, returns pointer to the new head of the list.
- */
-static struct ul_env_list *env_list_add(struct ul_env_list *ls0, const char *str)
-{
- struct ul_env_list *ls;
- char *p;
- size_t sz = 0;
-
- if (!str || !*str)
- return ls0;
-
- sz = strlen(str) + 1;
- p = malloc(sizeof(struct ul_env_list) + sz);
-
- ls = (struct ul_env_list *) p;
- p += sizeof(struct ul_env_list);
- memcpy(p, str, sz);
- ls->env = p;
-
- ls->next = ls0;
- return ls;
-}
-
-/*
- * Use setenv() for all stuff in @ls.
- *
- * It would be possible to use putenv(), but we want to keep @ls free()-able.
- */
-int env_list_setenv(struct ul_env_list *ls)
-{
- int rc = 0;
-
- while (ls && rc == 0) {
- if (ls->env) {
- char *val = strchr(ls->env, '=');
- if (!val)
- continue;
- *val = '\0';
- rc = setenv(ls->env, val + 1, 0);
- *val = '=';
- }
- ls = ls->next;
- }
- return rc;
-}
-
-void env_list_free(struct ul_env_list *ls)
-{
- while (ls) {
- struct ul_env_list *x = ls;
- ls = ls->next;
- free(x);
- }
-}
-
-/*
- * Removes unwanted variables from environ[]. If @ls is not NULL than stores
- * unwnated variables to the list.
- */
-void __sanitize_env(struct ul_env_list **org)
-{
- char **envp = environ;
- char * const *bad;
- char **cur;
- int last = 0;
-
- for (cur = envp; *cur; cur++)
- last++;
-
- for (cur = envp; *cur; cur++) {
- for (bad = forbid; *bad; bad++) {
- if (strncmp(*cur, *bad, strlen(*bad)) == 0) {
- if (org)
- *org = env_list_add(*org, *cur);
- last = remote_entry(envp, cur - envp, last);
- cur--;
- break;
- }
- }
- }
-
- for (cur = envp; *cur; cur++) {
- for (bad = noslash; *bad; bad++) {
- if (strncmp(*cur, *bad, strlen(*bad)) != 0)
- continue;
- if (!strchr(*cur, '/'))
- continue; /* OK */
- if (org)
- *org = env_list_add(*org, *cur);
- last = remote_entry(envp, cur - envp, last);
- cur--;
- break;
- }
- }
-}
-
-void sanitize_env(void)
-{
- __sanitize_env(NULL);
-}
-
-char *safe_getenv(const char *arg)
-{
- uid_t ruid = getuid();
-
- if (ruid != 0 || (ruid != geteuid()) || (getgid() != getegid()))
- return NULL;
-#ifdef HAVE_PRCTL
- if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0)
- return NULL;
-#else
-#if (defined(linux) && defined(SYS_prctl))
- if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0)
- return NULL;
-#endif
-#endif
-#ifdef HAVE_SECURE_GETENV
-return secure_getenv(arg);
-#elif HAVE___SECURE_GETENV
- return __secure_getenv(arg);
-#else
- return getenv(arg);
-#endif
-}
-
-#ifdef TEST_PROGRAM
-int main(void)
-{
- char *const *bad;
- char copy[32];
- char *p;
- int retval = EXIT_SUCCESS;
- struct ul_env_list *removed = NULL;
-
- for (bad = forbid; *bad; bad++) {
- strcpy(copy, *bad);
- p = strchr(copy, '=');
- if (p)
- *p = '\0';
- setenv(copy, copy, 1);
- }
-
- /* removed */
- __sanitize_env(&removed);
-
- /* check removal */
- for (bad = forbid; *bad; bad++) {
- strcpy(copy, *bad);
- p = strchr(copy, '=');
- if (p)
- *p = '\0';
- p = getenv(copy);
- if (p) {
- warnx("%s was not removed", copy);
- retval = EXIT_FAILURE;
- }
- }
-
- /* restore removed */
- env_list_setenv(removed);
-
- /* check restore */
- for (bad = forbid; *bad; bad++) {
- strcpy(copy, *bad);
- p = strchr(copy, '=');
- if (p)
- *p = '\0';
- p = getenv(copy);
- if (!p) {
- warnx("%s was not restored", copy);
- retval = EXIT_FAILURE;
- }
- }
-
- env_list_free(removed);
-
- return retval;
-}
-#endif
diff --git a/utils/lib/exec_shell.c b/utils/lib/exec_shell.c
deleted file mode 100644
index 18798eb..0000000
--- a/utils/lib/exec_shell.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * exec_shell() - launch a shell, else exit!
- *
- * 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.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <libgen.h>
-
-#include "nls.h"
-#include "c.h"
-#include "xalloc.h"
-
-#include "exec_shell.h"
-
-#define DEFAULT_SHELL "/bin/sh"
-
-void __attribute__((__noreturn__)) exec_shell(void)
-{
- const char *shell = getenv("SHELL");
- char *shellc;
- const char *shell_basename;
- char *arg0;
-
- if (!shell)
- shell = DEFAULT_SHELL;
-
- shellc = xstrdup(shell);
- shell_basename = basename(shellc);
- arg0 = xmalloc(strlen(shell_basename) + 2);
- arg0[0] = '-';
- strcpy(arg0 + 1, shell_basename);
-
- execl(shell, arg0, NULL);
- errexec(shell);
-}
diff --git a/utils/lib/fileutils.c b/utils/lib/fileutils.c
deleted file mode 100644
index 3ca43c1..0000000
--- a/utils/lib/fileutils.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (C) 2012 Sami Kerola <kerolasa@iki.fi>
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-
-#include "c.h"
-#include "fileutils.h"
-#include "pathnames.h"
-
-int mkstemp_cloexec(char *template)
-{
-#ifdef HAVE_MKOSTEMP
- return mkostemp(template, O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC);
-#else
- int fd, old_flags, errno_save;
-
- fd = mkstemp(template);
- if (fd < 0)
- return fd;
-
- old_flags = fcntl(fd, F_GETFD, 0);
- if (old_flags < 0)
- goto unwind;
- if (fcntl(fd, F_SETFD, old_flags | O_CLOEXEC) < 0)
- goto unwind;
-
- return fd;
-
-unwind:
- errno_save = errno;
- unlink(template);
- close(fd);
- errno = errno_save;
-
- return -1;
-#endif
-}
-
-/* Create open temporary file in safe way. Please notice that the
- * file permissions are -rw------- by default. */
-int xmkstemp(char **tmpname, const char *dir, const char *prefix)
-{
- char *localtmp;
- const char *tmpenv;
- mode_t old_mode;
- int fd, rc;
-
- /* Some use cases must be capable of being moved atomically
- * with rename(2), which is the reason why dir is here. */
- tmpenv = dir ? dir : getenv("TMPDIR");
- if (!tmpenv)
- tmpenv = _PATH_TMP;
-
- rc = asprintf(&localtmp, "%s/%s.XXXXXX", tmpenv, prefix);
- if (rc < 0)
- return -1;
-
- old_mode = umask(077);
- fd = mkstemp_cloexec(localtmp);
- umask(old_mode);
- if (fd == -1) {
- free(localtmp);
- localtmp = NULL;
- }
- *tmpname = localtmp;
- return fd;
-}
-
-int dup_fd_cloexec(int oldfd, int lowfd)
-{
- int fd, flags, errno_save;
-
-#ifdef F_DUPFD_CLOEXEC
- fd = fcntl(oldfd, F_DUPFD_CLOEXEC, lowfd);
- if (fd >= 0)
- return fd;
-#endif
-
- fd = dup(oldfd);
- if (fd < 0)
- return fd;
-
- flags = fcntl(fd, F_GETFD);
- if (flags < 0)
- goto unwind;
- if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
- goto unwind;
-
- return fd;
-
-unwind:
- errno_save = errno;
- close(fd);
- errno = errno_save;
-
- return -1;
-}
-
-/*
- * portable getdtablesize()
- */
-int get_fd_tabsize(void)
-{
- int m;
-
-#if defined(HAVE_GETDTABLESIZE)
- m = getdtablesize();
-#elif defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
- struct rlimit rl;
-
- getrlimit(RLIMIT_NOFILE, &rl);
- m = rl.rlim_cur;
-#elif defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
- m = sysconf(_SC_OPEN_MAX);
-#else
- m = OPEN_MAX;
-#endif
- return m;
-}
-
-static inline int in_set(int x, const int set[], size_t setsz)
-{
- size_t i;
-
- for (i = 0; i < setsz; i++) {
- if (set[i] == x)
- return 1;
- }
- return 0;
-}
-
-void close_all_fds(const int exclude[], size_t exsz)
-{
- struct dirent *d;
- DIR *dir;
-
- dir = opendir(_PATH_PROC_FDDIR);
- if (dir) {
- while ((d = xreaddir(dir))) {
- char *end;
- int fd;
-
- errno = 0;
- fd = strtol(d->d_name, &end, 10);
-
- if (errno || end == d->d_name || !end || *end)
- continue;
- if (dirfd(dir) == fd)
- continue;
- if (in_set(fd, exclude, exsz))
- continue;
- close(fd);
- }
- closedir(dir);
- } else {
- int fd, tbsz = get_fd_tabsize();
-
- for (fd = 0; fd < tbsz; fd++) {
- if (!in_set(fd, exclude, exsz))
- close(fd);
- }
- }
-}
-
-#ifdef TEST_PROGRAM_FILEUTILS
-int main(int argc, char *argv[])
-{
- if (argc < 2)
- errx(EXIT_FAILURE, "Usage %s --{mkstemp,close-fds}", argv[0]);
-
- if (strcmp(argv[1], "--mkstemp") == 0) {
- FILE *f;
- char *tmpname;
- f = xfmkstemp(&tmpname, NULL, "test");
- unlink(tmpname);
- free(tmpname);
- fclose(f);
-
- } else if (strcmp(argv[1], "--close-fds") == 0) {
- static const int wanted_fds[] = {
- STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO
- };
-
- ignore_result( dup(STDIN_FILENO) );
- ignore_result( dup(STDIN_FILENO) );
- ignore_result( dup(STDIN_FILENO) );
-
- close_all_fds(wanted_fds, ARRAY_SIZE(wanted_fds));
- }
- return EXIT_SUCCESS;
-}
-#endif
-
-
-int mkdir_p(const char *path, mode_t mode)
-{
- char *p, *dir;
- int rc = 0;
-
- if (!path || !*path)
- return -EINVAL;
-
- dir = p = strdup(path);
- if (!dir)
- return -ENOMEM;
-
- if (*p == '/')
- p++;
-
- while (p && *p) {
- char *e = strchr(p, '/');
- if (e)
- *e = '\0';
- if (*p) {
- rc = mkdir(dir, mode);
- if (rc && errno != EEXIST)
- break;
- rc = 0;
- }
- if (!e)
- break;
- *e = '/';
- p = e + 1;
- }
-
- free(dir);
- return rc;
-}
-
-/* returns basename and keeps dirname in the @path, if @path is "/" (root)
- * then returns empty string */
-char *stripoff_last_component(char *path)
-{
- char *p = path ? strrchr(path, '/') : NULL;
-
- if (!p)
- return NULL;
- *p = '\0';
- return p + 1;
-}
diff --git a/utils/lib/idcache.c b/utils/lib/idcache.c
deleted file mode 100644
index 5550223..0000000
--- a/utils/lib/idcache.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * No copyright is claimed. This code is in the public domain; do with
- * it what you wish.
- *
- * Written by Karel Zak <kzak@redhat.com>
- */
-#include <wchar.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/types.h>
-
-#include "c.h"
-#include "idcache.h"
-
-struct identry *get_id(struct idcache *ic, unsigned long int id)
-{
- struct identry *ent;
-
- if (!ic)
- return NULL;
-
- for (ent = ic->ent; ent; ent = ent->next) {
- if (ent->id == id)
- return ent;
- }
-
- return NULL;
-}
-
-struct idcache *new_idcache(void)
-{
- return calloc(1, sizeof(struct idcache));
-}
-
-void free_idcache(struct idcache *ic)
-{
- struct identry *ent = ic->ent;
-
- while (ent) {
- struct identry *next = ent->next;
- free(ent->name);
- free(ent);
- ent = next;
- }
-
- free(ic);
-}
-
-static void add_id(struct idcache *ic, char *name, unsigned long int id)
-{
- struct identry *ent, *x;
- int w = 0;
-
- ent = calloc(1, sizeof(struct identry));
- if (!ent)
- return;
- ent->id = id;
-
- if (name) {
-#ifdef HAVE_WIDECHAR
- wchar_t wc[LOGIN_NAME_MAX + 1];
-
- if (mbstowcs(wc, name, LOGIN_NAME_MAX) > 0) {
- wc[LOGIN_NAME_MAX] = '\0';
- w = wcswidth(wc, LOGIN_NAME_MAX);
- }
- else
-#endif
- w = strlen(name);
- }
-
- /* note, we ignore names with non-printable widechars */
- if (w > 0) {
- ent->name = strdup(name);
- if (!ent->name) {
- free(ent);
- return;
- }
- } else {
- if (asprintf(&ent->name, "%lu", id) < 0) {
- free(ent);
- return;
- }
- }
-
- for (x = ic->ent; x && x->next; x = x->next);
-
- if (x)
- x->next = ent;
- else
- ic->ent = ent;
-
- if (w <= 0)
- w = ent->name ? strlen(ent->name) : 0;
- ic->width = ic->width < w ? w : ic->width;
-}
-
-void add_uid(struct idcache *cache, unsigned long int id)
-{
- struct identry *ent= get_id(cache, id);
-
- if (!ent) {
- struct passwd *pw = getpwuid((uid_t) id);
- add_id(cache, pw ? pw->pw_name : NULL, id);
- }
-}
-
-void add_gid(struct idcache *cache, unsigned long int id)
-{
- struct identry *ent = get_id(cache, id);
-
- if (!ent) {
- struct group *gr = getgrgid((gid_t) id);
- add_id(cache, gr ? gr->gr_name : NULL, id);
- }
-}
-
diff --git a/utils/lib/ismounted.c b/utils/lib/ismounted.c
deleted file mode 100644
index 9a20b23..0000000
--- a/utils/lib/ismounted.c
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * ismounted.c --- Check to see if the filesystem was mounted
- *
- * Copyright (C) 1995,1996,1997,1998,1999,2000,2008 Theodore Ts'o.
- *
- * This file may be redistributed under the terms of the GNU Public
- * License.
- */
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <fcntl.h>
-#ifdef HAVE_MNTENT_H
-#include <mntent.h>
-#endif
-#include <string.h>
-#include <sys/stat.h>
-#include <ctype.h>
-#include <sys/param.h>
-
-#ifndef __linux__
-# ifdef HAVE_SYS_UCRED_H
-# include <sys/ucred.h>
-# endif
-# ifdef HAVE_SYS_MOUNT_H
-# include <sys/mount.h>
-# endif
-#endif
-
-#include "pathnames.h"
-#include "strutils.h"
-#include "ismounted.h"
-#include "c.h"
-#ifdef __linux__
-# include "loopdev.h"
-#endif
-
-
-
-#ifdef HAVE_MNTENT_H
-/*
- * Helper function which checks a file in /etc/mtab format to see if a
- * filesystem is mounted. Returns an error if the file doesn't exist
- * or can't be opened.
- */
-static int check_mntent_file(const char *mtab_file, const char *file,
- int *mount_flags, char *mtpt, int mtlen)
-{
- struct mntent *mnt;
- struct stat st_buf;
- int retval = 0;
- dev_t file_dev=0, file_rdev=0;
- ino_t file_ino=0;
- FILE *f;
- int fd;
-
- *mount_flags = 0;
- if ((f = setmntent (mtab_file, "r")) == NULL)
- return errno;
-
- if (stat(file, &st_buf) == 0) {
- if (S_ISBLK(st_buf.st_mode)) {
-#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
- file_rdev = st_buf.st_rdev;
-#endif /* __GNU__ */
- } else {
- file_dev = st_buf.st_dev;
- file_ino = st_buf.st_ino;
- }
- }
-
- while ((mnt = getmntent (f)) != NULL) {
- if (mnt->mnt_fsname[0] != '/')
- continue;
- if (strcmp(file, mnt->mnt_fsname) == 0)
- break;
- if (stat(mnt->mnt_fsname, &st_buf) != 0)
- continue;
-
- if (S_ISBLK(st_buf.st_mode)) {
-#ifndef __GNU__
- if (file_rdev && file_rdev == st_buf.st_rdev)
- break;
-#ifdef __linux__
- /* maybe the file is loopdev backing file */
- if (file_dev
- && major(st_buf.st_rdev) == LOOPDEV_MAJOR
- && loopdev_is_used(mnt->mnt_fsname, file, 0, 0, 0))
- break;
-#endif /* __linux__ */
-#endif /* __GNU__ */
- } else {
- if (file_dev && ((file_dev == st_buf.st_dev) &&
- (file_ino == st_buf.st_ino)))
- break;
- }
- }
-
- if (mnt == NULL) {
-#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
- /*
- * Do an extra check to see if this is the root device. We
- * can't trust /etc/mtab, and /proc/mounts will only list
- * /dev/root for the root filesystem. Argh. Instead we
- * check if the given device has the same major/minor number
- * as the device that the root directory is on.
- */
- if (file_rdev && stat("/", &st_buf) == 0 &&
- st_buf.st_dev == file_rdev) {
- *mount_flags = MF_MOUNTED;
- if (mtpt)
- xstrncpy(mtpt, "/", mtlen);
- goto is_root;
- }
-#endif /* __GNU__ */
- goto errout;
- }
-#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
- /* Validate the entry in case /etc/mtab is out of date */
- /*
- * We need to be paranoid, because some broken distributions
- * (read: Slackware) don't initialize /etc/mtab before checking
- * all of the non-root filesystems on the disk.
- */
- if (stat(mnt->mnt_dir, &st_buf) < 0) {
- retval = errno;
- if (retval == ENOENT) {
-#ifdef DEBUG
- printf("Bogus entry in %s! (%s does not exist)\n",
- mtab_file, mnt->mnt_dir);
-#endif /* DEBUG */
- retval = 0;
- }
- goto errout;
- }
- if (file_rdev && (st_buf.st_dev != file_rdev)) {
-#ifdef DEBUG
- printf("Bogus entry in %s! (%s not mounted on %s)\n",
- mtab_file, file, mnt->mnt_dir);
-#endif /* DEBUG */
- goto errout;
- }
-#endif /* __GNU__ */
- *mount_flags = MF_MOUNTED;
-
-#ifdef MNTOPT_RO
- /* Check to see if the ro option is set */
- if (hasmntopt(mnt, MNTOPT_RO))
- *mount_flags |= MF_READONLY;
-#endif
-
- if (mtpt)
- xstrncpy(mtpt, mnt->mnt_dir, mtlen);
- /*
- * Check to see if we're referring to the root filesystem.
- * If so, do a manual check to see if we can open /etc/mtab
- * read/write, since if the root is mounted read/only, the
- * contents of /etc/mtab may not be accurate.
- */
- if (!strcmp(mnt->mnt_dir, "/")) {
-is_root:
-#define TEST_FILE "/.ismount-test-file"
- *mount_flags |= MF_ISROOT;
- fd = open(TEST_FILE, O_RDWR|O_CREAT|O_CLOEXEC, 0600);
- if (fd < 0) {
- if (errno == EROFS)
- *mount_flags |= MF_READONLY;
- } else
- close(fd);
- (void) unlink(TEST_FILE);
- }
- retval = 0;
-errout:
- endmntent (f);
- return retval;
-}
-
-static int check_mntent(const char *file, int *mount_flags,
- char *mtpt, int mtlen)
-{
- int retval;
-
-#ifdef DEBUG
- retval = check_mntent_file("/tmp/mtab", file, mount_flags,
- mtpt, mtlen);
- if (retval == 0)
- return 0;
-#endif /* DEBUG */
-#ifdef __linux__
- retval = check_mntent_file("/proc/mounts", file, mount_flags,
- mtpt, mtlen);
- if (retval == 0 && (*mount_flags != 0))
- return 0;
- if (access("/proc/mounts", R_OK) == 0) {
- *mount_flags = 0;
- return retval;
- }
-#endif /* __linux__ */
-#if defined(MOUNTED) || defined(_PATH_MOUNTED)
-#ifndef MOUNTED
-#define MOUNTED _PATH_MOUNTED
-#endif /* MOUNTED */
- retval = check_mntent_file(MOUNTED, file, mount_flags, mtpt, mtlen);
- return retval;
-#else
- *mount_flags = 0;
- return 0;
-#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
-}
-
-#else
-#if defined(HAVE_GETMNTINFO)
-
-static int check_getmntinfo(const char *file, int *mount_flags,
- char *mtpt, int mtlen)
-{
- struct statfs *mp;
- int len, n;
- const char *s1;
- char *s2;
-
- n = getmntinfo(&mp, MNT_NOWAIT);
- if (n == 0)
- return errno;
-
- len = sizeof(_PATH_DEV) - 1;
- s1 = file;
- if (strncmp(_PATH_DEV, s1, len) == 0)
- s1 += len;
-
- *mount_flags = 0;
- while (--n >= 0) {
- s2 = mp->f_mntfromname;
- if (strncmp(_PATH_DEV, s2, len) == 0) {
- s2 += len - 1;
- *s2 = 'r';
- }
- if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) {
- *mount_flags = MF_MOUNTED;
- break;
- }
- ++mp;
- }
- if (mtpt)
- xstrncpy(mtpt, mp->f_mntonname, mtlen);
- return 0;
-}
-#endif /* HAVE_GETMNTINFO */
-#endif /* HAVE_MNTENT_H */
-
-/*
- * Check to see if we're dealing with the swap device.
- */
-static int is_swap_device(const char *file)
-{
- FILE *f;
- char buf[1024], *cp;
- dev_t file_dev;
- struct stat st_buf;
- int ret = 0;
-
- file_dev = 0;
-#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
- if ((stat(file, &st_buf) == 0) &&
- S_ISBLK(st_buf.st_mode))
- file_dev = st_buf.st_rdev;
-#endif /* __GNU__ */
-
- if (!(f = fopen("/proc/swaps", "r" UL_CLOEXECSTR)))
- return 0;
- /* Skip the first line */
- if (!fgets(buf, sizeof(buf), f))
- goto leave;
- if (*buf && strncmp(buf, "Filename\t", 9) != 0)
- /* Linux <=2.6.19 contained a bug in the /proc/swaps
- * code where the header would not be displayed
- */
- goto valid_first_line;
-
- while (fgets(buf, sizeof(buf), f)) {
-valid_first_line:
- if ((cp = strchr(buf, ' ')) != NULL)
- *cp = 0;
- if ((cp = strchr(buf, '\t')) != NULL)
- *cp = 0;
- if (strcmp(buf, file) == 0) {
- ret++;
- break;
- }
-#ifndef __GNU__
- if (file_dev && (stat(buf, &st_buf) == 0) &&
- S_ISBLK(st_buf.st_mode) &&
- file_dev == st_buf.st_rdev) {
- ret++;
- break;
- }
-#endif /* __GNU__ */
- }
-
-leave:
- fclose(f);
- return ret;
-}
-
-
-/*
- * check_mount_point() fills determines if the device is mounted or otherwise
- * busy, and fills in mount_flags with one or more of the following flags:
- * MF_MOUNTED, MF_ISROOT, MF_READONLY, MF_SWAP, and MF_BUSY. If mtpt is
- * non-NULL, the directory where the device is mounted is copied to where mtpt
- * is pointing, up to mtlen characters.
- */
-#ifdef __TURBOC__
- #pragma argsused
-#endif
-int check_mount_point(const char *device, int *mount_flags,
- char *mtpt, int mtlen)
-{
- int retval = 0;
-
- if (is_swap_device(device)) {
- *mount_flags = MF_MOUNTED | MF_SWAP;
- if (mtpt && mtlen)
- xstrncpy(mtpt, "[SWAP]", mtlen);
- } else {
-#ifdef HAVE_MNTENT_H
- retval = check_mntent(device, mount_flags, mtpt, mtlen);
-#else
-#ifdef HAVE_GETMNTINFO
- retval = check_getmntinfo(device, mount_flags, mtpt, mtlen);
-#else
-#ifdef __GNUC__
- #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!"
-#endif
- *mount_flags = 0;
-#endif /* HAVE_GETMNTINFO */
-#endif /* HAVE_MNTENT_H */
- }
- if (retval)
- return retval;
-
-#ifdef __linux__ /* This only works on Linux 2.6+ systems */
- {
- struct stat st_buf;
- int fd;
- if ((stat(device, &st_buf) != 0) ||
- !S_ISBLK(st_buf.st_mode))
- return 0;
- fd = open(device, O_RDONLY|O_EXCL|O_CLOEXEC);
- if (fd < 0) {
- if (errno == EBUSY)
- *mount_flags |= MF_BUSY;
- } else
- close(fd);
- }
-#endif
-
- return 0;
-}
-
-int is_mounted(const char *file)
-{
- int retval;
- int mount_flags = 0;
-
- retval = check_mount_point(file, &mount_flags, NULL, 0);
- if (retval)
- return 0;
- return mount_flags & MF_MOUNTED;
-}
-
-#ifdef TEST_PROGRAM_ISMOUNTED
-int main(int argc, char **argv)
-{
- int flags = 0;
- char devname[PATH_MAX];
-
- if (argc < 2) {
- fprintf(stderr, "Usage: %s device\n", argv[0]);
- return EXIT_FAILURE;
- }
-
- if (check_mount_point(argv[1], &flags, devname, sizeof(devname)) == 0 &&
- (flags & MF_MOUNTED)) {
- if (flags & MF_SWAP)
- printf("used swap device\n");
- else
- printf("mounted on %s\n", devname);
- return EXIT_SUCCESS;
- }
-
- printf("not mounted\n");
- return EXIT_FAILURE;
-}
-#endif /* DEBUG */
diff --git a/utils/lib/langinfo.c b/utils/lib/langinfo.c
deleted file mode 100644
index a200085..0000000
--- a/utils/lib/langinfo.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * This is callback solution for systems without nl_langinfo(), this function
- * returns hardcoded and on locale setting indepndent value.
- *
- * See langinfo.h man page for more details.
- *
- * No copyright is claimed. This code is in the public domain; do with
- * it what you wish.
- *
- * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
- */
-#include "nls.h"
-
-char *langinfo_fallback(nl_item item)
-{
- switch (item) {
- case CODESET:
- return "ISO-8859-1";
- case THOUSEP:
- return ",";
- case D_T_FMT:
- case ERA_D_T_FMT:
- return "%a %b %e %H:%M:%S %Y";
- case D_FMT:
- case ERA_D_FMT:
- return "%m/%d/%y";
- case T_FMT:
- case ERA_T_FMT:
- return "%H:%M:%S";
- case T_FMT_AMPM:
- return "%I:%M:%S %p";
- case AM_STR:
- return "AM";
- case PM_STR:
- return "PM";
- case DAY_1:
- return "Sunday";
- case DAY_2:
- return "Monday";
- case DAY_3:
- return "Tuesday";
- case DAY_4:
- return "Wednesday";
- case DAY_5:
- return "Thursday";
- case DAY_6:
- return "Friday";
- case DAY_7:
- return "Saturday";
- case ABDAY_1:
- return "Sun";
- case ABDAY_2:
- return "Mon";
- case ABDAY_3:
- return "Tue";
- case ABDAY_4:
- return "Wed";
- case ABDAY_5:
- return "Thu";
- case ABDAY_6:
- return "Fri";
- case ABDAY_7:
- return "Sat";
- case MON_1:
- return "January";
- case MON_2:
- return "February";
- case MON_3:
- return "March";
- case MON_4:
- return "April";
- case MON_5:
- return "May";
- case MON_6:
- return "June";
- case MON_7:
- return "July";
- case MON_8:
- return "August";
- case MON_9:
- return "September";
- case MON_10:
- return "October";
- case MON_11:
- return "November";
- case MON_12:
- return "December";
- case ABMON_1:
- return "Jan";
- case ABMON_2:
- return "Feb";
- case ABMON_3:
- return "Mar";
- case ABMON_4:
- return "Apr";
- case ABMON_5:
- return "May";
- case ABMON_6:
- return "Jun";
- case ABMON_7:
- return "Jul";
- case ABMON_8:
- return "Aug";
- case ABMON_9:
- return "Sep";
- case ABMON_10:
- return "Oct";
- case ABMON_11:
- return "Nov";
- case ABMON_12:
- return "Dec";
- case ALT_DIGITS:
- return "\0\0\0\0\0\0\0\0\0\0";
- case CRNCYSTR:
- return "-";
- case YESEXPR:
- return "^[yY]";
- case NOEXPR:
- return "^[nN]";
- default:
- return "";
- }
-}
-
diff --git a/utils/lib/linux_version.c b/utils/lib/linux_version.c
deleted file mode 100644
index 137bbe7..0000000
--- a/utils/lib/linux_version.c
+++ /dev/null
@@ -1,71 +0,0 @@
-#include <stdio.h>
-#include <sys/utsname.h>
-
-#include "c.h"
-#include "linux_version.h"
-
-int get_linux_version (void)
-{
- static int kver = -1;
- struct utsname uts;
- int x = 0, y = 0, z = 0;
- int n;
-
- if (kver != -1)
- return kver;
- if (uname(&uts))
- return kver = 0;
-
- n = sscanf(uts.release, "%d.%d.%d", &x, &y, &z);
- if (n < 1 || n > 3)
- return kver = 0;
-
- return kver = KERNEL_VERSION(x, y, z);
-}
-
-#ifdef TEST_PROGRAM_LINUXVERSION
-# include <stdlib.h>
-int main(int argc, char *argv[])
-{
- int rc = EXIT_FAILURE;
-
- if (argc == 1) {
- printf("Linux version: %d\n", get_linux_version());
- rc = EXIT_SUCCESS;
-
- } else if (argc == 5) {
- const char *oper = argv[1];
-
- int x = atoi(argv[2]),
- y = atoi(argv[3]),
- z = atoi(argv[4]);
- int kver = get_linux_version();
- int uver = KERNEL_VERSION(x, y, z);
-
- if (strcmp(oper, "==") == 0)
- rc = kver == uver;
- else if (strcmp(oper, "<=") == 0)
- rc = kver <= uver;
- else if (strcmp(oper, ">=") == 0)
- rc = kver >= uver;
- else
- errx(EXIT_FAILURE, "unsupported operator");
-
- if (rc)
- printf("match\n");
- else
- printf("not-match [%d %s %d, x.y.z: %d.%d.%d]\n",
- kver, oper, uver, x, y, z);
-
- rc = rc ? EXIT_SUCCESS : EXIT_FAILURE;
-
- } else
- fprintf(stderr, "Usage:\n"
- " %s [<oper> <x> <y> <z>]\n"
- "supported operators:\n"
- " ==, <=, >=\n",
- program_invocation_short_name);
-
- return rc;
-}
-#endif
diff --git a/utils/lib/loopdev.c b/utils/lib/loopdev.c
deleted file mode 100644
index be4e486..0000000
--- a/utils/lib/loopdev.c
+++ /dev/null
@@ -1,1914 +0,0 @@
-
-/*
- * No copyright is claimed. This code is in the public domain; do with
- * it what you wish.
- *
- * Written by Karel Zak <kzak@redhat.com>
- *
- * -- based on mount/losetup.c
- *
- * Simple library for work with loop devices.
- *
- * - requires kernel 2.6.x
- * - reads info from /sys/block/loop<N>/loop/<attr> (new kernels)
- * - reads info by ioctl
- * - supports *unlimited* number of loop devices
- * - supports /dev/xloop<N> as well as /dev/xloop/<N>
- * - minimize overhead (fd, loopinfo, ... are shared for all operations)
- * - setup (associate device and backing file)
- * - delete (dis-associate file)
- * - old LOOP_{SET,GET}_STATUS (32bit) ioctls are unsupported
- * - extendible
- */
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <inttypes.h>
-#include <dirent.h>
-
-#include "linux_version.h"
-#include "c.h"
-#include "sysfs.h"
-#include "pathnames.h"
-#include "loopdev.h"
-#include "canonicalize.h"
-#include "blkdev.h"
-#include "debug.h"
-
-/*
- * Debug stuff (based on include/debug.h)
- */
-static UL_DEBUG_DEFINE_MASK(loopdev);
-UL_DEBUG_DEFINE_MASKNAMES(loopdev) = UL_DEBUG_EMPTY_MASKNAMES;
-
-#define XLOOPDEV_DEBUG_INIT (1 << 1)
-#define XLOOPDEV_DEBUG_CXT (1 << 2)
-#define XLOOPDEV_DEBUG_ITER (1 << 3)
-#define XLOOPDEV_DEBUG_SETUP (1 << 4)
-
-#define DBG(m, x) __UL_DBG(loopdev, XLOOPDEV_DEBUG_, m, x)
-#define ON_DBG(m, x) __UL_DBG_CALL(loopdev, XLOOPDEV_DEBUG_, m, x)
-
-#define UL_DEBUG_CURRENT_MASK UL_DEBUG_MASK(loopdev)
-#include "debugobj.h"
-
-static void loopdev_init_debug(void)
-{
- if (loopdev_debug_mask)
- return;
- __UL_INIT_DEBUG_FROM_ENV(loopdev, XLOOPDEV_DEBUG_, 0, XLOOPDEV_DEBUG);
-}
-
-/*
- * see loopcxt_init()
- */
-#define loopcxt_ioctl_enabled(_lc) (!((_lc)->flags & LOOPDEV_FL_NOIOCTL))
-#define loopcxt_sysfs_available(_lc) (!((_lc)->flags & LOOPDEV_FL_NOSYSFS)) \
- && !loopcxt_ioctl_enabled(_lc)
-
-/*
- * @lc: context
- * @device: device name, absolute device path or NULL to reset the current setting
- *
- * Sets device, absolute paths (e.g. "/dev/xloop<N>") are unchanged, device
- * names ("xloop<N>") are converted to the path (/dev/xloop<N> or to
- * /dev/xloop/<N>)
- *
- * This sets the device name, but does not check if the device exists!
- *
- * Returns: <0 on error, 0 on success
- */
-int loopcxt_set_device(struct loopdev_cxt *lc, const char *device)
-{
- if (!lc)
- return -EINVAL;
-
- if (lc->fd >= 0) {
- close(lc->fd);
- DBG(CXT, ul_debugobj(lc, "closing old open fd"));
- }
- lc->fd = -1;
- lc->mode = 0;
- lc->blocksize = 0;
- lc->has_info = 0;
- lc->info_failed = 0;
- *lc->device = '\0';
- memset(&lc->info, 0, sizeof(lc->info));
-
- /* set new */
- if (device) {
- if (*device != '/') {
- const char *dir = _PATH_DEV;
-
- /* compose device name for /dev/xloop<n> or /dev/xloop/<n> */
- if (lc->flags & LOOPDEV_FL_DEVSUBDIR) {
- if (strlen(device) <= 5)
- return -1;
- device += 5;
- dir = _PATH_DEV_LOOP "/"; /* _PATH_DEV uses tailing slash */
- }
- snprintf(lc->device, sizeof(lc->device), "%s%s",
- dir, device);
- } else
- xstrncpy(lc->device, device, sizeof(lc->device));
-
- DBG(CXT, ul_debugobj(lc, "%s name assigned", device));
- }
-
- ul_unref_path(lc->sysfs);
- lc->sysfs = NULL;
- return 0;
-}
-
-int loopcxt_has_device(struct loopdev_cxt *lc)
-{
- return lc && *lc->device;
-}
-
-/*
- * @lc: context
- * @flags: LOOPDEV_FL_* flags
- *
- * Initialize loop handler.
- *
- * We have two sets of the flags:
- *
- * * LOOPDEV_FL_* flags control loopcxt_* API behavior
- *
- * * LO_FLAGS_* are kernel flags used for LOOP_{SET,GET}_STAT64 ioctls
- *
- * Note about LOOPDEV_FL_{RDONLY,RDWR} flags. These flags are used for open(2)
- * syscall to open loop device. By default is the device open read-only.
- *
- * The exception is loopcxt_setup_device(), where the device is open read-write
- * if LO_FLAGS_READ_ONLY flags is not set (see loopcxt_set_flags()).
- *
- * Returns: <0 on error, 0 on success.
- */
-int loopcxt_init(struct loopdev_cxt *lc, int flags)
-{
- int rc;
- struct stat st;
- struct loopdev_cxt dummy = UL_LOOPDEVCXT_EMPTY;
-
- if (!lc)
- return -EINVAL;
-
- loopdev_init_debug();
- DBG(CXT, ul_debugobj(lc, "initialize context"));
-
- memcpy(lc, &dummy, sizeof(dummy));
- lc->flags = flags;
-
- rc = loopcxt_set_device(lc, NULL);
- if (rc)
- return rc;
-
- if (stat(_PATH_SYS_BLOCK, &st) || !S_ISDIR(st.st_mode)) {
- lc->flags |= LOOPDEV_FL_NOSYSFS;
- lc->flags &= ~LOOPDEV_FL_NOIOCTL;
- DBG(CXT, ul_debugobj(lc, "init: disable /sys usage"));
- }
-
- if (!(lc->flags & LOOPDEV_FL_NOSYSFS) &&
- get_linux_version() >= KERNEL_VERSION(2,6,37)) {
- /*
- * Use only sysfs for basic information about loop devices
- */
- lc->flags |= LOOPDEV_FL_NOIOCTL;
- DBG(CXT, ul_debugobj(lc, "init: ignore ioctls"));
- }
-
- if (!(lc->flags & LOOPDEV_FL_CONTROL) && !stat(_PATH_DEV_LOOPCTL, &st)) {
- lc->flags |= LOOPDEV_FL_CONTROL;
- DBG(CXT, ul_debugobj(lc, "init: xloop-control detected "));
- }
-
- return 0;
-}
-
-/*
- * @lc: context
- *
- * Deinitialize loop context
- */
-void loopcxt_deinit(struct loopdev_cxt *lc)
-{
- int errsv = errno;
-
- if (!lc)
- return;
-
- DBG(CXT, ul_debugobj(lc, "de-initialize"));
-
- free(lc->filename);
- lc->filename = NULL;
-
- ignore_result( loopcxt_set_device(lc, NULL) );
- loopcxt_deinit_iterator(lc);
-
- errno = errsv;
-}
-
-/*
- * @lc: context
- *
- * Returns newly allocated device path.
- */
-char *loopcxt_strdup_device(struct loopdev_cxt *lc)
-{
- if (!lc || !*lc->device)
- return NULL;
- return strdup(lc->device);
-}
-
-/*
- * @lc: context
- *
- * Returns pointer device name in the @lc struct.
- */
-const char *loopcxt_get_device(struct loopdev_cxt *lc)
-{
- return lc && *lc->device ? lc->device : NULL;
-}
-
-/*
- * @lc: context
- *
- * Returns pointer to the sysfs context (see lib/sysfs.c)
- */
-static struct path_cxt *loopcxt_get_sysfs(struct loopdev_cxt *lc)
-{
- if (!lc || !*lc->device || (lc->flags & LOOPDEV_FL_NOSYSFS))
- return NULL;
-
- if (!lc->sysfs) {
- dev_t devno = sysfs_devname_to_devno(lc->device);
- if (!devno) {
- DBG(CXT, ul_debugobj(lc, "sysfs: failed devname to devno"));
- return NULL;
- }
-
- lc->sysfs = ul_new_sysfs_path(devno, NULL, NULL);
- if (!lc->sysfs)
- DBG(CXT, ul_debugobj(lc, "sysfs: init failed"));
- }
-
- return lc->sysfs;
-}
-
-/*
- * @lc: context
- *
- * Returns: file descriptor to the open loop device or <0 on error. The mode
- * depends on LOOPDEV_FL_{RDWR,RDONLY} context flags. Default is
- * read-only.
- */
-int loopcxt_get_fd(struct loopdev_cxt *lc)
-{
- if (!lc || !*lc->device)
- return -EINVAL;
-
- if (lc->fd < 0) {
- lc->mode = lc->flags & LOOPDEV_FL_RDWR ? O_RDWR : O_RDONLY;
- lc->fd = open(lc->device, lc->mode | O_CLOEXEC);
- DBG(CXT, ul_debugobj(lc, "open %s [%s]: %m", lc->device,
- lc->flags & LOOPDEV_FL_RDWR ? "rw" : "ro"));
- }
- return lc->fd;
-}
-
-int loopcxt_set_fd(struct loopdev_cxt *lc, int fd, int mode)
-{
- if (!lc)
- return -EINVAL;
-
- lc->fd = fd;
- lc->mode = mode;
- return 0;
-}
-
-/*
- * @lc: context
- * @flags: LOOPITER_FL_* flags
- *
- * Iterator can be used to scan list of the free or used loop devices.
- *
- * Returns: <0 on error, 0 on success
- */
-int loopcxt_init_iterator(struct loopdev_cxt *lc, int flags)
-{
- struct loopdev_iter *iter;
- struct stat st;
-
- if (!lc)
- return -EINVAL;
-
-
- iter = &lc->iter;
- DBG(ITER, ul_debugobj(iter, "initialize"));
-
- /* always zeroize
- */
- memset(iter, 0, sizeof(*iter));
- iter->ncur = -1;
- iter->flags = flags;
- iter->default_check = 1;
-
- if (!lc->extra_check) {
- /*
- * Check for /dev/xloop/<N> subdirectory
- */
- if (!(lc->flags & LOOPDEV_FL_DEVSUBDIR) &&
- stat(_PATH_DEV_LOOP, &st) == 0 && S_ISDIR(st.st_mode))
- lc->flags |= LOOPDEV_FL_DEVSUBDIR;
-
- lc->extra_check = 1;
- }
- return 0;
-}
-
-/*
- * @lc: context
- *
- * Returns: <0 on error, 0 on success
- */
-int loopcxt_deinit_iterator(struct loopdev_cxt *lc)
-{
- struct loopdev_iter *iter;
-
- if (!lc)
- return -EINVAL;
-
- iter = &lc->iter;
- DBG(ITER, ul_debugobj(iter, "de-initialize"));
-
- free(iter->minors);
- if (iter->proc)
- fclose(iter->proc);
- if (iter->sysblock)
- closedir(iter->sysblock);
-
- memset(iter, 0, sizeof(*iter));
- return 0;
-}
-
-/*
- * Same as loopcxt_set_device, but also checks if the device is
- * associated with any file.
- *
- * Returns: <0 on error, 0 on success, 1 device does not match with
- * LOOPITER_FL_{USED,FREE} flags.
- */
-static int loopiter_set_device(struct loopdev_cxt *lc, const char *device)
-{
- int rc = loopcxt_set_device(lc, device);
- int used;
-
- if (rc)
- return rc;
-
- if (!(lc->iter.flags & LOOPITER_FL_USED) &&
- !(lc->iter.flags & LOOPITER_FL_FREE))
- return 0; /* caller does not care about device status */
-
- if (!is_loopdev(lc->device)) {
- DBG(ITER, ul_debugobj(&lc->iter, "%s does not exist", lc->device));
- return -errno;
- }
-
- DBG(ITER, ul_debugobj(&lc->iter, "%s exist", lc->device));
-
- used = loopcxt_get_offset(lc, NULL) == 0;
-
- if ((lc->iter.flags & LOOPITER_FL_USED) && used)
- return 0;
-
- if ((lc->iter.flags & LOOPITER_FL_FREE) && !used)
- return 0;
-
- DBG(ITER, ul_debugobj(&lc->iter, "failed to use %s device", lc->device));
-
- ignore_result( loopcxt_set_device(lc, NULL) );
- return 1;
-}
-
-static int cmpnum(const void *p1, const void *p2)
-{
- return (((* (const int *) p1) > (* (const int *) p2)) -
- ((* (const int *) p1) < (* (const int *) p2)));
-}
-
-/*
- * The classic scandir() is more expensive and less portable.
- * We needn't full loop device names -- loop numbers (loop<N>)
- * are enough.
- */
-static int loop_scandir(const char *dirname, int **ary, int hasprefix)
-{
- DIR *dir;
- struct dirent *d;
- unsigned int n, count = 0, arylen = 0;
-
- if (!dirname || !ary)
- return 0;
-
- DBG(ITER, ul_debug("scan dir: %s", dirname));
-
- dir = opendir(dirname);
- if (!dir)
- return 0;
- free(*ary);
- *ary = NULL;
-
- while((d = readdir(dir))) {
-#ifdef _DIRENT_HAVE_D_TYPE
- if (d->d_type != DT_BLK && d->d_type != DT_UNKNOWN &&
- d->d_type != DT_LNK)
- continue;
-#endif
- if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
- continue;
-
- if (hasprefix) {
- /* /dev/xloop<N> */
- if (sscanf(d->d_name, "xloop%u", &n) != 1)
- continue;
- } else {
- /* /dev/xloop/<N> */
- char *end = NULL;
-
- errno = 0;
- n = strtol(d->d_name, &end, 10);
- if (d->d_name == end || (end && *end) || errno)
- continue;
- }
- if (n < LOOPDEV_DEFAULT_NNODES)
- continue; /* ignore xloop<0..7> */
-
- if (count + 1 > arylen) {
- int *tmp;
-
- arylen += 1;
-
- tmp = realloc(*ary, arylen * sizeof(int));
- if (!tmp) {
- free(*ary);
- *ary = NULL;
- closedir(dir);
- return -1;
- }
- *ary = tmp;
- }
- if (*ary)
- (*ary)[count++] = n;
- }
- if (count && *ary)
- qsort(*ary, count, sizeof(int), cmpnum);
-
- closedir(dir);
- return count;
-}
-
-/*
- * Set the next *used* loop device according to /proc/partitions.
- *
- * Loop devices smaller than 512 bytes are invisible for this function.
- */
-static int loopcxt_next_from_proc(struct loopdev_cxt *lc)
-{
- struct loopdev_iter *iter = &lc->iter;
- char buf[BUFSIZ];
-
- DBG(ITER, ul_debugobj(iter, "scan /proc/partitions"));
-
- if (!iter->proc)
- iter->proc = fopen(_PATH_PROC_PARTITIONS, "r" UL_CLOEXECSTR);
- if (!iter->proc)
- return 1;
-
- while (fgets(buf, sizeof(buf), iter->proc)) {
- unsigned int m;
- char name[128 + 1];
-
-
- if (sscanf(buf, " %u %*s %*s %128[^\n ]",
- &m, name) != 2 || m != LOOPDEV_MAJOR)
- continue;
-
- DBG(ITER, ul_debugobj(iter, "checking %s", name));
-
- if (loopiter_set_device(lc, name) == 0)
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Set the next *used* loop device according to
- * /sys/block/loopN/loop/backing_file (kernel >= 2.6.37 is required).
- *
- * This is preferred method.
- */
-static int loopcxt_next_from_sysfs(struct loopdev_cxt *lc)
-{
- struct loopdev_iter *iter = &lc->iter;
- struct dirent *d;
- int fd;
-
- DBG(ITER, ul_debugobj(iter, "scanning /sys/block"));
-
- if (!iter->sysblock)
- iter->sysblock = opendir(_PATH_SYS_BLOCK);
-
- if (!iter->sysblock)
- return 1;
-
- fd = dirfd(iter->sysblock);
-
- while ((d = readdir(iter->sysblock))) {
- char name[NAME_MAX + 18 + 1];
- struct stat st;
-
- DBG(ITER, ul_debugobj(iter, "check %s", d->d_name));
-
- if (strcmp(d->d_name, ".") == 0
- || strcmp(d->d_name, "..") == 0
- || strncmp(d->d_name, "xloop", 4) != 0)
- continue;
-
- snprintf(name, sizeof(name), "%s/xloop/backing_file", d->d_name);
- if (fstatat(fd, name, &st, 0) != 0)
- continue;
-
- if (loopiter_set_device(lc, d->d_name) == 0)
- return 0;
- }
-
- return 1;
-}
-
-/*
- * @lc: context, has to initialized by loopcxt_init_iterator()
- *
- * Returns: 0 on success, -1 on error, 1 at the end of scanning. The details
- * about the current loop device are available by
- * loopcxt_get_{fd,backing_file,device,offset, ...} functions.
- */
-int loopcxt_next(struct loopdev_cxt *lc)
-{
- struct loopdev_iter *iter;
-
- if (!lc)
- return -EINVAL;
-
-
- iter = &lc->iter;
- if (iter->done)
- return 1;
-
- DBG(ITER, ul_debugobj(iter, "next"));
-
- /* A) Look for used loop devices in /proc/partitions ("losetup -a" only)
- */
- if (iter->flags & LOOPITER_FL_USED) {
- int rc;
-
- if (loopcxt_sysfs_available(lc))
- rc = loopcxt_next_from_sysfs(lc);
- else
- rc = loopcxt_next_from_proc(lc);
- if (rc == 0)
- return 0;
- goto done;
- }
-
- /* B) Classic way, try first eight loop devices (default number
- * of loop devices). This is enough for 99% of all cases.
- */
- if (iter->default_check) {
- DBG(ITER, ul_debugobj(iter, "next: default check"));
- for (++iter->ncur; iter->ncur < LOOPDEV_DEFAULT_NNODES;
- iter->ncur++) {
- char name[16];
- snprintf(name, sizeof(name), "xloop%d", iter->ncur);
-
- if (loopiter_set_device(lc, name) == 0)
- return 0;
- }
- iter->default_check = 0;
- }
-
- /* C) the worst possibility, scan whole /dev or /dev/xloop/<N>
- */
- if (!iter->minors) {
- DBG(ITER, ul_debugobj(iter, "next: scanning /dev"));
- iter->nminors = (lc->flags & LOOPDEV_FL_DEVSUBDIR) ?
- loop_scandir(_PATH_DEV_LOOP, &iter->minors, 0) :
- loop_scandir(_PATH_DEV, &iter->minors, 1);
- iter->ncur = -1;
- }
- for (++iter->ncur; iter->ncur < iter->nminors; iter->ncur++) {
- char name[16];
- snprintf(name, sizeof(name), "xloop%d", iter->minors[iter->ncur]);
-
- if (loopiter_set_device(lc, name) == 0)
- return 0;
- }
-done:
- loopcxt_deinit_iterator(lc);
- return 1;
-}
-
-/*
- * @device: path to device
- */
-int is_loopdev(const char *device)
-{
- struct stat st;
-
- if (device && stat(device, &st) == 0 &&
- S_ISBLK(st.st_mode) &&
- major(st.st_rdev) == LOOPDEV_MAJOR)
- return 1;
-
- errno = ENODEV;
- return 0;
-}
-
-/*
- * @lc: context
- *
- * Returns result from LOOP_GET_STAT64 ioctl or NULL on error.
- */
-struct loop_info64 *loopcxt_get_info(struct loopdev_cxt *lc)
-{
- int fd;
-
- if (!lc || lc->info_failed) {
- errno = EINVAL;
- return NULL;
- }
- errno = 0;
- if (lc->has_info)
- return &lc->info;
-
- fd = loopcxt_get_fd(lc);
- if (fd < 0)
- return NULL;
-
- if (ioctl(fd, LOOP_GET_STATUS64, &lc->info) == 0) {
- lc->has_info = 1;
- lc->info_failed = 0;
- DBG(CXT, ul_debugobj(lc, "reading loop_info64 OK"));
- return &lc->info;
- }
-
- lc->info_failed = 1;
- DBG(CXT, ul_debugobj(lc, "reading loop_info64 FAILED"));
-
- return NULL;
-}
-
-/*
- * @lc: context
- *
- * Returns (allocated) string with path to the file associated
- * with the current loop device.
- */
-char *loopcxt_get_backing_file(struct loopdev_cxt *lc)
-{
- struct path_cxt *sysfs = loopcxt_get_sysfs(lc);
- char *res = NULL;
-
- if (sysfs)
- /*
- * This is always preferred, the loop_info64
- * has too small buffer for the filename.
- */
- ul_path_read_string(sysfs, &res, "xloop/backing_file");
-
- if (!res && loopcxt_ioctl_enabled(lc)) {
- struct loop_info64 *lo = loopcxt_get_info(lc);
-
- if (lo) {
- lo->lo_file_name[LO_NAME_SIZE - 2] = '*';
- lo->lo_file_name[LO_NAME_SIZE - 1] = '\0';
- res = strdup((char *) lo->lo_file_name);
- }
- }
-
- DBG(CXT, ul_debugobj(lc, "get_backing_file [%s]", res));
- return res;
-}
-
-/*
- * @lc: context
- * @offset: returns offset number for the given device
- *
- * Returns: <0 on error, 0 on success
- */
-int loopcxt_get_offset(struct loopdev_cxt *lc, uint64_t *offset)
-{
- struct path_cxt *sysfs = loopcxt_get_sysfs(lc);
- int rc = -EINVAL;
-
- if (sysfs)
- rc = ul_path_read_u64(sysfs, offset, "xloop/offset");
-
- if (rc && loopcxt_ioctl_enabled(lc)) {
- struct loop_info64 *lo = loopcxt_get_info(lc);
- if (lo) {
- if (offset)
- *offset = lo->lo_offset;
- rc = 0;
- } else
- rc = -errno;
- }
-
- DBG(CXT, ul_debugobj(lc, "get_offset [rc=%d]", rc));
- return rc;
-}
-
-/*
- * @lc: context
- * @blocksize: returns logical blocksize for the given device
- *
- * Returns: <0 on error, 0 on success
- */
-int loopcxt_get_blocksize(struct loopdev_cxt *lc, uint64_t *blocksize)
-{
- struct path_cxt *sysfs = loopcxt_get_sysfs(lc);
- int rc = -EINVAL;
-
- if (sysfs)
- rc = ul_path_read_u64(sysfs, blocksize, "queue/logical_block_size");
-
- /* Fallback based on BLKSSZGET ioctl */
- if (rc) {
- int fd = loopcxt_get_fd(lc);
- int sz = 0;
-
- if (fd < 0)
- return -EINVAL;
- rc = blkdev_get_sector_size(fd, &sz);
- if (rc)
- return rc;
-
- *blocksize = sz;
- }
-
- DBG(CXT, ul_debugobj(lc, "get_blocksize [rc=%d]", rc));
- return rc;
-}
-
-/*
- * @lc: context
- * @sizelimit: returns size limit for the given device
- *
- * Returns: <0 on error, 0 on success
- */
-int loopcxt_get_sizelimit(struct loopdev_cxt *lc, uint64_t *size)
-{
- struct path_cxt *sysfs = loopcxt_get_sysfs(lc);
- int rc = -EINVAL;
-
- if (sysfs)
- rc = ul_path_read_u64(sysfs, size, "xloop/sizelimit");
-
- if (rc && loopcxt_ioctl_enabled(lc)) {
- struct loop_info64 *lo = loopcxt_get_info(lc);
- if (lo) {
- if (size)
- *size = lo->lo_sizelimit;
- rc = 0;
- } else
- rc = -errno;
- }
-
- DBG(CXT, ul_debugobj(lc, "get_sizelimit [rc=%d]", rc));
- return rc;
-}
-
-/*
- * @lc: context
- * @devno: returns encryption type
- *
- * Cryptoloop is DEPRECATED!
- *
- * Returns: <0 on error, 0 on success
- */
-int loopcxt_get_encrypt_type(struct loopdev_cxt *lc, uint32_t *type)
-{
- struct loop_info64 *lo = loopcxt_get_info(lc);
- int rc;
-
- /* not provided by sysfs */
- if (lo) {
- if (type)
- *type = lo->lo_encrypt_type;
- rc = 0;
- } else
- rc = -errno;
-
- DBG(CXT, ul_debugobj(lc, "get_encrypt_type [rc=%d]", rc));
- return rc;
-}
-
-/*
- * @file_fmt_type_str: file format type string.
- * @file_fmt_type: returns file format type from the given file format string.
- *
- * Returns: <0 on error, 0 on success
- */
-int parse_file_fmt_type(const char *file_fmt_type_str, uint32_t *file_fmt_type)
-{
- int rc = 0;
-
- if (!strcmp(file_fmt_type_str, "RAW"))
- *file_fmt_type = LO_FILE_FMT_RAW;
- else if (!strcmp(file_fmt_type_str, "QCOW"))
- *file_fmt_type = LO_FILE_FMT_QCOW;
- else if (!strcmp(file_fmt_type_str, "VDI"))
- *file_fmt_type = LO_FILE_FMT_VDI;
- else if (!strcmp(file_fmt_type_str, "VMDK"))
- *file_fmt_type = LO_FILE_FMT_VMDK;
- else
- rc = -EINVAL;
-
- return rc;
-}
-
-/*
- * @lc: context
- * @file_fmt_type: returns file format type of the given device
- *
- * Returns: <0 on error, 0 on success
- */
-int loopcxt_get_file_fmt_type(struct loopdev_cxt *lc, uint32_t* file_fmt_type)
-{
- struct path_cxt *sysfs = loopcxt_get_sysfs(lc);
- int rc = 0;
-
- if (sysfs) {
- /* check if file_fmt_type is accessible and supported by the kernel module */
- char* file_fmt_str = NULL;
- if (ul_path_read_string(sysfs, &file_fmt_str, "xloop/file_fmt_type") == 0)
- rc = parse_file_fmt_type(file_fmt_str, file_fmt_type);
- } else
- rc = -errno;
-
- if (rc != 0 && loopcxt_ioctl_enabled(lc)) {
- struct loop_info64 *lo = loopcxt_get_info(lc);
- if (lo)
- *file_fmt_type = lo->lo_file_fmt_type;
- }
-
- return 0;
-}
-
-/*
- * @lc: context
- *
- * Returns (allocated) string with file format type of the current loop device.
- */
-char *loopcxt_get_file_fmt_type_string(struct loopdev_cxt *lc)
-{
- struct path_cxt *sysfs = loopcxt_get_sysfs(lc);
- char *res = NULL;
-
- if (sysfs)
- ul_path_read_string(sysfs, &res, "xloop/file_fmt_type");
-
- DBG(CXT, ul_debugobj(lc, "xloopcxt_get_file_fmt_type_string [%s]", res));
- return res;
-}
-
-/*
- * @lc: context
- * @devno: returns crypt name
- *
- * Cryptoloop is DEPRECATED!
- *
- * Returns: <0 on error, 0 on success
- */
-const char *loopcxt_get_crypt_name(struct loopdev_cxt *lc)
-{
- struct loop_info64 *lo = loopcxt_get_info(lc);
-
- if (lo)
- return (char *) lo->lo_crypt_name;
-
- DBG(CXT, ul_debugobj(lc, "get_crypt_name failed"));
- return NULL;
-}
-
-/*
- * @lc: context
- * @devno: returns backing file devno
- *
- * Returns: <0 on error, 0 on success
- */
-int loopcxt_get_backing_devno(struct loopdev_cxt *lc, dev_t *devno)
-{
- struct loop_info64 *lo = loopcxt_get_info(lc);
- int rc;
-
- if (lo) {
- if (devno)
- *devno = lo->lo_device;
- rc = 0;
- } else
- rc = -errno;
-
- DBG(CXT, ul_debugobj(lc, "get_backing_devno [rc=%d]", rc));
- return rc;
-}
-
-/*
- * @lc: context
- * @ino: returns backing file inode
- *
- * Returns: <0 on error, 0 on success
- */
-int loopcxt_get_backing_inode(struct loopdev_cxt *lc, ino_t *ino)
-{
- struct loop_info64 *lo = loopcxt_get_info(lc);
- int rc;
-
- if (lo) {
- if (ino)
- *ino = lo->lo_inode;
- rc = 0;
- } else
- rc = -errno;
-
- DBG(CXT, ul_debugobj(lc, "get_backing_inode [rc=%d]", rc));
- return rc;
-}
-
-/*
- * Check if the kernel supports partitioned loop devices.
- *
- * Notes:
- * - kernels < 3.2 support partitioned loop devices and PT scanning
- * only if max_part= module parameter is non-zero
- *
- * - kernels >= 3.2 always support partitioned loop devices
- *
- * - kernels >= 3.2 always support BLKPG_{ADD,DEL}_PARTITION ioctls
- *
- * - kernels >= 3.2 enable PT scanner only if max_part= is non-zero or if the
- * LO_FLAGS_PARTSCAN flag is set for the device. The PT scanner is disabled
- * by default.
- *
- * See kernel commit e03c8dd14915fabc101aa495828d58598dc5af98.
- */
-int loopmod_supports_partscan(void)
-{
- int rc, ret = 0;
- FILE *f;
-
- if (get_linux_version() >= KERNEL_VERSION(3,2,0))
- return 1;
-
- f = fopen("/sys/module/loop/parameters/max_part", "r" UL_CLOEXECSTR);
- if (!f)
- return 0;
- rc = fscanf(f, "%d", &ret);
- fclose(f);
- return rc == 1 ? ret : 0;
-}
-
-/*
- * @lc: context
- *
- * Returns: 1 if the partscan flags is set *or* (for old kernels) partitions
- * scanning is enabled for all loop devices.
- */
-int loopcxt_is_partscan(struct loopdev_cxt *lc)
-{
- struct path_cxt *sysfs = loopcxt_get_sysfs(lc);
-
- if (sysfs) {
- /* kernel >= 3.2 */
- int fl;
- if (ul_path_read_s32(sysfs, &fl, "xloop/partscan") == 0)
- return fl;
- }
-
- /* old kernels (including kernels without loopN/loop/<flags> directory */
- return loopmod_supports_partscan();
-}
-
-/*
- * @lc: context
- *
- * Returns: 1 if the autoclear flags is set.
- */
-int loopcxt_is_autoclear(struct loopdev_cxt *lc)
-{
- struct path_cxt *sysfs = loopcxt_get_sysfs(lc);
-
- if (sysfs) {
- int fl;
- if (ul_path_read_s32(sysfs, &fl, "xloop/autoclear") == 0)
- return fl;
- }
-
- if (loopcxt_ioctl_enabled(lc)) {
- struct loop_info64 *lo = loopcxt_get_info(lc);
- if (lo)
- return lo->lo_flags & LO_FLAGS_AUTOCLEAR;
- }
- return 0;
-}
-
-/*
- * @lc: context
- *
- * Returns: 1 if the readonly flags is set.
- */
-int loopcxt_is_readonly(struct loopdev_cxt *lc)
-{
- struct path_cxt *sysfs = loopcxt_get_sysfs(lc);
-
- if (sysfs) {
- int fl;
- if (ul_path_read_s32(sysfs, &fl, "ro") == 0)
- return fl;
- }
-
- if (loopcxt_ioctl_enabled(lc)) {
- struct loop_info64 *lo = loopcxt_get_info(lc);
- if (lo)
- return lo->lo_flags & LO_FLAGS_READ_ONLY;
- }
- return 0;
-}
-
-/*
- * @lc: context
- *
- * Returns: 1 if the dio flags is set.
- */
-int loopcxt_is_dio(struct loopdev_cxt *lc)
-{
- struct path_cxt *sysfs = loopcxt_get_sysfs(lc);
-
- if (sysfs) {
- int fl;
- if (ul_path_read_s32(sysfs, &fl, "xloop/dio") == 0)
- return fl;
- }
- if (loopcxt_ioctl_enabled(lc)) {
- struct loop_info64 *lo = loopcxt_get_info(lc);
- if (lo)
- return lo->lo_flags & LO_FLAGS_DIRECT_IO;
- }
- return 0;
-}
-
-/*
- * @lc: context
- * @st: backing file stat or NULL
- * @backing_file: filename
- * @offset: offset (use LOOPDEV_FL_OFFSET if specified)
- * @sizelimit: size limit (use LOOPDEV_FL_SIZELIMIT if specified)
- * @flags: LOOPDEV_FL_{OFFSET,SIZELIMIT}
- *
- * Returns 1 if the current @lc loopdev is associated with the given backing
- * file. Note that the preferred way is to use devno and inode number rather
- * than filename. The @backing_file filename is poor solution usable in case
- * that you don't have rights to call stat().
- *
- * LOOPDEV_FL_SIZELIMIT requires LOOPDEV_FL_OFFSET being set as well.
- *
- * Don't forget that old kernels provide very restricted (in size) backing
- * filename by LOOP_GET_STAT64 ioctl only.
- */
-int loopcxt_is_used(struct loopdev_cxt *lc,
- struct stat *st,
- const char *backing_file,
- uint64_t offset,
- uint64_t sizelimit,
- int flags)
-{
- ino_t ino = 0;
- dev_t dev = 0;
-
- if (!lc)
- return 0;
-
- DBG(CXT, ul_debugobj(lc, "checking %s vs. %s",
- loopcxt_get_device(lc),
- backing_file));
-
- if (st && loopcxt_get_backing_inode(lc, &ino) == 0 &&
- loopcxt_get_backing_devno(lc, &dev) == 0) {
-
- if (ino == st->st_ino && dev == st->st_dev)
- goto found;
-
- /* don't use filename if we have devno and inode */
- return 0;
- }
-
- /* poor man's solution */
- if (backing_file) {
- char *name = loopcxt_get_backing_file(lc);
- int rc = name && strcmp(name, backing_file) == 0;
-
- free(name);
- if (rc)
- goto found;
- }
-
- return 0;
-found:
- if (flags & LOOPDEV_FL_OFFSET) {
- uint64_t off = 0;
-
- int rc = loopcxt_get_offset(lc, &off) == 0 && off == offset;
-
- if (rc && flags & LOOPDEV_FL_SIZELIMIT) {
- uint64_t sz = 0;
-
- return loopcxt_get_sizelimit(lc, &sz) == 0 && sz == sizelimit;
- }
- return rc;
- }
- return 1;
-}
-
-/*
- * The setting is removed by loopcxt_set_device() loopcxt_next()!
- */
-int loopcxt_set_offset(struct loopdev_cxt *lc, uint64_t offset)
-{
- if (!lc)
- return -EINVAL;
- lc->info.lo_offset = offset;
-
- DBG(CXT, ul_debugobj(lc, "set offset=%jd", offset));
- return 0;
-}
-
-/*
- * The setting is removed by loopcxt_set_device() loopcxt_next()!
- */
-int loopcxt_set_sizelimit(struct loopdev_cxt *lc, uint64_t sizelimit)
-{
- if (!lc)
- return -EINVAL;
- lc->info.lo_sizelimit = sizelimit;
-
- DBG(CXT, ul_debugobj(lc, "set sizelimit=%jd", sizelimit));
- return 0;
-}
-
-/*
- * The blocksize will be used by loopcxt_set_device(). For already exiting
- * devices use loopcxt_ioctl_blocksize().
- *
- * The setting is removed by loopcxt_set_device() loopcxt_next()!
- */
-int loopcxt_set_blocksize(struct loopdev_cxt *lc, uint64_t blocksize)
-{
- if (!lc)
- return -EINVAL;
- lc->blocksize = blocksize;
-
- DBG(CXT, ul_debugobj(lc, "set blocksize=%jd", blocksize));
- return 0;
-}
-
-/*
- * @lc: context
- * @file_fmt_type: kernel LO_FILE_FMT_{RAW,QCOW,VDI,VMDK} flags
- *
- * The setting is removed by loopcxt_set_device() loopcxt_next()!
- *
- * Returns: 0 on success, <0 on error.
- */
-int loopcxt_set_file_fmt_type(struct loopdev_cxt *lc, uint32_t file_fmt_type) {
- if (!lc)
- return -EINVAL;
- lc->info.lo_file_fmt_type = file_fmt_type;
-
- DBG(CXT, ul_debugobj(lc, "set file_fmt_type=%u", (unsigned) file_fmt_type));
- return 0;
-}
-
-/*
- * @lc: context
- * @flags: kernel LO_FLAGS_{READ_ONLY,USE_AOPS,AUTOCLEAR} flags
- *
- * The setting is removed by loopcxt_set_device() loopcxt_next()!
- *
- * Returns: 0 on success, <0 on error.
- */
-int loopcxt_set_flags(struct loopdev_cxt *lc, uint32_t flags)
-{
- if (!lc)
- return -EINVAL;
- lc->info.lo_flags = flags;
-
- DBG(CXT, ul_debugobj(lc, "set flags=%u", (unsigned) flags));
- return 0;
-}
-
-/*
- * @lc: context
- * @filename: backing file path (the path will be canonicalized)
- *
- * The setting is removed by loopcxt_set_device() loopcxt_next()!
- *
- * Returns: 0 on success, <0 on error.
- */
-int loopcxt_set_backing_file(struct loopdev_cxt *lc, const char *filename)
-{
- if (!lc)
- return -EINVAL;
-
- lc->filename = canonicalize_path(filename);
- if (!lc->filename)
- return -errno;
-
- xstrncpy((char *)lc->info.lo_file_name, lc->filename, LO_NAME_SIZE);
-
- DBG(CXT, ul_debugobj(lc, "set backing file=%s", lc->info.lo_file_name));
- return 0;
-}
-
-/*
- * In kernels prior to v3.9, if the offset or sizelimit options
- * are used, the block device's size won't be synced automatically.
- * blockdev --getsize64 and filesystems will use the backing
- * file size until the block device has been re-opened or the
- * LOOP_SET_CAPACITY ioctl is called to sync the sizes.
- *
- * Since mount -oloop uses the LO_FLAGS_AUTOCLEAR option and passes
- * the open file descriptor to the mount system call, we need to use
- * the ioctl. Calling losetup directly doesn't have this problem since
- * it closes the device when it exits and whatever consumes the device
- * next will re-open it, causing the resync.
- */
-static int loopcxt_check_size(struct loopdev_cxt *lc, int file_fd)
-{
- uint64_t size, expected_size;
- int dev_fd;
- struct stat st;
-
- if (!lc->info.lo_offset && !lc->info.lo_sizelimit)
- return 0;
-
- if (fstat(file_fd, &st)) {
- DBG(CXT, ul_debugobj(lc, "failed to fstat backing file"));
- return -errno;
- }
- if (S_ISBLK(st.st_mode)) {
- if (blkdev_get_size(file_fd,
- (unsigned long long *) &expected_size)) {
- DBG(CXT, ul_debugobj(lc, "failed to determine device size"));
- return -errno;
- }
- } else
- expected_size = st.st_size;
-
- if (expected_size == 0 || expected_size <= lc->info.lo_offset) {
- DBG(CXT, ul_debugobj(lc, "failed to determine expected size"));
- return 0; /* ignore this error */
- }
-
- if (lc->info.lo_offset > 0)
- expected_size -= lc->info.lo_offset;
-
- if (lc->info.lo_sizelimit > 0 && lc->info.lo_sizelimit < expected_size)
- expected_size = lc->info.lo_sizelimit;
-
- dev_fd = loopcxt_get_fd(lc);
- if (dev_fd < 0) {
- DBG(CXT, ul_debugobj(lc, "failed to get loop FD"));
- return -errno;
- }
-
- if (blkdev_get_size(dev_fd, (unsigned long long *) &size)) {
- DBG(CXT, ul_debugobj(lc, "failed to determine loopdev size"));
- return -errno;
- }
-
- /* It's block device, so, align to 512-byte sectors */
- if (expected_size % 512) {
- DBG(CXT, ul_debugobj(lc, "expected size misaligned to 512-byte sectors"));
- expected_size = (expected_size >> 9) << 9;
- }
-
- if (expected_size != size) {
- DBG(CXT, ul_debugobj(lc, "warning: loopdev and expected "
- "size mismatch (%ju/%ju)",
- size, expected_size));
-
- if (loopcxt_ioctl_capacity(lc)) {
- /* ioctl not available */
- if (errno == ENOTTY || errno == EINVAL)
- errno = ERANGE;
- return -errno;
- }
-
- if (blkdev_get_size(dev_fd, (unsigned long long *) &size))
- return -errno;
-
- if (expected_size != size) {
- errno = ERANGE;
- DBG(CXT, ul_debugobj(lc, "failed to set loopdev size, "
- "size: %ju, expected: %ju",
- size, expected_size));
- return -errno;
- }
- }
-
- return 0;
-}
-
-/*
- * @lc: context
- *
- * Associate the current device (see loopcxt_{set,get}_device()) with
- * a file (see loopcxt_set_backing_file()).
- *
- * The device is initialized read-write by default. If you want read-only
- * device then set LO_FLAGS_READ_ONLY by loopcxt_set_flags(). The LOOPDEV_FL_*
- * flags are ignored and modified according to LO_FLAGS_*.
- *
- * If the device is already open by loopcxt_get_fd() then this setup device
- * function will re-open the device to fix read/write mode.
- *
- * The device is also initialized read-only if the backing file is not
- * possible to open read-write (e.g. read-only FS).
- *
- * Returns: <0 on error, 0 on success.
- */
-int loopcxt_setup_device(struct loopdev_cxt *lc)
-{
- int file_fd, dev_fd, mode = O_RDWR, rc = -1, cnt = 0, err, again;
- int errsv = 0;
-
- if (!lc || !*lc->device || !lc->filename)
- return -EINVAL;
-
- DBG(SETUP, ul_debugobj(lc, "device setup requested"));
-
- /*
- * Open backing file and device
- */
- if (lc->info.lo_flags & LO_FLAGS_READ_ONLY)
- mode = O_RDONLY;
-
- if ((file_fd = open(lc->filename, mode | O_CLOEXEC)) < 0) {
- if (mode != O_RDONLY && (errno == EROFS || errno == EACCES))
- file_fd = open(lc->filename, mode = O_RDONLY);
-
- if (file_fd < 0) {
- DBG(SETUP, ul_debugobj(lc, "open backing file failed: %m"));
- return -errno;
- }
- }
- DBG(SETUP, ul_debugobj(lc, "backing file open: OK"));
-
- if (lc->fd != -1 && lc->mode != mode) {
- DBG(SETUP, ul_debugobj(lc, "closing already open device (mode mismatch)"));
- close(lc->fd);
- lc->fd = -1;
- lc->mode = 0;
- }
-
- if (mode == O_RDONLY) {
- lc->flags |= LOOPDEV_FL_RDONLY; /* open() mode */
- lc->info.lo_flags |= LO_FLAGS_READ_ONLY; /* kernel loopdev mode */
- } else {
- lc->flags |= LOOPDEV_FL_RDWR; /* open() mode */
- lc->info.lo_flags &= ~LO_FLAGS_READ_ONLY;
- lc->flags &= ~LOOPDEV_FL_RDONLY;
- }
-
- do {
- errno = 0;
- dev_fd = loopcxt_get_fd(lc);
- if (dev_fd >= 0 || lc->control_ok == 0)
- break;
- if (errno != EACCES && errno != ENOENT)
- break;
- /* We have permissions to open /dev/xloop-control, but open
- * /dev/xloopN failed with EACCES, it's probably because udevd
- * does not applied chown yet. Let's wait a moment. */
- xusleep(25000);
- } while (cnt++ < 16);
-
- if (dev_fd < 0) {
- rc = -errno;
- goto err;
- }
-
- DBG(SETUP, ul_debugobj(lc, "device open: OK"));
-
- /*
- * Set FD
- */
- if (ioctl(dev_fd, LOOP_SET_FD, file_fd) < 0) {
- rc = -errno;
- errsv = errno;
- DBG(SETUP, ul_debugobj(lc, "LOOP_SET_FD failed: %m"));
- goto err;
- }
-
- DBG(SETUP, ul_debugobj(lc, "LOOP_SET_FD: OK"));
-
- if (lc->blocksize > 0
- && (rc = loopcxt_ioctl_blocksize(lc, lc->blocksize)) < 0) {
- errsv = -rc;
- goto err;
- }
-
- do {
- err = ioctl(dev_fd, LOOP_SET_STATUS64, &lc->info);
- again = err && errno == EAGAIN;
- if (again)
- xusleep(250000);
- } while (again);
- if (err) {
- rc = -errno;
- errsv = errno;
- DBG(SETUP, ul_debugobj(lc, "LOOP_SET_STATUS64 failed: %m"));
- goto err;
- }
-
- DBG(SETUP, ul_debugobj(lc, "LOOP_SET_STATUS64: OK"));
-
- if ((rc = loopcxt_check_size(lc, file_fd)))
- goto err;
-
- close(file_fd);
-
- memset(&lc->info, 0, sizeof(lc->info));
- lc->has_info = 0;
- lc->info_failed = 0;
-
- DBG(SETUP, ul_debugobj(lc, "success [rc=0]"));
- return 0;
-err:
- if (file_fd >= 0)
- close(file_fd);
- if (dev_fd >= 0 && rc != -EBUSY)
- ioctl(dev_fd, LOOP_CLR_FD, 0);
- if (errsv)
- errno = errsv;
-
- DBG(SETUP, ul_debugobj(lc, "failed [rc=%d]", rc));
- return rc;
-}
-
-/*
- * @lc: context
- *
- * Update status of the current device (see loopcxt_{set,get}_device()).
- *
- * Note that once initialized, kernel accepts only selected changes:
- * LO_FLAGS_AUTOCLEAR and LO_FLAGS_PARTSCAN
- * For more see linux/drivers/block/loop.c:loop_set_status()
- *
- * Returns: <0 on error, 0 on success.
- */
-int loopcxt_ioctl_status(struct loopdev_cxt *lc)
-{
- int dev_fd, rc = -1, err, again;
-
- errno = 0;
- dev_fd = loopcxt_get_fd(lc);
-
- if (dev_fd < 0) {
- rc = -errno;
- return rc;
- }
- DBG(SETUP, ul_debugobj(lc, "device open: OK"));
-
- do {
- err = ioctl(dev_fd, LOOP_SET_STATUS64, &lc->info);
- again = err && errno == EAGAIN;
- if (again)
- xusleep(250000);
- } while (again);
- if (err) {
- rc = -errno;
- DBG(SETUP, ul_debugobj(lc, "LOOP_SET_STATUS64 failed: %m"));
- return rc;
- }
-
- DBG(SETUP, ul_debugobj(lc, "LOOP_SET_STATUS64: OK"));
- return 0;
-}
-
-int loopcxt_ioctl_capacity(struct loopdev_cxt *lc)
-{
- int fd = loopcxt_get_fd(lc);
-
- if (fd < 0)
- return -EINVAL;
-
- /* Kernels prior to v2.6.30 don't support this ioctl */
- if (ioctl(fd, LOOP_SET_CAPACITY, 0) < 0) {
- int rc = -errno;
- DBG(CXT, ul_debugobj(lc, "LOOP_SET_CAPACITY failed: %m"));
- return rc;
- }
-
- DBG(CXT, ul_debugobj(lc, "capacity set"));
- return 0;
-}
-
-int loopcxt_ioctl_dio(struct loopdev_cxt *lc, unsigned long use_dio)
-{
- int fd = loopcxt_get_fd(lc);
-
- if (fd < 0)
- return -EINVAL;
-
- /* Kernels prior to v4.4 don't support this ioctl */
- if (ioctl(fd, LOOP_SET_DIRECT_IO, use_dio) < 0) {
- int rc = -errno;
- DBG(CXT, ul_debugobj(lc, "LOOP_SET_DIRECT_IO failed: %m"));
- return rc;
- }
-
- DBG(CXT, ul_debugobj(lc, "direct io set"));
- return 0;
-}
-
-/*
- * Kernel uses "unsigned long" as ioctl arg, but we use u64 for all sizes to
- * keep loopdev internal API simple.
- */
-int loopcxt_ioctl_blocksize(struct loopdev_cxt *lc, uint64_t blocksize)
-{
- int fd = loopcxt_get_fd(lc);
-
- if (fd < 0)
- return -EINVAL;
-
- /* Kernels prior to v4.14 don't support this ioctl */
- if (ioctl(fd, LOOP_SET_BLOCK_SIZE, (unsigned long) blocksize) < 0) {
- int rc = -errno;
- DBG(CXT, ul_debugobj(lc, "LOOP_SET_BLOCK_SIZE failed: %m"));
- return rc;
- }
-
- DBG(CXT, ul_debugobj(lc, "logical block size set"));
- return 0;
-}
-
-int loopcxt_delete_device(struct loopdev_cxt *lc)
-{
- int fd = loopcxt_get_fd(lc);
-
- if (fd < 0)
- return -EINVAL;
-
- if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
- DBG(CXT, ul_debugobj(lc, "LOOP_CLR_FD failed: %m"));
- return -errno;
- }
-
- DBG(CXT, ul_debugobj(lc, "device removed"));
- return 0;
-}
-
-int loopcxt_add_device(struct loopdev_cxt *lc)
-{
- int rc = -EINVAL;
- int ctl, nr = -1;
- const char *p, *dev = loopcxt_get_device(lc);
-
- if (!dev)
- goto done;
-
- if (!(lc->flags & LOOPDEV_FL_CONTROL)) {
- rc = -ENOSYS;
- goto done;
- }
-
- p = strrchr(dev, '/');
- if (!p || (sscanf(p, "/xloop%d", &nr) != 1 && sscanf(p, "/%d", &nr) != 1)
- || nr < 0)
- goto done;
-
- ctl = open(_PATH_DEV_LOOPCTL, O_RDWR|O_CLOEXEC);
- if (ctl >= 0) {
- DBG(CXT, ul_debugobj(lc, "add_device %d", nr));
- rc = ioctl(ctl, LOOP_CTL_ADD, nr);
- close(ctl);
- }
- lc->control_ok = rc >= 0 ? 1 : 0;
-done:
- DBG(CXT, ul_debugobj(lc, "add_device done [rc=%d]", rc));
- return rc;
-}
-
-/*
- * Note that LOOP_CTL_GET_FREE ioctl is supported since kernel 3.1. In older
- * kernels we have to check all loop devices to found unused one.
- *
- * See kernel commit 770fe30a46a12b6fb6b63fbe1737654d28e8484.
- */
-int loopcxt_find_unused(struct loopdev_cxt *lc)
-{
- int rc = -1;
-
- DBG(CXT, ul_debugobj(lc, "find_unused requested"));
-
- if (lc->flags & LOOPDEV_FL_CONTROL) {
- int ctl;
-
- DBG(CXT, ul_debugobj(lc, "using xloop-control"));
-
- ctl = open(_PATH_DEV_LOOPCTL, O_RDWR|O_CLOEXEC);
- if (ctl >= 0)
- rc = ioctl(ctl, LOOP_CTL_GET_FREE);
- if (rc >= 0) {
- char name[16];
- snprintf(name, sizeof(name), "xloop%d", rc);
-
- rc = loopiter_set_device(lc, name);
- }
- lc->control_ok = ctl >= 0 && rc == 0 ? 1 : 0;
- if (ctl >= 0)
- close(ctl);
- DBG(CXT, ul_debugobj(lc, "find_unused by xloop-control [rc=%d]", rc));
- }
-
- if (rc < 0) {
- DBG(CXT, ul_debugobj(lc, "using loop scan"));
- rc = loopcxt_init_iterator(lc, LOOPITER_FL_FREE);
- if (rc)
- return rc;
-
- rc = loopcxt_next(lc);
- loopcxt_deinit_iterator(lc);
- DBG(CXT, ul_debugobj(lc, "find_unused by scan [rc=%d]", rc));
- }
- return rc;
-}
-
-
-
-/*
- * Return: TRUE/FALSE
- */
-int loopdev_is_autoclear(const char *device)
-{
- struct loopdev_cxt lc;
- int rc;
-
- if (!device)
- return 0;
-
- rc = loopcxt_init(&lc, 0);
- if (!rc)
- rc = loopcxt_set_device(&lc, device);
- if (!rc)
- rc = loopcxt_is_autoclear(&lc);
-
- loopcxt_deinit(&lc);
- return rc;
-}
-
-char *loopdev_get_backing_file(const char *device)
-{
- struct loopdev_cxt lc;
- char *res = NULL;
-
- if (!device)
- return NULL;
- if (loopcxt_init(&lc, 0))
- return NULL;
- if (loopcxt_set_device(&lc, device) == 0)
- res = loopcxt_get_backing_file(&lc);
-
- loopcxt_deinit(&lc);
- return res;
-}
-
-/*
- * Returns: TRUE/FALSE
- */
-int loopdev_is_used(const char *device, const char *filename,
- uint64_t offset, uint64_t sizelimit, int flags)
-{
- struct loopdev_cxt lc;
- struct stat st;
- int rc = 0;
-
- if (!device || !filename)
- return 0;
-
- rc = loopcxt_init(&lc, 0);
- if (!rc)
- rc = loopcxt_set_device(&lc, device);
- if (rc)
- return rc;
-
- rc = !stat(filename, &st);
- rc = loopcxt_is_used(&lc, rc ? &st : NULL, filename, offset, sizelimit, flags);
-
- loopcxt_deinit(&lc);
- return rc;
-}
-
-int loopdev_delete(const char *device)
-{
- struct loopdev_cxt lc;
- int rc;
-
- if (!device)
- return -EINVAL;
-
- rc = loopcxt_init(&lc, 0);
- if (!rc)
- rc = loopcxt_set_device(&lc, device);
- if (!rc)
- rc = loopcxt_delete_device(&lc);
- loopcxt_deinit(&lc);
- return rc;
-}
-
-/*
- * Returns: 0 = success, < 0 error, 1 not found
- */
-int loopcxt_find_by_backing_file(struct loopdev_cxt *lc, const char *filename,
- uint64_t offset, uint64_t sizelimit, int flags)
-{
- int rc, hasst;
- struct stat st;
-
- if (!filename)
- return -EINVAL;
-
- hasst = !stat(filename, &st);
-
- rc = loopcxt_init_iterator(lc, LOOPITER_FL_USED);
- if (rc)
- return rc;
-
- while ((rc = loopcxt_next(lc)) == 0) {
-
- if (loopcxt_is_used(lc, hasst ? &st : NULL,
- filename, offset, sizelimit, flags))
- break;
- }
-
- loopcxt_deinit_iterator(lc);
- return rc;
-}
-
-/*
- * Returns: 0 = not found, < 0 error, 1 found, 2 found full size and offset match
- */
-int loopcxt_find_overlap(struct loopdev_cxt *lc, const char *filename,
- uint64_t offset, uint64_t sizelimit)
-{
- int rc, hasst;
- struct stat st;
-
- if (!filename)
- return -EINVAL;
-
- DBG(CXT, ul_debugobj(lc, "find_overlap requested"));
- hasst = !stat(filename, &st);
-
- rc = loopcxt_init_iterator(lc, LOOPITER_FL_USED);
- if (rc)
- return rc;
-
- while ((rc = loopcxt_next(lc)) == 0) {
- uint64_t lc_sizelimit, lc_offset;
-
- rc = loopcxt_is_used(lc, hasst ? &st : NULL,
- filename, offset, sizelimit, 0);
- if (!rc)
- continue; /* unused */
- if (rc < 0)
- break; /* error */
-
- DBG(CXT, ul_debugobj(lc, "found %s backed by %s",
- loopcxt_get_device(lc), filename));
-
- rc = loopcxt_get_offset(lc, &lc_offset);
- if (rc) {
- DBG(CXT, ul_debugobj(lc, "failed to get offset for device %s",
- loopcxt_get_device(lc)));
- break;
- }
- rc = loopcxt_get_sizelimit(lc, &lc_sizelimit);
- if (rc) {
- DBG(CXT, ul_debugobj(lc, "failed to get sizelimit for device %s",
- loopcxt_get_device(lc)));
- break;
- }
-
- /* full match */
- if (lc_sizelimit == sizelimit && lc_offset == offset) {
- DBG(CXT, ul_debugobj(lc, "overlapping loop device %s (full match)",
- loopcxt_get_device(lc)));
- rc = 2;
- goto found;
- }
-
- /* overlap */
- if (lc_sizelimit != 0 && offset >= lc_offset + lc_sizelimit)
- continue;
- if (sizelimit != 0 && offset + sizelimit <= lc_offset)
- continue;
-
- DBG(CXT, ul_debugobj(lc, "overlapping loop device %s",
- loopcxt_get_device(lc)));
- rc = 1;
- goto found;
- }
-
- if (rc == 1)
- rc = 0; /* not found */
-found:
- loopcxt_deinit_iterator(lc);
- DBG(CXT, ul_debugobj(lc, "find_overlap done [rc=%d]", rc));
- return rc;
-}
-
-/*
- * Returns allocated string with device name
- */
-char *loopdev_find_by_backing_file(const char *filename, uint64_t offset, uint64_t sizelimit, int flags)
-{
- struct loopdev_cxt lc;
- char *res = NULL;
-
- if (!filename)
- return NULL;
-
- if (loopcxt_init(&lc, 0))
- return NULL;
- if (loopcxt_find_by_backing_file(&lc, filename, offset, sizelimit, flags) == 0)
- res = loopcxt_strdup_device(&lc);
- loopcxt_deinit(&lc);
-
- return res;
-}
-
-/*
- * Returns number of loop devices associated with @file, if only one loop
- * device is associated with the given @filename and @loopdev is not NULL then
- * @loopdev returns name of the device.
- */
-int loopdev_count_by_backing_file(const char *filename, char **loopdev)
-{
- struct loopdev_cxt lc;
- int count = 0, rc;
-
- if (!filename)
- return -1;
-
- rc = loopcxt_init(&lc, 0);
- if (rc)
- return rc;
- if (loopcxt_init_iterator(&lc, LOOPITER_FL_USED))
- return -1;
-
- while(loopcxt_next(&lc) == 0) {
- char *backing = loopcxt_get_backing_file(&lc);
-
- if (!backing || strcmp(backing, filename) != 0) {
- free(backing);
- continue;
- }
-
- free(backing);
- if (loopdev && count == 0)
- *loopdev = loopcxt_strdup_device(&lc);
- count++;
- }
-
- loopcxt_deinit(&lc);
-
- if (loopdev && count > 1) {
- free(*loopdev);
- *loopdev = NULL;
- }
- return count;
-}
-
diff --git a/utils/lib/mangle.c b/utils/lib/mangle.c
deleted file mode 100644
index 1a3b89a..0000000
--- a/utils/lib/mangle.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Functions for \oct encoding used in mtab/fstab/swaps/etc.
- *
- * No copyright is claimed. This code is in the public domain; do with
- * it what you wish.
- *
- * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "mangle.h"
-#include "c.h"
-
-#define isoctal(a) (((a) & ~7) == '0')
-
-#define from_hex(c) (isdigit(c) ? c - '0' : tolower(c) - 'a' + 10)
-
-#define is_unwanted_char(x) (strchr(" \t\n\\", (unsigned int) x) != NULL)
-
-
-char *mangle(const char *s)
-{
- char *ss, *sp;
-
- if (!s)
- return NULL;
-
- ss = sp = malloc(4 * strlen(s) + 1);
- if (!sp)
- return NULL;
- while(1) {
- if (!*s) {
- *sp = '\0';
- break;
- }
- if (is_unwanted_char(*s)) {
- *sp++ = '\\';
- *sp++ = '0' + ((*s & 0300) >> 6);
- *sp++ = '0' + ((*s & 070) >> 3);
- *sp++ = '0' + (*s & 07);
- } else
- *sp++ = *s;
- s++;
- }
- return ss;
-}
-
-
-void unmangle_to_buffer(const char *s, char *buf, size_t len)
-{
- size_t sz = 0;
-
- if (!s)
- return;
-
- while(*s && sz < len - 1) {
- if (*s == '\\' && sz + 3 < len - 1 && isoctal(s[1]) &&
- isoctal(s[2]) && isoctal(s[3])) {
-
- *buf++ = 64*(s[1] & 7) + 8*(s[2] & 7) + (s[3] & 7);
- s += 4;
- sz += 4;
- } else {
- *buf++ = *s++;
- sz++;
- }
- }
- *buf = '\0';
-}
-
-size_t unhexmangle_to_buffer(const char *s, char *buf, size_t len)
-{
- size_t sz = 0;
- const char *buf0 = buf;
-
- if (!s)
- return 0;
-
- while(*s && sz < len - 1) {
- if (*s == '\\' && sz + 3 < len - 1 && s[1] == 'x' &&
- isxdigit(s[2]) && isxdigit(s[3])) {
-
- *buf++ = from_hex(s[2]) << 4 | from_hex(s[3]);
- s += 4;
- sz += 4;
- } else {
- *buf++ = *s++;
- sz++;
- }
- }
- *buf = '\0';
- return buf - buf0 + 1;
-}
-
-static inline const char *skip_nonspaces(const char *s)
-{
- while (s && *s && !(*s == ' ' || *s == '\t'))
- s++;
- return s;
-}
-
-/*
- * Returns mallocated buffer or NULL in case of error.
- */
-char *unmangle(const char *s, const char **end)
-{
- char *buf;
- const char *e;
- size_t sz;
-
- if (!s)
- return NULL;
-
- e = skip_nonspaces(s);
- sz = e - s + 1;
-
- if (end)
- *end = e;
- if (e == s)
- return NULL; /* empty string */
-
- buf = malloc(sz);
- if (!buf)
- return NULL;
-
- unmangle_to_buffer(s, buf, sz);
- return buf;
-}
-
-#ifdef TEST_PROGRAM_MANGLE
-#include <errno.h>
-int main(int argc, char *argv[])
-{
- char *p = NULL;
- if (argc < 3) {
- fprintf(stderr, "usage: %s --mangle|unmangle <string>\n",
- program_invocation_short_name);
- return EXIT_FAILURE;
- }
-
- if (!strcmp(argv[1], "--mangle")) {
- p = mangle(argv[2]);
- printf("mangled: '%s'\n", p);
- free(p);
- }
-
- else if (!strcmp(argv[1], "--unmangle")) {
- char *x = unmangle(argv[2], NULL);
-
- if (x) {
- printf("unmangled: '%s'\n", x);
- free(x);
- }
-
- x = strdup(argv[2]);
- if (x) {
- unmangle_to_buffer(x, x, strlen(x) + 1);
-
- printf("self-unmangled: '%s'\n", x);
- free(x);
- }
- }
-
- return EXIT_SUCCESS;
-}
-#endif /* TEST_PROGRAM_MANGLE */
diff --git a/utils/lib/match.c b/utils/lib/match.c
deleted file mode 100644
index a286a19..0000000
--- a/utils/lib/match.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2011 Karel Zak <kzak@redhat.com>
- *
- * This file may be redistributed under the terms of the
- * GNU Lesser General Public License.
- */
-
-#include <string.h>
-
-#include "match.h"
-
-/*
- * match_fstype:
- * @type: filesystem type
- * @pattern: filesystem name or comma delimited list of names
- *
- * The @pattern list of filesystem can be prefixed with a global
- * "no" prefix to invert matching of the whole list. The "no" could
- * also be used for individual items in the @pattern list. So,
- * "nofoo,bar" has the same meaning as "nofoo,nobar".
- */
-int match_fstype(const char *type, const char *pattern)
-{
- int no = 0; /* negated types list */
- int len;
- const char *p;
-
- if (!pattern && !type)
- return 1;
- if (!pattern)
- return 0;
-
- if (!strncmp(pattern, "no", 2)) {
- no = 1;
- pattern += 2;
- }
-
- /* Does type occur in types, separated by commas? */
- len = strlen(type);
- p = pattern;
- while(1) {
- if (!strncmp(p, "no", 2) && !strncasecmp(p+2, type, len) &&
- (p[len+2] == 0 || p[len+2] == ','))
- return 0;
- if (strncasecmp(p, type, len) == 0 && (p[len] == 0 || p[len] == ','))
- return !no;
- p = strchr(p,',');
- if (!p)
- break;
- p++;
- }
- return no;
-}
diff --git a/utils/lib/mbsalign.c b/utils/lib/mbsalign.c
deleted file mode 100644
index e251202..0000000
--- a/utils/lib/mbsalign.c
+++ /dev/null
@@ -1,627 +0,0 @@
-/* Align/Truncate a string in a given screen width
- Copyright (C) 2009-2010 Free Software Foundation, Inc.
-
- 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/>. */
-
-/* Written by Pádraig Brady. */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <limits.h>
-#include <ctype.h>
-
-#include "c.h"
-#include "mbsalign.h"
-#include "strutils.h"
-#include "widechar.h"
-
-/*
- * Counts number of cells in multibyte string. All control and
- * non-printable chars are ignored.
- *
- * Returns: number of cells.
- */
-size_t mbs_nwidth(const char *buf, size_t bufsz)
-{
- const char *p = buf, *last = buf;
- size_t width = 0;
-
-#ifdef HAVE_WIDECHAR
- mbstate_t st;
- memset(&st, 0, sizeof(st));
-#endif
- if (p && *p && bufsz)
- last = p + (bufsz - 1);
-
- while (p && *p && p <= last) {
- if (iscntrl((unsigned char) *p)) {
- p++;
-
- /* try detect "\e[x;ym" and skip on success */
- if (*p && *p == '[') {
- const char *e = p;
- while (*e && e < last && *e != 'm')
- e++;
- if (*e == 'm')
- p = e + 1;
- }
- continue;
- }
-#ifdef HAVE_WIDECHAR
- wchar_t wc;
- size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st);
-
- if (len == 0)
- break;
- if (len > 0 && iswprint(wc)) {
- int x = wcwidth(wc);
- if (x > 0)
- width += x;
- } else if (len == (size_t) -1 || len == (size_t) -2)
- len = 1;
- p += len;
-#else
- if (isprint((unsigned char) *p))
- width++;
- p++;
-#endif
- }
-
- return width;
-}
-
-size_t mbs_width(const char *s)
-{
- if (!s || !*s)
- return 0;
- return mbs_nwidth(s, strlen(s));
-}
-
-/*
- * Counts number of cells in multibyte string. For all control and
- * non-printable chars is the result width enlarged to store \x?? hex
- * sequence. See mbs_safe_encode().
- *
- * Returns: number of cells, @sz returns number of bytes.
- */
-size_t mbs_safe_nwidth(const char *buf, size_t bufsz, size_t *sz)
-{
- const char *p = buf, *last = buf;
- size_t width = 0, bytes = 0;
-
-#ifdef HAVE_WIDECHAR
- mbstate_t st;
- memset(&st, 0, sizeof(st));
-#endif
- if (p && *p && bufsz)
- last = p + (bufsz - 1);
-
- while (p && *p && p <= last) {
- if ((p < last && *p == '\\' && *(p + 1) == 'x')
- || iscntrl((unsigned char) *p)) {
- width += 4, bytes += 4; /* *p encoded to \x?? */
- p++;
- }
-#ifdef HAVE_WIDECHAR
- else {
- wchar_t wc;
- size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st);
-
- if (len == 0)
- break;
-
- if (len == (size_t) -1 || len == (size_t) -2) {
- len = 1;
- if (isprint((unsigned char) *p))
- width += 1, bytes += 1;
- else
- width += 4, bytes += 4;
-
- } else if (!iswprint(wc)) {
- width += len * 4; /* hex encode whole sequence */
- bytes += len * 4;
- } else {
- width += wcwidth(wc); /* number of cells */
- bytes += len; /* number of bytes */
- }
- p += len;
- }
-#else
- else if (!isprint((unsigned char) *p)) {
- width += 4, bytes += 4; /* *p encoded to \x?? */
- p++;
- } else {
- width++, bytes++;
- p++;
- }
-#endif
- }
-
- if (sz)
- *sz = bytes;
- return width;
-}
-
-size_t mbs_safe_width(const char *s)
-{
- if (!s || !*s)
- return 0;
- return mbs_safe_nwidth(s, strlen(s), NULL);
-}
-
-/*
- * Copy @s to @buf and replace control and non-printable chars with
- * \x?? hex sequence. The @width returns number of cells. The @safechars
- * are not encoded.
- *
- * The @buf has to be big enough to store mbs_safe_encode_size(strlen(s)))
- * bytes.
- */
-char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf, const char *safechars)
-{
- const char *p = s;
- char *r;
- size_t sz = s ? strlen(s) : 0;
-
-#ifdef HAVE_WIDECHAR
- mbstate_t st;
- memset(&st, 0, sizeof(st));
-#endif
- if (!sz || !buf)
- return NULL;
-
- r = buf;
- *width = 0;
-
- while (p && *p) {
- if (safechars && strchr(safechars, *p)) {
- *r++ = *p++;
- continue;
- }
-
- if ((*p == '\\' && *(p + 1) == 'x')
- || iscntrl((unsigned char) *p)) {
- sprintf(r, "\\x%02x", (unsigned char) *p);
- r += 4;
- *width += 4;
- p++;
- }
-#ifdef HAVE_WIDECHAR
- else {
- wchar_t wc;
- size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st);
-
- if (len == 0)
- break; /* end of string */
-
- if (len == (size_t) -1 || len == (size_t) -2) {
- len = 1;
- /*
- * Not valid multibyte sequence -- maybe it's
- * printable char according to the current locales.
- */
- if (!isprint((unsigned char) *p)) {
- sprintf(r, "\\x%02x", (unsigned char) *p);
- r += 4;
- *width += 4;
- } else {
- (*width)++;
- *r++ = *p;
- }
- } else if (!iswprint(wc)) {
- size_t i;
- for (i = 0; i < len; i++) {
- sprintf(r, "\\x%02x", (unsigned char) p[i]);
- r += 4;
- *width += 4;
- }
- } else {
- memcpy(r, p, len);
- r += len;
- *width += wcwidth(wc);
- }
- p += len;
- }
-#else
- else if (!isprint((unsigned char) *p)) {
- sprintf(r, "\\x%02x", (unsigned char) *p);
- p++;
- r += 4;
- *width += 4;
- } else {
- *r++ = *p++;
- (*width)++;
- }
-#endif
- }
-
- *r = '\0';
- return buf;
-}
-
-/*
- * Copy @s to @buf and replace broken sequences to \x?? hex sequence. The
- * @width returns number of cells. The @safechars are not encoded.
- *
- * The @buf has to be big enough to store mbs_safe_encode_size(strlen(s)))
- * bytes.
- */
-char *mbs_invalid_encode_to_buffer(const char *s, size_t *width, char *buf)
-{
- const char *p = s;
- char *r;
- size_t sz = s ? strlen(s) : 0;
-
-#ifdef HAVE_WIDECHAR
- mbstate_t st;
- memset(&st, 0, sizeof(st));
-#endif
- if (!sz || !buf)
- return NULL;
-
- r = buf;
- *width = 0;
-
- while (p && *p) {
-#ifdef HAVE_WIDECHAR
- wchar_t wc;
- size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st);
-#else
- size_t len = 1;
-#endif
-
- if (len == 0)
- break; /* end of string */
-
- if (len == (size_t) -1 || len == (size_t) -2) {
- len = 1;
- /*
- * Not valid multibyte sequence -- maybe it's
- * printable char according to the current locales.
- */
- if (!isprint((unsigned char) *p)) {
- sprintf(r, "\\x%02x", (unsigned char) *p);
- r += 4;
- *width += 4;
- } else {
- (*width)++;
- *r++ = *p;
- }
- } else if (*p == '\\' && *(p + 1) == 'x') {
- sprintf(r, "\\x%02x", (unsigned char) *p);
- r += 4;
- *width += 4;
- } else {
- memcpy(r, p, len);
- r += len;
- *width += wcwidth(wc);
- }
- p += len;
- }
-
- *r = '\0';
- return buf;
-}
-
-size_t mbs_safe_encode_size(size_t bytes)
-{
- return (bytes * 4) + 1;
-}
-
-/*
- * Returns allocated string where all control and non-printable chars are
- * replaced with \x?? hex sequence.
- */
-char *mbs_safe_encode(const char *s, size_t *width)
-{
- size_t sz = s ? strlen(s) : 0;
- char *buf, *ret = NULL;
-
- if (!sz)
- return NULL;
- buf = malloc(mbs_safe_encode_size(sz));
- if (buf)
- ret = mbs_safe_encode_to_buffer(s, width, buf, NULL);
- if (!ret)
- free(buf);
- return ret;
-}
-
-/*
- * Returns allocated string where all broken widechars chars are
- * replaced with \x?? hex sequence.
- */
-char *mbs_invalid_encode(const char *s, size_t *width)
-{
- size_t sz = s ? strlen(s) : 0;
- char *buf, *ret = NULL;
-
- if (!sz)
- return NULL;
- buf = malloc(mbs_safe_encode_size(sz));
- if (buf)
- ret = mbs_invalid_encode_to_buffer(s, width, buf);
- if (!ret)
- free(buf);
- return ret;
-}
-
-#ifdef HAVE_WIDECHAR
-
-static bool
-wc_ensure_printable (wchar_t *wchars)
-{
- bool replaced = false;
- wchar_t *wc = wchars;
- while (*wc)
- {
- if (!iswprint ((wint_t) *wc))
- {
- *wc = 0xFFFD; /* L'\uFFFD' (replacement char) */
- replaced = true;
- }
- wc++;
- }
- return replaced;
-}
-
-/* Truncate wchar string to width cells.
- * Returns number of cells used. */
-
-static size_t
-wc_truncate (wchar_t *wc, size_t width)
-{
- size_t cells = 0;
- int next_cells = 0;
-
- while (*wc)
- {
- next_cells = wcwidth (*wc);
- if (next_cells == -1) /* non printable */
- {
- *wc = 0xFFFD; /* L'\uFFFD' (replacement char) */
- next_cells = 1;
- }
- if (cells + next_cells > width)
- break;
-
- cells += next_cells;
- wc++;
- }
- *wc = L'\0';
- return cells;
-}
-
-static int
-rpl_wcswidth (const wchar_t *s, size_t n)
-{
- int ret = 0;
-
- while (n-- > 0 && *s != L'\0')
- {
- int nwidth = wcwidth (*s++);
- if (nwidth == -1) /* non printable */
- return -1;
- if (ret > (INT_MAX - nwidth)) /* overflow */
- return -1;
- ret += nwidth;
- }
-
- return ret;
-}
-#endif /* HAVE_WIDECHAR */
-
-/* Truncate multi-byte string to @width and returns number of
- * bytes of the new string @str, and in @width returns number
- * of cells.
- */
-size_t
-mbs_truncate(char *str, size_t *width)
-{
- ssize_t bytes = strlen(str);
-#ifdef HAVE_WIDECHAR
- ssize_t sz = mbstowcs(NULL, str, 0);
- wchar_t *wcs = NULL;
-
- if (sz == (ssize_t) -1)
- goto done;
-
- wcs = calloc(1, (sz + 1) * sizeof(wchar_t));
- if (!wcs)
- goto done;
-
- if (!mbstowcs(wcs, str, sz))
- goto done;
- *width = wc_truncate(wcs, *width);
- bytes = wcstombs(str, wcs, bytes);
-done:
- free(wcs);
-#else
- if (bytes >= 0 && *width < (size_t) bytes)
- bytes = *width;
-#endif
- if (bytes >= 0)
- str[bytes] = '\0';
- return bytes;
-}
-
-/* Write N_SPACES space characters to DEST while ensuring
- nothing is written beyond DEST_END. A terminating NUL
- is always added to DEST.
- A pointer to the terminating NUL is returned. */
-
-static char*
-mbs_align_pad (char *dest, const char* dest_end, size_t n_spaces, int padchar)
-{
- for (/* nothing */; n_spaces && (dest < dest_end); n_spaces--)
- *dest++ = padchar;
- *dest = '\0';
- return dest;
-}
-
-size_t
-mbsalign (const char *src, char *dest, size_t dest_size,
- size_t *width, mbs_align_t align, int flags)
-{
- return mbsalign_with_padding(src, dest, dest_size, width, align, flags, ' ');
-}
-
-/* Align a string, SRC, in a field of *WIDTH columns, handling multi-byte
- characters; write the result into the DEST_SIZE-byte buffer, DEST.
- ALIGNMENT specifies whether to left- or right-justify or to center.
- If SRC requires more than *WIDTH columns, truncate it to fit.
- When centering, the number of trailing spaces may be one less than the
- number of leading spaces. The FLAGS parameter is unused at present.
- Return the length in bytes required for the final result, not counting
- the trailing NUL. A return value of DEST_SIZE or larger means there
- wasn't enough space. DEST will be NUL terminated in any case.
- Return (size_t) -1 upon error (invalid multi-byte sequence in SRC,
- or malloc failure), unless MBA_UNIBYTE_FALLBACK is specified.
- Update *WIDTH to indicate how many columns were used before padding. */
-
-size_t
-mbsalign_with_padding (const char *src, char *dest, size_t dest_size,
- size_t *width, mbs_align_t align,
-#ifdef HAVE_WIDECHAR
- int flags,
-#else
- int flags __attribute__((__unused__)),
-#endif
- int padchar)
-{
- size_t ret = -1;
- size_t src_size = strlen (src) + 1;
- char *newstr = NULL;
- wchar_t *str_wc = NULL;
- const char *str_to_print = src;
- size_t n_cols = src_size - 1;
- size_t n_used_bytes = n_cols; /* Not including NUL */
- size_t n_spaces = 0, space_left;
-
-#ifdef HAVE_WIDECHAR
- bool conversion = false;
- bool wc_enabled = false;
-
- /* In multi-byte locales convert to wide characters
- to allow easy truncation. Also determine number
- of screen columns used. */
- if (MB_CUR_MAX > 1)
- {
- size_t src_chars = mbstowcs (NULL, src, 0);
- if (src_chars == (size_t) -1)
- {
- if (flags & MBA_UNIBYTE_FALLBACK)
- goto mbsalign_unibyte;
- else
- goto mbsalign_cleanup;
- }
- src_chars += 1; /* make space for NUL */
- str_wc = malloc (src_chars * sizeof (wchar_t));
- if (str_wc == NULL)
- {
- if (flags & MBA_UNIBYTE_FALLBACK)
- goto mbsalign_unibyte;
- else
- goto mbsalign_cleanup;
- }
- if (mbstowcs (str_wc, src, src_chars) != 0)
- {
- str_wc[src_chars - 1] = L'\0';
- wc_enabled = true;
- conversion = wc_ensure_printable (str_wc);
- n_cols = rpl_wcswidth (str_wc, src_chars);
- }
- }
-
- /* If we transformed or need to truncate the source string
- then create a modified copy of it. */
- if (wc_enabled && (conversion || (n_cols > *width)))
- {
- if (conversion)
- {
- /* May have increased the size by converting
- \t to \uFFFD for example. */
- src_size = wcstombs(NULL, str_wc, 0) + 1;
- }
- newstr = malloc (src_size);
- if (newstr == NULL)
- {
- if (flags & MBA_UNIBYTE_FALLBACK)
- goto mbsalign_unibyte;
- else
- goto mbsalign_cleanup;
- }
- str_to_print = newstr;
- n_cols = wc_truncate (str_wc, *width);
- n_used_bytes = wcstombs (newstr, str_wc, src_size);
- }
-
-mbsalign_unibyte:
-#endif
-
- if (n_cols > *width) /* Unibyte truncation required. */
- {
- n_cols = *width;
- n_used_bytes = n_cols;
- }
-
- if (*width > n_cols) /* Padding required. */
- n_spaces = *width - n_cols;
-
- /* indicate to caller how many cells needed (not including padding). */
- *width = n_cols;
-
- /* indicate to caller how many bytes needed (not including NUL). */
- ret = n_used_bytes + (n_spaces * 1);
-
- /* Write as much NUL terminated output to DEST as possible. */
- if (dest_size != 0)
- {
- char *dest_end = dest + dest_size - 1;
- size_t start_spaces;
- size_t end_spaces;
-
- switch (align)
- {
- case MBS_ALIGN_CENTER:
- start_spaces = n_spaces / 2 + n_spaces % 2;
- end_spaces = n_spaces / 2;
- break;
- case MBS_ALIGN_LEFT:
- start_spaces = 0;
- end_spaces = n_spaces;
- break;
- case MBS_ALIGN_RIGHT:
- start_spaces = n_spaces;
- end_spaces = 0;
- break;
- default:
- abort();
- }
-
- dest = mbs_align_pad (dest, dest_end, start_spaces, padchar);
- space_left = dest_end - dest;
- dest = mempcpy (dest, str_to_print, min (n_used_bytes, space_left));
- mbs_align_pad (dest, dest_end, end_spaces, padchar);
- }
-#ifdef HAVE_WIDECHAR
-mbsalign_cleanup:
-#endif
- free (str_wc);
- free (newstr);
-
- return ret;
-}
diff --git a/utils/lib/mbsedit.c b/utils/lib/mbsedit.c
deleted file mode 100644
index 8ce5901..0000000
--- a/utils/lib/mbsedit.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Very simple multibyte buffer editor. Allows to maintaine the current
- * position in the string, add and remove chars on the current position.
- *
- * This file may be distributed under the terms of the
- * GNU Lesser General Public License.
- *
- * Copyright (C) 2017 Karel Zak <kzak@redhat.com>
- */
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <stdio.h>
-
-#include "mbsalign.h"
-#include "mbsedit.h"
-
-struct mbs_editor *mbs_new_edit(char *buf, size_t bufsz, size_t ncells)
-{
- struct mbs_editor *edit = calloc(1, sizeof(*edit));
-
- if (edit) {
- edit->buf = buf;
- edit->max_bytes = bufsz;
- edit->max_cells = ncells;
- edit->cur_cells = mbs_safe_width(buf);
- edit->cur_bytes = strlen(buf);
- }
- return edit;
-}
-
-char *mbs_free_edit(struct mbs_editor *edit)
-{
- char *ret = edit ? edit->buf : NULL;
-
- free(edit);
- return ret;
-}
-
-static size_t mbs_next(const char *str, size_t *ncells)
-{
-#ifdef HAVE_WIDECHAR
- wchar_t wc;
- size_t n = 0;
-
- if (!str || !*str)
- return 0;
-
- n = mbrtowc(&wc, str, MB_CUR_MAX, NULL);
- *ncells = wcwidth(wc);
- return n;
-#else
- if (!str || !*str)
- return 0;
- *ncells = 1;
- return 1;
-#endif
-}
-
-static size_t mbs_prev(const char *start, const char *end, size_t *ncells)
-{
-#ifdef HAVE_WIDECHAR
- wchar_t wc = 0;
- const char *p, *prev;
- size_t n = 0;
-
- if (!start || !end || start == end || !*start)
- return 0;
-
- prev = p = start;
- while (p < end) {
- n = mbrtowc(&wc, p, MB_CUR_MAX, NULL);
- prev = p;
-
- if (n == (size_t) -1 || n == (size_t) -2)
- p++;
- else
- p += n;
- }
-
- if (prev == end)
- return 0;
- *ncells = wcwidth(wc);
- return n;
-#else
- if (!start || !end || start == end || !*start)
- return 0;
- *ncells = 1;
- return 1;
-#endif
-}
-
-int mbs_edit_goto(struct mbs_editor *edit, int where)
-{
- switch (where) {
- case MBS_EDIT_LEFT:
- if (edit->cursor == 0)
- return 1;
- else {
- size_t n, cells;
- n = mbs_prev(edit->buf, edit->buf + edit->cursor, &cells);
- if (n) {
- edit->cursor -= n;
- edit->cursor_cells -= cells;
- }
- }
- break;
- case MBS_EDIT_RIGHT:
- if (edit->cursor_cells >= edit->cur_cells)
- return 1;
- else {
- size_t n, cells;
- n = mbs_next(edit->buf + edit->cursor, &cells);
- if (n) {
- edit->cursor += n;
- edit->cursor_cells += cells;
- }
- }
- break;
- case MBS_EDIT_HOME:
- edit->cursor = 0;
- edit->cursor_cells = 0;
- break;
- case MBS_EDIT_END:
- edit->cursor = edit->cur_bytes;
- edit->cursor_cells = edit->cur_cells;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-/* Remove next MB from @str, returns number of removed bytes */
-static size_t remove_next(char *str, size_t *ncells)
-{
- /* all in bytes! */
- size_t bytes, move_bytes, n;
-
- n = mbs_next(str, ncells);
- bytes = strlen(str);
- move_bytes = bytes - n;
-
- memmove(str, str + n, move_bytes);
- str[bytes - n] = '\0';
- return n;
-}
-
-static size_t mbs_insert(char *str, wint_t c, size_t *ncells)
-{
- /* all in bytes! */
- size_t n = 1, bytes;
- char *in;
-
-#ifdef HAVE_WIDECHAR
- wchar_t wc = (wchar_t) c;
- char in_buf[MB_CUR_MAX];
-
- n = wctomb(in_buf, wc);
- if (n == (size_t) -1)
- return n;
- *ncells = wcwidth(wc);
- in = in_buf;
-#else
- *ncells = 1;
- in = (char *) &c;
-#endif
- bytes = strlen(str);
-
- memmove(str + n, str, bytes);
- memcpy(str, in, n);
- str[bytes + n] = '\0';
- return n;
-}
-
-static int mbs_edit_remove(struct mbs_editor *edit)
-{
- size_t n, ncells;
-
- if (edit->cur_cells == 0 || edit->cursor >= edit->cur_bytes)
- return 1;
-
- n = remove_next(edit->buf + edit->cursor, &ncells);
- if (n == (size_t)-1)
- return 1;
-
- edit->cur_bytes -= n;
- edit->cur_cells = mbs_safe_width(edit->buf);
- return 0;
-}
-
-int mbs_edit_delete(struct mbs_editor *edit)
-{
- if (edit->cursor >= edit->cur_bytes
- && mbs_edit_goto(edit, MBS_EDIT_LEFT) == 1)
- return 1;
-
- return mbs_edit_remove(edit);
-}
-
-int mbs_edit_backspace(struct mbs_editor *edit)
-{
- if (mbs_edit_goto(edit, MBS_EDIT_LEFT) == 0)
- return mbs_edit_remove(edit);
- return 1;
-}
-
-int mbs_edit_insert(struct mbs_editor *edit, wint_t c)
-{
- size_t n, ncells;
-
- if (edit->cur_bytes + MB_CUR_MAX > edit->max_bytes)
- return 1;
-
- n = mbs_insert(edit->buf + edit->cursor, c, &ncells);
- if (n == (size_t)-1)
- return 1;
-
- edit->cursor += n;
- edit->cursor_cells += ncells;
- edit->cur_bytes += n;
- edit->cur_cells = mbs_safe_width(edit->buf);
- return 0;
-}
diff --git a/utils/lib/md5.c b/utils/lib/md5.c
deleted file mode 100644
index 3765ab9..0000000
--- a/utils/lib/md5.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * This code implements the MD5 message-digest algorithm.
- * The algorithm is due to Ron Rivest. This code was
- * written by Colin Plumb in 1993, no copyright is claimed.
- * This code is in the public domain; do with it what you wish.
- *
- * Equivalent code is available from RSA Data Security, Inc.
- * This code has been tested against that, and is equivalent,
- * except that you don't need to include two pages of legalese
- * with every copy.
- *
- * To compute the message digest of a chunk of bytes, declare an
- * MD5Context structure, pass it to MD5Init, call MD5Update as
- * needed on buffers full of bytes, and then call MD5Final, which
- * will fill a supplied 16-byte array with the digest.
- */
-#include <string.h> /* for memcpy() */
-
-#include "md5.h"
-
-#if !defined(WORDS_BIGENDIAN)
-# define byteReverse(buf, len) /* Nothing */
-#else
-static void byteReverse(unsigned char *buf, unsigned longs);
-
-#ifndef ASM_MD5
-/*
- * Note: this code is harmless on little-endian machines.
- */
-static void byteReverse(unsigned char *buf, unsigned longs)
-{
- uint32_t t;
- do {
- t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
- ((unsigned) buf[1] << 8 | buf[0]);
- *(uint32_t *) buf = t;
- buf += 4;
- } while (--longs);
-}
-#endif /* !ASM_MD5 */
-#endif /* !WORDS_BIGENDIAN */
-
-/*
- * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
- * initialization constants.
- */
-void ul_MD5Init(struct UL_MD5Context *ctx)
-{
- ctx->buf[0] = 0x67452301;
- ctx->buf[1] = 0xefcdab89;
- ctx->buf[2] = 0x98badcfe;
- ctx->buf[3] = 0x10325476;
-
- ctx->bits[0] = 0;
- ctx->bits[1] = 0;
-}
-
-/*
- * Update context to reflect the concatenation of another buffer full
- * of bytes.
- */
-void ul_MD5Update(struct UL_MD5Context *ctx, unsigned char const *buf, unsigned len)
-{
- uint32_t t;
-
- /* Update bitcount */
-
- t = ctx->bits[0];
- if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
- ctx->bits[1]++; /* Carry from low to high */
- ctx->bits[1] += len >> 29;
-
- t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
-
- /* Handle any leading odd-sized chunks */
-
- if (t) {
- unsigned char *p = (unsigned char *) ctx->in + t;
-
- t = 64 - t;
- if (len < t) {
- memcpy(p, buf, len);
- return;
- }
- memcpy(p, buf, t);
- byteReverse(ctx->in, 16);
- ul_MD5Transform(ctx->buf, (uint32_t *) ctx->in);
- buf += t;
- len -= t;
- }
- /* Process data in 64-byte chunks */
-
- while (len >= 64) {
- memcpy(ctx->in, buf, 64);
- byteReverse(ctx->in, 16);
- ul_MD5Transform(ctx->buf, (uint32_t *) ctx->in);
- buf += 64;
- len -= 64;
- }
-
- /* Handle any remaining bytes of data. */
-
- memcpy(ctx->in, buf, len);
-}
-
-/*
- * Final wrapup - pad to 64-byte boundary with the bit pattern
- * 1 0* (64-bit count of bits processed, MSB-first)
- */
-void ul_MD5Final(unsigned char digest[UL_MD5LENGTH], struct UL_MD5Context *ctx)
-{
- unsigned count;
- unsigned char *p;
-
- /* Compute number of bytes mod 64 */
- count = (ctx->bits[0] >> 3) & 0x3F;
-
- /* Set the first char of padding to 0x80. This is safe since there is
- always at least one byte free */
- p = ctx->in + count;
- *p++ = 0x80;
-
- /* Bytes of padding needed to make 64 bytes */
- count = 64 - 1 - count;
-
- /* Pad out to 56 mod 64 */
- if (count < 8) {
- /* Two lots of padding: Pad the first block to 64 bytes */
- memset(p, 0, count);
- byteReverse(ctx->in, 16);
- ul_MD5Transform(ctx->buf, (uint32_t *) ctx->in);
-
- /* Now fill the next block with 56 bytes */
- memset(ctx->in, 0, 56);
- } else {
- /* Pad block to 56 bytes */
- memset(p, 0, count - 8);
- }
- byteReverse(ctx->in, 14);
-
- /* Append length in bits and transform.
- * Use memcpy to avoid aliasing problems. On most systems,
- * this will be optimized away to the same code.
- */
- memcpy(&ctx->in[14 * sizeof(uint32_t)], &ctx->bits[0], 4);
- memcpy(&ctx->in[15 * sizeof(uint32_t)], &ctx->bits[1], 4);
-
- ul_MD5Transform(ctx->buf, (uint32_t *) ctx->in);
- byteReverse((unsigned char *) ctx->buf, 4);
- memcpy(digest, ctx->buf, UL_MD5LENGTH);
- memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
-}
-
-#ifndef ASM_MD5
-
-/* The four core functions - F1 is optimized somewhat */
-
-/* #define F1(x, y, z) (x & y | ~x & z) */
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-/* This is the central step in the MD5 algorithm. */
-#define MD5STEP(f, w, x, y, z, data, s) \
- ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
-
-/*
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data. MD5Update blocks
- * the data and converts bytes into longwords for this routine.
- */
-void ul_MD5Transform(uint32_t buf[4], uint32_t const in[16])
-{
- register uint32_t a, b, c, d;
-
- a = buf[0];
- b = buf[1];
- c = buf[2];
- d = buf[3];
-
- MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
- MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
- MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
- MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
- MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
- MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
- MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
- MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
- MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
- MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
- MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
- MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
- MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
- MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
- MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
- MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
-
- MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
- MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
- MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
- MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
- MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
- MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
- MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
- MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
- MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
- MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
- MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
- MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
- MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
- MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
- MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
- MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
-
- MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
- MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
- MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
- MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
- MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
- MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
- MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
- MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
- MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
- MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
- MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
- MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
- MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
- MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
- MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
- MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
-
- MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
- MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
- MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
- MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
- MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
- MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
- MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
- MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
- MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
- MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
- MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
- MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
- MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
- MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
- MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
- MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
-
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
-}
-
-#endif
-
diff --git a/utils/lib/monotonic.c b/utils/lib/monotonic.c
deleted file mode 100644
index f0aeba6..0000000
--- a/utils/lib/monotonic.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Please, don't add this file to libcommon because clock_gettime() requires
- * -lrt on systems with old libc.
- *
- * No copyright is claimed. This code is in the public domain; do with
- * it what you wish.
- */
-#include <time.h>
-#include <signal.h>
-#ifdef HAVE_SYSINFO
-#include <sys/sysinfo.h>
-#endif
-#include <sys/time.h>
-
-#include "c.h"
-#include "monotonic.h"
-
-int get_boot_time(struct timeval *boot_time)
-{
-#ifdef CLOCK_BOOTTIME
- struct timespec hires_uptime;
- struct timeval lores_uptime;
-#endif
- struct timeval now;
-#ifdef HAVE_SYSINFO
- struct sysinfo info;
-#endif
-
- if (gettimeofday(&now, NULL) != 0)
- return -errno;
-#ifdef CLOCK_BOOTTIME
- if (clock_gettime(CLOCK_BOOTTIME, &hires_uptime) == 0) {
- TIMESPEC_TO_TIMEVAL(&lores_uptime, &hires_uptime);
- timersub(&now, &lores_uptime, boot_time);
- return 0;
- }
-#endif
-#ifdef HAVE_SYSINFO
- /* fallback */
- if (sysinfo(&info) != 0)
- return -errno;
-
- boot_time->tv_sec = now.tv_sec - info.uptime;
- boot_time->tv_usec = 0;
- return 0;
-#else
- return -ENOSYS;
-#endif
-}
-
-time_t get_suspended_time(void)
-{
-#if defined(CLOCK_BOOTTIME) && defined(CLOCK_MONOTONIC)
- struct timespec boot, mono;
-
- if (clock_gettime(CLOCK_BOOTTIME, &boot) == 0 &&
- clock_gettime(CLOCK_MONOTONIC, &mono) == 0)
- return boot.tv_sec - mono.tv_sec;
-#endif
- return 0;
-}
-
-int gettime_monotonic(struct timeval *tv)
-{
-#ifdef CLOCK_MONOTONIC
- /* Can slew only by ntp and adjtime */
- int ret;
- struct timespec ts;
-
- /* Linux specific, can't slew */
- if (!(ret = clock_gettime(UL_CLOCK_MONOTONIC, &ts))) {
- tv->tv_sec = ts.tv_sec;
- tv->tv_usec = ts.tv_nsec / 1000;
- }
- return ret;
-#else
- return gettimeofday(tv, NULL);
-#endif
-}
-
-
diff --git a/utils/lib/pager.c b/utils/lib/pager.c
deleted file mode 100644
index b3cf6ee..0000000
--- a/utils/lib/pager.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Based on linux-perf/git scm
- *
- * Some modifications and simplifications for util-linux
- * by Davidlohr Bueso <dave@xxxxxxx> - March 2012.
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <err.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <signal.h>
-
-#include "c.h"
-#include "xalloc.h"
-#include "nls.h"
-#include "ttyutils.h"
-#include "pager.h"
-
-#define NULL_DEVICE "/dev/null"
-
-static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
-
-struct child_process {
- const char **argv;
- pid_t pid;
- int in;
- int out;
- int err;
-
- int org_err;
- int org_out;
- struct sigaction orig_sigint;
- struct sigaction orig_sighup;
- struct sigaction orig_sigterm;
- struct sigaction orig_sigquit;
- struct sigaction orig_sigpipe;
-
- unsigned no_stdin:1;
- void (*preexec_cb)(void);
-};
-static struct child_process pager_process;
-
-static inline void close_pair(int fd[2])
-{
- close(fd[0]);
- close(fd[1]);
-}
-
-static int start_command(struct child_process *cmd)
-{
- int need_in;
- int fdin[2];
-
- /*
- * In case of errors we must keep the promise to close FDs
- * that have been passed in via ->in and ->out.
- */
- need_in = !cmd->no_stdin && cmd->in < 0;
- if (need_in) {
- if (pipe(fdin) < 0) {
- if (cmd->out > 0)
- close(cmd->out);
- return -1;
- }
- cmd->in = fdin[1];
- }
-
- fflush(NULL);
- cmd->pid = fork();
- if (!cmd->pid) {
- if (need_in) {
- dup2(fdin[0], STDIN_FILENO);
- close_pair(fdin);
- } else if (cmd->in > 0) {
- dup2(cmd->in, STDIN_FILENO);
- close(cmd->in);
- }
-
- cmd->preexec_cb();
- execvp(cmd->argv[0], (char *const*) cmd->argv);
- errexec(cmd->argv[0]);
- }
-
- if (cmd->pid < 0) {
- if (need_in)
- close_pair(fdin);
- else if (cmd->in)
- close(cmd->in);
- return -1;
- }
-
- if (need_in)
- close(fdin[0]);
- else if (cmd->in)
- close(cmd->in);
- return 0;
-}
-
-static int wait_or_whine(pid_t pid)
-{
- for (;;) {
- int status, code;
- pid_t waiting = waitpid(pid, &status, 0);
-
- if (waiting < 0) {
- if (errno == EINTR)
- continue;
- err(EXIT_FAILURE, _("waitpid failed (%s)"), strerror(errno));
- }
- if (waiting != pid)
- return -1;
- if (WIFSIGNALED(status))
- return -1;
-
- if (!WIFEXITED(status))
- return -1;
- code = WEXITSTATUS(status);
- switch (code) {
- case 127:
- return -1;
- case 0:
- return 0;
- default:
- return -1;
- }
- }
-}
-
-static int finish_command(struct child_process *cmd)
-{
- return wait_or_whine(cmd->pid);
-}
-
-static void pager_preexec(void)
-{
- /*
- * Work around bug in "less" by not starting it until we
- * have real input
- */
- fd_set in, ex;
-
- FD_ZERO(&in);
- FD_SET(STDIN_FILENO, &in);
- ex = in;
-
- select(STDIN_FILENO + 1, &in, NULL, &ex, NULL);
-
- if (setenv("LESS", "FRSX", 0) != 0)
- warn(_("failed to set the %s environment variable"), "LESS");
-}
-
-static void wait_for_pager(void)
-{
- if (pager_process.pid == 0)
- return;
-
- fflush(stdout);
- fflush(stderr);
- /* signal EOF to pager */
- close(STDOUT_FILENO);
- close(STDERR_FILENO);
- finish_command(&pager_process);
-}
-
-static void wait_for_pager_signal(int signo)
-{
- wait_for_pager();
- raise(signo);
-}
-
-static int has_command(const char *cmd)
-{
- const char *path;
- char *p, *s;
- int rc = 0;
-
- if (!cmd)
- goto done;
- if (*cmd == '/') {
- rc = access(cmd, X_OK) == 0;
- goto done;
- }
-
- path = getenv("PATH");
- if (!path)
- goto done;
- p = xstrdup(path);
- if (!p)
- goto done;
-
- for(s = strtok(p, ":"); s; s = strtok(NULL, ":")) {
- int fd = open(s, O_RDONLY|O_CLOEXEC);
- if (fd < 0)
- continue;
- rc = faccessat(fd, cmd, X_OK, 0) == 0;
- close(fd);
- if (rc)
- break;
- }
- free(p);
-done:
- /*fprintf(stderr, "has PAGER %s rc=%d\n", cmd, rc);*/
- return rc;
-}
-
-static void __setup_pager(void)
-{
- const char *pager = getenv("PAGER");
- struct sigaction sa;
-
- if (!isatty(STDOUT_FILENO))
- return;
-
- if (!pager)
- pager = "less";
- else if (!*pager || !strcmp(pager, "cat"))
- return;
-
- if (!has_command(pager))
- return;
-
- /* spawn the pager */
- pager_argv[2] = pager;
- pager_process.argv = pager_argv;
- pager_process.in = -1;
- pager_process.preexec_cb = pager_preexec;
-
- if (start_command(&pager_process))
- return;
-
- /* original process continues, but writes to the pipe */
- dup2(pager_process.in, STDOUT_FILENO);
- if (isatty(STDERR_FILENO))
- dup2(pager_process.in, STDERR_FILENO);
- close(pager_process.in);
-
- memset(&sa, 0, sizeof(sa));
- sa.sa_handler = wait_for_pager_signal;
-
- /* this makes sure that the parent terminates after the pager */
- sigaction(SIGINT, &sa, &pager_process.orig_sigint);
- sigaction(SIGHUP, &sa, &pager_process.orig_sighup);
- sigaction(SIGTERM, &sa, &pager_process.orig_sigterm);
- sigaction(SIGQUIT, &sa, &pager_process.orig_sigquit);
- sigaction(SIGPIPE, &sa, &pager_process.orig_sigpipe);
-}
-
-/* Setup pager and redirects output to the $PAGER. The pager is closed at exit.
- */
-void pager_redirect(void)
-{
- if (pager_process.pid)
- return; /* already running */
-
- __setup_pager();
-
- atexit(wait_for_pager);
-}
-
-/* Setup pager and redirect output, the pager may be closed by pager_close().
- */
-void pager_open(void)
-{
- if (pager_process.pid)
- return; /* already running */
-
- pager_process.org_out = dup(STDOUT_FILENO);
- pager_process.org_err = dup(STDERR_FILENO);
-
- __setup_pager();
-}
-
-/* Close pager and restore original std{out,err}.
- */
-void pager_close(void)
-{
- if (pager_process.pid == 0)
- return;
-
- wait_for_pager();
-
- /* restore original output */
- dup2(pager_process.org_out, STDOUT_FILENO);
- dup2(pager_process.org_err, STDERR_FILENO);
-
- close(pager_process.org_out);
- close(pager_process.org_err);
-
- /* restore original segnals setting */
- sigaction(SIGINT, &pager_process.orig_sigint, NULL);
- sigaction(SIGHUP, &pager_process.orig_sighup, NULL);
- sigaction(SIGTERM, &pager_process.orig_sigterm, NULL);
- sigaction(SIGQUIT, &pager_process.orig_sigquit, NULL);
- sigaction(SIGPIPE, &pager_process.orig_sigpipe, NULL);
-
- memset(&pager_process, 0, sizeof(pager_process));
-}
-
-#ifdef TEST_PROGRAM_PAGER
-
-#define MAX 255
-
-int main(int argc __attribute__ ((__unused__)),
- char *argv[] __attribute__ ((__unused__)))
-{
- int i;
-
- pager_redirect();
- for (i = 0; i < MAX; i++)
- printf("%d\n", i);
- return EXIT_SUCCESS;
-}
-#endif /* TEST_PROGRAM_PAGER */
diff --git a/utils/lib/path.c b/utils/lib/path.c
deleted file mode 100644
index 75fa853..0000000
--- a/utils/lib/path.c
+++ /dev/null
@@ -1,1248 +0,0 @@
-/*
- * Simple functions to access files. Paths can be globally prefixed to read
- * data from an alternative source (e.g. a /proc dump for regression tests).
- *
- * The paths is possible to format by printf-like way for functions with "f"
- * postfix in the name (e.g. readf, openf, ... ul_path_readf_u64()).
- *
- * The ul_path_read_* API is possible to use without path_cxt handler. In this
- * case is not possible to use global prefix and printf-like formatting.
- *
- * No copyright is claimed. This code is in the public domain; do with
- * it what you wish.
- *
- * Written by Karel Zak <kzak@redhat.com> [February 2018]
- */
-#include <stdarg.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <inttypes.h>
-#include <errno.h>
-
-#include "c.h"
-#include "fileutils.h"
-#include "all-io.h"
-#include "path.h"
-#include "debug.h"
-#include "strutils.h"
-
-/*
- * Debug stuff (based on include/debug.h)
- */
-static UL_DEBUG_DEFINE_MASK(ulpath);
-UL_DEBUG_DEFINE_MASKNAMES(ulpath) = UL_DEBUG_EMPTY_MASKNAMES;
-
-#define ULPATH_DEBUG_INIT (1 << 1)
-#define ULPATH_DEBUG_CXT (1 << 2)
-
-#define DBG(m, x) __UL_DBG(ulpath, ULPATH_DEBUG_, m, x)
-#define ON_DBG(m, x) __UL_DBG_CALL(ulpath, ULPATH_DEBUG_, m, x)
-
-#define UL_DEBUG_CURRENT_MASK UL_DEBUG_MASK(ulpath)
-#include "debugobj.h"
-
-void ul_path_init_debug(void)
-{
- if (ulpath_debug_mask)
- return;
- __UL_INIT_DEBUG_FROM_ENV(ulpath, ULPATH_DEBUG_, 0, ULPATH_DEBUG);
-}
-
-struct path_cxt *ul_new_path(const char *dir, ...)
-{
- struct path_cxt *pc = calloc(1, sizeof(*pc));
-
- if (!pc)
- return NULL;
-
- DBG(CXT, ul_debugobj(pc, "alloc"));
-
- pc->refcount = 1;
- pc->dir_fd = -1;
-
- if (dir) {
- int rc;
- va_list ap;
-
- va_start(ap, dir);
- rc = vasprintf(&pc->dir_path, dir, ap);
- va_end(ap);
-
- if (rc < 0 || !pc->dir_path)
- goto fail;
- }
- return pc;
-fail:
- ul_unref_path(pc);
- return NULL;
-}
-
-void ul_ref_path(struct path_cxt *pc)
-{
- if (pc)
- pc->refcount++;
-}
-
-void ul_unref_path(struct path_cxt *pc)
-{
- if (!pc)
- return;
-
- pc->refcount--;
-
- if (pc->refcount <= 0) {
- DBG(CXT, ul_debugobj(pc, "dealloc"));
- if (pc->dialect)
- pc->free_dialect(pc);
- ul_path_close_dirfd(pc);
- free(pc->dir_path);
- free(pc->prefix);
- free(pc);
- }
-}
-
-int ul_path_set_prefix(struct path_cxt *pc, const char *prefix)
-{
- char *p = NULL;
-
- assert(pc->dir_fd < 0);
-
- if (prefix) {
- p = strdup(prefix);
- if (!p)
- return -ENOMEM;
- }
-
- free(pc->prefix);
- pc->prefix = p;
- DBG(CXT, ul_debugobj(pc, "new prefix: '%s'", p));
- return 0;
-}
-
-const char *ul_path_get_prefix(struct path_cxt *pc)
-{
- return pc ? pc->prefix : NULL;
-}
-
-int ul_path_set_dir(struct path_cxt *pc, const char *dir)
-{
- char *p = NULL;
-
- if (dir) {
- p = strdup(dir);
- if (!p)
- return -ENOMEM;
- }
-
- if (pc->dir_fd >= 0) {
- close(pc->dir_fd);
- pc->dir_fd = -1;
- }
-
- free(pc->dir_path);
- pc->dir_path = p;
- DBG(CXT, ul_debugobj(pc, "new dir: '%s'", p));
- return 0;
-}
-
-const char *ul_path_get_dir(struct path_cxt *pc)
-{
- return pc ? pc->dir_path : NULL;
-}
-
-int ul_path_set_dialect(struct path_cxt *pc, void *data, void free_data(struct path_cxt *))
-{
- pc->dialect = data;
- pc->free_dialect = free_data;
- DBG(CXT, ul_debugobj(pc, "(re)set dialect"));
- return 0;
-}
-
-void *ul_path_get_dialect(struct path_cxt *pc)
-{
- return pc ? pc->dialect : NULL;
-}
-
-int ul_path_set_enoent_redirect(struct path_cxt *pc, int (*func)(struct path_cxt *, const char *, int *))
-{
- pc->redirect_on_enoent = func;
- return 0;
-}
-
-static const char *get_absdir(struct path_cxt *pc)
-{
- int rc;
- const char *dirpath;
-
- if (!pc->prefix)
- return pc->dir_path;
-
- dirpath = pc->dir_path;
- if (!dirpath)
- return pc->prefix;
- if (*dirpath == '/')
- dirpath++;
-
- rc = snprintf(pc->path_buffer, sizeof(pc->path_buffer), "%s/%s", pc->prefix, dirpath);
- if (rc < 0)
- return NULL;
- if ((size_t)rc >= sizeof(pc->path_buffer)) {
- errno = ENAMETOOLONG;
- return NULL;
- }
-
- return pc->path_buffer;
-}
-
-int ul_path_is_accessible(struct path_cxt *pc)
-{
- const char *path;
- assert(pc);
-
- if (pc->dir_fd >= 0)
- return 1;
-
- path = get_absdir(pc);
- if (!path)
- return 0;
- return access(path, F_OK) == 0;
-}
-
-int ul_path_get_dirfd(struct path_cxt *pc)
-{
- assert(pc);
- assert(pc->dir_path);
-
- if (pc->dir_fd < 0) {
- const char *path = get_absdir(pc);
- if (!path)
- return -errno;
-
- DBG(CXT, ul_debugobj(pc, "opening dir: '%s'", path));
- pc->dir_fd = open(path, O_RDONLY|O_CLOEXEC);
- }
-
- return pc->dir_fd;
-}
-
-/* Note that next ul_path_get_dirfd() will reopen the directory */
-void ul_path_close_dirfd(struct path_cxt *pc)
-{
- assert(pc);
-
- if (pc->dir_fd >= 0) {
- DBG(CXT, ul_debugobj(pc, "closing dir"));
- close(pc->dir_fd);
- pc->dir_fd = -1;
- }
-}
-
-int ul_path_isopen_dirfd(struct path_cxt *pc)
-{
- return pc && pc->dir_fd >= 0;
-}
-
-static const char *ul_path_mkpath(struct path_cxt *pc, const char *path, va_list ap)
-{
- int rc;
-
- errno = 0;
-
- rc = vsnprintf(pc->path_buffer, sizeof(pc->path_buffer), path, ap);
- if (rc < 0) {
- if (!errno)
- errno = EINVAL;
- return NULL;
- }
-
- if ((size_t)rc >= sizeof(pc->path_buffer)) {
- errno = ENAMETOOLONG;
- return NULL;
- }
-
- return pc->path_buffer;
-}
-
-char *ul_path_get_abspath(struct path_cxt *pc, char *buf, size_t bufsz, const char *path, ...)
-{
- if (path) {
- int rc;
- va_list ap;
- const char *tail = NULL, *dirpath = pc->dir_path;
-
- va_start(ap, path);
- tail = ul_path_mkpath(pc, path, ap);
- va_end(ap);
-
- if (dirpath && *dirpath == '/')
- dirpath++;
- if (tail && *tail == '/')
- tail++;
-
- rc = snprintf(buf, bufsz, "%s/%s/%s",
- pc->prefix ? pc->prefix : "",
- dirpath ? dirpath : "",
- tail ? tail : "");
-
- if ((size_t)rc >= bufsz) {
- errno = ENAMETOOLONG;
- return NULL;
- }
- } else {
- const char *tmp = get_absdir(pc);
-
- if (!tmp)
- return NULL;
- xstrncpy(buf, tmp, bufsz);
- }
-
- return buf;
-}
-
-
-int ul_path_access(struct path_cxt *pc, int mode, const char *path)
-{
- int rc;
-
- if (!pc) {
- rc = access(path, mode);
- DBG(CXT, ul_debug("access '%s' [no context, rc=%d]", path, rc));
- } else {
- int dir = ul_path_get_dirfd(pc);
- if (dir < 0)
- return dir;
- if (*path == '/')
- path++;
-
- rc = faccessat(dir, path, mode, 0);
-
- if (rc && errno == ENOENT
- && pc->redirect_on_enoent
- && pc->redirect_on_enoent(pc, path, &dir) == 0)
- rc = faccessat(dir, path, mode, 0);
-
- DBG(CXT, ul_debugobj(pc, "access: '%s' [rc=%d]", path, rc));
- }
- return rc;
-}
-
-int ul_path_accessf(struct path_cxt *pc, int mode, const char *path, ...)
-{
- va_list ap;
- const char *p;
-
- va_start(ap, path);
- p = ul_path_mkpath(pc, path, ap);
- va_end(ap);
-
- return !p ? -errno : ul_path_access(pc, mode, p);
-}
-
-int ul_path_stat(struct path_cxt *pc, struct stat *sb, const char *path)
-{
- int rc;
-
- if (!pc) {
- rc = stat(path, sb);
- DBG(CXT, ul_debug("stat '%s' [no context, rc=%d]", path, rc));
- } else {
- int dir = ul_path_get_dirfd(pc);
- if (dir < 0)
- return dir;
- if (*path == '/')
- path++;
-
- rc = fstatat(dir, path, sb, 0);
-
- if (rc && errno == ENOENT
- && pc->redirect_on_enoent
- && pc->redirect_on_enoent(pc, path, &dir) == 0)
- rc = fstatat(dir, path, sb, 0);
-
- DBG(CXT, ul_debugobj(pc, "stat '%s' [rc=%d]", path, rc));
- }
- return rc;
-}
-
-int ul_path_open(struct path_cxt *pc, int flags, const char *path)
-{
- int fd;
-
- if (!pc) {
- fd = open(path, flags);
- DBG(CXT, ul_debug("opening '%s' [no context]", path));
- } else {
- int fdx;
- int dir = ul_path_get_dirfd(pc);
- if (dir < 0)
- return dir;
-
- if (*path == '/')
- path++;
-
- fdx = fd = openat(dir, path, flags);
-
- if (fd < 0 && errno == ENOENT
- && pc->redirect_on_enoent
- && pc->redirect_on_enoent(pc, path, &dir) == 0)
- fd = openat(dir, path, flags);
-
- DBG(CXT, ul_debugobj(pc, "opening '%s'%s", path, fdx != fd ? " [redirected]" : ""));
- }
- return fd;
-}
-
-int ul_path_vopenf(struct path_cxt *pc, int flags, const char *path, va_list ap)
-{
- const char *p = ul_path_mkpath(pc, path, ap);
-
- return !p ? -errno : ul_path_open(pc, flags, p);
-}
-
-int ul_path_openf(struct path_cxt *pc, int flags, const char *path, ...)
-{
- va_list ap;
- int rc;
-
- va_start(ap, path);
- rc = ul_path_vopenf(pc, flags, path, ap);
- va_end(ap);
-
- return rc;
-}
-
-/*
- * Maybe stupid, but good enough ;-)
- */
-static int mode2flags(const char *mode)
-{
- int flags = 0;
- const char *p;
-
- for (p = mode; p && *p; p++) {
- if (*p == 'r' && *(p + 1) == '+')
- flags |= O_RDWR;
- else if (*p == 'r')
- flags |= O_RDONLY;
-
- else if (*p == 'w' && *(p + 1) == '+')
- flags |= O_RDWR | O_TRUNC;
- else if (*p == 'w')
- flags |= O_WRONLY | O_TRUNC;
-
- else if (*p == 'a' && *(p + 1) == '+')
- flags |= O_RDWR | O_APPEND;
- else if (*p == 'a')
- flags |= O_WRONLY | O_APPEND;
-#ifdef O_CLOEXEC
- else if (*p == *UL_CLOEXECSTR)
- flags |= O_CLOEXEC;
-#endif
- }
-
- return flags;
-}
-
-FILE *ul_path_fopen(struct path_cxt *pc, const char *mode, const char *path)
-{
- int flags = mode2flags(mode);
- int fd = ul_path_open(pc, flags, path);
-
- if (fd < 0)
- return NULL;
-
- return fdopen(fd, mode);
-}
-
-
-FILE *ul_path_vfopenf(struct path_cxt *pc, const char *mode, const char *path, va_list ap)
-{
- const char *p = ul_path_mkpath(pc, path, ap);
-
- return !p ? NULL : ul_path_fopen(pc, mode, p);
-}
-
-FILE *ul_path_fopenf(struct path_cxt *pc, const char *mode, const char *path, ...)
-{
- FILE *f;
- va_list ap;
-
- va_start(ap, path);
- f = ul_path_vfopenf(pc, mode, path, ap);
- va_end(ap);
-
- return f;
-}
-
-/*
- * Open directory @path in read-onl mode. If the path is NULL then duplicate FD
- * to the directory addressed by @pc.
- */
-DIR *ul_path_opendir(struct path_cxt *pc, const char *path)
-{
- DIR *dir;
- int fd = -1;
-
- if (path)
- fd = ul_path_open(pc, O_RDONLY|O_CLOEXEC, path);
- else if (pc->dir_path) {
- int dirfd;
-
- DBG(CXT, ul_debugobj(pc, "duplicate dir path"));
- dirfd = ul_path_get_dirfd(pc);
- if (dirfd >= 0)
- fd = dup_fd_cloexec(dirfd, STDERR_FILENO + 1);
- }
-
- if (fd < 0)
- return NULL;
-
- dir = fdopendir(fd);
- if (!dir) {
- close(fd);
- return NULL;
- }
- if (!path)
- rewinddir(dir);
- return dir;
-}
-
-
-/*
- * Open directory @path in read-onl mode. If the path is NULL then duplicate FD
- * to the directory addressed by @pc.
- */
-DIR *ul_path_vopendirf(struct path_cxt *pc, const char *path, va_list ap)
-{
- const char *p = ul_path_mkpath(pc, path, ap);
-
- return !p ? NULL : ul_path_opendir(pc, p);
-}
-
-/*
- * Open directory @path in read-onl mode. If the path is NULL then duplicate FD
- * to the directory addressed by @pc.
- */
-DIR *ul_path_opendirf(struct path_cxt *pc, const char *path, ...)
-{
- va_list ap;
- DIR *dir;
-
- va_start(ap, path);
- dir = ul_path_vopendirf(pc, path, ap);
- va_end(ap);
-
- return dir;
-}
-
-/*
- * If @path is NULL then readlink is called on @pc directory.
- */
-ssize_t ul_path_readlink(struct path_cxt *pc, char *buf, size_t bufsiz, const char *path)
-{
- int dirfd;
-
- if (!path) {
- const char *p = get_absdir(pc);
- if (!p)
- return -errno;
- return readlink(p, buf, bufsiz);
- }
-
- dirfd = ul_path_get_dirfd(pc);
- if (dirfd < 0)
- return dirfd;
-
- if (*path == '/')
- path++;
-
- return readlinkat(dirfd, path, buf, bufsiz);
-}
-
-/*
- * If @path is NULL then readlink is called on @pc directory.
- */
-ssize_t ul_path_readlinkf(struct path_cxt *pc, char *buf, size_t bufsiz, const char *path, ...)
-{
- const char *p;
- va_list ap;
-
- va_start(ap, path);
- p = ul_path_mkpath(pc, path, ap);
- va_end(ap);
-
- return !p ? -errno : ul_path_readlink(pc, buf, bufsiz, p);
-}
-
-int ul_path_read(struct path_cxt *pc, char *buf, size_t len, const char *path)
-{
- int rc, errsv;
- int fd;
-
- fd = ul_path_open(pc, O_RDONLY|O_CLOEXEC, path);
- if (fd < 0)
- return -errno;
-
- DBG(CXT, ul_debug(" reading '%s'", path));
- rc = read_all(fd, buf, len);
-
- errsv = errno;
- close(fd);
- errno = errsv;
- return rc;
-}
-
-int ul_path_vreadf(struct path_cxt *pc, char *buf, size_t len, const char *path, va_list ap)
-{
- const char *p = ul_path_mkpath(pc, path, ap);
-
- return !p ? -errno : ul_path_read(pc, buf, len, p);
-}
-
-int ul_path_readf(struct path_cxt *pc, char *buf, size_t len, const char *path, ...)
-{
- va_list ap;
- int rc;
-
- va_start(ap, path);
- rc = ul_path_vreadf(pc, buf, len, path, ap);
- va_end(ap);
-
- return rc;
-}
-
-
-/*
- * Returns newly allocated buffer with data from file. Maximal size is BUFSIZ
- * (send patch if you need something bigger;-)
- *
- * Returns size of the string!
- */
-int ul_path_read_string(struct path_cxt *pc, char **str, const char *path)
-{
- char buf[BUFSIZ];
- int rc;
-
- if (!str)
- return -EINVAL;
-
- *str = NULL;
- rc = ul_path_read(pc, buf, sizeof(buf) - 1, path);
- if (rc < 0)
- return rc;
-
- /* Remove tailing newline (usual in sysfs) */
- if (rc > 0 && *(buf + rc - 1) == '\n')
- --rc;
-
- buf[rc] = '\0';
- *str = strdup(buf);
- if (!*str)
- rc = -ENOMEM;
-
- return rc;
-}
-
-int ul_path_readf_string(struct path_cxt *pc, char **str, const char *path, ...)
-{
- const char *p;
- va_list ap;
-
- va_start(ap, path);
- p = ul_path_mkpath(pc, path, ap);
- va_end(ap);
-
- return !p ? -errno : ul_path_read_string(pc, str, p);
-}
-
-int ul_path_read_buffer(struct path_cxt *pc, char *buf, size_t bufsz, const char *path)
-{
- int rc = ul_path_read(pc, buf, bufsz - 1, path);
- if (rc < 0)
- return rc;
-
- /* Remove tailing newline (usual in sysfs) */
- if (rc > 0 && *(buf + rc - 1) == '\n')
- buf[--rc] = '\0';
- else
- buf[rc - 1] = '\0';
-
- return rc;
-}
-
-int ul_path_readf_buffer(struct path_cxt *pc, char *buf, size_t bufsz, const char *path, ...)
-{
- const char *p;
- va_list ap;
-
- va_start(ap, path);
- p = ul_path_mkpath(pc, path, ap);
- va_end(ap);
-
- return !p ? -errno : ul_path_read_buffer(pc, buf, bufsz, p);
-}
-
-int ul_path_scanf(struct path_cxt *pc, const char *path, const char *fmt, ...)
-{
- FILE *f;
- va_list fmt_ap;
- int rc;
-
- f = ul_path_fopen(pc, "r" UL_CLOEXECSTR, path);
- if (!f)
- return -EINVAL;
-
- DBG(CXT, ul_debug(" fscanf [%s] '%s'", fmt, path));
-
- va_start(fmt_ap, fmt);
- rc = vfscanf(f, fmt, fmt_ap);
- va_end(fmt_ap);
-
- fclose(f);
- return rc;
-}
-
-int ul_path_scanff(struct path_cxt *pc, const char *path, va_list ap, const char *fmt, ...)
-{
- FILE *f;
- va_list fmt_ap;
- int rc;
-
- f = ul_path_vfopenf(pc, "r" UL_CLOEXECSTR, path, ap);
- if (!f)
- return -EINVAL;
-
- va_start(fmt_ap, fmt);
- rc = vfscanf(f, fmt, fmt_ap);
- va_end(fmt_ap);
-
- fclose(f);
- return rc;
-}
-
-
-int ul_path_read_s64(struct path_cxt *pc, int64_t *res, const char *path)
-{
- int64_t x = 0;
- int rc;
-
- rc = ul_path_scanf(pc, path, "%"SCNd64, &x);
- if (rc != 1)
- return -1;
- if (res)
- *res = x;
- return 0;
-}
-
-int ul_path_readf_s64(struct path_cxt *pc, int64_t *res, const char *path, ...)
-{
- const char *p;
- va_list ap;
-
- va_start(ap, path);
- p = ul_path_mkpath(pc, path, ap);
- va_end(ap);
-
- return !p ? -errno : ul_path_read_s64(pc, res, p);
-}
-
-int ul_path_read_u64(struct path_cxt *pc, uint64_t *res, const char *path)
-{
- uint64_t x = 0;
- int rc;
-
- rc = ul_path_scanf(pc, path, "%"SCNu64, &x);
- if (rc != 1)
- return -1;
- if (res)
- *res = x;
- return 0;
-}
-
-int ul_path_readf_u64(struct path_cxt *pc, uint64_t *res, const char *path, ...)
-{
- const char *p;
- va_list ap;
-
- va_start(ap, path);
- p = ul_path_mkpath(pc, path, ap);
- va_end(ap);
-
- return !p ? -errno : ul_path_read_u64(pc, res, p);
-}
-
-int ul_path_read_s32(struct path_cxt *pc, int *res, const char *path)
-{
- int rc, x = 0;
-
- rc = ul_path_scanf(pc, path, "%d", &x);
- if (rc != 1)
- return -1;
- if (res)
- *res = x;
- return 0;
-}
-
-int ul_path_readf_s32(struct path_cxt *pc, int *res, const char *path, ...)
-{
- const char *p;
- va_list ap;
-
- va_start(ap, path);
- p = ul_path_mkpath(pc, path, ap);
- va_end(ap);
-
- return !p ? -errno : ul_path_read_s32(pc, res, p);
-}
-
-int ul_path_read_u32(struct path_cxt *pc, unsigned int *res, const char *path)
-{
- int rc;
- unsigned int x;
-
- rc = ul_path_scanf(pc, path, "%u", &x);
- if (rc != 1)
- return -1;
- if (res)
- *res = x;
- return 0;
-}
-
-int ul_path_readf_u32(struct path_cxt *pc, unsigned int *res, const char *path, ...)
-{
- const char *p;
- va_list ap;
-
- va_start(ap, path);
- p = ul_path_mkpath(pc, path, ap);
- va_end(ap);
-
- return !p ? -errno : ul_path_read_u32(pc, res, p);
-}
-
-int ul_path_read_majmin(struct path_cxt *pc, dev_t *res, const char *path)
-{
- int rc, maj, min;
-
- rc = ul_path_scanf(pc, path, "%d:%d", &maj, &min);
- if (rc != 2)
- return -1;
- if (res)
- *res = makedev(maj, min);
- return 0;
-}
-
-int ul_path_readf_majmin(struct path_cxt *pc, dev_t *res, const char *path, ...)
-{
- const char *p;
- va_list ap;
-
- va_start(ap, path);
- p = ul_path_mkpath(pc, path, ap);
- va_end(ap);
-
- return !p ? -errno : ul_path_read_majmin(pc, res, p);
-}
-
-int ul_path_write_string(struct path_cxt *pc, const char *str, const char *path)
-{
- int rc, errsv;
- int fd;
-
- fd = ul_path_open(pc, O_WRONLY|O_CLOEXEC, path);
- if (fd < 0)
- return -errno;
-
- rc = write_all(fd, str, strlen(str));
-
- errsv = errno;
- close(fd);
- errno = errsv;
- return rc;
-}
-
-int ul_path_writef_string(struct path_cxt *pc, const char *str, const char *path, ...)
-{
- const char *p;
- va_list ap;
-
- va_start(ap, path);
- p = ul_path_mkpath(pc, path, ap);
- va_end(ap);
-
- return !p ? -errno : ul_path_write_string(pc, str, p);
-}
-
-int ul_path_write_s64(struct path_cxt *pc, int64_t num, const char *path)
-{
- char buf[sizeof(stringify_value(LLONG_MAX))];
- int rc, errsv;
- int fd, len;
-
- fd = ul_path_open(pc, O_WRONLY|O_CLOEXEC, path);
- if (fd < 0)
- return -errno;
-
- len = snprintf(buf, sizeof(buf), "%" PRId64, num);
- if (len < 0 || (size_t) len >= sizeof(buf))
- rc = len < 0 ? -errno : -E2BIG;
- else
- rc = write_all(fd, buf, len);
-
- errsv = errno;
- close(fd);
- errno = errsv;
- return rc;
-}
-
-int ul_path_write_u64(struct path_cxt *pc, uint64_t num, const char *path)
-{
- char buf[sizeof(stringify_value(ULLONG_MAX))];
- int rc, errsv;
- int fd, len;
-
- fd = ul_path_open(pc, O_WRONLY|O_CLOEXEC, path);
- if (fd < 0)
- return -errno;
-
- len = snprintf(buf, sizeof(buf), "%" PRIu64, num);
- if (len < 0 || (size_t) len >= sizeof(buf))
- rc = len < 0 ? -errno : -E2BIG;
- else
- rc = write_all(fd, buf, len);
-
- errsv = errno;
- close(fd);
- errno = errsv;
- return rc;
-}
-
-int ul_path_writef_u64(struct path_cxt *pc, uint64_t num, const char *path, ...)
-{
- const char *p;
- va_list ap;
-
- va_start(ap, path);
- p = ul_path_mkpath(pc, path, ap);
- va_end(ap);
-
- return !p ? -errno : ul_path_write_u64(pc, num, p);
-
-}
-
-int ul_path_count_dirents(struct path_cxt *pc, const char *path)
-{
- DIR *dir;
- int r = 0;
-
- dir = ul_path_opendir(pc, path);
- if (!dir)
- return 0;
-
- while (xreaddir(dir)) r++;
-
- closedir(dir);
- return r;
-}
-
-int ul_path_countf_dirents(struct path_cxt *pc, const char *path, ...)
-{
- const char *p;
- va_list ap;
-
- va_start(ap, path);
- p = ul_path_mkpath(pc, path, ap);
- va_end(ap);
-
- return !p ? -errno : ul_path_count_dirents(pc, p);
-}
-
-/*
- * Like fopen() but, @path is always prefixed by @prefix. This function is
- * useful in case when ul_path_* API is overkill.
- */
-FILE *ul_prefix_fopen(const char *prefix, const char *path, const char *mode)
-{
- char buf[PATH_MAX];
-
- if (!path)
- return NULL;
- if (!prefix)
- return fopen(path, mode);
- if (*path == '/')
- path++;
-
- snprintf(buf, sizeof(buf), "%s/%s", prefix, path);
- return fopen(buf, mode);
-}
-
-#ifdef HAVE_CPU_SET_T
-static int ul_path_cpuparse(struct path_cxt *pc, cpu_set_t **set, int maxcpus, int islist, const char *path, va_list ap)
-{
- FILE *f;
- size_t setsize, len = maxcpus * 7;
- char buf[len];
- int rc;
-
- *set = NULL;
-
- f = ul_path_vfopenf(pc, "r" UL_CLOEXECSTR, path, ap);
- if (!f)
- return -errno;
-
- rc = fgets(buf, len, f) == NULL ? -errno : 0;
- fclose(f);
-
- if (rc)
- return rc;
-
- len = strlen(buf);
- if (buf[len - 1] == '\n')
- buf[len - 1] = '\0';
-
- *set = cpuset_alloc(maxcpus, &setsize, NULL);
- if (!*set)
- return -ENOMEM;
-
- if (islist) {
- if (cpulist_parse(buf, *set, setsize, 0)) {
- cpuset_free(*set);
- return -EINVAL;
- }
- } else {
- if (cpumask_parse(buf, *set, setsize)) {
- cpuset_free(*set);
- return -EINVAL;
- }
- }
- return 0;
-}
-
-int ul_path_readf_cpuset(struct path_cxt *pc, cpu_set_t **set, int maxcpus, const char *path, ...)
-{
- va_list ap;
- int rc = 0;
-
- va_start(ap, path);
- rc = ul_path_cpuparse(pc, set, maxcpus, 0, path, ap);
- va_end(ap);
-
- return rc;
-}
-
-int ul_path_readf_cpulist(struct path_cxt *pc, cpu_set_t **set, int maxcpus, const char *path, ...)
-{
- va_list ap;
- int rc = 0;
-
- va_start(ap, path);
- rc = ul_path_cpuparse(pc, set, maxcpus, 1, path, ap);
- va_end(ap);
-
- return rc;
-}
-
-#endif /* HAVE_CPU_SET_T */
-
-
-#ifdef TEST_PROGRAM_PATH
-#include <getopt.h>
-
-static void __attribute__((__noreturn__)) usage(void)
-{
- fprintf(stdout, " %s [options] <dir> <command>\n\n", program_invocation_short_name);
- fputs(" -p, --prefix <dir> redirect hardcoded paths to <dir>\n", stdout);
-
- fputs(" Commands:\n", stdout);
- fputs(" read-u64 <file> read uint64_t from file\n", stdout);
- fputs(" read-s64 <file> read int64_t from file\n", stdout);
- fputs(" read-u32 <file> read uint32_t from file\n", stdout);
- fputs(" read-s32 <file> read int32_t from file\n", stdout);
- fputs(" read-string <file> read string from file\n", stdout);
- fputs(" read-majmin <file> read devno from file\n", stdout);
- fputs(" read-link <file> read symlink\n", stdout);
- fputs(" write-string <file> <str> write string from file\n", stdout);
- fputs(" write-u64 <file> <str> write uint64_t from file\n", stdout);
-
- exit(EXIT_SUCCESS);
-}
-
-int main(int argc, char *argv[])
-{
- int c;
- const char *prefix = NULL, *dir, *file, *command;
- struct path_cxt *pc = NULL;
-
- static const struct option longopts[] = {
- { "prefix", 1, NULL, 'p' },
- { "help", 0, NULL, 'h' },
- { NULL, 0, NULL, 0 },
- };
-
- while((c = getopt_long(argc, argv, "p:h", longopts, NULL)) != -1) {
- switch(c) {
- case 'p':
- prefix = optarg;
- break;
- case 'h':
- usage();
- break;
- default:
- err(EXIT_FAILURE, "try --help");
- }
- }
-
- if (optind == argc)
- errx(EXIT_FAILURE, "<dir> not defined");
- dir = argv[optind++];
-
- ul_path_init_debug();
-
- pc = ul_new_path(dir);
- if (!pc)
- err(EXIT_FAILURE, "failed to initialize path context");
- if (prefix)
- ul_path_set_prefix(pc, prefix);
-
- if (optind == argc)
- errx(EXIT_FAILURE, "<command> not defined");
- command = argv[optind++];
-
- if (strcmp(command, "read-u32") == 0) {
- uint32_t res;
-
- if (optind == argc)
- errx(EXIT_FAILURE, "<file> not defined");
- file = argv[optind++];
-
- if (ul_path_read_u32(pc, &res, file) != 0)
- err(EXIT_FAILURE, "read u64 failed");
- printf("read: %s: %u\n", file, res);
-
- if (ul_path_readf_u32(pc, &res, "%s", file) != 0)
- err(EXIT_FAILURE, "readf u64 failed");
- printf("readf: %s: %u\n", file, res);
-
- } else if (strcmp(command, "read-s32") == 0) {
- int32_t res;
-
- if (optind == argc)
- errx(EXIT_FAILURE, "<file> not defined");
- file = argv[optind++];
-
- if (ul_path_read_s32(pc, &res, file) != 0)
- err(EXIT_FAILURE, "read u64 failed");
- printf("read: %s: %d\n", file, res);
-
- if (ul_path_readf_s32(pc, &res, "%s", file) != 0)
- err(EXIT_FAILURE, "readf u64 failed");
- printf("readf: %s: %d\n", file, res);
-
- } else if (strcmp(command, "read-u64") == 0) {
- uint64_t res;
-
- if (optind == argc)
- errx(EXIT_FAILURE, "<file> not defined");
- file = argv[optind++];
-
- if (ul_path_read_u64(pc, &res, file) != 0)
- err(EXIT_FAILURE, "read u64 failed");
- printf("read: %s: %" PRIu64 "\n", file, res);
-
- if (ul_path_readf_u64(pc, &res, "%s", file) != 0)
- err(EXIT_FAILURE, "readf u64 failed");
- printf("readf: %s: %" PRIu64 "\n", file, res);
-
- } else if (strcmp(command, "read-s64") == 0) {
- int64_t res;
-
- if (optind == argc)
- errx(EXIT_FAILURE, "<file> not defined");
- file = argv[optind++];
-
- if (ul_path_read_s64(pc, &res, file) != 0)
- err(EXIT_FAILURE, "read u64 failed");
- printf("read: %s: %" PRIu64 "\n", file, res);
-
- if (ul_path_readf_s64(pc, &res, "%s", file) != 0)
- err(EXIT_FAILURE, "readf u64 failed");
- printf("readf: %s: %" PRIu64 "\n", file, res);
-
- } else if (strcmp(command, "read-majmin") == 0) {
- dev_t res;
-
- if (optind == argc)
- errx(EXIT_FAILURE, "<file> not defined");
- file = argv[optind++];
-
- if (ul_path_read_majmin(pc, &res, file) != 0)
- err(EXIT_FAILURE, "read maj:min failed");
- printf("read: %s: %d\n", file, (int) res);
-
- if (ul_path_readf_majmin(pc, &res, "%s", file) != 0)
- err(EXIT_FAILURE, "readf maj:min failed");
- printf("readf: %s: %d\n", file, (int) res);
-
- } else if (strcmp(command, "read-string") == 0) {
- char *res;
-
- if (optind == argc)
- errx(EXIT_FAILURE, "<file> not defined");
- file = argv[optind++];
-
- if (ul_path_read_string(pc, &res, file) < 0)
- err(EXIT_FAILURE, "read string failed");
- printf("read: %s: %s\n", file, res);
-
- if (ul_path_readf_string(pc, &res, "%s", file) < 0)
- err(EXIT_FAILURE, "readf string failed");
- printf("readf: %s: %s\n", file, res);
-
- } else if (strcmp(command, "read-link") == 0) {
- char res[PATH_MAX];
-
- if (optind == argc)
- errx(EXIT_FAILURE, "<file> not defined");
- file = argv[optind++];
-
- if (ul_path_readlink(pc, res, sizeof(res), file) < 0)
- err(EXIT_FAILURE, "read symlink failed");
- printf("read: %s: %s\n", file, res);
-
- if (ul_path_readlinkf(pc, res, sizeof(res), "%s", file) < 0)
- err(EXIT_FAILURE, "readf symlink failed");
- printf("readf: %s: %s\n", file, res);
-
- } else if (strcmp(command, "write-string") == 0) {
- char *str;
-
- if (optind + 1 == argc)
- errx(EXIT_FAILURE, "<file> <string> not defined");
- file = argv[optind++];
- str = argv[optind++];
-
- if (ul_path_write_string(pc, str, file) != 0)
- err(EXIT_FAILURE, "write string failed");
- if (ul_path_writef_string(pc, str, "%s", file) != 0)
- err(EXIT_FAILURE, "writef string failed");
-
- } else if (strcmp(command, "write-u64") == 0) {
- uint64_t num;
-
- if (optind + 1 == argc)
- errx(EXIT_FAILURE, "<file> <num> not defined");
- file = argv[optind++];
- num = strtoumax(argv[optind++], NULL, 0);
-
- if (ul_path_write_u64(pc, num, file) != 0)
- err(EXIT_FAILURE, "write u64 failed");
- if (ul_path_writef_u64(pc, num, "%s", file) != 0)
- err(EXIT_FAILURE, "writef u64 failed");
- }
-
- ul_unref_path(pc);
- return EXIT_SUCCESS;
-}
-#endif /* TEST_PROGRAM_PATH */
-
diff --git a/utils/lib/plymouth-ctrl.c b/utils/lib/plymouth-ctrl.c
deleted file mode 100644
index 2d3deda..0000000
--- a/utils/lib/plymouth-ctrl.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * plymouth-ctrl.c Simply communications with plymouthd
- * to avoid forked sub processes and/or
- * missed plymouth send commands tool
- * due a plymouthd replacement.
- *
- * 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>
- */
-
-#include <errno.h>
-#include <limits.h>
-#include <poll.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include "all-io.h"
-#include "c.h"
-#include "nls.h"
-#include "plymouth-ctrl.h"
-
-static int can_read(int fd, const long timeout)
-{
- struct pollfd fds = {
- .fd = fd,
- .events = POLLIN|POLLPRI,
- .revents = 0,
- };
- int ret;
-
- do {
- ret = poll(&fds, 1, timeout);
- } while ((ret < 0) && (errno == EINTR));
-
- return (ret == 1) && (fds.revents & (POLLIN|POLLPRI));
-}
-
-static int open_un_socket_and_connect(void)
-{
- /* The abstract UNIX socket of plymouth */
- struct sockaddr_un su = {
- .sun_family = AF_UNIX,
- .sun_path = PLYMOUTH_SOCKET_PATH,
- };
- const int one = 1;
- int fd, ret;
-
- fd = socket(PF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (fd < 0) {
- warnx(_("cannot open UNIX socket"));
- goto err;
- }
-
- ret = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
- if (ret < 0) {
- warnx(_("cannot set option for UNIX socket"));
- close(fd);
- fd = -1;
- goto err;
- }
-
- /* Note, the abstract PLYMOUTH_SOCKET_PATH has a leading NULL byte */
- ret = connect(fd, (struct sockaddr *) &su,
- offsetof(struct sockaddr_un, sun_path) + 1 + strlen(su.sun_path+1));
- if (ret < 0) {
- if (errno != ECONNREFUSED)
- warnx(_("cannot connect on UNIX socket"));
- close(fd);
- fd = -1;
- goto err;
- }
-err:
- return fd;
-}
-
-int plymouth_command(int cmd, ...)
-{
- uint8_t answer[2], command[2];
- struct sigaction sp, op;
- int fdsock = -1, ret = 0;
-
- sigemptyset (&sp.sa_mask);
- sp.sa_handler = SIG_IGN;
- sp.sa_flags = SA_RESTART;
- sigaction(SIGPIPE, &sp, &op);
-
- /* The plymouthd does read at least two bytes. */
- command[1] = '\0';
- switch (cmd) {
- case MAGIC_PING:
- fdsock = open_un_socket_and_connect();
- if (fdsock >= 0) {
- command[0] = cmd;
- write_all(fdsock, command, sizeof(command));
- }
- break;
- case MAGIC_QUIT:
- fdsock = open_un_socket_and_connect();
- if (fdsock >= 0) {
- command[0] = cmd;
- write_all(fdsock, command, sizeof(command));
- }
- break;
- default:
- warnx(_("the plymouth request %c is not implemented"), cmd);
- case '?':
- goto err;
- }
-
- answer[0] = '\0';
- if (fdsock >= 0) {
- if (can_read(fdsock, 1000))
- read_all(fdsock, (char *) &answer[0], sizeof(answer));
- close(fdsock);
- }
- sigaction(SIGPIPE, &op, NULL);
- ret = (answer[0] == ANSWER_ACK) ? 1 : 0;
-err:
- return ret;
-}
-
diff --git a/utils/lib/procutils.c b/utils/lib/procutils.c
deleted file mode 100644
index 8fb5d5c..0000000
--- a/utils/lib/procutils.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (C) 2011 Davidlohr Bueso <dave@gnu.org>
- *
- * procutils.c: General purpose procfs parsing utilities
- *
- * 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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <ctype.h>
-
-#include "procutils.h"
-#include "fileutils.h"
-#include "all-io.h"
-#include "c.h"
-
-/*
- * @pid: process ID for which we want to obtain the threads group
- *
- * Returns: newly allocated tasks structure
- */
-struct proc_tasks *proc_open_tasks(pid_t pid)
-{
- struct proc_tasks *tasks;
- char path[PATH_MAX];
-
- sprintf(path, "/proc/%d/task/", pid);
-
- tasks = malloc(sizeof(struct proc_tasks));
- if (tasks) {
- tasks->dir = opendir(path);
- if (tasks->dir)
- return tasks;
- }
-
- free(tasks);
- return NULL;
-}
-
-/*
- * @tasks: allocated tasks structure
- *
- * Returns: nothing
- */
-void proc_close_tasks(struct proc_tasks *tasks)
-{
- if (tasks && tasks->dir)
- closedir(tasks->dir);
- free(tasks);
-}
-
-/*
- * @tasks: allocated task structure
- * @tid: [output] one of the thread IDs belonging to the thread group
- * If when an error occurs, it is set to 0.
- *
- * Returns: 0 on success, 1 on end, -1 on failure or no more threads
- */
-int proc_next_tid(struct proc_tasks *tasks, pid_t *tid)
-{
- struct dirent *d;
- char *end;
-
- if (!tasks || !tid)
- return -EINVAL;
-
- *tid = 0;
- errno = 0;
-
- do {
- d = readdir(tasks->dir);
- if (!d)
- return errno ? -1 : 1; /* error or end-of-dir */
-
- if (!isdigit((unsigned char) *d->d_name))
- continue;
- errno = 0;
- *tid = (pid_t) strtol(d->d_name, &end, 10);
- if (errno || d->d_name == end || (end && *end))
- return -1;
-
- } while (!*tid);
-
- return 0;
-}
-
-/* returns process command path, use free() for result */
-static char *proc_file_strdup(pid_t pid, const char *name)
-{
- char buf[BUFSIZ], *res = NULL;
- ssize_t sz = 0;
- size_t i;
- int fd;
-
- snprintf(buf, sizeof(buf), "/proc/%d/%s", (int) pid, name);
- fd = open(buf, O_RDONLY);
- if (fd < 0)
- goto done;
-
- sz = read_all(fd, buf, sizeof(buf));
- if (sz <= 0)
- goto done;
-
- for (i = 0; i < (size_t) sz; i++) {
-
- if (buf[i] == '\0')
- buf[i] = ' ';
- }
- buf[sz - 1] = '\0';
- res = strdup(buf);
-done:
- if (fd >= 0)
- close(fd);
- return res;
-}
-
-/* returns process command path, use free() for result */
-char *proc_get_command(pid_t pid)
-{
- return proc_file_strdup(pid, "cmdline");
-}
-
-/* returns process command name, use free() for result */
-char *proc_get_command_name(pid_t pid)
-{
- return proc_file_strdup(pid, "comm");
-}
-
-struct proc_processes *proc_open_processes(void)
-{
- struct proc_processes *ps;
-
- ps = calloc(1, sizeof(struct proc_processes));
- if (ps) {
- ps->dir = opendir("/proc");
- if (ps->dir)
- return ps;
- }
-
- free(ps);
- return NULL;
-}
-
-void proc_close_processes(struct proc_processes *ps)
-{
- if (ps && ps->dir)
- closedir(ps->dir);
- free(ps);
-}
-
-void proc_processes_filter_by_name(struct proc_processes *ps, const char *name)
-{
- ps->fltr_name = name;
- ps->has_fltr_name = name ? 1 : 0;
-}
-
-void proc_processes_filter_by_uid(struct proc_processes *ps, uid_t uid)
-{
- ps->fltr_uid = uid;
- ps->has_fltr_uid = 1;
-}
-
-int proc_next_pid(struct proc_processes *ps, pid_t *pid)
-{
- struct dirent *d;
-
- if (!ps || !pid)
- return -EINVAL;
-
- *pid = 0;
- errno = 0;
-
- do {
- char buf[BUFSIZ], *p;
-
- errno = 0;
- d = readdir(ps->dir);
- if (!d)
- return errno ? -1 : 1; /* error or end-of-dir */
-
-
- if (!isdigit((unsigned char) *d->d_name))
- continue;
-
- /* filter out by UID */
- if (ps->has_fltr_uid) {
- struct stat st;
-
- if (fstatat(dirfd(ps->dir), d->d_name, &st, 0))
- continue;
- if (ps->fltr_uid != st.st_uid)
- continue;
- }
-
- /* filter out by NAME */
- if (ps->has_fltr_name) {
- char procname[256];
- FILE *f;
-
- snprintf(buf, sizeof(buf), "%s/stat", d->d_name);
- f = fopen_at(dirfd(ps->dir), buf, O_CLOEXEC|O_RDONLY, "r");
- if (!f)
- continue;
-
- p = fgets(buf, sizeof(buf), f);
- fclose(f);
- if (!p)
- continue;
-
- if (sscanf(buf, "%*d (%255[^)])", procname) != 1)
- continue;
-
- /* ok, we got the process name. */
- if (strcmp(procname, ps->fltr_name) != 0)
- continue;
- }
-
- p = NULL;
- errno = 0;
- *pid = (pid_t) strtol(d->d_name, &p, 10);
- if (errno || d->d_name == p || (p && *p))
- return errno ? -errno : -1;
-
- return 0;
- } while (1);
-
- return 0;
-}
-
-#ifdef TEST_PROGRAM_PROCUTILS
-
-static int test_tasks(int argc, char *argv[])
-{
- pid_t tid, pid;
- struct proc_tasks *ts;
-
- if (argc != 2)
- return EXIT_FAILURE;
-
- pid = strtol(argv[1], (char **) NULL, 10);
- printf("PID=%d, TIDs:", pid);
-
- ts = proc_open_tasks(pid);
- if (!ts)
- err(EXIT_FAILURE, "open list of tasks failed");
-
- while (proc_next_tid(ts, &tid) == 0)
- printf(" %d", tid);
-
- printf("\n");
- proc_close_tasks(ts);
- return EXIT_SUCCESS;
-}
-
-static int test_processes(int argc, char *argv[])
-{
- pid_t pid;
- struct proc_processes *ps;
-
- ps = proc_open_processes();
- if (!ps)
- err(EXIT_FAILURE, "open list of processes failed");
-
- if (argc >= 3 && strcmp(argv[1], "--name") == 0)
- proc_processes_filter_by_name(ps, argv[2]);
-
- if (argc >= 3 && strcmp(argv[1], "--uid") == 0)
- proc_processes_filter_by_uid(ps, (uid_t) atol(argv[2]));
-
- while (proc_next_pid(ps, &pid) == 0)
- printf(" %d", pid);
-
- printf("\n");
- proc_close_processes(ps);
- return EXIT_SUCCESS;
-}
-
-int main(int argc, char *argv[])
-{
- if (argc < 2) {
- fprintf(stderr, "usage: %1$s --tasks <pid>\n"
- " %1$s --processes [---name <name>] [--uid <uid>]\n",
- program_invocation_short_name);
- return EXIT_FAILURE;
- }
-
- if (strcmp(argv[1], "--tasks") == 0)
- return test_tasks(argc - 1, argv + 1);
- if (strcmp(argv[1], "--processes") == 0)
- return test_processes(argc - 1, argv + 1);
-
- return EXIT_FAILURE;
-}
-#endif /* TEST_PROGRAM_PROCUTILS */
diff --git a/utils/lib/pty-session.c b/utils/lib/pty-session.c
deleted file mode 100644
index 06b2a49..0000000
--- a/utils/lib/pty-session.c
+++ /dev/null
@@ -1,725 +0,0 @@
-/*
- * This is pseudo-terminal container for child process where parent creates a
- * proxy between the current std{in,out,etrr} and the child's pty. Advantages:
- *
- * - child has no access to parent's terminal (e.g. su --pty)
- * - parent can log all traffic between user and child's terminal (e.g. script(1))
- * - it's possible to start commands on terminal although parent has no terminal
- *
- * This code is in the public domain; do with it what you wish.
- *
- * Written by Karel Zak <kzak@redhat.com> in Jul 2019
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <pty.h>
-#include <poll.h>
-#include <sys/signalfd.h>
-#include <paths.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include "c.h"
-#include "all-io.h"
-#include "ttyutils.h"
-#include "pty-session.h"
-#include "monotonic.h"
-#include "debug.h"
-
-static UL_DEBUG_DEFINE_MASK(ulpty);
-UL_DEBUG_DEFINE_MASKNAMES(ulpty) = UL_DEBUG_EMPTY_MASKNAMES;
-
-#define ULPTY_DEBUG_INIT (1 << 1)
-#define ULPTY_DEBUG_SETUP (1 << 2)
-#define ULPTY_DEBUG_SIG (1 << 3)
-#define ULPTY_DEBUG_IO (1 << 4)
-#define ULPTY_DEBUG_DONE (1 << 5)
-#define ULPTY_DEBUG_ALL 0xFFFF
-
-#define DBG(m, x) __UL_DBG(ulpty, ULPTY_DEBUG_, m, x)
-#define ON_DBG(m, x) __UL_DBG_CALL(ulpty, ULPTY_DEBUG_, m, x)
-
-#define UL_DEBUG_CURRENT_MASK UL_DEBUG_MASK(ulpty)
-#include "debugobj.h"
-
-void ul_pty_init_debug(int mask)
-{
- if (ulpty_debug_mask)
- return;
- __UL_INIT_DEBUG_FROM_ENV(ulpty, ULPTY_DEBUG_, mask, ULPTY_DEBUG);
-}
-
-struct ul_pty *ul_new_pty(int is_stdin_tty)
-{
- struct ul_pty *pty = calloc(1, sizeof(*pty));
-
- if (!pty)
- return NULL;
-
- DBG(SETUP, ul_debugobj(pty, "alloc handler"));
- pty->isterm = is_stdin_tty;
- pty->master = -1;
- pty->slave = -1;
- pty->sigfd = -1;
- pty->child = (pid_t) -1;
-
- return pty;
-}
-
-void ul_free_pty(struct ul_pty *pty)
-{
- free(pty);
-}
-
-void ul_pty_slave_echo(struct ul_pty *pty, int enable)
-{
- assert(pty);
- pty->slave_echo = enable ? 1 : 0;
-}
-
-int ul_pty_get_delivered_signal(struct ul_pty *pty)
-{
- assert(pty);
- return pty->delivered_signal;
-}
-
-struct ul_pty_callbacks *ul_pty_get_callbacks(struct ul_pty *pty)
-{
- assert(pty);
- return &pty->callbacks;
-}
-
-void ul_pty_set_callback_data(struct ul_pty *pty, void *data)
-{
- assert(pty);
- pty->callback_data = data;
-}
-
-void ul_pty_set_child(struct ul_pty *pty, pid_t child)
-{
- assert(pty);
- pty->child = child;
-}
-
-int ul_pty_get_childfd(struct ul_pty *pty)
-{
- assert(pty);
- return pty->master;
-}
-
-pid_t ul_pty_get_child(struct ul_pty *pty)
-{
- assert(pty);
- return pty->child;
-}
-
-/* it's active when signals are redirected to sigfd */
-int ul_pty_is_running(struct ul_pty *pty)
-{
- assert(pty);
- return pty->sigfd >= 0;
-}
-
-void ul_pty_set_mainloop_time(struct ul_pty *pty, struct timeval *tv)
-{
- assert(pty);
- if (!tv) {
- DBG(IO, ul_debugobj(pty, "mainloop time: clear"));
- timerclear(&pty->next_callback_time);
- } else {
- pty->next_callback_time.tv_sec = tv->tv_sec;
- pty->next_callback_time.tv_usec = tv->tv_usec;
- DBG(IO, ul_debugobj(pty, "mainloop time: %ld.%06ld", tv->tv_sec, tv->tv_usec));
- }
-}
-
-static void pty_signals_cleanup(struct ul_pty *pty)
-{
- if (pty->sigfd != -1)
- close(pty->sigfd);
- pty->sigfd = -1;
-
- /* restore original setting */
- sigprocmask(SIG_SETMASK, &pty->orgsig, NULL);
-}
-
-/* call me before fork() */
-int ul_pty_setup(struct ul_pty *pty)
-{
- struct termios attrs;
- sigset_t ourset;
- int rc = 0;
-
- assert(pty->sigfd == -1);
-
- /* save the current signals setting */
- sigprocmask(0, NULL, &pty->orgsig);
-
- if (pty->isterm) {
- DBG(SETUP, ul_debugobj(pty, "create for terminal"));
-
- /* original setting of the current terminal */
- if (tcgetattr(STDIN_FILENO, &pty->stdin_attrs) != 0) {
- rc = -errno;
- goto done;
- }
-
- attrs = pty->stdin_attrs;
- if (pty->slave_echo)
- attrs.c_lflag |= ECHO;
- else
- attrs.c_lflag &= ~ECHO;
-
- ioctl(STDIN_FILENO, TIOCGWINSZ, (char *)&pty->win);
- /* create master+slave */
- rc = openpty(&pty->master, &pty->slave, NULL, &attrs, &pty->win);
- if (rc)
- goto done;
-
- /* set the current terminal to raw mode; pty_cleanup() reverses this change on exit */
- cfmakeraw(&attrs);
- tcsetattr(STDIN_FILENO, TCSANOW, &attrs);
- } else {
- DBG(SETUP, ul_debugobj(pty, "create for non-terminal"));
-
- rc = openpty(&pty->master, &pty->slave, NULL, NULL, NULL);
- if (rc)
- goto done;
-
- tcgetattr(pty->slave, &attrs);
-
- if (pty->slave_echo)
- attrs.c_lflag |= ECHO;
- else
- attrs.c_lflag &= ~ECHO;
-
- tcsetattr(pty->slave, TCSANOW, &attrs);
- }
-
- sigfillset(&ourset);
- if (sigprocmask(SIG_BLOCK, &ourset, NULL)) {
- rc = -errno;
- goto done;
- }
-
- sigemptyset(&ourset);
- sigaddset(&ourset, SIGCHLD);
- sigaddset(&ourset, SIGWINCH);
- sigaddset(&ourset, SIGALRM);
- sigaddset(&ourset, SIGTERM);
- sigaddset(&ourset, SIGINT);
- sigaddset(&ourset, SIGQUIT);
-
- if (pty->callbacks.flush_logs)
- sigaddset(&ourset, SIGUSR1);
-
- if ((pty->sigfd = signalfd(-1, &ourset, SFD_CLOEXEC)) < 0)
- rc = -errno;
-done:
- if (rc)
- ul_pty_cleanup(pty);
-
- DBG(SETUP, ul_debugobj(pty, "pty setup done [master=%d, slave=%d, rc=%d]",
- pty->master, pty->slave, rc));
- return rc;
-}
-
-/* cleanup in parent process */
-void ul_pty_cleanup(struct ul_pty *pty)
-{
- struct termios rtt;
-
- pty_signals_cleanup(pty);
-
- if (pty->master == -1 || !pty->isterm)
- return;
-
- DBG(DONE, ul_debugobj(pty, "cleanup"));
- rtt = pty->stdin_attrs;
- tcsetattr(STDIN_FILENO, TCSADRAIN, &rtt);
-}
-
-/* call me in child process */
-void ul_pty_init_slave(struct ul_pty *pty)
-{
- DBG(SETUP, ul_debugobj(pty, "initialize slave"));
-
- setsid();
-
- ioctl(pty->slave, TIOCSCTTY, 1);
- close(pty->master);
-
- dup2(pty->slave, STDIN_FILENO);
- dup2(pty->slave, STDOUT_FILENO);
- dup2(pty->slave, STDERR_FILENO);
-
- close(pty->slave);
-
- if (pty->sigfd >= 0)
- close(pty->sigfd);
-
- pty->slave = -1;
- pty->master = -1;
- pty->sigfd = -1;
-
- sigprocmask(SIG_SETMASK, &pty->orgsig, NULL);
-
- DBG(SETUP, ul_debugobj(pty, "... initialize slave done"));
-}
-
-static int write_output(char *obuf, ssize_t bytes)
-{
- DBG(IO, ul_debug(" writing output"));
-
- if (write_all(STDOUT_FILENO, obuf, bytes)) {
- DBG(IO, ul_debug(" writing output *failed*"));
- return -errno;
- }
-
- return 0;
-}
-
-static int write_to_child(struct ul_pty *pty, char *buf, size_t bufsz)
-{
- return write_all(pty->master, buf, bufsz);
-}
-
-/*
- * The pty is usually faster than shell, so it's a good idea to wait until
- * the previous message has been already read by shell from slave before we
- * write to master. This is necessary especially for EOF situation when we can
- * send EOF to master before shell is fully initialized, to workaround this
- * problem we wait until slave is empty. For example:
- *
- * echo "date" | su --pty
- *
- * Unfortunately, the child (usually shell) can ignore stdin at all, so we
- * don't wait forever to avoid dead locks...
- *
- * Note that su --pty is primarily designed for interactive sessions as it
- * maintains master+slave tty stuff within the session. Use pipe to write to
- * pty and assume non-interactive (tee-like) behavior is NOT well supported.
- */
-void ul_pty_write_eof_to_child(struct ul_pty *pty)
-{
- unsigned int tries = 0;
- struct pollfd fds[] = {
- { .fd = pty->slave, .events = POLLIN }
- };
- char c = DEF_EOF;
-
- DBG(IO, ul_debugobj(pty, " waiting for empty slave"));
- while (poll(fds, 1, 10) == 1 && tries < 8) {
- DBG(IO, ul_debugobj(pty, " slave is not empty"));
- xusleep(250000);
- tries++;
- }
- if (tries < 8)
- DBG(IO, ul_debugobj(pty, " slave is empty now"));
-
- DBG(IO, ul_debugobj(pty, " sending EOF to master"));
- write_to_child(pty, &c, sizeof(char));
-}
-
-static int mainloop_callback(struct ul_pty *pty)
-{
- int rc;
-
- if (!pty->callbacks.mainloop)
- return 0;
-
- DBG(IO, ul_debugobj(pty, "calling mainloop callback"));
- rc = pty->callbacks.mainloop(pty->callback_data);
-
- DBG(IO, ul_debugobj(pty, " callback done [rc=%d]", rc));
- return rc;
-}
-
-static int handle_io(struct ul_pty *pty, int fd, int *eof)
-{
- char buf[BUFSIZ];
- ssize_t bytes;
- int rc = 0;
-
- DBG(IO, ul_debugobj(pty, " handle I/O on fd=%d", fd));
- *eof = 0;
-
- /* read from active FD */
- bytes = read(fd, buf, sizeof(buf));
- if (bytes < 0) {
- if (errno == EAGAIN || errno == EINTR)
- return 0;
- return -errno;
- }
-
- if (bytes == 0) {
- *eof = 1;
- return 0;
- }
-
- /* from stdin (user) to command */
- if (fd == STDIN_FILENO) {
- DBG(IO, ul_debugobj(pty, " stdin --> master %zd bytes", bytes));
-
- if (write_to_child(pty, buf, bytes))
- return -errno;
-
- /* without sync write_output() will write both input &
- * shell output that looks like double echoing */
- fdatasync(pty->master);
-
- /* from command (master) to stdout */
- } else if (fd == pty->master) {
- DBG(IO, ul_debugobj(pty, " master --> stdout %zd bytes", bytes));
- write_output(buf, bytes);
- }
-
- if (pty->callbacks.log_stream_activity)
- rc = pty->callbacks.log_stream_activity(
- pty->callback_data, fd, buf, bytes);
-
- return rc;
-}
-
-void ul_pty_wait_for_child(struct ul_pty *pty)
-{
- int status;
- pid_t pid;
- int options = 0;
-
- if (pty->child == (pid_t) -1)
- return;
-
- DBG(SIG, ul_debug("waiting for child [child=%d]", (int) pty->child));
-
- if (ul_pty_is_running(pty)) {
- /* wait for specific child */
- options = WNOHANG;
- for (;;) {
- pid = waitpid(pty->child, &status, options);
- DBG(SIG, ul_debug(" waitpid done [rc=%d]", (int) pid));
- if (pid != (pid_t) - 1) {
- if (pty->callbacks.child_die)
- pty->callbacks.child_die(
- pty->callback_data,
- pty->child, status);
- ul_pty_set_child(pty, (pid_t) -1);
- } else
- break;
- }
- } else {
- /* final wait */
- while ((pid = wait3(&status, options, NULL)) > 0) {
- DBG(SIG, ul_debug(" wait3 done [rc=%d]", (int) pid));
- if (pid == pty->child) {
- if (pty->callbacks.child_die)
- pty->callbacks.child_die(
- pty->callback_data,
- pty->child, status);
- ul_pty_set_child(pty, (pid_t) -1);
- }
- }
- }
-}
-
-static int handle_signal(struct ul_pty *pty, int fd)
-{
- struct signalfd_siginfo info;
- ssize_t bytes;
- int rc = 0;
-
- DBG(SIG, ul_debugobj(pty, " handle signal on fd=%d", fd));
-
- bytes = read(fd, &info, sizeof(info));
- if (bytes != sizeof(info)) {
- if (bytes < 0 && (errno == EAGAIN || errno == EINTR))
- return 0;
- return -errno;
- }
-
- switch (info.ssi_signo) {
- case SIGCHLD:
- DBG(SIG, ul_debugobj(pty, " get signal SIGCHLD"));
-
- if (info.ssi_code == CLD_EXITED
- || info.ssi_code == CLD_KILLED
- || info.ssi_code == CLD_DUMPED) {
-
- if (pty->callbacks.child_wait)
- pty->callbacks.child_wait(pty->callback_data,
- pty->child);
- else
- ul_pty_wait_for_child(pty);
-
- } else if (info.ssi_status == SIGSTOP && pty->child > 0)
- pty->callbacks.child_sigstop(pty->callback_data,
- pty->child);
-
- if (pty->child <= 0) {
- DBG(SIG, ul_debugobj(pty, " no child, setting leaving timeout"));
- pty->poll_timeout = 10;
- timerclear(&pty->next_callback_time);
- }
- return 0;
- case SIGWINCH:
- DBG(SIG, ul_debugobj(pty, " get signal SIGWINCH"));
- if (pty->isterm) {
- ioctl(STDIN_FILENO, TIOCGWINSZ, (char *)&pty->win);
- ioctl(pty->slave, TIOCSWINSZ, (char *)&pty->win);
-
- if (pty->callbacks.log_signal)
- rc = pty->callbacks.log_signal(pty->callback_data,
- &info, (void *) &pty->win);
- }
- break;
- case SIGTERM:
- /* fallthrough */
- case SIGINT:
- /* fallthrough */
- case SIGQUIT:
- DBG(SIG, ul_debugobj(pty, " get signal SIG{TERM,INT,QUIT}"));
- pty->delivered_signal = info.ssi_signo;
- /* Child termination is going to generate SIGCHLD (see above) */
- if (pty->child > 0)
- kill(pty->child, SIGTERM);
-
- if (pty->callbacks.log_signal)
- rc = pty->callbacks.log_signal(pty->callback_data,
- &info, (void *) &pty->win);
- break;
- case SIGUSR1:
- DBG(SIG, ul_debugobj(pty, " get signal SIGUSR1"));
- if (pty->callbacks.flush_logs)
- rc = pty->callbacks.flush_logs(pty->callback_data);
- break;
- default:
- abort();
- }
-
- return rc;
-}
-
-/* loop in parent */
-int ul_pty_proxy_master(struct ul_pty *pty)
-{
- int rc = 0, ret, eof = 0;
- enum {
- POLLFD_SIGNAL = 0,
- POLLFD_MASTER,
- POLLFD_STDIN
-
- };
- struct pollfd pfd[] = {
- [POLLFD_SIGNAL] = { .fd = -1, .events = POLLIN | POLLERR | POLLHUP },
- [POLLFD_MASTER] = { .fd = pty->master, .events = POLLIN | POLLERR | POLLHUP },
- [POLLFD_STDIN] = { .fd = STDIN_FILENO, .events = POLLIN | POLLERR | POLLHUP }
- };
-
- /* We use signalfd, and standard signals by handlers are completely blocked */
- assert(pty->sigfd >= 0);
-
- pfd[POLLFD_SIGNAL].fd = pty->sigfd;
- pty->poll_timeout = -1;
-
- while (!pty->delivered_signal) {
- size_t i;
- int errsv, timeout;
-
- DBG(IO, ul_debugobj(pty, "--poll() loop--"));
-
- /* note, callback usually updates @next_callback_time */
- if (timerisset(&pty->next_callback_time)) {
- struct timeval now;
-
- DBG(IO, ul_debugobj(pty, " callback requested"));
- gettime_monotonic(&now);
- if (timercmp(&now, &pty->next_callback_time, >)) {
- rc = mainloop_callback(pty);
- if (rc)
- break;
- }
- }
-
- /* set timeout */
- if (timerisset(&pty->next_callback_time)) {
- struct timeval now, rest;
-
- gettime_monotonic(&now);
- timersub(&pty->next_callback_time, &now, &rest);
- timeout = (rest.tv_sec * 1000) + (rest.tv_usec / 1000);
- } else
- timeout = pty->poll_timeout;
-
- /* wait for input, signal or timeout */
- DBG(IO, ul_debugobj(pty, "calling poll() [timeout=%dms]", timeout));
- ret = poll(pfd, ARRAY_SIZE(pfd), timeout);
-
- errsv = errno;
- DBG(IO, ul_debugobj(pty, "poll() rc=%d", ret));
-
- /* error */
- if (ret < 0) {
- if (errsv == EAGAIN)
- continue;
- rc = -errno;
- break;
- }
-
- /* timeout */
- if (ret == 0) {
- if (timerisset(&pty->next_callback_time)) {
- rc = mainloop_callback(pty);
- if (rc == 0)
- continue;
- } else
- rc = 0;
-
- DBG(IO, ul_debugobj(pty, "leaving poll() loop [timeout=%d, rc=%d]", timeout, rc));
- break;
- }
- /* event */
- for (i = 0; i < ARRAY_SIZE(pfd); i++) {
- rc = 0;
-
- if (pfd[i].revents == 0)
- continue;
-
- DBG(IO, ul_debugobj(pty, " active pfd[%s].fd=%d %s %s %s %s",
- i == POLLFD_STDIN ? "stdin" :
- i == POLLFD_MASTER ? "master" :
- i == POLLFD_SIGNAL ? "signal" : "???",
- pfd[i].fd,
- pfd[i].revents & POLLIN ? "POLLIN" : "",
- pfd[i].revents & POLLHUP ? "POLLHUP" : "",
- pfd[i].revents & POLLERR ? "POLLERR" : "",
- pfd[i].revents & POLLNVAL ? "POLLNVAL" : ""));
-
- switch (i) {
- case POLLFD_STDIN:
- case POLLFD_MASTER:
- /* data */
- if (pfd[i].revents & POLLIN)
- rc = handle_io(pty, pfd[i].fd, &eof);
- /* EOF maybe detected in two ways; they are as follows:
- * A) poll() return POLLHUP event after close()
- * B) read() returns 0 (no data)
- *
- * POLLNVAL means that fd is closed.
- */
- if ((pfd[i].revents & POLLHUP) || (pfd[i].revents & POLLNVAL) || eof) {
- DBG(IO, ul_debugobj(pty, " ignore FD"));
- pfd[i].fd = -1;
- if (i == POLLFD_STDIN) {
- ul_pty_write_eof_to_child(pty);
- DBG(IO, ul_debugobj(pty, " ignore STDIN"));
- }
- }
- continue;
- case POLLFD_SIGNAL:
- rc = handle_signal(pty, pfd[i].fd);
- break;
- }
- if (rc)
- break;
- }
- }
-
- pty_signals_cleanup(pty);
-
- DBG(IO, ul_debug("poll() done [signal=%d, rc=%d]", pty->delivered_signal, rc));
- return rc;
-}
-
-#ifdef TEST_PROGRAM_PTY
-/*
- * $ make test_pty
- * $ ./test_pty
- *
- * ... and see for example tty(1) or "ps afu"
- */
-static void child_sigstop(void *data __attribute__((__unused__)), pid_t child)
-{
- kill(getpid(), SIGSTOP);
- kill(child, SIGCONT);
-}
-
-int main(int argc, char *argv[])
-{
- struct ul_pty_callbacks *cb;
- const char *shell, *command = NULL, *shname = NULL;
- int caught_signal = 0;
- pid_t child;
- struct ul_pty *pty;
-
- shell = getenv("SHELL");
- if (shell == NULL)
- shell = _PATH_BSHELL;
- if (argc == 2)
- command = argv[1];
-
- ul_pty_init_debug(0);
-
- pty = ul_new_pty(isatty(STDIN_FILENO));
- if (!pty)
- err(EXIT_FAILURE, "failed to allocate PTY handler");
-
- cb = ul_pty_get_callbacks(pty);
- cb->child_sigstop = child_sigstop;
-
- if (ul_pty_setup(pty))
- err(EXIT_FAILURE, "failed to create pseudo-terminal");
-
- fflush(stdout); /* ??? */
-
- switch ((int) (child = fork())) {
- case -1: /* error */
- ul_pty_cleanup(pty);
- err(EXIT_FAILURE, "cannot create child process");
- break;
-
- case 0: /* child */
- ul_pty_init_slave(pty);
-
- signal(SIGTERM, SIG_DFL); /* because /etc/csh.login */
-
- shname = strrchr(shell, '/');
- shname = shname ? shname + 1 : shell;
-
- if (command)
- execl(shell, shname, "-c", command, NULL);
- else
- execl(shell, shname, "-i", NULL);
- err(EXIT_FAILURE, "failed to execute %s", shell);
- break;
-
- default:
- break;
- }
-
- /* parent */
- ul_pty_set_child(pty, child);
-
- /* this is the main loop */
- ul_pty_proxy_master(pty);
-
- /* all done; cleanup and kill */
- caught_signal = ul_pty_get_delivered_signal(pty);
-
- if (!caught_signal && ul_pty_get_child(pty) != (pid_t)-1)
- ul_pty_wait_for_child(pty); /* final wait */
-
- if (caught_signal && ul_pty_get_child(pty) != (pid_t)-1) {
- fprintf(stderr, "\nSession terminated, killing shell...");
- kill(child, SIGTERM);
- sleep(2);
- kill(child, SIGKILL);
- fprintf(stderr, " ...killed.\n");
- }
-
- ul_pty_cleanup(pty);
- ul_free_pty(pty);
- return EXIT_SUCCESS;
-}
-
-#endif /* TEST_PROGRAM */
-
diff --git a/utils/lib/pwdutils.c b/utils/lib/pwdutils.c
deleted file mode 100644
index d5f4d2e..0000000
--- a/utils/lib/pwdutils.c
+++ /dev/null
@@ -1,156 +0,0 @@
-#include <stdlib.h>
-
-#include "c.h"
-#include "pwdutils.h"
-#include "xalloc.h"
-
-/* Returns allocated passwd and allocated pwdbuf to store passwd strings
- * fields. In case of error returns NULL and set errno, for unknown user set
- * errno to EINVAL
- */
-struct passwd *xgetpwnam(const char *username, char **pwdbuf)
-{
- struct passwd *pwd = NULL, *res = NULL;
- int rc;
-
- if (!pwdbuf || !username)
- return NULL;
-
- *pwdbuf = xmalloc(UL_GETPW_BUFSIZ);
- pwd = xcalloc(1, sizeof(struct passwd));
-
- errno = 0;
- rc = getpwnam_r(username, pwd, *pwdbuf, UL_GETPW_BUFSIZ, &res);
- if (rc != 0) {
- errno = rc;
- goto failed;
- }
- if (!res) {
- errno = EINVAL;
- goto failed;
- }
- return pwd;
-failed:
- free(pwd);
- free(*pwdbuf);
- return NULL;
-}
-
-/* Returns allocated group and allocated grpbuf to store group strings
- * fields. In case of error returns NULL and set errno, for unknown group set
- * errno to EINVAL
- */
-struct group *xgetgrnam(const char *groupname, char **grpbuf)
-{
- struct group *grp = NULL, *res = NULL;
- int rc;
-
- if (!grpbuf || !groupname)
- return NULL;
-
- *grpbuf = xmalloc(UL_GETPW_BUFSIZ);
- grp = xcalloc(1, sizeof(struct group));
-
- errno = 0;
- rc = getgrnam_r(groupname, grp, *grpbuf, UL_GETPW_BUFSIZ, &res);
- if (rc != 0) {
- errno = rc;
- goto failed;
- }
- if (!res) {
- errno = EINVAL;
- goto failed;
- }
- return grp;
-failed:
- free(grp);
- free(*grpbuf);
- return NULL;
-}
-
-struct passwd *xgetpwuid(uid_t uid, char **pwdbuf)
-{
- struct passwd *pwd = NULL, *res = NULL;
- int rc;
-
- if (!pwdbuf)
- return NULL;
-
- *pwdbuf = xmalloc(UL_GETPW_BUFSIZ);
- pwd = xcalloc(1, sizeof(struct passwd));
-
- errno = 0;
- rc = getpwuid_r(uid, pwd, *pwdbuf, UL_GETPW_BUFSIZ, &res);
- if (rc != 0) {
- errno = rc;
- goto failed;
- }
- if (!res) {
- errno = EINVAL;
- goto failed;
- }
- return pwd;
-failed:
- free(pwd);
- free(*pwdbuf);
- return NULL;
-}
-
-char *xgetlogin(void)
-{
- struct passwd *pw = NULL;
- uid_t ruid;
- char *user;
-
- user = getlogin();
- if (user)
- return xstrdup(user);
-
- /* GNU Hurd implementation has an extension where a process can exist in a
- * non-conforming environment, and thus be outside the realms of POSIX
- * process identifiers; on this platform, getuid() fails with a status of
- * (uid_t)(-1) and sets errno if a program is run from a non-conforming
- * environment.
- *
- * http://austingroupbugs.net/view.php?id=511
- */
- errno = 0;
- ruid = getuid();
-
- if (errno == 0)
- pw = getpwuid(ruid);
- if (pw && pw->pw_name && *pw->pw_name)
- return xstrdup(pw->pw_name);
-
- return NULL;
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char *argv[])
-{
- char *buf = NULL;
- struct passwd *pwd = NULL;
-
- if (argc != 2) {
- fprintf(stderr, "usage: %s <username>\n", argv[0]);
- return EXIT_FAILURE;
- }
-
- pwd = xgetpwnam(argv[1], &buf);
- if (!pwd)
- err(EXIT_FAILURE, "failed to get %s pwd entry", argv[1]);
-
- printf("Username: %s\n", pwd->pw_name);
- printf("UID: %d\n", pwd->pw_uid);
- printf("HOME: %s\n", pwd->pw_dir);
- printf("GECO: %s\n", pwd->pw_gecos);
-
- free(pwd);
- free(buf);
-
- printf("Current: %s\n", (buf = xgetlogin()));
- free(buf);
-
- return EXIT_SUCCESS;
-}
-#endif /* TEST_PROGRAM */
diff --git a/utils/lib/randutils.c b/utils/lib/randutils.c
deleted file mode 100644
index bd2a8f6..0000000
--- a/utils/lib/randutils.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * General purpose random utilities. Based on libuuid code.
- *
- * This code is free software; you can redistribute it and/or modify it under
- * the terms of the Modified BSD License. The complete text of the license is
- * available in the Documentation/licenses/COPYING.BSD-3-Clause file.
- */
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-
-#include <sys/syscall.h>
-
-#include "c.h"
-#include "randutils.h"
-#include "nls.h"
-
-#ifdef HAVE_TLS
-#define THREAD_LOCAL static __thread
-#else
-#define THREAD_LOCAL static
-#endif
-
-#ifdef HAVE_GETRANDOM
-# include <sys/random.h>
-#elif defined (__linux__)
-# if !defined(SYS_getrandom) && defined(__NR_getrandom)
- /* usable kernel-headers, but old glibc-headers */
-# define SYS_getrandom __NR_getrandom
-# endif
-#endif
-
-#if !defined(HAVE_GETRANDOM) && defined(SYS_getrandom)
-/* libc without function, but we have syscal */
-#define GRND_NONBLOCK 0x01
-#define GRND_RANDOM 0x02
-static int getrandom(void *buf, size_t buflen, unsigned int flags)
-{
- return (syscall(SYS_getrandom, buf, buflen, flags));
-}
-# define HAVE_GETRANDOM
-#endif
-
-#if defined(__linux__) && defined(__NR_gettid) && defined(HAVE_JRAND48)
-#define DO_JRAND_MIX
-THREAD_LOCAL unsigned short ul_jrand_seed[3];
-#endif
-
-int rand_get_number(int low_n, int high_n)
-{
- return rand() % (high_n - low_n + 1) + low_n;
-}
-
-static void crank_random(void)
-{
- int i;
- struct timeval tv;
- unsigned int n_pid, n_uid;
-
- gettimeofday(&tv, NULL);
- n_pid = getpid();
- n_uid = getuid();
- srand((n_pid << 16) ^ n_uid ^ tv.tv_sec ^ tv.tv_usec);
-
-#ifdef DO_JRAND_MIX
- ul_jrand_seed[0] = getpid() ^ (tv.tv_sec & 0xFFFF);
- ul_jrand_seed[1] = getppid() ^ (tv.tv_usec & 0xFFFF);
- ul_jrand_seed[2] = (tv.tv_sec ^ tv.tv_usec) >> 16;
-#endif
- /* Crank the random number generator a few times */
- gettimeofday(&tv, NULL);
- for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
- rand();
-}
-
-int random_get_fd(void)
-{
- int i, fd;
-
- fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
- if (fd == -1)
- fd = open("/dev/random", O_RDONLY | O_NONBLOCK | O_CLOEXEC);
- if (fd >= 0) {
- i = fcntl(fd, F_GETFD);
- if (i >= 0)
- fcntl(fd, F_SETFD, i | FD_CLOEXEC);
- }
- crank_random();
- return fd;
-}
-
-/*
- * Generate a stream of random nbytes into buf.
- * Use /dev/urandom if possible, and if not,
- * use glibc pseudo-random functions.
- */
-#define UL_RAND_READ_ATTEMPTS 8
-#define UL_RAND_READ_DELAY 125000 /* microseconds */
-
-void random_get_bytes(void *buf, size_t nbytes)
-{
- unsigned char *cp = (unsigned char *)buf;
- size_t i, n = nbytes;
- int lose_counter = 0;
-
-#ifdef HAVE_GETRANDOM
- while (n > 0) {
- int x;
-
- errno = 0;
- x = getrandom(cp, n, GRND_NONBLOCK);
- if (x > 0) { /* success */
- n -= x;
- cp += x;
- lose_counter = 0;
-
- } else if (errno == ENOSYS) { /* kernel without getrandom() */
- break;
-
- } else if (errno == EAGAIN && lose_counter < UL_RAND_READ_ATTEMPTS) {
- xusleep(UL_RAND_READ_DELAY); /* no entropy, wait and try again */
- lose_counter++;
- } else
- break;
- }
-
- if (errno == ENOSYS)
-#endif
- /*
- * We've been built against headers that support getrandom, but the
- * running kernel does not. Fallback to reading from /dev/{u,}random
- * as before
- */
- {
- int fd = random_get_fd();
-
- lose_counter = 0;
- if (fd >= 0) {
- while (n > 0) {
- ssize_t x = read(fd, cp, n);
- if (x <= 0) {
- if (lose_counter++ > UL_RAND_READ_ATTEMPTS)
- break;
- xusleep(UL_RAND_READ_DELAY);
- continue;
- }
- n -= x;
- cp += x;
- lose_counter = 0;
- }
-
- close(fd);
- }
- }
- /*
- * We do this all the time, but this is the only source of
- * randomness if /dev/random/urandom is out to lunch.
- */
- crank_random();
- for (cp = buf, i = 0; i < nbytes; i++)
- *cp++ ^= (rand() >> 7) & 0xFF;
-
-#ifdef DO_JRAND_MIX
- {
- unsigned short tmp_seed[3];
-
- memcpy(tmp_seed, ul_jrand_seed, sizeof(tmp_seed));
- ul_jrand_seed[2] = ul_jrand_seed[2] ^ syscall(__NR_gettid);
- for (cp = buf, i = 0; i < nbytes; i++)
- *cp++ ^= (jrand48(tmp_seed) >> 7) & 0xFF;
- memcpy(ul_jrand_seed, tmp_seed,
- sizeof(ul_jrand_seed)-sizeof(unsigned short));
- }
-#endif
-}
-
-
-/*
- * Tell source of randomness.
- */
-const char *random_tell_source(void)
-{
-#ifdef HAVE_GETRANDOM
- return _("getrandom() function");
-#else
- size_t i;
- static const char *random_sources[] = {
- "/dev/urandom",
- "/dev/random"
- };
-
- for (i = 0; i < ARRAY_SIZE(random_sources); i++) {
- if (!access(random_sources[i], R_OK))
- return random_sources[i];
- }
-#endif
- return _("libc pseudo-random functions");
-}
-
-#ifdef TEST_PROGRAM_RANDUTILS
-#include <inttypes.h>
-
-int main(int argc, char *argv[])
-{
- size_t i, n;
- int64_t *vp, v;
- char *buf;
- size_t bufsz;
-
- n = argc == 1 ? 16 : atoi(argv[1]);
-
- printf("Multiple random calls:\n");
- for (i = 0; i < n; i++) {
- random_get_bytes(&v, sizeof(v));
- printf("#%02zu: %25"PRIu64"\n", i, v);
- }
-
-
- printf("One random call:\n");
- bufsz = n * sizeof(*vp);
- buf = malloc(bufsz);
- if (!buf)
- err(EXIT_FAILURE, "failed to allocate buffer");
-
- random_get_bytes(buf, bufsz);
- for (i = 0; i < n; i++) {
- vp = (int64_t *) (buf + (i * sizeof(*vp)));
- printf("#%02zu: %25"PRIu64"\n", i, *vp);
- }
-
- return EXIT_SUCCESS;
-}
-#endif /* TEST_PROGRAM_RANDUTILS */
diff --git a/utils/lib/setproctitle.c b/utils/lib/setproctitle.c
deleted file mode 100644
index 7168e46..0000000
--- a/utils/lib/setproctitle.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * set process title for ps (from sendmail)
- *
- * Clobbers argv of our main procedure so ps(1) will display the title.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-
-#include "setproctitle.h"
-
-#ifndef SPT_BUFSIZE
-# define SPT_BUFSIZE 2048
-#endif
-
-extern char **environ;
-
-static char **argv0;
-static size_t argv_lth;
-
-void initproctitle (int argc, char **argv)
-{
- int i;
- char **envp = environ;
-
- /*
- * Move the environment so we can reuse the memory.
- * (Code borrowed from sendmail.)
- * WARNING: ugly assumptions on memory layout here;
- * if this ever causes problems, #undef DO_PS_FIDDLING
- */
- for (i = 0; envp[i] != NULL; i++)
- continue;
-
- environ = malloc(sizeof(char *) * (i + 1));
- if (environ == NULL)
- return;
-
- for (i = 0; envp[i] != NULL; i++)
- if ((environ[i] = strdup(envp[i])) == NULL)
- return;
- environ[i] = NULL;
-
- if (i > 0)
- argv_lth = envp[i-1] + strlen(envp[i-1]) - argv[0];
- else
- argv_lth = argv[argc-1] + strlen(argv[argc-1]) - argv[0];
- if (argv_lth > 1)
- argv0 = argv;
-}
-
-void setproctitle (const char *prog, const char *txt)
-{
- size_t i;
- char buf[SPT_BUFSIZE];
-
- if (!argv0)
- return;
-
- if (strlen(prog) + strlen(txt) + 5 > SPT_BUFSIZE)
- return;
-
- sprintf(buf, "%s -- %s", prog, txt);
-
- i = strlen(buf);
- if (i > argv_lth - 2) {
- i = argv_lth - 2;
- buf[i] = '\0';
- }
- memset(argv0[0], '\0', argv_lth); /* clear the memory area */
- strcpy(argv0[0], buf);
-
- argv0[1] = NULL;
-}
diff --git a/utils/lib/sha1.c b/utils/lib/sha1.c
deleted file mode 100644
index 22d33b3..0000000
--- a/utils/lib/sha1.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * SHA-1 in C by Steve Reid <steve@edmweb.com>
- * 100% Public Domain
- *
- * Test Vectors (from FIPS PUB 180-1)
- * 1) "abc": A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
- * 2) "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq": 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
- * 3) A million repetitions of "a": 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
- */
-
-#define UL_SHA1HANDSOFF
-
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-
-#include "sha1.h"
-
-#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-
-/* blk0() and blk() perform the initial expand. */
-#ifdef WORDS_BIGENDIAN
-# define blk0(i) block->l[i]
-#else
-# define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
- |(rol(block->l[i],8)&0x00FF00FF))
-#endif
-
-#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
- ^block->l[(i+2)&15]^block->l[i&15],1))
-
-/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
-
-/* Hash a single 512-bit block. This is the core of the algorithm. */
-
-void ul_SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
-{
- uint32_t a, b, c, d, e;
-
- typedef union {
- unsigned char c[64];
- uint32_t l[16];
- } CHAR64LONG16;
-
-#ifdef UL_SHA1HANDSOFF
- CHAR64LONG16 block[1]; /* use array to appear as a pointer */
-
- memcpy(block, buffer, 64);
-#else
- /* The following had better never be used because it causes the
- * pointer-to-const buffer to be cast into a pointer to non-const.
- * And the result is written through. I threw a "const" in, hoping
- * this will cause a diagnostic.
- */
- CHAR64LONG16 *block = (const CHAR64LONG16 *)buffer;
-#endif
- /* Copy context->state[] to working vars */
- a = state[0];
- b = state[1];
- c = state[2];
- d = state[3];
- e = state[4];
- /* 4 rounds of 20 operations each. Loop unrolled. */
- R0(a, b, c, d, e, 0);
- R0(e, a, b, c, d, 1);
- R0(d, e, a, b, c, 2);
- R0(c, d, e, a, b, 3);
- R0(b, c, d, e, a, 4);
- R0(a, b, c, d, e, 5);
- R0(e, a, b, c, d, 6);
- R0(d, e, a, b, c, 7);
- R0(c, d, e, a, b, 8);
- R0(b, c, d, e, a, 9);
- R0(a, b, c, d, e, 10);
- R0(e, a, b, c, d, 11);
- R0(d, e, a, b, c, 12);
- R0(c, d, e, a, b, 13);
- R0(b, c, d, e, a, 14);
- R0(a, b, c, d, e, 15);
- R1(e, a, b, c, d, 16);
- R1(d, e, a, b, c, 17);
- R1(c, d, e, a, b, 18);
- R1(b, c, d, e, a, 19);
- R2(a, b, c, d, e, 20);
- R2(e, a, b, c, d, 21);
- R2(d, e, a, b, c, 22);
- R2(c, d, e, a, b, 23);
- R2(b, c, d, e, a, 24);
- R2(a, b, c, d, e, 25);
- R2(e, a, b, c, d, 26);
- R2(d, e, a, b, c, 27);
- R2(c, d, e, a, b, 28);
- R2(b, c, d, e, a, 29);
- R2(a, b, c, d, e, 30);
- R2(e, a, b, c, d, 31);
- R2(d, e, a, b, c, 32);
- R2(c, d, e, a, b, 33);
- R2(b, c, d, e, a, 34);
- R2(a, b, c, d, e, 35);
- R2(e, a, b, c, d, 36);
- R2(d, e, a, b, c, 37);
- R2(c, d, e, a, b, 38);
- R2(b, c, d, e, a, 39);
- R3(a, b, c, d, e, 40);
- R3(e, a, b, c, d, 41);
- R3(d, e, a, b, c, 42);
- R3(c, d, e, a, b, 43);
- R3(b, c, d, e, a, 44);
- R3(a, b, c, d, e, 45);
- R3(e, a, b, c, d, 46);
- R3(d, e, a, b, c, 47);
- R3(c, d, e, a, b, 48);
- R3(b, c, d, e, a, 49);
- R3(a, b, c, d, e, 50);
- R3(e, a, b, c, d, 51);
- R3(d, e, a, b, c, 52);
- R3(c, d, e, a, b, 53);
- R3(b, c, d, e, a, 54);
- R3(a, b, c, d, e, 55);
- R3(e, a, b, c, d, 56);
- R3(d, e, a, b, c, 57);
- R3(c, d, e, a, b, 58);
- R3(b, c, d, e, a, 59);
- R4(a, b, c, d, e, 60);
- R4(e, a, b, c, d, 61);
- R4(d, e, a, b, c, 62);
- R4(c, d, e, a, b, 63);
- R4(b, c, d, e, a, 64);
- R4(a, b, c, d, e, 65);
- R4(e, a, b, c, d, 66);
- R4(d, e, a, b, c, 67);
- R4(c, d, e, a, b, 68);
- R4(b, c, d, e, a, 69);
- R4(a, b, c, d, e, 70);
- R4(e, a, b, c, d, 71);
- R4(d, e, a, b, c, 72);
- R4(c, d, e, a, b, 73);
- R4(b, c, d, e, a, 74);
- R4(a, b, c, d, e, 75);
- R4(e, a, b, c, d, 76);
- R4(d, e, a, b, c, 77);
- R4(c, d, e, a, b, 78);
- R4(b, c, d, e, a, 79);
- /* Add the working vars back into context.state[] */
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
- state[4] += e;
- /* Wipe variables */
- a = b = c = d = e = 0;
-#ifdef UL_SHA1HANDSOFF
- memset(block, '\0', sizeof(block));
-#endif
-}
-
-/* SHA1Init - Initialize new context */
-
-void ul_SHA1Init(UL_SHA1_CTX *context)
-{
- /* SHA1 initialization constants */
- context->state[0] = 0x67452301;
- context->state[1] = 0xEFCDAB89;
- context->state[2] = 0x98BADCFE;
- context->state[3] = 0x10325476;
- context->state[4] = 0xC3D2E1F0;
- context->count[0] = context->count[1] = 0;
-}
-
-/* Run your data through this. */
-
-void ul_SHA1Update(UL_SHA1_CTX *context, const unsigned char *data, uint32_t len)
-{
- uint32_t i;
-
- uint32_t j;
-
- j = context->count[0];
- if ((context->count[0] += len << 3) < j)
- context->count[1]++;
- context->count[1] += (len >> 29);
- j = (j >> 3) & 63;
- if ((j + len) > 63) {
- memcpy(&context->buffer[j], data, (i = 64 - j));
- ul_SHA1Transform(context->state, context->buffer);
- for (; i + 63 < len; i += 64) {
- ul_SHA1Transform(context->state, &data[i]);
- }
- j = 0;
- } else
- i = 0;
- memcpy(&context->buffer[j], &data[i], len - i);
-}
-
-/* Add padding and return the message digest. */
-
-void ul_SHA1Final(unsigned char digest[20], UL_SHA1_CTX *context)
-{
- unsigned i;
-
- unsigned char finalcount[8];
-
- unsigned char c;
-
-#if 0 /* untested "improvement" by DHR */
- /* Convert context->count to a sequence of bytes
- * in finalcount. Second element first, but
- * big-endian order within element.
- * But we do it all backwards.
- */
- unsigned char *fcp = &finalcount[8];
-
- for (i = 0; i < 2; i++) {
- uint32_t t = context->count[i];
-
- int j;
-
- for (j = 0; j < 4; t >>= 8, j++)
- *--fcp = (unsigned char)t}
-#else
- for (i = 0; i < 8; i++) {
- finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */
- }
-#endif
- c = 0200;
- ul_SHA1Update(context, &c, 1);
- while ((context->count[0] & 504) != 448) {
- c = 0000;
- ul_SHA1Update(context, &c, 1);
- }
- ul_SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
- for (i = 0; i < 20; i++) {
- digest[i] = (unsigned char)
- ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
- }
- /* Wipe variables */
- memset(context, '\0', sizeof(*context));
- memset(&finalcount, '\0', sizeof(finalcount));
-}
-
-void ul_SHA1(char *hash_out, const char *str, unsigned len)
-{
- UL_SHA1_CTX ctx;
- unsigned int ii;
-
- ul_SHA1Init(&ctx);
- for (ii = 0; ii < len; ii += 1)
- ul_SHA1Update(&ctx, (const unsigned char *)str + ii, 1);
- ul_SHA1Final((unsigned char *)hash_out, &ctx);
- hash_out[20] = '\0';
-}
diff --git a/utils/lib/signames.c b/utils/lib/signames.c
deleted file mode 100644
index 316eec5..0000000
--- a/utils/lib/signames.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 1988, 1993, 1994, 2017
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-/*
- * 2017-10-14 Niklas Hambüchen <mail@nh2.me>
- * - Extracted signal names mapping from kill.c
- *
- * Copyright (C) 2014 Sami Kerola <kerolasa@iki.fi>
- * Copyright (C) 2014 Karel Zak <kzak@redhat.com>
- * Copyright (C) 2017 Niklas Hambüchen <mail@nh2.me>
- */
-
-#include <ctype.h> /* for isdigit() */
-#include <signal.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-#include "c.h"
-#include "strutils.h"
-#include "signames.h"
-
-static const struct ul_signal_name {
- const char *name;
- int val;
-} ul_signames[] = {
- /* POSIX signals */
- { "HUP", SIGHUP }, /* 1 */
- { "INT", SIGINT }, /* 2 */
- { "QUIT", SIGQUIT }, /* 3 */
- { "ILL", SIGILL }, /* 4 */
-#ifdef SIGTRAP
- { "TRAP", SIGTRAP }, /* 5 */
-#endif
- { "ABRT", SIGABRT }, /* 6 */
-#ifdef SIGIOT
- { "IOT", SIGIOT }, /* 6, same as SIGABRT */
-#endif
-#ifdef SIGEMT
- { "EMT", SIGEMT }, /* 7 (mips,alpha,sparc*) */
-#endif
-#ifdef SIGBUS
- { "BUS", SIGBUS }, /* 7 (arm,i386,m68k,ppc), 10 (mips,alpha,sparc*) */
-#endif
- { "FPE", SIGFPE }, /* 8 */
- { "KILL", SIGKILL }, /* 9 */
- { "USR1", SIGUSR1 }, /* 10 (arm,i386,m68k,ppc), 30 (alpha,sparc*), 16 (mips) */
- { "SEGV", SIGSEGV }, /* 11 */
- { "USR2", SIGUSR2 }, /* 12 (arm,i386,m68k,ppc), 31 (alpha,sparc*), 17 (mips) */
- { "PIPE", SIGPIPE }, /* 13 */
- { "ALRM", SIGALRM }, /* 14 */
- { "TERM", SIGTERM }, /* 15 */
-#ifdef SIGSTKFLT
- { "STKFLT", SIGSTKFLT }, /* 16 (arm,i386,m68k,ppc) */
-#endif
- { "CHLD", SIGCHLD }, /* 17 (arm,i386,m68k,ppc), 20 (alpha,sparc*), 18 (mips) */
-#ifdef SIGCLD
- { "CLD", SIGCLD }, /* same as SIGCHLD (mips) */
-#endif
- { "CONT", SIGCONT }, /* 18 (arm,i386,m68k,ppc), 19 (alpha,sparc*), 25 (mips) */
- { "STOP", SIGSTOP }, /* 19 (arm,i386,m68k,ppc), 17 (alpha,sparc*), 23 (mips) */
- { "TSTP", SIGTSTP }, /* 20 (arm,i386,m68k,ppc), 18 (alpha,sparc*), 24 (mips) */
- { "TTIN", SIGTTIN }, /* 21 (arm,i386,m68k,ppc,alpha,sparc*), 26 (mips) */
- { "TTOU", SIGTTOU }, /* 22 (arm,i386,m68k,ppc,alpha,sparc*), 27 (mips) */
-#ifdef SIGURG
- { "URG", SIGURG }, /* 23 (arm,i386,m68k,ppc), 16 (alpha,sparc*), 21 (mips) */
-#endif
-#ifdef SIGXCPU
- { "XCPU", SIGXCPU }, /* 24 (arm,i386,m68k,ppc,alpha,sparc*), 30 (mips) */
-#endif
-#ifdef SIGXFSZ
- { "XFSZ", SIGXFSZ }, /* 25 (arm,i386,m68k,ppc,alpha,sparc*), 31 (mips) */
-#endif
-#ifdef SIGVTALRM
- { "VTALRM", SIGVTALRM }, /* 26 (arm,i386,m68k,ppc,alpha,sparc*), 28 (mips) */
-#endif
-#ifdef SIGPROF
- { "PROF", SIGPROF }, /* 27 (arm,i386,m68k,ppc,alpha,sparc*), 29 (mips) */
-#endif
-#ifdef SIGWINCH
- { "WINCH", SIGWINCH }, /* 28 (arm,i386,m68k,ppc,alpha,sparc*), 20 (mips) */
-#endif
-#ifdef SIGIO
- { "IO", SIGIO }, /* 29 (arm,i386,m68k,ppc), 23 (alpha,sparc*), 22 (mips) */
-#endif
-#ifdef SIGPOLL
- { "POLL", SIGPOLL }, /* same as SIGIO */
-#endif
-#ifdef SIGINFO
- { "INFO", SIGINFO }, /* 29 (alpha) */
-#endif
-#ifdef SIGLOST
- { "LOST", SIGLOST }, /* 29 (arm,i386,m68k,ppc,sparc*) */
-#endif
-#ifdef SIGPWR
- { "PWR", SIGPWR }, /* 30 (arm,i386,m68k,ppc), 29 (alpha,sparc*), 19 (mips) */
-#endif
-#ifdef SIGUNUSED
- { "UNUSED", SIGUNUSED }, /* 31 (arm,i386,m68k,ppc) */
-#endif
-#ifdef SIGSYS
- { "SYS", SIGSYS }, /* 31 (mips,alpha,sparc*) */
-#endif
-};
-
-#ifdef SIGRTMIN
-static int rtsig_to_signum(const char *sig)
-{
- int num, maxi = 0;
- char *ep = NULL;
-
- if (strncasecmp(sig, "min+", 4) == 0)
- sig += 4;
- else if (strncasecmp(sig, "max-", 4) == 0) {
- sig += 4;
- maxi = 1;
- }
- if (!isdigit(*sig))
- return -1;
- errno = 0;
- num = strtol(sig, &ep, 10);
- if (!ep || sig == ep || errno || num < 0)
- return -1;
- num = maxi ? SIGRTMAX - num : SIGRTMIN + num;
- if (num < SIGRTMIN || SIGRTMAX < num)
- return -1;
- return num;
-}
-#endif
-
-int signame_to_signum(const char *sig)
-{
- size_t n;
-
- if (!strncasecmp(sig, "sig", 3))
- sig += 3;
-#ifdef SIGRTMIN
- /* RT signals */
- if (!strncasecmp(sig, "rt", 2))
- return rtsig_to_signum(sig + 2);
-#endif
- /* Normal signals */
- for (n = 0; n < ARRAY_SIZE(ul_signames); n++) {
- if (!strcasecmp(ul_signames[n].name, sig))
- return ul_signames[n].val;
- }
- return -1;
-}
-
-const char *signum_to_signame(int signum)
-{
- size_t n;
-
- for (n = 0; n < ARRAY_SIZE(ul_signames); n++) {
- if (ul_signames[n].val == signum) {
- return ul_signames[n].name;
- }
- }
-
- return NULL;
-}
-
-int get_signame_by_idx(size_t idx, const char **signame, int *signum)
-{
- if (idx >= ARRAY_SIZE(ul_signames))
- return -1;
-
- if (signame)
- *signame = ul_signames[idx].name;
- if (signum)
- *signum = ul_signames[idx].val;
- return 0;
-
-}
-
diff --git a/utils/lib/strutils.c b/utils/lib/strutils.c
deleted file mode 100644
index 304f314..0000000
--- a/utils/lib/strutils.c
+++ /dev/null
@@ -1,1135 +0,0 @@
-/*
- * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
- * Copyright (C) 2010 Davidlohr Bueso <dave@gnu.org>
- *
- * No copyright is claimed. This code is in the public domain; do with
- * it what you wish.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <ctype.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <assert.h>
-
-#include "c.h"
-#include "nls.h"
-#include "strutils.h"
-#include "bitops.h"
-#include "pathnames.h"
-
-static int STRTOXX_EXIT_CODE = EXIT_FAILURE;
-
-void strutils_set_exitcode(int ex) {
- STRTOXX_EXIT_CODE = ex;
-}
-
-static int do_scale_by_power (uintmax_t *x, int base, int power)
-{
- while (power--) {
- if (UINTMAX_MAX / base < *x)
- return -ERANGE;
- *x *= base;
- }
- return 0;
-}
-
-/*
- * strtosize() - convert string to size (uintmax_t).
- *
- * Supported suffixes:
- *
- * XiB or X for 2^N
- * where X = {K,M,G,T,P,E,Z,Y}
- * or X = {k,m,g,t,p,e} (undocumented for backward compatibility only)
- * for example:
- * 10KiB = 10240
- * 10K = 10240
- *
- * XB for 10^N
- * where X = {K,M,G,T,P,E,Z,Y}
- * for example:
- * 10KB = 10000
- *
- * The optional 'power' variable returns number associated with used suffix
- * {K,M,G,T,P,E,Z,Y} = {1,2,3,4,5,6,7,8}.
- *
- * The function also supports decimal point, for example:
- * 0.5MB = 500000
- * 0.5MiB = 512000
- *
- * Note that the function does not accept numbers with '-' (negative sign)
- * prefix.
- */
-int parse_size(const char *str, uintmax_t *res, int *power)
-{
- const char *p;
- char *end;
- uintmax_t x, frac = 0;
- int base = 1024, rc = 0, pwr = 0, frac_zeros = 0;
-
- static const char *suf = "KMGTPEZY";
- static const char *suf2 = "kmgtpezy";
- const char *sp;
-
- *res = 0;
-
- if (!str || !*str) {
- rc = -EINVAL;
- goto err;
- }
-
- /* Only positive numbers are acceptable
- *
- * Note that this check is not perfect, it would be better to
- * use lconv->negative_sign. But coreutils use the same solution,
- * so it's probably good enough...
- */
- p = str;
- while (isspace((unsigned char) *p))
- p++;
- if (*p == '-') {
- rc = -EINVAL;
- goto err;
- }
-
- errno = 0, end = NULL;
- x = strtoumax(str, &end, 0);
-
- if (end == str ||
- (errno != 0 && (x == UINTMAX_MAX || x == 0))) {
- rc = errno ? -errno : -EINVAL;
- goto err;
- }
- if (!end || !*end)
- goto done; /* without suffix */
- p = end;
-
- /*
- * Check size suffixes
- */
-check_suffix:
- if (*(p + 1) == 'i' && (*(p + 2) == 'B' || *(p + 2) == 'b') && !*(p + 3))
- base = 1024; /* XiB, 2^N */
- else if ((*(p + 1) == 'B' || *(p + 1) == 'b') && !*(p + 2))
- base = 1000; /* XB, 10^N */
- else if (*(p + 1)) {
- struct lconv const *l = localeconv();
- const char *dp = l ? l->decimal_point : NULL;
- size_t dpsz = dp ? strlen(dp) : 0;
-
- if (frac == 0 && *p && dp && strncmp(dp, p, dpsz) == 0) {
- const char *fstr = p + dpsz;
-
- for (p = fstr; *p == '0'; p++)
- frac_zeros++;
- fstr = p;
- if (isdigit(*fstr)) {
- errno = 0, end = NULL;
- frac = strtoumax(fstr, &end, 0);
- if (end == fstr ||
- (errno != 0 && (frac == UINTMAX_MAX || frac == 0))) {
- rc = errno ? -errno : -EINVAL;
- goto err;
- }
- } else
- end = (char *) p;
-
- if (frac && (!end || !*end)) {
- rc = -EINVAL;
- goto err; /* without suffix, but with frac */
- }
- p = end;
- goto check_suffix;
- }
- rc = -EINVAL;
- goto err; /* unexpected suffix */
- }
-
- sp = strchr(suf, *p);
- if (sp)
- pwr = (sp - suf) + 1;
- else {
- sp = strchr(suf2, *p);
- if (sp)
- pwr = (sp - suf2) + 1;
- else {
- rc = -EINVAL;
- goto err;
- }
- }
-
- rc = do_scale_by_power(&x, base, pwr);
- if (power)
- *power = pwr;
- if (frac && pwr) {
- int i;
- uintmax_t frac_div = 10, frac_poz = 1, frac_base = 1;
-
- /* mega, giga, ... */
- do_scale_by_power(&frac_base, base, pwr);
-
- /* maximal divisor for last digit (e.g. for 0.05 is
- * frac_div=100, for 0.054 is frac_div=1000, etc.)
- *
- * Reduce frac if too large.
- */
- while (frac_div < frac) {
- if (frac_div <= UINTMAX_MAX/10)
- frac_div *= 10;
- else
- frac /= 10;
- }
-
- /* 'frac' is without zeros (5 means 0.5 as well as 0.05) */
- for (i = 0; i < frac_zeros; i++) {
- if (frac_div <= UINTMAX_MAX/10)
- frac_div *= 10;
- else
- frac /= 10;
- }
-
- /*
- * Go backwardly from last digit and add to result what the
- * digit represents in the frac_base. For example 0.25G
- *
- * 5 means 1GiB / (100/5)
- * 2 means 1GiB / (10/2)
- */
- do {
- unsigned int seg = frac % 10; /* last digit of the frac */
- uintmax_t seg_div = frac_div / frac_poz; /* what represents the segment 1000, 100, .. */
-
- frac /= 10; /* remove last digit from frac */
- frac_poz *= 10;
-
- if (seg && seg_div / seg)
- x += frac_base / (seg_div / seg);
- } while (frac);
- }
-done:
- *res = x;
-err:
- if (rc < 0)
- errno = -rc;
- return rc;
-}
-
-int strtosize(const char *str, uintmax_t *res)
-{
- return parse_size(str, res, NULL);
-}
-
-int isdigit_strend(const char *str, const char **end)
-{
- const char *p;
-
- for (p = str; p && *p && isdigit((unsigned char) *p); p++);
-
- if (end)
- *end = p;
- return p && p > str && !*p;
-}
-
-int isxdigit_strend(const char *str, const char **end)
-{
- const char *p;
-
- for (p = str; p && *p && isxdigit((unsigned char) *p); p++);
-
- if (end)
- *end = p;
-
- return p && p > str && !*p;
-}
-
-/*
- * parse_switch(argv[i], "on", "off", "yes", "no", NULL);
- */
-int parse_switch(const char *arg, const char *errmesg, ...)
-{
- const char *a, *b;
- va_list ap;
-
- va_start(ap, errmesg);
- do {
- a = va_arg(ap, char *);
- if (!a)
- break;
- b = va_arg(ap, char *);
- if (!b)
- break;
-
- if (strcmp(arg, a) == 0) {
- va_end(ap);
- return 1;
- }
-
- if (strcmp(arg, b) == 0) {
- va_end(ap);
- return 0;
- }
- } while (1);
- va_end(ap);
-
- errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, arg);
-}
-
-#ifndef HAVE_MEMPCPY
-void *mempcpy(void *restrict dest, const void *restrict src, size_t n)
-{
- return ((char *)memcpy(dest, src, n)) + n;
-}
-#endif
-
-#ifndef HAVE_STRNLEN
-size_t strnlen(const char *s, size_t maxlen)
-{
- size_t i;
-
- for (i = 0; i < maxlen; i++) {
- if (s[i] == '\0')
- return i;
- }
- return maxlen;
-}
-#endif
-
-#ifndef HAVE_STRNCHR
-char *strnchr(const char *s, size_t maxlen, int c)
-{
- for (; maxlen-- && *s != '\0'; ++s)
- if (*s == (char)c)
- return (char *)s;
- return NULL;
-}
-#endif
-
-#ifndef HAVE_STRNDUP
-char *strndup(const char *s, size_t n)
-{
- size_t len = strnlen(s, n);
- char *new = malloc((len + 1) * sizeof(char));
- if (!new)
- return NULL;
- new[len] = '\0';
- return (char *) memcpy(new, s, len);
-}
-#endif
-
-static uint32_t _strtou32_or_err(const char *str, const char *errmesg, int base);
-static uint64_t _strtou64_or_err(const char *str, const char *errmesg, int base);
-
-int16_t strtos16_or_err(const char *str, const char *errmesg)
-{
- int32_t num = strtos32_or_err(str, errmesg);
-
- if (num < INT16_MIN || num > INT16_MAX) {
- errno = ERANGE;
- err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
- }
- return num;
-}
-
-static uint16_t _strtou16_or_err(const char *str, const char *errmesg, int base)
-{
- uint32_t num = _strtou32_or_err(str, errmesg, base);
-
- if (num > UINT16_MAX) {
- errno = ERANGE;
- err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
- }
- return num;
-}
-
-uint16_t strtou16_or_err(const char *str, const char *errmesg)
-{
- return _strtou16_or_err(str, errmesg, 10);
-}
-
-uint16_t strtox16_or_err(const char *str, const char *errmesg)
-{
- return _strtou16_or_err(str, errmesg, 16);
-}
-
-int32_t strtos32_or_err(const char *str, const char *errmesg)
-{
- int64_t num = strtos64_or_err(str, errmesg);
-
- if (num < INT32_MIN || num > INT32_MAX) {
- errno = ERANGE;
- err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
- }
- return num;
-}
-
-static uint32_t _strtou32_or_err(const char *str, const char *errmesg, int base)
-{
- uint64_t num = _strtou64_or_err(str, errmesg, base);
-
- if (num > UINT32_MAX) {
- errno = ERANGE;
- err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
- }
- return num;
-}
-
-uint32_t strtou32_or_err(const char *str, const char *errmesg)
-{
- return _strtou32_or_err(str, errmesg, 10);
-}
-
-uint32_t strtox32_or_err(const char *str, const char *errmesg)
-{
- return _strtou32_or_err(str, errmesg, 16);
-}
-
-int64_t strtos64_or_err(const char *str, const char *errmesg)
-{
- int64_t num;
- char *end = NULL;
-
- errno = 0;
- if (str == NULL || *str == '\0')
- goto err;
- num = strtoimax(str, &end, 10);
-
- if (errno || str == end || (end && *end))
- goto err;
-
- return num;
-err:
- if (errno == ERANGE)
- err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
-
- errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
-}
-
-static uint64_t _strtou64_or_err(const char *str, const char *errmesg, int base)
-{
- uintmax_t num;
- char *end = NULL;
-
- errno = 0;
- if (str == NULL || *str == '\0')
- goto err;
- num = strtoumax(str, &end, base);
-
- if (errno || str == end || (end && *end))
- goto err;
-
- return num;
-err:
- if (errno == ERANGE)
- err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
-
- errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
-}
-
-uint64_t strtou64_or_err(const char *str, const char *errmesg)
-{
- return _strtou64_or_err(str, errmesg, 10);
-}
-
-uint64_t strtox64_or_err(const char *str, const char *errmesg)
-{
- return _strtou64_or_err(str, errmesg, 16);
-}
-
-double strtod_or_err(const char *str, const char *errmesg)
-{
- double num;
- char *end = NULL;
-
- errno = 0;
- if (str == NULL || *str == '\0')
- goto err;
- num = strtod(str, &end);
-
- if (errno || str == end || (end && *end))
- goto err;
-
- return num;
-err:
- if (errno == ERANGE)
- err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
-
- errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
-}
-
-long strtol_or_err(const char *str, const char *errmesg)
-{
- long num;
- char *end = NULL;
-
- errno = 0;
- if (str == NULL || *str == '\0')
- goto err;
- num = strtol(str, &end, 10);
-
- if (errno || str == end || (end && *end))
- goto err;
-
- return num;
-err:
- if (errno == ERANGE)
- err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
-
- errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
-}
-
-unsigned long strtoul_or_err(const char *str, const char *errmesg)
-{
- unsigned long num;
- char *end = NULL;
-
- errno = 0;
- if (str == NULL || *str == '\0')
- goto err;
- num = strtoul(str, &end, 10);
-
- if (errno || str == end || (end && *end))
- goto err;
-
- return num;
-err:
- if (errno == ERANGE)
- err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
-
- errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
-}
-
-uintmax_t strtosize_or_err(const char *str, const char *errmesg)
-{
- uintmax_t num;
-
- if (strtosize(str, &num) == 0)
- return num;
-
- if (errno)
- err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
-
- errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
-}
-
-
-void strtotimeval_or_err(const char *str, struct timeval *tv, const char *errmesg)
-{
- double user_input;
-
- user_input = strtod_or_err(str, errmesg);
- tv->tv_sec = (time_t) user_input;
- tv->tv_usec = (long)((user_input - tv->tv_sec) * 1000000);
-}
-
-/*
- * Converts stat->st_mode to ls(1)-like mode string. The size of "str" must
- * be 11 bytes.
- */
-char *xstrmode(mode_t mode, char *str)
-{
- unsigned short i = 0;
-
- if (S_ISDIR(mode))
- str[i++] = 'd';
- else if (S_ISLNK(mode))
- str[i++] = 'l';
- else if (S_ISCHR(mode))
- str[i++] = 'c';
- else if (S_ISBLK(mode))
- str[i++] = 'b';
- else if (S_ISSOCK(mode))
- str[i++] = 's';
- else if (S_ISFIFO(mode))
- str[i++] = 'p';
- else if (S_ISREG(mode))
- str[i++] = '-';
-
- str[i++] = mode & S_IRUSR ? 'r' : '-';
- str[i++] = mode & S_IWUSR ? 'w' : '-';
- str[i++] = (mode & S_ISUID
- ? (mode & S_IXUSR ? 's' : 'S')
- : (mode & S_IXUSR ? 'x' : '-'));
- str[i++] = mode & S_IRGRP ? 'r' : '-';
- str[i++] = mode & S_IWGRP ? 'w' : '-';
- str[i++] = (mode & S_ISGID
- ? (mode & S_IXGRP ? 's' : 'S')
- : (mode & S_IXGRP ? 'x' : '-'));
- str[i++] = mode & S_IROTH ? 'r' : '-';
- str[i++] = mode & S_IWOTH ? 'w' : '-';
- str[i++] = (mode & S_ISVTX
- ? (mode & S_IXOTH ? 't' : 'T')
- : (mode & S_IXOTH ? 'x' : '-'));
- str[i] = '\0';
-
- return str;
-}
-
-/*
- * returns exponent (2^x=n) in range KiB..EiB (2^10..2^60)
- */
-static int get_exp(uint64_t n)
-{
- int shft;
-
- for (shft = 10; shft <= 60; shft += 10) {
- if (n < (1ULL << shft))
- break;
- }
- return shft - 10;
-}
-
-char *size_to_human_string(int options, uint64_t bytes)
-{
- char buf[32];
- int dec, exp;
- uint64_t frac;
- const char *letters = "BKMGTPE";
- char suffix[sizeof(" KiB")], *psuf = suffix;
- char c;
-
- if (options & SIZE_SUFFIX_SPACE)
- *psuf++ = ' ';
-
-
- exp = get_exp(bytes);
- c = *(letters + (exp ? exp / 10 : 0));
- dec = exp ? bytes / (1ULL << exp) : bytes;
- frac = exp ? bytes % (1ULL << exp) : 0;
-
- *psuf++ = c;
-
- if ((options & SIZE_SUFFIX_3LETTER) && (c != 'B')) {
- *psuf++ = 'i';
- *psuf++ = 'B';
- }
-
- *psuf = '\0';
-
- /* fprintf(stderr, "exp: %d, unit: %c, dec: %d, frac: %jd\n",
- * exp, suffix[0], dec, frac);
- */
-
- /* round */
- if (frac) {
- /* get 3 digits after decimal point */
- if (frac >= UINT64_MAX / 1000)
- frac = ((frac / 1024) * 1000) / (1ULL << (exp - 10)) ;
- else
- frac = (frac * 1000) / (1ULL << (exp)) ;
-
- if (options & SIZE_DECIMAL_2DIGITS) {
- /* round 4/5 and keep 2 digits after decimal point */
- frac = (frac + 5) / 10 ;
- } else {
- /* round 4/5 and keep 1 digit after decimal point */
- frac = ((frac + 50) / 100) * 10 ;
- }
-
- /* rounding could have overflowed */
- if (frac == 100) {
- dec++;
- frac = 0;
- }
- }
-
- if (frac) {
- struct lconv const *l = localeconv();
- char *dp = l ? l->decimal_point : NULL;
- int len;
-
- if (!dp || !*dp)
- dp = ".";
-
- len = snprintf(buf, sizeof(buf), "%d%s%02" PRIu64, dec, dp, frac);
- if (len > 0 && (size_t) len < sizeof(buf)) {
- /* remove potential extraneous zero */
- if (buf[len - 1] == '0')
- buf[len--] = '\0';
- /* append suffix */
- xstrncpy(buf+len, suffix, sizeof(buf) - len);
- } else
- *buf = '\0'; /* snprintf error */
- } else
- snprintf(buf, sizeof(buf), "%d%s", dec, suffix);
-
- return strdup(buf);
-}
-
-/*
- * Parses comma delimited list to array with IDs, for example:
- *
- * "aaa,bbb,ccc" --> ary[0] = FOO_AAA;
- * ary[1] = FOO_BBB;
- * ary[3] = FOO_CCC;
- *
- * The function name2id() provides conversion from string to ID.
- *
- * Returns: >= 0 : number of items added to ary[]
- * -1 : parse error or unknown item
- * -2 : arysz reached
- */
-int string_to_idarray(const char *list, int ary[], size_t arysz,
- int (name2id)(const char *, size_t))
-{
- const char *begin = NULL, *p;
- size_t n = 0;
-
- if (!list || !*list || !ary || !arysz || !name2id)
- return -1;
-
- for (p = list; p && *p; p++) {
- const char *end = NULL;
- int id;
-
- if (n >= arysz)
- return -2;
- if (!begin)
- begin = p; /* begin of the column name */
- if (*p == ',')
- end = p; /* terminate the name */
- if (*(p + 1) == '\0')
- end = p + 1; /* end of string */
- if (!begin || !end)
- continue;
- if (end <= begin)
- return -1;
-
- id = name2id(begin, end - begin);
- if (id == -1)
- return -1;
- ary[ n++ ] = id;
- begin = NULL;
- if (end && !*end)
- break;
- }
- return n;
-}
-
-/*
- * Parses the array like string_to_idarray but if format is "+aaa,bbb"
- * it adds fields to array instead of replacing them.
- */
-int string_add_to_idarray(const char *list, int ary[], size_t arysz,
- size_t *ary_pos, int (name2id)(const char *, size_t))
-{
- const char *list_add;
- int r;
-
- if (!list || !*list || !ary_pos || *ary_pos > arysz)
- return -1;
-
- if (list[0] == '+')
- list_add = &list[1];
- else {
- list_add = list;
- *ary_pos = 0;
- }
-
- r = string_to_idarray(list_add, &ary[*ary_pos], arysz - *ary_pos, name2id);
- if (r > 0)
- *ary_pos += r;
- return r;
-}
-
-/*
- * LIST ::= <item> [, <item>]
- *
- * The <item> is translated to 'id' by name2id() function and the 'id' is used
- * as a position in the 'ary' bit array. It means that the 'id' has to be in
- * range <0..N> where N < sizeof(ary) * NBBY.
- *
- * Returns: 0 on success, <0 on error.
- */
-int string_to_bitarray(const char *list,
- char *ary,
- int (*name2bit)(const char *, size_t))
-{
- const char *begin = NULL, *p;
-
- if (!list || !name2bit || !ary)
- return -EINVAL;
-
- for (p = list; p && *p; p++) {
- const char *end = NULL;
- int bit;
-
- if (!begin)
- begin = p; /* begin of the level name */
- if (*p == ',')
- end = p; /* terminate the name */
- if (*(p + 1) == '\0')
- end = p + 1; /* end of string */
- if (!begin || !end)
- continue;
- if (end <= begin)
- return -1;
-
- bit = name2bit(begin, end - begin);
- if (bit < 0)
- return bit;
- setbit(ary, bit);
- begin = NULL;
- if (end && !*end)
- break;
- }
- return 0;
-}
-
-/*
- * LIST ::= <item> [, <item>]
- *
- * The <item> is translated to 'id' by name2flag() function and the flags is
- * set to the 'mask'
-*
- * Returns: 0 on success, <0 on error.
- */
-int string_to_bitmask(const char *list,
- unsigned long *mask,
- long (*name2flag)(const char *, size_t))
-{
- const char *begin = NULL, *p;
-
- if (!list || !name2flag || !mask)
- return -EINVAL;
-
- for (p = list; p && *p; p++) {
- const char *end = NULL;
- long flag;
-
- if (!begin)
- begin = p; /* begin of the level name */
- if (*p == ',')
- end = p; /* terminate the name */
- if (*(p + 1) == '\0')
- end = p + 1; /* end of string */
- if (!begin || !end)
- continue;
- if (end <= begin)
- return -1;
-
- flag = name2flag(begin, end - begin);
- if (flag < 0)
- return flag; /* error */
- *mask |= flag;
- begin = NULL;
- if (end && !*end)
- break;
- }
- return 0;
-}
-
-/*
- * Parse the lower and higher values in a string containing
- * "lower:higher" or "lower-higher" format. Note that either
- * the lower or the higher values may be missing, and the def
- * value will be assigned to it by default.
- *
- * Returns: 0 on success, <0 on error.
- */
-int parse_range(const char *str, int *lower, int *upper, int def)
-{
- char *end = NULL;
-
- if (!str)
- return 0;
-
- *upper = *lower = def;
- errno = 0;
-
- if (*str == ':') { /* <:N> */
- str++;
- *upper = strtol(str, &end, 10);
- if (errno || !end || *end || end == str)
- return -1;
- } else {
- *upper = *lower = strtol(str, &end, 10);
- if (errno || !end || end == str)
- return -1;
-
- if (*end == ':' && !*(end + 1)) /* <M:> */
- *upper = def;
- else if (*end == '-' || *end == ':') { /* <M:N> <M-N> */
- str = end + 1;
- end = NULL;
- errno = 0;
- *upper = strtol(str, &end, 10);
-
- if (errno || !end || *end || end == str)
- return -1;
- }
- }
- return 0;
-}
-
-static const char *next_path_segment(const char *str, size_t *sz)
-{
- const char *start, *p;
-
- start = str;
- *sz = 0;
- while (start && *start == '/' && *(start + 1) == '/')
- start++;
-
- if (!start || !*start)
- return NULL;
-
- for (*sz = 1, p = start + 1; *p && *p != '/'; p++) {
- (*sz)++;
- }
-
- return start;
-}
-
-int streq_paths(const char *a, const char *b)
-{
- while (a && b) {
- size_t a_sz, b_sz;
- const char *a_seg = next_path_segment(a, &a_sz);
- const char *b_seg = next_path_segment(b, &b_sz);
-
- /*
- fprintf(stderr, "A>>>(%zu) '%s'\n", a_sz, a_seg);
- fprintf(stderr, "B>>>(%zu) '%s'\n", b_sz, b_seg);
- */
-
- /* end of the path */
- if (a_sz + b_sz == 0)
- return 1;
-
- /* ignore tailing slash */
- if (a_sz + b_sz == 1 &&
- ((a_seg && *a_seg == '/') || (b_seg && *b_seg == '/')))
- return 1;
-
- if (!a_seg || !b_seg)
- break;
- if (a_sz != b_sz || strncmp(a_seg, b_seg, a_sz) != 0)
- break;
-
- a = a_seg + a_sz;
- b = b_seg + b_sz;
- };
-
- return 0;
-}
-
-char *strnappend(const char *s, const char *suffix, size_t b)
-{
- size_t a;
- char *r;
-
- if (!s && !suffix)
- return strdup("");
- if (!s)
- return strndup(suffix, b);
- if (!suffix)
- return strdup(s);
-
- assert(s);
- assert(suffix);
-
- a = strlen(s);
- if (b > ((size_t) -1) - a)
- return NULL;
-
- r = malloc(a + b + 1);
- if (!r)
- return NULL;
-
- memcpy(r, s, a);
- memcpy(r + a, suffix, b);
- r[a+b] = 0;
-
- return r;
-}
-
-char *strappend(const char *s, const char *suffix)
-{
- return strnappend(s, suffix, suffix ? strlen(suffix) : 0);
-}
-
-char *strfappend(const char *s, const char *format, ...)
-{
- va_list ap;
- char *val, *res;
- int sz;
-
- va_start(ap, format);
- sz = vasprintf(&val, format, ap);
- va_end(ap);
-
- if (sz < 0)
- return NULL;
-
- res = strnappend(s, val, sz);
- free(val);
- return res;
-}
-
-static size_t strcspn_escaped(const char *s, const char *reject)
-{
- int escaped = 0;
- int n;
-
- for (n=0; s[n]; n++) {
- if (escaped)
- escaped = 0;
- else if (s[n] == '\\')
- escaped = 1;
- else if (strchr(reject, s[n]))
- break;
- }
-
- /* if s ends in \, return index of previous char */
- return n - escaped;
-}
-
-/* Split a string into words. */
-const char *split(const char **state, size_t *l, const char *separator, int quoted)
-{
- const char *current;
-
- current = *state;
-
- if (!*current) {
- assert(**state == '\0');
- return NULL;
- }
-
- current += strspn(current, separator);
- if (!*current) {
- *state = current;
- return NULL;
- }
-
- if (quoted && strchr("\'\"", *current)) {
- char quotechars[2] = {*current, '\0'};
-
- *l = strcspn_escaped(current + 1, quotechars);
- if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] ||
- (current[*l + 2] && !strchr(separator, current[*l + 2]))) {
- /* right quote missing or garbage at the end */
- *state = current;
- return NULL;
- }
- *state = current++ + *l + 2;
- } else if (quoted) {
- *l = strcspn_escaped(current, separator);
- if (current[*l] && !strchr(separator, current[*l])) {
- /* unfinished escape */
- *state = current;
- return NULL;
- }
- *state = current + *l;
- } else {
- *l = strcspn(current, separator);
- *state = current + *l;
- }
-
- return current;
-}
-
-/* Rewind file pointer forward to new line. */
-int skip_fline(FILE *fp)
-{
- int ch;
-
- do {
- if ((ch = fgetc(fp)) == EOF)
- return 1;
- if (ch == '\n')
- return 0;
- } while (1);
-}
-
-#ifdef TEST_PROGRAM_STRUTILS
-struct testS {
- char *name;
- char *value;
-};
-
-static int test_strdup_to_member(int argc, char *argv[])
-{
- struct testS *xx;
-
- if (argc < 3)
- return EXIT_FAILURE;
-
- xx = calloc(1, sizeof(*xx));
- if (!xx)
- err(EXIT_FAILURE, "calloc() failed");
-
- strdup_to_struct_member(xx, name, argv[1]);
- strdup_to_struct_member(xx, value, argv[2]);
-
- if (strcmp(xx->name, argv[1]) != 0 &&
- strcmp(xx->value, argv[2]) != 0)
- errx(EXIT_FAILURE, "strdup_to_struct_member() failed");
-
- printf("1: '%s', 2: '%s'\n", xx->name, xx->value);
-
- free(xx->name);
- free(xx->value);
- free(xx);
- return EXIT_SUCCESS;
-}
-
-static int test_strutils_sizes(int argc, char *argv[])
-{
- uintmax_t size = 0;
- char *hum1, *hum2, *hum3;
-
- if (argc < 2)
- return EXIT_FAILURE;
-
- if (strtosize(argv[1], &size))
- errx(EXIT_FAILURE, "invalid size '%s' value", argv[1]);
-
- hum1 = size_to_human_string(SIZE_SUFFIX_1LETTER, size);
- hum2 = size_to_human_string(SIZE_SUFFIX_3LETTER |
- SIZE_SUFFIX_SPACE, size);
- hum3 = size_to_human_string(SIZE_SUFFIX_3LETTER |
- SIZE_SUFFIX_SPACE |
- SIZE_DECIMAL_2DIGITS, size);
-
- printf("%25s : %20ju : %8s : %12s : %13s\n", argv[1], size, hum1, hum2, hum3);
- free(hum1);
- free(hum2);
- free(hum3);
-
- return EXIT_SUCCESS;
-}
-
-static int test_strutils_cmp_paths(int argc, char *argv[])
-{
- int rc = streq_paths(argv[1], argv[2]);
-
- if (argc < 3)
- return EXIT_FAILURE;
-
- printf("%s: '%s' '%s'\n", rc == 1 ? "YES" : "NOT", argv[1], argv[2]);
- return EXIT_SUCCESS;
-}
-
-int main(int argc, char *argv[])
-{
- if (argc == 3 && strcmp(argv[1], "--size") == 0)
- return test_strutils_sizes(argc - 1, argv + 1);
-
- if (argc == 4 && strcmp(argv[1], "--cmp-paths") == 0)
- return test_strutils_cmp_paths(argc - 1, argv + 1);
-
- if (argc == 4 && strcmp(argv[1], "--strdup-member") == 0)
- return test_strdup_to_member(argc - 1, argv + 1);
-
- fprintf(stderr, "usage: %1$s --size <number>[suffix]\n"
- " %1$s --cmp-paths <path> <path>\n"
- " %1$s --strdup-member <str> <str>\n",
- argv[0]);
-
- return EXIT_FAILURE;
-}
-#endif /* TEST_PROGRAM_STRUTILS */
diff --git a/utils/lib/strv.c b/utils/lib/strv.c
deleted file mode 100644
index ddc2a0c..0000000
--- a/utils/lib/strv.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- *
- * Copyright 2010 Lennart Poettering
- *
- * This 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.
- *
- *
- * Copyright (C) 2015 Karel Zak <kzak@redhat.com>
- * Modified the original version from systemd project for util-linux.
- */
-
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <assert.h>
-
-#include "strutils.h"
-#include "strv.h"
-
-void strv_clear(char **l) {
- char **k;
-
- if (!l)
- return;
-
- for (k = l; *k; k++)
- free(*k);
-
- *l = NULL;
-}
-
-char **strv_free(char **l) {
- strv_clear(l);
- free(l);
- return NULL;
-}
-
-char **strv_copy(char * const *l) {
- char **r, **k;
-
- k = r = malloc(sizeof(char *) * (strv_length(l) + 1));
- if (!r)
- return NULL;
-
- if (l)
- for (; *l; k++, l++) {
- *k = strdup(*l);
- if (!*k) {
- strv_free(r);
- return NULL;
- }
- }
-
- *k = NULL;
- return r;
-}
-
-unsigned strv_length(char * const *l) {
- unsigned n = 0;
-
- if (!l)
- return 0;
-
- for (; *l; l++)
- n++;
-
- return n;
-}
-
-char **strv_new_ap(const char *x, va_list ap) {
- const char *s;
- char **a;
- unsigned n = 0, i = 0;
- va_list aq;
-
- /* As a special trick we ignore all listed strings that equal
- * (const char*) -1. This is supposed to be used with the
- * STRV_IFNOTNULL() macro to include possibly NULL strings in
- * the string list. */
-
- if (x) {
- n = x == (const char*) -1 ? 0 : 1;
-
- va_copy(aq, ap);
- while ((s = va_arg(aq, const char*))) {
- if (s == (const char*) -1)
- continue;
-
- n++;
- }
-
- va_end(aq);
- }
-
- a = malloc(sizeof(char *) * (n + 1));
- if (!a)
- return NULL;
-
- if (x) {
- if (x != (const char*) -1) {
- a[i] = strdup(x);
- if (!a[i])
- goto fail;
- i++;
- }
-
- while ((s = va_arg(ap, const char*))) {
-
- if (s == (const char*) -1)
- continue;
-
- a[i] = strdup(s);
- if (!a[i])
- goto fail;
-
- i++;
- }
- }
-
- a[i] = NULL;
-
- return a;
-
-fail:
- strv_free(a);
- return NULL;
-}
-
-char **strv_new(const char *x, ...) {
- char **r;
- va_list ap;
-
- va_start(ap, x);
- r = strv_new_ap(x, ap);
- va_end(ap);
-
- return r;
-}
-
-int strv_extend_strv(char ***a, char **b) {
- int r;
- char **s;
-
- STRV_FOREACH(s, b) {
- r = strv_extend(a, *s);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
- int r;
- char **s;
-
- STRV_FOREACH(s, b) {
- char *v;
-
- v = strappend(*s, suffix);
- if (!v)
- return -ENOMEM;
-
- r = strv_push(a, v);
- if (r < 0) {
- free(v);
- return r;
- }
- }
-
- return 0;
-}
-
-
-#define _FOREACH_WORD(word, length, s, separator, quoted, state) \
- for ((state) = (s), (word) = split(&(state), &(length), (separator), (quoted)); (word); (word) = split(&(state), &(length), (separator), (quoted)))
-
-#define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \
- _FOREACH_WORD(word, length, s, separator, false, state)
-
-
-char **strv_split(const char *s, const char *separator) {
- const char *word, *state;
- size_t l;
- unsigned n, i;
- char **r;
-
- assert(s);
-
- n = 0;
- FOREACH_WORD_SEPARATOR(word, l, s, separator, state)
- n++;
-
- r = malloc(sizeof(char *) * (n + 1));
- if (!r)
- return NULL;
-
- i = 0;
- FOREACH_WORD_SEPARATOR(word, l, s, separator, state) {
- r[i] = strndup(word, l);
- if (!r[i]) {
- strv_free(r);
- return NULL;
- }
-
- i++;
- }
-
- r[i] = NULL;
- return r;
-}
-
-char *strv_join(char **l, const char *separator) {
- char *r, *e;
- char **s;
- size_t n, k;
-
- if (!separator)
- separator = " ";
-
- k = strlen(separator);
-
- n = 0;
- STRV_FOREACH(s, l) {
- if (n != 0)
- n += k;
- n += strlen(*s);
- }
-
- r = malloc(n + 1);
- if (!r)
- return NULL;
-
- e = r;
- STRV_FOREACH(s, l) {
- if (e != r)
- e = stpcpy(e, separator);
-
- e = stpcpy(e, *s);
- }
-
- *e = 0;
-
- return r;
-}
-
-int strv_push(char ***l, char *value) {
- char **c;
- unsigned n, m;
-
- if (!value)
- return 0;
-
- n = strv_length(*l);
-
- /* Increase and check for overflow */
- m = n + 2;
- if (m < n)
- return -ENOMEM;
-
- c = realloc(*l, sizeof(char *) * m);
- if (!c)
- return -ENOMEM;
-
- c[n] = value;
- c[n+1] = NULL;
-
- *l = c;
- return 0;
-}
-
-int strv_push_prepend(char ***l, char *value) {
- char **c;
- unsigned n, m, i;
-
- if (!value)
- return 0;
-
- n = strv_length(*l);
-
- /* increase and check for overflow */
- m = n + 2;
- if (m < n)
- return -ENOMEM;
-
- c = malloc(sizeof(char *) * m);
- if (!c)
- return -ENOMEM;
-
- for (i = 0; i < n; i++)
- c[i+1] = (*l)[i];
-
- c[0] = value;
- c[n+1] = NULL;
-
- free(*l);
- *l = c;
-
- return 0;
-}
-
-int strv_consume(char ***l, char *value) {
- int r;
-
- r = strv_push(l, value);
- if (r < 0)
- free(value);
-
- return r;
-}
-
-int strv_consume_prepend(char ***l, char *value) {
- int r;
-
- r = strv_push_prepend(l, value);
- if (r < 0)
- free(value);
-
- return r;
-}
-
-int strv_extend(char ***l, const char *value) {
- char *v;
-
- if (!value)
- return 0;
-
- v = strdup(value);
- if (!v)
- return -ENOMEM;
-
- return strv_consume(l, v);
-}
-
-char **strv_remove(char **l, const char *s) {
- char **f, **t;
-
- if (!l)
- return NULL;
-
- assert(s);
-
- /* Drops every occurrence of s in the string list, edits
- * in-place. */
-
- for (f = t = l; *f; f++)
- if (strcmp(*f, s) == 0)
- free(*f);
- else
- *(t++) = *f;
-
- *t = NULL;
- return l;
-}
-
-int strv_extendf(char ***l, const char *format, ...) {
- va_list ap;
- char *x;
- int r;
-
- va_start(ap, format);
- r = vasprintf(&x, format, ap);
- va_end(ap);
-
- if (r < 0)
- return -ENOMEM;
-
- return strv_consume(l, x);
-}
-
-int strv_extendv(char ***l, const char *format, va_list ap) {
- char *x;
- int r;
-
- r = vasprintf(&x, format, ap);
- if (r < 0)
- return -ENOMEM;
-
- return strv_consume(l, x);
-}
-
-char **strv_reverse(char **l) {
- unsigned n, i;
-
- n = strv_length(l);
- if (n <= 1)
- return l;
-
- for (i = 0; i < n / 2; i++) {
- char *t;
-
- t = l[i];
- l[i] = l[n-1-i];
- l[n-1-i] = t;
- }
-
- return l;
-}
diff --git a/utils/lib/sysfs.c b/utils/lib/sysfs.c
deleted file mode 100644
index 5b4de2c..0000000
--- a/utils/lib/sysfs.c
+++ /dev/null
@@ -1,1127 +0,0 @@
-/*
- * No copyright is claimed. This code is in the public domain; do with
- * it what you wish.
- *
- * Written by Karel Zak <kzak@redhat.com>
- */
-#include <ctype.h>
-#include <libgen.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include "c.h"
-#include "pathnames.h"
-#include "sysfs.h"
-#include "fileutils.h"
-#include "all-io.h"
-#include "debug.h"
-#include "strutils.h"
-
-static void sysfs_blkdev_deinit_path(struct path_cxt *pc);
-static int sysfs_blkdev_enoent_redirect(struct path_cxt *pc, const char *path, int *dirfd);
-
-/*
- * Debug stuff (based on include/debug.h)
- */
-static UL_DEBUG_DEFINE_MASK(ulsysfs);
-UL_DEBUG_DEFINE_MASKNAMES(ulsysfs) = UL_DEBUG_EMPTY_MASKNAMES;
-
-#define ULSYSFS_DEBUG_INIT (1 << 1)
-#define ULSYSFS_DEBUG_CXT (1 << 2)
-
-#define DBG(m, x) __UL_DBG(ulsysfs, ULSYSFS_DEBUG_, m, x)
-#define ON_DBG(m, x) __UL_DBG_CALL(ulsysfs, ULSYSFS_DEBUG_, m, x)
-
-#define UL_DEBUG_CURRENT_MASK UL_DEBUG_MASK(ulsysfs)
-#include "debugobj.h"
-
-void ul_sysfs_init_debug(void)
-{
- if (ulsysfs_debug_mask)
- return;
- __UL_INIT_DEBUG_FROM_ENV(ulsysfs, ULSYSFS_DEBUG_, 0, ULSYSFS_DEBUG);
-}
-
-struct path_cxt *ul_new_sysfs_path(dev_t devno, struct path_cxt *parent, const char *prefix)
-{
- struct path_cxt *pc = ul_new_path(NULL);
-
- if (!pc)
- return NULL;
- if (prefix)
- ul_path_set_prefix(pc, prefix);
-
- if (sysfs_blkdev_init_path(pc, devno, parent) != 0) {
- ul_unref_path(pc);
- return NULL;
- }
-
- DBG(CXT, ul_debugobj(pc, "alloc"));
- return pc;
-}
-
-/*
- * sysfs_blkdev_* is sysfs extension to ul_path_* API for block devices.
- *
- * The function is possible to call in loop and without sysfs_blkdev_deinit_path().
- * The sysfs_blkdev_deinit_path() is automatically called by ul_unref_path().
- *
- */
-int sysfs_blkdev_init_path(struct path_cxt *pc, dev_t devno, struct path_cxt *parent)
-{
- struct sysfs_blkdev *blk;
- int rc;
- char buf[sizeof(_PATH_SYS_DEVBLOCK)
- + sizeof(stringify_value(UINT32_MAX)) * 2
- + 3];
-
- /* define path to devno stuff */
- snprintf(buf, sizeof(buf), _PATH_SYS_DEVBLOCK "/%d:%d", major(devno), minor(devno));
- rc = ul_path_set_dir(pc, buf);
- if (rc)
- return rc;
-
- /* make sure path exists */
- rc = ul_path_get_dirfd(pc);
- if (rc < 0)
- return rc;
-
- /* initialize sysfs blkdev specific stuff */
- blk = ul_path_get_dialect(pc);
- if (!blk) {
- DBG(CXT, ul_debugobj(pc, "alloc new sysfs handler"));
- blk = calloc(1, sizeof(struct sysfs_blkdev));
- if (!blk)
- return -ENOMEM;
-
- ul_path_set_dialect(pc, blk, sysfs_blkdev_deinit_path);
- ul_path_set_enoent_redirect(pc, sysfs_blkdev_enoent_redirect);
- }
-
- DBG(CXT, ul_debugobj(pc, "init sysfs stuff"));
-
- blk->devno = devno;
- sysfs_blkdev_set_parent(pc, parent);
-
- return 0;
-}
-
-static void sysfs_blkdev_deinit_path(struct path_cxt *pc)
-{
- struct sysfs_blkdev *blk;
-
- if (!pc)
- return;
-
- DBG(CXT, ul_debugobj(pc, "deinit"));
-
- blk = ul_path_get_dialect(pc);
- if (!blk)
- return;
-
- ul_unref_path(blk->parent);
- free(blk);
-
- ul_path_set_dialect(pc, NULL, NULL);
-}
-
-int sysfs_blkdev_set_parent(struct path_cxt *pc, struct path_cxt *parent)
-{
- struct sysfs_blkdev *blk = ul_path_get_dialect(pc);
-
- if (!pc || !blk)
- return -EINVAL;
-
- if (blk->parent) {
- ul_unref_path(blk->parent);
- blk->parent = NULL;
- }
-
- if (parent) {
- ul_ref_path(parent);
- blk->parent = parent;
- } else
- blk->parent = NULL;
-
- DBG(CXT, ul_debugobj(pc, "new parent"));
- return 0;
-}
-
-struct path_cxt *sysfs_blkdev_get_parent(struct path_cxt *pc)
-{
- struct sysfs_blkdev *blk = ul_path_get_dialect(pc);
- return blk ? blk->parent : NULL;
-}
-
-/*
- * Redirects ENOENT errors to the parent, if the path is to the queue/
- * sysfs directory. For example
- *
- * /sys/dev/block/8:1/queue/logical_block_size redirects to
- * /sys/dev/block/8:0/queue/logical_block_size
- */
-static int sysfs_blkdev_enoent_redirect(struct path_cxt *pc, const char *path, int *dirfd)
-{
- struct sysfs_blkdev *blk = ul_path_get_dialect(pc);
-
- if (blk && blk->parent && strncmp(path, "queue/", 6) == 0) {
- *dirfd = ul_path_get_dirfd(blk->parent);
- if (*dirfd >= 0) {
- DBG(CXT, ul_debugobj(pc, "%s redirected to parent", path));
- return 0;
- }
- }
- return 1; /* no redirect */
-}
-
-char *sysfs_blkdev_get_name(struct path_cxt *pc, char *buf, size_t bufsiz)
-{
- char link[PATH_MAX];
- char *name;
- ssize_t sz;
-
- /* read /sys/dev/block/<maj:min> link */
- sz = ul_path_readlink(pc, link, sizeof(link) - 1, NULL);
- if (sz < 0)
- return NULL;
- link[sz] = '\0';
-
- name = strrchr(link, '/');
- if (!name)
- return NULL;
-
- name++;
- sz = strlen(name);
- if ((size_t) sz + 1 > bufsiz)
- return NULL;
-
- memcpy(buf, name, sz + 1);
- sysfs_devname_sys_to_dev(buf);
- return buf;
-}
-
-int sysfs_blkdev_is_partition_dirent(DIR *dir, struct dirent *d, const char *parent_name)
-{
- char path[NAME_MAX + 6 + 1];
-
-#ifdef _DIRENT_HAVE_D_TYPE
- if (d->d_type != DT_DIR &&
- d->d_type != DT_LNK &&
- d->d_type != DT_UNKNOWN)
- return 0;
-#endif
- if (parent_name) {
- const char *p = parent_name;
- size_t len;
-
- /* /dev/sda --> "sda" */
- if (*parent_name == '/') {
- p = strrchr(parent_name, '/');
- if (!p)
- return 0;
- p++;
- }
-
- len = strlen(p);
- if (strlen(d->d_name) <= len)
- return 0;
-
- /* partitions subdir name is
- * "<parent>[:digit:]" or "<parent>p[:digit:]"
- */
- return strncmp(p, d->d_name, len) == 0 &&
- ((*(d->d_name + len) == 'p' && isdigit(*(d->d_name + len + 1)))
- || isdigit(*(d->d_name + len)));
- }
-
- /* Cannot use /partition file, not supported on old sysfs */
- snprintf(path, sizeof(path), "%s/start", d->d_name);
-
- return faccessat(dirfd(dir), path, R_OK, 0) == 0;
-}
-
-int sysfs_blkdev_count_partitions(struct path_cxt *pc, const char *devname)
-{
- DIR *dir;
- struct dirent *d;
- int r = 0;
-
- dir = ul_path_opendir(pc, NULL);
- if (!dir)
- return 0;
-
- while ((d = xreaddir(dir))) {
- if (sysfs_blkdev_is_partition_dirent(dir, d, devname))
- r++;
- }
-
- closedir(dir);
- return r;
-}
-
-/*
- * Converts @partno (partition number) to devno of the partition.
- * The @pc handles wholedisk device.
- *
- * Note that this code does not expect any special format of the
- * partitions devnames.
- */
-dev_t sysfs_blkdev_partno_to_devno(struct path_cxt *pc, int partno)
-{
- DIR *dir;
- struct dirent *d;
- dev_t devno = 0;
-
- dir = ul_path_opendir(pc, NULL);
- if (!dir)
- return 0;
-
- while ((d = xreaddir(dir))) {
- int n;
-
- if (!sysfs_blkdev_is_partition_dirent(dir, d, NULL))
- continue;
-
- if (ul_path_readf_s32(pc, &n, "%s/partition", d->d_name))
- continue;
-
- if (n == partno) {
- if (ul_path_readf_majmin(pc, &devno, "%s/dev", d->d_name) == 0)
- break;
- }
- }
-
- closedir(dir);
- DBG(CXT, ul_debugobj(pc, "partno (%d) -> devno (%d)", (int) partno, (int) devno));
- return devno;
-}
-
-
-/*
- * Returns slave name if there is only one slave, otherwise returns NULL.
- * The result should be deallocated by free().
- */
-char *sysfs_blkdev_get_slave(struct path_cxt *pc)
-{
- DIR *dir;
- struct dirent *d;
- char *name = NULL;
-
- dir = ul_path_opendir(pc, "slaves");
- if (!dir)
- return NULL;
-
- while ((d = xreaddir(dir))) {
- if (name)
- goto err; /* more slaves */
- name = strdup(d->d_name);
- }
-
- closedir(dir);
- return name;
-err:
- free(name);
- closedir(dir);
- return NULL;
-}
-
-
-#define SUBSYSTEM_LINKNAME "/subsystem"
-
-/*
- * For example:
- *
- * chain: /sys/dev/block/../../devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/ \
- * 1-1.2:1.0/host65/target65:0:0/65:0:0:0/block/sdb
- *
- * The function check if <chain>/subsystem symlink exists, if yes then returns
- * basename of the readlink result, and remove the last subdirectory from the
- * <chain> path.
- */
-static char *get_subsystem(char *chain, char *buf, size_t bufsz)
-{
- size_t len;
- char *p;
-
- if (!chain || !*chain)
- return NULL;
-
- len = strlen(chain);
- if (len + sizeof(SUBSYSTEM_LINKNAME) > PATH_MAX)
- return NULL;
-
- do {
- ssize_t sz;
-
- /* append "/subsystem" to the path */
- memcpy(chain + len, SUBSYSTEM_LINKNAME, sizeof(SUBSYSTEM_LINKNAME));
-
- /* try if subsystem symlink exists */
- sz = readlink(chain, buf, bufsz - 1);
-
- /* remove last subsystem from chain */
- chain[len] = '\0';
- p = strrchr(chain, '/');
- if (p) {
- *p = '\0';
- len = p - chain;
- }
-
- if (sz > 0) {
- /* we found symlink to subsystem, return basename */
- buf[sz] = '\0';
- return basename(buf);
- }
-
- } while (p);
-
- return NULL;
-}
-
-/*
- * Returns complete path to the device, the patch contains all subsystems
- * used for the device.
- */
-char *sysfs_blkdev_get_devchain(struct path_cxt *pc, char *buf, size_t bufsz)
-{
- /* read /sys/dev/block/<maj>:<min> symlink */
- ssize_t sz = ul_path_readlink(pc, buf, bufsz, NULL);
- const char *prefix;
- size_t psz = 0;
-
- if (sz <= 0 || sz + sizeof(_PATH_SYS_DEVBLOCK "/") > bufsz)
- return NULL;
-
- buf[sz++] = '\0';
- prefix = ul_path_get_prefix(pc);
- if (prefix)
- psz = strlen(prefix);
-
- /* create absolute patch from the link */
- memmove(buf + psz + sizeof(_PATH_SYS_DEVBLOCK "/") - 1, buf, sz);
- if (prefix)
- memcpy(buf, prefix, psz);
-
- memcpy(buf + psz, _PATH_SYS_DEVBLOCK "/", sizeof(_PATH_SYS_DEVBLOCK "/") - 1);
- return buf;
-}
-
-/*
- * The @subsys returns the next subsystem in the chain. Function modifies
- * @devchain string.
- *
- * Returns: 0 in success, <0 on error, 1 on end of chain
- */
-int sysfs_blkdev_next_subsystem(struct path_cxt *pc __attribute__((unused)),
- char *devchain, char **subsys)
-{
- char subbuf[PATH_MAX];
- char *sub;
-
- if (!subsys || !devchain)
- return -EINVAL;
-
- *subsys = NULL;
-
- while ((sub = get_subsystem(devchain, subbuf, sizeof(subbuf)))) {
- *subsys = strdup(sub);
- if (!*subsys)
- return -ENOMEM;
- return 0;
- }
-
- return 1;
-}
-
-
-static int is_hotpluggable_subsystem(const char *name)
-{
- static const char * const hotplug_subsystems[] = {
- "usb",
- "ieee1394",
- "pcmcia",
- "mmc",
- "ccw"
- };
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(hotplug_subsystems); i++)
- if (strcmp(name, hotplug_subsystems[i]) == 0)
- return 1;
-
- return 0;
-}
-
-int sysfs_blkdev_is_hotpluggable(struct path_cxt *pc)
-{
- char buf[PATH_MAX], *chain, *sub;
- int rc = 0;
-
-
- /* check /sys/dev/block/<maj>:<min>/removable attribute */
- if (ul_path_read_s32(pc, &rc, "removable") == 0 && rc == 1)
- return 1;
-
- chain = sysfs_blkdev_get_devchain(pc, buf, sizeof(buf));
-
- while (chain && sysfs_blkdev_next_subsystem(pc, chain, &sub) == 0) {
- rc = is_hotpluggable_subsystem(sub);
- if (rc) {
- free(sub);
- break;
- }
- free(sub);
- }
-
- return rc;
-}
-
-static int get_dm_wholedisk(struct path_cxt *pc, char *diskname,
- size_t len, dev_t *diskdevno)
-{
- int rc = 0;
- char *name;
-
- /* Note, sysfs_blkdev_get_slave() returns the first slave only,
- * if there is more slaves, then return NULL
- */
- name = sysfs_blkdev_get_slave(pc);
- if (!name)
- return -1;
-
- if (diskname && len)
- xstrncpy(diskname, name, len);
-
- if (diskdevno) {
- *diskdevno = __sysfs_devname_to_devno(ul_path_get_prefix(pc), name, NULL);
- if (!*diskdevno)
- rc = -1;
- }
-
- free(name);
- return rc;
-}
-
-/*
- * Returns by @diskdevno whole disk device devno and (optionally) by
- * @diskname the whole disk device name.
- */
-int sysfs_blkdev_get_wholedisk( struct path_cxt *pc,
- char *diskname,
- size_t len,
- dev_t *diskdevno)
-{
- int is_part = 0;
-
- if (!pc)
- return -1;
-
- is_part = ul_path_access(pc, F_OK, "partition") == 0;
- if (!is_part) {
- /*
- * Extra case for partitions mapped by device-mapper.
- *
- * All regular partitions (added by BLKPG ioctl or kernel PT
- * parser) have the /sys/.../partition file. The partitions
- * mapped by DM don't have such file, but they have "part"
- * prefix in DM UUID.
- */
- char *uuid = NULL, *tmp, *prefix;
-
- ul_path_read_string(pc, &uuid, "dm/uuid");
- tmp = uuid;
- prefix = uuid ? strsep(&tmp, "-") : NULL;
-
- if (prefix && strncasecmp(prefix, "part", 4) == 0)
- is_part = 1;
- free(uuid);
-
- if (is_part &&
- get_dm_wholedisk(pc, diskname, len, diskdevno) == 0)
- /*
- * partitioned device, mapped by DM
- */
- goto done;
-
- is_part = 0;
- }
-
- if (!is_part) {
- /*
- * unpartitioned device
- */
- if (diskname && !sysfs_blkdev_get_name(pc, diskname, len))
- goto err;
- if (diskdevno)
- *diskdevno = sysfs_blkdev_get_devno(pc);
-
- } else {
- /*
- * partitioned device
- * - readlink /sys/dev/block/8:1 = ../../block/sda/sda1
- * - dirname ../../block/sda/sda1 = ../../block/sda
- * - basename ../../block/sda = sda
- */
- char linkpath[PATH_MAX];
- char *name;
- ssize_t linklen;
-
- linklen = ul_path_readlink(pc, linkpath, sizeof(linkpath) - 1, NULL);
- if (linklen < 0)
- goto err;
- linkpath[linklen] = '\0';
-
- stripoff_last_component(linkpath); /* dirname */
- name = stripoff_last_component(linkpath); /* basename */
- if (!name)
- goto err;
-
- sysfs_devname_sys_to_dev(name);
- if (diskname && len)
- xstrncpy(diskname, name, len);
-
- if (diskdevno) {
- *diskdevno = __sysfs_devname_to_devno(ul_path_get_prefix(pc), name, NULL);
- if (!*diskdevno)
- goto err;
- }
- }
-
-done:
- return 0;
-err:
- return -1;
-}
-
-int sysfs_devno_to_wholedisk(dev_t devno, char *diskname,
- size_t len, dev_t *diskdevno)
-{
- struct path_cxt *pc;
- int rc = 0;
-
- if (!devno)
- return -EINVAL;
- pc = ul_new_sysfs_path(devno, NULL, NULL);
- if (!pc)
- return -ENOMEM;
-
- rc = sysfs_blkdev_get_wholedisk(pc, diskname, len, diskdevno);
- ul_unref_path(pc);
- return rc;
-}
-
-/*
- * Returns 1 if the device is private device mapper device. The @uuid
- * (if not NULL) returns DM device UUID, use free() to deallocate.
- */
-int sysfs_devno_is_dm_private(dev_t devno, char **uuid)
-{
- struct path_cxt *pc = NULL;
- char *id = NULL;
- int rc = 0;
-
- pc = ul_new_sysfs_path(devno, NULL, NULL);
- if (!pc)
- goto done;
- if (ul_path_read_string(pc, &id, "dm/uuid") <= 0 || !id)
- goto done;
-
- /* Private LVM devices use "LVM-<uuid>-<name>" uuid format (important
- * is the "LVM" prefix and "-<name>" postfix).
- */
- if (strncmp(id, "LVM-", 4) == 0) {
- char *p = strrchr(id + 4, '-');
-
- if (p && *(p + 1))
- rc = 1;
-
- /* Private Stratis devices prefix the UUID with "stratis-1-private"
- */
- } else if (strncmp(id, "stratis-1-private", 17) == 0) {
- rc = 1;
- }
-done:
- ul_unref_path(pc);
- if (uuid)
- *uuid = id;
- else
- free(id);
- return rc;
-}
-
-/*
- * Return 0 or 1, or < 0 in case of error
- */
-int sysfs_devno_is_wholedisk(dev_t devno)
-{
- dev_t disk;
-
- if (sysfs_devno_to_wholedisk(devno, NULL, 0, &disk) != 0)
- return -1;
-
- return devno == disk;
-}
-
-
-int sysfs_blkdev_scsi_get_hctl(struct path_cxt *pc, int *h, int *c, int *t, int *l)
-{
- char buf[PATH_MAX], *hctl;
- struct sysfs_blkdev *blk;
- ssize_t len;
-
- blk = ul_path_get_dialect(pc);
-
- if (!blk || blk->hctl_error)
- return -EINVAL;
- if (blk->has_hctl)
- goto done;
-
- blk->hctl_error = 1;
- len = ul_path_readlink(pc, buf, sizeof(buf) - 1, "device");
- if (len < 0)
- return len;
-
- buf[len] = '\0';
- hctl = strrchr(buf, '/');
- if (!hctl)
- return -1;
- hctl++;
-
- if (sscanf(hctl, "%u:%u:%u:%u", &blk->scsi_host, &blk->scsi_channel,
- &blk->scsi_target, &blk->scsi_lun) != 4)
- return -1;
-
- blk->has_hctl = 1;
-done:
- if (h)
- *h = blk->scsi_host;
- if (c)
- *c = blk->scsi_channel;
- if (t)
- *t = blk->scsi_target;
- if (l)
- *l = blk->scsi_lun;
-
- blk->hctl_error = 0;
- return 0;
-}
-
-
-static char *scsi_host_attribute_path(
- struct path_cxt *pc,
- const char *type,
- char *buf,
- size_t bufsz,
- const char *attr)
-{
- int len;
- int host;
- const char *prefix;
-
- if (sysfs_blkdev_scsi_get_hctl(pc, &host, NULL, NULL, NULL))
- return NULL;
-
- prefix = ul_path_get_prefix(pc);
- if (!prefix)
- prefix = "";
-
- if (attr)
- len = snprintf(buf, bufsz, "%s%s/%s_host/host%d/%s",
- prefix, _PATH_SYS_CLASS, type, host, attr);
- else
- len = snprintf(buf, bufsz, "%s%s/%s_host/host%d",
- prefix, _PATH_SYS_CLASS, type, host);
-
- return (len < 0 || (size_t) len >= bufsz) ? NULL : buf;
-}
-
-char *sysfs_blkdev_scsi_host_strdup_attribute(struct path_cxt *pc,
- const char *type, const char *attr)
-{
- char buf[1024];
- int rc;
- FILE *f;
-
- if (!attr || !type ||
- !scsi_host_attribute_path(pc, type, buf, sizeof(buf), attr))
- return NULL;
-
- if (!(f = fopen(buf, "r" UL_CLOEXECSTR)))
- return NULL;
-
- rc = fscanf(f, "%1023[^\n]", buf);
- fclose(f);
-
- return rc == 1 ? strdup(buf) : NULL;
-}
-
-int sysfs_blkdev_scsi_host_is(struct path_cxt *pc, const char *type)
-{
- char buf[PATH_MAX];
- struct stat st;
-
- if (!type || !scsi_host_attribute_path(pc, type,
- buf, sizeof(buf), NULL))
- return 0;
-
- return stat(buf, &st) == 0 && S_ISDIR(st.st_mode);
-}
-
-static char *scsi_attribute_path(struct path_cxt *pc,
- char *buf, size_t bufsz, const char *attr)
-{
- int len, h, c, t, l;
- const char *prefix;
-
- if (sysfs_blkdev_scsi_get_hctl(pc, &h, &c, &t, &l) != 0)
- return NULL;
-
- prefix = ul_path_get_prefix(pc);
- if (!prefix)
- prefix = "";
-
- if (attr)
- len = snprintf(buf, bufsz, "%s%s/devices/%d:%d:%d:%d/%s",
- prefix, _PATH_SYS_SCSI,
- h,c,t,l, attr);
- else
- len = snprintf(buf, bufsz, "%s%s/devices/%d:%d:%d:%d",
- prefix, _PATH_SYS_SCSI,
- h,c,t,l);
- return (len < 0 || (size_t) len >= bufsz) ? NULL : buf;
-}
-
-int sysfs_blkdev_scsi_has_attribute(struct path_cxt *pc, const char *attr)
-{
- char path[PATH_MAX];
- struct stat st;
-
- if (!scsi_attribute_path(pc, path, sizeof(path), attr))
- return 0;
-
- return stat(path, &st) == 0;
-}
-
-int sysfs_blkdev_scsi_path_contains(struct path_cxt *pc, const char *pattern)
-{
- char path[PATH_MAX], linkc[PATH_MAX];
- struct stat st;
- ssize_t len;
-
- if (!scsi_attribute_path(pc, path, sizeof(path), NULL))
- return 0;
-
- if (stat(path, &st) != 0)
- return 0;
-
- len = readlink(path, linkc, sizeof(linkc) - 1);
- if (len < 0)
- return 0;
-
- linkc[len] = '\0';
- return strstr(linkc, pattern) != NULL;
-}
-
-static dev_t read_devno(const char *path)
-{
- FILE *f;
- int maj = 0, min = 0;
- dev_t dev = 0;
-
- f = fopen(path, "r" UL_CLOEXECSTR);
- if (!f)
- return 0;
-
- if (fscanf(f, "%d:%d", &maj, &min) == 2)
- dev = makedev(maj, min);
- fclose(f);
- return dev;
-}
-
-int sysfs_devname_is_hidden(const char *prefix, const char *name)
-{
- char buf[PATH_MAX];
- int rc = 0, hidden = 0, len;
- FILE *f;
-
- if (strncmp("/dev/", name, 5) == 0)
- return 0;
-
- if (!prefix)
- prefix = "";
- /*
- * Create path to /sys/block/<name>/hidden
- */
- len = snprintf(buf, sizeof(buf),
- "%s" _PATH_SYS_BLOCK "/%s/hidden",
- prefix, name);
-
- if (len < 0 || (size_t) len + 1 > sizeof(buf))
- return 0;
-
- f = fopen(buf, "r" UL_CLOEXECSTR);
- if (!f)
- return 0;
-
- rc = fscanf(f, "%d", &hidden);
- fclose(f);
-
- return rc == 1 ? hidden : 0;
-}
-
-
-dev_t __sysfs_devname_to_devno(const char *prefix, const char *name, const char *parent)
-{
- char buf[PATH_MAX];
- char *_name = NULL; /* name as encoded in sysfs */
- dev_t dev = 0;
- int len;
-
- if (!prefix)
- prefix = "";
-
- assert(name);
-
- if (strncmp("/dev/", name, 5) == 0) {
- /*
- * Read from /dev
- */
- struct stat st;
-
- if (stat(name, &st) == 0) {
- dev = st.st_rdev;
- goto done;
- }
- name += 5; /* unaccessible, or not node in /dev */
- }
-
- _name = strdup(name);
- if (!_name)
- goto done;
- sysfs_devname_dev_to_sys(_name);
-
- if (parent && strncmp("dm-", name, 3) != 0) {
- /*
- * Create path to /sys/block/<parent>/<name>/dev
- */
- char *_parent = strdup(parent);
-
- if (!_parent) {
- free(_parent);
- goto done;
- }
- sysfs_devname_dev_to_sys(_parent);
- len = snprintf(buf, sizeof(buf),
- "%s" _PATH_SYS_BLOCK "/%s/%s/dev",
- prefix, _parent, _name);
- free(_parent);
- if (len < 0 || (size_t) len >= sizeof(buf))
- goto done;
-
- /* don't try anything else for dm-* */
- dev = read_devno(buf);
- goto done;
- }
-
- /*
- * Read from /sys/block/<sysname>/dev
- */
- len = snprintf(buf, sizeof(buf),
- "%s" _PATH_SYS_BLOCK "/%s/dev",
- prefix, _name);
- if (len < 0 || (size_t) len >= sizeof(buf))
- goto done;
- dev = read_devno(buf);
-
- if (!dev) {
- /*
- * Read from /sys/block/<sysname>/device/dev
- */
- len = snprintf(buf, sizeof(buf),
- "%s" _PATH_SYS_BLOCK "/%s/device/dev",
- prefix, _name);
- if (len < 0 || (size_t) len >= sizeof(buf))
- goto done;
- dev = read_devno(buf);
- }
-done:
- free(_name);
- return dev;
-}
-
-dev_t sysfs_devname_to_devno(const char *name)
-{
- return __sysfs_devname_to_devno(NULL, name, NULL);
-}
-
-char *sysfs_blkdev_get_path(struct path_cxt *pc, char *buf, size_t bufsiz)
-{
- const char *name = sysfs_blkdev_get_name(pc, buf, bufsiz);
- char *res = NULL;
- size_t sz;
- struct stat st;
-
- if (!name)
- goto done;
-
- sz = strlen(name);
- if (sz + sizeof("/dev/") > bufsiz)
- goto done;
-
- /* create the final "/dev/<name>" string */
- memmove(buf + 5, name, sz + 1);
- memcpy(buf, "/dev/", 5);
-
- if (!stat(buf, &st) && S_ISBLK(st.st_mode) && st.st_rdev == sysfs_blkdev_get_devno(pc))
- res = buf;
-done:
- return res;
-}
-
-dev_t sysfs_blkdev_get_devno(struct path_cxt *pc)
-{
- return ((struct sysfs_blkdev *) ul_path_get_dialect(pc))->devno;
-}
-
-/*
- * Returns devname (e.g. "/dev/sda1") for the given devno.
- *
- * Please, use more robust blkid_devno_to_devname() in your applications.
- */
-char *sysfs_devno_to_devpath(dev_t devno, char *buf, size_t bufsiz)
-{
- struct path_cxt *pc = ul_new_sysfs_path(devno, NULL, NULL);
- char *res = NULL;
-
- if (pc) {
- res = sysfs_blkdev_get_path(pc, buf, bufsiz);
- ul_unref_path(pc);
- }
- return res;
-}
-
-char *sysfs_devno_to_devname(dev_t devno, char *buf, size_t bufsiz)
-{
- struct path_cxt *pc = ul_new_sysfs_path(devno, NULL, NULL);
- char *res = NULL;
-
- if (pc) {
- res = sysfs_blkdev_get_name(pc, buf, bufsiz);
- ul_unref_path(pc);
- }
- return res;
-}
-
-int sysfs_devno_count_partitions(dev_t devno)
-{
- struct path_cxt *pc = ul_new_sysfs_path(devno, NULL, NULL);
- int n = 0;
-
- if (pc) {
- char buf[PATH_MAX + 1];
- char *name = sysfs_blkdev_get_name(pc, buf, sizeof(buf));
-
- n = sysfs_blkdev_count_partitions(pc, name);
- ul_unref_path(pc);
- }
- return n;
-}
-
-
-#ifdef TEST_PROGRAM_SYSFS
-#include <errno.h>
-#include <err.h>
-#include <stdlib.h>
-
-int main(int argc, char *argv[])
-{
- struct path_cxt *pc;
- char *devname;
- dev_t devno, disk_devno;
- char path[PATH_MAX], *sub, *chain;
- char diskname[32];
- int i, is_part, rc = EXIT_SUCCESS;
- uint64_t u64;
-
- if (argc != 2)
- errx(EXIT_FAILURE, "usage: %s <devname>", argv[0]);
-
- ul_sysfs_init_debug();
-
- devname = argv[1];
- devno = sysfs_devname_to_devno(devname);
-
- if (!devno)
- err(EXIT_FAILURE, "failed to read devno");
-
- printf("non-context:\n");
- printf(" DEVNO: %u (%d:%d)\n", (unsigned int) devno, major(devno), minor(devno));
- printf(" DEVNAME: %s\n", sysfs_devno_to_devname(devno, path, sizeof(path)));
- printf(" DEVPATH: %s\n", sysfs_devno_to_devpath(devno, path, sizeof(path)));
-
- sysfs_devno_to_wholedisk(devno, diskname, sizeof(diskname), &disk_devno);
- printf(" WHOLEDISK-DEVNO: %u (%d:%d)\n", (unsigned int) disk_devno, major(disk_devno), minor(disk_devno));
- printf(" WHOLEDISK-DEVNAME: %s\n", diskname);
-
- pc = ul_new_sysfs_path(devno, NULL, NULL);
- if (!pc)
- goto done;
-
- printf("context based:\n");
- devno = sysfs_blkdev_get_devno(pc);
- printf(" DEVNO: %u (%d:%d)\n", (unsigned int) devno, major(devno), minor(devno));
- printf(" DEVNAME: %s\n", sysfs_blkdev_get_name(pc, path, sizeof(path)));
- printf(" DEVPATH: %s\n", sysfs_blkdev_get_path(pc, path, sizeof(path)));
-
- sysfs_devno_to_wholedisk(devno, diskname, sizeof(diskname), &disk_devno);
- printf(" WHOLEDISK-DEVNO: %u (%d:%d)\n", (unsigned int) disk_devno, major(disk_devno), minor(disk_devno));
- printf(" WHOLEDISK-DEVNAME: %s\n", diskname);
-
- is_part = ul_path_access(pc, F_OK, "partition") == 0;
- printf(" PARTITION: %s\n", is_part ? "YES" : "NOT");
-
- if (is_part && disk_devno) {
- struct path_cxt *disk_pc = ul_new_sysfs_path(disk_devno, NULL, NULL);
- sysfs_blkdev_set_parent(pc, disk_pc);
-
- ul_unref_path(disk_pc);
- }
-
- printf(" HOTPLUG: %s\n", sysfs_blkdev_is_hotpluggable(pc) ? "yes" : "no");
- printf(" SLAVES: %d\n", ul_path_count_dirents(pc, "slaves"));
-
- if (!is_part) {
- printf("First 5 partitions:\n");
- for (i = 1; i <= 5; i++) {
- dev_t dev = sysfs_blkdev_partno_to_devno(pc, i);
- if (dev)
- printf("\t#%d %d:%d\n", i, major(dev), minor(dev));
- }
- }
-
- if (ul_path_read_u64(pc, &u64, "size") != 0)
- printf(" (!) read SIZE failed\n");
- else
- printf(" SIZE: %jd\n", u64);
-
- if (ul_path_read_s32(pc, &i, "queue/hw_sector_size"))
- printf(" (!) read SECTOR failed\n");
- else
- printf(" SECTOR: %d\n", i);
-
-
- chain = sysfs_blkdev_get_devchain(pc, path, sizeof(path));
- printf(" SUBSUSTEMS:\n");
-
- while (chain && sysfs_blkdev_next_subsystem(pc, chain, &sub) == 0) {
- printf("\t%s\n", sub);
- free(sub);
- }
-
- rc = EXIT_SUCCESS;
-done:
- ul_unref_path(pc);
- return rc;
-}
-#endif /* TEST_PROGRAM_SYSFS */
diff --git a/utils/lib/timer.c b/utils/lib/timer.c
deleted file mode 100644
index c1ea54e..0000000
--- a/utils/lib/timer.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Please, don't add this file to libcommon because timers requires
- * -lrt on systems with old libc (and probably also -lpthread for static
- * build).
- */
-#include <time.h>
-#include <signal.h>
-#include <sys/time.h>
-
-#include "c.h"
-#include "timer.h"
-
-/*
- * Note the timeout is used for the first signal, then the signal is send
- * repeatedly in interval ~1% of the original timeout to avoid race in signal
- * handling -- for example you want to use timer to define timeout for a
- * syscall:
- *
- * setup_timer()
- * syscall()
- * cancel_timer()
- *
- * if the timeout is too short than it's possible that the signal is delivered
- * before application enter the syscall function. For this reason timer send
- * the signal repeatedly.
- *
- * The applications need to ensure that they can tolerate multiple signal
- * deliveries.
- */
-#ifdef HAVE_TIMER_CREATE
-int setup_timer(struct ul_timer *timer,
- struct itimerval *timeout,
- void (*timeout_handler)(int, siginfo_t *, void *))
-{
- time_t sec = timeout->it_value.tv_sec;
- long usec = timeout->it_value.tv_usec;
- struct sigaction sig_a;
- static struct sigevent sig_e = {
- .sigev_notify = SIGEV_SIGNAL,
- .sigev_signo = SIGALRM
- };
- struct itimerspec val = {
- .it_value.tv_sec = sec,
- .it_value.tv_nsec = usec * 1000,
- .it_interval.tv_sec = sec / 100,
- .it_interval.tv_nsec = (sec ? sec % 100 : 1) * 10*1000*1000
- };
-
- if (sigemptyset(&sig_a.sa_mask))
- return 1;
-
- sig_a.sa_flags = SA_SIGINFO;
- sig_a.sa_sigaction = timeout_handler;
-
- if (sigaction(SIGALRM, &sig_a, NULL))
- return 1;
- if (timer_create(CLOCK_MONOTONIC, &sig_e, &timer->t_id))
- return 1;
- if (timer_settime(timer->t_id, 0, &val, NULL))
- return 1;
- return 0;
-}
-void cancel_timer(struct ul_timer *timer)
-{
- timer_delete(timer->t_id);
-}
-
-#else /* !HAVE_TIMER_CREATE */
-
-int setup_timer(struct ul_timer *timer,
- struct itimerval *timeout,
- void (*timeout_handler)(int, siginfo_t *, void *))
-{
- struct sigaction sa;
-
- memset(&sa, 0, sizeof sa);
- memset(timer, 0, sizeof(*timer));
-
- sa.sa_flags = SA_SIGINFO | SA_RESETHAND;
- sa.sa_sigaction = timeout_handler;
-
- if (sigaction(SIGALRM, &sa, &timer->old_sa))
- return 1;
- if (setitimer(ITIMER_REAL, timeout, &timer->old_timer) != 0)
- return 1;
- return 0;
-}
-
-void cancel_timer(struct ul_timer *timer)
-{
- setitimer(ITIMER_REAL, &timer->old_timer, NULL);
- sigaction(SIGALRM, &timer->old_sa, NULL);
-
-}
-#endif /* !HAVE_TIMER_CREATE */
diff --git a/utils/lib/timeutils.c b/utils/lib/timeutils.c
deleted file mode 100644
index 8b443cd..0000000
--- a/utils/lib/timeutils.c
+++ /dev/null
@@ -1,611 +0,0 @@
-/***
- First set of functions in this file are part of systemd, and were
- copied to util-linux at August 2013.
-
- Copyright 2010 Lennart Poettering
-
- 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 util-linux; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <assert.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <sys/time.h>
-
-#include "c.h"
-#include "nls.h"
-#include "strutils.h"
-#include "timeutils.h"
-
-#define WHITESPACE " \t\n\r"
-
-#define streq(a,b) (strcmp((a),(b)) == 0)
-
-static int parse_sec(const char *t, usec_t *usec)
-{
- static const struct {
- const char *suffix;
- usec_t usec;
- } table[] = {
- { "seconds", USEC_PER_SEC },
- { "second", USEC_PER_SEC },
- { "sec", USEC_PER_SEC },
- { "s", USEC_PER_SEC },
- { "minutes", USEC_PER_MINUTE },
- { "minute", USEC_PER_MINUTE },
- { "min", USEC_PER_MINUTE },
- { "months", USEC_PER_MONTH },
- { "month", USEC_PER_MONTH },
- { "msec", USEC_PER_MSEC },
- { "ms", USEC_PER_MSEC },
- { "m", USEC_PER_MINUTE },
- { "hours", USEC_PER_HOUR },
- { "hour", USEC_PER_HOUR },
- { "hr", USEC_PER_HOUR },
- { "h", USEC_PER_HOUR },
- { "days", USEC_PER_DAY },
- { "day", USEC_PER_DAY },
- { "d", USEC_PER_DAY },
- { "weeks", USEC_PER_WEEK },
- { "week", USEC_PER_WEEK },
- { "w", USEC_PER_WEEK },
- { "years", USEC_PER_YEAR },
- { "year", USEC_PER_YEAR },
- { "y", USEC_PER_YEAR },
- { "usec", 1ULL },
- { "us", 1ULL },
- { "", USEC_PER_SEC }, /* default is sec */
- };
-
- const char *p;
- usec_t r = 0;
- int something = FALSE;
-
- assert(t);
- assert(usec);
-
- p = t;
- for (;;) {
- long long l, z = 0;
- char *e;
- unsigned i, n = 0;
-
- p += strspn(p, WHITESPACE);
-
- if (*p == 0) {
- if (!something)
- return -EINVAL;
-
- break;
- }
-
- errno = 0;
- l = strtoll(p, &e, 10);
-
- if (errno > 0)
- return -errno;
-
- if (l < 0)
- return -ERANGE;
-
- if (*e == '.') {
- char *b = e + 1;
-
- errno = 0;
- z = strtoll(b, &e, 10);
- if (errno > 0)
- return -errno;
-
- if (z < 0)
- return -ERANGE;
-
- if (e == b)
- return -EINVAL;
-
- n = e - b;
-
- } else if (e == p)
- return -EINVAL;
-
- e += strspn(e, WHITESPACE);
-
- for (i = 0; i < ARRAY_SIZE(table); i++)
- if (startswith(e, table[i].suffix)) {
- usec_t k = (usec_t) z * table[i].usec;
-
- for (; n > 0; n--)
- k /= 10;
-
- r += (usec_t) l *table[i].usec + k;
- p = e + strlen(table[i].suffix);
-
- something = TRUE;
- break;
- }
-
- if (i >= ARRAY_SIZE(table))
- return -EINVAL;
-
- }
-
- *usec = r;
-
- return 0;
-}
-
-int parse_timestamp(const char *t, usec_t *usec)
-{
- static const struct {
- const char *name;
- const int nr;
- } day_nr[] = {
- { "Sunday", 0 },
- { "Sun", 0 },
- { "Monday", 1 },
- { "Mon", 1 },
- { "Tuesday", 2 },
- { "Tue", 2 },
- { "Wednesday", 3 },
- { "Wed", 3 },
- { "Thursday", 4 },
- { "Thu", 4 },
- { "Friday", 5 },
- { "Fri", 5 },
- { "Saturday", 6 },
- { "Sat", 6 },
- };
-
- const char *k;
- struct tm tm, copy;
- time_t x;
- usec_t plus = 0, minus = 0, ret;
- int r, weekday = -1;
- unsigned i;
-
- /*
- * Allowed syntaxes:
- *
- * 2012-09-22 16:34:22
- * 2012-09-22T16:34:22
- * 2012-09-22 16:34 (seconds will be set to 0)
- * 2012-09-22 (time will be set to 00:00:00)
- * 16:34:22 (date will be set to today)
- * 16:34 (date will be set to today, seconds to 0)
- * now
- * yesterday (time is set to 00:00:00)
- * today (time is set to 00:00:00)
- * tomorrow (time is set to 00:00:00)
- * +5min
- * -5days
- *
- */
-
- assert(t);
- assert(usec);
-
- x = time(NULL);
- localtime_r(&x, &tm);
- tm.tm_isdst = -1;
-
- if (streq(t, "now"))
- goto finish;
-
- else if (streq(t, "today")) {
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
-
- } else if (streq(t, "yesterday")) {
- tm.tm_mday--;
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
-
- } else if (streq(t, "tomorrow")) {
- tm.tm_mday++;
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
-
- } else if (t[0] == '+') {
-
- r = parse_sec(t + 1, &plus);
- if (r < 0)
- return r;
-
- goto finish;
- } else if (t[0] == '-') {
-
- r = parse_sec(t + 1, &minus);
- if (r < 0)
- return r;
-
- goto finish;
-
- } else if (endswith(t, " ago")) {
- char *z;
-
- z = strndup(t, strlen(t) - 4);
- if (!z)
- return -ENOMEM;
-
- r = parse_sec(z, &minus);
- free(z);
- if (r < 0)
- return r;
-
- goto finish;
- }
-
- for (i = 0; i < ARRAY_SIZE(day_nr); i++) {
- size_t skip;
-
- if (!startswith_no_case(t, day_nr[i].name))
- continue;
-
- skip = strlen(day_nr[i].name);
- if (t[skip] != ' ')
- continue;
-
- weekday = day_nr[i].nr;
- t += skip + 1;
- break;
- }
-
- copy = tm;
- k = strptime(t, "%y-%m-%d %H:%M:%S", &tm);
- if (k && *k == 0)
- goto finish;
-
- tm = copy;
- k = strptime(t, "%Y-%m-%d %H:%M:%S", &tm);
- if (k && *k == 0)
- goto finish;
-
- tm = copy;
- k = strptime(t, "%Y-%m-%dT%H:%M:%S", &tm);
- if (k && *k == 0)
- goto finish;
-
- tm = copy;
- k = strptime(t, "%y-%m-%d %H:%M", &tm);
- if (k && *k == 0) {
- tm.tm_sec = 0;
- goto finish;
- }
-
- tm = copy;
- k = strptime(t, "%Y-%m-%d %H:%M", &tm);
- if (k && *k == 0) {
- tm.tm_sec = 0;
- goto finish;
- }
-
- tm = copy;
- k = strptime(t, "%y-%m-%d", &tm);
- if (k && *k == 0) {
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
- }
-
- tm = copy;
- k = strptime(t, "%Y-%m-%d", &tm);
- if (k && *k == 0) {
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
- }
-
- tm = copy;
- k = strptime(t, "%H:%M:%S", &tm);
- if (k && *k == 0)
- goto finish;
-
- tm = copy;
- k = strptime(t, "%H:%M", &tm);
- if (k && *k == 0) {
- tm.tm_sec = 0;
- goto finish;
- }
-
- tm = copy;
- k = strptime(t, "%Y%m%d%H%M%S", &tm);
- if (k && *k == 0) {
- tm.tm_sec = 0;
- goto finish;
- }
-
- return -EINVAL;
-
- finish:
- x = mktime(&tm);
- if (x == (time_t)-1)
- return -EINVAL;
-
- if (weekday >= 0 && tm.tm_wday != weekday)
- return -EINVAL;
-
- ret = (usec_t) x *USEC_PER_SEC;
-
- ret += plus;
- if (ret > minus)
- ret -= minus;
- else
- ret = 0;
-
- *usec = ret;
-
- return 0;
-}
-
-/* Returns the difference in seconds between its argument and GMT. If if TP is
- * invalid or no DST information is available default to UTC, that is, zero.
- * tzset is called so, for example, 'TZ="UTC" hwclock' will work as expected.
- * Derived from glibc/time/strftime_l.c
- */
-int get_gmtoff(const struct tm *tp)
-{
- if (tp->tm_isdst < 0)
- return 0;
-
-#if HAVE_TM_GMTOFF
- return tp->tm_gmtoff;
-#else
- struct tm tm;
- struct tm gtm;
- struct tm ltm = *tp;
- time_t lt;
-
- tzset();
- lt = mktime(&ltm);
- /* Check if mktime returning -1 is an error or a valid time_t */
- if (lt == (time_t) -1) {
- if (! localtime_r(&lt, &tm)
- || ((ltm.tm_sec ^ tm.tm_sec)
- | (ltm.tm_min ^ tm.tm_min)
- | (ltm.tm_hour ^ tm.tm_hour)
- | (ltm.tm_mday ^ tm.tm_mday)
- | (ltm.tm_mon ^ tm.tm_mon)
- | (ltm.tm_year ^ tm.tm_year)))
- return 0;
- }
-
- if (! gmtime_r(&lt, &gtm))
- return 0;
-
- /* Calculate the GMT offset, that is, the difference between the
- * TP argument (ltm) and GMT (gtm).
- *
- * Compute intervening leap days correctly even if year is negative.
- * Take care to avoid int overflow in leap day calculations, but it's OK
- * to assume that A and B are close to each other.
- */
- int a4 = (ltm.tm_year >> 2) + (1900 >> 2) - ! (ltm.tm_year & 3);
- int b4 = (gtm.tm_year >> 2) + (1900 >> 2) - ! (gtm.tm_year & 3);
- int a100 = a4 / 25 - (a4 % 25 < 0);
- int b100 = b4 / 25 - (b4 % 25 < 0);
- int a400 = a100 >> 2;
- int b400 = b100 >> 2;
- int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
-
- int years = ltm.tm_year - gtm.tm_year;
- int days = (365 * years + intervening_leap_days
- + (ltm.tm_yday - gtm.tm_yday));
-
- return (60 * (60 * (24 * days + (ltm.tm_hour - gtm.tm_hour))
- + (ltm.tm_min - gtm.tm_min)) + (ltm.tm_sec - gtm.tm_sec));
-#endif
-}
-
-static int format_iso_time(struct tm *tm, suseconds_t usec, int flags, char *buf, size_t bufsz)
-{
- char *p = buf;
- int len;
-
- if (flags & ISO_DATE) {
- len = snprintf(p, bufsz, "%4ld-%.2d-%.2d",
- tm->tm_year + (long) 1900,
- tm->tm_mon + 1, tm->tm_mday);
- if (len < 0 || (size_t) len > bufsz)
- goto err;
- bufsz -= len;
- p += len;
- }
-
- if ((flags & ISO_DATE) && (flags & ISO_TIME)) {
- if (bufsz < 1)
- goto err;
- *p++ = (flags & ISO_T) ? 'T' : ' ';
- bufsz--;
- }
-
- if (flags & ISO_TIME) {
- len = snprintf(p, bufsz, "%02d:%02d:%02d", tm->tm_hour,
- tm->tm_min, tm->tm_sec);
- if (len < 0 || (size_t) len > bufsz)
- goto err;
- bufsz -= len;
- p += len;
- }
-
- if (flags & ISO_DOTUSEC) {
- len = snprintf(p, bufsz, ".%06ld", (long) usec);
- if (len < 0 || (size_t) len > bufsz)
- goto err;
- bufsz -= len;
- p += len;
-
- } else if (flags & ISO_COMMAUSEC) {
- len = snprintf(p, bufsz, ",%06ld", (long) usec);
- if (len < 0 || (size_t) len > bufsz)
- goto err;
- bufsz -= len;
- p += len;
- }
-
- if (flags & ISO_TIMEZONE) {
- int tmin = get_gmtoff(tm) / 60;
- int zhour = tmin / 60;
- int zmin = abs(tmin % 60);
- len = snprintf(p, bufsz, "%+03d:%02d", zhour,zmin);
- if (len < 0 || (size_t) len > bufsz)
- goto err;
- }
- return 0;
- err:
- warnx(_("format_iso_time: buffer overflow."));
- return -1;
-}
-
-/* timeval to ISO 8601 */
-int strtimeval_iso(struct timeval *tv, int flags, char *buf, size_t bufsz)
-{
- struct tm tm;
- struct tm *rc;
-
- if (flags & ISO_GMTIME)
- rc = gmtime_r(&tv->tv_sec, &tm);
- else
- rc = localtime_r(&tv->tv_sec, &tm);
-
- if (rc)
- return format_iso_time(&tm, tv->tv_usec, flags, buf, bufsz);
-
- warnx(_("time %ld is out of range."), tv->tv_sec);
- return -1;
-}
-
-/* struct tm to ISO 8601 */
-int strtm_iso(struct tm *tm, int flags, char *buf, size_t bufsz)
-{
- return format_iso_time(tm, 0, flags, buf, bufsz);
-}
-
-/* time_t to ISO 8601 */
-int strtime_iso(const time_t *t, int flags, char *buf, size_t bufsz)
-{
- struct tm tm;
- struct tm *rc;
-
- if (flags & ISO_GMTIME)
- rc = gmtime_r(t, &tm);
- else
- rc = localtime_r(t, &tm);
-
- if (rc)
- return format_iso_time(&tm, 0, flags, buf, bufsz);
-
- warnx(_("time %ld is out of range."), (long)t);
- return -1;
-}
-
-/* relative time functions */
-static inline int time_is_thisyear(struct tm const *const tm,
- struct tm const *const tmnow)
-{
- return tm->tm_year == tmnow->tm_year;
-}
-
-static inline int time_is_today(struct tm const *const tm,
- struct tm const *const tmnow)
-{
- return (tm->tm_yday == tmnow->tm_yday &&
- time_is_thisyear(tm, tmnow));
-}
-
-int strtime_short(const time_t *t, struct timeval *now, int flags, char *buf, size_t bufsz)
-{
- struct tm tm, tmnow;
- int rc = 0;
-
- if (now->tv_sec == 0)
- gettimeofday(now, NULL);
-
- localtime_r(t, &tm);
- localtime_r(&now->tv_sec, &tmnow);
-
- if (time_is_today(&tm, &tmnow)) {
- rc = snprintf(buf, bufsz, "%02d:%02d", tm.tm_hour, tm.tm_min);
- if (rc < 0 || (size_t) rc > bufsz)
- return -1;
- rc = 1;
-
- } else if (time_is_thisyear(&tm, &tmnow)) {
- if (flags & UL_SHORTTIME_THISYEAR_HHMM)
- rc = strftime(buf, bufsz, "%b%d/%H:%M", &tm);
- else
- rc = strftime(buf, bufsz, "%b%d", &tm);
- } else
- rc = strftime(buf, bufsz, "%Y-%b%d", &tm);
-
- return rc <= 0 ? -1 : 0;
-}
-
-#ifndef HAVE_TIMEGM
-time_t timegm(struct tm *tm)
-{
- const char *zone = getenv("TZ");
- time_t ret;
-
- setenv("TZ", "", 1);
- tzset();
- ret = mktime(tm);
- if (zone)
- setenv("TZ", zone, 1);
- else
- unsetenv("TZ");
- tzset();
- return ret;
-}
-#endif /* HAVE_TIMEGM */
-
-#ifdef TEST_PROGRAM_TIMEUTILS
-
-int main(int argc, char *argv[])
-{
- struct timeval tv = { 0 };
- char buf[ISO_BUFSIZ];
-
- if (argc < 2) {
- fprintf(stderr, "usage: %s [<time> [<usec>]] | [--timestamp <str>]\n", argv[0]);
- exit(EXIT_FAILURE);
- }
-
- if (strcmp(argv[1], "--timestamp") == 0) {
- usec_t usec;
-
- parse_timestamp(argv[2], &usec);
- tv.tv_sec = (time_t) (usec / 1000000);
- tv.tv_usec = usec % 1000000;
- } else {
- tv.tv_sec = strtos64_or_err(argv[1], "failed to parse <time>");
- if (argc == 3)
- tv.tv_usec = strtos64_or_err(argv[2], "failed to parse <usec>");
- }
-
- strtimeval_iso(&tv, ISO_DATE, buf, sizeof(buf));
- printf("Date: '%s'\n", buf);
-
- strtimeval_iso(&tv, ISO_TIME, buf, sizeof(buf));
- printf("Time: '%s'\n", buf);
-
- strtimeval_iso(&tv, ISO_DATE | ISO_TIME | ISO_COMMAUSEC | ISO_T,
- buf, sizeof(buf));
- printf("Full: '%s'\n", buf);
-
- strtimeval_iso(&tv, ISO_TIMESTAMP_DOT, buf, sizeof(buf));
- printf("Zone: '%s'\n", buf);
-
- return EXIT_SUCCESS;
-}
-
-#endif /* TEST_PROGRAM_TIMEUTILS */
diff --git a/utils/lib/ttyutils.c b/utils/lib/ttyutils.c
deleted file mode 100644
index 7064565..0000000
--- a/utils/lib/ttyutils.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * No copyright is claimed. This code is in the public domain; do with
- * it what you wish.
- *
- * Written by Karel Zak <kzak@redhat.com>
- */
-#include <ctype.h>
-#include <unistd.h>
-
-#include "c.h"
-#include "ttyutils.h"
-
-
-static int get_env_int(const char *name)
-{
- const char *cp = getenv(name);
-
- if (cp) {
- char *end = NULL;
- long x;
-
- errno = 0;
- x = strtol(cp, &end, 10);
-
- if (errno == 0 && end && *end == '\0' && end > cp &&
- x > 0 && x <= INT_MAX)
- return x;
- }
-
- return -1;
-}
-
-int get_terminal_dimension(int *cols, int *lines)
-{
- int c = 0, l = 0;
-
-#if defined(TIOCGWINSZ)
- struct winsize w_win;
- if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &w_win) == 0) {
- c = w_win.ws_col;
- l = w_win.ws_row;
- }
-#elif defined(TIOCGSIZE)
- struct ttysize t_win;
- if (ioctl (STDOUT_FILENO, TIOCGSIZE, &t_win) == 0) {
- c = t_win.ts_cols;
- l = t_win.ts_lines;
- }
-#endif
- if (cols) {
- if (c <= 0)
- c = get_env_int("COLUMNS");
- *cols = c;
- }
- if (lines) {
- if (l <= 0)
- l = get_env_int("LINES");
- *lines = l;
- }
- return 0;
-}
-
-int get_terminal_width(int default_width)
-{
- int width = 0;
-
- get_terminal_dimension(&width, NULL);
-
- return width > 0 ? width : default_width;
-}
-
-int get_terminal_stdfd(void)
-{
- if (isatty(STDIN_FILENO))
- return STDIN_FILENO;
- if (isatty(STDOUT_FILENO))
- return STDOUT_FILENO;
- if (isatty(STDERR_FILENO))
- return STDERR_FILENO;
-
- return -EINVAL;
-}
-
-int get_terminal_name(const char **path,
- const char **name,
- const char **number)
-{
- const char *tty;
- const char *p;
- int fd;
-
-
- if (name)
- *name = NULL;
- if (path)
- *path = NULL;
- if (number)
- *number = NULL;
-
- fd = get_terminal_stdfd();
- if (fd < 0)
- return fd; /* error */
-
- tty = ttyname(fd);
- if (!tty)
- return -1;
-
- if (path)
- *path = tty;
- if (name || number)
- tty = strncmp(tty, "/dev/", 5) == 0 ? tty + 5 : tty;
- if (name)
- *name = tty;
- if (number) {
- for (p = tty; p && *p; p++) {
- if (isdigit(*p)) {
- *number = p;
- break;
- }
- }
- }
- return 0;
-}
-
-int get_terminal_type(const char **type)
-{
- *type = getenv("TERM");
- if (*type)
- return -EINVAL;
- return 0;
-}
-
-#ifdef TEST_PROGRAM_TTYUTILS
-# include <stdlib.h>
-int main(void)
-{
- const char *path, *name, *num;
- int c, l;
-
- if (get_terminal_name(&path, &name, &num) == 0) {
- fprintf(stderr, "tty path: %s\n", path);
- fprintf(stderr, "tty name: %s\n", name);
- fprintf(stderr, "tty number: %s\n", num);
- }
- get_terminal_dimension(&c, &l);
- fprintf(stderr, "tty cols: %d\n", c);
- fprintf(stderr, "tty lines: %d\n", l);
-
-
- return EXIT_SUCCESS;
-}
-#endif /* TEST_PROGRAM_TTYUTILS */