diff --git a/59-dasd.rules-wait_for.patch b/59-dasd.rules-wait_for.patch
index 03d86e9..98a032e 100644
--- a/59-dasd.rules-wait_for.patch
+++ b/59-dasd.rules-wait_for.patch
@@ -8,7 +8,7 @@
-# on device add set request queue scheduler to deadline
-SUBSYSTEM!="block", GOTO="sched_end"
-
--ACTION!="add", GOTO="sched_end"
--KERNEL=="dasd*[!0-9]", WAIT_FOR="queue/scheduler", ATTR{queue/scheduler}="deadline"
+-ACTION!="change", GOTO="sched_end"
+-KERNEL=="dasd*[!0-9]", TEST=="queue/scheduler", ATTR{queue/scheduler}="deadline"
-
-LABEL="sched_end"
diff --git a/boot.cpi b/boot.cpi
deleted file mode 100644
index 8a18fcc..0000000
--- a/boot.cpi
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2001-2002 SuSE Linux AG, Nuernberg, Germany.
-# Copyright (c) 2008 SuSE LINUX Products GmbH, Nuernberg, Germany.
-# All rights reserved.
-#
-# /etc/init.d/boot.cpi
-#
-### BEGIN INIT INFO
-# Provides: boot.cpi
-# Required-Start: boot.rootfsck
-# Required-Stop: $null
-# Should-Start:
-# X-Start-Before:
-# Default-Start: B S
-# Default-Stop:
-# Description: Set Control Program Identification data
-# Short-Description: Set Control Program Identification data
-### END INIT INFO
-
-. /etc/rc.status
-. /etc/sysconfig/cpi
-
-rc_reset
-
-case "$1" in
- start|restart|reload)
- if test "$CPI_SET" == "yes"; then
- if test ! -e /sys/firmware/cpi; then
- echo -n "sclp_cpi interface not found"
- rc_status -s
- rc_exit
- fi
- echo "$CPI_SYSTEM_NAME" >/sys/firmware/cpi/system_name
- echo "$CPI_SYSPLEX_NAME" >/sys/firmware/cpi/sysplex_name
- echo "LINUX " >/sys/firmware/cpi/system_type
- awk "BEGIN { split(\"`uname -r`\",x,\".\"); printf(\"0x0000000000%02x%02x%02x\", x[1],x[2],x[3]) }" >/sys/firmware/cpi/system_level
- echo 1 >/sys/firmware/cpi/set 2>/dev/null
- rc_status -v -r
- else
- rc_status -u
- fi
- ;;
- stop)
- rc_status -s
- ;;
- status)
- rc_status -s
- ;;
- *)
- echo "Usage: $0 {start|stop|status|restart|reload}"
- exit 1
- ;;
-esac
-
-rc_exit
diff --git a/dasdfmt-retry-BIODASDINFO-if-device-is-busy.patch b/dasdfmt-retry-BIODASDINFO-if-device-is-busy.patch
index 11cd2b0..2fdc4e2 100644
--- a/dasdfmt-retry-BIODASDINFO-if-device-is-busy.patch
+++ b/dasdfmt-retry-BIODASDINFO-if-device-is-busy.patch
@@ -23,49 +23,44 @@ diff --git a/dasdfmt/dasdfmt.c b/dasdfmt/dasdfmt.c
index e1877ac..f03cbad 100644
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
-@@ -270,7 +270,7 @@ static void init_info(dasdfmt_info_t *info)
+@@ -588,7 +616,7 @@
+ */
static void check_disk(dasdfmt_info_t *info)
{
- dasd_information_t dasd_info;
- int ro, errno_save;
+ int ro, errno_save, i = 0;
if (ioctl(filedes, BLKROGET, &ro) != 0) {
errno_save = errno;
-@@ -283,7 +283,7 @@ static void check_disk(dasdfmt_info_t *info)
- if (ro) {
+@@ -602,9 +630,27 @@
+ if (ro)
ERRMSG_EXIT(EXIT_FAILURE, "Disk is read only!\n");
- }
--
-+retry:
- if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) {
- errno_save = errno;
- close(filedes);
-@@ -294,8 +294,23 @@ static void check_disk(dasdfmt_info_t *info)
- }
- if (!info->force)
-- if (dasd_info.open_count > 1)
+- if (!info->force)
++ if (!info->force) {
+ /*
+ * udev strikes again.
+ * Modern udev will issue a 'change' event whenever
+ * a device opened with O_RDWR is closed again.
-+ * On the ground that program _might_ have changed
++ * On the grounds that program _might_ have changed
+ * the partition table.
+ * And confusing the hell out ouf anyone else.
+ * Bah.
-+ */
-+ if (dasd_info.open_count > 1) {
-+ if (i < 5) {
-+ ++i;
++ */
++ for ( i = 0 ; i < 6 ; i++ ) {
++ if (info->dasd_info.open_count > 1) {
++ get_device_info(info);
+ sleep(1);
-+ goto retry;
+ }
- ERRMSG_EXIT(EXIT_BUSY, "Disk in use!\n");
++ else break;
++
+ }
+ if (info->dasd_info.open_count > 1)
+ ERRMSG_EXIT(EXIT_BUSY, "Disk in use!\n");
++ }
- info->usage_count = dasd_info.open_count;
- info->devno = dasd_info.devno;
+ if (strncmp(info->dasd_info.type, "ECKD", 4) != 0) {
+ ERRMSG_EXIT(EXIT_FAILURE,
--
1.8.4.5
diff --git a/mkdump.8 b/mkdump.8
index a1335af..b80e543 100644
--- a/mkdump.8
+++ b/mkdump.8
@@ -6,7 +6,7 @@ mkdump \- Preparing disks for use as S/390 dump device.
.B mkdump
[\fIOPTIONS\fR] [\fIDEVICE\fR]...
.SH DESCRIPTION
-mkdump 2.0.2
+mkdump 2.0.3
.PP
Prepare one or more volumes for use as S/390 dump device. Supported devices
are ECKD DASD and SCSI over zFCP disks, while multi\-volumes are limited to DASD.
diff --git a/mkdump.pl b/mkdump.pl
index b69a4ac..f354f57 100644
--- a/mkdump.pl
+++ b/mkdump.pl
@@ -4,7 +4,8 @@
# mkdump.pl - Preparing disks for use as S/390 dump device
#
# Copyright (c) 2011 Tim Hardeck, SUSE LINUX Products GmbH
-# bases on mkdump.sh (c) 2004 Hannes Reinecke, SuSE AG
+# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Based on mkdump.sh (c) 2004 Hannes Reinecke, SuSE AG
#
# License:
#
@@ -30,7 +31,7 @@ use warnings;
use Fcntl;
use Getopt::Long;
-my $VERSION = "2.0.2";
+my $VERSION = "2.0.3";
my $BLKID = "/sbin/blkid";
my $PARTED = "/usr/sbin/parted";
@@ -41,7 +42,6 @@ my $ZIPL = "/sbin/zipl";
my $UDEVADM = "/sbin/udevadm";
my $ZGETDUMP = "/sbin/zgetdump";
-my $MNTPOINT = "/var/run/mkdump." . getppid();
# temporary DASD device configuration file for Zipl
my $MDPATH = "/tmp/mvdump.conf";
# zFCP dump dir, without a leading '/'
@@ -57,11 +57,6 @@ sub cleanup
if (-e $MDPATH) {
system("rm -f $MDPATH");
}
- # zFCP
- if (-d $MNTPOINT) {
- system("umount $MNTPOINT");
- system("rmdir $MNTPOINT");
- }
}
sub exit_with
@@ -230,15 +225,10 @@ sub print_device
$output .= "\t$adapter\t$wwpn\t$lun";
# check for dump record
- system("mkdir -p $MNTPOINT");
- if (get_partition_num($device) == 1 and system("mount -o ro ${device}1 $MNTPOINT 2>/dev/null") == 0) {
- if ( -r "$MNTPOINT/bootmap" and -d "$MNTPOINT/$ZFCP_DUMP_DIR") {
- $dump_device = 1;
- $output .= "\tdumpdevice";
- }
- system("umount $MNTPOINT");
+ if (system("$ZGETDUMP -d ${device} >/dev/null 2>&1") == 0) {
+ $dump_device = 1;
+ $output .= "\tdumpdevice";
}
- system("rmdir $MNTPOINT");
}
if ($only_dump_disks) {
if ($dump_device) {
@@ -324,7 +314,7 @@ sub prepare_dasd
# check formatting
for my $device (@devices) {
# determine disk layout
- my ($fmtstr) = `$DASDVIEW -x -f $device` =~ /(\w\w\w) formatted/;
+ my ($fmtstr) = `$DASDVIEW -x $device` =~ /(\w\w\w) formatted/;
SWITCH:
for($fmtstr) {
diff --git a/s390-tools-1.34.0.tar.bz2 b/s390-tools-1.34.0.tar.bz2
deleted file mode 100644
index 9092dfa..0000000
--- a/s390-tools-1.34.0.tar.bz2
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:6f4e9d6f27cfad77ff84ac7a332a7fb2e17b620b3c2da4fc2ba47d2c77c94287
-size 814967
diff --git a/s390-tools-2.1.0.tar.gz b/s390-tools-2.1.0.tar.gz
new file mode 100644
index 0000000..aada5a0
--- /dev/null
+++ b/s390-tools-2.1.0.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b5ce3fa0de074dfe7d16c74771fcb5092c4a6f575168bf4e13f88275a6370122
+size 1046910
diff --git a/s390-tools-sles12-fdasd-skip-partition-check-and-BLKRRPART-ioctl.patch b/s390-tools-sles12-fdasd-skip-partition-check-and-BLKRRPART-ioctl.patch
index 72c85e2..60237ca 100644
--- a/s390-tools-sles12-fdasd-skip-partition-check-and-BLKRRPART-ioctl.patch
+++ b/s390-tools-sles12-fdasd-skip-partition-check-and-BLKRRPART-ioctl.patch
@@ -19,27 +19,9 @@ diff --git a/fdasd/fdasd.c b/fdasd/fdasd.c
index 4503d3e..f04dc3d 100644
--- a/fdasd/fdasd.c
+++ b/fdasd/fdasd.c
-@@ -826,7 +826,7 @@ fdasd_check_conffile_input (fdasd_anchor_t *anc,
- * Verifies the specified block device.
- */
- static void
--fdasd_verify_device (fdasd_anchor_t *anc, char *name)
-+fdasd_verify_device (fdasd_anchor_t *anc, char *name)
- {
- struct stat dst;
- char err_str[ERROR_STRING_SIZE];
-@@ -847,7 +847,7 @@ fdasd_verify_device (fdasd_anchor_t *anc, char *name)
- fdasd_error(anc, device_verification_failed, err_str);
+@@ -1247,9 +1247,12 @@
}
-- if (minor (dst.st_rdev) & PARTN_MASK) {
-+ if (!anc->force_virtual && minor (dst.st_rdev) & PARTN_MASK) {
- snprintf(err_str, ERROR_STRING_SIZE,
- "Partition '%s' (%d/%d) detected where device is "
- "required\n", name,
-@@ -1156,9 +1156,12 @@ fdasd_reread_partition_table (fdasd_anchor_t *anc)
- }
-
if (ioctl(fd, BLKRRPART, NULL) != 0) {
- close(fd);
- fdasd_error(anc, unable_to_ioctl, "Error while rereading "
@@ -52,6 +34,4 @@ index 4503d3e..f04dc3d 100644
+ }
}
close(fd);
- }
---
-1.8.5.2
+ }
diff --git a/s390-tools-sles12-pardasdfmt.patch b/s390-tools-sles12-pardasdfmt.patch
index c0a4b14..e8d077d 100644
--- a/s390-tools-sles12-pardasdfmt.patch
+++ b/s390-tools-sles12-pardasdfmt.patch
@@ -10,12 +10,12 @@
- [-r \fIcylinder\fR] [-b \fIblksize\fR] [-l \fIvolser\fR] [-d \fIlayout\fR]
+ [-r \fIcylinder\fR] [-b \fIblksize\fR] [-l \fIvolser\fR] [-d \fIlayout\fR] [-P maxpar]
.br
-- [-L] [-V] [-F] [-k] [-C] \fIdevice\fR
-+ [-L] [-V] [-F] [-k] [-C] \fIdevice\fR ...
+- [-L] [-V] [-F] [-k] [-C] [-M \fImode\fR] \fIdevice\fR
++ [-L] [-V] [-F] [-k] [-C] [-M \fImode\fR] \fIdevice\fR ...
.SH DESCRIPTION
\fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it
-@@ -91,7 +91,7 @@
+@@ -95,7 +95,7 @@
running in background or redirecting the output to a file.
.TP
@@ -24,7 +24,7 @@
Print one line for each formatted cylinder showing the number of the
cylinder and percentage of formatting process.
Intended to be used by higher level interfaces.
-@@ -123,6 +123,20 @@
+@@ -152,6 +152,20 @@
and always be a power of two. The recommended blocksize is 4096 bytes.
.TP
@@ -47,7 +47,7 @@
to disk after formatting. If no label is specified, a sensible default
--- s390-tools-1.34.0/dasdfmt/dasdfmt.h 2016-04-14 16:43:51.000000000 -0400
+++ s390-tools-1.34.0/dasdfmt/dasdfmt.h 2016-04-14 16:35:01.000000000 -0400
-@@ -195,6 +195,7 @@
+@@ -260,6 +260,7 @@
#define LABEL_LENGTH 14
#define VLABEL_CHARS 84
#define LINE_LENGTH 80
diff --git a/s390-tools-sles12-zipl_boot_msg.patch b/s390-tools-sles12-zipl_boot_msg.patch
index b933842..1a84cb2 100644
--- a/s390-tools-sles12-zipl_boot_msg.patch
+++ b/s390-tools-sles12-zipl_boot_msg.patch
@@ -1,13 +1,16 @@
--- s390-tools-1.24.1/zipl/boot/menu.c 2013-12-18 11:11:45.000000000 -0500
+++ s390-tools-1.24.1/zipl/boot/menu.c 2013-12-18 11:59:18.000000000 -0500
-@@ -166,7 +166,9 @@
+@@ -167,8 +167,11 @@
+ /* print config list */
menu_list();
- if (is_zvm())
+- if (is_zvm())
- printf("Note: VM users please use '#cp vi vmsg '\n");
++ if (is_zvm()) {
+ printf(" \n");
+ printf("Note: VM users please use '#cp vi vmsg '\n");
+ printf(" \n");
++ }
value = menu_read();
diff --git a/s390-tools-sles12sp2-chiucvallow-verify.patch b/s390-tools-sles12sp2-chiucvallow-verify.patch
deleted file mode 100644
index 4cb9479..0000000
--- a/s390-tools-sles12sp2-chiucvallow-verify.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-Subject: [PATCH] [BZ 141695] chiucvallow: correct verification return code
-From: Hendrik Brueckner
-
-Description: chiucvallow: correct verification return code
-Symptom: When running test_chiucvallow.sh, the script is
- failing to validate filter files with special
- characters.
- because the chiucvallow.in -V is
-Problem: The chiucvallow -V is returning code 2 and for
- this reason, the script gives an error message,
- but the filter file is validated successfully
- manually.
-Solution: Correct the return code of chiucvallow to handle
- verification failures correctly.
-Reproduction: See Symptom.
-Upstream-ID: -
-Problem-ID: 141695
-
-Signed-off-by: Hendrik Brueckner
----
- iucvterm/bin/chiucvallow.in | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/iucvterm/bin/chiucvallow.in
-+++ b/iucvterm/bin/chiucvallow.in
-@@ -115,7 +115,8 @@ verify_filter(){
-
- printf "\n$PRG: Verification summary: verified=%d failed=%d size=%d bytes\n" \
- $count $failed $fsize
-- return 2
-+
-+ test $failed -eq 0 || return 2
- }
-
- #
diff --git a/s390-tools-sles12sp2-chreipl-virtio.patch b/s390-tools-sles12sp2-chreipl-virtio.patch
deleted file mode 100644
index 6684311..0000000
--- a/s390-tools-sles12sp2-chreipl-virtio.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-Subject: [PATCH] [BZ 143839] chreipl/virtio: fix chreipl node for virtio-blk disks
-From: Christian Borntraeger
-
-Description: chreipl/virtio: fix chreipl node for virtio-blk disks
-Symptom: chreipl node for a virtio-blk disk fails:
- Could not find DASD CCW device "virtio1"
-Problem: The sysfs walking code to resolve the device is not
- handling virtio devices correctly.
-Solution: Use the realpath of the device to get the busid for all
- supported devices.
-Reproduction: Run chreipl node with virtio-blk devices as
- backing for mount point.
-Upstream-ID: -
-Problem-ID: 143839
-
-Signed-off-by: Christian Borntraeger
----
- ipl_tools/ccw.c | 12 +++++-------
- 1 file changed, 5 insertions(+), 7 deletions(-)
-
---- a/ipl_tools/ccw.c
-+++ b/ipl_tools/ccw.c
-@@ -76,21 +76,19 @@ out_fclose:
- static int ccw_busid_get_sysfs_new(const char *device, char *busid)
- {
- char path[PATH_MAX], buf[4096];
-- char *ptr;
-
- memset(buf, 0, sizeof(buf));
- snprintf(path, sizeof(path), "/sys/block/%s/device", device);
-- if (readlink(path, buf, sizeof(buf) - 1) == -1)
-+ if (realpath(path, buf) == NULL)
- return -1;
-
- /*
- * The output has the following format:
-- * ../../../0.0.4e13
-+ * /sys/devices/css0/0.0.0119/0.0.3f19/block/dasda
-+ * /sys/devices/css0/0.0.0000/0.0.0000/virtio0/block/vda
- */
-- ptr = strrchr(buf, '/');
-- if (!ptr)
-- ERR_EXIT("Could not read \"%s\"", path);
-- strncpy(busid, ptr + 1, 9);
-+ if (sscanf(buf, "/sys/devices/css0/%*[0-9a-f.]/%[0-9a-f.]", busid) != 1)
-+ return -1;
- return 0;
- }
-
diff --git a/s390-tools-sles12sp2-chzdev-disable-root-update.patch b/s390-tools-sles12sp2-chzdev-disable-root-update.patch
deleted file mode 100644
index 405e9be..0000000
--- a/s390-tools-sles12sp2-chzdev-disable-root-update.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-Subject: [PATCH] [BZ 147113] chzdev: Disable root device update mechanism
-From: Peter Oberparleiter
-
-Description: chzdev: Disable root device update mechanism
-Symptom: chzdev reports problems updating /etc/zipl.conf and running
- zipl.
-Problem: When chzdev changes the root device persistent configuration,
- it performs additional steps to ensure that these changes are
- correctly applied. Example for such steps are: updating the
- initial RAM disk, modifying the zipl.conf configuration file
- and running zipl. As these steps are incompatible with the target
- distribution, they fail.
-Solution: Suppress chzdev's root device update mechanism.
-Reproduction: chzdev --enable --persistent --by-path /
-Upstream-ID: -
-Problem-ID: 147113
-
-Signed-off-by: Peter Oberparleiter
----
- zdev/src/chzdev.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/zdev/src/chzdev.c
-+++ b/zdev/src/chzdev.c
-@@ -233,6 +233,7 @@ static void init_options(struct options
- opts->settings = strlist_new();
- opts->remove = strlist_new();
- opts->base = strlist_new();
-+ opts->no_root_check = 1;
- }
-
- /* Release memory used in options data structure. */
diff --git a/s390-tools-sles12sp2-feat-01-dasd-query-host.patch b/s390-tools-sles12sp2-feat-01-dasd-query-host.patch
deleted file mode 100644
index b9bc686..0000000
--- a/s390-tools-sles12sp2-feat-01-dasd-query-host.patch
+++ /dev/null
@@ -1,744 +0,0 @@
-Subject: [PATCH] [FEAT LS1213] dasd: add query host access to volume support
-From: Stefan Haberland
-
-Summary: dasd: add query host access to volume support
-Description: With this feature, applications can query if a DASD volume is
- online to another operating system instances by checking the
- online status of all attached hosts from the storage server.
-Upstream-ID: -
-Problem-ID: LS1213
-
-Signed-off-by: Stefan Haberland
----
- dasdfmt/dasdfmt.8 | 7 ++
- dasdfmt/dasdfmt.c | 38 ++++++++++++--
- dasdfmt/dasdfmt.h | 4 +
- fdasd/fdasd.8 | 9 ++-
- fdasd/fdasd.c | 32 ++++++++++++
- fdasd/fdasd.h | 28 +++++-----
- include/libzds.h | 1
- include/u2s.h | 5 +
- libu2s/u2s.c | 43 ++++++++++++++++
- libzds/Makefile | 2
- libzds/libzds.c | 46 +++++++++++++++--
- zconf/lsdasd | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
- zconf/lsdasd.8 | 5 +
- zdsfs/zdsfs.1 | 4 +
- zdsfs/zdsfs.c | 18 ++++++
- 15 files changed, 345 insertions(+), 36 deletions(-)
-
---- a/dasdfmt/dasdfmt.8
-+++ b/dasdfmt/dasdfmt.8
-@@ -7,7 +7,7 @@ dasdfmt \- formatting of DASD (ECKD) dis
- .br
- [-r \fIcylinder\fR] [-b \fIblksize\fR] [-l \fIvolser\fR] [-d \fIlayout\fR]
- .br
-- [-L] [-V] [-F] [-k] \fIdevice\fR
-+ [-L] [-V] [-F] [-k] [-C] \fIdevice\fR
-
- .SH DESCRIPTION
- \fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it
-@@ -70,6 +70,11 @@ Print version number and exit.
- Formats the device without checking, if the device is in use.
-
- .TP
-+\fB-C\fR or \fB--check_host_count\fR
-+Force dasdfmt to check the host access open count to ensure the device
-+is not online on another operating system instance
-+
-+.TP
- \fB-d\fR \fIlayout\fR or \fB--disk_layout\fR=\fIlayout\fR
- Formats the device with compatible disk layout or linux disk layout.
- \fIlayout\fR is either \fIcdl\fR for the compatible disk layout
---- a/dasdfmt/dasdfmt.c
-+++ b/dasdfmt/dasdfmt.c
-@@ -18,6 +18,8 @@
- #include "util_proc.h"
- #include "dasd_sys.h"
-
-+#define BUSIDSIZE 8
-+
- /* Full tool name */
- static const char tool_name[] = "dasdfmt: zSeries DASD format program";
-
-@@ -46,7 +48,7 @@ print_version (void)
- */
- static void exit_usage(int exitcode)
- {
-- printf("Usage: %s [-htvypPLVFk]\n"
-+ printf("Usage: %s [-htvypPLVFkC]\n"
- " [-l | --label=]\n"
- " [-b | --blocksize=]\n"
- " [-d | --disk_layout=]\n"
-@@ -65,6 +67,9 @@ static void exit_usage(int exitcode)
- " -v means verbose mode\n"
- " -F means don't check if the device is in use\n"
- " -k means keep volume serial\n"
-+ " -C or --check_host_count means force dasdfmt to check\n"
-+ " the host access open count to ensure the device\n"
-+ " is not online on another operating system instance\n"
- " --norecordzero prevent storage server from modifying"
- " record 0\n\n"
- " is the volume identifier, which is converted\n"
-@@ -190,7 +195,6 @@ static void get_device_name(dasdfmt_info
- }
- }
-
--
- /*
- * initialize the dasdfmt info structure
- */
-@@ -214,6 +218,7 @@ static void init_info(dasdfmt_info_t *in
- info->node_specified = 0;
- info->device_id = 0;
- info->keep_volser = 0;
-+ info->force_host = 0;
- }
-
-
-@@ -776,6 +781,7 @@ static void do_format_dasd(dasdfmt_info_
- dasd_information_t dasd_info;
- struct dasd_eckd_characteristics *characteristics;
- unsigned int cylinders, heads;
-+ int count;
-
- if (info->verbosity > 0) printf("Retrieving disk geometry...\n");
-
-@@ -835,6 +841,27 @@ static void do_format_dasd(dasdfmt_info_
- if ((info->verbosity > 0) || (!info->withoutprompt))
- dasdfmt_print_info(info, vlabel, cylinders, heads, p);
-
-+ count = u2s_get_host_access_count(info->devname);
-+ if (info->force_host) {
-+ if (count > 1) {
-+ ERRMSG_EXIT(EXIT_FAILURE,
-+ "\n%s: Disk %s is online on OS instances in %d different LPARs.\n"
-+ "Note: Your installation might include z/VM systems that are configured to\n"
-+ "automatically vary on disks, regardless of whether they are subsequently used.\n\n",
-+ prog_name, info->devname, count);
-+ } else if (count < 0) {
-+ ERRMSG("\nHosts access information not available for disk %s.\n\n",
-+ info->devname);
-+ return;
-+ }
-+ } else if (count > 1)
-+ ERRMSG("\nWARNING:\n"
-+ "Disk %s is online on operating system instances in %d different LPARs.\n"
-+ "Ensure that the disk is not being used by a system outside your LPAR.\n"
-+ "Note: Your installation might include z/VM systems that are configured to\n"
-+ "automatically vary on disks, regardless of whether they are subsequently used.\n",
-+ info->devname, count);
-+
- if (!info->testmode) {
- if (!info->withoutprompt) {
- printf("\n--->> ATTENTION! <<---\n");
-@@ -916,10 +943,6 @@ int main(int argc,char *argv[])
- info.force=1;
- break;
-
-- case 'C':
-- format_params.intensity |= DASD_FMT_INT_COMPAT;
-- break;
--
- case 'd' :
- if (strncmp(optarg,"cdl",3)==0)
- {
-@@ -1017,6 +1040,9 @@ int main(int argc,char *argv[])
- case 'k' :
- info.keep_volser=1;
- break;
-+ case 'C':
-+ info.force_host = 1;
-+ break;
- case -1:
- /* End of options string - start of devices list */
- info.device_id = optind;
---- a/dasdfmt/dasdfmt.h
-+++ b/dasdfmt/dasdfmt.h
-@@ -214,7 +214,7 @@ typedef struct format_data_t {
- if (*endptr) ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \
- "is in invalid format\n",prog_name);}
-
--#define dasdfmt_getopt_string "b:n:l:f:d:m:r:hpPLtyvVFk"
-+#define dasdfmt_getopt_string "b:n:l:f:d:m:r:hpPLtyvVFkC"
-
- static struct option dasdfmt_getopt_long_options[]=
- {
-@@ -233,6 +233,7 @@ static struct option dasdfmt_getopt_long
- { "help", 0, 0, 'h'},
- { "keep_volser", 0, 0, 'k'},
- { "norecordzero", 0, 0, 'z'},
-+ { "check_host_count", 0, 0, 'C'},
- {0, 0, 0, 0}
- };
-
-@@ -265,6 +266,7 @@ typedef struct dasdfmt_info {
- int node_specified;
- int device_id;
- int keep_volser;
-+ int force_host;
- } dasdfmt_info_t;
-
-
---- a/fdasd/fdasd.8
-+++ b/fdasd/fdasd.8
-@@ -4,11 +4,11 @@ fdasd \- partitioning tool.
- .SH SYNOPSIS
- interactive mode:
- .br
-- \fBfdasd\fR [-s] [-r] \fIdevice\fR
-+ \fBfdasd\fR [-s] [-r] [-C] \fIdevice\fR
- .br
- command line mode:
- .br
-- \fBfdasd\fR [-s] [-r] {-a[-k|-l \fIvolser\fR]|-i|-p|-c \fIconf_file\fR}
-+ \fBfdasd\fR [-s] [-r] [-C] {-a[-k|-l \fIvolser\fR]|-i|-p|-c \fIconf_file\fR}
- [-f \fI[type,blocksize]\fR] \fIdevice\fR
- .br
- help:
-@@ -131,6 +131,11 @@ In combination with the -s option fdasd
- partition table.
-
- .TP
-+\fB-C\fR or \fB--check_host_count\fR
-+Force fdasd to check the host access open count to ensure the device
-+is not online on another operating system instance
-+
-+.TP
- \fB-f\fR \fI[type,blocksize]\fR or \fB--force\fR \fI[type,blocksize]\fR
- Force fdasd to work on non DASD devices.
- .br
---- a/fdasd/fdasd.c
-+++ b/fdasd/fdasd.c
-@@ -369,7 +369,10 @@ fdasd_usage (void)
- " found in CONFIGFILE\n"
- "-i, --volser Print volume serial\n"
- "-p, --table Print partition table\n"
-- "-f, --force Force fdasd to work on non DASD devices\n");
-+ "-f, --force Force fdasd to work on non DASD devices\n"
-+ "-C, --check_host_count Force fdasd to check the host access\n"
-+ " open count to ensure the device is not\n"
-+ " online on another operating system instance\n");
- }
-
-
-@@ -572,6 +575,9 @@ fdasd_parse_options (fdasd_anchor_t *anc
- anc->force_virtual++;
- fdasd_parse_force_options(anc, optarg);
- break;
-+ case 'C':
-+ anc->force_host++;
-+ break;
- case -1:
- /* End of options string - start of devices list */
- break;
-@@ -824,6 +830,7 @@ fdasd_verify_device (fdasd_anchor_t *anc
- {
- struct stat dst;
- char err_str[ERROR_STRING_SIZE];
-+ int count;
-
- if ((stat(name, &dst)) < 0 ) {
- snprintf(err_str, ERROR_STRING_SIZE,
-@@ -856,6 +863,29 @@ fdasd_verify_device (fdasd_anchor_t *anc
- fdasd_error(anc, device_verification_failed, err_str);
- }
-
-+ count = u2s_get_host_access_count(name);
-+ if (anc->force_host) {
-+ if (count > 1) {
-+ snprintf(err_str, ERROR_STRING_SIZE,
-+ "Disk %s is online on operating system instances in %d different LPARs.\n"
-+ "Note: Your installation might include z/VM systems that are configured to\n"
-+ "automatically vary on disks, regardless of whether they are subsequently used.\n",
-+ name, count);
-+ fdasd_error(anc, device_verification_failed, err_str);
-+ } else if (count < 0) {
-+ snprintf(err_str, ERROR_STRING_SIZE,
-+ "Hosts access information not available for disk %s.\n",
-+ name);
-+ fdasd_error(anc, device_verification_failed, err_str);
-+ }
-+ } else if (count > 1)
-+ printf("\nWARNING:\n"
-+ "Disk %s is online on operating system instances in %d different LPARs.\n"
-+ "Ensure that the disk is not being used by a system outside your LPAR.\n"
-+ "Note: Your installation might include z/VM systems that are configured to\n"
-+ "automatically vary on disks, regardless of whether they are subsequently used.\n\n",
-+ name, count);
-+
- if (anc->verbose)
- printf("Verification successful for '%s' (%d/%d)\n", name,
- (unsigned short) major(dst.st_rdev),
---- a/fdasd/fdasd.h
-+++ b/fdasd/fdasd.h
-@@ -157,22 +157,23 @@ struct dasd_eckd_characteristics {
- #define PARTITION_GPFS 5
-
- static struct option fdasd_long_options[] = {
-- { "version", no_argument, NULL, 'v'},
-- { "auto", no_argument, NULL, 'a'},
-- { "silent", no_argument, NULL, 's'},
-- { "verbose", no_argument, NULL, 'r'},
-- { "label", required_argument, NULL, 'l'},
-- { "config", required_argument, NULL, 'c'},
-- { "help", no_argument, NULL, 'h'},
-- { "table", no_argument, NULL, 'p'},
-- { "volser", no_argument, NULL, 'i'},
-- { "keep_volser", no_argument, NULL, 'k'},
-- { "force", optional_argument, NULL, 'f'},
-- { 0, 0, 0, 0 }
-+ { "version", no_argument, NULL, 'v'},
-+ { "auto", no_argument, NULL, 'a'},
-+ { "silent", no_argument, NULL, 's'},
-+ { "verbose", no_argument, NULL, 'r'},
-+ { "label", required_argument, NULL, 'l'},
-+ { "config", required_argument, NULL, 'c'},
-+ { "help", no_argument, NULL, 'h'},
-+ { "table", no_argument, NULL, 'p'},
-+ { "volser", no_argument, NULL, 'i'},
-+ { "keep_volser", no_argument, NULL, 'k'},
-+ { "force", optional_argument, NULL, 'f'},
-+ { "check_host_count", no_argument, NULL, 'C'},
-+ { 0, 0, 0, 0 }
- };
-
- /* Command line option abbreviations */
--static const char option_string[] = "vasrl:c:hpikf::";
-+static const char option_string[] = "vasrl:c:hpikf::C";
-
- struct fdasd_options {
- char *device;
-@@ -214,6 +215,7 @@ typedef struct fdasd_anchor {
- int print_volser;
- int keep_volser;
- int force_virtual;
-+ int force_host;
- int big_disk;
- int silent;
- int verbose;
---- a/include/libzds.h
-+++ b/include/libzds.h
-@@ -803,6 +803,7 @@ int lzds_zdsroot_extract_datasets_from_d
- void lzds_DS1RECFM_to_recfm(char DS1RECFM, char *buffer);
-
-
-+int lzds_analyse_open_count(struct zdsroot *root, int warn);
-
- /** @} */ /* end of group libzds_functions_helper */
-
---- a/include/u2s.h
-+++ b/include/u2s.h
-@@ -13,7 +13,8 @@
-
- #define U2S_BUS_ID_SIZE 32
-
--int
--u2s_getbusid(char * devicenode, char * busid);
-+int u2s_getbusid(char *, char *);
-+int u2s_read_attribute(char *, char *, char *, size_t);
-+int u2s_get_host_access_count(char *);
-
- #endif /* U2S_H */
---- a/libu2s/u2s.c
-+++ b/libu2s/u2s.c
-@@ -17,6 +17,7 @@
- #include
- #include
- #include
-+#include
-
- #include "u2s.h"
-
-@@ -282,3 +283,45 @@ int u2s_getbusid(char *devicenode, char
-
- return rc;
- }
-+
-+/*
-+ * Attempts to find the sysfs entry for the given busid and reads
-+ * the contents of a specified attribute to the buffer
-+ */
-+int u2s_read_attribute(char *busid, char *attribute, char *buffer,
-+ size_t count)
-+{
-+ char path[100];
-+ int rc, fd;
-+ ssize_t rcount;
-+
-+ rc = 0;
-+ snprintf(path, sizeof(path), "/sys/bus/ccw/devices/%s/%s",
-+ busid, attribute);
-+ fd = open(path, O_RDONLY);
-+ if (fd < 0)
-+ return errno;
-+ rcount = read(fd, buffer, count);
-+ if (rcount < 0)
-+ rc = errno;
-+ close(fd);
-+ return rc;
-+}
-+
-+int u2s_get_host_access_count(char *devicenode)
-+{
-+ char busid[BUSIDSIZE];
-+ unsigned long value;
-+ char buffer[10];
-+ char *endp;
-+
-+ u2s_getbusid(devicenode, busid);
-+ u2s_read_attribute(busid, "host_access_count", buffer, sizeof(buffer));
-+
-+ value = strtoul(buffer, &endp, 0);
-+
-+ if (endp == buffer)
-+ return -EINVAL;
-+
-+ return value;
-+}
---- a/libzds/Makefile
-+++ b/libzds/Makefile
-@@ -8,7 +8,7 @@ CFLAGS += -D_FILE_OFFSET_BITS=64
-
- all: libzds.a
-
--libzds.a: libzds.o $(rootdir)/libutil/util_list.o $(rootdir)/libvtoc/vtoc.o
-+libzds.a: libzds.o $(rootdir)/libutil/util_list.o $(rootdir)/libvtoc/vtoc.o $(rootdir)/libu2s/u2s.o
-
- libzds.o: ../include/libzds.h
-
---- a/libzds/libzds.c
-+++ b/libzds/libzds.c
-@@ -29,6 +29,7 @@
- #include "libzds.h"
-
- #include "util.h"
-+#include "u2s.h"
-
- #include
- #include
-@@ -72,6 +73,8 @@ struct errorlog {
- */
- #define ERRORMSG 240
-
-+#define BUSIDSIZE 8
-+
- /**
- * @brief An internal structure that represents an entry in the error log.
- */
-@@ -3760,15 +3763,46 @@ void lzds_DS1RECFM_to_recfm(char DS1RECF
- */
- }
-
-+int lzds_analyse_open_count(struct zdsroot *root, int warn)
-+{
-+ struct dasd *dasd;
-+ int value;
-+ int rc = 0;
-
-+ util_list_iterate(root->dasdlist, dasd) {
-+ value = u2s_get_host_access_count(dasd->device);
-
-+ if (value < 0) {
-+ fprintf(stderr,
-+ "Hosts access information not available for disk %s.\n",
-+ dasd->device);
-+ rc = value;
-+ continue;
-+ }
-
-+ if (value == 1)
-+ continue;
-
-+ if (warn)
-+ fprintf(stderr,
-+ "\nWARNING:\n"
-+ "Disk %s is online on operating system instances in %d different LPARs.\n"
-+ "Ensure that the disk is not being used by a system outside your LPAR.\n"
-+ "Note: Your installation might include z/VM systems that are configured to\n"
-+ "automatically vary on disks, regardless of whether they are subsequently used.\n",
-+ dasd->device, value);
-+ else {
-+ fprintf(stderr,
-+ "\nERROR:\n"
-+ "Disk %s is online on operating system instances in %d different LPARs.\n"
-+ "Ensure that the disk is not being used by a system outside your LPAR.\n"
-+ "Note: Your installation might include z/VM systems that are configured to\n"
-+ "automatically vary on disks, regardless of whether they are subsequently used.\n",
-+ dasd->device, value);
-+ rc = -EACCES;
-+ }
-+ }
-
--
--
--
--
--
--
-+ return rc;
-+}
-
---- a/zconf/lsdasd
-+++ b/zconf/lsdasd
-@@ -30,6 +30,8 @@ function PrintUsage() {
- Print old version of lsdasd output.
- -l|--long
- Print extended information about DASDs.
-+ -H|--host-access-list
-+ Print information about hosts accessing DASDs.
- -v|--verbose
- For compatibility/future use. Currently ignored.
- --version
-@@ -115,6 +117,33 @@ function listDASDDeviceDirectories() {
- }
-
- #------------------------------------------------------------------------------
-+# find dasd directory in debugfs
-+#------------------------------------------------------------------------------
-+function findDASDDebugfsDirectorie() {
-+ local mntentries
-+
-+ while read -a mntentries
-+ do
-+ if [[ "${mntentries[2]}" == "debugfs" ]]
-+ then
-+ DASD_DBF_DIR="${mntentries[1]}"
-+ break;
-+ fi
-+ done < /etc/mtab
-+ if [[ "$DASD_DBF_DIR" == "" ]]
-+ then
-+ echo "$CMD: No debugfs mount point found" >&2
-+ exit 1
-+ fi
-+ DASD_DBF_DIR="$DASD_DBF_DIR/dasd"
-+ if [[ ! -d "$DASD_DBF_DIR" ]]
-+ then
-+ echo "$CMD: Default DASD debugfs directory $DASD_DBF_DIR does not exist" >&2
-+ exit 1
-+ fi
-+}
-+
-+#------------------------------------------------------------------------------
- # gather device data and call appropriate output function
- #------------------------------------------------------------------------------
- function gatherDeviceData() {
-@@ -197,6 +226,8 @@ function gatherDeviceData() {
- extended
- elif [[ "$PRINTUID" == "true" ]]; then
- uid
-+ elif [[ "$OUTPUT" == "host" ]]; then
-+ host
- else
- newoutput
- fi
-@@ -527,6 +558,104 @@ function extended()
- "${HPF_PATHS[@]}" ;
- }
-
-+function host()
-+{
-+findDASDDebugfsDirectorie
-+
-+if [[ ! -f "$DASD_DBF_DIR/$BUSID/host_access_list" ]]
-+then
-+ printf "\n%s: hosts access information not available\n" "$BUSID"
-+ return
-+fi
-+
-+local temp=`mktemp /tmp/lsdasd.XXXXXX`
-+if test -w $temp ; then :; else
-+ printf "\nCreating temporary file failed\n"
-+ return
-+fi
-+
-+cat $DASD_DBF_DIR/$BUSID/host_access_list > $temp 2> /dev/null
-+ret=$?
-+if [[ $ret -ne 0 ]]
-+then
-+ printf "%s: hosts access information not available\n" "$BUSID"
-+ rm -f $temp
-+ return $ret
-+fi
-+
-+unset index
-+unset array
-+declare -a array
-+
-+index=(pgid status_flags sysplex_name supported_cylinder timestamp)
-+
-+for element in ${index[@]}
-+do
-+ count=0
-+
-+ declare -a $element
-+ OLDIFS=$IFS
-+ IFS=$'\n'
-+ for value in `grep $element $temp`
-+ do
-+ (( ++count ))
-+ value=$(echo -e $value | cut -d ' ' -f2)
-+ eval $element[$count]=$value
-+ done
-+ IFS=$OLDIFS
-+done
-+
-+printf "Host information for %s\n" "$BUSID";
-+printf "Path-Group-ID LPAR CPU FL Status Sysplex Max_Cyls Time\n";
-+printf "================================================================================\n";
-+
-+# mask bits for online and reserved state
-+online_reserved_mask=0xE0
-+
-+# print name value lists
-+for i in `seq 1 $count`;
-+do
-+ # get flags field
-+ value=${status_flags[$i]}
-+ # mark as hex value
-+ value=0x$value
-+ # mask online and reserved bits
-+ value=$(($value & $online_reserved_mask))
-+
-+ case $value in
-+ 0 ) # 0x00
-+ STATE="OFF"
-+ ;;
-+ 32 ) # 0x20
-+ STATE="OFF-RSV"
-+ ;;
-+ 64 ) # 0x40
-+ STATE="ON"
-+ ;;
-+ 96 ) # 0x60
-+ STATE="ON-RSV"
-+ ;;
-+ * )
-+ STATE="-"
-+ ;;
-+ esac
-+
-+ printf "%22s %02s %07s %02s %-6s %-8s %11u %10lu\n" \
-+ "${pgid[$i]}" \
-+ "${pgid[$i]:4:2}" \
-+ "${pgid[$i]:6:4}" \
-+ "${status_flags[$i]}" \
-+ "$STATE" \
-+ "${sysplex_name[$i]}" \
-+ "${supported_cylinder[$i]}" \
-+ "${timestamp[$i]}" \
-+ ;
-+done
-+printf "\n";
-+
-+rm -f $temp
-+}
-+
- function uid()
- {
- #-------------------------------------------#
-@@ -586,6 +715,9 @@ while [ $# -gt 0 ]; do
- --long|-l)
- OUTPUT="extended"
- ;;
-+ --host-access-list|-H)
-+ OUTPUT="host"
-+ ;;
- --version)
- PrintVersion
- exit 0
-@@ -626,8 +758,13 @@ fi
-
- # gather information on devices in list
- PROCESSING=" $PROCESSING | gatherDeviceData "
-+
- # sort resulting list
--PROCESSING=" $PROCESSING | sort -t: -k1n -k2 | cut -d: -f3- "
-+if [[ "$OUTPUT" == "host" ]]; then
-+ PROCESSING=" $PROCESSING"
-+else
-+ PROCESSING=" $PROCESSING | sort -t: -k1n -k2 | cut -d: -f3- "
-+fi
-
- if [[ "$PRINTUID" == "true" ]] && [[ "$OUTPUT" != "old" ]]; then
- printf "Bus-ID Name UID\n"
---- a/zconf/lsdasd.8
-+++ b/zconf/lsdasd.8
-@@ -40,11 +40,14 @@ Include only base devices.
- Old output of lsdasd for compatibility.
- .TP
- .BR -l | --long
--Extended output of lsdasd including UID, attributes and path information.
-+Extended output of lsdasd including UID and attributes.
- .TP
- .BR -u | --uid
- Output includes and is sorted by UID.
- .TP
-+.BR -H | --host-acces
-+Show information about all hosts using this device.
-+.TP
- .BR -v | --verbose
- Only for compatibility (and maybe future) use. This option currently does
- nothing.
---- a/zdsfs/zdsfs.1
-+++ b/zdsfs/zdsfs.1
-@@ -150,6 +150,10 @@ If \fI\fR is set to 0, no seek histor
- case `seek' is still supported, but a `seek' operation might result in a
- read from the beginning of the data set.
-
-+.TP
-+\fB\-o\fR check_host_count
-+Stop processing if the device is used by another operating system instance.
-+
- .SS "Applicable FUSE options (version 2.8):"
- This is a selected subset of all FUSE options. Use the zdsfs
- \fB\--help\fR option to print a full list.
---- a/zdsfs/zdsfs.c
-+++ b/zdsfs/zdsfs.c
-@@ -39,6 +39,7 @@ struct zdsfs_info {
- int devcount;
- int allow_inclomplete_multi_volume;
- int keepRDW;
-+ int host_count;
- unsigned int tracks_per_frame;
- unsigned long long seek_buffer_size;
- struct zdsroot *zdsroot;
-@@ -765,6 +766,7 @@ static const struct fuse_opt zdsfs_opts[
- FUSE_OPT_KEY("seekbuffer=", KEY_SEEKBUFFER),
- ZDSFS_OPT("rdw", keepRDW, 1),
- ZDSFS_OPT("ignore_incomplete", allow_inclomplete_multi_volume, 1),
-+ ZDSFS_OPT("check_host_count", host_count, 1),
- FUSE_OPT_END
- };
-
-@@ -790,7 +792,10 @@ static void usage(const char *progname)
- " data set are missing\n"
- " -o tracks=N Size of the track buffer in tracks (default 128)\n"
- " -o seekbuffer=S Upper limit in bytes for the seek history buffer\n"
--" size (default 1048576)\n", progname);
-+" size (default 1048576)\n"
-+" -o check_host_count Stop processing if the device is used by another\n"
-+" operating system instance\n"
-+ , progname);
- }
-
- static void zdsfs_process_device(const char *device)
-@@ -1014,6 +1019,17 @@ int main(int argc, char *argv[])
- argv[0]);
- exit(1);
- }
-+
-+ if (zdsfsinfo.host_count) {
-+ /* check, print error and exit if multiple online */
-+ rc = lzds_analyse_open_count(zdsfsinfo.zdsroot, 0);
-+ if (rc == -EACCES)
-+ goto cleanup;
-+ } else {
-+ /* check, print warning if multiple online */
-+ lzds_analyse_open_count(zdsfsinfo.zdsroot, 1);
-+ }
-+
- rc = zdsfs_verify_datasets();
- if (rc)
- goto cleanup;
diff --git a/s390-tools-sles12sp2-libu2s-Fix-busid-parsing.patch b/s390-tools-sles12sp2-libu2s-Fix-busid-parsing.patch
deleted file mode 100644
index 5283fe9..0000000
--- a/s390-tools-sles12sp2-libu2s-Fix-busid-parsing.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-Subject: [PATCH] [BZ 140500] libu2s: Fix busid parsing
-From: Jan Höppner
-
-Description: libu2s: Fix busid parsing
-Symptom: dasdview displays a wrong busid and shows the error message
- "Error: dasdview: Could not retrieve raw_track_access mode
- information.", which is wrong as well.
-Problem: dasdview retrieves the busid information from libu2s. Whenever
- an FBA DASD is listed prior to the target DASD in
- /proc/dasd/devices, the parsing will fail due to an additional
- whitespace character. For example, an entry for ECKD devices
- starts with "0.0.5e30(ECKD)...", while an entry for FBA starts
- with "0.0.8000(FBA )...".
-Solution: Change the busid parsing in libu2s by explicitly looking for the
- closing bracket.
-Reproduction: Add an FBA device and then an ECKD device to the system and use
- dasdview to display information about the ECKD device.
- # dasdview -i /dev/dasdX
-Upstream-ID: -
-Problem-ID: 140500
-
-Signed-off-by: Jan Höppner
----
- libu2s/u2s.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/libu2s/u2s.c
-+++ b/libu2s/u2s.c
-@@ -237,7 +237,7 @@ static int find_busid_in_proc(int maja,
- filp = fopen("/proc/dasd/devices", "r");
- if (!filp)
- return rc;
-- while (fscanf(filp, "%[^(] %*s at ( %d : %d %*[^\n]\n",
-+ while (fscanf(filp, "%[^(] %*[^)] ) at ( %d : %d %*[^\n]\n",
- bus, &majb, &minb) != EOF) {
- if ((maja == majb) && (mina == minb)) {
- strncpy(busid, bus, BUSIDSIZE + 1);
diff --git a/s390-tools-sles12sp2-lscss-allow-to-specify-devices-from-ssid-3.patch b/s390-tools-sles12sp2-lscss-allow-to-specify-devices-from-ssid-3.patch
deleted file mode 100644
index 9677209..0000000
--- a/s390-tools-sles12sp2-lscss-allow-to-specify-devices-from-ssid-3.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-Subject: lscss: allow to specify devices from ssid > 2
-From: Sebastian Ott
-
-Description: lscss: allow to specify devices from ssid > 2
-Symptom: Specifying devices with ssid > 2 results in:
- "Syntax error: 0.3.0000"
-Problem: SSIDs > 2 are disallowed
-Solution: allow SSIDs > 2
-Reproduction: lscss 0.3.0000
-Upstream-ID: -
-Problem-ID: 150872
-
-Signed-off-by: Sebastian Ott
----
- zconf/lscss | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/zconf/lscss
-+++ b/zconf/lscss
-@@ -61,7 +61,7 @@ SUBCHANNEL_TYPE_IO=0
- SUBCHANNEL_TYPE_CHSC=1
- SUBCHANNEL_TYPE_EADM=3
-
--IDFORMAT=[[:xdigit:]]*.[0-3].[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]
-+IDFORMAT=[[:xdigit:]]*.[[:xdigit:]].[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]
-
- unset SCH_IO SCH_CHSC SCH_EADM SHOW_AVAIL UPPERCASE SHORTID DEVTYPES DEVRANGE
- unset RANGE SHOW_VPM
-@@ -81,7 +81,7 @@ function check_id() #return 0 if $1 has
- fi
- ;;
- 3)
-- if [ ${#__ID[2]} != 4 -o ${#__ID[1]} != 1 -o "${__ID[1]//[012]/}" \
-+ if [ ${#__ID[2]} != 4 -o ${#__ID[1]} != 1 \
- -o \( ${#__ID[0]} != 2 -a ${#__ID[0]} != 1 \) ] ;then
- return 1
- fi
diff --git a/s390-tools-sles12sp2-zipl-fix-failed-start-subchannel.patch b/s390-tools-sles12sp2-zipl-fix-failed-start-subchannel.patch
deleted file mode 100644
index 68f199c..0000000
--- a/s390-tools-sles12sp2-zipl-fix-failed-start-subchannel.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-Subject: [PATCH] [BZ 143050] zipl/boot: fix failed start subchannel in FBA loader
-From: Stefan Haberland
-
-Description: zipl/boot: fix failed start subchannel in FBA loader
-Symptom: IPL of a FBA device fails with:
- Start subchannel failed
- disabled wait PSW 00020000 80000000 00000000 00004502
-Problem: The FBA loader has only a limited amount of memory to build CCW
- requests. Therefore larger I/O requests need to be split.
- This splitting was off by one leading to the fact that one CCW
- request uses memory of another data structure which in turn leads
- to corrupted data.
-Solution: Fix by correcting the split rule.
-Reproduction: IPL a FBA device.
- The error might occur randomly depending on the size of the
- kernel image and offsets within it.
-Upstream-ID: -
-Problem-ID: 143050
-
-Signed-off-by: Stefan Haberland
----
- zipl/boot/fba2.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/zipl/boot/fba2.c
-+++ b/zipl/boot/fba2.c
-@@ -59,7 +59,7 @@ restart:
- memset(irb, 0, sizeof(struct irb));
- memset(&orb, 0, sizeof(struct orb));
-
-- if (blockptr->blockct > MAX_BLOCKCT) {
-+ if (blockptr->blockct >= MAX_BLOCKCT) {
- record_number = MAX_BLOCKCT - 1;
- blockptr->blockct -= MAX_BLOCKCT;
- } else {
diff --git a/s390-tools-sles12sp3-chmem-try-to-online-zone-movable.patch b/s390-tools-sles12sp3-chmem-try-to-online-zone-movable.patch
deleted file mode 100644
index 1c58336..0000000
--- a/s390-tools-sles12sp3-chmem-try-to-online-zone-movable.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-Subject: [PATCH] [BZ 156627] chmem: try to online memory to zone movable
-From: Gerald Schaefer
-
-Description: chmem: try to online memory to zone movable
-Symptom: Standby/reserved memory that is onlined with chmem will be set
- online to zone normal, instead of zone movable, and so it is much
- less likely to be able to be offlined again.
-Problem: With recent kernels, the default zone for hotplug memory was
- changed from zone movable to zone normal.
-Solution: Let chmem first try to online memory to the zone movable, before
- setting it online to the default zone.
-Reproduction: Set standby/reserved memory online with chmem, and check
- /proc/zoneinfo for zone allocation.
-Upstream-ID: -
-Problem-ID: 156627
-
-Signed-off-by: Gerald Schaefer
----
- zconf/chmem | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
---- a/zconf/chmem
-+++ b/zconf/chmem
-@@ -86,7 +86,10 @@ sub chmem_online($)
- {
- my $block = shift;
-
-- qx(echo online > $memdir/memory$block/state 2>/dev/null);
-+ qx(echo online_movable > $memdir/memory$block/state 2>/dev/null);
-+ if ($? >> 8 != 0) {
-+ qx(echo online > $memdir/memory$block/state 2>/dev/null);
-+ }
- return $? >> 8;
- }
-
diff --git a/s390-tools-sles12sp3-dasdfmt-01-Fix-behaviour-of-t-combined-with-y.patch b/s390-tools-sles12sp3-dasdfmt-01-Fix-behaviour-of-t-combined-with-y.patch
deleted file mode 100644
index f05316c..0000000
--- a/s390-tools-sles12sp3-dasdfmt-01-Fix-behaviour-of-t-combined-with-y.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
-From: Jan Höppner
-
-Summary: dasdfmt: Add new formatting modes
-Description: Introduce new formatting modes 'quick' and 'expand' to either
- format an earlier formatted DASD that could potentially be
- re-initialized very easily or format unformatted tracks at the
- end of a device that was previously extended.
-
- Also add the command line argument --check to provide a function
- that checks a DASD volume for correct formatting.
-Upstream-ID: 9e49066f5c779e6591b06d2276add744ea8ca4d0
-Problem-ID: LS1501
-
-Upstream-Description:
-
- dasdfmt: Fix behaviour of -t combined with -y
-
- When -t (testmode) is being combined with -y (noprompt), the
- informations about what dasdfmt *would* do, is not being displayed.
-
- Simply fix this by checking whether testmode is set.
-
- Signed-off-by: Jan Höppner
-
-
-Signed-off-by: Jan Höppner
----
- dasdfmt/dasdfmt.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/dasdfmt/dasdfmt.c
-+++ b/dasdfmt/dasdfmt.c
-@@ -894,7 +894,7 @@ static void do_format_dasd(dasdfmt_info_
- vtoc_volume_label_set_label(vlabel, "LNX1");
- }
-
-- if ((info->verbosity > 0) || (!info->withoutprompt))
-+ if ((info->verbosity > 0) || !info->withoutprompt || info->testmode)
- dasdfmt_print_info(info, vlabel, cylinders, heads, p);
-
- count = u2s_get_host_access_count(info->devname);
diff --git a/s390-tools-sles12sp3-dasdfmt-02-Fix-trailing-whitespace.patch b/s390-tools-sles12sp3-dasdfmt-02-Fix-trailing-whitespace.patch
deleted file mode 100644
index 73f49ff..0000000
--- a/s390-tools-sles12sp3-dasdfmt-02-Fix-trailing-whitespace.patch
+++ /dev/null
@@ -1,250 +0,0 @@
-Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
-From: Jan Höppner
-
-Summary: dasdfmt: Add new formatting modes
-Description: Introduce new formatting modes 'quick' and 'expand' to either
- format an earlier formatted DASD that could potentially be
- re-initialized very easily or format unformatted tracks at the
- end of a device that was previously extended.
-
- Also add the command line argument --check to provide a function
- that checks a DASD volume for correct formatting.
-Upstream-ID: -
-Problem-ID: LS1501
-
-Upstream-Description:
-
- dasdfmt: Fix trailing whitespace
-
- Signed-off-by: Jan Höppner
- Signed-off-by: Stefan Haberland
-
-
-Signed-off-by: Jan Höppner
----
- dasdfmt/dasdfmt.c | 58 +++++++++++++++++++++++++++---------------------------
- 1 file changed, 29 insertions(+), 29 deletions(-)
-
---- a/dasdfmt/dasdfmt.c
-+++ b/dasdfmt/dasdfmt.c
-@@ -133,7 +133,7 @@ static void program_interrupt_signal (in
-
- rc = close(filedes);
- if (rc)
-- ERRMSG("%s: (signal handler) Unable to close device (%s)\n",
-+ ERRMSG("%s: (signal handler) Unable to close device (%s)\n",
- prog_name, strerror(errno));
-
- signal (sig, SIG_DFL);
-@@ -329,7 +329,7 @@ retry:
-
-
- /*
-- * check the volume serial for special
-+ * check the volume serial for special
- * characters and move blanks to the end
- */
- static int check_volser(char *s, int devno)
-@@ -345,7 +345,7 @@ static int check_volser(char *s, int dev
- s[i] = ' ';
- s[i] = toupper(s[i]);
- }
-- s[6] = 0x00;
-+ s[6] = 0x00;
-
- for (i=0; i<6; i++) {
- if (s[i] == ' ')
-@@ -416,16 +416,16 @@ static format_data_t ask_user_for_blksiz
- break;
-
- rc = sscanf(buffer,"%d%c", ¶ms.blksize, &c);
-- if ((rc == 2) && (c == '\n'))
-+ if ((rc == 2) && (c == '\n'))
- rc = 1;
-- if (rc == -1)
-+ if (rc == -1)
- rc = 1; /* this happens, if enter is pressed */
-- if (rc != 1)
-+ if (rc != 1)
- printf(" -- wrong input, try again.\n");
-
- if (check_param(str, ERR_LENGTH, ¶ms) < 0) {
-- printf(" -- %s\n",str);
-- rc = 0;
-+ printf(" -- %s\n",str);
-+ rc = 0;
- }
- } while (rc != 1);
-
-@@ -479,7 +479,7 @@ static int dasdfmt_get_volser(char * dev
- volume_label_t vlabel;
-
- if ((f = open(devname, O_RDONLY)) == -1)
-- ERRMSG_EXIT(EXIT_FAILURE,"%s: Unable to open device %s: %s\n",
-+ ERRMSG_EXIT(EXIT_FAILURE,"%s: Unable to open device %s: %s\n",
- prog_name, devname, strerror(errno));
-
- if (ioctl(f, BIODASDINFO, &dasd_info) != 0)
-@@ -491,7 +491,7 @@ static int dasdfmt_get_volser(char * dev
- "failed (%s).\n", prog_name, strerror(errno));
-
- if (close(f) != 0)
-- ERRMSG("%s: error during close: %s\ncontinuing...\n",
-+ ERRMSG("%s: error during close: %s\ncontinuing...\n",
- prog_name, strerror(errno));
-
- if ((strncmp(dasd_info.type, "ECKD", 4) == 0) &&
-@@ -505,7 +505,7 @@ static int dasdfmt_get_volser(char * dev
- return -1;
- }
- }
--
-+
- /*
- * do all the labeling (volume label and initial VTOC)
- */
-@@ -577,7 +577,7 @@ static void dasdfmt_write_labels(dasdfmt
- rc = lseek(filedes, label_position, SEEK_SET);
- if (rc != label_position)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: lseek command to %i failed "
-- "(%s).\n", prog_name, label_position,
-+ "(%s).\n", prog_name, label_position,
- strerror(errno));
-
- rc = write(filedes, ipl2_record, ipl2_record_len);
-@@ -633,9 +633,9 @@ static void dasdfmt_write_labels(dasdfmt
- rc = lseek(filedes, label_position, SEEK_SET);
- if (rc != label_position)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: lseek command to %i failed "
-- "(%s).\n", prog_name, label_position,
-+ "(%s).\n", prog_name, label_position,
- strerror(errno));
--
-+
- /* write VTOC FMT4 DSCB */
- rc = write(filedes, &f4, sizeof(format4_label_t));
- if (rc != sizeof(format4_label_t))
-@@ -695,21 +695,21 @@ static void dasdfmt_format(dasdfmt_info_
- "using the default.\n");
- info->hashstep = 10;
- }
--
-+
- if(!info->yast_mode) printf("Printing hashmark every %d cylinders.\n",
- info->hashstep);
- }
-
- format_step.blksize = format_params->blksize;
- format_step.intensity = format_params->intensity;
--
-+
- k = 0;
- cyl = 1;
- if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode)
- printf("\n");
-
- while (1) {
-- p1 = -1;
-+ p1 = -1;
- p2 = 0;
- if (k + heads * reqsize >= format_params->stop_unit)
- reqsize = 1;
-@@ -734,7 +734,7 @@ static void dasdfmt_format(dasdfmt_info_
- tmp = cyl*50/cylinders;
- for (j=1; j<=tmp; j++)
- printf("#");
-- for (j=tmp+1; j<=50; j++)
-+ for (j=tmp+1; j<=50; j++)
- printf("-");
- printf("|%3d%%", p1);
- }
-@@ -758,15 +758,15 @@ static void dasdfmt_format(dasdfmt_info_
- k += reqsize * heads;
- cyl += reqsize;
- }
-- else
-+ else
- k += format_params->stop_unit % heads;
-
-- if (k > format_params->stop_unit)
-+ if (k > format_params->stop_unit)
- break;
- }
-
- if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode)
-- printf("\n\n");
-+ printf("\n\n");
- }
-
-
-@@ -790,7 +790,7 @@ static void dasdfmt_prepare_and_format (
-
- if (ioctl(filedes, BIODASDDISABLE, p) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL "
-- "BIODASDDISABLE failed. (%s)\n", prog_name,
-+ "BIODASDDISABLE failed. (%s)\n", prog_name,
- strerror(errno));
- disk_disabled = 1;
-
-@@ -798,7 +798,7 @@ static void dasdfmt_prepare_and_format (
-
- if (ioctl(filedes, BIODASDFMT, &temp) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (invalidate first track) IOCTL "
-- "BIODASDFMT failed. (%s)\n", prog_name,
-+ "BIODASDFMT failed. (%s)\n", prog_name,
- strerror(errno));
-
- /* except track 0 from standard formatting procss */
-@@ -814,14 +814,14 @@ static void dasdfmt_prepare_and_format (
-
- if (ioctl(filedes, BIODASDFMT, &temp) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (re-validate first track) IOCTL"
-- " BIODASDFMT failed (%s)\n", prog_name,
-+ " BIODASDFMT failed (%s)\n", prog_name,
- strerror(errno));
-
- if (info->verbosity > 0) printf("Re-accessing the device...\n");
-
- if (ioctl(filedes, BIODASDENABLE, p) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL "
-- "BIODASDENABLE failed. (%s)\n", prog_name,
-+ "BIODASDENABLE failed. (%s)\n", prog_name,
- strerror(errno));
- disk_disabled = 0;
- }
-@@ -830,7 +830,7 @@ static void dasdfmt_prepare_and_format (
- /*
- *
- */
--static void do_format_dasd(dasdfmt_info_t *info, format_data_t *p,
-+static void do_format_dasd(dasdfmt_info_t *info, format_data_t *p,
- volume_label_t *vlabel)
- {
- char inp_buffer[5];
-@@ -943,7 +943,7 @@ static void do_format_dasd(dasdfmt_info_
- if (!info->yast_mode)
- printf("Finished formatting the device.\n");
-
-- if (!info->writenolabel)
-+ if (!info->writenolabel)
- dasdfmt_write_labels(info, vlabel, cylinders, heads);
-
- if (!info->yast_mode)
-@@ -959,7 +959,7 @@ static void do_format_dasd(dasdfmt_info_
- }
-
-
--int main(int argc,char *argv[])
-+int main(int argc,char *argv[])
- {
- dasdfmt_info_t info;
- volume_label_t vlabel;
-@@ -1001,7 +1001,7 @@ int main(int argc,char *argv[])
- rc=getopt_long(argc, argv, dasdfmt_getopt_string,
- dasdfmt_getopt_long_options, &index);
-
-- switch (rc)
-+ switch (rc)
- {
- case 'F':
- info.force=1;
diff --git a/s390-tools-sles12sp3-dasdfmt-03-Apply-coding-convention.patch b/s390-tools-sles12sp3-dasdfmt-03-Apply-coding-convention.patch
deleted file mode 100644
index bda753a..0000000
--- a/s390-tools-sles12sp3-dasdfmt-03-Apply-coding-convention.patch
+++ /dev/null
@@ -1,892 +0,0 @@
-Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
-From: Jan Höppner
-
-Summary: dasdfmt: Add new formatting modes
-Description: Introduce new formatting modes 'quick' and 'expand' to either
- format an earlier formatted DASD that could potentially be
- re-initialized very easily or format unformatted tracks at the
- end of a device that was previously extended.
-
- Also add the command line argument --check to provide a function
- that checks a DASD volume for correct formatting.
-Upstream-ID: -
-Problem-ID: LS1501
-
-Upstream-Description:
-
- dasdfmt: Apply coding convention
-
- Improve the overall readability of the code by applying the Kernel
- coding convention.
-
- Signed-off-by: Jan Höppner
- Signed-off-by: Stefan Haberland
-
-
-Signed-off-by: Jan Höppner
----
- dasdfmt/dasdfmt.c | 362 +++++++++++++++++++++++++-----------------------------
- 1 file changed, 171 insertions(+), 191 deletions(-)
-
---- a/dasdfmt/dasdfmt.c
-+++ b/dasdfmt/dasdfmt.c
-@@ -37,11 +37,10 @@ int reqsize;
- /*
- * Print version information.
- */
--static void
--print_version (void)
-+static void print_version(void)
- {
-- printf ("%s version %s\n", tool_name, RELEASE_STRING);
-- printf ("%s\n", copyright_notice);
-+ printf("%s version %s\n", tool_name, RELEASE_STRING);
-+ printf("%s\n", copyright_notice);
- }
-
- /*
-@@ -54,7 +53,7 @@ static void exit_usage(int exitcode)
- " [-b | --blocksize=]\n"
- " [-d | --disk_layout=]\n"
- " [-r | --requestsize=]\n"
-- " \n\n",prog_name);
-+ " \n\n", prog_name);
-
- printf(" -t or --test means testmode\n"
- " -V or --version means print version\n"
-@@ -71,13 +70,13 @@ static void exit_usage(int exitcode)
- " -C or --check_host_count means force dasdfmt to check\n"
- " the host access open count to ensure the device\n"
- " is not online on another operating system instance\n"
-- " --norecordzero prevent storage server from modifying"
-- " record 0\n\n"
-+ " --norecordzero prevent storage server from modifying"
-+ " record 0\n\n"
- " is the volume identifier, which is converted\n"
-- " to EBCDIC and written to disk. \n"
-+ " to EBCDIC and written to disk.\n"
- " (6 characters, e.g. LNX001\n"
- " has to be power of 2 and at least 512\n"
-- " is either \n"
-+ " is either\n"
- " 'cdl' for compatible disk layout (default) or\n"
- " 'ldl' for linux disk layout\n"
- " device node of the device to format\n");
-@@ -106,38 +105,39 @@ static int reread_partition_table(void)
- * signal handler:
- * enables the disk again in case of SIGTERM, SIGINT and SIGQUIT
- */
--static void program_interrupt_signal (int sig)
-+static void program_interrupt_signal(int sig)
- {
- int rc;
-
- if (program_interrupt_in_progress)
-- raise (sig);
-+ raise(sig);
- program_interrupt_in_progress = 1;
-
- if (disk_disabled) {
-- printf("Re-accessing the device... \n");
-+ printf("Re-accessing the device...\n");
- rc = ioctl(filedes, BIODASDENABLE, &format_params);
- if (rc)
-- ERRMSG_EXIT(EXIT_FAILURE,
-- "%s: (signal handler) IOCTL BIODASDENABLE "
-- "failed (%s)\n",prog_name,strerror(errno));
-+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (signal handler) IOCTL "
-+ "BIODASDENABLE failed (%s)\n", prog_name,
-+ strerror(errno));
- }
-
-- printf("Rereading the partition table... \n");
-+ printf("Rereading the partition table...\n");
- rc = reread_partition_table();
- if (rc) {
- ERRMSG("%s: (signal handler) Re-reading partition table "
- "failed. (%s)\n", prog_name, strerror(errno));
-- } else
-+ } else {
- printf("Exiting...\n");
-+ }
-
- rc = close(filedes);
- if (rc)
- ERRMSG("%s: (signal handler) Unable to close device (%s)\n",
- prog_name, strerror(errno));
-
-- signal (sig, SIG_DFL);
-- raise (sig);
-+ signal(sig, SIG_DFL);
-+ raise(sig);
- }
-
-
-@@ -171,13 +171,13 @@ static void get_device_name(dasdfmt_info
- char* device;
- int i;
-
-- if ((strchr(name, ' ') != NULL)||(strchr(name, '#') != NULL)||
-- (strchr(name, '[') != NULL)||(strchr(name, ']') != NULL)||
-- (strchr(name, '!') != NULL)||(strchr(name, '>') != NULL)||
-- (strchr(name, '(') != NULL)||(strchr(name, '<') != NULL)||
-- (strchr(name, ')') != NULL)||(strchr(name, ':') != NULL)||
-- (strchr(name, '&') != NULL)||(strchr(name, ';') != NULL))
-- ERRMSG_EXIT(EXIT_MISUSE,"%s: Your filename contains "
-+ if ((strchr(name, ' ') != NULL) || (strchr(name, '#') != NULL) ||
-+ (strchr(name, '[') != NULL) || (strchr(name, ']') != NULL) ||
-+ (strchr(name, '!') != NULL) || (strchr(name, '>') != NULL) ||
-+ (strchr(name, '(') != NULL) || (strchr(name, '<') != NULL) ||
-+ (strchr(name, ')') != NULL) || (strchr(name, ':') != NULL) ||
-+ (strchr(name, '&') != NULL) || (strchr(name, ';') != NULL))
-+ ERRMSG_EXIT(EXIT_MISUSE, "%s: Your filename contains "
- "blanks or special characters!\n",
- prog_name);
-
-@@ -215,14 +215,14 @@ static void get_device_name(dasdfmt_info
- info->devname[PATH_MAX - 1] = '\0';
-
- if (stat(info->devname, &dev_stat) != 0)
-- ERRMSG_EXIT(EXIT_MISUSE,
-- "%s: Could not get information for device node %s: %s\n",
-- prog_name, info->devname, strerror(errno));
-+ ERRMSG_EXIT(EXIT_MISUSE, "%s: Could not get information for "
-+ "device node %s: %s\n", prog_name, info->devname,
-+ strerror(errno));
-
- if (minor(dev_stat.st_rdev) & PARTN_MASK) {
-- ERRMSG_EXIT(EXIT_MISUSE,
-- "%s: Unable to format partition %s. Please specify a device.\n",
-- prog_name, info->devname);
-+ ERRMSG_EXIT(EXIT_MISUSE, "%s: Unable to format partition %s. "
-+ "Please specify a device.\n", prog_name,
-+ info->devname);
- }
-
- if (util_proc_dev_get_entry(dev_stat.st_rdev, 1, &dev_entry) == 0) {
-@@ -253,7 +253,7 @@ static void init_info(dasdfmt_info_t *in
- info->force = 0;
- info->writenolabel = 0;
- info->labelspec = 0;
-- info->cdl_format = 0;
-+ info->cdl_format = 0;
- info->blksize_specified = 0;
- info->reqsize_specified = 0;
- info->node_specified = 0;
-@@ -263,7 +263,6 @@ static void init_info(dasdfmt_info_t *in
- info->yast_mode = 0;
- }
-
--
- /*
- * check for disk type and set some variables (e.g. usage count)
- */
-@@ -280,9 +279,9 @@ static void check_disk(dasdfmt_info_t *i
- "status information failed (%s)\n",
- prog_name, strerror(errno_save));
- }
-- if (ro) {
-+ if (ro)
- ERRMSG_EXIT(EXIT_FAILURE, "Disk is read only!\n");
-- }
-+
- retry:
- if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) {
- errno_save = errno;
-@@ -314,7 +313,7 @@ retry:
-
- info->usage_count = dasd_info.open_count;
- info->devno = dasd_info.devno;
-- if (strncmp(dasd_info.type, "ECKD",4) != 0) {
-+ if (strncmp(dasd_info.type, "ECKD", 4) != 0) {
- ERRMSG_EXIT(EXIT_FAILURE,
- "%s: Unsupported disk type\n%s is not an "
- "ECKD disk!\n", prog_name, info->devname);
-@@ -327,29 +326,28 @@ retry:
- }
- }
-
--
- /*
- * check the volume serial for special
- * characters and move blanks to the end
- */
- static int check_volser(char *s, int devno)
- {
-- int i,j;
-+ int i, j;
-
-- for (i=0; i<6; i++) {
-+ for (i = 0; i < 6; i++) {
- if ((s[i] < 0x20) || (s[i] > 0x7a) ||
-- ((s[i] >= 0x21)&&(s[i] <= 0x22)) || /* !" */
-- ((s[i] >= 0x26)&&(s[i] <= 0x2f)) || /* &'()*+,-./ */
-- ((s[i] >= 0x3a)&&(s[i] <= 0x3f)) || /* :;<=>? */
-- ((s[i] >= 0x5b)&&(s[i] <= 0x60))) /* \]^_` */
-+ ((s[i] >= 0x21) && (s[i] <= 0x22)) || /* !" */
-+ ((s[i] >= 0x26) && (s[i] <= 0x2f)) || /* &'()*+,-./ */
-+ ((s[i] >= 0x3a) && (s[i] <= 0x3f)) || /* :;<=>? */
-+ ((s[i] >= 0x5b) && (s[i] <= 0x60))) /* \]^_` */
- s[i] = ' ';
- s[i] = toupper(s[i]);
- }
- s[6] = 0x00;
-
-- for (i=0; i<6; i++) {
-+ for (i = 0; i < 6; i++) {
- if (s[i] == ' ')
-- for (j=i; j<6; j++)
-+ for (j = i; j < 6; j++)
- if (s[j] != ' ') {
- s[i] = s[j];
- s[j] = ' ';
-@@ -360,7 +358,7 @@ static int check_volser(char *s, int dev
- if (s[0] == ' ') {
- printf("Usage error, switching to default.\n");
- sprintf(s, "0X%04x", devno);
-- for (i=0; i<6; i++)
-+ for (i = 0; i < 6; i++)
- s[i] = toupper(s[i]);
- return -1;
- }
-@@ -368,7 +366,6 @@ static int check_volser(char *s, int dev
- return 0;
- }
-
--
- /*
- * do some blocksize checks
- */
-@@ -377,7 +374,7 @@ static int check_param(char *s, size_t b
- int tmp = data->blksize;
-
- if ((tmp < 512) || (tmp > 4096)) {
-- strncpy(s,"Blocksize must be one of the following positive "
-+ strncpy(s, "Blocksize must be one of the following positive "
- "integers:\n512, 1024, 2048, 4096.", buffsize);
- if (buffsize > 0)
- s[buffsize - 1] = '\0';
-@@ -386,7 +383,7 @@ static int check_param(char *s, size_t b
-
- while (tmp > 0) {
- if ((tmp % 2) && (tmp != 1)) {
-- strncpy(s,"Blocksize must be a power of 2.", buffsize);
-+ strncpy(s, "Blocksize must be a power of 2.", buffsize);
- if (buffsize > 0)
- s[buffsize - 1] = '\0';
- return -1;
-@@ -397,7 +394,6 @@ static int check_param(char *s, size_t b
- return 0;
- }
-
--
- /*
- * ask the user to specify a blocksize
- */
-@@ -415,7 +411,7 @@ static format_data_t ask_user_for_blksiz
- if (fgets(buffer, sizeof(buffer), stdin) == NULL)
- break;
-
-- rc = sscanf(buffer,"%d%c", ¶ms.blksize, &c);
-+ rc = sscanf(buffer, "%d%c", ¶ms.blksize, &c);
- if ((rc == 2) && (c == '\n'))
- rc = 1;
- if (rc == -1)
-@@ -424,7 +420,7 @@ static format_data_t ask_user_for_blksiz
- printf(" -- wrong input, try again.\n");
-
- if (check_param(str, ERR_LENGTH, ¶ms) < 0) {
-- printf(" -- %s\n",str);
-+ printf(" -- %s\n", str);
- rc = 0;
- }
- } while (rc != 1);
-@@ -432,7 +428,6 @@ static format_data_t ask_user_for_blksiz
- return params;
- }
-
--
- /*
- * print all information needed to format the device
- */
-@@ -449,7 +444,7 @@ static void dasdfmt_print_info(dasdfmt_i
- printf("%s in the following way:\n", info->devname);
- printf(" Device number of device : 0x%x\n", info->devno);
- printf(" Labelling device : %s\n",
-- (info->writenolabel)?"no":"yes");
-+ (info->writenolabel) ? "no" : "yes");
-
- if (!info->writenolabel) {
- vtoc_volume_label_get_label(vlabel, vollbl);
-@@ -460,31 +455,31 @@ static void dasdfmt_print_info(dasdfmt_i
- printf(" Extent start (trk no) : %u\n", p->start_unit);
- printf(" Extent end (trk no) : %u\n", p->stop_unit);
- printf(" Compatible Disk Layout : %s\n",
-- (p->intensity & DASD_FMT_INT_COMPAT)?"yes":"no");
-+ (p->intensity & DASD_FMT_INT_COMPAT) ? "yes" : "no");
- printf(" Blocksize : %d\n", p->blksize);
-
- if (info->testmode)
- printf("Test mode active, omitting ioctl.\n");
- }
-
--
- /*
- * get volser
- */
--static int dasdfmt_get_volser(char * devname, char * volser)
-+static int dasdfmt_get_volser(char *devname, char *volser)
- {
-- dasd_information_t dasd_info;
-+ dasd_information_t dasd_info;
- int blksize;
- int f;
- volume_label_t vlabel;
-
-- if ((f = open(devname, O_RDONLY)) == -1)
-- ERRMSG_EXIT(EXIT_FAILURE,"%s: Unable to open device %s: %s\n",
-+ f = open(devname, O_RDONLY);
-+ if (f == -1)
-+ ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n",
- prog_name, devname, strerror(errno));
-
- if (ioctl(f, BIODASDINFO, &dasd_info) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BIODASD"
-- "INFO failed (%s).\n",prog_name, strerror(errno));
-+ "INFO failed (%s).\n", prog_name, strerror(errno));
-
- if (ioctl(f, BLKSSZGET, &blksize) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BLKSSZGET "
-@@ -500,8 +495,7 @@ static int dasdfmt_get_volser(char * dev
- vtoc_read_volume_label(devname, dasd_info.label_block * blksize, &vlabel);
- vtoc_volume_label_get_volser(&vlabel, volser);
- return 0;
-- }
-- else {
-+ } else {
- return -1;
- }
- }
-@@ -512,22 +506,24 @@ static int dasdfmt_get_volser(char * dev
- static void dasdfmt_write_labels(dasdfmt_info_t *info, volume_label_t *vlabel,
- unsigned int cylinders, unsigned int heads)
- {
-- int label_position;
-- dasd_information_t dasd_info;
-- struct hd_geometry geo;
-- format4_label_t f4;
-- format5_label_t f5;
-- format7_label_t f7;
-+ int label_position;
-+ dasd_information_t dasd_info;
-+ struct hd_geometry geo;
-+ format4_label_t f4;
-+ format5_label_t f5;
-+ format7_label_t f7;
- int rc, blksize;
- void *ipl1_record, *ipl2_record;
- int ipl1_record_len, ipl2_record_len;
-
-
-- if (info->verbosity > 0) printf("Retrieving dasd information... ");
-+ if (info->verbosity > 0)
-+ printf("Retrieving dasd information... ");
-
- if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0)
-- ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL BIODASD"
-- "INFO failed (%s).\n",prog_name, strerror(errno));
-+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL "
-+ "BIODASDINFO failed (%s).\n",
-+ prog_name, strerror(errno));
-
- if (ioctl(filedes, BLKSSZGET, &blksize) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL BLKSSZGET "
-@@ -539,13 +535,16 @@ static void dasdfmt_write_labels(dasdfmt
- * vary depending on the format.
- */
- if (ioctl(filedes, HDIO_GETGEO, &geo) != 0)
-- ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL HDIO_GET"
-- "GEO failed (%s).\n", prog_name, strerror(errno));
-+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL "
-+ "HDIO_GETGEO failed (%s).\n",
-+ prog_name, strerror(errno));
-
-- if (info->verbosity > 0) printf("ok\n");
-+ if (info->verbosity > 0)
-+ printf("ok\n");
-
- /* write empty bootstrap (initial IPL records) */
-- if (info->verbosity > 0) printf("Writing empty bootstrap...\n");
-+ if (info->verbosity > 0)
-+ printf("Writing empty bootstrap...\n");
-
- /*
- * Note: ldl labels do not contain the key field
-@@ -596,7 +595,8 @@ static void dasdfmt_write_labels(dasdfmt
-
- label_position = dasd_info.label_block * blksize;
-
-- if (info->verbosity > 0) printf("Writing label...\n");
-+ if (info->verbosity > 0)
-+ printf("Writing label...\n");
-
- rc = lseek(filedes, label_position, SEEK_SET);
- if (rc != label_position)
-@@ -608,10 +608,10 @@ static void dasdfmt_write_labels(dasdfmt
- * Note: cdl volume labels do not contain the 'formatted_blocks' part
- * and ldl labels do not contain the key field
- */
-- if (info->cdl_format)
-+ if (info->cdl_format) {
- rc = write(filedes, vlabel, (sizeof(*vlabel) -
- sizeof(vlabel->formatted_blocks)));
-- else {
-+ } else {
- vlabel->ldl_version = 0xf2; /* EBCDIC '2' */
- vlabel->formatted_blocks = cylinders * heads * geo.sectors;
- rc = write(filedes, &vlabel->vollbl, (sizeof(*vlabel)
-@@ -625,7 +625,8 @@ static void dasdfmt_write_labels(dasdfmt
- ERRMSG_EXIT(EXIT_FAILURE, "%s: Error writing volume label "
- "(%d).\n", prog_name, rc);
-
-- if (info->verbosity > 0) printf("Writing VTOC... ");
-+ if (info->verbosity > 0)
-+ printf("Writing VTOC... ");
-
- label_position = (VTOC_START_CC * heads + VTOC_START_HH) *
- geo.sectors * blksize;
-@@ -673,10 +674,10 @@ static void dasdfmt_write_labels(dasdfmt
-
- fsync(filedes);
-
-- if (info->verbosity > 0) printf("ok\n");
-+ if (info->verbosity > 0)
-+ printf("ok\n");
- }
-
--
- /*
- * formats the disk cylinderwise
- */
-@@ -720,21 +721,20 @@ static void dasdfmt_format(dasdfmt_info_
- format_step.start_unit += 1;
-
- if (ioctl(filedes, BIODASDFMT, &format_step) != 0)
-- ERRMSG_EXIT(EXIT_FAILURE,"%s: (format cylinder) IOCTL "
-+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (format cylinder) IOCTL "
- "BIODASDFMT failed. (%s)\n",
- prog_name, strerror(errno));
-
- if (info->print_progressbar) {
- printf("cyl %7d of %7d |", cyl, cylinders);
- p2 = p1;
-- p1 = cyl*100/cylinders;
-- if (p1 != p2)
-- {
-+ p1 = cyl * 100 / cylinders;
-+ if (p1 != p2) {
- /* percent value has changed */
-- tmp = cyl*50/cylinders;
-- for (j=1; j<=tmp; j++)
-+ tmp = cyl * 50 / cylinders;
-+ for (j = 1; j <= tmp; j++)
- printf("#");
-- for (j=tmp+1; j<=50; j++)
-+ for (j = tmp + 1; j <= 50; j++)
- printf("-");
- printf("|%3d%%", p1);
- }
-@@ -748,6 +748,7 @@ static void dasdfmt_format(dasdfmt_info_
- fflush(stdout);
- hashcount++;
- }
-+
- if (info->print_percentage) {
- printf("cyl %7d of %7d |%3d%%\n", cyl, cylinders,
- cyl*100/cylinders);
-@@ -757,9 +758,9 @@ static void dasdfmt_format(dasdfmt_info_
- if (k % heads == 0) {
- k += reqsize * heads;
- cyl += reqsize;
-- }
-- else
-+ } else {
- k += format_params->stop_unit % heads;
-+ }
-
- if (k > format_params->stop_unit)
- break;
-@@ -769,14 +770,9 @@ static void dasdfmt_format(dasdfmt_info_
- printf("\n\n");
- }
-
--
--/*
-- *
-- */
--static void dasdfmt_prepare_and_format (dasdfmt_info_t *info,
-- unsigned int cylinders,
-- unsigned int heads,
-- format_data_t *p)
-+static void dasdfmt_prepare_and_format(dasdfmt_info_t *info,
-+ unsigned int cylinders,
-+ unsigned int heads, format_data_t *p)
- {
- format_data_t temp = {
- start_unit: 0,
-@@ -786,7 +782,8 @@ static void dasdfmt_prepare_and_format (
- | DASD_FMT_INT_INVAL)
- };
-
-- if (info->verbosity > 0) printf("Detaching the device...\n");
-+ if (info->verbosity > 0)
-+ printf("Detaching the device...\n");
-
- if (ioctl(filedes, BIODASDDISABLE, p) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL "
-@@ -794,7 +791,8 @@ static void dasdfmt_prepare_and_format (
- strerror(errno));
- disk_disabled = 1;
-
-- if (info->verbosity > 0) printf("Invalidate first track...\n");
-+ if (info->verbosity > 0)
-+ printf("Invalidate first track...\n");
-
- if (ioctl(filedes, BIODASDFMT, &temp) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (invalidate first track) IOCTL "
-@@ -806,18 +804,21 @@ static void dasdfmt_prepare_and_format (
-
- dasdfmt_format(info, cylinders, heads, p);
-
-- if (info->verbosity > 0) printf("formatting tracks complete...\n");
-+ if (info->verbosity > 0)
-+ printf("formatting tracks complete...\n");
-
- temp.intensity = p->intensity;
-
-- if (info->verbosity > 0) printf("Revalidate first track...\n");
-+ if (info->verbosity > 0)
-+ printf("Revalidate first track...\n");
-
- if (ioctl(filedes, BIODASDFMT, &temp) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (re-validate first track) IOCTL"
- " BIODASDFMT failed (%s)\n", prog_name,
- strerror(errno));
-
-- if (info->verbosity > 0) printf("Re-accessing the device...\n");
-+ if (info->verbosity > 0)
-+ printf("Re-accessing the device...\n");
-
- if (ioctl(filedes, BIODASDENABLE, p) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL "
-@@ -826,20 +827,17 @@ static void dasdfmt_prepare_and_format (
- disk_disabled = 0;
- }
-
--
--/*
-- *
-- */
- static void do_format_dasd(dasdfmt_info_t *info, format_data_t *p,
- volume_label_t *vlabel)
- {
-- char inp_buffer[5];
-+ char inp_buffer[5];
- dasd_information_t dasd_info;
- struct dasd_eckd_characteristics *characteristics;
- unsigned int cylinders, heads;
- int count;
-
-- if (info->verbosity > 0) printf("Retrieving disk geometry...\n");
-+ if (info->verbosity > 0)
-+ printf("Retrieving disk geometry...\n");
-
- if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (retrieving disk information) "
-@@ -877,22 +875,23 @@ static void do_format_dasd(dasdfmt_info_
- }
- }
- } else {
-- if (!info->labelspec && !info->keep_volser) {
-+ if (!info->labelspec && !info->keep_volser) {
- char buf[7];
-
-- sprintf(buf, "0X%04x", info->devno);
-+ sprintf(buf, "0X%04x", info->devno);
- check_volser(buf, info->devno);
- vtoc_volume_label_set_volser(vlabel, buf);
- }
-
-- if (p->intensity & DASD_FMT_INT_COMPAT) {
-+ if (p->intensity & DASD_FMT_INT_COMPAT) {
- info->cdl_format = 1;
- vtoc_volume_label_set_label(vlabel, "VOL1");
- vtoc_volume_label_set_key(vlabel, "VOL1");
- vtoc_set_cchhb(&vlabel->vtoc, 0x0000, 0x0001, 0x01);
-- } else
-+ } else {
- vtoc_volume_label_set_label(vlabel, "LNX1");
-- }
-+ }
-+ }
-
- if ((info->verbosity > 0) || !info->withoutprompt || info->testmode)
- dasdfmt_print_info(info, vlabel, cylinders, heads, p);
-@@ -926,15 +925,15 @@ static void do_format_dasd(dasdfmt_info_
- "untouched: ");
- if (fgets(inp_buffer, sizeof(inp_buffer), stdin) == NULL)
- return;
-- if (strcasecmp(inp_buffer,"yes") &&
-- strcasecmp(inp_buffer,"yes\n")) {
-+ if (strcasecmp(inp_buffer, "yes") &&
-+ strcasecmp(inp_buffer, "yes\n")) {
- printf("Omitting ioctl call (disk will "
- "NOT be formatted).\n");
- return;
- }
- }
-
-- if (!((info->withoutprompt)&&(info->verbosity<1)))
-+ if (!((info->withoutprompt) && (info->verbosity < 1)))
- printf("Formatting the device. This may take a "
- "while (get yourself a coffee).\n");
-
-@@ -954,12 +953,11 @@ static void do_format_dasd(dasdfmt_info_
- } else {
- if (!info->yast_mode)
- printf("ok\n");
-- }
-+ }
- }
- }
-
--
--int main(int argc,char *argv[])
-+int main(int argc, char *argv[])
- {
- dasdfmt_info_t info;
- volume_label_t vlabel;
-@@ -980,9 +978,9 @@ int main(int argc,char *argv[])
- int running=0;
-
- /* Establish a handler for interrupt signals. */
-- signal (SIGTERM, program_interrupt_signal);
-- signal (SIGINT, program_interrupt_signal);
-- signal (SIGQUIT, program_interrupt_signal);
-+ signal(SIGTERM, program_interrupt_signal);
-+ signal(SIGINT, program_interrupt_signal);
-+ signal(SIGQUIT, program_interrupt_signal);
-
- /******************* initialization ********************/
- prog_name = argv[0];
-@@ -996,102 +994,81 @@ int main(int argc,char *argv[])
-
- /*************** parse parameters **********************/
-
-- while (1)
-- {
-- rc=getopt_long(argc, argv, dasdfmt_getopt_string,
-- dasdfmt_getopt_long_options, &index);
-+ while (1) {
-+ rc = getopt_long(argc, argv, dasdfmt_getopt_string,
-+ dasdfmt_getopt_long_options, &index);
-
-- switch (rc)
-- {
-+ switch (rc) {
- case 'F':
-- info.force=1;
-+ info.force = 1;
- break;
--
-- case 'd' :
-- if (strncmp(optarg,"cdl",3)==0)
-- {
-+ case 'd':
-+ if (strncmp(optarg, "cdl", 3) == 0) {
- format_params.intensity |= DASD_FMT_INT_COMPAT;
-- if (info.writenolabel)
-- {
-- printf("WARNING: using the cdl " \
-- "format without writing a " \
-- "label doesn't make much " \
-+ if (info.writenolabel) {
-+ printf("WARNING: using the cdl "
-+ "format without writing a "
-+ "label doesn't make much "
- "sense!\n");
- exit(1);
- }
-- }
-- else if (strncmp(optarg,"ldl",3)==0)
-+ } else if (strncmp(optarg, "ldl", 3) == 0) {
- format_params.intensity &= ~DASD_FMT_INT_COMPAT;
-- else
-- {
-+ } else {
- printf("%s is not a valid option!\n", optarg);
- exit(1);
- }
-- break;
--
-+ break;
- case 'y':
-- info.withoutprompt=1;
-+ info.withoutprompt = 1;
- break;
--
- case 'z':
-- format_params.intensity |= DASD_FMT_INT_FMT_NOR0;
-+ format_params.intensity |= DASD_FMT_INT_FMT_NOR0;
- break;
--
- case 't':
-- info.testmode=1;
-+ info.testmode = 1;
- break;
--
- case 'p':
- if (!(info.print_hashmarks || info.print_percentage))
- info.print_progressbar = 1;
- break;
--
- case 'm':
-- if (!(info.print_progressbar || info.print_percentage))
-- {
-- hashstep_str=optarg;
-- info.print_hashmarks=1;
-+ if (!(info.print_progressbar || info.print_percentage)) {
-+ hashstep_str = optarg;
-+ info.print_hashmarks = 1;
- }
- break;
--
- case 'Q':
- if (!(info.print_hashmarks || info.print_progressbar))
- info.print_percentage = 1;
- break;
--
- case 'v':
-- info.verbosity=1;
-+ info.verbosity = 1;
- break;
--
- case 'h':
- exit_usage(0);
--
- case 'V':
- print_version();
- exit(0);
--
- case 'l':
-- strncpy(buf, optarg, 6);
-+ strncpy(buf, optarg, 6);
- if (check_volser(buf, 0) < 0)
- break;
-- vtoc_volume_label_set_volser(&vlabel,buf);
-- info.labelspec=1;
-+ vtoc_volume_label_set_volser(&vlabel, buf);
-+ info.labelspec = 1;
- break;
--
- case 'L':
-- if (format_params.intensity & DASD_FMT_INT_COMPAT)
-- {
-- printf("WARNING: using the cdl format " \
-- "without writing a label doesn't " \
-+ if (format_params.intensity & DASD_FMT_INT_COMPAT) {
-+ printf("WARNING: using the cdl format "
-+ "without writing a label doesn't "
- "make much sense!\n");
- exit(1);
- }
-- info.writenolabel=1;
-+ info.writenolabel = 1;
- break;
--
-- case 'b' :
-- blksize_param_str=optarg;
-- info.blksize_specified=1;
-+ case 'b':
-+ blksize_param_str = optarg;
-+ info.blksize_specified = 1;
- break;
- case 'r':
- reqsize_param_str = optarg;
-@@ -1102,7 +1079,7 @@ int main(int argc,char *argv[])
- ERRMSG_EXIT(EXIT_MISUSE,"%s: too many devices specified.\n",
- prog_name);
- dev_filename[dev_count++]=strdup(optarg);
-- info.node_specified=1;
-+ info.node_specified = 1;
- break;
- case 'Y' : /* YaST mode */
- info.yast_mode=1;
-@@ -1110,8 +1087,8 @@ int main(int argc,char *argv[])
- case 'P' : /* max parallel formatting processes */
- max_parallel=atoi(optarg);
- break;
-- case 'k' :
-- info.keep_volser=1;
-+ case 'k':
-+ info.keep_volser = 1;
- break;
- case 'C':
- info.force_host = 1;
-@@ -1121,11 +1098,12 @@ int main(int argc,char *argv[])
- info.device_id = optind;
- break;
- default:
-- ERRMSG_EXIT(EXIT_MISUSE,
-- "Try '%s --help' for more"
-- " information.\n",prog_name);
-+ ERRMSG_EXIT(EXIT_MISUSE, "Try '%s --help' for more"
-+ " information.\n", prog_name);
- }
-- if (rc==-1) break; // exit loop if finished
-+
-+ if (rc == -1)
-+ break; /* exit loop if finished */
- }
-
- CHECK_SPEC_MAX_ONCE(info.blksize_specified, "blocksize");
-@@ -1222,7 +1200,7 @@ int main(int argc,char *argv[])
- } else
- reqsize = DEFAULT_REQUESTSIZE;
- if (info.print_hashmarks)
-- PARSE_PARAM_INTO(info.hashstep, hashstep_str,10,"hashstep");
-+ PARSE_PARAM_INTO(info.hashstep, hashstep_str, 10, "hashstep");
-
- get_device_name(&info, dev_filename[i]);
-
-@@ -1230,22 +1208,24 @@ int main(int argc,char *argv[])
- format_params = ask_user_for_blksize(format_params);
-
- if (info.keep_volser) {
-- if(format_params.intensity == 0x00) {
-- printf("WARNING: VOLSER cannot be kept " \
-+ if (format_params.intensity == 0x00) {
-+ printf("WARNING: VOLSER cannot be kept "
- "when using the ldl format!\n");
- exit(1);
- }
-
-- if(dasdfmt_get_volser(info.devname, old_volser) == 0)
-+ if (dasdfmt_get_volser(info.devname, old_volser) == 0)
- vtoc_volume_label_set_volser(&vlabel, old_volser);
- else
-- ERRMSG_EXIT(EXIT_FAILURE,"%s: VOLSER not found on device %s\n",
-+ ERRMSG_EXIT(EXIT_FAILURE,
-+ "%s: VOLSER not found on device %s\n",
- prog_name, info.devname);
-
- }
-
-- if ((filedes = open(info.devname, O_RDWR)) == -1)
-- ERRMSG_EXIT(EXIT_FAILURE,"%s: Unable to open device %s: %s\n",
-+ filedes = open(info.devname, O_RDWR);
-+ if (filedes == -1)
-+ ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n",
- prog_name, info.devname, strerror(errno));
-
- check_disk(&info);
diff --git a/s390-tools-sles12sp3-dasdfmt-04-Use-enhanced-DASD-information.patch b/s390-tools-sles12sp3-dasdfmt-04-Use-enhanced-DASD-information.patch
deleted file mode 100644
index 1116f55..0000000
--- a/s390-tools-sles12sp3-dasdfmt-04-Use-enhanced-DASD-information.patch
+++ /dev/null
@@ -1,399 +0,0 @@
-Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
-From: Jan Höppner
-
-Summary: dasdfmt: Add new formatting modes
-Description: Introduce new formatting modes 'quick' and 'expand' to either
- format an earlier formatted DASD that could potentially be
- re-initialized very easily or format unformatted tracks at the
- end of a device that was previously extended.
-
- Also add the command line argument --check to provide a function
- that checks a DASD volume for correct formatting.
-Upstream-ID: -
-Problem-ID: LS1501
-
-Upstream-Description:
-
- dasdfmt: Use enhanced DASD information
-
- Currently dasdfmt uses BIODASDINFO as the IOCTL command to retrieve
- information about a DASD and stores them in dasd_information_t.
- However, BIODASDINFO2 offers a few more useful information (which are
- then stored in dasd_information2_t).
-
- - Replace dasd_information_t with dasd_information2_t.
- - Make the corresponding variable part of dasdfmt_info_t, since it is
- used in several functions anyway and we can save a few parameters and
- IOCTL calls.
- - Change the initialization of dasdfmt_info_t. A separate function isn't
- necessary for that.
- - Put the BIODASDINFO2 IOCTL call in a separate function which is then
- called only once.
-
- Signed-off-by: Jan Höppner
- Signed-off-by: Stefan Haberland
-
-
-Signed-off-by: Jan Höppner
----
- dasdfmt/dasdfmt.c | 132 ++++++++++++++++++------------------------------------
- dasdfmt/dasdfmt.h | 21 ++++++--
- 2 files changed, 61 insertions(+), 92 deletions(-)
-
---- a/dasdfmt/dasdfmt.c
-+++ b/dasdfmt/dasdfmt.c
-@@ -237,30 +237,18 @@ static void get_device_name(dasdfmt_info
- }
-
- /*
-- * initialize the dasdfmt info structure
-+ * Retrieve DASD information
- */
--static void init_info(dasdfmt_info_t *info)
-+static void get_device_info(dasdfmt_info_t *info)
- {
-- info->devno = 0x0;
-- info->usage_count = 0;
-- info->testmode = 0;
-- info->verbosity = 0;
-- info->withoutprompt = 0;
-- info->print_progressbar = 0;
-- info->print_hashmarks = 0;
-- info->print_percentage = 0;
-- info->hashstep = 0;
-- info->force = 0;
-- info->writenolabel = 0;
-- info->labelspec = 0;
-- info->cdl_format = 0;
-- info->blksize_specified = 0;
-- info->reqsize_specified = 0;
-- info->node_specified = 0;
-- info->device_id = 0;
-- info->keep_volser = 0;
-- info->force_host = 0;
-- info->yast_mode = 0;
-+ dasd_information2_t dasd_info;
-+
-+ if (ioctl(filedes, BIODASDINFO2, &dasd_info))
-+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl call to retrieve "
-+ "device information failed (%s).\n",
-+ prog_name, strerror(errno));
-+
-+ info->dasd_info = dasd_info;
- }
-
- /*
-@@ -268,7 +256,6 @@ static void init_info(dasdfmt_info_t *in
- */
- static void check_disk(dasdfmt_info_t *info)
- {
-- dasd_information_t dasd_info;
- int ro, errno_save, i = 0;
-
- if (ioctl(filedes, BLKROGET, &ro) != 0) {
-@@ -283,15 +270,6 @@ static void check_disk(dasdfmt_info_t *i
- ERRMSG_EXIT(EXIT_FAILURE, "Disk is read only!\n");
-
- retry:
-- if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) {
-- errno_save = errno;
-- close(filedes);
-- ERRMSG_EXIT(EXIT_FAILURE,
-- "%s: the ioctl call to retrieve device "
-- "information failed (%s)\n",
-- prog_name, strerror(errno_save));
-- }
--
- if (!info->force)
- /*
- * udev strikes again.
-@@ -302,7 +280,7 @@ retry:
- * And confusing the hell out ouf anyone else.
- * Bah.
- */
-- if (dasd_info.open_count > 1) {
-+ if (info->dasd_info.open_count > 1) {
- if (i < 5) {
- ++i;
- sleep(1);
-@@ -311,9 +289,7 @@ retry:
- ERRMSG_EXIT(EXIT_BUSY, "Disk in use!\n");
- }
-
-- info->usage_count = dasd_info.open_count;
-- info->devno = dasd_info.devno;
-- if (strncmp(dasd_info.type, "ECKD", 4) != 0) {
-+ if (strncmp(info->dasd_info.type, "ECKD", 4) != 0) {
- ERRMSG_EXIT(EXIT_FAILURE,
- "%s: Unsupported disk type\n%s is not an "
- "ECKD disk!\n", prog_name, info->devname);
-@@ -442,7 +418,7 @@ static void dasdfmt_print_info(dasdfmt_i
-
- printf("\nI am going to format the device ");
- printf("%s in the following way:\n", info->devname);
-- printf(" Device number of device : 0x%x\n", info->devno);
-+ printf(" Device number of device : 0x%x\n", info->dasd_info.devno);
- printf(" Labelling device : %s\n",
- (info->writenolabel) ? "no" : "yes");
-
-@@ -465,21 +441,16 @@ static void dasdfmt_print_info(dasdfmt_i
- /*
- * get volser
- */
--static int dasdfmt_get_volser(char *devname, char *volser)
-+static int dasdfmt_get_volser(dasdfmt_info_t *info, char *volser)
- {
-- dasd_information_t dasd_info;
- int blksize;
- int f;
- volume_label_t vlabel;
-
-- f = open(devname, O_RDONLY);
-+ f = open(info->devname, O_RDONLY);
- if (f == -1)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n",
-- prog_name, devname, strerror(errno));
--
-- if (ioctl(f, BIODASDINFO, &dasd_info) != 0)
-- ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BIODASD"
-- "INFO failed (%s).\n", prog_name, strerror(errno));
-+ prog_name, info->devname, strerror(errno));
-
- if (ioctl(f, BLKSSZGET, &blksize) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BLKSSZGET "
-@@ -489,10 +460,12 @@ static int dasdfmt_get_volser(char *devn
- ERRMSG("%s: error during close: %s\ncontinuing...\n",
- prog_name, strerror(errno));
-
-- if ((strncmp(dasd_info.type, "ECKD", 4) == 0) &&
-- (!dasd_info.FBA_layout)) {
-+ if ((strncmp(info->dasd_info.type, "ECKD", 4) == 0) &&
-+ (!info->dasd_info.FBA_layout)) {
- /* OS/390 and zOS compatible disk layout */
-- vtoc_read_volume_label(devname, dasd_info.label_block * blksize, &vlabel);
-+ vtoc_read_volume_label(info->devname,
-+ info->dasd_info.label_block * blksize,
-+ &vlabel);
- vtoc_volume_label_get_volser(&vlabel, volser);
- return 0;
- } else {
-@@ -507,7 +480,6 @@ static void dasdfmt_write_labels(dasdfmt
- unsigned int cylinders, unsigned int heads)
- {
- int label_position;
-- dasd_information_t dasd_info;
- struct hd_geometry geo;
- format4_label_t f4;
- format5_label_t f5;
-@@ -520,11 +492,6 @@ static void dasdfmt_write_labels(dasdfmt
- if (info->verbosity > 0)
- printf("Retrieving dasd information... ");
-
-- if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0)
-- ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL "
-- "BIODASDINFO failed (%s).\n",
-- prog_name, strerror(errno));
--
- if (ioctl(filedes, BLKSSZGET, &blksize) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL BLKSSZGET "
- "failed (%s).\n", prog_name, strerror(errno));
-@@ -586,14 +553,14 @@ static void dasdfmt_write_labels(dasdfmt
-
- /* write VTOC */
- vtoc_init_format4_label(&f4, geo.cylinders, cylinders, heads,
-- geo.sectors, blksize, dasd_info.dev_type);
-+ geo.sectors, blksize, info->dasd_info.dev_type);
-
- vtoc_init_format5_label(&f5);
- vtoc_init_format7_label(&f7);
- vtoc_set_freespace(&f4, &f5, &f7, '+', 0, FIRST_USABLE_TRK,
- (cylinders * heads - 1), cylinders, heads);
-
-- label_position = dasd_info.label_block * blksize;
-+ label_position = info->dasd_info.label_block * blksize;
-
- if (info->verbosity > 0)
- printf("Writing label...\n");
-@@ -831,7 +798,6 @@ static void do_format_dasd(dasdfmt_info_
- volume_label_t *vlabel)
- {
- char inp_buffer[5];
-- dasd_information_t dasd_info;
- struct dasd_eckd_characteristics *characteristics;
- unsigned int cylinders, heads;
- int count;
-@@ -839,13 +805,9 @@ static void do_format_dasd(dasdfmt_info_
- if (info->verbosity > 0)
- printf("Retrieving disk geometry...\n");
-
-- if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0)
-- ERRMSG_EXIT(EXIT_FAILURE, "%s: (retrieving disk information) "
-- "IOCTL BIODASDINFO failed (%s).\n",
-- prog_name, strerror(errno));
--
- characteristics =
-- (struct dasd_eckd_characteristics *) &dasd_info.characteristics;
-+ (struct dasd_eckd_characteristics *)
-+ &info->dasd_info.characteristics;
- if (characteristics->no_cyl == LV_COMPAT_CYL &&
- characteristics->long_no_cyl)
- cylinders = characteristics->long_no_cyl;
-@@ -878,8 +840,8 @@ static void do_format_dasd(dasdfmt_info_
- if (!info->labelspec && !info->keep_volser) {
- char buf[7];
-
-- sprintf(buf, "0X%04x", info->devno);
-- check_volser(buf, info->devno);
-+ sprintf(buf, "0X%04x", info->dasd_info.devno);
-+ check_volser(buf, info->dasd_info.devno);
- vtoc_volume_label_set_volser(vlabel, buf);
- }
-
-@@ -959,7 +921,10 @@ static void do_format_dasd(dasdfmt_info_
-
- int main(int argc, char *argv[])
- {
-- dasdfmt_info_t info;
-+ dasdfmt_info_t info = {
-+ .dasd_info = {0},
-+ {0}
-+ };
- volume_label_t vlabel;
- char old_volser[7];
-
-@@ -986,7 +951,6 @@ int main(int argc, char *argv[])
- prog_name = argv[0];
-
- /* set default values */
-- init_info(&info);
- vtoc_volume_label_init(&vlabel);
-
- format_params.blksize = DEFAULT_BLOCKSIZE;
-@@ -1137,30 +1101,24 @@ int main(int argc, char *argv[])
-
- if(info.yast_mode) {
- for(i=0;ino_cyl == LV_COMPAT_CYL &&
- characteristics->long_no_cyl)
- cylinders = characteristics->long_no_cyl;
-@@ -1204,6 +1162,13 @@ int main(int argc, char *argv[])
-
- get_device_name(&info, dev_filename[i]);
-
-+ filedes = open(info.devname, O_RDWR);
-+ if (filedes == -1)
-+ ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n",
-+ prog_name, info.devname, strerror(errno));
-+
-+ get_device_info(&info);
-+
- if (!info.blksize_specified)
- format_params = ask_user_for_blksize(format_params);
-
-@@ -1214,7 +1179,7 @@ int main(int argc, char *argv[])
- exit(1);
- }
-
-- if (dasdfmt_get_volser(info.devname, old_volser) == 0)
-+ if (dasdfmt_get_volser(&info, old_volser) == 0)
- vtoc_volume_label_set_volser(&vlabel, old_volser);
- else
- ERRMSG_EXIT(EXIT_FAILURE,
-@@ -1223,11 +1188,6 @@ int main(int argc, char *argv[])
-
- }
-
-- filedes = open(info.devname, O_RDWR);
-- if (filedes == -1)
-- ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n",
-- prog_name, info.devname, strerror(errno));
--
- check_disk(&info);
-
- if (check_param(str, ERR_LENGTH, &format_params) < 0)
---- a/dasdfmt/dasdfmt.h
-+++ b/dasdfmt/dasdfmt.h
-@@ -32,11 +32,11 @@
- #define DASD_IOCTL_LETTER 'D'
-
- /*
-- * struct dasd_information_t
-+ * struct dasd_information2_t
- * represents any data about the device, which is visible to userspace.
- * including format and features.
- */
--typedef struct dasd_information_t {
-+typedef struct dasd_information2_t {
- unsigned int devno; /* S/390 devno */
- unsigned int real_devno; /* for aliases */
- unsigned int schid; /* S/390 subchannel identifier */
-@@ -56,7 +56,17 @@ typedef struct dasd_information_t {
- unsigned int confdata_size;
- char characteristics[64]; /* from read_device_characteristics */
- char configuration_data[256]; /* from read_configuration_data */
--} dasd_information_t;
-+ unsigned int format; /* format info like formatted/cdl/ldl/... */
-+ unsigned int features; /* dasd features like 'ro',... */
-+ unsigned int reserved0; /* reserved for further use ,... */
-+ unsigned int reserved1; /* reserved for further use ,... */
-+ unsigned int reserved2; /* reserved for further use ,... */
-+ unsigned int reserved3; /* reserved for further use ,... */
-+ unsigned int reserved4; /* reserved for further use ,... */
-+ unsigned int reserved5; /* reserved for further use ,... */
-+ unsigned int reserved6; /* reserved for further use ,... */
-+ unsigned int reserved7; /* reserved for further use ,... */
-+} dasd_information2_t;
-
-
- struct dasd_eckd_characteristics {
-@@ -165,7 +175,7 @@ typedef struct format_data_t {
- #define BIODASDENABLE _IO(DASD_IOCTL_LETTER,1)
-
- /* Get information on a dasd device (enhanced) */
--#define BIODASDINFO _IOR(DASD_IOCTL_LETTER,1,dasd_information_t)
-+#define BIODASDINFO2 _IOR(DASD_IOCTL_LETTER, 3, dasd_information2_t)
-
- /* #define BIODASDFORMAT _IOW(IOCTL_LETTER,0,format_data_t) , deprecated */
- #define BIODASDFMT _IOW(DASD_IOCTL_LETTER,1,format_data_t)
-@@ -251,9 +261,8 @@ typedef struct bootstrap2 {
- } __attribute__ ((packed)) bootstrap2_t;
-
- typedef struct dasdfmt_info {
-- int devno;
-+ dasd_information2_t dasd_info;
- char devname[PATH_MAX];
-- int usage_count;
- int verbosity;
- int testmode;
- int withoutprompt;
diff --git a/s390-tools-sles12sp3-dasdfmt-05-Refactor-do_format_dasd.patch b/s390-tools-sles12sp3-dasdfmt-05-Refactor-do_format_dasd.patch
deleted file mode 100644
index 46f6372..0000000
--- a/s390-tools-sles12sp3-dasdfmt-05-Refactor-do_format_dasd.patch
+++ /dev/null
@@ -1,210 +0,0 @@
-Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
-From: Jan Höppner
-
-Summary: dasdfmt: Add new formatting modes
-Description: Introduce new formatting modes 'quick' and 'expand' to either
- format an earlier formatted DASD that could potentially be
- re-initialized very easily or format unformatted tracks at the
- end of a device that was previously extended.
-
- Also add the command line argument --check to provide a function
- that checks a DASD volume for correct formatting.
-Upstream-ID: -
-Problem-ID: LS1501
-
-Upstream-Description:
-
- dasdfmt: Refactor do_format_dasd
-
- In order to allow for new features to be integrated properly in the
- existing code, certain parts of do_format_dasd() must be moved to
- separate functions. This applies to setting VTOC information and
- geometrical information.
-
- Therefore, move the relevant bits to set_geo() and set_label().
-
- Signed-off-by: Jan Höppner
- Signed-off-by: Stefan Haberland
-
-
-Signed-off-by: Jan Höppner
----
- dasdfmt/dasdfmt.c | 132 +++++++++++++++++++++++++++++++-----------------------
- 1 file changed, 76 insertions(+), 56 deletions(-)
-
---- a/dasdfmt/dasdfmt.c
-+++ b/dasdfmt/dasdfmt.c
-@@ -371,6 +371,73 @@ static int check_param(char *s, size_t b
- }
-
- /*
-+ * Retrieve disk information and set cylinders and heads accordingly.
-+ */
-+static void set_geo(dasdfmt_info_t *info, unsigned int *cylinders,
-+ unsigned int *heads)
-+{
-+ struct dasd_eckd_characteristics *characteristics;
-+
-+ if (info->verbosity > 0)
-+ printf("Retrieving disk geometry...\n");
-+
-+ characteristics = (struct dasd_eckd_characteristics *)
-+ &info->dasd_info.characteristics;
-+ if (characteristics->no_cyl == LV_COMPAT_CYL &&
-+ characteristics->long_no_cyl)
-+ *cylinders = characteristics->long_no_cyl;
-+ else
-+ *cylinders = characteristics->no_cyl;
-+ *heads = characteristics->trk_per_cyl;
-+}
-+
-+/*
-+ * Set VTOC label information
-+ */
-+static void set_label(dasdfmt_info_t *info, volume_label_t *vlabel,
-+ format_data_t *p, unsigned int cylinders)
-+{
-+ char inp_buffer[5];
-+
-+ if (info->writenolabel) {
-+ if (cylinders > LV_COMPAT_CYL && !info->withoutprompt) {
-+ printf("\n--->> ATTENTION! <<---\n");
-+ printf("You specified to write no labels to a"
-+ " volume with more then %u cylinders.\n"
-+ "Cylinders above this limit will not be"
-+ " accessible as a linux partition!\n"
-+ "Type \"yes\" to continue, no will leave"
-+ " the disk untouched: ", LV_COMPAT_CYL);
-+ if (fgets(inp_buffer, sizeof(inp_buffer), stdin) == NULL)
-+ return;
-+ if (strcasecmp(inp_buffer, "yes") &&
-+ strcasecmp(inp_buffer, "yes\n")) {
-+ printf("Omitting ioctl call (disk will "
-+ "NOT be formatted).\n");
-+ return;
-+ }
-+ }
-+ } else {
-+ if (!info->labelspec && !info->keep_volser) {
-+ char buf[7];
-+
-+ sprintf(buf, "0X%04x", info->dasd_info.devno);
-+ check_volser(buf, info->dasd_info.devno);
-+ vtoc_volume_label_set_volser(vlabel, buf);
-+ }
-+
-+ if (p->intensity & DASD_FMT_INT_COMPAT) {
-+ info->cdl_format = 1;
-+ vtoc_volume_label_set_label(vlabel, "VOL1");
-+ vtoc_volume_label_set_key(vlabel, "VOL1");
-+ vtoc_set_cchhb(&vlabel->vtoc, 0x0000, 0x0001, 0x01);
-+ } else {
-+ vtoc_volume_label_set_label(vlabel, "LNX1");
-+ }
-+ }
-+}
-+
-+/*
- * ask the user to specify a blocksize
- */
- static format_data_t ask_user_for_blksize(format_data_t params)
-@@ -452,7 +519,7 @@ static int dasdfmt_get_volser(dasdfmt_in
- ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n",
- prog_name, info->devname, strerror(errno));
-
-- if (ioctl(f, BLKSSZGET, &blksize) != 0)
-+ if (ioctl(filedes, BLKSSZGET, &blksize) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BLKSSZGET "
- "failed (%s).\n", prog_name, strerror(errno));
-
-@@ -794,67 +861,16 @@ static void dasdfmt_prepare_and_format(d
- disk_disabled = 0;
- }
-
--static void do_format_dasd(dasdfmt_info_t *info, format_data_t *p,
-- volume_label_t *vlabel)
-+static void do_format_dasd(dasdfmt_info_t *info, volume_label_t *vlabel,
-+ format_data_t *p, unsigned int cylinders,
-+ unsigned int heads)
- {
- char inp_buffer[5];
-- struct dasd_eckd_characteristics *characteristics;
-- unsigned int cylinders, heads;
- int count;
-
-- if (info->verbosity > 0)
-- printf("Retrieving disk geometry...\n");
--
-- characteristics =
-- (struct dasd_eckd_characteristics *)
-- &info->dasd_info.characteristics;
-- if (characteristics->no_cyl == LV_COMPAT_CYL &&
-- characteristics->long_no_cyl)
-- cylinders = characteristics->long_no_cyl;
-- else
-- cylinders = characteristics->no_cyl;
-- heads = characteristics->trk_per_cyl;
--
- p->start_unit = 0;
- p->stop_unit = (cylinders * heads) - 1;
-
-- if (info->writenolabel) {
-- if (cylinders > LV_COMPAT_CYL && !info->withoutprompt) {
-- printf("\n--->> ATTENTION! <<---\n");
-- printf("You specified to write no labels to a"
-- " volume with more then %u cylinders.\n"
-- "Cylinders above this limit will not be"
-- " accessible as a linux partition!\n"
-- "Type \"yes\" to continue, no will leave"
-- " the disk untouched: ", LV_COMPAT_CYL);
-- if (fgets(inp_buffer, sizeof(inp_buffer), stdin) == NULL)
-- return;
-- if (strcasecmp(inp_buffer, "yes") &&
-- strcasecmp(inp_buffer, "yes\n")) {
-- printf("Omitting ioctl call (disk will "
-- "NOT be formatted).\n");
-- return;
-- }
-- }
-- } else {
-- if (!info->labelspec && !info->keep_volser) {
-- char buf[7];
--
-- sprintf(buf, "0X%04x", info->dasd_info.devno);
-- check_volser(buf, info->dasd_info.devno);
-- vtoc_volume_label_set_volser(vlabel, buf);
-- }
--
-- if (p->intensity & DASD_FMT_INT_COMPAT) {
-- info->cdl_format = 1;
-- vtoc_volume_label_set_label(vlabel, "VOL1");
-- vtoc_volume_label_set_key(vlabel, "VOL1");
-- vtoc_set_cchhb(&vlabel->vtoc, 0x0000, 0x0001, 0x01);
-- } else {
-- vtoc_volume_label_set_label(vlabel, "LNX1");
-- }
-- }
--
- if ((info->verbosity > 0) || !info->withoutprompt || info->testmode)
- dasdfmt_print_info(info, vlabel, cylinders, heads, p);
-
-@@ -938,6 +954,7 @@ int main(int argc, char *argv[])
- char *hashstep_str = NULL;
-
- int rc, index, i;
-+ unsigned int cylinders, heads;
-
- int max_parallel=1;
- int running=0;
-@@ -1193,7 +1210,10 @@ int main(int argc, char *argv[])
- if (check_param(str, ERR_LENGTH, &format_params) < 0)
- ERRMSG_EXIT(EXIT_MISUSE, "%s: %s\n", prog_name, str);
-
-- do_format_dasd(&info, &format_params, &vlabel);
-+ set_geo(&info, &cylinders, &heads);
-+ set_label(&info, &vlabel, &format_params, cylinders);
-+ do_format_dasd(&info, &vlabel, &format_params,
-+ cylinders, heads);
-
- if (close(filedes) != 0)
- ERRMSG("%s: error during close: %s\ncontinuing...\n",
diff --git a/s390-tools-sles12sp3-dasdfmt-06-Make-the-IOCTL-BLKSSZGET-reusable.patch b/s390-tools-sles12sp3-dasdfmt-06-Make-the-IOCTL-BLKSSZGET-reusable.patch
deleted file mode 100644
index b078fcf..0000000
--- a/s390-tools-sles12sp3-dasdfmt-06-Make-the-IOCTL-BLKSSZGET-reusable.patch
+++ /dev/null
@@ -1,93 +0,0 @@
-Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
-From: Jan Höppner
-
-Summary: dasdfmt: Add new formatting modes
-Description: Introduce new formatting modes 'quick' and 'expand' to either
- format an earlier formatted DASD that could potentially be
- re-initialized very easily or format unformatted tracks at the
- end of a device that was previously extended.
-
- Also add the command line argument --check to provide a function
- that checks a DASD volume for correct formatting.
-Upstream-ID: -
-Problem-ID: LS1501
-
-Upstream-Description:
-
- dasdfmt: Make the IOCTL BLKSSZGET reusable
-
- The IOCTL BLKSSZGET is used to get blocksize information of a device.
- Since it is used several times already and could be used for new
- features as well, move the call to a separate function and make it
- reusable.
-
- Signed-off-by: Jan Höppner
- Signed-off-by: Stefan Haberland
-
-
-Signed-off-by: Jan Höppner
----
- dasdfmt/dasdfmt.c | 24 ++++++++++++++++--------
- 1 file changed, 16 insertions(+), 8 deletions(-)
-
---- a/dasdfmt/dasdfmt.c
-+++ b/dasdfmt/dasdfmt.c
-@@ -252,6 +252,17 @@ static void get_device_info(dasdfmt_info
- }
-
- /*
-+ * Retrieve blocksize of device
-+ */
-+static void get_blocksize(unsigned int *blksize)
-+{
-+ if (ioctl(filedes, BLKSSZGET, blksize) != 0)
-+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl to get the blocksize "
-+ "of the device failed (%s).\n", prog_name,
-+ strerror(errno));
-+}
-+
-+/*
- * check for disk type and set some variables (e.g. usage count)
- */
- static void check_disk(dasdfmt_info_t *info)
-@@ -510,7 +521,7 @@ static void dasdfmt_print_info(dasdfmt_i
- */
- static int dasdfmt_get_volser(dasdfmt_info_t *info, char *volser)
- {
-- int blksize;
-+ unsigned int blksize;
- int f;
- volume_label_t vlabel;
-
-@@ -519,9 +530,7 @@ static int dasdfmt_get_volser(dasdfmt_in
- ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n",
- prog_name, info->devname, strerror(errno));
-
-- if (ioctl(filedes, BLKSSZGET, &blksize) != 0)
-- ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BLKSSZGET "
-- "failed (%s).\n", prog_name, strerror(errno));
-+ get_blocksize(&blksize);
-
- if (close(f) != 0)
- ERRMSG("%s: error during close: %s\ncontinuing...\n",
-@@ -551,7 +560,8 @@ static void dasdfmt_write_labels(dasdfmt
- format4_label_t f4;
- format5_label_t f5;
- format7_label_t f7;
-- int rc, blksize;
-+ unsigned int blksize;
-+ int rc;
- void *ipl1_record, *ipl2_record;
- int ipl1_record_len, ipl2_record_len;
-
-@@ -559,9 +569,7 @@ static void dasdfmt_write_labels(dasdfmt
- if (info->verbosity > 0)
- printf("Retrieving dasd information... ");
-
-- if (ioctl(filedes, BLKSSZGET, &blksize) != 0)
-- ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL BLKSSZGET "
-- "failed (%s).\n", prog_name, strerror(errno));
-+ get_blocksize(&blksize);
-
- /*
- * Don't rely on the cylinders returned by HDIO_GETGEO, they might be
diff --git a/s390-tools-sles12sp3-dasdfmt-07-Add-quick-format-support.patch b/s390-tools-sles12sp3-dasdfmt-07-Add-quick-format-support.patch
deleted file mode 100644
index 555f4d2..0000000
--- a/s390-tools-sles12sp3-dasdfmt-07-Add-quick-format-support.patch
+++ /dev/null
@@ -1,555 +0,0 @@
-Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
-From: Jan Höppner
-
-Summary: dasdfmt: Add new formatting modes
-Description: Introduce new formatting modes 'quick' and 'expand' to either
- format an earlier formatted DASD that could potentially be
- re-initialized very easily or format unformatted tracks at the
- end of a device that was previously extended.
-
- Also add the command line argument --check to provide a function
- that checks a DASD volume for correct formatting.
-Upstream-ID: -
-Problem-ID: LS1501
-
-Upstream-Description:
-
- dasdfmt: Add quick format support
-
- On occasion, a DASD device might have been formatted earlier and could
- potentially be re-initialized very easily. For device initalization it
- is necessary to write disk information (i.e. volume label (CDL or LDL)
- and VTOC) to the first two tracks. Currently you'd need to format the
- entire disk, which can take a long time and is totally unnecessary.
-
- Therefore, add a quick format mode which formats only the first two
- tracks and fills them with data accordingly.
- Before any formatting is done, several checks regarding the
- expected device format are performed.
-
- The mode can be specified with the new command line switch -M (--mode)
- . Where 'mode' can be either 'full' (default) or 'quick'.
-
- Document the switch -M (--mode) and its options full and quick in the
- man page.
-
- Signed-off-by: Jan Höppner
- Signed-off-by: Stefan Haberland
-
-
-Signed-off-by: Jan Höppner
----
- dasdfmt/dasdfmt.8 | 15 ++
- dasdfmt/dasdfmt.c | 290 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
- dasdfmt/dasdfmt.h | 51 +++++++++
- 3 files changed, 344 insertions(+), 12 deletions(-)
-
---- a/dasdfmt/dasdfmt.8
-+++ b/dasdfmt/dasdfmt.8
-@@ -67,7 +67,7 @@ Print version number and exit.
-
- .TP
- \fB-F\fR or \fB--force\fR
--Formats the device without checking, if the device is in use.
-+Formats the device without performing sanity checking.
-
- .TP
- \fB-C\fR or \fB--check_host_count\fR
-@@ -108,6 +108,19 @@ The value will be at least as big as the
- .br
-
- .TP
-+\fB-M\fR \fImode\fR or \fB--mode\fR=\fImode\fR
-+Specify the \fImode\fR to be used to format the device. Valid modes are:
-+.RS
-+.IP full
-+Format the entire disk with the specified blocksize. (default)
-+.IP quick
-+Format the first two tracks and write label and partition information. Only use
-+this option if you are sure that the target DASD already contains a regular
-+format with the specified blocksize. A blocksize can optionally be specified
-+using \fB-b\fR (\fB--blocksize\fR).
-+.RE
-+
-+.TP
- \fB-r\fR \fIcylindercount\fR or \fB--requestsize\fR=\fIcylindercount\fR
- Number of cylinders to be processed in one formatting step.
- The value must be an integer in the range 1 - 255.
---- a/dasdfmt/dasdfmt.c
-+++ b/dasdfmt/dasdfmt.c
-@@ -30,6 +30,7 @@ static const char copyright_notice[] = "
- static int filedes;
- static int disk_disabled;
- static format_data_t format_params;
-+static format_mode_t mode;
- char *prog_name;
- volatile sig_atomic_t program_interrupt_in_progress;
- int reqsize;
-@@ -53,6 +54,7 @@ static void exit_usage(int exitcode)
- " [-b | --blocksize=]\n"
- " [-d | --disk_layout=]\n"
- " [-r | --requestsize=]\n"
-+ " [-M | --mode=]\n"
- " \n\n", prog_name);
-
- printf(" -t or --test means testmode\n"
-@@ -65,7 +67,7 @@ static void exit_usage(int exitcode)
- " -r x or --requestsize=x means use x cylinders in one "
- "format step\n"
- " -v means verbose mode\n"
-- " -F means don't check if the device is in use\n"
-+ " -F means format without performing sanity checking\n"
- " -k means keep volume serial\n"
- " -C or --check_host_count means force dasdfmt to check\n"
- " the host access open count to ensure the device\n"
-@@ -79,7 +81,10 @@ static void exit_usage(int exitcode)
- " is either\n"
- " 'cdl' for compatible disk layout (default) or\n"
- " 'ldl' for linux disk layout\n"
-- " device node of the device to format\n");
-+ " device node of the device to format\n"
-+ " is either\n"
-+ " 'full' to fully format the device (default)\n"
-+ " 'quick' to format only the first two tracks\n");
- exit(exitcode);
- }
-
-@@ -102,6 +107,131 @@ static int reread_partition_table(void)
- }
-
- /*
-+ * Helper function for recs_per_track.
-+ */
-+static inline unsigned int ceil_quot(unsigned int d1, unsigned int d2)
-+{
-+ return (d1 + (d2 - 1)) / d2;
-+}
-+
-+/*
-+ * Calculate records per track depending on the device characteristics.
-+ */
-+static unsigned int recs_per_track(struct dasd_eckd_characteristics *rdc,
-+ unsigned int kl, unsigned int dl)
-+{
-+ int dn, kn;
-+
-+ switch (rdc->dev_type) {
-+ case 0x3380:
-+ if (kl)
-+ return 1499 / (15 + 7 + ceil_quot(kl + 12, 32) +
-+ ceil_quot(dl + 12, 32));
-+ else
-+ return 1499 / (15 + ceil_quot(dl + 12, 32));
-+ case 0x3390:
-+ dn = ceil_quot(dl + 6, 232) + 1;
-+ if (kl) {
-+ kn = ceil_quot(kl + 6, 232) + 1;
-+ return 1729 / (10 + 9 + ceil_quot(kl + 6 * kn, 34) +
-+ 9 + ceil_quot(dl + 6 * dn, 34));
-+ } else
-+ return 1729 / (10 + 9 + ceil_quot(dl + 6 * dn, 34));
-+ case 0x9345:
-+ dn = ceil_quot(dl + 6, 232) + 1;
-+ if (kl) {
-+ kn = ceil_quot(kl + 6, 232) + 1;
-+ return 1420 / (18 + 7 + ceil_quot(kl + 6 * kn, 34) +
-+ ceil_quot(dl + 6 * dn, 34));
-+ } else
-+ return 1420 / (18 + 7 + ceil_quot(dl + 6 * dn, 34));
-+ }
-+ return 0;
-+}
-+
-+/*
-+ * Evaluate errors recognized by format checks and print appropriate error
-+ * messages depending on the content of cdata.
-+ */
-+static void evaluate_format_error(dasdfmt_info_t *info, format_check_t *cdata,
-+ unsigned int heads)
-+{
-+ struct dasd_eckd_characteristics *rdc;
-+ /* Special blocksize values of the first 3 records of trk 0 of cyl 0 */
-+ const int blksizes_trk0[] = { 24, 144, 80 };
-+ /* Special blocksize value of trk 1 cyl 0 */
-+ const int blksize_trk1 = 96;
-+ unsigned int cyl;
-+ unsigned int head;
-+ unsigned int rpt;
-+ unsigned int kl = 0;
-+ int blksize = cdata->expect.blksize;
-+
-+ /*
-+ * Reading record zero will never happen. If the record in error is 0
-+ * nonetheless, the device is not formatted at all!
-+ */
-+ if (cdata->rec == 0) {
-+ ERRMSG("WARNING: The specified device is not "
-+ "formatted at all.\n");
-+ return;
-+ }
-+
-+ cyl = cdata->unit / heads;
-+ head = cyl >> 16;
-+ head <<= 4;
-+ head |= cdata->unit % heads;
-+
-+ /*
-+ * Set special expected values for the first 3 records of trk 0 of cyl 0
-+ * and trk 1 of cyl 0 when checking a CDL formatted device.
-+ */
-+ if ((cdata->expect.intensity & DASD_FMT_INT_COMPAT) &&
-+ cyl == 0 && head == 0 && cdata->rec < 4) {
-+ kl = 4;
-+ blksize = blksizes_trk0[cdata->rec - 1];
-+ }
-+ if ((cdata->expect.intensity & DASD_FMT_INT_COMPAT) &&
-+ cyl == 0 && head == 1) {
-+ kl = 44;
-+ blksize = blksize_trk1;
-+ }
-+
-+ rdc = (struct dasd_eckd_characteristics *)
-+ &info->dasd_info.characteristics;
-+
-+ rpt = recs_per_track(rdc, kl, cdata->expect.blksize);
-+
-+ ERRMSG("WARNING: The specified device is not formatted as expected.\n");
-+ switch (cdata->result) {
-+ case DASD_FMT_ERR_TOO_FEW_RECORDS:
-+ ERRMSG("Too few records (found %d, expected %d) "
-+ "at cyl: %d trk: %d rec: %d.\n",
-+ cdata->num_records, rpt, cyl, head, cdata->rec);
-+ break;
-+ case DASD_FMT_ERR_TOO_MANY_RECORDS:
-+ ERRMSG("Too many records (found %d, expected %d) "
-+ "at cyl: %d trk: %d rec: %d.\n",
-+ cdata->num_records, rpt, cyl, head, cdata->rec);
-+ break;
-+ case DASD_FMT_ERR_BLKSIZE:
-+ ERRMSG("Invalid blocksize (found %d, expected %d) "
-+ "at cyl: %d trk: %d rec: %d.\n",
-+ cdata->blksize, blksize, cyl, head, cdata->rec);
-+ break;
-+ case DASD_FMT_ERR_RECORD_ID:
-+ ERRMSG("Invalid record ID at cyl: %d trk: %d rec: %d.\n",
-+ cyl, head, cdata->rec);
-+ break;
-+ case DASD_FMT_ERR_KEY_LENGTH:
-+ ERRMSG("Invalid key length (found %d, expected %d) "
-+ "at cyl: %d trk: %d rec: %d.\n",
-+ cdata->key_length, kl, cyl, head, cdata->rec);
-+ break;
-+ }
-+}
-+
-+/*
- * signal handler:
- * enables the disk again in case of SIGTERM, SIGINT and SIGQUIT
- */
-@@ -263,6 +393,25 @@ static void get_blocksize(unsigned int *
- }
-
- /*
-+ * Check whether a specified blocksize matches the blocksize of the device
-+ */
-+static void check_blocksize(dasdfmt_info_t *info, unsigned int blksize)
-+{
-+ unsigned int dev_blksize;
-+
-+ if (!info->blksize_specified ||
-+ info->dasd_info.format == DASD_FORMAT_NONE)
-+ return;
-+
-+ get_blocksize(&dev_blksize);
-+ if (dev_blksize != blksize) {
-+ ERRMSG_EXIT(EXIT_FAILURE, "WARNING: Device is formatted with a "
-+ "different blocksize (%d).\nUse --mode=full to "
-+ "perform a clean format.\n", dev_blksize);
-+ }
-+}
-+
-+/*
- * check for disk type and set some variables (e.g. usage count)
- */
- static void check_disk(dasdfmt_info_t *info)
-@@ -449,6 +598,35 @@ static void set_label(dasdfmt_info_t *in
- }
-
- /*
-+ * This function checks whether a range of tracks is in regular format
-+ * with the specified block size.
-+ */
-+static format_check_t check_track_format(format_data_t *p)
-+{
-+ format_check_t cdata = {
-+ .expect = {
-+ .blksize = p->blksize,
-+ .intensity = p->intensity,
-+ .start_unit = p->start_unit,
-+ .stop_unit = p->stop_unit
-+ }, 0
-+ };
-+
-+ if (ioctl(filedes, BIODASDCHECKFMT, &cdata)) {
-+ if (errno == ENOTTY) {
-+ ERRMSG_EXIT(EXIT_FAILURE, "%s: Missing kernel support "
-+ "for format checking (--force to "
-+ "override)\n", prog_name);
-+ }
-+ ERRMSG_EXIT(EXIT_FAILURE, "%s: Could no check format: %s\n",
-+ prog_name, strerror(errno));
-+ }
-+
-+ return cdata;
-+}
-+
-+
-+/*
- * ask the user to specify a blocksize
- */
- static format_data_t ask_user_for_blksize(format_data_t params)
-@@ -511,6 +689,8 @@ static void dasdfmt_print_info(dasdfmt_i
- printf(" Compatible Disk Layout : %s\n",
- (p->intensity & DASD_FMT_INT_COMPAT) ? "yes" : "no");
- printf(" Blocksize : %d\n", p->blksize);
-+ printf(" Mode : %s\n",
-+ (mode == FULL) ? "Full" : "Quick");
-
- if (info->testmode)
- printf("Test mode active, omitting ioctl.\n");
-@@ -869,6 +1049,62 @@ static void dasdfmt_prepare_and_format(d
- disk_disabled = 0;
- }
-
-+/*
-+ * This function will only format the first two tracks of a DASD.
-+ * The rest of the DASD is untouched and left as is.
-+ */
-+static void dasdfmt_quick_format(dasdfmt_info_t *info, unsigned int cylinders,
-+ unsigned int heads, format_data_t *p)
-+{
-+ format_check_t cdata = { .expect = {0}, 0 };
-+ format_data_t tmp = *p;
-+
-+ if (info->force) {
-+ printf("Skipping format check due to --force.\n");
-+ } else {
-+ check_blocksize(info, p->blksize);
-+
-+ printf("Checking the format of selected tracks...\n");
-+
-+ /* Check device format on the first and last 3 regular tracks */
-+ tmp.start_unit = 2;
-+ tmp.stop_unit = 4;
-+ cdata = check_track_format(&tmp);
-+ if (!cdata.result) {
-+ tmp.start_unit = (cylinders * heads) - 3;
-+ tmp.stop_unit = (cylinders * heads) - 1;
-+ cdata = check_track_format(&tmp);
-+ }
-+ if (cdata.result) {
-+ evaluate_format_error(info, &cdata, heads);
-+ ERRMSG_EXIT(EXIT_FAILURE, "Use --mode=full to perform "
-+ "a clean format.\n");
-+ } else {
-+ printf("Done. Disk seems fine.\n");
-+ }
-+ }
-+
-+ if (!((info->withoutprompt) && (info->verbosity < 1)))
-+ printf("Formatting the first two tracks of the device.\n");
-+
-+ /* Disable the device before we do anything */
-+ if (ioctl(filedes, BIODASDDISABLE, p))
-+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl to disable the device "
-+ "failed. (%s)\n", prog_name, strerror(errno));
-+ disk_disabled = 1;
-+
-+ /* Now do the actual formatting of our first two tracks */
-+ if (ioctl(filedes, BIODASDFMT, p))
-+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl to format the device "
-+ "failed. (%s)\n", prog_name, strerror(errno));
-+
-+ /* Re-Enable the device so that we can continue working with it */
-+ if (ioctl(filedes, BIODASDENABLE, p))
-+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl to enable the device "
-+ "failed. (%s)\n", prog_name, strerror(errno));
-+ disk_disabled = 0;
-+}
-+
- static void do_format_dasd(dasdfmt_info_t *info, volume_label_t *vlabel,
- format_data_t *p, unsigned int cylinders,
- unsigned int heads)
-@@ -877,7 +1113,15 @@ static void do_format_dasd(dasdfmt_info_
- int count;
-
- p->start_unit = 0;
-- p->stop_unit = (cylinders * heads) - 1;
-+
-+ switch (mode) {
-+ case FULL: /* all tracks */
-+ p->stop_unit = (cylinders * heads) - 1;
-+ break;
-+ case QUICK: /* just the first two */
-+ p->stop_unit = 1;
-+ break;
-+ }
-
- if ((info->verbosity > 0) || !info->withoutprompt || info->testmode)
- dasdfmt_print_info(info, vlabel, cylinders, heads, p);
-@@ -919,11 +1163,17 @@ static void do_format_dasd(dasdfmt_info_
- }
- }
-
-- if (!((info->withoutprompt) && (info->verbosity < 1)))
-- printf("Formatting the device. This may take a "
-- "while (get yourself a coffee).\n");
--
-- dasdfmt_prepare_and_format(info, cylinders, heads, p);
-+ switch (mode) {
-+ case FULL:
-+ if (!((info->withoutprompt) && (info->verbosity < 1)))
-+ printf("Formatting the device. This may take a "
-+ "while (get yourself a coffee).\n");
-+ dasdfmt_prepare_and_format(info, cylinders, heads, p);
-+ break;
-+ case QUICK:
-+ dasdfmt_quick_format(info, cylinders, heads, p);
-+ break;
-+ }
-
- if (!info->yast_mode)
- printf("Finished formatting the device.\n");
-@@ -981,6 +1231,8 @@ int main(int argc, char *argv[])
- format_params.blksize = DEFAULT_BLOCKSIZE;
- format_params.intensity = DASD_FMT_INT_COMPAT;
-
-+ mode = FULL;
-+
- /*************** parse parameters **********************/
-
- while (1) {
-@@ -1082,6 +1334,18 @@ int main(int argc, char *argv[])
- case 'C':
- info.force_host = 1;
- break;
-+ case 'M':
-+ if (strcasecmp(optarg, "full") == 0)
-+ mode = FULL;
-+ else if (strcasecmp(optarg, "quick") == 0)
-+ mode = QUICK;
-+ else
-+ ERRMSG_EXIT(EXIT_FAILURE,
-+ "%s: The specified mode '%s' is "
-+ "invalid. Consult the man page for "
-+ "more information.\n",
-+ prog_name, optarg);
-+ break;
- case -1:
- /* End of options string - start of devices list */
- info.device_id = optind;
-@@ -1194,8 +1458,14 @@ int main(int argc, char *argv[])
-
- get_device_info(&info);
-
-- if (!info.blksize_specified)
-- format_params = ask_user_for_blksize(format_params);
-+ /* Either let the user specify the blksize or get it from the kernel */
-+ if (!info.blksize_specified) {
-+ if (!(mode == FULL ||
-+ info.dasd_info.format == DASD_FORMAT_NONE))
-+ get_blocksize(&format_params.blksize);
-+ else
-+ format_params = ask_user_for_blksize(format_params);
-+ }
-
- if (info.keep_volser) {
- if (format_params.intensity == 0x00) {
---- a/dasdfmt/dasdfmt.h
-+++ b/dasdfmt/dasdfmt.h
-@@ -143,6 +143,14 @@ struct dasd_eckd_characteristics {
- unsigned int long_no_cyl;
- } __attribute__ ((packed));
-
-+/*
-+ * Represents possible format modes that can be specified when formatting
-+ * a DASD.
-+ */
-+typedef enum format_mode_t {
-+ FULL, /* default mode */
-+ QUICK, /* format only the first 2 tracks */
-+} format_mode_t;
-
- /*
- * struct format_data_t
-@@ -168,6 +176,43 @@ typedef struct format_data_t {
- #define DASD_FMT_INT_COMPAT 8 /* use OS/390 compatible disk layout */
- #define DASD_FMT_INT_FMT_NOR0 16 /* remove permission to write record zero */
-
-+/*
-+ * struct format_check_t
-+ * represents all data necessary to evaluate the format of
-+ * different tracks of a dasd
-+ */
-+typedef struct format_check_t {
-+ /* Input */
-+ struct format_data_t expect;
-+
-+ /* Output */
-+ unsigned int result; /* Error indication (DASD_FMT_ERR_*) */
-+ unsigned int unit; /* Track that is in error */
-+ unsigned int rec; /* Record that is in error */
-+ unsigned int num_records; /* Records in the track in error */
-+ unsigned int blksize; /* Block-size of first record in error */
-+ unsigned int key_length; /* Key length of first record in error */
-+} format_check_t;
-+
-+/*
-+ * values to be used in format_check_t for indicating
-+ * possible format errors
-+ */
-+#define DASD_FMT_ERR_TOO_FEW_RECORDS 1
-+#define DASD_FMT_ERR_TOO_MANY_RECORDS 2
-+#define DASD_FMT_ERR_BLKSIZE 3
-+#define DASD_FMT_ERR_RECORD_ID 4
-+#define DASD_FMT_ERR_KEY_LENGTH 5
-+
-+/*
-+ * values to be used for dasd_information2_t.format
-+ * 0x00: NOT formatted
-+ * 0x01: Linux disc layout
-+ * 0x02: Common disc layout
-+ */
-+#define DASD_FORMAT_NONE 0
-+#define DASD_FORMAT_LDL 1
-+#define DASD_FORMAT_CDL 2
-
- /* Disable the volume (for Linux) */
- #define BIODASDDISABLE _IO(DASD_IOCTL_LETTER,0)
-@@ -180,6 +225,9 @@ typedef struct format_data_t {
- /* #define BIODASDFORMAT _IOW(IOCTL_LETTER,0,format_data_t) , deprecated */
- #define BIODASDFMT _IOW(DASD_IOCTL_LETTER,1,format_data_t)
-
-+/* Check device format according to format_data_t */
-+#define BIODASDCHECKFMT _IOWR(DASD_IOCTL_LETTER, 2, format_check_t)
-+
- /****************************************************************************
- * SECTION: Further IOCTL Definitions (see fs.h and hdreq.h ) *
- ****************************************************************************/
-@@ -225,7 +273,7 @@ typedef struct format_data_t {
- if (*endptr) ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \
- "is in invalid format\n",prog_name);}
-
--#define dasdfmt_getopt_string "b:n:l:f:d:m:r:hpQLtyvVFkCYP:"
-+#define dasdfmt_getopt_string "b:n:l:f:d:m:M:r:hpQLtyvVFkCYP:"
-
- static struct option dasdfmt_getopt_long_options[]=
- {
-@@ -247,6 +295,7 @@ static struct option dasdfmt_getopt_long
- { "keep_volser", 0, 0, 'k'},
- { "norecordzero", 0, 0, 'z'},
- { "check_host_count", 0, 0, 'C'},
-+ { "mode", 1, 0, 'M'},
- {0, 0, 0, 0}
- };
-
diff --git a/s390-tools-sles12sp3-dasdfmt-08-Make-progress-output-reusable-and-add-ETR.patch b/s390-tools-sles12sp3-dasdfmt-08-Make-progress-output-reusable-and-add-ETR.patch
deleted file mode 100644
index 0063641..0000000
--- a/s390-tools-sles12sp3-dasdfmt-08-Make-progress-output-reusable-and-add-ETR.patch
+++ /dev/null
@@ -1,279 +0,0 @@
-Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
-From: Jan Höppner
-
-Summary: dasdfmt: Add new formatting modes
-Description: Introduce new formatting modes 'quick' and 'expand' to either
- format an earlier formatted DASD that could potentially be
- re-initialized very easily or format unformatted tracks at the
- end of a device that was previously extended.
-
- Also add the command line argument --check to provide a function
- that checks a DASD volume for correct formatting.
-Upstream-ID: -
-Problem-ID: LS1501
-
-Upstream-Description:
-
- dasdfmt: Make progress output reusable and add ETR
-
- The progress indicator (in form of a progressbar, hashmarks or
- percentages) is created within the formatting loop.
-
- Put the drawing of the progress into a separate function to make it
- reusable. Clean up the formatting loop while at it and make it
- more readable. Also, add the estimated time remaining to the output.
-
- Signed-off-by: Jan Höppner
- Signed-off-by: Stefan Haberland
-
-
-Signed-off-by: Jan Höppner
----
- dasdfmt/dasdfmt.c | 198 +++++++++++++++++++++++++++++++++++++-----------------
- 1 file changed, 138 insertions(+), 60 deletions(-)
-
---- a/dasdfmt/dasdfmt.c
-+++ b/dasdfmt/dasdfmt.c
-@@ -11,6 +11,7 @@
-
- #include
- #include
-+#include
-
- #include "zt_common.h"
- #include "dasdfmt.h"
-@@ -20,6 +21,8 @@
- #include
-
- #define BUSIDSIZE 8
-+#define SEC_PER_DAY (60 * 60 * 24)
-+#define SEC_PER_HOUR (60 * 60)
-
- /* Full tool name */
- static const char tool_name[] = "dasdfmt: zSeries DASD format program";
-@@ -88,6 +91,120 @@ static void exit_usage(int exitcode)
- exit(exitcode);
- }
-
-+/*
-+ * Helper function to calculate the days, hours, minutes, and seconds
-+ * for a given timestamp in seconds
-+ */
-+static void calc_time(time_t time, int *d, int *h, int *m, int *s)
-+{
-+ *d = time / SEC_PER_DAY;
-+ time %= SEC_PER_DAY;
-+ *h = time / SEC_PER_HOUR;
-+ time %= SEC_PER_HOUR;
-+ *m = time / 60;
-+ *s = time % 60;
-+}
-+
-+/*
-+ * This function calculates and prints the estimated time remaining.
-+ */
-+static void print_etr(int p_new, int started)
-+{
-+ static struct timeval start;
-+ struct timeval now;
-+ time_t time_elapsed;
-+ time_t time_end;
-+ int d, h, m, s;
-+ static int p_init;
-+ int p;
-+
-+ if (!started) {
-+ gettimeofday(&start, NULL);
-+ p_init = p_new;
-+ }
-+ gettimeofday(&now, NULL);
-+ time_elapsed = now.tv_sec - start.tv_sec;
-+
-+ /*
-+ * We might start somewhere in the middle with an initial percentage
-+ * value of i.e. 60%. Therefore we need to calculate the relative
-+ * percentage of p_new within that remaining range (100 - 60) in order
-+ * to correctly estimate the remaining time.
-+ */
-+ if (p_init == 100)
-+ p = p_init;
-+ else
-+ p = 100 * (p_new - p_init) / (100 - p_init);
-+
-+ if (p == 0)
-+ time_end = time_elapsed;
-+ else
-+ time_end = time_elapsed * (100 - p) / p;
-+
-+ /* Calculate days, hours, minutes, and seconds */
-+ calc_time(time_end, &d, &h, &m, &s);
-+ if (p_new == 100)
-+ calc_time(time_elapsed, &d, &h, &m, &s);
-+
-+ /* Avoid printing leading zeros */
-+ if (d > 0)
-+ printf(" [%dd %dh %dm %ds%-4s", d, h, m, s, "]");
-+ else if (h > 0)
-+ printf(" [%dh %dm %ds%-7s", h, m, s, "]");
-+ else if (m > 0)
-+ printf(" [%dm %ds%-6s", m, s, "]");
-+ else if (s > 0 || p > 50)
-+ printf(" [%ds%-5s", s, "]");
-+ else
-+ printf(" [--%-1s", "]");
-+}
-+
-+/*
-+ * Draw the progress indicator depending on what command line argument is set.
-+ * This can either be a progressbar, hashmarks, or percentage.
-+ */
-+static void draw_progress(dasdfmt_info_t *info, int cyl, unsigned int cylinders)
-+{
-+ static int hashcount;
-+ static int started;
-+ static int p_old;
-+ int p_new = 0;
-+ int barlength;
-+ int i;
-+
-+ if (info->print_progressbar) {
-+ printf("cyl %7d of %7d |", cyl, cylinders);
-+ p_new = cyl * 100 / cylinders;
-+ if (p_new != p_old || !started) {
-+ /* percent value has changed */
-+ p_old = p_new;
-+ barlength = cyl * 33 / cylinders;
-+ for (i = 1; i <= barlength; i++)
-+ printf("#");
-+ for (i = barlength + 1; i <= 33; i++)
-+ printf("-");
-+ printf("|%3d%%", p_new);
-+ print_etr(p_new, started);
-+ started = 1;
-+ }
-+ printf("\r");
-+ fflush(stdout);
-+ }
-+
-+ if (info->print_hashmarks &&
-+ (cyl / info->hashstep - hashcount) != 0) {
-+ printf("%d|", info->procnum);
-+ fflush(stdout);
-+ hashcount++;
-+ }
-+
-+ if (info->print_percentage) {
-+ printf("cyl %7d of %7d |%3d%%\n", cyl, cylinders,
-+ cyl * 100 / cylinders);
-+ fflush(stdout);
-+ }
-+}
-+
- static int reread_partition_table(void)
- {
- int i = 0;
-@@ -906,9 +1023,10 @@ static void dasdfmt_write_labels(dasdfmt
- static void dasdfmt_format(dasdfmt_info_t *info, unsigned int cylinders,
- unsigned int heads, format_data_t *format_params)
- {
-- format_data_t format_step;
-- int j, cyl, tmp, p1, p2, hashcount = 0;
-- unsigned int k;
-+ unsigned int step_value;
-+ unsigned long cur_trk;
-+ format_data_t step;
-+ int cyl = 0;
-
- if (info->print_hashmarks) {
- if (info->hashstep < reqsize)
-@@ -923,73 +1041,33 @@ static void dasdfmt_format(dasdfmt_info_
- info->hashstep);
- }
-
-- format_step.blksize = format_params->blksize;
-- format_step.intensity = format_params->intensity;
--
-- k = 0;
-- cyl = 1;
-- if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode)
-- printf("\n");
--
-- while (1) {
-- p1 = -1;
-- p2 = 0;
-- if (k + heads * reqsize >= format_params->stop_unit)
-- reqsize = 1;
-- format_step.start_unit = k;
-- format_step.stop_unit = k + reqsize * heads - 1;
-+ step = *format_params;
-+ cur_trk = format_params->start_unit;
-
-- if (cyl == 1)
-- format_step.start_unit += 1;
-+ while (cur_trk < format_params->stop_unit) {
-+ step_value = reqsize * heads - (cur_trk % heads);
-+ step.start_unit = cur_trk;
-+ if (cur_trk + reqsize * heads >= format_params->stop_unit)
-+ step.stop_unit = format_params->stop_unit;
-+ else
-+ step.stop_unit = cur_trk + step_value - 1;
-
-- if (ioctl(filedes, BIODASDFMT, &format_step) != 0)
-+ if (ioctl(filedes, BIODASDFMT, &step) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (format cylinder) IOCTL "
- "BIODASDFMT failed. (%s)\n",
- prog_name, strerror(errno));
-
-- if (info->print_progressbar) {
-- printf("cyl %7d of %7d |", cyl, cylinders);
-- p2 = p1;
-- p1 = cyl * 100 / cylinders;
-- if (p1 != p2) {
-- /* percent value has changed */
-- tmp = cyl * 50 / cylinders;
-- for (j = 1; j <= tmp; j++)
-- printf("#");
-- for (j = tmp + 1; j <= 50; j++)
-- printf("-");
-- printf("|%3d%%", p1);
-- }
-- printf("\r");
-- fflush(stdout);
-- }
--
-- if (info->print_hashmarks)
-- if ((cyl / info->hashstep - hashcount) != 0) {
-- printf("%d|",info->procnum);
-- fflush(stdout);
-- hashcount++;
-- }
--
-- if (info->print_percentage) {
-- printf("cyl %7d of %7d |%3d%%\n", cyl, cylinders,
-- cyl*100/cylinders);
-- fflush(stdout);
-- }
-+ cyl = cur_trk / heads + 1;
-+ draw_progress(info, cyl, cylinders);
-
-- if (k % heads == 0) {
-- k += reqsize * heads;
-- cyl += reqsize;
-- } else {
-- k += format_params->stop_unit % heads;
-- }
--
-- if (k > format_params->stop_unit)
-- break;
-+ cur_trk += step_value;
- }
-+ /* We're done, draw the 100% mark */
-+ cyl = step.stop_unit / heads + 1;
-+ draw_progress(info, cyl, cylinders);
-
- if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode)
-- printf("\n\n");
-+ printf("\n");
- }
-
- static void dasdfmt_prepare_and_format(dasdfmt_info_t *info,
diff --git a/s390-tools-sles12sp3-dasdfmt-09-Add-command-line-argument-check.patch b/s390-tools-sles12sp3-dasdfmt-09-Add-command-line-argument-check.patch
deleted file mode 100644
index d06bab5..0000000
--- a/s390-tools-sles12sp3-dasdfmt-09-Add-command-line-argument-check.patch
+++ /dev/null
@@ -1,453 +0,0 @@
-Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
-From: Jan Höppner
-
-Summary: dasdfmt: Add new formatting modes
-Description: Introduce new formatting modes 'quick' and 'expand' to either
- format an earlier formatted DASD that could potentially be
- re-initialized very easily or format unformatted tracks at the
- end of a device that was previously extended.
-
- Also add the command line argument --check to provide a function
- that checks a DASD volume for correct formatting.
-Upstream-ID: -
-Problem-ID: LS1501
-
-Upstream-Description:
-
- dasdfmt: Add command line argument --check
-
- Provide a function to check a DASD volume for correct formatting. This
- can be useful in cases where only a few tracks of a volume are
- incorrectly formatted.
-
- All tracks on the device are checked. In an error case, the check
- process is stopped and appropriate messages are displayed.
-
- The --check command line argument can be combined with either -P,
- -p or -m to display progress on the console.
-
- Signed-off-by: Jan Höppner
- Signed-off-by: Stefan Haberland
-
-
-Signed-off-by: Jan Höppner
----
- dasdfmt/dasdfmt.8 | 5 +
- dasdfmt/dasdfmt.c | 244 ++++++++++++++++++++++++++++++++++++++++--------------
- dasdfmt/dasdfmt.h | 4
- 3 files changed, 190 insertions(+), 63 deletions(-)
-
---- a/dasdfmt/dasdfmt.8
-+++ b/dasdfmt/dasdfmt.8
-@@ -121,6 +121,11 @@ using \fB-b\fR (\fB--blocksize\fR).
- .RE
-
- .TP
-+\fB--check\fR
-+Perform a complete format check on a DASD volume. A blocksize can be specified
-+with \fB-b\fR (\fB--blocksize\fR).
-+
-+.TP
- \fB-r\fR \fIcylindercount\fR or \fB--requestsize\fR=\fIcylindercount\fR
- Number of cylinders to be processed in one formatting step.
- The value must be an integer in the range 1 - 255.
---- a/dasdfmt/dasdfmt.c
-+++ b/dasdfmt/dasdfmt.c
-@@ -76,7 +76,8 @@ static void exit_usage(int exitcode)
- " the host access open count to ensure the device\n"
- " is not online on another operating system instance\n"
- " --norecordzero prevent storage server from modifying"
-- " record 0\n\n"
-+ " record 0\n"
-+ " --check perform complete format check on device\n\n"
- " is the volume identifier, which is converted\n"
- " to EBCDIC and written to disk.\n"
- " (6 characters, e.g. LNX001\n"
-@@ -163,7 +164,8 @@ static void print_etr(int p_new, int sta
- * Draw the progress indicator depending on what command line argument is set.
- * This can either be a progressbar, hashmarks, or percentage.
- */
--static void draw_progress(dasdfmt_info_t *info, int cyl, unsigned int cylinders)
-+static void draw_progress(dasdfmt_info_t *info, int cyl, unsigned int cylinders,
-+ int aborted)
- {
- static int hashcount;
- static int started;
-@@ -175,7 +177,7 @@ static void draw_progress(dasdfmt_info_t
- if (info->print_progressbar) {
- printf("cyl %7d of %7d |", cyl, cylinders);
- p_new = cyl * 100 / cylinders;
-- if (p_new != p_old || !started) {
-+ if (p_new != p_old || !started || aborted) {
- /* percent value has changed */
- p_old = p_new;
- barlength = cyl * 33 / cylinders;
-@@ -184,6 +186,8 @@ static void draw_progress(dasdfmt_info_t
- for (i = barlength + 1; i <= 33; i++)
- printf("-");
- printf("|%3d%%", p_new);
-+ if (aborted)
-+ p_new = 100;
- print_etr(p_new, started);
- started = 1;
- }
-@@ -284,11 +288,17 @@ static void evaluate_format_error(dasdfm
- unsigned int kl = 0;
- int blksize = cdata->expect.blksize;
-
-+ if (info->print_progressbar || info->print_hashmarks)
-+ printf("\n");
-+
- /*
-- * Reading record zero will never happen. If the record in error is 0
-- * nonetheless, the device is not formatted at all!
-+ * If mode is not QUICK and a device format couldn't be determined, the
-+ * device is considered not formatted.
-+ * Also, reading record zero will never happen. If the record in error
-+ * is 0 nonetheless, the device is not formatted at all as well!
- */
-- if (cdata->rec == 0) {
-+ if ((info->dasd_info.format == DASD_FORMAT_NONE && mode != QUICK) ||
-+ cdata->rec == 0) {
- ERRMSG("WARNING: The specified device is not "
- "formatted at all.\n");
- return;
-@@ -529,6 +539,35 @@ static void check_blocksize(dasdfmt_info
- }
-
- /*
-+ * Check whether a specified layout matches the layout
-+ * a device is formatted with.
-+ */
-+static void check_layout(dasdfmt_info_t *info, unsigned int intensity)
-+{
-+ char layout[4];
-+
-+ if (!info->layout_specified ||
-+ info->dasd_info.format == DASD_FORMAT_NONE)
-+ return;
-+
-+ if ((intensity & DASD_FMT_INT_COMPAT) &&
-+ info->dasd_info.format == DASD_FORMAT_CDL)
-+ return;
-+
-+ if (!(intensity & DASD_FMT_INT_COMPAT) &&
-+ info->dasd_info.format == DASD_FORMAT_LDL)
-+ return;
-+
-+ if (info->dasd_info.format == DASD_FORMAT_CDL)
-+ sprintf(layout, "CDL");
-+ if (info->dasd_info.format == DASD_FORMAT_LDL)
-+ sprintf(layout, "LDL");
-+
-+ ERRMSG_EXIT(EXIT_FAILURE, "WARNING: Device is formatted with a "
-+ "different layout (%s).\n", layout);
-+}
-+
-+/*
- * check for disk type and set some variables (e.g. usage count)
- */
- static void check_disk(dasdfmt_info_t *info)
-@@ -715,10 +754,29 @@ static void set_label(dasdfmt_info_t *in
- }
-
- /*
-+ * Check whether hashsteps are within the correct interval.
-+ */
-+static void check_hashmarks(dasdfmt_info_t *info)
-+{
-+ if (info->print_hashmarks) {
-+ if (info->hashstep < reqsize)
-+ info->hashstep = reqsize;
-+ if ((info->hashstep < 1) || (info->hashstep > 1000)) {
-+ printf("Hashmark increment is not in range <1,1000>, "
-+ "using the default.\n");
-+ info->hashstep = 10;
-+ }
-+
-+ printf("Printing hashmark every %d cylinders.\n",
-+ info->hashstep);
-+ }
-+}
-+
-+/*
- * This function checks whether a range of tracks is in regular format
- * with the specified block size.
- */
--static format_check_t check_track_format(format_data_t *p)
-+static format_check_t check_track_format(dasdfmt_info_t *info, format_data_t *p)
- {
- format_check_t cdata = {
- .expect = {
-@@ -731,9 +789,11 @@ static format_check_t check_track_format
-
- if (ioctl(filedes, BIODASDCHECKFMT, &cdata)) {
- if (errno == ENOTTY) {
-- ERRMSG_EXIT(EXIT_FAILURE, "%s: Missing kernel support "
-- "for format checking (--force to "
-- "override)\n", prog_name);
-+ ERRMSG("%s: Missing kernel support for format checking",
-+ prog_name);
-+ if (!info->check)
-+ ERRMSG(" (--force to override)");
-+ ERRMSG_EXIT(EXIT_FAILURE, ".\n");
- }
- ERRMSG_EXIT(EXIT_FAILURE, "%s: Could no check format: %s\n",
- prog_name, strerror(errno));
-@@ -742,6 +802,97 @@ static format_check_t check_track_format
- return cdata;
- }
-
-+/*
-+ * Either do the actual format or check depending on the check-value.
-+ */
-+static int process_tracks(dasdfmt_info_t *info, unsigned int cylinders,
-+ unsigned int heads, format_data_t *format_params)
-+{
-+ format_check_t cdata = { .expect = {0}, 0};
-+ format_data_t step = *format_params;
-+ unsigned long step_value;
-+ unsigned long cur_trk;
-+ int cyl = 0;
-+
-+ check_hashmarks(info);
-+
-+ cur_trk = format_params->start_unit;
-+
-+ while (cur_trk < format_params->stop_unit) {
-+ step_value = reqsize * heads - (cur_trk % heads);
-+ step.start_unit = cur_trk;
-+ if (cur_trk + heads * reqsize >= format_params->stop_unit)
-+ step.stop_unit = format_params->stop_unit;
-+ else
-+ step.stop_unit = cur_trk + step_value - 1;
-+
-+ if (info->check) {
-+ cdata = check_track_format(info, &step);
-+ if (cdata.result) {
-+ cyl = cur_trk / heads + 1;
-+ draw_progress(info, cyl, cylinders, 1);
-+ evaluate_format_error(info, &cdata, heads);
-+ break;
-+ }
-+ } else {
-+ if (ioctl(filedes, BIODASDFMT, &step) != 0)
-+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl call "
-+ "to format tracks failed. (%s)\n",
-+ prog_name, strerror(errno));
-+ }
-+
-+ cyl = cur_trk / heads + 1;
-+ draw_progress(info, cyl, cylinders, 0);
-+
-+ cur_trk += step_value;
-+ }
-+ /* We're done, draw the 100% mark */
-+ if (!cdata.result) {
-+ cyl = step.stop_unit / heads + 1;
-+ draw_progress(info, cyl, cylinders, 0);
-+ printf("\n");
-+ }
-+
-+ return cdata.result;
-+}
-+
-+/*
-+ * This function checks the format of the entire disk.
-+ */
-+static void check_disk_format(dasdfmt_info_t *info, unsigned int cylinders,
-+ unsigned int heads, format_data_t *check_params)
-+{
-+ check_params->start_unit = 0;
-+ check_params->stop_unit = (cylinders * heads) - 1;
-+
-+ printf("Checking format of the entire disk...\n");
-+
-+ if (info->testmode) {
-+ printf("Test mode active, omitting ioctl.\n");
-+ return;
-+ }
-+
-+ check_blocksize(info, check_params->blksize);
-+ check_layout(info, check_params->intensity);
-+
-+ /*
-+ * If no layout was specified, set the intensity
-+ * according to what the layout seems to be.
-+ */
-+ if (!info->layout_specified) {
-+ if (info->dasd_info.format == DASD_FORMAT_CDL)
-+ check_params->intensity |= DASD_FMT_INT_COMPAT;
-+ else if (info->dasd_info.format == DASD_FORMAT_LDL)
-+ check_params->intensity &= ~DASD_FMT_INT_COMPAT;
-+ }
-+
-+ if (process_tracks(info, cylinders, heads, check_params)) {
-+ ERRMSG_EXIT(EXIT_FAILURE, "Use --mode=full to perform a "
-+ "clean format.\n");
-+ }
-+
-+ printf("Done. Disk is fine.\n");
-+}
-
- /*
- * ask the user to specify a blocksize
-@@ -1023,51 +1174,7 @@ static void dasdfmt_write_labels(dasdfmt
- static void dasdfmt_format(dasdfmt_info_t *info, unsigned int cylinders,
- unsigned int heads, format_data_t *format_params)
- {
-- unsigned int step_value;
-- unsigned long cur_trk;
-- format_data_t step;
-- int cyl = 0;
--
-- if (info->print_hashmarks) {
-- if (info->hashstep < reqsize)
-- info->hashstep = reqsize;
-- if ((info->hashstep < 1) || (info->hashstep > 1000)) {
-- printf("Hashmark increment is not in range <1,1000>, "
-- "using the default.\n");
-- info->hashstep = 10;
-- }
--
-- if(!info->yast_mode) printf("Printing hashmark every %d cylinders.\n",
-- info->hashstep);
-- }
--
-- step = *format_params;
-- cur_trk = format_params->start_unit;
--
-- while (cur_trk < format_params->stop_unit) {
-- step_value = reqsize * heads - (cur_trk % heads);
-- step.start_unit = cur_trk;
-- if (cur_trk + reqsize * heads >= format_params->stop_unit)
-- step.stop_unit = format_params->stop_unit;
-- else
-- step.stop_unit = cur_trk + step_value - 1;
--
-- if (ioctl(filedes, BIODASDFMT, &step) != 0)
-- ERRMSG_EXIT(EXIT_FAILURE, "%s: (format cylinder) IOCTL "
-- "BIODASDFMT failed. (%s)\n",
-- prog_name, strerror(errno));
--
-- cyl = cur_trk / heads + 1;
-- draw_progress(info, cyl, cylinders);
--
-- cur_trk += step_value;
-- }
-- /* We're done, draw the 100% mark */
-- cyl = step.stop_unit / heads + 1;
-- draw_progress(info, cyl, cylinders);
--
-- if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode)
-- printf("\n");
-+ process_tracks(info, cylinders, heads, format_params);
- }
-
- static void dasdfmt_prepare_and_format(dasdfmt_info_t *info,
-@@ -1082,6 +1189,10 @@ static void dasdfmt_prepare_and_format(d
- | DASD_FMT_INT_INVAL)
- };
-
-+ if (!((info->withoutprompt) && (info->verbosity < 1)))
-+ printf("Formatting the device. This may take a while "
-+ "(get yourself a coffee).\n");
-+
- if (info->verbosity > 0)
- printf("Detaching the device...\n");
-
-@@ -1147,11 +1258,11 @@ static void dasdfmt_quick_format(dasdfmt
- /* Check device format on the first and last 3 regular tracks */
- tmp.start_unit = 2;
- tmp.stop_unit = 4;
-- cdata = check_track_format(&tmp);
-+ cdata = check_track_format(info, &tmp);
- if (!cdata.result) {
- tmp.start_unit = (cylinders * heads) - 3;
- tmp.stop_unit = (cylinders * heads) - 1;
-- cdata = check_track_format(&tmp);
-+ cdata = check_track_format(info, &tmp);
- }
- if (cdata.result) {
- evaluate_format_error(info, &cdata, heads);
-@@ -1243,9 +1354,6 @@ static void do_format_dasd(dasdfmt_info_
-
- switch (mode) {
- case FULL:
-- if (!((info->withoutprompt) && (info->verbosity < 1)))
-- printf("Formatting the device. This may take a "
-- "while (get yourself a coffee).\n");
- dasdfmt_prepare_and_format(info, cylinders, heads, p);
- break;
- case QUICK:
-@@ -1337,6 +1445,7 @@ int main(int argc, char *argv[])
- printf("%s is not a valid option!\n", optarg);
- exit(1);
- }
-+ info.layout_specified = 1;
- break;
- case 'y':
- info.withoutprompt = 1;
-@@ -1424,6 +1533,9 @@ int main(int argc, char *argv[])
- "more information.\n",
- prog_name, optarg);
- break;
-+ case OPT_CHECK:
-+ info.check = 1;
-+ break;
- case -1:
- /* End of options string - start of devices list */
- info.device_id = optind;
-@@ -1539,7 +1651,7 @@ int main(int argc, char *argv[])
- /* Either let the user specify the blksize or get it from the kernel */
- if (!info.blksize_specified) {
- if (!(mode == FULL ||
-- info.dasd_info.format == DASD_FORMAT_NONE))
-+ info.dasd_info.format == DASD_FORMAT_NONE) || info.check)
- get_blocksize(&format_params.blksize);
- else
- format_params = ask_user_for_blksize(format_params);
-@@ -1568,8 +1680,14 @@ int main(int argc, char *argv[])
-
- set_geo(&info, &cylinders, &heads);
- set_label(&info, &vlabel, &format_params, cylinders);
-- do_format_dasd(&info, &vlabel, &format_params,
-- cylinders, heads);
-+
-+ if (info.check) {
-+ check_disk_format(&info, cylinders, heads,
-+ &format_params);
-+ } else {
-+ do_format_dasd(&info, &vlabel, &format_params,
-+ cylinders, heads);
-+ }
-
- if (close(filedes) != 0)
- ERRMSG("%s: error during close: %s\ncontinuing...\n",
---- a/dasdfmt/dasdfmt.h
-+++ b/dasdfmt/dasdfmt.h
-@@ -273,6 +273,7 @@ typedef struct format_check_t {
- if (*endptr) ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \
- "is in invalid format\n",prog_name);}
-
-+#define OPT_CHECK 128
- #define dasdfmt_getopt_string "b:n:l:f:d:m:M:r:hpQLtyvVFkCYP:"
-
- static struct option dasdfmt_getopt_long_options[]=
-@@ -296,6 +297,7 @@ static struct option dasdfmt_getopt_long
- { "norecordzero", 0, 0, 'z'},
- { "check_host_count", 0, 0, 'C'},
- { "mode", 1, 0, 'M'},
-+ { "check", 0, 0, OPT_CHECK},
- {0, 0, 0, 0}
- };
-
-@@ -328,6 +330,8 @@ typedef struct dasdfmt_info {
- int device_id;
- int keep_volser;
- int force_host;
-+ int layout_specified;
-+ int check;
- int yast_mode;
- int procnum;
- } dasdfmt_info_t;
diff --git a/s390-tools-sles12sp3-dasdfmt-10-Add-expand-format-mode.patch b/s390-tools-sles12sp3-dasdfmt-10-Add-expand-format-mode.patch
deleted file mode 100644
index 840edfb..0000000
--- a/s390-tools-sles12sp3-dasdfmt-10-Add-expand-format-mode.patch
+++ /dev/null
@@ -1,266 +0,0 @@
-Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
-From: Jan Höppner
-
-Summary: dasdfmt: Add new formatting modes
-Description: Introduce new formatting modes 'quick' and 'expand' to either
- format an earlier formatted DASD that could potentially be
- re-initialized very easily or format unformatted tracks at the
- end of a device that was previously extended.
-
- Also add the command line argument --check to provide a function
- that checks a DASD volume for correct formatting.
-Upstream-ID: -
-Problem-ID: LS1501
-
-Upstream-Description:
-
- dasdfmt: Add expand format mode
-
- If a DASD was extended, the format of the first part of the disk
- can be assumed to be correct. Usually, a full format would be necessary
- to ensure a fully functional disk. However, this would also format
- the already formatted part resulting in the loss of the data stored in
- that part.
-
- Add an expand mode which will search for the start of the unformatted
- area and begin formatting from there.
-
- The mode is being specified by --mode=expand (or -M expand for short).
-
- Furthermore:
- - Add string array for the individual modes for output purposes
- - Avoid writing labels when EXPAND mode is active since they can be
- assumed to be correct
- - Add man page description
-
-
-Signed-off-by: Jan Höppner
----
- dasdfmt/dasdfmt.8 | 7 +++
- dasdfmt/dasdfmt.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++-----
- dasdfmt/dasdfmt.h | 5 ++
- 3 files changed, 123 insertions(+), 9 deletions(-)
-
---- a/dasdfmt/dasdfmt.8
-+++ b/dasdfmt/dasdfmt.8
-@@ -118,6 +118,13 @@ Format the first two tracks and write la
- this option if you are sure that the target DASD already contains a regular
- format with the specified blocksize. A blocksize can optionally be specified
- using \fB-b\fR (\fB--blocksize\fR).
-+.IP expand
-+Format all unformatted tracks at the end of the target DASD. This mode assumes
-+that tracks at the beginning of the DASD volume have already been correctly
-+formatted, while a consecutive set of tracks at the end are unformatted. You can
-+use this mode to make added space available for Linux use after dynamically
-+increasing the size of a DASD volume. A blocksize can optionally be specified
-+using \fB-b\fR (\fB--blocksize\fR).
- .RE
-
- .TP
---- a/dasdfmt/dasdfmt.c
-+++ b/dasdfmt/dasdfmt.c
-@@ -88,7 +88,9 @@ static void exit_usage(int exitcode)
- " device node of the device to format\n"
- " is either\n"
- " 'full' to fully format the device (default)\n"
-- " 'quick' to format only the first two tracks\n");
-+ " 'quick' to format only the first two tracks\n"
-+ " 'expand' to format only the unformatted end"
-+ " of a device\n");
- exit(exitcode);
- }
-
-@@ -791,8 +793,11 @@ static format_check_t check_track_format
- if (errno == ENOTTY) {
- ERRMSG("%s: Missing kernel support for format checking",
- prog_name);
-- if (!info->check)
-+ if (mode == EXPAND) {
-+ ERRMSG(". Mode 'expand' cannot be used");
-+ } else if (!info->check) {
- ERRMSG(" (--force to override)");
-+ }
- ERRMSG_EXIT(EXIT_FAILURE, ".\n");
- }
- ERRMSG_EXIT(EXIT_FAILURE, "%s: Could no check format: %s\n",
-@@ -957,8 +962,7 @@ static void dasdfmt_print_info(dasdfmt_i
- printf(" Compatible Disk Layout : %s\n",
- (p->intensity & DASD_FMT_INT_COMPAT) ? "yes" : "no");
- printf(" Blocksize : %d\n", p->blksize);
-- printf(" Mode : %s\n",
-- (mode == FULL) ? "Full" : "Quick");
-+ printf(" Mode : %s\n", mode_str[mode]);
-
- if (info->testmode)
- printf("Test mode active, omitting ioctl.\n");
-@@ -1169,6 +1173,60 @@ static void dasdfmt_write_labels(dasdfmt
- }
-
- /*
-+ * This function will search for the beginning of an unformatted area
-+ * on the device. It checks selected tracks beforehand and makes sure
-+ * that the device is formatted to a certain extent. Otherwise the
-+ * process is terminated.
-+ */
-+static void dasdfmt_find_start(dasdfmt_info_t *info, unsigned int cylinders,
-+ unsigned heads, format_data_t *format_params)
-+{
-+ format_check_t cdata;
-+ unsigned int middle;
-+ unsigned int left = 2;
-+ unsigned int right = (cylinders * heads) - 1;
-+ unsigned int first = left;
-+
-+ check_blocksize(info, format_params->blksize);
-+
-+ format_params->start_unit = 0;
-+ format_params->stop_unit = 4;
-+ cdata = check_track_format(info, format_params);
-+
-+ if (cdata.result) {
-+ evaluate_format_error(info, &cdata, heads);
-+ ERRMSG_EXIT(EXIT_FAILURE, "Use --mode=full to perform a "
-+ "clean format.\n");
-+ }
-+
-+ printf("Expansion mode active. Searching for starting position...\n");
-+
-+ while (left <= right) {
-+ /* new track number to look at */
-+ middle = left + ((right - left) / 2);
-+
-+ format_params->start_unit = middle;
-+ format_params->stop_unit = middle;
-+ cdata = check_track_format(info, format_params);
-+ if (cdata.blksize != format_params->blksize) {
-+ first = middle;
-+ right = middle - 1;
-+ } else {
-+ left = middle + 1;
-+ }
-+ }
-+
-+ if (first == 2 && cdata.blksize == format_params->blksize)
-+ ERRMSG_EXIT(EXIT_FAILURE,
-+ "No unformatted part found, aborting.\n");
-+
-+ printf("Done. Unformatted part starts at track %d.\n", first);
-+
-+ /* return format_params with start_unit set to the correct value */
-+ format_params->start_unit = first;
-+}
-+
-+/*
- * formats the disk cylinderwise
- */
- static void dasdfmt_format(dasdfmt_info_t *info, unsigned int cylinders,
-@@ -1239,6 +1297,40 @@ static void dasdfmt_prepare_and_format(d
- }
-
- /*
-+ * This function will start the expand format process.
-+ */
-+static void dasdfmt_expand_format(dasdfmt_info_t *info, unsigned int cylinders,
-+ unsigned int heads, format_data_t *p)
-+{
-+ if (!((info->withoutprompt) && (info->verbosity < 1)))
-+ printf("Formatting the device. This may take a while "
-+ "(get yourself a coffee).\n");
-+
-+ if (info->verbosity > 0)
-+ printf("Detaching the device...\n");
-+
-+ if (ioctl(filedes, BIODASDDISABLE, p) != 0)
-+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL "
-+ "BIODASDDISABLE failed. (%s)\n", prog_name,
-+ strerror(errno));
-+ disk_disabled = 1;
-+
-+ dasdfmt_format(info, cylinders, heads, p);
-+
-+ if (info->verbosity > 0)
-+ printf("Formatting tracks complete...\n");
-+
-+ if (info->verbosity > 0)
-+ printf("Re-accessing the device...\n");
-+
-+ if (ioctl(filedes, BIODASDENABLE, p) != 0)
-+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL "
-+ "BIODASDENABLE failed. (%s)\n", prog_name,
-+ strerror(errno));
-+ disk_disabled = 0;
-+}
-+
-+/*
- * This function will only format the first two tracks of a DASD.
- * The rest of the DASD is untouched and left as is.
- */
-@@ -1310,6 +1402,10 @@ static void do_format_dasd(dasdfmt_info_
- case QUICK: /* just the first two */
- p->stop_unit = 1;
- break;
-+ case EXPAND: /* only the end of the disk */
-+ dasdfmt_find_start(info, cylinders, heads, p);
-+ p->stop_unit = (cylinders * heads) - 1;
-+ break;
- }
-
- if ((info->verbosity > 0) || !info->withoutprompt || info->testmode)
-@@ -1338,10 +1434,12 @@ static void do_format_dasd(dasdfmt_info_
-
- if (!info->testmode) {
- if (!info->withoutprompt) {
-- printf("\n--->> ATTENTION! <<---\n");
-- printf("All data of that device will be lost.\nType "
-- "\"yes\" to continue, no will leave the disk "
-- "untouched: ");
-+ printf("\n");
-+ if (mode != EXPAND)
-+ printf("--->> ATTENTION! <<---\nAll data of "
-+ "that device will be lost.\n");
-+ printf("Type \"yes\" to continue, no will leave the "
-+ "disk untouched: ");
- if (fgets(inp_buffer, sizeof(inp_buffer), stdin) == NULL)
- return;
- if (strcasecmp(inp_buffer, "yes") &&
-@@ -1359,12 +1457,14 @@ static void do_format_dasd(dasdfmt_info_
- case QUICK:
- dasdfmt_quick_format(info, cylinders, heads, p);
- break;
-+ case EXPAND:
-+ dasdfmt_expand_format(info, cylinders, heads, p);
- }
-
- if (!info->yast_mode)
- printf("Finished formatting the device.\n");
-
-- if (!info->writenolabel)
-+ if (!(info->writenolabel || mode == EXPAND))
- dasdfmt_write_labels(info, vlabel, cylinders, heads);
-
- if (!info->yast_mode)
-@@ -1526,6 +1626,8 @@ int main(int argc, char *argv[])
- mode = FULL;
- else if (strcasecmp(optarg, "quick") == 0)
- mode = QUICK;
-+ else if (strcasecmp(optarg, "expand") == 0)
-+ mode = EXPAND;
- else
- ERRMSG_EXIT(EXIT_FAILURE,
- "%s: The specified mode '%s' is "
---- a/dasdfmt/dasdfmt.h
-+++ b/dasdfmt/dasdfmt.h
-@@ -150,8 +150,13 @@ struct dasd_eckd_characteristics {
- typedef enum format_mode_t {
- FULL, /* default mode */
- QUICK, /* format only the first 2 tracks */
-+ EXPAND, /* search for unformatted area and format only that part*/
- } format_mode_t;
-
-+static const char mode_str[3][10] = {
-+ "Full", "Quick", "Expand"
-+};
-+
- /*
- * struct format_data_t
- * represents all data necessary to format a dasd
diff --git a/s390-tools-sles12sp3-dbginfo-01-libutil-Add-utility-functions.patch b/s390-tools-sles12sp3-dbginfo-01-libutil-Add-utility-functions.patch
deleted file mode 100644
index 5fed129..0000000
--- a/s390-tools-sles12sp3-dbginfo-01-libutil-Add-utility-functions.patch
+++ /dev/null
@@ -1,1053 +0,0 @@
-Subject: [PATCH] [FEAT RTL1601] libutil: Add utility functions
-From: Peter Oberparleiter
-
-Summary: libutil: Add utility functions
-Description: Introduce utility functions for use by s390-tools.
-Upstream-ID: -
-Problem-ID: RTL1601
-
-Signed-off-by: Peter Oberparleiter
----
- include/util_base.h | 2
- include/util_libc.h | 125 +++++++++++++++++++
- include/util_opt.h | 82 ++++++++++++
- include/util_panic.h | 45 ++++++
- include/util_prg.h | 55 ++++++++
- libutil/Makefile | 11 +
- libutil/util_libc.c | 155 +++++++++++++++++++++++
- libutil/util_opt.c | 281 +++++++++++++++++++++++++++++++++++++++++++
- libutil/util_panic.c | 119 ++++++++++++++++++
- libutil/util_prg.c | 111 ++++++++++++++++
- 10 files changed, 985 insertions(+), 1 deletion(-)
-
---- a/include/util_base.h
-+++ b/include/util_base.h
-@@ -15,4 +15,6 @@ void util_hexdump(FILE *fh, const char *
- void util_hexdump_grp(FILE *fh, const char *tag, const void *data, int group,
- int cnt, int indent);
-
-+#define UTIL_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
-+
- #endif /* UTIL_BASE_H */
---- /dev/null
-+++ b/include/util_libc.h
-@@ -0,0 +1,125 @@
-+/**
-+ * @defgroup util_libc_h util_libc: Libc wrapper interface
-+ * @{
-+ * @brief Handle standard errors for libc functions
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#ifndef UTIL_LIBC_H
-+#define UTIL_LIBC_H
-+
-+#include
-+
-+/**
-+ * Allocate memory or panic in case of failure
-+ *
-+ * @param[in] size Number of bytes to be allocated
-+ *
-+ * @returns Pointer to allocated memory buffer
-+ */
-+#define util_malloc(size) \
-+ __util_malloc(__func__, __FILE__, __LINE__, size)
-+
-+void *__util_malloc(const char *func, const char *file, int line, size_t size);
-+
-+/**
-+ * Allocate zero-initialized memory or panic in case of failure
-+ *
-+ * @param[in] size Number of bytes to be allocated
-+ *
-+ * @returns Pointer to allocated memory buffer initialized with zeroes
-+ */
-+#define util_zalloc(size) \
-+ __util_zalloc(__func__, __FILE__, __LINE__, size)
-+
-+void *__util_zalloc(const char *func, const char *file, int line, size_t size);
-+
-+
-+/**
-+ * Re-allocate memory or exit in case of failure
-+ *
-+ * @param[in] ptr Pointer ot old memory buffer
-+ * @param[in] size Number of bytes to be allocated
-+ *
-+ * @returns Pointer to allocated memory buffer
-+ */
-+#define util_realloc(ptr, size) \
-+ __util_realloc(__func__, __FILE__, __LINE__, ptr, size)
-+
-+void *__util_realloc(const char *func, const char *file, int line,
-+ void *ptr, size_t size);
-+
-+/**
-+ * Duplicate a string buffer or exit in case of failure
-+ *
-+ * @param[in] str String to be duplicated
-+ *
-+ * @returns Pointer to newly allocated and copied string
-+ */
-+#define util_strdup(str) \
-+ __util_strdup(__func__, __FILE__, __LINE__, str)
-+
-+void *__util_strdup(const char *func, const char *file, int line,
-+ const char *str);
-+
-+/**
-+ * Print to allocated string or exit in case of failure
-+ *
-+ * @param[in] strp String to be allocated
-+ * @param[in] fmt Format string for generation of string
-+ * @param[in] ap Parameters for format string
-+ *
-+ * @returns num Number of formatted characters
-+ */
-+#define util_vasprintf(strp, fmt, ap) \
-+ __util_vasprintf(__func__, __FILE__, __LINE__, strp, fmt, ap)
-+
-+#define UTIL_VASPRINTF(strp, fmt, ap) \
-+do { \
-+ va_start(ap, fmt); \
-+ util_vasprintf(strp, fmt, ap); \
-+ va_end(ap); \
-+} while (0)
-+
-+int __util_vasprintf(const char *func, const char *file, int line,
-+ char **strp, const char *fmt, va_list ap);
-+
-+/**
-+ * Print to newly allocated string or exit in case of failure
-+ *
-+ * @param[in] strp String to be allocated
-+ * @param[in] ... Format string and parameters for format string
-+ *
-+ * @returns num Number of formatted characters
-+ */
-+#define util_asprintf(strp, ...) \
-+ __util_asprintf(__func__, __FILE__, __LINE__, strp, ##__VA_ARGS__)
-+
-+int __util_asprintf(const char *func, const char *file, int line,
-+ char **strp, const char *fmt, ...);
-+
-+
-+/**
-+ * Print to string buffer or exit in case of failure
-+ *
-+ * @param[in] str String buffer
-+ * @param[in] fmt Format string for generation of string
-+ * @param[in] ap Parameters for format string
-+ *
-+ * @returns num Number of formatted characters
-+ */
-+#define util_vsprintf(str, fmt, ap) \
-+ __util_vsprintf(__func__, __FILE__, __LINE__, str, fmt, ap)
-+
-+#define UTIL_VSPRINTF(str, fmt, ap) \
-+do { \
-+ va_start(ap, fmt); \
-+ util_vsprintf(str, fmt, ap); \
-+ va_end(ap); \
-+} while (0)
-+
-+int __util_vsprintf(const char *func, const char *file, int line,
-+ char *str, const char *fmt, va_list ap);
-+
-+#endif /** UTIL_LIBC_H @} */
---- /dev/null
-+++ b/include/util_opt.h
-@@ -0,0 +1,82 @@
-+/**
-+ * @defgroup util_opt_h util_opt: Command line options interface
-+ * @{
-+ * @brief Parse the command line options
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#ifndef UTIL_OPT_H
-+#define UTIL_OPT_H
-+
-+#include
-+#include
-+
-+/* Flag indicating that an option does not have a short form */
-+#define UTIL_OPT_FLAG_NOSHORT 1
-+
-+/* Flag indicating that an option does not have a long form */
-+#define UTIL_OPT_FLAG_NOLONG 2
-+
-+/* Flag indicating that this is a section heading */
-+#define UTIL_OPT_FLAG_SECTION 4
-+
-+/**
-+ * Command line option
-+ */
-+struct util_opt {
-+ /** Defined by getopt.h, see "man getopt_long" */
-+ struct option option;
-+ /** For options with arguments: Argument name */
-+ char *argument;
-+ /** Description displayed for --help */
-+ char *desc;
-+ /** Flags for this option */
-+ int flags;
-+};
-+
-+/**
-+ * Standard option: --help
-+ */
-+#define UTIL_OPT_HELP \
-+{ \
-+ .option = { "help", 0, NULL, 'h' }, \
-+ .desc = "Print this help, then exit", \
-+}
-+
-+/**
-+ * Standard option: --version
-+ */
-+#define UTIL_OPT_VERSION \
-+{ \
-+ .option = { "version", 0, NULL, 'v' }, \
-+ .desc = "Print version information, then exit", \
-+}
-+
-+/**
-+ * End-marker for the option pointer vector
-+ */
-+#define UTIL_OPT_END \
-+{ \
-+ .option = { NULL, 0, NULL, 0 }, \
-+}
-+
-+/**
-+ * Section header
-+ */
-+#define UTIL_OPT_SECTION(title) \
-+{ \
-+ .desc = (title), \
-+ .flags = UTIL_OPT_FLAG_SECTION, \
-+}
-+
-+/*
-+ * Option functions
-+ */
-+void util_opt_init(struct util_opt *opt_vec, const char *opt_prefix);
-+int util_opt_getopt_long(int argc, char *argv[]);
-+void util_opt_print_help(void);
-+void util_opt_print_indented(const char *opt, const char *desc);
-+void util_opt_print_parse_error(char opt, char *argv[]);
-+
-+#endif /** UTIL_OPT_H @} */
---- /dev/null
-+++ b/include/util_panic.h
-@@ -0,0 +1,45 @@
-+/**
-+ * @defgroup util_panic_h util_panic: Panic interface
-+ * @{
-+ * @brief Collect FFDC data for unexpected errors
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#ifndef UTIL_PANIC_H
-+#define UTIL_PANIC_H
-+
-+#include "zt_common.h"
-+
-+#ifndef __noreturn
-+#define __noreturn
-+#endif
-+
-+/**
-+ * Write message, print backtrace and then call the abort() function
-+ *
-+ * @param[in] ... Format string and parameters describing the panic reason
-+ */
-+#define util_panic(...) \
-+ __util_panic(__func__, __FILE__, __LINE__, ##__VA_ARGS__)
-+
-+void __util_panic(const char *func, const char *file, int line,
-+ const char *fmt, ...) __noreturn;
-+
-+/**
-+ * Ensure that assumption is not true, otherwise panic
-+ *
-+ * Example: util_assert(ptr == NULL, "The ptr must be NULL, but is %p", ptr)
-+ *
-+ * @param[in] assumption This assumption has to be true
-+ * @param[in] ... Format string and parameters describing the assumption
-+ */
-+#define util_assert(assumption, ...) \
-+ __util_assert(#assumption, __func__, __FILE__, __LINE__, \
-+ assumption, ##__VA_ARGS__)
-+
-+void __util_assert(const char *assertion_string,
-+ const char *func, const char *file, int line,
-+ int assumption, const char *fmt, ...);
-+
-+#endif /** UTIL_PANIC_H @} */
---- /dev/null
-+++ b/include/util_prg.h
-@@ -0,0 +1,55 @@
-+/**
-+ * @defgroup util_prg_h util_prg: Program interface
-+ * @{
-+ * @brief Print standard program messages
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#ifndef UTIL_PRG_H
-+#define UTIL_PRG_H
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+/**
-+ * Copyright description
-+ */
-+struct util_prg_copyright {
-+ /** Name of the copyright owner, e.g. IBM */
-+ const char *owner;
-+ /** Year of first publishing */
-+ int pub_first;
-+ /** Year of last major changes */
-+ int pub_last;
-+};
-+
-+/**
-+ * @brief Coypright end marker
-+ */
-+#define UTIL_PRG_COPYRIGHT_END {NULL, 0, 0}
-+
-+/**
-+ * Program description
-+ */
-+struct util_prg {
-+ /** Description for help */
-+ const char *desc;
-+ /** Positional arguments */
-+ const char *args;
-+ /** Copyright list */
-+ struct util_prg_copyright copyright_vec[];
-+};
-+
-+void util_prg_init(const struct util_prg *prg);
-+void util_prg_print_parse_error(void);
-+void util_prg_print_required_arg(const char *option);
-+void util_prg_print_invalid_option(const char *option);
-+void util_prg_print_arg_error(const char *arg_name);
-+void util_prg_print_version(void);
-+void util_prg_print_help(void);
-+
-+#endif /** UTIL_PRG_H @} */
---- a/libutil/Makefile
-+++ b/libutil/Makefile
-@@ -2,12 +2,21 @@ include ../common.mak
-
- CPPFLAGS += -I../include
-
--all: util_base.o util_list.o util_part.o util_proc.o
-+all: util_base.o util_list.o util_part.o util_proc.o util_libc.o util_opt.o \
-+ util_panic.o util_prg.o
-
- util_list.o: util_list.c ../include/util.h
-
- util_proc.o: util_proc.c ../include/util_proc.h
-
-+util_libc.o: util_libc.c ../include/util_libc.h
-+
-+util_opt.o: util_opt.c ../include/util_opt.h
-+
-+util_panic.o: util_panic.c ../include/util_panic.h
-+
-+util_prg.o: util_prg.c ../include/util_prg.h
-+
- install: all
-
- clean:
---- /dev/null
-+++ b/libutil/util_libc.c
-@@ -0,0 +1,155 @@
-+/*
-+ * util - Utility function library
-+ *
-+ * Handle standard errors for libc functions
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#define _GNU_SOURCE /* for program_invocation_short_name */
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include "util_base.h"
-+#include "util_panic.h"
-+#include "util_libc.h"
-+
-+/*
-+ * Return size as string of largest unit, e.g. 1025 = "1 KiB"
-+ */
-+static void format_size(char *str, size_t size)
-+{
-+ static const char * const unit_vec[] =
-+ {"byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"};
-+ unsigned int i;
-+
-+ for (i = 0; i < UTIL_ARRAY_SIZE(unit_vec); i++) {
-+ if (size / 1024 == 0) {
-+ sprintf(str, "%zu %s", size, unit_vec[i]);
-+ return;
-+ }
-+ size /= 1024;
-+ }
-+ sprintf(str, "huge");
-+}
-+
-+static void __util_oom(const char *func, const char *file, int line,
-+ size_t size)
-+{
-+ char size_str[256];
-+
-+ fprintf(stderr, "%s: Failed to allocate memory",
-+ program_invocation_short_name);
-+ if (size > 0) {
-+ format_size(size_str, size);
-+ fprintf(stderr, " (%s)", size_str);
-+ }
-+ fprintf(stderr, " at %s:%d %s()\n", file, line, func);
-+ exit(EXIT_FAILURE);
-+}
-+
-+/*
-+ * Allocate memory or exit in case of failure
-+ */
-+void *__util_malloc(const char *func, const char *file, int line, size_t size)
-+{
-+ void *buf;
-+
-+ buf = malloc(size);
-+
-+ if (buf == NULL)
-+ __util_oom(func, file, line, size);
-+
-+ return buf;
-+}
-+
-+/*
-+ * Allocate zero-initialized memory or exit in case of failure
-+ */
-+void *__util_zalloc(const char *func, const char *file, int line, size_t size)
-+{
-+ void *buf = __util_malloc(func, file, line, size);
-+
-+ memset(buf, 0, size);
-+
-+ return buf;
-+}
-+
-+/*
-+ * Re-allocate memory or exit in case of failure
-+ */
-+void *__util_realloc(const char *func, const char *file, int line,
-+ void *ptr, size_t size)
-+{
-+ void *buf;
-+
-+ buf = realloc(ptr, size);
-+
-+ if (buf == NULL)
-+ __util_oom(func, file, line, size);
-+
-+ return buf;
-+}
-+
-+/*
-+ * Duplicate a string buffer or exit in case of failure
-+ */
-+void *__util_strdup(const char *func, const char *file, int line,
-+ const char *str)
-+{
-+ void *buf = strdup(str);
-+
-+ if (buf == NULL)
-+ __util_oom(func, file, line, strlen(str) + 1);
-+
-+ return buf;
-+}
-+
-+/*
-+ * Print to newly allocated string or exit in case of failure
-+ */
-+int __util_vasprintf(const char *func, const char *file, int line,
-+ char **strp, const char *fmt, va_list ap)
-+{
-+ int rc;
-+
-+ rc = vasprintf(strp, fmt, ap);
-+ if (rc == -1)
-+ __util_oom(func, file, line, 0);
-+
-+ return rc;
-+}
-+
-+/*
-+ * Print to newly allocated string or exit in case of failure
-+ */
-+int __util_asprintf(const char *func, const char *file, int line,
-+ char **strp, const char *fmt, ...)
-+{
-+ va_list ap;
-+ int rc;
-+
-+ va_start(ap, fmt);
-+ rc = __util_vasprintf(func, file, line, strp, fmt, ap);
-+ va_end(ap);
-+ return rc;
-+}
-+
-+/*
-+ * Print to string buffer or exit in case of failure
-+ */
-+int __util_vsprintf(const char *func, const char *file, int line,
-+ char *str, const char *fmt, va_list ap)
-+{
-+ int rc;
-+
-+ rc = vsprintf(str, fmt, ap);
-+ if (rc == -1)
-+ __util_assert("rc != -1", func, file, line,
-+ rc != -1, "Could not format string\n");
-+ return rc;
-+}
---- /dev/null
-+++ b/libutil/util_opt.c
-@@ -0,0 +1,281 @@
-+/*
-+ * util - Utility function library
-+ *
-+ * Parse the command line options
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include "util_base.h"
-+#include "util_libc.h"
-+#include "util_opt.h"
-+#include "util_panic.h"
-+#include "util_prg.h"
-+
-+/*
-+ * Private data
-+ */
-+/// @cond
-+static struct util_opt_l {
-+ /* Option character string for getopt_long() */
-+ char *opt_str;
-+ /* Option array for getopt_long() */
-+ struct option *option_vec;
-+ /* Original util_opt array */
-+ struct util_opt *opt_vec;
-+ /* Length of longest option string */
-+ int opt_max;
-+} l;
-+
-+struct util_opt_l *util_opt_l = &l;
-+/// @endcond
-+
-+#define util_opt_iterate(opt) \
-+ for (opt = &l.opt_vec[0]; opt->desc != NULL; opt++)
-+
-+#define MAX(x, y) ((x) < (y) ? (y) : (x))
-+#define MAX_OPTLEN 256
-+
-+static int opt_max_len(void);
-+
-+/**
-+ * Initialize the command line options
-+ *
-+ * Build short option string and long option array to be used for getopt_long().
-+ * The ":" prefix is added to the short option string for handling of "missing
-+ * required arguments".
-+ *
-+ * @param[in] opt_vec Option array
-+ * @param[in] opt_prefix Optional option string prefix
-+ */
-+void util_opt_init(struct util_opt *opt_vec, const char *opt_prefix)
-+{
-+ int i, j, count;
-+ char *str;
-+ size_t prefix_len = opt_prefix ? strlen(opt_prefix) : 0;
-+
-+ opterr = 0;
-+ /* Get number of options */
-+ for (count = 0; opt_vec[count].desc != NULL; count++);
-+ /*
-+ * Allocate short option string for worst case when all options have
-+ * optional parameters e.g "x::" and long option string.
-+ */
-+ l.opt_str = util_malloc(sizeof(char) * count * 3 + 2 + prefix_len);
-+ l.option_vec = util_malloc(sizeof(struct option) * (count + 1));
-+ l.opt_vec = opt_vec;
-+
-+ str = l.opt_str;
-+ if (opt_prefix) {
-+ strcpy(str, opt_prefix);
-+ str += prefix_len;
-+ }
-+ /* Force getopt_long() to return ':' for missing required arguments */
-+ *str++ = ':';
-+ /* Construction of input structures for getopt_long() function. */
-+ for (i = 0, j = 0; i < count; i++) {
-+ if (opt_vec[i].flags & UTIL_OPT_FLAG_SECTION)
-+ continue;
-+ memcpy(&l.option_vec[j++], &opt_vec[i].option,
-+ sizeof(struct option));
-+ if (opt_vec[i].flags & UTIL_OPT_FLAG_NOSHORT)
-+ continue;
-+ *str++ = opt_vec[i].option.val;
-+ switch (opt_vec[i].option.has_arg) {
-+ case no_argument:
-+ break;
-+ case required_argument:
-+ *str++ = ':';
-+ break;
-+ case optional_argument:
-+ *str++ = ':';
-+ *str++ = ':';
-+ break;
-+ default:
-+ util_panic("Unexpected \"has_arg\" parameter: %d\n",
-+ opt_vec[i].option.has_arg);
-+ }
-+ }
-+ /* Add end marker to option array and short option string */
-+ memset(&l.option_vec[j], 0, sizeof(struct option));
-+ *str = '\0';
-+
-+ l.opt_max = opt_max_len();
-+}
-+
-+/**
-+ * Wrapper for getopt_long
-+ *
-+ * @param[in] argc Count of command line parameters
-+ * @param[in] argv Array of command line parameters
-+ */
-+int util_opt_getopt_long(int argc, char *argv[])
-+{
-+ return getopt_long(argc, argv, l.opt_str, l.option_vec, NULL);
-+}
-+
-+/*
-+ * Format option name: Add short, long option and argument (as applicable)
-+ */
-+static void format_opt(char *buf, size_t maxlen, const struct util_opt *opt)
-+{
-+ int has_arg, flags, rc;
-+ char val, *arg_str;
-+ const char *name;
-+
-+ has_arg = opt->option.has_arg;
-+ name = opt->option.name;
-+ val = opt->option.val;
-+ flags = opt->flags;
-+
-+ /* Prepare potential option argument string */
-+ if (has_arg == optional_argument) {
-+ if (flags & UTIL_OPT_FLAG_NOLONG)
-+ util_asprintf(&arg_str, "[%s]", opt->argument);
-+ else
-+ util_asprintf(&arg_str, "[=%s]", opt->argument);
-+ } else if (has_arg == required_argument) {
-+ util_asprintf(&arg_str, " %s", opt->argument);
-+ } else {
-+ util_asprintf(&arg_str, "");
-+ }
-+
-+ /* Format the option */
-+ if (flags & UTIL_OPT_FLAG_NOLONG)
-+ rc = snprintf(buf, maxlen, "-%c%s", val, arg_str);
-+ else if (flags & UTIL_OPT_FLAG_NOSHORT)
-+ rc = snprintf(buf, maxlen, " --%s%s", name, arg_str);
-+ else
-+ rc = snprintf(buf, maxlen, "-%c, --%s%s", val, name, arg_str);
-+
-+ util_assert(rc < (int)maxlen, "Option too long: %s\n", name);
-+ free(arg_str);
-+}
-+
-+/*
-+ * Return size of the longest formatted option
-+ */
-+static int opt_max_len(void)
-+{
-+ const struct util_opt *opt;
-+ unsigned int max = 0;
-+ char opt_str[MAX_OPTLEN];
-+
-+ util_opt_iterate(opt) {
-+ if (opt->flags & UTIL_OPT_FLAG_SECTION)
-+ continue;
-+ format_opt(opt_str, MAX_OPTLEN, opt);
-+ max = MAX(max, strlen(opt_str));
-+ }
-+ return max;
-+}
-+
-+/*
-+ * Print option description with indentation
-+ */
-+static void print_opt_description(const char *desc_in, int indent)
-+{
-+ char *word, *line, *desc, *desc_ptr;
-+ int word_len, pos = indent;
-+
-+ desc = desc_ptr = util_strdup(desc_in);
-+ line = strsep(&desc, "\n");
-+ while (line) {
-+ word = strsep(&line, " ");
-+ pos = indent;
-+ while (word) {
-+ word_len = strlen(word);
-+ if (pos + word_len + 1 > 80) {
-+ printf("\n%*s", indent, " ");
-+ pos = indent;
-+ }
-+ printf(" %s", word);
-+ pos += word_len + 1;
-+ word = strsep(&line, " ");
-+ }
-+ if (desc)
-+ printf("\n%*s", indent, " ");
-+ line = strsep(&desc, "\n");
-+ }
-+ printf("\n");
-+ free(desc_ptr);
-+}
-+
-+/**
-+ * Print an option name, followed by a description indented to fit the
-+ * longest option name
-+ */
-+void util_opt_print_indented(const char *opt, const char *desc)
-+{
-+ printf(" %-*s ", l.opt_max, opt);
-+ print_opt_description(desc, 2 + l.opt_max);
-+}
-+
-+/**
-+ * Print the usage of the command line options to the console
-+ */
-+void util_opt_print_help(void)
-+{
-+ char opt_str[MAX_OPTLEN];
-+ struct util_opt *opt;
-+ int first = 1;
-+
-+ /*
-+ * Create format string: " -%c, --%-s %s"
-+ *
-+ * Example:
-+ *
-+ * -p, --print STRING Print STRING to console
-+ */
-+ util_opt_iterate(opt) {
-+ if (opt->flags & UTIL_OPT_FLAG_SECTION) {
-+ printf("%s%s\n", first ? "" : "\n", opt->desc);
-+ first = 0;
-+ continue;
-+ }
-+ format_opt(opt_str, MAX_OPTLEN, opt);
-+ util_opt_print_indented(opt_str, opt->desc);
-+ }
-+}
-+
-+/**
-+ * Print option parsing error message
-+ *
-+ * This function should be used when the return code of the
-+ * util_opt_getopt_long() function returns a character that does
-+ * not match any of the expected options.
-+ *
-+ * @param[in] opt Short option returned by getopt_long()
-+ * @param[in] argv Option array
-+ */
-+void util_opt_print_parse_error(char opt, char *argv[])
-+{
-+ char optopt_str[3];
-+
-+ switch (opt) {
-+ case ':':
-+ /* A required option argument has not been specified */
-+ util_prg_print_required_arg(argv[optind - 1]);
-+ break;
-+ case '?':
-+ /* An invalid option has been specified */
-+ if (optopt) {
-+ /* Short option */
-+ sprintf(optopt_str, "-%c", optopt);
-+ util_prg_print_invalid_option(optopt_str);
-+ } else {
-+ /* Long option */
-+ util_prg_print_invalid_option(argv[optind - 1]);
-+ }
-+ break;
-+ default:
-+ util_panic("Option '%c' should not be handled here\n", opt);
-+ }
-+}
-+
---- /dev/null
-+++ b/libutil/util_panic.c
-@@ -0,0 +1,119 @@
-+/*
-+ * util - Utility function library
-+ *
-+ * Collect FFDC data for unexpected errors
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#include
-+#include
-+
-+#include
-+#include
-+#include
-+#include
-+
-+#include "util_base.h"
-+#include "util_panic.h"
-+
-+/*
-+ * Obtain a backtrace and print it to stderr
-+ *
-+ * To get symbols, compile the code with "-rdynamic".
-+ */
-+static void print_backtrace(void)
-+{
-+ void *array[256];
-+ size_t i, size;
-+ char **strings;
-+
-+ fprintf(stderr, "Backtrace:\n\n");
-+ size = backtrace(array, UTIL_ARRAY_SIZE(array));
-+ strings = backtrace_symbols(array, size);
-+ if (strings == NULL) {
-+ fprintf(stderr, " Could not obtain backtrace (ENOMEM)\n");
-+ return;
-+ }
-+ for (i = 0; i < size; i++)
-+ fprintf(stderr, " %s\n", strings[i]);
-+
-+ free(strings);
-+}
-+
-+/*
-+ * Check for core ulimit
-+ */
-+static void ulimit_core_check(void)
-+{
-+ struct rlimit limit;
-+
-+ if (getrlimit(RLIMIT_CORE, &limit) != 0)
-+ return;
-+ if (limit.rlim_cur != 0)
-+ return;
-+ fprintf(stderr, "Core dump size is zero. To get a full core dump use 'ulimit -c unlimited'.\n");
-+}
-+
-+/*
-+ * Print FFDC data and then abort
-+ */
-+static void panic_finish(const char *func, const char *file, int line,
-+ const char *fmt, va_list ap)
-+{
-+ /* Write panic error string */
-+ fprintf(stderr, "\n");
-+ fprintf(stderr, "Error string:\n");
-+ fprintf(stderr, "\n");
-+ fprintf(stderr, " ");
-+ vfprintf(stderr, fmt, ap);
-+ fprintf(stderr, "\n");
-+ /* Write file, line number, and function name */
-+ fprintf(stderr, "Location:\n\n");
-+ fprintf(stderr, " %s:%d: %s()\n", file, line, func);
-+ fprintf(stderr, "\n");
-+
-+ /* Print the function backtrace */
-+ print_backtrace();
-+ fprintf(stderr, "\n");
-+
-+ ulimit_core_check();
-+ fprintf(stderr, "----------------------------------------------------------------------->8-----\n");
-+ abort();
-+}
-+
-+/*
-+ * Do panic processing if the assumption is not true
-+ */
-+void __util_assert(const char *assertion_str,
-+ const char *func, const char *file, int line,
-+ int assumption, const char *fmt, ...)
-+{
-+ va_list ap;
-+
-+ if (assumption)
-+ return;
-+ va_start(ap, fmt);
-+ fprintf(stderr, "---8<-------------------------------------------------------------------------\n");
-+ fprintf(stderr, "ASSERTION FAILED: The application terminated due to an internal or OS error\n");
-+ fprintf(stderr, "\n");
-+ fprintf(stderr, "The following assumption was *not* true:\n");
-+ fprintf(stderr, "\n");
-+ fprintf(stderr, " %s\n", assertion_str);
-+ panic_finish(func, file, line, fmt, ap);
-+}
-+
-+/*
-+ * Do panic processing
-+ */
-+void __util_panic(const char *func, const char *file, int line,
-+ const char *fmt, ...)
-+{
-+ va_list ap;
-+
-+ va_start(ap, fmt);
-+ fprintf(stderr, "---8<-------------------------------------------------------------------------\n");
-+ fprintf(stderr, "PANIC: The application terminated due to an unrecoverable error\n");
-+ panic_finish(func, file, line, fmt, ap);
-+ while(1);
-+}
---- /dev/null
-+++ b/libutil/util_prg.c
-@@ -0,0 +1,111 @@
-+/*
-+ * util - Utility function library
-+ *
-+ * Print standard program messages
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#define _GNU_SOURCE /* for program_invocation_short_name */
-+
-+#include
-+#include
-+
-+#include "util_prg.h"
-+#include "zt_common.h"
-+
-+/*
-+ * Private data
-+ */
-+static struct util_prg_l {
-+ const struct util_prg *prg;
-+} l;
-+
-+struct util_prg_l *util_prg_l = &l;
-+
-+/**
-+ * Print program usage information for the --help option
-+ */
-+void util_prg_print_help(void)
-+{
-+ printf("Usage: %s [OPTIONS]", program_invocation_short_name);
-+ if (l.prg->args)
-+ printf(" %s", l.prg->args);
-+ printf("\n\n%s\n\n", l.prg->desc);
-+}
-+
-+/**
-+ * Print program version information for the --version option
-+ */
-+void util_prg_print_version(void)
-+{
-+ const struct util_prg_copyright *copyright;
-+
-+ printf("%s version %s\n", program_invocation_short_name,
-+ RELEASE_STRING);
-+ copyright = l.prg->copyright_vec;
-+ while (copyright->owner) {
-+ if (copyright->pub_first == copyright->pub_last)
-+ printf("Copyright %s %d\n", copyright->owner,
-+ copyright->pub_first);
-+ else
-+ printf("Copyright %s %d, %d\n", copyright->owner,
-+ copyright->pub_first, copyright->pub_last);
-+ copyright++;
-+ }
-+}
-+
-+/*
-+ * Ask user to use the --help option
-+ */
-+void util_prg_print_parse_error(void)
-+{
-+ fprintf(stderr, "Try '%s --help' for more information.\n",
-+ program_invocation_short_name);
-+}
-+
-+/**
-+ * An option has been specified that is not supported
-+ *
-+ * @param[in] option Option string (short or long)
-+ */
-+void util_prg_print_invalid_option(const char *opt_name)
-+{
-+ fprintf(stderr, "%s: Invalid option '%s'\n",
-+ program_invocation_short_name, opt_name);
-+ util_prg_print_parse_error();
-+}
-+
-+/**
-+ * A required argument for an option is missing
-+ *
-+ * @param[in] option Option string
-+ */
-+void util_prg_print_required_arg(const char *opt_name)
-+{
-+ fprintf(stderr, "%s: Option '%s' requires an argument\n",
-+ program_invocation_short_name, opt_name);
-+ util_prg_print_parse_error();
-+}
-+
-+/**
-+ * A superfluous invalid positional argument has been specified
-+ *
-+ * @param[in] arg_name Name of the invalid argument
-+ */
-+void util_prg_print_arg_error(const char *arg_name)
-+{
-+ fprintf(stderr, "%s: Invalid argument '%s'\n",
-+ program_invocation_short_name, arg_name);
-+ util_prg_print_parse_error();
-+}
-+
-+/**
-+ * Initialize the program module
-+ *
-+ * @param[in] prg Program description
-+ */
-+void util_prg_init(const struct util_prg *prg)
-+{
-+ l.prg = prg;
-+}
diff --git a/s390-tools-sles12sp3-dbginfo-02-dump2tar-Add-sysfs-collection-helper-for-dbginfo.sh-v2.patch b/s390-tools-sles12sp3-dbginfo-02-dump2tar-Add-sysfs-collection-helper-for-dbginfo.sh-v2.patch
deleted file mode 100644
index e0c486d..0000000
--- a/s390-tools-sles12sp3-dbginfo-02-dump2tar-Add-sysfs-collection-helper-for-dbginfo.sh-v2.patch
+++ /dev/null
@@ -1,4687 +0,0 @@
-Subject: [PATCH] [FEAT RTL1601] dump2tar: Add sysfs collection helper for dbginfo.sh
-From: Peter Oberparleiter
-
-Summary: dump2tar: Add sysfs collection helper for dbginfo.sh
-Description: Certain files in virtual filesystems such as sysfs,
- debugfs and procfs do not correctly report their size.
- As a result, tools like tar, cp or rsync cannot be easily
- used to collect these files.
-
- This patch adds a tool to efficiently dump such files
- into a compressed tar archive. It is intended to be used
- by the dbginfo.sh script to significantly speed up data
- collection.
-Upstream-ID: -
-Problem-ID: RTL1601
-
-Changelog:
-
- - v2: Fix compiler warning and missing DESTDIR logic in Makefiles
-
-Signed-off-by: Peter Oberparleiter
----
- Makefile | 2
- README | 5
- dump2tar/Makefile | 12
- dump2tar/include/buffer.h | 47 +
- dump2tar/include/dref.h | 26
- dump2tar/include/dump.h | 60 +
- dump2tar/include/global.h | 20
- dump2tar/include/idcache.h | 23
- dump2tar/include/misc.h | 98 ++
- dump2tar/include/strarray.h | 23
- dump2tar/include/tar.h | 41
- dump2tar/man/Makefile | 12
- dump2tar/man/dump2tar.1 | 454 ++++++++++
- dump2tar/src/Makefile | 36
- dump2tar/src/buffer.c | 271 ++++++
- dump2tar/src/dref.c | 92 ++
- dump2tar/src/dump.c | 1850 ++++++++++++++++++++++++++++++++++++++++++++
- dump2tar/src/dump2tar.c | 474 +++++++++++
- dump2tar/src/global.c | 17
- dump2tar/src/idcache.c | 153 +++
- dump2tar/src/misc.c | 492 +++++++++++
- dump2tar/src/strarray.c | 81 +
- dump2tar/src/tar.c | 270 ++++++
- 23 files changed, 4558 insertions(+), 1 deletion(-)
-
---- a/Makefile
-+++ b/Makefile
-@@ -8,7 +8,7 @@ SUB_DIRS = $(LIB_DIRS) zipl zdump fdasd
- tape390 osasnmpd qetharp ip_watcher qethconf scripts zconf \
- vmconvert vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \
- ziomon iucvterm hyptop cmsfs-fuse qethqoat zfcpdump zdsfs cpumf \
-- systemd hmcdrvfs cpacfstats zdev
-+ systemd hmcdrvfs cpacfstats zdev dump2tar
-
- all: subdirs_make
-
---- a/README
-+++ b/README
-@@ -210,6 +210,11 @@ s390-tools (1.34.0)
- configuration of devices and device drivers which are specific to the s390
- platform.
-
-+ * dump2tar:
-+ dump2tar is a tool for creating a tar archive from the contents of
-+ arbitrary files. It works even when the size of the actual file content
-+ is not known beforehand (e.g. FIFOs, sysfs files).
-+
- For more information refer to the following publications:
- * "Device Drivers, Features, and Commands" chapter "Useful Linux commands"
- * "Using the dump tools"
---- /dev/null
-+++ b/dump2tar/Makefile
-@@ -0,0 +1,12 @@
-+# Common definitions
-+include ../common.mak
-+
-+all:
-+ $(MAKE) -C src
-+
-+install: all
-+ $(MAKE) -C src install
-+ $(MAKE) -C man install
-+
-+clean:
-+ $(MAKE) -C src clean
---- /dev/null
-+++ b/dump2tar/include/buffer.h
-@@ -0,0 +1,47 @@
-+/*
-+ * dump2tar - tool to dump files and command output into a tar archive
-+ *
-+ * Data buffering functions
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#ifndef BUFFER_H
-+#define BUFFER_H
-+
-+#include
-+#include
-+#include
-+
-+/* Buffers for building tar file entries */
-+struct buffer {
-+ size_t total; /* Total number of bytes in buffer */
-+ size_t off; /* Current offset to next free byte in memory buffer */
-+ size_t size; /* Memory buffer size */
-+ char *addr; /* Memory buffer address */
-+ bool fd_open; /* Has fd been openend yet? */
-+ FILE *file; /* FILE * of file containing previous buffer data */
-+ int fd; /* Handle of file containing previous buffer data */
-+};
-+
-+void buffer_init(struct buffer *buffer, size_t size);
-+struct buffer *buffer_alloc(size_t size);
-+void buffer_reset(struct buffer *buffer);
-+void buffer_close(struct buffer *buffer);
-+void buffer_free(struct buffer *buffer, bool dyn);
-+int buffer_open(struct buffer *buffer);
-+int buffer_flush(struct buffer *buffer);
-+ssize_t buffer_make_room(struct buffer *buffer, size_t size, bool usefile,
-+ size_t max_buffer_size);
-+int buffer_truncate(struct buffer *buffer, size_t len);
-+
-+ssize_t buffer_read_fd(struct buffer *buffer, int fd, size_t chunk,
-+ bool usefile, size_t max_buffer_size);
-+int buffer_add_data(struct buffer *buffer, char *addr, size_t len,
-+ bool usefile, size_t max_buffer_size);
-+
-+typedef int (*buffer_cb_t)(void *data, void *addr, size_t len);
-+int buffer_iterate(struct buffer *buffer, buffer_cb_t cb, void *data);
-+void buffer_print(struct buffer *buffer);
-+
-+#endif /* BUFFER_H */
---- /dev/null
-+++ b/dump2tar/include/dref.h
-@@ -0,0 +1,26 @@
-+/*
-+ * dump2tar - tool to dump files and command output into a tar archive
-+ *
-+ * Reference counting for directory handles
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#ifndef DREF_H
-+#define DREF_H
-+
-+#include
-+#include
-+
-+/* Multiple jobs may refer to an open DIR * - need reference counting */
-+struct dref {
-+ DIR *dd;
-+ int dirfd;
-+ unsigned int count;
-+};
-+
-+struct dref *dref_create(const char *dirname);
-+struct dref *dref_get(struct dref *dref);
-+void dref_put(struct dref *dref);
-+
-+#endif /* DREF_H */
---- /dev/null
-+++ b/dump2tar/include/dump.h
-@@ -0,0 +1,60 @@
-+/*
-+ * dump2tar - tool to dump files and command output into a tar archive
-+ *
-+ * Main dump logic
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#ifndef DUMP_H
-+#define DUMP_H
-+
-+#include
-+#include
-+#include
-+
-+#include "strarray.h"
-+
-+#define NUM_EXCLUDE_TYPES 7
-+
-+struct dump_spec {
-+ char *inname;
-+ char *outname;
-+ bool is_cmd;
-+};
-+
-+struct dump_opts {
-+ bool add_cmd_status;
-+ bool append;
-+ bool dereference;
-+ bool exclude_type[NUM_EXCLUDE_TYPES];
-+ bool gzip;
-+ bool ignore_failed_read;
-+ bool no_eof;
-+ bool quiet;
-+ bool recursive;
-+ bool threaded;
-+ bool verbose;
-+ const char *output_file;
-+ int file_timeout;
-+ int timeout;
-+ long jobs;
-+ long jobs_per_cpu;
-+ size_t file_max_size;
-+ size_t max_buffer_size;
-+ size_t max_size;
-+ size_t read_chunk_size;
-+ struct strarray exclude;
-+ struct dump_spec *specs;
-+ unsigned int num_specs;
-+};
-+
-+struct dump_opts *dump_opts_new(void);
-+int dump_opts_set_type_excluded(struct dump_opts *opts, char c);
-+void dump_opts_add_spec(struct dump_opts *opts, char *inname, char *outname,
-+ bool is_cmd);
-+void dump_opts_free(struct dump_opts *opts);
-+
-+int dump_to_tar(struct dump_opts *opts);
-+
-+#endif /* DUMP_H */
---- /dev/null
-+++ b/dump2tar/include/global.h
-@@ -0,0 +1,20 @@
-+/*
-+ * dump2tar - tool to dump files and command output into a tar archive
-+ *
-+ * Global variables
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#ifndef GLOBAL_H
-+#define GLOBAL_H
-+
-+#include
-+
-+extern bool global_threaded;
-+extern bool global_debug;
-+extern bool global_verbose;
-+extern bool global_quiet;
-+extern bool global_timestamps;
-+
-+#endif /* GLOBAL_H */
---- /dev/null
-+++ b/dump2tar/include/idcache.h
-@@ -0,0 +1,23 @@
-+/*
-+ * dump2tar - tool to dump files and command output into a tar archive
-+ *
-+ * Caches for user and group ID lookups
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#ifndef IDCACHE_H
-+#define IDCACHE_H
-+
-+#include
-+#include
-+
-+/* Buffer sizes for getpwuid_r and getgid_r calls (bytes) */
-+#define PWD_BUFFER_SIZE 4096
-+#define GRP_BUFFER_SIZE 4096
-+
-+void uid_to_name(uid_t uid, char *name, size_t len);
-+void gid_to_name(gid_t gid, char *name, size_t len);
-+void idcache_cleanup(void);
-+
-+#endif /* IDCACHE_H */
---- /dev/null
-+++ b/dump2tar/include/misc.h
-@@ -0,0 +1,98 @@
-+/*
-+ * dump2tar - tool to dump files and command output into a tar archive
-+ *
-+ * Helper functions
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#ifndef MISC_H
-+#define MISC_H
-+
-+#include
-+#include
-+#include
-+#include
-+
-+#include "global.h"
-+
-+#include "util_libc.h"
-+
-+#define MSG_LEN 256
-+
-+#define DBG(...) \
-+ do { \
-+ if (global_debug) \
-+ debug(__FILE__, __LINE__, ##__VA_ARGS__); \
-+ } while (0)
-+
-+#define mwarn(fmt, ...) _mwarn(true, (fmt), ##__VA_ARGS__)
-+#define mwarnx(fmt, ...) _mwarn(false, (fmt), ##__VA_ARGS__)
-+
-+/* Helper macro for constructing messages in variables */
-+#define HANDLE_RC(rc, max, off, label) \
-+ do { \
-+ if ((rc) > 0) \
-+ (off) += (rc); \
-+ if ((off) > (max)) \
-+ goto label; \
-+ } while (0)
-+
-+/* Program exit codes */
-+#define EXIT_OK 0
-+#define EXIT_RUNTIME 1
-+#define EXIT_USAGE 2
-+
-+/* Number of nanoseconds in a second */
-+#define NSEC_PER_SEC 1000000000L
-+#define NSEC_PER_MSEC 1000000L
-+#define NSEC_PER_USEC 1000L
-+
-+extern struct timespec main_start_ts;
-+struct dref;
-+
-+int misc_write_data(int fd, char *addr, size_t len);
-+ssize_t misc_read_data(int fd, char *addr, size_t len);
-+void inc_timespec(struct timespec *ts, time_t sec, long nsec);
-+void set_timespec(struct timespec *ts, time_t sec, long nsec);
-+bool ts_before(struct timespec *a, struct timespec *b);
-+int snprintf_duration(char *buff, size_t len, struct timespec *start,
-+ struct timespec *end);
-+char *get_threadname(void);
-+void debug(const char *file, unsigned long line, const char *format, ...);
-+void _mwarn(bool print_errno, const char *format, ...);
-+void verb(const char *format, ...);
-+void info(const char *format, ...);
-+#define mmalloc(len) util_zalloc(len)
-+#define mcalloc(n, len) util_zalloc((n) * (len))
-+#define mrealloc(ptr, len) util_realloc((ptr), (len))
-+#define mstrdup(str) util_strdup(str)
-+#define masprintf(fmt, ...) __masprintf(__func__, __FILE__, __LINE__, \
-+ (fmt), ##__VA_ARGS__)
-+char *__masprintf(const char *func, const char *file, int line,
-+ const char *fmt, ...);
-+#define set_threadname(fmt, ...) __set_threadname(__func__, __FILE__, \
-+ __LINE__, (fmt), \
-+ ##__VA_ARGS__)
-+void __set_threadname(const char *func, const char *file, int line,
-+ const char *fmt, ...);
-+
-+void clear_threadname(void);
-+void chomp(char *str, char *c);
-+void lchomp(char *str, char *c);
-+void remove_double_slashes(char *str);
-+int stat_file(bool dereference, const char *abs, const char *rel,
-+ struct dref *dref, struct stat *st);
-+void set_dummy_stat(struct stat *st);
-+bool starts_with(const char *str, const char *prefix);
-+bool ends_with(const char *str, const char *suffix);
-+
-+int cmd_child(int fd, char *cmd);
-+int cmd_open(char *cmd, pid_t *pid_ptr);
-+int cmd_close(int fd, pid_t pid, int *status_ptr);
-+
-+void misc_init(void);
-+void misc_cleanup(void);
-+void set_stdout_data(void);
-+
-+#endif /* MISC_H */
---- /dev/null
-+++ b/dump2tar/include/strarray.h
-@@ -0,0 +1,23 @@
-+/*
-+ * dump2tar - tool to dump files and command output into a tar archive
-+ *
-+ * Dynamically growing string arrays
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#ifndef STRARRAY_H
-+#define STRARRAY_H
-+
-+/* A string array that can grow in size */
-+struct strarray {
-+ unsigned int num;
-+ char **str;
-+};
-+
-+void free_strarray(struct strarray *array);
-+void add_str_to_strarray(struct strarray *array, const char *str);
-+void add_vstr_to_strarray(struct strarray *array, const char *fmt, ...);
-+int add_file_to_strarray(struct strarray *array, const char *filename);
-+
-+#endif /* STRARRAY_H */
---- /dev/null
-+++ b/dump2tar/include/tar.h
-@@ -0,0 +1,41 @@
-+/*
-+ * dump2tar - tool to dump files and command output into a tar archive
-+ *
-+ * TAR file generation
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#ifndef TAR_H
-+#define TAR_H
-+
-+#include
-+#include
-+#include
-+
-+#define TYPE_REGULAR '0'
-+#define TYPE_LINK '2'
-+#define TYPE_DIR '5'
-+
-+#define TAR_BLOCKSIZE 512
-+
-+struct buffer;
-+
-+/* emit_cb_t - Callback used for emitting chunks of a byte stream
-+ * @data: Arbitrary pointer passed via the @data parameter of the
-+ * tar_emit_file_* functions
-+ * @addr: Pointer to data
-+ * @len: Size of data
-+ * Return %0 on success. Returning non-zero will indicate failure and abort
-+ * further data emission. */
-+typedef int (*emit_cb_t)(void *data, void *addr, size_t len);
-+
-+int tar_emit_file_from_buffer(char *filename, char *link, size_t len,
-+ struct stat *stat, char type,
-+ struct buffer *content, emit_cb_t emit_cb,
-+ void *data);
-+int tar_emit_file_from_data(char *filename, char *link, size_t len,
-+ struct stat *stat, char type, void *addr,
-+ emit_cb_t emit_cb, void *data);
-+
-+#endif /* TAR_H */
---- /dev/null
-+++ b/dump2tar/man/Makefile
-@@ -0,0 +1,12 @@
-+# Common definitions
-+include ../../common.mak
-+
-+all:
-+
-+install:
-+ $(INSTALL) -d -m 755 $(DESTDIR)$(MANDIR)/man1
-+ $(INSTALL) -m 644 -c dump2tar.1 $(DESTDIR)$(MANDIR)/man1
-+
-+clean:
-+
-+.PHONY: all clean
---- /dev/null
-+++ b/dump2tar/man/dump2tar.1
-@@ -0,0 +1,454 @@
-+.\" Macro for inserting an option description prologue.
-+.\" .OD [] [args]
-+.de OD
-+. ds args "
-+. if !'\\$3'' .as args \fI\\$3\fP
-+. if !'\\$4'' .as args \\$4
-+. if !'\\$5'' .as args \fI\\$5\fP
-+. if !'\\$6'' .as args \\$6
-+. if !'\\$7'' .as args \fI\\$7\fP
-+. PD 0
-+. if !'\\$2'' .IP "\fB\-\\$2\fP \\*[args]" 4
-+. if !'\\$1'' .IP "\fB\-\-\\$1\fP \\*[args]" 4
-+. PD
-+..
-+.\" Macro for inserting code line.
-+.\" .CL
-+.de CL
-+. ds pfont \\n[.f]
-+. nh
-+. na
-+. ft CW
-+\\$*
-+. ft \\*[pfont]
-+. ad
-+. hy
-+. br
-+..
-+.\" Macro for inserting a man page reference.
-+.\" .MP man-page section [suffix]
-+.de MP
-+. nh
-+. na
-+. BR \\$1 (\\$2)\\$3
-+. ad
-+. hy
-+..
-+.
-+.TH "dump2tar" "1" "2016\-09\-02" "" ""
-+.
-+.SH "NAME"
-+dump2tar - Gather file contents and command output into a tar archive
-+.
-+.
-+.SH "SYNOPSIS"
-+.B "dump2tar "
-+.RI "[" "OPTIONS" "] " "SPECS"
-+.
-+.
-+.SH "DESCRIPTION"
-+.B dump2tar
-+creates a tar archive from the contents of any files, including files of
-+unknown size.
-+
-+Examples for files of unknown size are:
-+.IP \(bu 3
-+Named pipes (FIFOs)
-+.PP
-+.IP \(bu 3
-+Particular Linux kernel debugfs or sysfs files
-+.PP
-+.IP \(bu 3
-+Character or block devices
-+.PP
-+
-+When adding such a file,
-+.B dump2tar
-+first reads all available data until an end-of-file indication is found. From
-+this data, it then creates a regular file entry in the resulting tar archive.
-+By default, symbolic links and directories are preserved in the archive in
-+their original form.
-+
-+.B dump2tar
-+can also:
-+.IP \(bu 3
-+Add files under a different name
-+.PP
-+.IP \(bu 3
-+Run arbitrary commands and add the resulting command output as a
-+regular file
-+.PP
-+.
-+.
-+.SH "FILE SPECIFICATIONS"
-+.
-+This section describes the format of the
-+.I SPECS
-+argument mentioned in the command synopsis.
-+Use the following command line syntax to identify data sources and
-+to specify file names within the archive:
-+.PP
-+
-+.TP
-+.I "PATH"
-+Adds the contents of the file system subtree at file system location
-+.I PATH
-+(with possible exceptions described by options) in the archive under the same
-+file name as on the file system.
-+.PP
-+.
-+.
-+.TP
-+.IR "FILENAME" ":=" "PATH"
-+Adds the contents of the file at file system location
-+.I PATH
-+in the archive under the name specified by
-+.IR FILENAME .
-+.PP
-+.
-+.
-+.TP
-+.IR "FILENAME" "|=" "CMDLINE"
-+Runs the command
-+.IR CMDLINE
-+and captures both the resulting standard output and standard error streams.
-+Adds the collected output as a regular file named
-+.I FILENAME
-+in the resulting archive. You can also include the resulting program exit code
-+by using option \-\-add\-cmd\-status.
-+.PP
-+.
-+You can also specify "\-\-". All specifications that follow are interpreted as
-+simple file names. This is useful for archiving files that contain ":=" or "|=".
-+.PP
-+.
-+.
-+.SH "OUTPUT OPTIONS"
-+.
-+.OD "output\-file" "o" "TARFILE"
-+Writes the resulting tar archive to
-+.IR TARFILE .
-+An existing file at the specified file system location is overwritten.
-+
-+If this option is omitted or if "\-" is specified for
-+.IR TARFILE ,
-+the archive is written to the standard output stream.
-+.PP
-+.
-+.
-+.OD "gzip" "z" ""
-+Compresses the resulting tar archive using gzip.
-+.PP
-+.
-+.
-+.OD "max\-size" "m" "VALUE"
-+Sets an upper size limit, in bytes, for the resulting archive. If this limit
-+is exceeded after adding a file, no further files are added.
-+.PP
-+.
-+.
-+.OD "timeout" "t" "VALUE"
-+Sets an upper time limit, in seconds, for the archiving process. If this limit
-+is exceeded while adding a file, that file is truncated and no
-+further files are added.
-+.PP
-+.
-+.
-+.OD "no-eof" "" ""
-+Does not write an end-of-file marker.
-+
-+Use this option if you want to create an archive that can be extended by
-+appending additional tar archive data.
-+
-+Note: Do not use this option for the final data to be added.
-+A valid tar archive requires a trailing end-of-file marker.
-+.PP
-+.
-+.
-+.OD "append" "" ""
-+Appends data to the end of the archive.
-+
-+Use this option to incrementally build a tar file by repeatedly calling
-+.BR dump2tar .
-+You must specify the \-\-no\-eof option for each but the final call of
-+.BR dump2tar .
-+.PP
-+.
-+.
-+.OD "add-cmd-status" "" ""
-+Adds a separate file named
-+.RI \(dq FILENAME .cmdstatus\(dq
-+for each command output added through the
-+.RI \(dq FILENAME |= CMDLINE \(dq
-+notation (see FILE SPECIFICATIONS).
-+This file contains information about the exit status of the
-+process that executed the command:
-+.
-+.RS 8
-+.TP
-+.RI EXITSTATUS= VALUE
-+Unless
-+.I VALUE
-+is -1, the process ended normally with the specified exit value.
-+.PP
-+.
-+.TP
-+.RI TERMSIG= VALUE
-+Unless
-+.I VALUE
-+is -1, the process was stopped by a signal of the specified number.
-+.PP
-+.
-+.TP
-+.RI WAITPID_ERRNO= VALUE
-+Unless
-+.I VALUE
-+is -1, an attempt to obtain the status of the process failed with the
-+specified error.
-+.PP
-+.RE
-+.
-+.
-+.
-+.SH "INPUT OPTIONS"
-+.
-+.OD "files\-from" "F" "FILENAME"
-+Reads input data specifications (see FILE SPECIFICATIONS) from
-+.IR FILENAME ,
-+one specification per line. Each line contains either a file name or a
-+.IR FILENAME := PATH
-+or
-+.IR FILENAME |= CMDLINE
-+specification. Empty lines are ignored.
-+
-+A line can also consist of only "\-\-". All lines following this specification
-+are interpreted as simple file names. This is useful for archiving files that
-+contain ":=" or "|=".
-+.PP
-+.
-+.
-+.OD "ignore\-failed\-read" "i" ""
-+Continues after read errors.
-+
-+By default,
-+.B dump2tar
-+stops processing after encountering errors while reading an input file.
-+With this option,
-+.B dump2tar
-+prints a warning message and adds an empty entry for the erroneous file in
-+the archive.
-+.PP
-+.
-+.
-+.OD "buffer\-size" "b" "VALUE"
-+Reads data from input files in chunks of
-+.I VALUE
-+bytes. Large values can accelerate the archiving process for large files
-+at the cost of increased memory usage. The default value is 1048576.
-+.PP
-+.
-+.
-+.OD "file\-timeout" "T" "VALUE"
-+Sets an upper time limit, in seconds, for reading an input file.
-+
-+.B dump2tar
-+stops processing a file when the time limit is exceeded. Archive entries for
-+such files are truncated to the amount of data that is collected by the time
-+the limit is reached.
-+.PP
-+.
-+.
-+.OD "file\-max\-size" "M" "N"
-+Sets an upper size limit, in bytes, for an input file.
-+
-+.B dump2tar
-+stops processing a file when the size limit is exceeded. Archive entries for
-+such files are truncated to the specified size.
-+.PP
-+.
-+.
-+.OD "jobs" "j" "N"
-+By default,
-+.B dump2tar
-+processes one file at a time. With this option,
-+.B dump2tar
-+processes
-+.I N
-+files in parallel.
-+
-+Parallel processing can accelerate the archiving process,
-+especially if input files are located on slow devices, or when output from
-+multiple commands is added to the archive.
-+
-+Note: Use
-+.B tar
-+option \-\-delay\-directory\-restore when extracting files from an archive
-+created with \-\-jobs to prevent conflicts with directory permissions and
-+modification times.
-+.PP
-+.
-+.
-+.OD "jobs\-per\-cpu" "J" "N"
-+Processes
-+.I N
-+files for each online CPU in parallel.
-+
-+Parallel processing can accelerate the
-+archiving process, especially if input files are located on slow devices, or
-+when output from multiple commands is added to the archive.
-+
-+Note: Use
-+.B tar
-+option \-\-delay\-directory\-restore when extracting files from an archive
-+created with \-\-jobs\-per\-cpu to prevent conflicts with directory permissions
-+and modification times.
-+.PP
-+.
-+.
-+.OD "exclude" "x" "PATTERN"
-+Does not add files to the archive if their file names match
-+.IR PATTERN .
-+.I PATTERN
-+is an expression that uses the shell wildcards.
-+.PP
-+.
-+.
-+.OD "exclude\-from" "X" "FILENAME"
-+Does not add files to the archive if their names match at least one of the
-+patterns listed in the pattern file with name
-+.IR FILENAME .
-+In the pattern file, each line specifies an expression that uses the
-+shell wildcards.
-+.PP
-+.
-+.
-+.OD "exclude\-type" "" "TYPE"
-+Does not add files to the archive if they match at least one of the file types
-+specified with
-+.IR TYPE .
-+.I TYPE
-+uses one or more of the characters "fdcbpls", where:
-+
-+.RS 8
-+.IP f 3
-+regular files
-+.PP
-+.IP d 3
-+directories
-+.PP
-+.IP c 3
-+character devices
-+.PP
-+.IP b 3
-+block devices
-+.PP
-+.IP p 3
-+named pipes (FIFOs)
-+.PP
-+.IP l 3
-+symbolic links
-+.PP
-+.IP s 3
-+sockets
-+.PP
-+.RE
-+.
-+.PP
-+.
-+.
-+.OD "dereference" "" ""
-+Adds the content of link targets instead of symbolic links.
-+.PP
-+.
-+.
-+.OD "no\-recursion" "" ""
-+Does not add files from sub\-directories.
-+
-+By default,
-+.B dump2tar
-+adds archive entries for specified directories, and for the files within these
-+directories. With this option, a specified directory results in a single entry
-+for the directory. Any contained files to be included must be specified
-+explicitly.
-+.PP
-+.
-+.
-+.SH "MISC OPTIONS"
-+.
-+.OD "help" "h" ""
-+Prints an overview of available options, then exits.
-+.PP
-+.
-+.
-+.OD "verbose" "V" ""
-+Prints additional informational output.
-+.PP
-+.
-+.
-+.OD "quiet" "q" ""
-+Suppresses printing of informational output.
-+.PP
-+.
-+.
-+.
-+.SH "EXAMPLES"
-+.
-+.\fB
-+.CL # dump2tar a b \-o archive.tar
-+.\fR
-+
-+.RS 4
-+Creates a tar archive named archive.tar containing files a and b.
-+.RE
-+.PP
-+.
-+.\fB
-+.CL # dump2tar /proc \-o procdump.tar.gz \-z \-i \-T 1 \-M 1048576
-+.\fR
-+
-+.RS 4
-+Creates a gzip compressed tar archive named procdump.tar.gz that contains
-+all procfs files. Unreadable files are ignored. Files are truncated when the
-+first of the two limiting conditions is reached, either 1048576 bytes of
-+content or the reading time of 1 second.
-+.RE
-+.PP
-+.
-+.\fB
-+.CL # dump2tar '|=dmesg' '|=lspci' \-o data.tar
-+.\fR
-+
-+.RS 4
-+Creates a tar archive named data.tar containing the output of the 'dmesg'
-+and 'lspci' commands.
-+.RE
-+.PP
-+.
-+.\fB
-+.CL # dump2tar /sys/kernel/debug/ -x '*/tracing/*' -o debug.tar -i
-+.\fR
-+
-+.RS 4
-+Creates a tar archive named debug.tar containing the contents of directory
-+/sys/kernel/debug/ while excluding any file that is located in a sub-directory
-+named 'tracing'.
-+.RE
-+.PP
-+.
-+.
-+.SH "EXIT CODES"
-+.TP
-+.B 0
-+The program finished successfully
-+.TP
-+.B 1
-+A run-time error occurred
-+.TP
-+.B 2
-+The specified command was not valid
-+.PP
-+.
-+.
-+.SH "SEE ALSO"
-+.MP dump2tar 1 ,
-+.MP tar 1
---- /dev/null
-+++ b/dump2tar/src/Makefile
-@@ -0,0 +1,36 @@
-+# Common definitions
-+include ../../common.mak
-+
-+CPPFLAGS += -I ../../include -I../include -std=gnu99 -Wno-unused-parameter
-+LDLIBS += -lpthread -lrt
-+ifneq ($(HAVE_ZLIB),0)
-+CPPFLAGS += -DHAVE_ZLIB
-+LDLIBS += -lz
-+endif
-+
-+core_objects = buffer.o dref.o global.o dump.o idcache.o misc.o strarray.o tar.o
-+libs = $(rootdir)/libutil/util_libc.o $(rootdir)/libutil/util_opt.o \
-+ $(rootdir)/libutil/util_prg.o $(rootdir)/libutil/util_panic.o
-+
-+check_dep_zlib:
-+ $(call check_dep, \
-+ "dump2tar", \
-+ "zlib.h", \
-+ "zlib-devel", \
-+ "HAVE_ZLIB=0")
-+
-+all: check_dep_zlib dump2tar
-+
-+dump2tar: $(core_objects) dump2tar.o $(libs)
-+
-+install: dump2tar
-+ $(INSTALL) -c dump2tar $(DESTDIR)$(USRBINDIR)
-+
-+clean:
-+ @rm -f dump2tar *.o
-+
-+.PHONY: all install clean
-+
-+# Additional manual dependencies
-+../../libutil/%.o:
-+ make -C ../../libutil $<
---- /dev/null
-+++ b/dump2tar/src/buffer.c
-@@ -0,0 +1,271 @@
-+/*
-+ * dump2tar - tool to dump files and command output into a tar archive
-+ *
-+ * Data buffering functions
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#include "buffer.h"
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include "misc.h"
-+
-+void buffer_print(struct buffer *buffer)
-+{
-+ fprintf(stderr, "DEBUG: buffer at %p\n", (void *) buffer);
-+ if (!buffer)
-+ return;
-+ fprintf(stderr, "DEBUG: total=%zu\n", buffer->total);
-+ fprintf(stderr, "DEBUG: off=%zu\n", buffer->off);
-+ fprintf(stderr, "DEBUG: size=%zu\n", buffer->size);
-+ fprintf(stderr, "DEBUG: addr=%p\n", (void *) buffer->addr);
-+ fprintf(stderr, "DEBUG: fd_open=%d\n", buffer->fd_open);
-+ fprintf(stderr, "DEBUG: fd=%d\n", buffer->fd);
-+ if (buffer->fd_open) {
-+ fprintf(stderr, "DEBUG: fd->pos=%zu\n",
-+ lseek(buffer->fd, 0, SEEK_CUR));
-+ }
-+}
-+
-+/* Initialize @buffer to hold @size bytes in memory */
-+void buffer_init(struct buffer *buffer, size_t size)
-+{
-+ memset(buffer, 0, sizeof(struct buffer));
-+ buffer->addr = mmalloc(size);
-+ buffer->size = size;
-+}
-+
-+/* Allocate a new buffer for holding @size bytes in memory */
-+struct buffer *buffer_alloc(size_t size)
-+{
-+ struct buffer *buffer;
-+
-+ buffer = mmalloc(sizeof(struct buffer));
-+ buffer_init(buffer, size);
-+
-+ return buffer;
-+}
-+
-+/* Forget about any data stored in @buffer */
-+void buffer_reset(struct buffer *buffer)
-+{
-+ buffer->total = 0;
-+ buffer->off = 0;
-+ if (buffer->fd_open) {
-+ if (ftruncate(buffer->fd, 0))
-+ mwarn("Cannot truncate temporary file");
-+ if (lseek(buffer->fd, 0, SEEK_SET) == (off_t) -1)
-+ mwarn("Cannot seek in temporary file");
-+ }
-+}
-+
-+/* Close buffer file associated with @buffer */
-+void buffer_close(struct buffer *buffer)
-+{
-+ if (!buffer->fd_open)
-+ return;
-+
-+ fclose(buffer->file);
-+ buffer->fd = 0;
-+ buffer->fd_open = false;
-+}
-+
-+/* Release all resources associated with @buffer. If @dyn is %true, also free
-+ * @buffer itself. */
-+void buffer_free(struct buffer *buffer, bool dyn)
-+{
-+ if (!buffer)
-+ return;
-+ buffer_reset(buffer);
-+ buffer_close(buffer);
-+ free(buffer->addr);
-+ if (dyn)
-+ free(buffer);
-+}
-+
-+/* Open a buffer file for @buffer. Return %EXIT_OK on success, %EXIT_RUNTIME
-+ * otherwise. */
-+int buffer_open(struct buffer *buffer)
-+{
-+ if (buffer->fd_open)
-+ return EXIT_OK;
-+
-+ buffer->file = tmpfile();
-+ if (!buffer->file) {
-+ mwarn("Could not create temporary file");
-+ return EXIT_RUNTIME;
-+ }
-+
-+ buffer->fd = fileno(buffer->file);
-+ buffer->fd_open = true;
-+
-+ return EXIT_OK;
-+}
-+
-+/* Write data in memory of @buffer to buffer file. Return %EXIT_OK on success,
-+ * %EXIT_RUNTIME otherwise. */
-+int buffer_flush(struct buffer *buffer)
-+{
-+ if (buffer->off == 0)
-+ return EXIT_OK;
-+ if (buffer_open(buffer))
-+ return EXIT_RUNTIME;
-+ if (misc_write_data(buffer->fd, buffer->addr, buffer->off)) {
-+ mwarn("Could not write to temporary file");
-+ return EXIT_RUNTIME;
-+ }
-+ buffer->off = 0;
-+
-+ return EXIT_OK;
-+}
-+
-+/* Try to ensure that at least @size bytes are available at
-+ * @buffer->addr[buffer->off]. Return the actual number of bytes available or
-+ * @-1 on error. If @usefile is %true, make use of a buffer file if
-+ * the total buffer size exceeds @max_buffer_size. */
-+ssize_t buffer_make_room(struct buffer *buffer, size_t size, bool usefile,
-+ size_t max_buffer_size)
-+{
-+ size_t needsize;
-+
-+ if (size > max_buffer_size && usefile)
-+ size = max_buffer_size;
-+
-+ needsize = buffer->off + size;
-+ if (needsize <= buffer->size) {
-+ /* Room available */
-+ return size;
-+ }
-+
-+ if (needsize > max_buffer_size && usefile) {
-+ /* Need to write out memory buffer to buffer file */
-+ if (buffer_flush(buffer))
-+ return -1;
-+ if (size <= buffer->size)
-+ return size;
-+ needsize = size;
-+ }
-+
-+ /* Need to increase memory buffer size */
-+ buffer->size = needsize;
-+ buffer->addr = mrealloc(buffer->addr, buffer->size);
-+
-+ return size;
-+}
-+
-+/* Try to read @chunk bytes from @fd to @buffer. Return the number of bytes
-+ * read on success, %0 on EOF or %-1 on error. */
-+ssize_t buffer_read_fd(struct buffer *buffer, int fd, size_t chunk,
-+ bool usefile, size_t max_buffer_size)
-+{
-+ ssize_t c = buffer_make_room(buffer, chunk, usefile, max_buffer_size);
-+
-+ DBG("buffer_read_fd wanted %zd got %zd", chunk, c);
-+ if (c < 0)
-+ return c;
-+
-+ c = read(fd, buffer->addr + buffer->off, c);
-+ if (c > 0) {
-+ buffer->total += c;
-+ buffer->off += c;
-+ }
-+
-+ return c;
-+}
-+
-+/* Add @len bytes at @addr to @buffer. If @addr is %NULL, add zeroes. Return
-+ * %EXIT_OK on success, %EXIT_RUNTIME otherwise. */
-+int buffer_add_data(struct buffer *buffer, char *addr, size_t len, bool usefile,
-+ size_t max_buffer_size)
-+{
-+ ssize_t c;
-+
-+ while (len > 0) {
-+ c = buffer_make_room(buffer, len, usefile, max_buffer_size);
-+ if (c < 0)
-+ return EXIT_RUNTIME;
-+ if (addr) {
-+ memcpy(buffer->addr + buffer->off, addr, c);
-+ addr += c;
-+ } else {
-+ memset(buffer->addr + buffer->off, 0, c);
-+ }
-+ buffer->total += c;
-+ buffer->off += c;
-+
-+ len -= c;
-+ }
-+
-+ return EXIT_OK;
-+}
-+
-+/* Call @cb for all chunks of data in @buffer. @data is passed to @cb. */
-+int buffer_iterate(struct buffer *buffer, buffer_cb_t cb, void *data)
-+{
-+ int rc;
-+ ssize_t r;
-+
-+ if (buffer->total == 0)
-+ return EXIT_OK;
-+
-+ if (!buffer->fd_open)
-+ return cb(data, buffer->addr, buffer->off);
-+
-+ /* Free memory buffer to be used as copy buffer */
-+ if (buffer_flush(buffer))
-+ return EXIT_RUNTIME;
-+ if (lseek(buffer->fd, 0, SEEK_SET) == (off_t) -1) {
-+ mwarn("Cannot seek in temporary file");
-+ return EXIT_RUNTIME;
-+ }
-+
-+ /* Copy data from temporary file to target file */
-+ while ((r = misc_read_data(buffer->fd, buffer->addr,
-+ buffer->size)) != 0) {
-+ if (r < 0) {
-+ mwarn("Cannot read from temporary file");
-+ return EXIT_RUNTIME;
-+ }
-+ rc = cb(data, buffer->addr, r);
-+ if (rc)
-+ return rc;
-+ }
-+
-+ return EXIT_OK;
-+}
-+
-+/* Truncate @buffer to at most @len bytes */
-+int buffer_truncate(struct buffer *buffer, size_t len)
-+{
-+ size_t delta;
-+
-+ if (buffer->total <= len)
-+ return EXIT_OK;
-+
-+ delta = buffer->total - len;
-+
-+ buffer->total = len;
-+ if (buffer->fd_open && delta > buffer->off) {
-+ /* All of memory and some of file buffer is truncated */
-+ buffer->off = 0;
-+ if (ftruncate(buffer->fd, len)) {
-+ mwarn("Cannot truncate temporary file");
-+ return EXIT_RUNTIME;
-+ }
-+ if (lseek(buffer->fd, len, SEEK_SET) == (off_t) -1) {
-+ mwarn("Cannot seek in temporary file");
-+ return EXIT_RUNTIME;
-+ }
-+ } else {
-+ /* Only memory buffer is truncated */
-+ buffer->off -= delta;
-+ }
-+
-+ return EXIT_OK;
-+}
---- /dev/null
-+++ b/dump2tar/src/dref.c
-@@ -0,0 +1,92 @@
-+/*
-+ * dump2tar - tool to dump files and command output into a tar archive
-+ *
-+ * Reference counting for directory handles
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#include "dref.h"
-+
-+#include
-+#include
-+#include
-+
-+#include "global.h"
-+#include "misc.h"
-+
-+/* dref_mutex serializes access to drefs */
-+static pthread_mutex_t dref_mutex = PTHREAD_MUTEX_INITIALIZER;
-+
-+static unsigned long num_open_dirs;
-+static unsigned long num_open_dirs_max;
-+
-+/* Lock dref mutex */
-+static void dref_lock(void)
-+{
-+ if (!global_threaded)
-+ return;
-+ pthread_mutex_lock(&dref_mutex);
-+}
-+
-+/* Unlock dref mutex */
-+static void dref_unlock(void)
-+{
-+ if (!global_threaded)
-+ return;
-+ pthread_mutex_unlock(&dref_mutex);
-+}
-+
-+/* Create a reference count managed directory handle for @dirname */
-+struct dref *dref_create(const char *dirname)
-+{
-+ struct dref *dref;
-+ DIR *dd;
-+
-+ dd = opendir(dirname);
-+ DBG("opendir(%s)=%p (total=%lu)", dirname, dd, ++num_open_dirs);
-+ if (!dd) {
-+ num_open_dirs--;
-+ return NULL;
-+ }
-+
-+ if (num_open_dirs > num_open_dirs_max)
-+ num_open_dirs_max = num_open_dirs;
-+
-+ dref = mmalloc(sizeof(struct dref));
-+ dref->dd = dd;
-+ dref->dirfd = dirfd(dd);
-+ dref->count = 1;
-+
-+ return dref;
-+}
-+
-+/* Obtain a reference to @dref */
-+struct dref *dref_get(struct dref *dref)
-+{
-+ if (dref) {
-+ dref_lock();
-+ dref->count++;
-+ dref_unlock();
-+ }
-+
-+ return dref;
-+}
-+
-+/* Release a reference to @dref. If this was the last reference, lose the
-+ * associated directory handle and free @dref. */
-+void dref_put(struct dref *dref)
-+{
-+ if (dref) {
-+ dref_lock();
-+ dref->count--;
-+ if (dref->count == 0) {
-+ num_open_dirs--;
-+ DBG("closedir(%p) (total=%lu, max=%lu)", dref->dd,
-+ num_open_dirs, num_open_dirs_max);
-+ closedir(dref->dd);
-+ free(dref);
-+ }
-+ dref_unlock();
-+ }
-+}
---- /dev/null
-+++ b/dump2tar/src/dump.c
-@@ -0,0 +1,1850 @@
-+/*
-+ * dump2tar - tool to dump files and command output into a tar archive
-+ *
-+ * Main dump logic
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#include "dump.h"
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#ifdef HAVE_ZLIB
-+#include
-+#endif /* HAVE_ZLIB */
-+
-+#include "buffer.h"
-+#include "dref.h"
-+#include "global.h"
-+#include "idcache.h"
-+#include "misc.h"
-+#include "tar.h"
-+
-+/* Default input file read size (bytes) */
-+#define DEFAULT_READ_CHUNK_SIZE (512 * 1024)
-+#define DEFAULT_MAX_BUFFER_SIZE (2 * 1024 * 1024)
-+
-+#define _SET_ABORTED(task) _set_aborted((task), __func__, __LINE__)
-+#define SET_ABORTED(task) set_aborted((task), __func__, __LINE__)
-+
-+#define read_error(task, filename, fmt, ...) \
-+ do { \
-+ if (!(task)->opts->ignore_failed_read) \
-+ SET_ABORTED((task)); \
-+ _mwarn(true, "%s: " fmt, (filename), ##__VA_ARGS__); \
-+ } while (0)
-+
-+#define write_error(task, fmt, ...) \
-+ do { \
-+ SET_ABORTED((task)); \
-+ _mwarn(true, "%s: " fmt, (task)->opts->output_file, \
-+ ##__VA_ARGS__); \
-+ } while (0)
-+
-+#define tverb(fmt, ...) \
-+ do { \
-+ if (task->opts->verbose) \
-+ verb((fmt), ##__VA_ARGS__); \
-+ } while (0)
-+
-+
-+/* Jobs representing a file or command output to add */
-+struct job {
-+ struct job *next_job;
-+ enum job_type {
-+ JOB_INIT, /* Initialization work */
-+ JOB_FILE, /* Add a regular file */
-+ JOB_LINK, /* Add a symbolic link */
-+ JOB_DIR, /* Add a directory */
-+ JOB_CMD, /* Add command output */
-+ } type;
-+ enum job_status {
-+ JOB_QUEUED, /* Transient: Job processing has not started */
-+ JOB_IN_PROGRESS,/* Transient: Job processing has started */
-+ JOB_EXCLUDED, /* Final: File was excluded */
-+ JOB_FAILED, /* Final: Data could not be obtained */
-+ JOB_DONE, /* Final: All data was obtained */
-+ JOB_PARTIAL, /* Final: Only some data was obtained */
-+ } status;
-+ char *outname;
-+ char *inname;
-+ char *relname;
-+ struct stat stat;
-+ bool timed;
-+ struct timespec deadline;
-+ struct dref *dref;
-+ int cmd_status;
-+ struct buffer *content;
-+};
-+
-+/* Run-time statistics */
-+struct stats {
-+ unsigned long num_done;
-+ unsigned long num_excluded;
-+ unsigned long num_failed;
-+ unsigned long num_partial;
-+};
-+
-+/* Information specific to a single dump task */
-+struct task {
-+ /* Input */
-+ struct dump_opts *opts;
-+
-+ /* State */
-+
-+ /* mutex serializes access to global data */
-+ pthread_mutex_t mutex;
-+ pthread_cond_t worker_cond;
-+ pthread_cond_t cond;
-+ unsigned long num_jobs_active;
-+ struct job *jobs_head;
-+ struct job *jobs_tail;
-+ bool aborted;
-+
-+ /* output_mutex serializes access to output file */
-+ pthread_mutex_t output_mutex;
-+ int output_fd;
-+ size_t output_written;
-+#ifdef HAVE_ZLIB
-+ gzFile output_gzfd;
-+#endif /* HAVE_ZLIB */
-+ unsigned long output_num_files;
-+
-+ /* No protection needed (only accessed in single-threaded mode) */
-+ struct stats stats;
-+ struct timespec start_ts;
-+};
-+
-+/* Per thread management data */
-+struct per_thread {
-+ long num;
-+ pthread_t thread;
-+ bool running;
-+ bool timed_out;
-+ struct stats stats;
-+ struct job *job;
-+ struct buffer buffer;
-+ struct task *task;
-+};
-+
-+static const struct {
-+ mode_t mode;
-+ char c;
-+} exclude_types[NUM_EXCLUDE_TYPES] = {
-+ { S_IFREG, 'f' },
-+ { S_IFDIR, 'd' },
-+ { S_IFCHR, 'c' },
-+ { S_IFBLK, 'b' },
-+ { S_IFIFO, 'p' },
-+ { S_IFLNK, 'l' },
-+ { S_IFSOCK, 's' },
-+};
-+
-+/* Lock main mutex */
-+static void main_lock(struct task *task)
-+{
-+ if (!global_threaded)
-+ return;
-+ DBG("main lock");
-+ pthread_mutex_lock(&task->mutex);
-+}
-+
-+/* Unlock main mutex */
-+static void main_unlock(struct task *task)
-+{
-+ if (!global_threaded)
-+ return;
-+ DBG("main unlock");
-+ pthread_mutex_unlock(&task->mutex);
-+}
-+
-+/* Lock output mutex */
-+static void output_lock(struct task *task)
-+{
-+ if (!global_threaded)
-+ return;
-+ pthread_mutex_lock(&task->output_mutex);
-+}
-+
-+/* Unlock output mutex */
-+static void output_unlock(struct task *task)
-+{
-+ if (!global_threaded)
-+ return;
-+ pthread_mutex_unlock(&task->output_mutex);
-+}
-+
-+/* Wake up all waiting workers */
-+static void _worker_wakeup_all(struct task *task)
-+{
-+ if (!global_threaded)
-+ return;
-+ DBG("waking up all worker threads");
-+ pthread_cond_broadcast(&task->worker_cond);
-+}
-+
-+/* Wake up one waiting worker */
-+static void _worker_wakeup_one(struct task *task)
-+{
-+ if (!global_threaded)
-+ return;
-+ DBG("waking up one worker thread");
-+ pthread_cond_signal(&task->worker_cond);
-+}
-+
-+/* Wait for a signal to a worker */
-+static int _worker_wait(struct task *task)
-+{
-+ int rc;
-+
-+ DBG("waiting for signal to worker");
-+ rc = pthread_cond_wait(&task->worker_cond, &task->mutex);
-+ DBG("waiting for signal to worker done (rc=%d)", rc);
-+
-+ return rc;
-+}
-+
-+/* Wake up main thread */
-+static void _main_wakeup(struct task *task)
-+{
-+ if (!global_threaded)
-+ return;
-+ DBG("waking up main thread");
-+ pthread_cond_broadcast(&task->cond);
-+}
-+
-+/* Wait for a signal to the main thread */
-+static int _main_wait(struct task *task)
-+{
-+ int rc;
-+
-+ DBG("waiting for status change");
-+ rc = pthread_cond_wait(&task->cond, &task->mutex);
-+ DBG("waiting for status change done (rc=%d)", rc);
-+
-+ return rc;
-+}
-+
-+/* Wait for a signal to the main thread. Abort waiting after @deadline */
-+static int _main_wait_timed(struct task *task, struct timespec *deadline)
-+{
-+ int rc;
-+
-+ DBG("timed waiting for status change");
-+ rc = pthread_cond_timedwait(&task->cond, &task->mutex, deadline);
-+ DBG("timed waiting for status change done (rc=%d)", rc);
-+
-+ return rc;
-+}
-+
-+/* Allow thread to be canceled */
-+static void cancel_enable(void)
-+{
-+ if (!global_threaded)
-+ return;
-+ if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
-+ mwarn("pthread_setcancelstate");
-+}
-+
-+/* Prevent thread from being canceled */
-+static void cancel_disable(void)
-+{
-+ if (!global_threaded)
-+ return;
-+ if (pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) != 0)
-+ mwarn("pthread_setcancelstate");
-+}
-+
-+/* Abort processing and inform all threads to shutdown. Must be called with
-+ * task->mutex locked */
-+static void _set_aborted(struct task *task, const char *func, unsigned int line)
-+{
-+ DBG("set aborted at %s:%u", func, line);
-+ task->aborted = true;
-+ _worker_wakeup_all(task);
-+ _main_wakeup(task);
-+}
-+
-+/* Abort processing and inform all threads to shutdown */
-+static void set_aborted(struct task *task, const char *func, unsigned int line)
-+{
-+ main_lock(task);
-+ _set_aborted(task, func, line);
-+ main_unlock(task);
-+}
-+
-+/* Check if abort processing has been initiated */
-+static bool is_aborted(struct task *task)
-+{
-+ bool result;
-+
-+ main_lock(task);
-+ result = task->aborted;
-+ main_unlock(task);
-+
-+ return result;
-+}
-+
-+/* Release resources associated with @job */
-+static void free_job(struct task *task, struct job *job)
-+{
-+ DBG("free job %p (%s)", job, job->inname);
-+ if (!job)
-+ return;
-+ free(job->inname);
-+ free(job->outname);
-+ free(job->relname);
-+ dref_put(job->dref);
-+ free(job);
-+}
-+
-+/* Check if file type specified by mode @m was marked as excluded */
-+static bool is_type_excluded(struct dump_opts *opts, mode_t m)
-+{
-+ int i;
-+
-+ m &= S_IFMT;
-+ for (i = 0; i < NUM_EXCLUDE_TYPES; i++) {
-+ if (exclude_types[i].mode == m)
-+ return opts->exclude_type[i];
-+ }
-+ return false;
-+}
-+
-+/* Replace all '/' characters in @filename with '_' */
-+static void escape_filename(char *filename)
-+{
-+ for (; *filename; filename++) {
-+ if (*filename == '/')
-+ *filename = '_';
-+ }
-+}
-+
-+/* Determine filename in archive from original filename @inname and
-+ * requested new filename @outname and depending on @type. */
-+static void set_outname(char **result_ptr, const char *outname,
-+ const char *inname, enum job_type type)
-+{
-+ const char *prefix = "", *name, *suffix;
-+ char *result, *end;
-+ size_t olen = outname ? strlen(outname) : 0, plen, nlen;
-+
-+ if (olen == 0) {
-+ /* No output name specified: outname = inname */
-+ name = inname;
-+ } else if (outname[olen - 1] == '/') {
-+ /* Output name is a directory: outname = outname/inname */
-+ prefix = outname;
-+ name = inname;
-+ } else {
-+ /* Output name is a filename: outname = inname */
-+ name = outname;
-+ }
-+
-+ if (type == JOB_DIR)
-+ suffix = "/";
-+ else
-+ suffix = "";
-+
-+ plen = strlen(prefix);
-+ nlen = strlen(name);
-+
-+ result = mmalloc(plen + nlen + strlen(suffix) + /* NUL */ 1);
-+
-+ /* Add prefix */
-+ strcpy(result, prefix);
-+
-+ /* Add name */
-+ end = result + plen;
-+ strcpy(end, name);
-+ if (type == JOB_CMD)
-+ escape_filename(end);
-+
-+ /* Add suffix */
-+ end = end + nlen;
-+ strcpy(end, suffix);
-+
-+ remove_double_slashes(result);
-+
-+ *result_ptr = result;
-+}
-+
-+static void sanitize_dirname(char **name_ptr)
-+{
-+ char *name;
-+
-+ name = mmalloc(strlen(*name_ptr) + /* Slash */ 1 + /* NUL */ 1);
-+ strcpy(name, *name_ptr);
-+ remove_double_slashes(name);
-+ chomp(name, "/");
-+ strcat(name, "/");
-+ free(*name_ptr);
-+ *name_ptr = name;
-+}
-+
-+/* Allocate and initialize a new job representation to add an entry according
-+ * to the specified parameters. @relname and @dref are used for opening files
-+ * more efficiently using *at() functions if specified. @is_cmd specifies if
-+ * the specified inname is a command line. */
-+static struct job *create_job(struct task *task, const char *inname,
-+ const char *outname, bool is_cmd,
-+ const char *relname, struct dref *dref,
-+ struct stats *stats)
-+{
-+ struct job *job = mmalloc(sizeof(struct job));
-+ int rc;
-+
-+ DBG("create job inname=%s outname=%s is_cmd=%d relname=%s dref=%p",
-+ inname, outname, is_cmd, relname, dref);
-+
-+ job->status = JOB_QUEUED;
-+
-+ if (!inname) {
-+ job->type = JOB_INIT;
-+ return job;
-+ }
-+
-+ job->inname = mstrdup(inname);
-+
-+ if (is_cmd) {
-+ /* Special case - read from command output */
-+ job->type = JOB_CMD;
-+ set_dummy_stat(&job->stat);
-+ goto out;
-+ }
-+
-+ if (!relname && strcmp(job->inname, "-") == 0) {
-+ /* Special case - read from standard input */
-+ job->type = JOB_FILE;
-+ set_dummy_stat(&job->stat);
-+ goto out;
-+ }
-+
-+ rc = stat_file(task->opts->dereference, job->inname, relname, dref,
-+ &job->stat);
-+
-+ if (rc < 0) {
-+ read_error(task, job->inname, "Cannot stat file");
-+ free_job(task, job);
-+ stats->num_failed++;
-+ return NULL;
-+ }
-+
-+ if (is_type_excluded(task->opts, job->stat.st_mode)) {
-+ free_job(task, job);
-+ stats->num_excluded++;
-+ return NULL;
-+ }
-+
-+ if (S_ISLNK(job->stat.st_mode)) {
-+ job->type = JOB_LINK;
-+ } else if (S_ISDIR(job->stat.st_mode)) {
-+ job->type = JOB_DIR;
-+ sanitize_dirname(&job->inname);
-+
-+ /* No need to keep parent directory open */
-+ relname = NULL;
-+ dref = NULL;
-+ } else {
-+ job->type = JOB_FILE;
-+ }
-+
-+ if (relname)
-+ job->relname = mstrdup(relname);
-+ job->dref = dref_get(dref);
-+
-+out:
-+ set_outname(&job->outname, outname, inname, job->type);
-+
-+ return job;
-+}
-+
-+void job_print(struct job *job)
-+{
-+ printf("DEBUG: job_print at %p\n", job);
-+ printf("DEBUG: next_job=%p\n", job->next_job);
-+ printf("DEBUG: type=%d\n", job->type);
-+ printf("DEBUG: status==%d\n", job->status);
-+ printf("DEBUG: outname=%s\n", job->outname);
-+ printf("DEBUG: inname=%s\n", job->inname);
-+ printf("DEBUG: relname=%s\n", job->relname);
-+ printf("DEBUG: timed=%d\n", job->timed);
-+ printf("DEBUG: dref=%p\n", job->dref);
-+ printf("DEBUG: cmd_status=%d\n", job->cmd_status);
-+ printf("DEBUG: content=%p\n", job->content);
-+}
-+
-+/* Return the number of bytes written to the output file */
-+static size_t get_output_size(struct task *task)
-+{
-+#ifdef HAVE_ZLIB
-+ if (task->opts->gzip) {
-+ gzflush(task->output_gzfd, Z_SYNC_FLUSH);
-+ return gztell(task->output_gzfd);
-+ }
-+#endif /* HAVE_ZLIB */
-+ return task->output_written;
-+}
-+
-+/* Write @len bytes at address @ptr to the output file */
-+static int write_output(struct task *task, const char *ptr, size_t len)
-+{
-+ size_t todo = len;
-+ ssize_t w;
-+
-+#ifdef HAVE_ZLIB
-+ if (task->opts->gzip) {
-+ if (gzwrite(task->output_gzfd, ptr, len) == 0)
-+ goto err_write;
-+ task->output_written += len;
-+
-+ return EXIT_OK;
-+ }
-+#endif /* HAVE_ZLIB */
-+
-+ while (todo > 0) {
-+ w = write(task->output_fd, ptr, todo);
-+ if (w < 0)
-+ goto err_write;
-+ todo -= w;
-+ ptr += w;
-+ }
-+ task->output_written += len;
-+
-+ return EXIT_OK;
-+
-+err_write:
-+ write_error(task, "Cannot write output");
-+
-+ return EXIT_RUNTIME;
-+}
-+
-+/* Write an end-of-file marker to the output file */
-+static void write_eof(struct task *task)
-+{
-+ char zeroes[TAR_BLOCKSIZE];
-+
-+ memset(zeroes, 0, sizeof(zeroes));
-+ write_output(task, zeroes, TAR_BLOCKSIZE);
-+ write_output(task, zeroes, TAR_BLOCKSIZE);
-+}
-+
-+/* Callback for writing out chunks of job data */
-+static int _write_job_data_cb(void *data, void *addr, size_t len)
-+{
-+ struct task *task = data;
-+
-+ return write_output(task, addr, len);
-+}
-+
-+/* Write tar entry for a file containing the exit status of the process that
-+ * ran command job @job */
-+static int write_job_status_file(struct task *task, struct job *job)
-+{
-+ char *name, *content;
-+ size_t len;
-+ struct stat st;
-+ int rc, status = job->cmd_status, exitstatus = -1, termsig = -1,
-+ waitpid_errno = -1;
-+
-+ name = masprintf("%s.cmdstatus", job->outname);
-+ if (status < 0)
-+ waitpid_errno = -status;
-+ else if (WIFEXITED(status))
-+ exitstatus = WEXITSTATUS(status);
-+ else if (WIFSIGNALED(status))
-+ termsig = WTERMSIG(status);
-+
-+ content = masprintf("EXITSTATUS=%d\n"
-+ "TERMSIG=%d\n"
-+ "WAITPID_ERRNO=%d\n", exitstatus, termsig,
-+ waitpid_errno);
-+
-+ len = strlen(content);
-+ set_dummy_stat(&st);
-+ rc = tar_emit_file_from_data(name, NULL, len, &st, TYPE_REGULAR,
-+ content, _write_job_data_cb, task);
-+ free(name);
-+ free(content);
-+
-+ return rc;
-+}
-+
-+/* Write tar entry for data in @job to output. Must be called with output_lock
-+ * held. */
-+static void _write_job_data(struct task *task, struct job *job)
-+{
-+ struct buffer *buffer = job->content;
-+
-+ switch (job->status) {
-+ case JOB_DONE:
-+ case JOB_PARTIAL:
-+ break;
-+ case JOB_FAILED:
-+ /* Create empty entries for failed reads */
-+ if (task->opts->ignore_failed_read)
-+ break;
-+ return;
-+ default:
-+ return;
-+ }
-+
-+ switch (job->type) {
-+ case JOB_CMD:
-+ tar_emit_file_from_buffer(job->outname, NULL, buffer->total,
-+ &job->stat, TYPE_REGULAR, buffer,
-+ _write_job_data_cb, task);
-+ task->output_num_files++;
-+ if (task->opts->add_cmd_status) {
-+ write_job_status_file(task, job);
-+ task->output_num_files++;
-+ }
-+ break;
-+ case JOB_FILE:
-+ tar_emit_file_from_buffer(job->outname, NULL, buffer->total,
-+ &job->stat, TYPE_REGULAR, buffer,
-+ _write_job_data_cb, task);
-+ task->output_num_files++;
-+ break;
-+ case JOB_LINK:
-+ tar_emit_file_from_buffer(job->outname, buffer->addr, 0,
-+ &job->stat, TYPE_LINK, NULL,
-+ _write_job_data_cb, task);
-+ task->output_num_files++;
-+ break;
-+ case JOB_DIR:
-+ tar_emit_file_from_buffer(job->outname, NULL, 0, &job->stat,
-+ TYPE_DIR, NULL, _write_job_data_cb,
-+ task);
-+ task->output_num_files++;
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ if (task->opts->max_size > 0 &&
-+ get_output_size(task) > task->opts->max_size) {
-+ mwarnx("Archive size exceeds maximum of %ld bytes - aborting",
-+ task->opts->max_size);
-+ SET_ABORTED(task);
-+ }
-+}
-+
-+/* Read the contents of the symbolic link at @filename. On success, the
-+ * contents is returned in @buffer and the return value is %EXIT_OK.
-+ * If @relname is non-null it points to the name of the file relative
-+ * to its parent directory for which @dirfd is an open file handle. */
-+static int read_symlink(struct task *task, const char *filename,
-+ const char *relname, int dirfd, struct buffer *buffer)
-+{
-+ ssize_t actual = 0;
-+ size_t currlen = buffer->size ? buffer->size :
-+ task->opts->read_chunk_size;
-+ int rc = EXIT_OK;
-+
-+ while (!is_aborted(task)) {
-+ buffer_make_room(buffer, currlen, false,
-+ task->opts->max_buffer_size);
-+
-+ cancel_enable();
-+ if (relname)
-+ actual = readlinkat(dirfd, relname, buffer->addr,
-+ buffer->size);
-+ else
-+ actual = readlink(filename, buffer->addr, buffer->size);
-+ cancel_disable();
-+
-+ if (actual == -1) {
-+ read_error(task, filename, "Cannot read link");
-+ rc = EXIT_RUNTIME;
-+ /* Reset actual counter to get an empty buffer */
-+ actual = 0;
-+ break;
-+ }
-+
-+ /* Ensure that content doesn't exceed --file-max-size limit */
-+ if (task->opts->file_max_size > 0 &&
-+ (size_t) actual > task->opts->file_max_size) {
-+ actual = task->opts->file_max_size;/* Don't count NUL */
-+ mwarnx("%s: Warning: Data exceeds maximum size of %ld "
-+ "bytes - truncating", filename,
-+ task->opts->file_max_size);
-+ break;
-+ }
-+
-+ if ((size_t) actual < buffer->size)
-+ break;
-+
-+ currlen += task->opts->read_chunk_size;
-+ }
-+
-+ if (rc == EXIT_OK && is_aborted(task))
-+ rc = EXIT_RUNTIME;
-+
-+ buffer->addr[actual] = 0;
-+ buffer->total = actual + 1;
-+
-+ return rc;
-+}
-+
-+/* Read data from the file descriptor @fd until an end-of-file condition is
-+ * encountered. On success, *@done bytes in @buffer contain the read data
-+ * and the return value is %EXIT_OK. */
-+static int read_fd(struct task *task, const char *name, int fd,
-+ struct buffer *buffer)
-+{
-+ ssize_t rc = 0;
-+ size_t c = buffer->size ? buffer->size : task->opts->read_chunk_size;
-+
-+ while (!is_aborted(task)) {
-+ cancel_enable();
-+ rc = buffer_read_fd(buffer, fd, c, true,
-+ task->opts->max_buffer_size);
-+ cancel_disable();
-+
-+ if (rc <= 0)
-+ break;
-+
-+ /* Ensure that content doesn't exceed --file-max-size limit */
-+ if (task->opts->file_max_size > 0 &&
-+ buffer->total >= task->opts->file_max_size) {
-+ buffer_truncate(buffer, task->opts->file_max_size);
-+ rc = 0;
-+ mwarnx("%s: Warning: Data exceeds maximum size of %ld "
-+ "bytes - truncating", name,
-+ task->opts->file_max_size);
-+ break;
-+ }
-+
-+ c = buffer->size - buffer->off;
-+ if (c > 0) {
-+ /* Read to memory */
-+ } else if (buffer->size + task->opts->read_chunk_size <
-+ task->opts->max_buffer_size) {
-+ /* Enlarge memory buffer */
-+ c = task->opts->read_chunk_size;
-+ } else {
-+ /* Use full memory buffer size */
-+ c = task->opts->max_buffer_size;
-+ }
-+ }
-+
-+ if (is_aborted(task) || rc != 0)
-+ return EXIT_RUNTIME;
-+
-+ return EXIT_OK;
-+}
-+
-+/* Read data from the file at @filename until an end-of-file condition is
-+ * encountered. On success, @buffer contains the data read and the return
-+ * value is %EXIT_OK. If @relname is non-null it points to the name of the
-+ * file relative to its parent directory for which @dirfd is an open file
-+ * handle. */
-+static int read_regular(struct task *task, const char *filename,
-+ const char *relname, int dirfd, struct buffer *buffer)
-+{
-+ int fd, rc = EXIT_OK;
-+ bool need_close = true;
-+
-+ /* Opening a named pipe can block when peer is not ready */
-+ cancel_enable();
-+ if (strcmp(filename, "-") == 0) {
-+ fd = STDIN_FILENO;
-+ need_close = false;
-+ filename = "Standard input";
-+ } else if (relname)
-+ fd = openat(dirfd, relname, O_RDONLY);
-+ else
-+ fd = open(filename, O_RDONLY);
-+ cancel_disable();
-+
-+ if (fd < 0) {
-+ read_error(task, filename, "Cannot open file");
-+ return EXIT_RUNTIME;
-+ }
-+
-+ rc = read_fd(task, filename, fd, buffer);
-+ if (rc) {
-+ if (is_aborted(task))
-+ mwarnx("%s: Read aborted", filename);
-+ else
-+ read_error(task, filename, "Cannot read file");
-+ }
-+
-+ if (need_close)
-+ close(fd);
-+
-+ return rc;
-+}
-+
-+/* Read the output of command @cmd until an end-of-file condition is
-+ * encountered. On success, @buffer contain the output and the return value
-+ * is %EXIT_OK. When not %NULL, use @status_ptr to store the resulting process
-+ * status. */
-+static int read_cmd_output(struct task *task, char *cmd, struct buffer *buffer,
-+ int *status_ptr)
-+{
-+ int fd, rc = EXIT_RUNTIME;
-+ pid_t pid;
-+
-+ fd = cmd_open(cmd, &pid);
-+ if (fd < 0) {
-+ read_error(task, cmd, "Cannot run command");
-+ return rc;
-+ }
-+
-+ if (read_fd(task, cmd, fd, buffer)) {
-+ if (is_aborted(task))
-+ mwarnx("%s: Command aborted", cmd);
-+ else
-+ read_error(task, cmd, "Cannot read command output");
-+ } else
-+ rc = EXIT_OK;
-+
-+ cmd_close(fd, pid, status_ptr);
-+
-+ return rc;
-+
-+}
-+
-+/* Check the exclude patterns in @task->opts->exclude for a match of @filename.
-+ * If found, return the matching pattern string, otherwise return %NULL. */
-+static const char *get_exclude_match(struct task *task, const char *filename)
-+{
-+ unsigned int i;
-+ int mode = FNM_PERIOD | FNM_NOESCAPE;
-+
-+ for (i = 0; i < task->opts->exclude.num; i++) {
-+ if (fnmatch(task->opts->exclude.str[i], filename, mode) == 0)
-+ return task->opts->exclude.str[i];
-+ }
-+
-+ return NULL;
-+}
-+
-+/* Add the specified @job to the start of the job queue */
-+static void _queue_job_head(struct task *task, struct job *job)
-+{
-+ DBG("queue job type=%d inname=%s at head", job->type, job->inname);
-+ job->next_job = task->jobs_head;
-+ task->jobs_head = job;
-+ if (!task->jobs_tail)
-+ task->jobs_tail = job;
-+}
-+
-+/* Add the specified @job to the end of the job queue */
-+static void _queue_job_tail(struct task *task, struct job *job)
-+{
-+ DBG("queue job type=%d inname=%s at tail", job->type, job->inname);
-+ if (task->jobs_tail)
-+ task->jobs_tail->next_job = job;
-+ else
-+ task->jobs_head = job;
-+ task->jobs_tail = job;
-+}
-+
-+/* Add the specified @job to the job queue and trigger processing.
-+ * If @head is %true, the new job is inserted at the start of the job queue,
-+ * otherwise at the end. */
-+static void queue_job(struct task *task, struct job *job, bool head)
-+{
-+ main_lock(task);
-+ task->num_jobs_active++;
-+ if (head)
-+ _queue_job_head(task, job);
-+ else
-+ _queue_job_tail(task, job);
-+ _worker_wakeup_one(task);
-+ main_unlock(task);
-+}
-+
-+/* Add the specified list of jobs starting with @first up to @last to the start
-+ * of the job queue and trigger processing */
-+static void queue_jobs(struct task *task, struct job *first, struct job *last,
-+ int num)
-+{
-+ main_lock(task);
-+ last->next_job = task->jobs_head;
-+ task->jobs_head = first;
-+ task->num_jobs_active += num;
-+ _worker_wakeup_all(task);
-+ main_unlock(task);
-+}
-+
-+/* Remove the head of the job queue and return it to the caller */
-+static struct job *_dequeue_job(struct task *task)
-+{
-+ struct job *job = NULL;
-+
-+ if (task->jobs_head) {
-+ job = task->jobs_head;
-+ task->jobs_head = job->next_job;
-+ job->next_job = NULL;
-+ if (job == task->jobs_tail)
-+ task->jobs_tail = NULL;
-+ DBG("dequeueing job type=%d inname=%s", job->type, job->inname);
-+ job->status = JOB_IN_PROGRESS;
-+ } else {
-+ DBG("no job to dequeue");
-+ }
-+
-+ return job;
-+}
-+
-+/* Create and queue job for file at @filename */
-+static void queue_file(struct task *task, const char *inname,
-+ const char *outname, bool is_cmd,
-+ const char *relname, struct dref *dref,
-+ struct stats *stats, bool head)
-+{
-+ struct job *job;
-+
-+ job = create_job(task, inname, outname, is_cmd, relname, dref, stats);
-+ if (job)
-+ queue_job(task, job, head);
-+}
-+
-+/* Queue initial job */
-+static void init_queue(struct task *task)
-+{
-+ queue_file(task, NULL, NULL, false, NULL, NULL, NULL, true);
-+}
-+
-+/* Create and queue jobs for all files found in @dirname */
-+static void queue_dir(struct task *task, const char *dirname,
-+ const char *outname, struct stats *stats)
-+{
-+ struct dirent *de;
-+ char *inpath, *outpath;
-+ struct dref *dref;
-+ struct job *job, *first = NULL, *last = NULL;
-+ int num = 0;
-+
-+ dref = dref_create(dirname);
-+ if (!dref) {
-+ read_error(task, dirname, "Cannot read directory");
-+ return;
-+ }
-+
-+ while ((de = readdir(dref->dd))) {
-+ if (de->d_name[0] == '.') {
-+ if (de->d_name[1] == 0)
-+ continue;
-+ if (de->d_name[1] == '.' && de->d_name[2] == 0)
-+ continue;
-+ }
-+ DBG("next file %s", de->d_name);
-+ inpath = masprintf("%s%s", dirname, de->d_name);
-+ outpath = masprintf("%s%s", outname, de->d_name);
-+ job = create_job(task, inpath, outpath, false, de->d_name, dref,
-+ stats);
-+ if (job) {
-+ if (last) {
-+ last->next_job = job;
-+ last = job;
-+ } else {
-+ first = job;
-+ last = job;
-+ }
-+ num++;
-+ }
-+ free(inpath);
-+ free(outpath);
-+ }
-+
-+ if (first)
-+ queue_jobs(task, first, last, num);
-+
-+ dref_put(dref);
-+}
-+
-+/* Create and queue jobs for all files specified on the command line */
-+static void queue_jobs_from_opts(struct task *task, struct stats *stats)
-+{
-+ struct dump_opts *opts = task->opts;
-+ unsigned int i;
-+
-+ /* Queue directly specified entries */
-+ for (i = 0; i < opts->num_specs && !is_aborted(task); i++) {
-+ queue_file(task, opts->specs[i].inname, opts->specs[i].outname,
-+ opts->specs[i].is_cmd, NULL, NULL, stats, false);
-+ }
-+}
-+
-+/* Prepare output stream */
-+static int open_output(struct task *task)
-+{
-+ bool to_stdout = !task->opts->output_file ||
-+ strcmp(task->opts->output_file, "-") == 0;
-+ int rc = EXIT_OK;
-+
-+ if (to_stdout) {
-+ set_stdout_data();
-+ task->opts->output_file = "Standard output";
-+ }
-+
-+ cancel_enable();
-+#ifdef HAVE_ZLIB
-+ if (task->opts->gzip) {
-+ if (to_stdout) {
-+ task->output_gzfd =
-+ gzdopen(STDOUT_FILENO,
-+ task->opts->append ? "ab" : "wb");
-+ } else {
-+ task->output_gzfd =
-+ gzopen(task->opts->output_file,
-+ task->opts->append ? "ab" : "wb");
-+ }
-+
-+ if (!task->output_gzfd)
-+ rc = EXIT_RUNTIME;
-+ goto out;
-+ }
-+#endif /* HAVE_ZLIB */
-+
-+ if (to_stdout) {
-+ task->output_fd = STDOUT_FILENO;
-+ } else {
-+ task->output_fd =
-+ open(task->opts->output_file, O_WRONLY | O_CREAT |
-+ (task->opts->append ? O_APPEND : 0), 0666);
-+ }
-+
-+ if (task->output_fd < 0)
-+ rc = EXIT_RUNTIME;
-+ else if (!task->opts->append && ftruncate(task->output_fd, 0) == -1)
-+ rc = EXIT_RUNTIME;
-+
-+#ifdef HAVE_ZLIB
-+out:
-+#endif /* HAVE_ZLIB */
-+ cancel_disable();
-+
-+ if (rc != EXIT_OK) {
-+ mwarn("%s: Cannot open output file", task->opts->output_file);
-+ return rc;
-+ }
-+
-+ return EXIT_OK;
-+}
-+
-+/* Determine if the specified @job should be excluded from archiving */
-+static bool is_job_excluded(struct task *task, struct job *job)
-+{
-+ const char *pat;
-+
-+ if (job->type == JOB_INIT || job->type == JOB_CMD)
-+ return false;
-+
-+ pat = get_exclude_match(task, job->inname);
-+ if (!pat)
-+ return false;
-+
-+ tverb("Excluding '%s' due to exclude pattern '%s'\n", job->inname, pat);
-+
-+ return true;
-+}
-+
-+/* Perform all actions necessary to process @job and add resulting tar
-+ * data buffers to the buffer list of @thread. */
-+static void process_job(struct per_thread *thread, struct job *job)
-+{
-+ struct task *task = thread->task;
-+ const char *relname = job->dref ? job->relname : NULL;
-+ int dirfd = job->dref ? job->dref->dirfd : -1;
-+ struct buffer *buffer = &thread->buffer;
-+ enum job_status status = JOB_DONE;
-+
-+ DBG("processing job type=%d inname=%s", job->type, job->inname);
-+
-+ if (is_job_excluded(task, job)) {
-+ status = JOB_EXCLUDED;
-+ goto out;
-+ }
-+
-+ switch (job->type) {
-+ case JOB_INIT: /* Perform initial setup steps */
-+ if (open_output(task)) {
-+ SET_ABORTED(task);
-+ status = JOB_FAILED;
-+ goto out;
-+ }
-+ queue_jobs_from_opts(task, &thread->stats);
-+ break;
-+ case JOB_CMD: /* Capture command output */
-+ tverb("Dumping command output '%s'\n", job->inname);
-+
-+ set_dummy_stat(&job->stat);
-+ if (read_cmd_output(task, job->inname, buffer,
-+ &job->cmd_status))
-+ status = JOB_FAILED;
-+
-+ break;
-+ case JOB_LINK: /* Read symbolic link */
-+ tverb("Dumping link '%s'\n", job->inname);
-+
-+ if (read_symlink(task, job->inname, relname, dirfd, buffer))
-+ status = JOB_FAILED;
-+
-+ break;
-+ case JOB_DIR: /* Read directory contents */
-+ tverb("Dumping directory '%s'\n", job->inname);
-+
-+ if (task->opts->recursive) {
-+ queue_dir(task, job->inname, job->outname,
-+ &thread->stats);
-+ }
-+ break;
-+ case JOB_FILE: /* Read file contents */
-+ tverb("Dumping file '%s'\n", job->inname);
-+
-+ if (read_regular(task, job->inname, relname, dirfd, buffer))
-+ status = JOB_FAILED;
-+
-+ break;
-+ default:
-+ break;
-+ }
-+
-+out:
-+ job->status = status;
-+ DBG("processing done status=%d", job->status);
-+}
-+
-+/* Add @job results to statistics @stats */
-+static void account_stats(struct task *task, struct stats *stats,
-+ struct job *job)
-+{
-+ DBG("accounting job %s", job->inname);
-+
-+ if (job->type == JOB_INIT)
-+ return;
-+
-+ switch (job->status) {
-+ case JOB_DONE:
-+ stats->num_done++;
-+ if (job->type == JOB_CMD && task->opts->add_cmd_status)
-+ stats->num_done++;
-+ break;
-+ case JOB_PARTIAL:
-+ stats->num_done++;
-+ stats->num_partial++;
-+ if (job->type == JOB_CMD && task->opts->add_cmd_status)
-+ stats->num_done++;
-+ break;
-+ case JOB_FAILED:
-+ stats->num_failed++;
-+ break;
-+ case JOB_EXCLUDED:
-+ stats->num_excluded++;
-+ break;
-+ default:
-+ break;
-+ }
-+}
-+
-+/* Add statistics @from to @to */
-+static void add_stats(struct stats *to, struct stats *from)
-+{
-+ to->num_done += from->num_done;
-+ to->num_partial += from->num_partial;
-+ to->num_excluded += from->num_excluded;
-+ to->num_failed += from->num_failed;
-+}
-+
-+/* Release resources allocated to @thread */
-+static void cleanup_thread(struct per_thread *thread)
-+{
-+ if (thread->job)
-+ free_job(thread->task, thread->job);
-+ buffer_free(&thread->buffer, false);
-+}
-+
-+/* Register activate @job at @thread */
-+static void start_thread_job(struct per_thread *thread, struct job *job)
-+{
-+ struct task *task = thread->task;
-+
-+ thread->job = job;
-+ job->content = &thread->buffer;
-+ if (task->opts->file_timeout > 0 && job->type != JOB_INIT) {
-+ /* Set up per-job timeout */
-+ set_timespec(&job->deadline, task->opts->file_timeout, 0);
-+ job->timed = true;
-+
-+ /* Signal main thread to update deadline timeout */
-+ _main_wakeup(task);
-+ }
-+}
-+
-+/* Unregister active @job at @thread */
-+static void stop_thread_job(struct per_thread *thread, struct job *job)
-+{
-+ thread->job = NULL;
-+ job->content = NULL;
-+ buffer_reset(&thread->buffer);
-+}
-+
-+/* Wait until a job is available in the job queue. When a job becomes
-+ * available, dequeue and return it. Return %NULL if no more jobs are
-+ * available, or if processing was aborted. Must be called with task->mutex
-+ * locked. */
-+static struct job *_get_next_job(struct task *task)
-+{
-+ struct job *job = NULL;
-+
-+ do {
-+ DBG("checking for jobs");
-+ if (task->aborted)
-+ break;
-+ job = _dequeue_job(task);
-+ if (job)
-+ break;
-+ if (task->num_jobs_active == 0)
-+ break;
-+ DBG("found no jobs (%d active)", task->num_jobs_active);
-+ } while (_worker_wait(task) == 0);
-+
-+ return job;
-+}
-+
-+/* Unlock the mutex specified by @data */
-+static void cleanup_unlock(void *data)
-+{
-+ pthread_mutex_t *mutex = data;
-+
-+ pthread_mutex_unlock(mutex);
-+}
-+
-+/* Write entry for data in @job to output */
-+static void write_job_data(struct task *task, struct job *job)
-+{
-+ DBG("write_job_data");
-+ output_lock(task);
-+ pthread_cleanup_push(cleanup_unlock, &task->output_mutex);
-+ cancel_enable();
-+
-+ _write_job_data(task, job);
-+
-+ cancel_disable();
-+ pthread_cleanup_pop(0);
-+ output_unlock(task);
-+}
-+
-+/* Perform second part of job processing for @job at @thread by writing the
-+ * resulting tar file entry */
-+static void postprocess_job(struct per_thread *thread, struct job *job,
-+ bool cancelable)
-+{
-+ struct task *task = thread->task;
-+
-+ account_stats(task, &thread->stats, job);
-+ if (cancelable)
-+ write_job_data(task, job);
-+ else
-+ _write_job_data(task, job);
-+}
-+
-+/* Mark @job as complete by releasing all associated resources. If this was
-+ * the last active job inform main thread. Must be called with main_lock
-+ * mutex held. */
-+static void _complete_job(struct task *task, struct job *job)
-+{
-+ task->num_jobs_active--;
-+ if (task->num_jobs_active == 0)
-+ _main_wakeup(task);
-+ free_job(task, job);
-+}
-+
-+static void init_thread(struct per_thread *thread, struct task *task, long num)
-+{
-+ memset(thread, 0, sizeof(struct per_thread));
-+ thread->task = task;
-+ thread->num = num;
-+}
-+
-+/* Dequeue and process all jobs on the job queue */
-+static int process_queue(struct task *task)
-+{
-+ struct job *job;
-+ struct per_thread thread;
-+
-+ init_thread(&thread, task, 0);
-+
-+ while ((job = _dequeue_job(task)) && !is_aborted(task)) {
-+ start_thread_job(&thread, job);
-+ process_job(&thread, job);
-+ postprocess_job(&thread, job, false);
-+ stop_thread_job(&thread, job);
-+ _complete_job(task, job);
-+ }
-+
-+ task->stats = thread.stats;
-+ cleanup_thread(&thread);
-+
-+ return EXIT_OK;
-+}
-+
-+/* Return %true if @job is in a final state, %false otherwise */
-+static bool job_is_final(struct job *job)
-+{
-+ switch (job->status) {
-+ case JOB_DONE:
-+ case JOB_PARTIAL:
-+ case JOB_EXCLUDED:
-+ case JOB_FAILED:
-+ return true;
-+ default:
-+ break;
-+ }
-+
-+ return false;
-+}
-+
-+/* Main thread function: process jobs on the job queue until all jobs
-+ * are processed or processing was aborted. */
-+static void *worker_thread_main(void *d)
-+{
-+ struct per_thread *thread = d;
-+ struct task *task = thread->task;
-+ struct job *job;
-+
-+ /* Allow cancel only at specific code points */
-+ cancel_disable();
-+ set_threadname("%*sworker %d", (thread->num + 1) * 2, "", thread->num);
-+
-+ /* Handle jobs left over from canceled thread */
-+ job = thread->job;
-+ if (job) {
-+ DBG("handle aborted job %p", job);
-+
-+ postprocess_job(thread, job, true);
-+
-+ main_lock(task);
-+ if (thread->timed_out)
-+ goto out;
-+ stop_thread_job(thread, job);
-+ _complete_job(task, job);
-+ main_unlock(task);
-+ }
-+
-+ DBG("enter worker loop");
-+
-+ main_lock(task);
-+ while ((job = _get_next_job(task))) {
-+ start_thread_job(thread, job);
-+ main_unlock(task);
-+
-+ process_job(thread, job);
-+ postprocess_job(thread, job, true);
-+
-+ main_lock(task);
-+ if (thread->timed_out)
-+ goto out;
-+ stop_thread_job(thread, job);
-+ _complete_job(task, job);
-+ }
-+
-+out:
-+ thread->running = false;
-+ _main_wakeup(task);
-+ main_unlock(task);
-+
-+ cancel_enable();
-+ DBG("leave work loop");
-+
-+ return NULL;
-+}
-+
-+/* Start a worker thread associated with the specified @data. Return %EXIT_OK on
-+ * success. */
-+static int start_worker_thread(struct per_thread *data)
-+{
-+ int rc;
-+
-+ DBG("start thread");
-+ global_threaded = true;
-+ data->timed_out = false;
-+ rc = pthread_create(&data->thread, NULL, &worker_thread_main, data);
-+ if (rc) {
-+ mwarnx("Cannot start thread: %s", strerror(rc));
-+ return EXIT_RUNTIME;
-+ }
-+ data->running = true;
-+
-+ return EXIT_OK;
-+}
-+
-+/* Perform timeout handling for thread associated with @data by canceling and
-+ * restarting the corresponding thread. Must be called with task->mutex
-+ * held. */
-+static void _timeout_thread(struct per_thread *data)
-+{
-+ struct task *task = data->task;
-+ struct job *job = data->job;
-+ pthread_t thread = data->thread;
-+ const char *op, *action;
-+
-+ if (!job) {
-+ /* Timeout raced with job completion */
-+ return;
-+ }
-+ if (job_is_final(job)) {
-+ /* Job processing done, timeout does not apply */
-+ return;
-+ }
-+
-+ data->timed_out = true;
-+
-+ /* Allow thread to obtain main lock during cancel handling */
-+ main_unlock(task);
-+ DBG("cancel num=%d thread=%p", data->num, thread);
-+ pthread_cancel(thread);
-+ DBG("join num=%d thread=%p", data->num, thread);
-+
-+ pthread_join(thread, NULL);
-+ main_lock(task);
-+
-+ DBG("join done");
-+
-+ if (job->type == JOB_CMD)
-+ op = "Command";
-+ else
-+ op = "Read";
-+
-+ if (task->opts->ignore_failed_read)
-+ action = "skipping";
-+ else
-+ action = "aborting";
-+
-+ if (!job->inname || !*job->inname)
-+ job_print(job);
-+ mwarnx("%s: %s%s timed out after %d second%s - %s", job->inname,
-+ task->opts->ignore_failed_read ? "Warning: " : "", op,
-+ task->opts->file_timeout,
-+ task->opts->file_timeout > 1 ? "s" : "", action);
-+ if (!task->opts->ignore_failed_read)
-+ _SET_ABORTED(task);
-+
-+ /* Interrupted job will be handled by new thread - adjust status */
-+ if (job->status == JOB_IN_PROGRESS)
-+ job->status = JOB_PARTIAL;
-+ else if (!job_is_final(job))
-+ job->status = JOB_FAILED;
-+
-+ if (start_worker_thread(data))
-+ _SET_ABORTED(task);
-+}
-+
-+/* Return the number of currently running jobs */
-+static long num_jobs_running(struct task *task, struct per_thread *threads)
-+{
-+ long i, num = 0;
-+
-+ for (i = 0; i < task->opts->jobs; i++) {
-+ if (threads[i].running)
-+ num++;
-+ }
-+
-+ return num;
-+}
-+
-+/* Wait until all jobs are done or timeout occurs */
-+static int wait_for_completion(struct task *task, struct per_thread *threads)
-+{
-+ int rc = 0, earliest_timeout;
-+ long i;
-+ struct per_thread *earliest_thread;
-+ struct timespec tool_deadline_ts, deadline_ts, *earliest_ts;
-+ struct job *job;
-+
-+ /* Set tool deadline */
-+ tool_deadline_ts = task->start_ts;
-+ inc_timespec(&tool_deadline_ts, task->opts->timeout, 0);
-+
-+ main_lock(task);
-+ while (!task->aborted && task->num_jobs_active > 0) {
-+ /* Calculate nearest timeout */
-+ earliest_timeout = 0;
-+ earliest_ts = NULL;
-+ earliest_thread = NULL;
-+
-+ if (task->opts->timeout > 0) {
-+ earliest_timeout = task->opts->timeout;
-+ earliest_ts = &tool_deadline_ts;
-+ }
-+
-+ for (i = 0; i < task->opts->jobs; i++) {
-+ job = threads[i].job;
-+ if (!job || !job->timed)
-+ continue;
-+ if (task->opts->file_timeout == 0)
-+ continue;
-+ if (!earliest_ts ||
-+ ts_before(&job->deadline, earliest_ts)) {
-+ earliest_timeout = task->opts->file_timeout;
-+ earliest_ts = &job->deadline;
-+ earliest_thread = &threads[i];
-+ }
-+ }
-+
-+ /* Wait for status change or timeout */
-+ if (earliest_ts) {
-+ deadline_ts = *earliest_ts;
-+ rc = _main_wait_timed(task, &deadline_ts);
-+ } else {
-+ rc = _main_wait(task);
-+ }
-+
-+ if (rc == 0)
-+ continue;
-+ if (rc != ETIMEDOUT) {
-+ mwarnx("Cannot wait for status change: %s",
-+ strerror(rc));
-+ _SET_ABORTED(task);
-+ break;
-+ }
-+
-+ /* Timeout handling */
-+ if (earliest_thread) {
-+ /* Per-file timeout, restart */
-+ _timeout_thread(earliest_thread);
-+ rc = 0;
-+ } else {
-+ /* Global timeout, abort */
-+ mwarnx("Operation timed out after %d second%s - "
-+ "aborting", earliest_timeout,
-+ earliest_timeout > 1 ? "s" : "");
-+ _SET_ABORTED(task);
-+ break;
-+ }
-+ }
-+
-+ if (task->aborted)
-+ DBG("aborted");
-+ else
-+ DBG("all work done");
-+ _worker_wakeup_all(task);
-+
-+ /* Allow jobs to finish */
-+ set_timespec(&deadline_ts, 0, NSEC_PER_SEC / 4);
-+ while (!task->aborted && num_jobs_running(task, threads) > 0) {
-+ DBG("waiting for %lu processes",
-+ num_jobs_running(task, threads));
-+
-+ if (_main_wait_timed(task, &deadline_ts))
-+ break;
-+ }
-+
-+ main_unlock(task);
-+
-+ return rc;
-+}
-+
-+/* Finalize output stream */
-+static void close_output(struct task *task)
-+{
-+#ifdef HAVE_ZLIB
-+ if (task->opts->gzip) {
-+ gzclose(task->output_gzfd);
-+ return;
-+ }
-+#endif /* HAVE_ZLIB */
-+
-+ if (task->output_fd != STDOUT_FILENO)
-+ close(task->output_fd);
-+}
-+
-+/* Start multi-threaded processing of job queue */
-+static int process_queue_threaded(struct task *task)
-+{
-+ struct per_thread *threads, *thread;
-+ int rc;
-+ long i;
-+
-+ tverb("Using %ld threads\n", task->opts->jobs);
-+ threads = mcalloc(sizeof(struct per_thread), task->opts->jobs);
-+
-+ rc = 0;
-+ for (i = 0; i < task->opts->jobs; i++) {
-+ init_thread(&threads[i], task, i);
-+ rc = start_worker_thread(&threads[i]);
-+ if (rc)
-+ break;
-+ }
-+
-+ if (!rc)
-+ wait_for_completion(task, threads);
-+
-+ DBG("thread cleanup");
-+ for (i = 0; i < task->opts->jobs; i++) {
-+ thread = &threads[i];
-+ if (thread->running) {
-+ DBG("cancel %p", thread->thread);
-+ pthread_cancel(thread->thread);
-+ }
-+ DBG("join %p", thread->thread);
-+ pthread_join(thread->thread, NULL);
-+ add_stats(&task->stats, &thread->stats);
-+ cleanup_thread(thread);
-+ }
-+
-+ free(threads);
-+
-+ return rc;
-+}
-+
-+/* Abort any remaining queued jobs and account to @stats */
-+static void abort_queued_jobs(struct task *task)
-+{
-+ struct job *job;
-+
-+ while ((job = _dequeue_job(task))) {
-+ DBG("aborting job %s", job->inname);
-+ task->stats.num_failed++;
-+ job->status = JOB_FAILED;
-+ _complete_job(task, job);
-+ }
-+}
-+
-+/* Print a summary line */
-+static void print_summary(struct task *task)
-+{
-+ char msg[MSG_LEN];
-+ size_t off = 0;
-+ int rc;
-+ struct stats *stats = &task->stats;
-+ struct timespec end_ts;
-+ int num_special;
-+ unsigned long num_added;
-+
-+ if (task->opts->quiet)
-+ return;
-+ set_timespec(&end_ts, 0, 0);
-+
-+ num_special = 0;
-+ num_special += stats->num_partial > 0 ? 1 : 0;
-+ num_special += stats->num_excluded > 0 ? 1 : 0;
-+ num_special += stats->num_failed > 0 ? 1 : 0;
-+
-+ num_added = stats->num_done;
-+ if (task->opts->ignore_failed_read)
-+ num_added += stats->num_partial + stats->num_failed;
-+
-+ rc = snprintf(&msg[off], MSG_LEN - off, "Dumped %lu entries ",
-+ num_added);
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+
-+ if (num_special > 0) {
-+ rc = snprintf(&msg[off], MSG_LEN - off, "(");
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+ if (stats->num_partial > 0) {
-+ rc = snprintf(&msg[off], MSG_LEN - off, "%lu partial",
-+ stats->num_partial);
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+ if (--num_special > 0) {
-+ rc = snprintf(&msg[off], MSG_LEN - off, ", ");
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+ }
-+ }
-+ if (stats->num_excluded > 0) {
-+ rc = snprintf(&msg[off], MSG_LEN - off, "%lu excluded",
-+ stats->num_excluded);
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+ if (--num_special > 0) {
-+ rc = snprintf(&msg[off], MSG_LEN - off, ", ");
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+ }
-+ }
-+ if (stats->num_failed > 0) {
-+ rc = snprintf(&msg[off], MSG_LEN - off, "%lu failed",
-+ stats->num_failed);
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+ }
-+ rc = snprintf(&msg[off], MSG_LEN - off, ") ");
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+ }
-+
-+ rc = snprintf(&msg[off], MSG_LEN - off, "in ");
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+ snprintf_duration(&msg[off], MSG_LEN - off, &task->start_ts, &end_ts);
-+
-+out:
-+ info("%s\n", msg);
-+}
-+
-+static int init_task(struct task *task, struct dump_opts *opts)
-+{
-+ pthread_condattr_t attr;
-+
-+ memset(task, 0, sizeof(struct task));
-+ set_timespec(&task->start_ts, 0, 0);
-+ task->opts = opts;
-+ pthread_mutex_init(&task->mutex, NULL);
-+ pthread_mutex_init(&task->output_mutex, NULL);
-+ pthread_cond_init(&task->worker_cond, NULL);
-+
-+ pthread_condattr_init(&attr);
-+ if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC) ||
-+ pthread_cond_init(&task->cond, &attr)) {
-+ mwarn("Could not adjust pthread clock");
-+ return EXIT_RUNTIME;
-+ }
-+
-+ return EXIT_OK;
-+}
-+
-+struct dump_opts *dump_opts_new(void)
-+{
-+ struct dump_opts *opts = mmalloc(sizeof(struct dump_opts));
-+
-+ opts->recursive = true;
-+ opts->read_chunk_size = DEFAULT_READ_CHUNK_SIZE;
-+ opts->max_buffer_size = DEFAULT_MAX_BUFFER_SIZE;
-+
-+ return opts;
-+}
-+
-+void dump_opts_free(struct dump_opts *opts)
-+{
-+ unsigned int i;
-+
-+ if (!opts)
-+ return;
-+
-+ free_strarray(&opts->exclude);
-+ for (i = 0; i < opts->num_specs; i++) {
-+ free(opts->specs[i].inname);
-+ free(opts->specs[i].outname);
-+ }
-+ free(opts->specs);
-+ free(opts);
-+}
-+
-+void dump_opts_print(struct dump_opts *opts)
-+{
-+ unsigned int i;
-+
-+ printf("DEBUG: dump_opts at %p\n", opts);
-+ if (!opts)
-+ return;
-+ printf("DEBUG: add_cmd_status=%d\n", opts->add_cmd_status);
-+ printf("DEBUG: append=%d\n", opts->append);
-+ printf("DEBUG: dereference=%d\n", opts->dereference);
-+ for (i = 0; i < NUM_EXCLUDE_TYPES; i++)
-+ printf("DEBUG: exclude_type[%d]=%d\n", i,
-+ opts->exclude_type[i]);
-+ printf("DEBUG: gzip=%d\n", opts->gzip);
-+ printf("DEBUG: ignore_failed_read=%d\n", opts->ignore_failed_read);
-+ printf("DEBUG: no_eof=%d\n", opts->no_eof);
-+ printf("DEBUG: quiet=%d\n", opts->quiet);
-+ printf("DEBUG: recursive=%d\n", opts->recursive);
-+ printf("DEBUG: threaded=%d\n", opts->threaded);
-+ printf("DEBUG: verbose=%d\n", opts->verbose);
-+ printf("DEBUG: output_file=%s\n", opts->output_file);
-+ printf("DEBUG: file_timeout=%d\n", opts->file_timeout);
-+ printf("DEBUG: timeout=%d\n", opts->timeout);
-+ printf("DEBUG: jobs=%ld\n", opts->jobs);
-+ printf("DEBUG: jobs_per_cpu=%ld\n", opts->jobs_per_cpu);
-+ printf("DEBUG: file_max_size=%zu\n", opts->file_max_size);
-+ printf("DEBUG: max_buffer_size=%zu\n", opts->max_buffer_size);
-+ printf("DEBUG: max_size=%zu\n", opts->max_size);
-+ printf("DEBUG: read_chunk_size=%zu\n", opts->read_chunk_size);
-+ for (i = 0; i < opts->exclude.num; i++)
-+ printf("DEBUG: exclude[%d]=%s\n", i, opts->exclude.str[i]);
-+ for (i = 0; i < opts->num_specs; i++) {
-+ printf("DEBUG: specs[%d]:\n", i);
-+ printf("DEBUG: inname=%s\n", opts->specs[i].inname);
-+ printf("DEBUG: outname=%s\n", opts->specs[i].outname);
-+ printf("DEBUG: is_cmd=%d\n", opts->specs[i].is_cmd);
-+ }
-+}
-+
-+/* Mark file type associated with character @c as excluded */
-+int dump_opts_set_type_excluded(struct dump_opts *opts, char c)
-+{
-+ int i;
-+
-+ for (i = 0; i < NUM_EXCLUDE_TYPES; i++) {
-+ if (exclude_types[i].c == c) {
-+ opts->exclude_type[i] = true;
-+ return 0;
-+ }
-+ }
-+ return -1;
-+}
-+
-+/* Add entry specification defined by @iname, @outname and @op to @opts. */
-+void dump_opts_add_spec(struct dump_opts *opts, char *inname, char *outname,
-+ bool is_cmd)
-+{
-+ unsigned int i = opts->num_specs;
-+
-+ opts->specs = mrealloc(opts->specs, (i + 1) * sizeof(struct dump_spec));
-+ opts->specs[i].inname = mstrdup(inname);
-+ if (outname)
-+ opts->specs[i].outname = mstrdup(outname);
-+ else
-+ opts->specs[i].outname = NULL;
-+ opts->specs[i].is_cmd = is_cmd;
-+ opts->num_specs++;
-+}
-+
-+int dump_to_tar(struct dump_opts *opts)
-+{
-+ struct task task;
-+ int rc;
-+ long num_cpus;
-+
-+ if (opts->jobs_per_cpu > 0) {
-+ num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
-+ if (num_cpus < 1) {
-+ mwarn("Cannot determine number of CPUs - assuming 1 "
-+ "CPU");
-+ num_cpus = 1;
-+ }
-+ opts->jobs = num_cpus;
-+ }
-+
-+ if (opts->jobs == 0 && (opts->timeout > 0 || opts->file_timeout > 0)) {
-+ /* Separate thread needed to implement timeout via cancel */
-+ opts->jobs = 1;
-+ }
-+
-+ rc = init_task(&task, opts);
-+ if (rc)
-+ return rc;
-+
-+ /* Queue initial job */
-+ init_queue(&task);
-+
-+ /* Process queue */
-+ if (opts->jobs > 0)
-+ rc = process_queue_threaded(&task);
-+ else
-+ rc = process_queue(&task);
-+ abort_queued_jobs(&task);
-+
-+ if (task.output_num_files > 0 && !opts->no_eof)
-+ write_eof(&task);
-+
-+ print_summary(&task);
-+
-+ close_output(&task);
-+
-+ if (rc == 0 && task.aborted)
-+ rc = EXIT_RUNTIME;
-+
-+ return rc;
-+}
---- /dev/null
-+++ b/dump2tar/src/dump2tar.c
-@@ -0,0 +1,474 @@
-+/*
-+ * dump2tar - tool to dump files and command output into a tar archive
-+ *
-+ * Command line interface
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include "dump.h"
-+#include "global.h"
-+#include "idcache.h"
-+#include "misc.h"
-+#include "strarray.h"
-+#include "util_opt.h"
-+#include "util_prg.h"
-+
-+#define MIN_BUFFER_SIZE 4096
-+
-+#define OPT_NOSHORT_BASE 256
-+
-+#define OPT_DEREFERENCE (OPT_NOSHORT_BASE + 0)
-+#define OPT_NORECURSION (OPT_NOSHORT_BASE + 1)
-+#define OPT_EXCLUDETYPE (OPT_NOSHORT_BASE + 2)
-+
-+/* Program description */
-+static const struct util_prg dump2tar_prg = {
-+ .desc = "Use dump2tar to create a tar archive from the contents "
-+ "of arbitrary files.\nIt works even when the size of actual "
-+ "file content is not known beforehand,\nsuch as with FIFOs, "
-+ "character devices or certain Linux debugfs or sysfs files.\n"
-+ "\nYou can also add files under different names and add "
-+ "command output using the\nformat described in section SPECS "
-+ "below. When no additional options are\nspecified, the "
-+ "resulting archive is written to the standard output stream\n"
-+ "in uncompressed tar format.",
-+ .args = "SPECS",
-+ .copyright_vec = {
-+ { "IBM Corp.", 2016, 2016 },
-+ UTIL_PRG_COPYRIGHT_END
-+ },
-+};
-+
-+/* Definition of command line options */
-+static struct util_opt dump2tar_opts[] = {
-+ UTIL_OPT_SECTION("OUTPUT OPTIONS"),
-+ {
-+ .option = { "output-file", required_argument, NULL, 'o' },
-+ .argument = "FILE",
-+ .desc = "Write archive to FILE (default: standard output)",
-+ },
-+#ifdef HAVE_ZLIB
-+ {
-+ .option = { "gzip", no_argument, NULL, 'z' },
-+ .desc = "Write a gzip compressed archive",
-+ },
-+#endif /* HAVE_ZLIB */
-+ {
-+ .option = { "max-size", required_argument, NULL, 'm' },
-+ .argument = "N",
-+ .desc = "Stop adding files when archive size exceeds N bytes",
-+ },
-+ {
-+ .option = { "timeout", required_argument, NULL, 't' },
-+ .argument = "SEC",
-+ .desc = "Stop adding files after SEC seconds",
-+ },
-+ {
-+ .option = { "no-eof", no_argument, NULL, 131 },
-+ .desc = "Do not write an end-of-file marker",
-+ .flags = UTIL_OPT_FLAG_NOSHORT,
-+ },
-+ {
-+ .option = { "add-cmd-status", no_argument, NULL, 132 },
-+ .desc = "Add status of commands as separate file",
-+ .flags = UTIL_OPT_FLAG_NOSHORT,
-+ },
-+ {
-+ .option = { "append", no_argument, NULL, 133 },
-+ .desc = "Append output to end of file",
-+ .flags = UTIL_OPT_FLAG_NOSHORT,
-+ },
-+
-+ UTIL_OPT_SECTION("INPUT OPTIONS"),
-+ {
-+ .option = { "files-from", required_argument, NULL, 'F' },
-+ .argument = "FILE",
-+ .desc = "Read filenames from FILE (- for standard input)",
-+ },
-+ {
-+ .option = { "ignore-failed-read", no_argument, NULL, 'i' },
-+ .desc = "Continue after read errors",
-+ },
-+ {
-+ .option = { "buffer-size", required_argument, NULL, 'b' },
-+ .argument = "N",
-+ .desc = "Read data in chunks of N byte (default: 16384)",
-+ },
-+ {
-+ .option = { "file-timeout", required_argument, NULL, 'T' },
-+ .desc = "Stop reading file after SEC seconds",
-+ },
-+ {
-+ .option = { "file-max-size", required_argument, NULL, 'M' },
-+ .argument = "N",
-+ .desc = "Stop reading file after N bytes",
-+ },
-+ {
-+ .option = { "jobs", required_argument, NULL, 'j' },
-+ .argument = "N",
-+ .desc = "Read N files in parallel (default: 1)",
-+ },
-+ {
-+ .option = { "jobs-per-cpu", required_argument, NULL, 'J' },
-+ .argument = "N",
-+ .desc = "Read N files per CPU in parallel",
-+ },
-+ {
-+ .option = { "exclude", required_argument, NULL, 'x' },
-+ .argument = "PATTERN",
-+ .desc = "Don't add files matching PATTERN",
-+ },
-+ {
-+ .option = { "exclude-from", required_argument, NULL, 'X' },
-+ .argument = "FILE",
-+ .desc = "Don't add files matching patterns in FILE",
-+ },
-+ {
-+ .option = { "exclude-type", required_argument, NULL,
-+ OPT_EXCLUDETYPE },
-+ .argument = "TYPE",
-+ .desc = "Don't add files of specified TYPE (one of: fdcbpls)",
-+ .flags = UTIL_OPT_FLAG_NOSHORT,
-+ },
-+ {
-+ .option = { "dereference", no_argument, NULL, OPT_DEREFERENCE },
-+ .desc = "Add link targets instead of links",
-+ .flags = UTIL_OPT_FLAG_NOSHORT,
-+ },
-+ {
-+ .option = { "no-recursion", no_argument, NULL,
-+ OPT_NORECURSION },
-+ .desc = "Don't add files from sub-directories",
-+ .flags = UTIL_OPT_FLAG_NOSHORT,
-+ },
-+
-+ UTIL_OPT_SECTION("MISC OPTIONS"),
-+ UTIL_OPT_HELP,
-+ UTIL_OPT_VERSION,
-+ {
-+ .option = { "verbose", no_argument, NULL, 'V' },
-+ .desc = "Print additional informational output",
-+ },
-+ {
-+ .option = { "quiet", no_argument, NULL, 'q' },
-+ .desc = "Suppress printing of informational output",
-+ },
-+ UTIL_OPT_END,
-+};
-+
-+/* Split buffer size specification in @arg into two numbers to be stored in
-+ * @from_ptr and @to_ptr. Return %EXIT_OK on success. */
-+static int parse_buffer_size(char *arg, size_t *from_ptr, size_t *to_ptr)
-+{
-+ char *err;
-+ unsigned long from, to;
-+
-+ if (!*arg) {
-+ mwarnx("Empty buffer size specified");
-+ return EXIT_USAGE;
-+ }
-+
-+ from = strtoul(arg, &err, 10);
-+
-+ if (*err == '-')
-+ to = strtoul(err + 1, &err, 10);
-+ else
-+ to = *to_ptr;
-+
-+ if (*err) {
-+ mwarnx("Invalid buffer size: %s", arg);
-+ return EXIT_USAGE;
-+ }
-+
-+ if (from < MIN_BUFFER_SIZE || to < MIN_BUFFER_SIZE) {
-+ mwarnx("Buffer size too low (minimum %u)", MIN_BUFFER_SIZE);
-+ return EXIT_USAGE;
-+ }
-+
-+ if (to < from)
-+ to = from;
-+
-+ *from_ptr = from;
-+ *to_ptr = to;
-+
-+ return EXIT_OK;
-+}
-+
-+static void parse_and_add_spec(struct dump_opts *opts, const char *spec)
-+{
-+ char *op, *s, *inname, *outname = NULL;
-+ bool is_cmd = false;
-+
-+ s = mstrdup(spec);
-+ op = strstr(s, "|=");
-+ if (op)
-+ is_cmd = true;
-+ else
-+ op = strstr(s, ":=");
-+
-+ if (op) {
-+ *op = 0;
-+ inname = op + 2;
-+ outname = s;
-+ } else {
-+ inname = s;
-+ }
-+ dump_opts_add_spec(opts, inname, outname, is_cmd);
-+ free(s);
-+}
-+
-+static int add_specs_from_file(struct dump_opts *opts, const char *filename)
-+{
-+ FILE *fd;
-+ char *line = NULL;
-+ size_t line_size;
-+ int rc = EXIT_RUNTIME;
-+ bool need_close = false, parse_spec = true;
-+
-+ if (strcmp(filename, "-") == 0)
-+ fd = stdin;
-+ else {
-+ fd = fopen(filename, "r");
-+ if (!fd) {
-+ mwarn("%s: Cannot open file", filename);
-+ goto out;
-+ }
-+ need_close = true;
-+ }
-+
-+ while ((getline(&line, &line_size, fd) != -1)) {
-+ chomp(line, "\n");
-+ if (line[0] == 0)
-+ continue;
-+ if (parse_spec && strcmp(line, "--") == 0) {
-+ /* After a line containing --, no more := or |= specs
-+ * are expected */
-+ parse_spec = false;
-+ continue;
-+ }
-+ if (parse_spec)
-+ parse_and_add_spec(opts, line);
-+ else
-+ dump_opts_add_spec(opts, line, NULL, false);
-+ }
-+
-+ if (ferror(fd))
-+ mwarn("%s: Cannot read file", filename);
-+ else
-+ rc = EXIT_OK;
-+
-+out:
-+ if (need_close)
-+ fclose(fd);
-+ free(line);
-+
-+ return rc;
-+}
-+
-+static void print_help(void)
-+{
-+ static const struct {
-+ const char *name;
-+ const char *desc;
-+ } specs[] = {
-+ { "PATH", "Add file or directory at PATH" },
-+ { "NEWPATH:=PATH", "Add file or directory at PATH as NEWPATH" },
-+ { "NEWPATH|=CMDLINE", "Add output of command line CMDLINE as "
-+ "NEWPATH" },
-+ { NULL, NULL },
-+ };
-+ int i;
-+
-+ util_prg_print_help();
-+ printf("SPECS\n");
-+ for (i = 0; specs[i].name; i++)
-+ util_opt_print_indented(specs[i].name, specs[i].desc);
-+ printf("\n");
-+ util_opt_print_help();
-+}
-+
-+int main(int argc, char *argv[])
-+{
-+ int rc = EXIT_USAGE, opt;
-+ long i;
-+ struct dump_opts *opts;
-+
-+ if (getenv("DUMP2TAR_DEBUG"))
-+ global_debug = true;
-+
-+ util_prg_init(&dump2tar_prg);
-+ util_opt_init(dump2tar_opts, "-");
-+ misc_init();
-+
-+ opts = dump_opts_new();
-+ opterr = 0;
-+ while ((opt = util_opt_getopt_long(argc, argv)) != -1) {
-+ switch (opt) {
-+ case 'h': /* --help */
-+ print_help();
-+ rc = EXIT_OK;
-+ goto out;
-+ case 'v': /* --version */
-+ util_prg_print_version();
-+ rc = EXIT_OK;
-+ goto out;
-+ case 'V': /* --verbose */
-+ global_verbose = true;
-+ global_quiet = false;
-+ opts->verbose = true;
-+ opts->quiet = false;
-+ break;
-+ case 'q': /* --quiet */
-+ global_quiet = true;
-+ global_verbose = false;
-+ opts->quiet = true;
-+ opts->verbose = false;
-+ break;
-+ case 'i': /* --ignore-failed-read */
-+ opts->ignore_failed_read = true;
-+ break;
-+ case 'j': /* --jobs N */
-+ opts->jobs = atoi(optarg);
-+ if (opts->jobs < 1) {
-+ mwarnx("Invalid number of jobs: %s", optarg);
-+ goto out;
-+ }
-+ break;
-+ case 'J': /* --jobs-per-cpu N */
-+ opts->jobs_per_cpu = atoi(optarg);
-+ if (opts->jobs_per_cpu < 1) {
-+ mwarnx("Invalid number of jobs: %s", optarg);
-+ goto out;
-+ }
-+ break;
-+ case 'b': /* --buffer-size N */
-+ if (parse_buffer_size(optarg, &opts->read_chunk_size,
-+ &opts->max_buffer_size))
-+ goto out;
-+ break;
-+ case 'x': /* --exclude PATTERN */
-+ add_str_to_strarray(&opts->exclude, optarg);
-+ break;
-+ case 'X': /* --exclude-from FILE */
-+ if (add_file_to_strarray(&opts->exclude, optarg))
-+ goto out;
-+ break;
-+ case 'F': /* --files-from FILE */
-+ if (add_specs_from_file(opts, optarg))
-+ goto out;
-+ break;
-+ case 'o': /* --output-file FILE */
-+ if (opts->output_file) {
-+ mwarnx("Output file specified multiple times");
-+ goto out;
-+ }
-+ opts->output_file = optarg;
-+ break;
-+ case OPT_DEREFERENCE: /* --dereference */
-+ opts->dereference = true;
-+ break;
-+ case OPT_NORECURSION: /* --no-recursion */
-+ opts->recursive = false;
-+ break;
-+ case OPT_EXCLUDETYPE: /* --exclude-type TYPE */
-+ for (i = 0; optarg[i]; i++) {
-+ if (dump_opts_set_type_excluded(opts,
-+ optarg[i]))
-+ break;
-+
-+ }
-+ if (optarg[i]) {
-+ mwarnx("Unrecognized file type: %c", optarg[i]);
-+ goto out;
-+ }
-+ break;
-+ case 131: /* --no-eof */
-+ opts->no_eof = true;
-+ break;
-+ case 132: /* --add-cmd-status */
-+ opts->add_cmd_status = true;
-+ break;
-+ case 133: /* --append */
-+ opts->append = true;
-+ break;
-+ case 't': /* --timeout VALUE */
-+ opts->timeout = atoi(optarg);
-+ if (opts->timeout < 1) {
-+ mwarnx("Invalid timeout value: %s", optarg);
-+ goto out;
-+ }
-+ break;
-+ case 'T': /* --file-timeout VALUE */
-+ opts->file_timeout = atoi(optarg);
-+ if (opts->file_timeout < 1) {
-+ mwarnx("Invalid timeout value: %s", optarg);
-+ goto out;
-+ }
-+ break;
-+ case 'm': /* --max-size N */
-+ opts->max_size = atol(optarg);
-+ if (opts->max_size < 2) {
-+ mwarnx("Invalid maximum size: %s", optarg);
-+ goto out;
-+ }
-+ break;
-+ case 'M': /* --file-max-size N */
-+ opts->file_max_size = atol(optarg);
-+ if (opts->file_max_size < 2) {
-+ mwarnx("Invalid maximum size: %s", optarg);
-+ goto out;
-+ }
-+ break;
-+ case 'z': /* --gzip */
-+ opts->gzip = true;
-+ break;
-+ case 1: /* Filename specification or unrecognized option */
-+ if (optarg[0] == '-') {
-+ mwarnx("Invalid option '%s'", optarg);
-+ goto out;
-+ }
-+ parse_and_add_spec(opts, optarg);
-+ break;
-+ case '?': /* Unrecognized option */
-+ if (optopt)
-+ mwarnx("Invalid option '-%c'", optopt);
-+ else
-+ mwarnx("Invalid option '%s'", argv[optind - 1]);
-+ goto out;
-+ case ':': /* Missing argument */
-+ mwarnx("Option '%s' requires an argument",
-+ argv[optind - 1]);
-+ goto out;
-+ default:
-+ break;
-+ }
-+ }
-+ if (optind >= argc && opts->num_specs == 0) {
-+ mwarnx("Please specify files to dump");
-+ goto out;
-+ }
-+
-+ for (i = optind; i < argc; i++)
-+ dump_opts_add_spec(opts, argv[i], NULL, false);
-+
-+ rc = dump_to_tar(opts);
-+
-+out:
-+ idcache_cleanup();
-+ misc_cleanup();
-+ dump_opts_free(opts);
-+
-+ if (rc == EXIT_USAGE)
-+ util_prg_print_parse_error();
-+
-+ return rc;
-+}
---- /dev/null
-+++ b/dump2tar/src/global.c
-@@ -0,0 +1,17 @@
-+/*
-+ * dump2tar - tool to dump files and command output into a tar archive
-+ *
-+ * Global variables
-+ *
-+ * Copyright IBM Corp. 2016
-+ *
-+ */
-+
-+#include "global.h"
-+
-+/* Global settings */
-+bool global_threaded;
-+bool global_debug;
-+bool global_verbose;
-+bool global_quiet;
-+bool global_timestamps;
---- /dev/null
-+++ b/dump2tar/src/idcache.c
-@@ -0,0 +1,153 @@
-+/*
-+ * dump2tar - tool to dump files and command output into a tar archive
-+ *
-+ * Caches for user and group ID lookups
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#include "idcache.h"
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include "global.h"
-+#include "misc.h"
-+
-+/* Maximum user and group name lengths as defined in tar header */
-+#define ID_NAME_MAXLEN 32
-+
-+/* Types for user and group ID caches */
-+typedef uid_t generic_id_t; /* Assumes that uid_t == gid_t */
-+
-+struct id_cache_entry {
-+ generic_id_t id;
-+ char name[ID_NAME_MAXLEN];
-+};
-+
-+struct id_cache {
-+ unsigned int num;
-+ struct id_cache_entry entries[];
-+};
-+
-+/* cache_mutex serializes access to cached uid and gid data */
-+static pthread_mutex_t id_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
-+static struct id_cache *id_cache_uid;
-+static struct id_cache *id_cache_gid;
-+
-+/* Lock cache mutex */
-+static void cache_lock(void)
-+{
-+ if (!global_threaded)
-+ return;
-+ pthread_mutex_lock(&id_cache_mutex);
-+}
-+
-+/* Unlock cache mutex */
-+static void cache_unlock(void)
-+{
-+ if (!global_threaded)
-+ return;
-+ pthread_mutex_unlock(&id_cache_mutex);
-+}
-+
-+/* Copy the name associated with @id in @cache to at most @len bytes at @dest.
-+ * Return %true if name was found in cache, %false otherwise. */
-+static bool strncpy_id_cache_entry(char *dest, struct id_cache *cache,
-+ generic_id_t id, size_t len)
-+{
-+ unsigned int i;
-+ bool hit = false;
-+
-+ cache_lock();
-+ if (cache) {
-+ for (i = 0; i < cache->num; i++) {
-+ if (cache->entries[i].id == id) {
-+ strncpy(dest, cache->entries[i].name, len);
-+ hit = true;
-+ break;
-+ }
-+ }
-+ }
-+ cache_unlock();
-+
-+ return hit;
-+}
-+
-+/* Add a new entry consisting of @id and @name to ID cache in @*cache_ptr.
-+ * Update @cache_ptr if necessary. */
-+static void add_id_cache_entry(struct id_cache **cache_ptr, generic_id_t id,
-+ char *name)
-+{
-+ struct id_cache *cache;
-+ unsigned int cache_num;
-+ size_t new_size;
-+ struct id_cache *new_cache;
-+
-+ cache_lock();
-+
-+ cache = *cache_ptr;
-+ cache_num = cache ? cache->num : 0;
-+ new_size = sizeof(struct id_cache) +
-+ sizeof(struct id_cache_entry) * (cache_num + 1);
-+ new_cache = mrealloc(cache, new_size);
-+ if (cache_num == 0)
-+ new_cache->num = 0;
-+ new_cache->entries[cache_num].id = id;
-+ strncpy(new_cache->entries[cache_num].name, name, ID_NAME_MAXLEN);
-+ new_cache->num++;
-+ *cache_ptr = new_cache;
-+
-+ cache_unlock();
-+}
-+
-+/* Copy the user name corresponding to user ID @uid to at most @len bytes
-+ * at @name */
-+void uid_to_name(uid_t uid, char *name, size_t len)
-+{
-+ struct passwd pwd, *pwd_ptr;
-+ char buffer[PWD_BUFFER_SIZE], *result;
-+
-+ if (strncpy_id_cache_entry(name, id_cache_uid, uid, len))
-+ return;
-+
-+ /* getpwuid() can be slow so cache results */
-+ getpwuid_r(uid, &pwd, buffer, PWD_BUFFER_SIZE, &pwd_ptr);
-+ if (!pwd_ptr || !pwd_ptr->pw_name)
-+ return;
-+ result = pwd_ptr->pw_name;
-+
-+ add_id_cache_entry(&id_cache_uid, uid, result);
-+
-+ strncpy(name, result, len);
-+}
-+
-+/* Copy the group name corresponding to group ID @gid to at most @len bytes
-+ * at @name */
-+void gid_to_name(gid_t gid, char *name, size_t len)
-+{
-+ struct group grp, *grp_ptr;
-+ char buffer[GRP_BUFFER_SIZE], *result;
-+
-+ if (strncpy_id_cache_entry(name, id_cache_gid, gid, len))
-+ return;
-+
-+ /* getgrgid() can be slow so cache results */
-+ getgrgid_r(gid, &grp, buffer, GRP_BUFFER_SIZE, &grp_ptr);
-+ if (!grp_ptr || !grp_ptr->gr_name)
-+ return;
-+ result = grp_ptr->gr_name;
-+
-+ add_id_cache_entry(&id_cache_gid, gid, result);
-+
-+ strncpy(name, result, len);
-+}
-+
-+void idcache_cleanup(void)
-+{
-+ free(id_cache_uid);
-+ free(id_cache_gid);
-+}
---- /dev/null
-+++ b/dump2tar/src/misc.c
-@@ -0,0 +1,492 @@
-+/*
-+ * dump2tar - tool to dump files and command output into a tar archive
-+ *
-+ * Helper functions
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#define _GNU_SOURCE /* for program_invocation_short_name */
-+
-+#include "misc.h"
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include "dref.h"
-+#include "global.h"
-+
-+struct timespec main_start_ts;
-+
-+static pthread_key_t thread_name_key;
-+static bool stdout_data;
-+
-+/* Write @len bytes at @addr to @fd. Return %EXIT_OK on success, %EXIT_RUNTIME
-+ * otherwise. */
-+int misc_write_data(int fd, char *addr, size_t len)
-+{
-+ ssize_t w;
-+
-+ while (len > 0) {
-+ w = write(fd, addr, len);
-+ if (w < 0)
-+ return EXIT_RUNTIME;
-+ len -= w;
-+ addr += w;
-+ }
-+
-+ return EXIT_OK;
-+}
-+
-+/* Read at most @len bytes from @fd to @addr. Return the number of bytes read
-+ * or %-1 on error. */
-+ssize_t misc_read_data(int fd, char *addr, size_t len)
-+{
-+ size_t done = 0;
-+ ssize_t r;
-+
-+ while (len > 0) {
-+ r = read(fd, addr, len);
-+ if (r < 0)
-+ return -1;
-+ if (r == 0)
-+ break;
-+ len -= r;
-+ addr += r;
-+ done += r;
-+ }
-+
-+ return done;
-+}
-+
-+/* Advance timespec @ts by @sec seconds and @nsec nanoseconds */
-+void inc_timespec(struct timespec *ts, time_t sec, long nsec)
-+{
-+ ts->tv_nsec += nsec;
-+ ts->tv_sec += sec;
-+ if (ts->tv_nsec > NSEC_PER_SEC) {
-+ ts->tv_nsec -= NSEC_PER_SEC;
-+ ts->tv_sec++;
-+ }
-+}
-+
-+/* Set timespec @ts to point to @sec seconds and @nsec nanoseconds in the
-+ * future */
-+void set_timespec(struct timespec *ts, time_t sec, long nsec)
-+{
-+ clock_gettime(CLOCK_MONOTONIC, ts);
-+ inc_timespec(ts, sec, nsec);
-+}
-+
-+/* Return true if timespec @a refers to a point in time before @b */
-+bool ts_before(struct timespec *a, struct timespec *b)
-+{
-+ if (a->tv_sec < b->tv_sec ||
-+ (a->tv_sec == b->tv_sec && a->tv_nsec < b->tv_nsec))
-+ return true;
-+
-+ return false;
-+}
-+
-+/* Store a string representing the time duration between @start and @end in
-+ * at most @len bytes of @buff. */
-+int snprintf_duration(char *buff, size_t len, struct timespec *start,
-+ struct timespec *end)
-+{
-+ time_t sec;
-+ long nsec, msec, s, m, h;
-+
-+ sec = end->tv_sec - start->tv_sec;
-+ nsec = end->tv_nsec - start->tv_nsec;
-+
-+ if (nsec < 0) {
-+ nsec += NSEC_PER_SEC;
-+ sec--;
-+ }
-+
-+ msec = nsec / NSEC_PER_MSEC;
-+ s = sec % 60;
-+ sec /= 60;
-+ m = sec % 60;
-+ sec /= 60;
-+ h = sec;
-+
-+ if (h > 0)
-+ return snprintf(buff, len, "%luh%lum%lu.%03lus", h, m, s, msec);
-+ else if (m > 0)
-+ return snprintf(buff, len, "%lum%lu.%03lus", m, s, msec);
-+ else
-+ return snprintf(buff, len, "%lu.%03lus", s, msec);
-+}
-+
-+/* Return the name of the current thread */
-+char *get_threadname(void)
-+{
-+ return pthread_getspecific(thread_name_key);
-+}
-+
-+static int snprintf_timestamp(char *str, size_t size)
-+{
-+ struct timespec now_ts;
-+
-+ set_timespec(&now_ts, 0, 0);
-+ now_ts.tv_sec -= main_start_ts.tv_sec;
-+ now_ts.tv_nsec -= main_start_ts.tv_nsec;
-+ if (now_ts.tv_nsec < 0) {
-+ now_ts.tv_nsec += NSEC_PER_SEC;
-+ now_ts.tv_sec--;
-+ }
-+
-+ return snprintf(str, size, "[%3lu.%06lu] ", now_ts.tv_sec,
-+ now_ts.tv_nsec / NSEC_PER_USEC);
-+}
-+
-+/* When DUMP2TAR_DEBUG is set to non-zero, print debugging information */
-+void debug(const char *file, unsigned long line, const char *format, ...)
-+{
-+ char msg[MSG_LEN];
-+ size_t off = 0;
-+ int rc;
-+ va_list args;
-+
-+ /* Debug marker */
-+ rc = snprintf(&msg[off], MSG_LEN - off, "DEBUG: ");
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+
-+ /* Timestamp */
-+ rc = snprintf_timestamp(&msg[off], MSG_LEN - off);
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+
-+ /* Thread name */
-+ rc = snprintf(&msg[off], MSG_LEN - off, "%s: ", get_threadname());
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+
-+ /* Message */
-+ va_start(args, format);
-+ rc = vsnprintf(&msg[off], MSG_LEN - off, format, args);
-+ va_end(args);
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+
-+ /* Call site */
-+ rc = snprintf(&msg[off], MSG_LEN - off, " (%s:%lu)", file, line);
-+
-+out:
-+ fprintf(stderr, "%s\n", msg);
-+}
-+
-+/* Print a warning message consisting of @format and variable arguments.
-+ * If @print_errno is true, also print the text corresponding to errno.
-+ * We're not using err.h's warn since we want timestamps and synchronized
-+ * output. */
-+void _mwarn(bool print_errno, const char *format, ...)
-+{
-+ char msg[MSG_LEN];
-+ size_t off = 0;
-+ int rc;
-+ va_list args;
-+
-+ if (global_timestamps) {
-+ rc = snprintf_timestamp(&msg[off], MSG_LEN - off);
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+ }
-+
-+ rc = snprintf(&msg[off], MSG_LEN - off, "%s: ",
-+ program_invocation_short_name);
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+
-+ va_start(args, format);
-+ rc = vsnprintf(&msg[off], MSG_LEN - off, format, args);
-+ va_end(args);
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+
-+ if (print_errno)
-+ snprintf(&msg[off], MSG_LEN - off, ": %s", strerror(errno));
-+
-+out:
-+ fprintf(stderr, "%s\n", msg);
-+}
-+
-+/* Provide informational output if --verbose was specified */
-+void verb(const char *format, ...)
-+{
-+ char msg[MSG_LEN];
-+ size_t off = 0;
-+ int rc;
-+ va_list args;
-+ FILE *fd;
-+
-+ if (!global_verbose)
-+ return;
-+ if (stdout_data)
-+ fd = stderr;
-+ else
-+ fd = stdout;
-+ if (global_timestamps) {
-+ rc = snprintf_timestamp(&msg[off], MSG_LEN - off);
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+ }
-+
-+ va_start(args, format);
-+ rc = vsnprintf(&msg[off], MSG_LEN - off, format, args);
-+ va_end(args);
-+
-+out:
-+ fprintf(fd, "%s", msg);
-+}
-+
-+/* Provide informational output. */
-+void info(const char *format, ...)
-+{
-+ char msg[MSG_LEN];
-+ size_t off = 0;
-+ int rc;
-+ va_list args;
-+ FILE *fd;
-+
-+ if (global_quiet)
-+ return;
-+ if (stdout_data)
-+ fd = stderr;
-+ else
-+ fd = stdout;
-+
-+ if (global_timestamps) {
-+ rc = snprintf_timestamp(&msg[off], MSG_LEN - off);
-+ HANDLE_RC(rc, MSG_LEN, off, out);
-+ }
-+
-+ va_start(args, format);
-+ rc = vsnprintf(&msg[off], MSG_LEN - off, format, args);
-+ va_end(args);
-+
-+out:
-+ fprintf(fd, "%s", msg);
-+}
-+
-+/* Return a newly allocated buffer containing the result of the specified
-+ * string format arguments */
-+char *__masprintf(const char *func, const char *file, int line, const char *fmt,
-+ ...)
-+{
-+ char *str;
-+ va_list args;
-+
-+ va_start(args, fmt);
-+ __util_vasprintf(func, file, line, &str, fmt, args);
-+ va_end(args);
-+
-+ return str;
-+}
-+
-+/* Set the internal name of the calling thread */
-+void __set_threadname(const char *func, const char *file, int line,
-+ const char *fmt, ...)
-+{
-+ char *str;
-+ va_list args;
-+
-+ va_start(args, fmt);
-+ __util_vasprintf(func, file, line, &str, fmt, args);
-+ va_end(args);
-+
-+ pthread_setspecific(thread_name_key, str);
-+}
-+
-+/* Clear any previously set thread name */
-+void clear_threadname(void)
-+{
-+ void *addr = pthread_getspecific(thread_name_key);
-+
-+ if (addr) {
-+ pthread_setspecific(thread_name_key, NULL);
-+ free(addr);
-+ }
-+}
-+
-+/* Remove any number of trailing characters @c in @str */
-+void chomp(char *str, char *c)
-+{
-+ ssize_t i;
-+
-+ for (i = strlen(str) - 1; i >= 0 && strchr(c, str[i]); i--)
-+ str[i] = 0;
-+}
-+
-+/* Remove any number of leading characters @c in @str */
-+void lchomp(char *str, char *c)
-+{
-+ char *from;
-+
-+ for (from = str; *from && strchr(c, *from); from++)
-+ ;
-+ if (str != from)
-+ memmove(str, from, strlen(from) + 1);
-+}
-+
-+/* Perform a stat on file referenced by either @abs or @rel and @dref. Store
-+ * results in @stat and return stat()'s return code. */
-+int stat_file(bool dereference, const char *abs, const char *rel,
-+ struct dref *dref, struct stat *st)
-+{
-+ int rc;
-+
-+ if (dref) {
-+ if (dereference)
-+ rc = fstatat(dref->dirfd, rel, st, 0);
-+ else
-+ rc = fstatat(dref->dirfd, rel, st, AT_SYMLINK_NOFOLLOW);
-+ } else {
-+ if (dereference)
-+ rc = stat(abs, st);
-+ else
-+ rc = lstat(abs, st);
-+ }
-+
-+ return rc;
-+}
-+
-+/* Fill stat buffer @st with dummy values. */
-+void set_dummy_stat(struct stat *st)
-+{
-+ /* Fake stat */
-+ memset(st, 0, sizeof(struct stat));
-+ st->st_mode = S_IRUSR | S_IWUSR | S_IFREG;
-+ st->st_uid = geteuid();
-+ st->st_gid = getegid();
-+ st->st_mtime = time(NULL);
-+}
-+
-+/* Redirect all output streams to @fd and execute command @CMD */
-+int cmd_child(int fd, char *cmd)
-+{
-+ char *argv[] = { "/bin/sh", "-c", NULL, NULL };
-+ char *env[] = { NULL };
-+
-+ argv[2] = cmd;
-+ if (dup2(fd, STDOUT_FILENO) == -1 || dup2(fd, STDERR_FILENO) == -1) {
-+ mwarn("Could not redirect command output");
-+ return EXIT_RUNTIME;
-+ }
-+
-+ execve("/bin/sh", argv, env);
-+
-+ return EXIT_RUNTIME;
-+}
-+
-+#define PIPE_READ 0
-+#define PIPE_WRITE 1
-+
-+/* Run command @cmd as a child process and store its PID in @pid_ptr. On
-+ * success, return a file descriptor that is an output pipe to the standard
-+ * output and standard error streams of the child process. Return %-1 on
-+ * error. */
-+int cmd_open(char *cmd, pid_t *pid_ptr)
-+{
-+ int pfd[2];
-+ pid_t pid;
-+
-+ if (pipe(pfd) < 0)
-+ return -1;
-+
-+ pid = fork();
-+ if (pid < 0) {
-+ /* Fork error */
-+ close(pfd[PIPE_READ]);
-+ close(pfd[PIPE_WRITE]);
-+ return -1;
-+ } else if (pid == 0) {
-+ /* Child process */
-+ close(pfd[PIPE_READ]);
-+ exit(cmd_child(pfd[PIPE_WRITE], cmd));
-+ }
-+
-+ /* Parent process */
-+ close(pfd[PIPE_WRITE]);
-+
-+ *pid_ptr = pid;
-+
-+ return pfd[PIPE_READ];
-+}
-+
-+/* Close the file descriptor @fd and end the process with PID @pid. When
-+ * not %NULL, use @status_ptr to store the resulting process status. */
-+int cmd_close(int fd, pid_t pid, int *status_ptr)
-+{
-+ int status, rc = EXIT_OK;
-+
-+ close(fd);
-+ kill(pid, SIGQUIT);
-+ if (waitpid(pid, &status, 0) == -1) {
-+ status = -errno;
-+ rc = EXIT_RUNTIME;
-+ }
-+ if (status_ptr)
-+ *status_ptr = status;
-+
-+ return rc;
-+}
-+
-+void misc_init(void)
-+{
-+ set_timespec(&main_start_ts, 0, 0);
-+ pthread_key_create(&thread_name_key, free);
-+ set_threadname("main");
-+}
-+
-+void misc_cleanup(void)
-+{
-+ clear_threadname();
-+ pthread_key_delete(thread_name_key);
-+}
-+
-+void set_stdout_data(void)
-+{
-+ stdout_data = true;
-+}
-+
-+bool starts_with(const char *str, const char *prefix)
-+{
-+ size_t len;
-+
-+ len = strlen(prefix);
-+
-+ if (strncmp(str, prefix, len) == 0)
-+ return true;
-+ return false;
-+}
-+
-+bool ends_with(const char *str, const char *suffix)
-+{
-+ size_t str_len, s_len;
-+
-+ str_len = strlen(str);
-+ s_len = strlen(suffix);
-+
-+ if (str_len < s_len)
-+ return false;
-+ if (strcmp(str + str_len - s_len, suffix) != 0)
-+ return false;
-+
-+ return true;
-+}
-+
-+/* Remove subsequent slashes in @str */
-+void remove_double_slashes(char *str)
-+{
-+ size_t i, to;
-+ char last;
-+
-+ last = 0;
-+ for (i = 0, to = 0; str[i]; i++) {
-+ if (last != '/' || str[i] != '/')
-+ last = str[to++] = str[i];
-+ }
-+ str[to] = 0;
-+}
---- /dev/null
-+++ b/dump2tar/src/strarray.c
-@@ -0,0 +1,81 @@
-+/*
-+ * dump2tar - tool to dump files and command output into a tar archive
-+ *
-+ * Dynamically growing string arrays
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#include "strarray.h"
-+
-+#include
-+#include
-+#include
-+
-+#include "misc.h"
-+
-+/* Release resources associated with string array @array */
-+void free_strarray(struct strarray *array)
-+{
-+ unsigned int i;
-+
-+ for (i = 0; i < array->num; i++)
-+ free(array->str[i]);
-+ free(array->str);
-+ array->str = NULL;
-+ array->num = 0;
-+}
-+
-+/* Add string @str to string array @array */
-+void add_str_to_strarray(struct strarray *array, const char *str)
-+{
-+ array->str = mrealloc(array->str, sizeof(char *) * (array->num + 2));
-+ array->str[array->num + 1] = NULL;
-+ array->str[array->num] = mstrdup(str);
-+ array->num++;
-+}
-+
-+/* Add string resulting from @fmt and additional arguments to @array */
-+void add_vstr_to_strarray(struct strarray *array, const char *fmt, ...)
-+{
-+ va_list args;
-+ char *str;
-+
-+ va_start(args, fmt);
-+ util_vasprintf(&str, fmt, args);
-+ va_end(args);
-+
-+ array->str = mrealloc(array->str, sizeof(char *) * (array->num + 2));
-+ array->str[array->num + 1] = NULL;
-+ array->str[array->num] = str;
-+ array->num++;
-+}
-+
-+/* Add all lines in file at @filename to @array */
-+int add_file_to_strarray(struct strarray *array, const char *filename)
-+{
-+ FILE *fd;
-+ char *line = NULL;
-+ size_t line_size;
-+ int rc = EXIT_OK;
-+
-+ fd = fopen(filename, "r");
-+ if (!fd) {
-+ mwarn("%s: Cannot open file", filename);
-+ return EXIT_RUNTIME;
-+ }
-+
-+ while (!feof(fd) && !ferror(fd)) {
-+ if (getline(&line, &line_size, fd) == -1)
-+ continue;
-+ chomp(line, "\n");
-+ add_str_to_strarray(array, line);
-+ }
-+ if (ferror(fd))
-+ rc = EXIT_RUNTIME;
-+ free(line);
-+
-+ fclose(fd);
-+
-+ return rc;
-+}
---- /dev/null
-+++ b/dump2tar/src/tar.c
-@@ -0,0 +1,270 @@
-+/*
-+ * dump2tar - tool to dump files and command output into a tar archive
-+ *
-+ * TAR file generation
-+ *
-+ * Copyright IBM Corp. 2016
-+ */
-+
-+#include "tar.h"
-+
-+#include
-+#include
-+
-+#include "buffer.h"
-+#include "idcache.h"
-+#include "misc.h"
-+
-+#define LONGLINK "././@LongLink"
-+#define TYPE_LONGLINK 'K'
-+#define TYPE_LONGNAME 'L'
-+
-+#define BLOCKSIZE 512
-+
-+/* Basic TAR header */
-+struct tar_header {
-+ char name[100];
-+ char mode[8];
-+ char uid[8];
-+ char gid[8];
-+ char size[12];
-+ char mtime[12];
-+ char chksum[8];
-+ char typeflag;
-+ char linkname[100];
-+ char magic[6];
-+ char version[2];
-+ char uname[32];
-+ char gname[32];
-+ char devmajor[8];
-+ char devminor[8];
-+ char prefix[155];
-+};
-+
-+/* Store the octal value of @value to at most @len bytes at @dest */
-+static void set_octal(char *dest, size_t len, unsigned long value)
-+{
-+ int i;
-+
-+ dest[len - 1] = 0;
-+ for (i = len - 2; i >= 0; i--) {
-+ dest[i] = '0' + (value & 7);
-+ value >>= 3;
-+ }
-+}
-+
-+/* Store time @value to at most @len bytes at @dest */
-+static void set_time(char *dest, size_t len, time_t value)
-+{
-+ time_t max = (1ULL << (3 * (len - 1))) - 1;
-+
-+ if (value >= 0 && value <= max) {
-+ set_octal(dest, len, value);
-+ return;
-+ }
-+
-+ for (; len > 0; len--) {
-+ dest[len - 1] = value & 0xff;
-+ value >>= 8;
-+ }
-+
-+ dest[0] |= 0x80;
-+}
-+
-+#define SET_FIELD(obj, name, value) \
-+ set_octal((obj)->name, sizeof((obj)->name), (unsigned long) (value))
-+#define SET_TIME_FIELD(obj, name, value) \
-+ set_time((obj)->name, sizeof((obj)->name), (time_t) (value))
-+#define SET_STR_FIELD(obj, name, value) \
-+ strncpy((obj)->name, (value), sizeof((obj)->name))
-+
-+/* Initialize the tar file @header with the provided data */
-+static void init_header(struct tar_header *header, const char *filename,
-+ const char *link, size_t len, struct stat *stat,
-+ char type)
-+{
-+ unsigned int i, checksum;
-+ unsigned char *c;
-+
-+ memset(header, 0, sizeof(*header));
-+
-+ /* Fill in header fields */
-+ SET_STR_FIELD(header, name, filename);
-+ if (link)
-+ SET_STR_FIELD(header, linkname, link);
-+ SET_FIELD(header, size, len);
-+ if (stat) {
-+ SET_FIELD(header, mode, stat->st_mode & 07777);
-+ SET_FIELD(header, uid, stat->st_uid);
-+ SET_FIELD(header, gid, stat->st_gid);
-+ SET_TIME_FIELD(header, mtime, stat->st_mtime);
-+ uid_to_name(stat->st_uid, header->uname, sizeof(header->uname));
-+ gid_to_name(stat->st_gid, header->gname, sizeof(header->gname));
-+ } else {
-+ SET_FIELD(header, mode, 0644);
-+ SET_FIELD(header, uid, 0);
-+ SET_FIELD(header, gid, 0);
-+ SET_TIME_FIELD(header, mtime, 0);
-+ uid_to_name(0, header->uname, sizeof(header->uname));
-+ gid_to_name(0, header->gname, sizeof(header->gname));
-+ }
-+ header->typeflag = type;
-+ memcpy(header->magic, "ustar ", sizeof(header->magic));
-+ memcpy(header->version, " ", sizeof(header->version));
-+
-+ /* Calculate checksum */
-+ memset(header->chksum, ' ', sizeof(header->chksum));
-+ checksum = 0;
-+ c = (unsigned char *) header;
-+ for (i = 0; i < sizeof(*header); i++)
-+ checksum += c[i];
-+ snprintf(header->chksum, 7, "%06o", checksum);
-+}
-+
-+/* Emit zero bytes via @emit_cb to pad @len to a multiple of BLOCKSIZE */
-+static int emit_padding(emit_cb_t emit_cb, void *data, size_t len)
-+{
-+ size_t pad = BLOCKSIZE - len % BLOCKSIZE;
-+ char zeroes[BLOCKSIZE];
-+
-+ if (len % BLOCKSIZE > 0) {
-+ memset(zeroes, 0, BLOCKSIZE);
-+ return emit_cb(data, zeroes, pad);
-+ }
-+
-+ return 0;
-+}
-+
-+/* Emit @len bytes at @addr via @emit_cb and pad data to BLOCKSIZE with zero
-+ * bytes */
-+static int emit_data(emit_cb_t emit_cb, void *data, void *addr, size_t len)
-+{
-+ int rc;
-+
-+ if (len == 0)
-+ return 0;
-+
-+ rc = emit_cb(data, addr, len);
-+ if (rc)
-+ return rc;
-+ return emit_padding(emit_cb, data, len);
-+}
-+
-+/* Emit a tar header via @emit_cb */
-+static int emit_header(emit_cb_t emit_cb, void *data, char *filename,
-+ char *link, size_t len, struct stat *stat, char type)
-+{
-+ struct tar_header header;
-+ size_t namelen = strlen(filename);
-+ size_t linklen;
-+ int rc;
-+
-+ /* /proc can contain unreadable links which causes tar to complain
-+ * during extract - use a dummy value to handle this more gracefully */
-+ if (link && !*link)
-+ link = " ";
-+
-+ linklen = link ? strlen(link) : 0;
-+ if (linklen > sizeof(header.linkname)) {
-+ rc = emit_header(emit_cb, data, LONGLINK, NULL, linklen + 1,
-+ NULL, TYPE_LONGLINK);
-+ if (rc)
-+ return rc;
-+ rc = emit_data(emit_cb, data, link, linklen + 1);
-+ if (rc)
-+ return rc;
-+ }
-+ if (namelen > sizeof(header.name)) {
-+ rc = emit_header(emit_cb, data, LONGLINK, NULL, namelen + 1,
-+ NULL, TYPE_LONGNAME);
-+ if (rc)
-+ return rc;
-+ rc = emit_data(emit_cb, data, filename, namelen + 1);
-+ if (rc)
-+ return rc;
-+ }
-+
-+ init_header(&header, filename, link, len, stat, type);
-+ return emit_data(emit_cb, data, &header, sizeof(header));
-+}
-+
-+struct emit_content_cb_data {
-+ emit_cb_t emit_cb;
-+ void *data;
-+ size_t len;
-+ int rc;
-+};
-+
-+/* Callback for emitting a single chunk of data of a buffer */
-+static int emit_content_cb(void *data, void *addr, size_t len)
-+{
-+ struct emit_content_cb_data *cb_data = data;
-+
-+ if (len > cb_data->len)
-+ len = cb_data->len;
-+ cb_data->len -= len;
-+
-+ cb_data->rc = cb_data->emit_cb(cb_data->data, addr, len);
-+
-+ if (cb_data->rc || cb_data->len == 0)
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/* Emit at most @len bytes of contents of @buffer via @emit_cb and pad output
-+ * to BLOCKSIZE with zero bytes */
-+static int emit_content(emit_cb_t emit_cb, void *data, struct buffer *buffer,
-+ size_t len)
-+{
-+ struct emit_content_cb_data cb_data;
-+
-+ cb_data.emit_cb = emit_cb;
-+ cb_data.data = data;
-+ cb_data.len = len;
-+ cb_data.rc = 0;
-+ buffer_iterate(buffer, emit_content_cb, &cb_data);
-+ if (cb_data.rc)
-+ return cb_data.rc;
-+
-+ return emit_padding(emit_cb, data, buffer->total);
-+}
-+
-+/* Convert file meta data and content specified as @content into a
-+ * stream of bytes that is reported via the @emit_cb callback. @data is
-+ * passed through to the callback for arbitrary use. */
-+int tar_emit_file_from_buffer(char *filename, char *link, size_t len,
-+ struct stat *stat, char type,
-+ struct buffer *content, emit_cb_t emit_cb,
-+ void *data)
-+{
-+ int rc;
-+
-+ DBG("emit tar file=%s type=%d len=%zu", filename, type, len);
-+ rc = emit_header(emit_cb, data, filename, link, len, stat, type);
-+ if (rc)
-+ return rc;
-+ if (content)
-+ rc = emit_content(emit_cb, data, content, len);
-+
-+ return rc;
-+}
-+
-+/* Convert file meta data and content specified as @addr and @len into a
-+ * stream of bytes that is reported via the @emit_cb callback. @data is
-+ * passed through to the callback for arbitrary use. */
-+int tar_emit_file_from_data(char *filename, char *link, size_t len,
-+ struct stat *stat, char type, void *addr,
-+ emit_cb_t emit_cb, void *data)
-+{
-+ int rc;
-+
-+ DBG("emit tar file=%s type=%d len=%zu", filename, type, len);
-+ rc = emit_header(emit_cb, data, filename, link, len, stat, type);
-+ if (rc)
-+ return rc;
-+ if (addr)
-+ rc = emit_data(emit_cb, data, addr, len);
-+
-+ return rc;
-+}
diff --git a/s390-tools-sles12sp3-dbginfo-03-dbginfo.sh-Make-use-of-sysinfo-collection-helper.patch b/s390-tools-sles12sp3-dbginfo-03-dbginfo.sh-Make-use-of-sysinfo-collection-helper.patch
deleted file mode 100644
index e37fd0a..0000000
--- a/s390-tools-sles12sp3-dbginfo-03-dbginfo.sh-Make-use-of-sysinfo-collection-helper.patch
+++ /dev/null
@@ -1,72 +0,0 @@
-Subject: [PATCH] [FEAT RTL1601] dbginfo.sh: Make use of sysfs collection helper
-From: Peter Oberparleiter
-
-Summary: dbginfo.sh: Make use of sysfs collection helper
-Description: If available, use dump2tar in dbginfo.sh for sysfs
- file collection to significantly speed up dbginfo.sh
- processing. Example speedup on an LPAR with ~190k
- sysfs files:
-
- Unpatched:
- # time ./dbginfo.sh
- real 1m19.624s
- user 0m44.985s
- sys 0m45.173s
-
- Patched:
- # time ./dbginfo.sh
- real 0m5.822s
- user 0m4.523s
- sys 0m2.636s
-Upstream-ID: -
-Problem-ID: RTL1601
-
-Signed-off-by: Peter Oberparleiter
----
- scripts/dbginfo.sh | 33 +++++++++++++++++++++------------
- 1 file changed, 21 insertions(+), 12 deletions(-)
-
---- a/scripts/dbginfo.sh
-+++ b/scripts/dbginfo.sh
-@@ -620,20 +620,29 @@ collect_sysfs() {
- fi
- fi
-
-- call_run_command "find /sys -print0 | sort -z | xargs -0 -n 10 ls -ld" "${OUTPUT_FILE_SYSFS}"
-+ # Collect sysfs files using multiple threads (-J 1) while excluding
-+ # files known to block on read (-x). Stop reading a file that takes
-+ # more than 5 seconds (-T 5) such as an active ftrace buffer.
-+ dump2tar /sys -z -o "${WORKPATH}/sysfs.tgz" -x '*/tracing/trace_pipe*' \
-+ -x '*/tracing/per_cpu/*' --ignore-failed-read -J 1 -T 5
-
-- find /sys -noleaf -type d 2>/dev/null | while IFS= read -r dir_name; do
-- mkdir -p "${WORKPATH}${dir_name}"
-- done
-+ if [ $? -ne 0 ] ; then
-+ echo "${SCRIPTNAME}: Warning: dump2tar failed or is unavailable - falling back to slow path"
-+ call_run_command "find /sys -print0 | sort -z | xargs -0 -n 10 ls -ld" "${OUTPUT_FILE_SYSFS}"
-
-- find /sys -noleaf -type f -perm /444\
-- -a -not -name "*trace_pipe*"\
-- 2>/dev/null | while IFS= read -r file_name; do
-- echo " ${file_name}"
-- if ! dd if="${file_name}" status=noxfer iflag=nonblock of="${WORKPATH}${file_name}" >/dev/null 2>&1; then
-- echo "${SCRIPTNAME}: Warning: failed to copy \"${file_name}\""
-- fi
-- done
-+ find /sys -noleaf -type d 2>/dev/null | while IFS= read -r dir_name; do
-+ mkdir -p "${WORKPATH}${dir_name}"
-+ done
-+
-+ find /sys -noleaf -type f -perm /444\
-+ -a -not -name "*trace_pipe*"\
-+ 2>/dev/null | while IFS= read -r file_name; do
-+ echo " ${file_name}"
-+ if ! dd if="${file_name}" status=noxfer iflag=nonblock of="${WORKPATH}${file_name}" >/dev/null 2>&1; then
-+ echo "${SCRIPTNAME}: Warning: failed to copy \"${file_name}\""
-+ fi
-+ done
-+ fi
-
- if test ${debugfs_mounted} -eq 1; then
- umount "${MOUNT_POINT_DEBUGFS}"
diff --git a/s390-tools-sles12sp3-dbginfo-Collect-docker-debug-data.patch b/s390-tools-sles12sp3-dbginfo-Collect-docker-debug-data.patch
deleted file mode 100644
index d62ad51..0000000
--- a/s390-tools-sles12sp3-dbginfo-Collect-docker-debug-data.patch
+++ /dev/null
@@ -1,142 +0,0 @@
-Subject: [PATCH] [BZ 151594] dbginfo: Collect docker debug output.
-From: Karsten Graul
-
-Description: dbginfo: Collect docker debug output.
-Symptom: dbginfo.sh output does not contain docker debug output.
-Problem: dbginfo.sh does not collect docker debug output.
-Solution: Add invocation of docker debug commands to dbginfo.sh.
-Reproduction: -
-Upstream-ID: -
-Problem-ID: 151594
-
-Signed-off-by: Karsten Graul
----
- scripts/dbginfo.sh | 58 +++++++++++++++++++++++++++++++++++++++++++++++++----
- 1 file changed, 54 insertions(+), 4 deletions(-)
-
---- a/scripts/dbginfo.sh
-+++ b/scripts/dbginfo.sh
-@@ -2,7 +2,7 @@
- #
- # dbginfo.sh - Tool to collect runtime, configuration, and trace information
- #
--# Copyright IBM Corp. 2002, 2016
-+# Copyright IBM Corp. 2002, 2017
- #
-
- # Switching to neutral locale
-@@ -18,7 +18,7 @@ readonly SCRIPTNAME="${0##*/}"
- print_version() {
- cat </dev/null | cut -d'.' -f1)
-@@ -301,6 +304,8 @@ LOGFILES="\
- /var/log/yum.log\
- /var/log/openvswitch/ovs-vswitchd.log\
- /var/log/openvswitch/ovsdb-server.log\
-+ /var/run/docker/libcontainerd/containerd/events.log\
-+ /run/containerd/events.log\
- "
-
- ########################################
-@@ -351,6 +356,9 @@ CONFIGFILES="\
- /etc/xinet.d\
- /etc/*release\
- $(find /lib/modules -name modules.dep 2>/dev/null)\
-+ /etc/docker\
-+ /usr/lib/systemd\
-+ /etc/apparmor.d\
- "
-
- ########################################
-@@ -436,6 +444,16 @@ CMDS="uname -a\
- :systemctl --all --no-pager show\
- :systemctl --all --no-pager list-units\
- :systemctl --all --no-pager list-unit-files\
-+ :docker info\
-+ :docker images\
-+ :docker network ls\
-+ :docker ps\
-+ :docker ps -a\
-+ :docker stats --no-stream\
-+ :docker version\
-+ :systemctl status docker.service\
-+ :df /var/lib/docker\
-+ :df --inodes /var/lib/docker\
- "
-
- ########################################
-@@ -767,13 +785,43 @@ collect_domain_xml() {
- }
-
- ########################################
-+collect_docker() {
-+ local item_list
-+ local item
-+
-+ # call docker inspect for all containers
-+ item_list=$(docker ps -qa)
-+ if test -n "${item_list}"; then
-+ pr_syslog_stdout "10a of ${COLLECTION_COUNT}: Collecting docker container output"
-+ for item in ${item_list}; do
-+ call_run_command "docker inspect ${item}" "${OUTPUT_FILE_DOCKER}"
-+ done
-+ else
-+ pr_syslog_stdout "10a of ${COLLECTION_COUNT}: Collecting docker container output skipped"
-+ fi
-+
-+ # call docker inspect for all networks
-+ item_list=$(docker network ls -q)
-+ if test -n "${item_list}"; then
-+ pr_syslog_stdout "10b of ${COLLECTION_COUNT}: Collecting docker network output"
-+ for item in ${item_list}; do
-+ call_run_command "docker network inspect ${item}" "${OUTPUT_FILE_DOCKER}"
-+ done
-+ else
-+ pr_syslog_stdout "10b of ${COLLECTION_COUNT}: Collecting docker network output skipped"
-+ fi
-+
-+ pr_log_stdout " "
-+}
-+
-+########################################
- post_processing() {
- local file_mtime
- local file_mtime_epoche
- local tmp_file
- local file_name
-
-- pr_syslog_stdout "10 of ${COLLECTION_COUNT}: Postprocessing"
-+ pr_syslog_stdout "11 of ${COLLECTION_COUNT}: Postprocessing"
-
- find "${WORKPATH}etc/libvirt/qemu/" -maxdepth 1 -name "*.xml" 2>/dev/null | while IFS= read -r file_name; do
- file_mtime_epoche=$(stat --format=%Y "${file_name}")
-@@ -1056,6 +1104,8 @@ collect_ovs
-
- collect_domain_xml
-
-+collect_docker
-+
- post_processing
-
- create_package
diff --git a/s390-tools-sles12sp3-lsdasd-tunedasd-Add-channel-path-aware-erp.patch b/s390-tools-sles12sp3-lsdasd-tunedasd-Add-channel-path-aware-erp.patch
deleted file mode 100644
index b8a89d3..0000000
--- a/s390-tools-sles12sp3-lsdasd-tunedasd-Add-channel-path-aware-erp.patch
+++ /dev/null
@@ -1,558 +0,0 @@
-Subject: [PATCH] [FEAT LS1502] lsdasd/tunedasd: Add channel path aware erp
-From: Stefan Haberland
-
-Summary: lsdasd/tunedasd: Add channel path aware erp
-Description: Add tools support for channel path aware error recovery.
- lsdasd shows the newly added IFCC path mask and HPF availability.
- tunedasd gets an option to reset channel paths for a device.
-Upstream-ID: -
-Problem-ID: LS1502
-
-Signed-off-by: Stefan Haberland
----
- include/dasd_sys.h | 1
- libdasd/dasd_sys.c | 94 +++++++++++++++++++++++++++++++++++++
- tunedasd/include/disk.h | 3 -
- tunedasd/man/tunedasd.8 | 17 ++++++
- tunedasd/src/Makefile | 2
- tunedasd/src/disk.c | 35 ++++++++++++++
- tunedasd/src/tunedasd.c | 120 ++++++++++++++++++++++++++++--------------------
- zconf/lsdasd | 36 +++++++++++---
- 8 files changed, 251 insertions(+), 57 deletions(-)
-
---- a/include/dasd_sys.h
-+++ b/include/dasd_sys.h
-@@ -13,5 +13,6 @@
- #include "u2s.h"
-
- int dasd_sys_raw_track_access(char *);
-+int dasd_reset_chpid(char *, char *);
-
- #endif /* DASD_SYS_H */
---- a/libdasd/dasd_sys.c
-+++ b/libdasd/dasd_sys.c
-@@ -6,6 +6,9 @@
- * Copyright IBM Corp. 2016
- */
-
-+#include
-+#include
-+
- #include "dasd_sys.h"
-
- /**
-@@ -44,3 +47,94 @@ int dasd_sys_raw_track_access(char *devn
-
- return (rc == 1) ? 1 : 0;
- }
-+
-+
-+int dasd_get_pm_from_chpid(char *busid, unsigned int chpid, int *mask)
-+{
-+ unsigned int val;
-+ char path[40];
-+ int count, i;
-+ FILE *fp;
-+
-+ sprintf(path, "/sys/bus/ccw/devices/%s/../chpids", busid);
-+ *mask = 0;
-+ fp = fopen(path, "r");
-+ if (!fp)
-+ return ENODEV;
-+
-+ for (i = 0; i < 8; i++) {
-+ count = fscanf(fp, " %x", &val);
-+ if (count != 1) {
-+ fclose(fp);
-+ return EIO;
-+ }
-+ if (val == chpid)
-+ *mask = 0x80 >> i;
-+ }
-+ fclose(fp);
-+
-+ return 0;
-+}
-+
-+/**
-+ * reset chpid
-+ *
-+ * The "devnode" parameter can be any valid relative or absolute path to
-+ * a DASD device node, for example:
-+ *
-+ * - /dev/dasda
-+ * - /dev/disk/by-path/ccw-0.0.bf20
-+ *
-+ * @param[in] devnode Device node of interest
-+ * @param[in] chpid The chpid to reset
-+ * If NULL all chpids will be reset
-+ *
-+ * @return 0 on success, otherwise one of the following error codes:
-+ * - EINVAL No valid chpid specified.
-+ * - ENODEV Could not open device.
-+ * - ENOENT Specified chpid not found.
-+ * - EIO Other I/O error
-+ *
-+ */
-+int dasd_reset_chpid(char *devnode, char *chpid_char)
-+{
-+ unsigned int chpid;
-+ char path[41];
-+ char busid[9];
-+ int mask, rc;
-+ char *endptr;
-+ FILE *fp;
-+
-+ if (u2s_getbusid(devnode, busid))
-+ return ENODEV;
-+
-+ if (!chpid_char) {
-+ sprintf(path, "/sys/bus/ccw/devices/%s/path_reset", busid);
-+ fp = fopen(path, "w");
-+ if (!fp)
-+ return ENODEV;
-+ fprintf(fp, "%s", "all\n");
-+ fclose(fp);
-+ return 0;
-+ }
-+
-+ errno = 0;
-+ chpid = strtoul(chpid_char, &endptr, 16);
-+ if (errno || (endptr && (*endptr != '\0')))
-+ return EINVAL;
-+
-+ rc = dasd_get_pm_from_chpid(busid, chpid, &mask);
-+ if (rc)
-+ return rc;
-+ if (!mask)
-+ return ENOENT;
-+
-+ sprintf(path, "/sys/bus/ccw/devices/%s/path_reset", busid);
-+ fp = fopen(path, "w");
-+ if (!fp)
-+ return ENODEV;
-+ fprintf(fp, "%02x", mask);
-+ fclose(fp);
-+
-+ return 0;
-+}
---- a/tunedasd/include/disk.h
-+++ b/tunedasd/include/disk.h
-@@ -27,7 +27,8 @@ int disk_release (char* device);
- int disk_slock (char* device);
- int disk_query_reserve_status(char* device);
- int disk_profile (char* device, char* prof_item);
--int disk_reset_prof (char* device);
-+int disk_reset_prof(char *device);
-+int disk_reset_chpid(char *device, char *chpid);
-
- #endif /* not DISK_H */
-
---- a/tunedasd/man/tunedasd.8
-+++ b/tunedasd/man/tunedasd.8
-@@ -149,6 +149,18 @@ Following rows are supported:
- .TP
- .BR "\-R" " or " "\-\-reset_prof"
- Reset profile info of device.
-+.TP
-+.BR "\-p" " or " "\-\-path_reset "
-+Reset a channel path of a selected device. A channel path
-+might be suspended due to high IFCC error rates or a High Performance
-+FICON failure. Use this option to resume considering the channel path
-+for I/O.
-+.TP
-+.BR "\-\-path_reset_all"
-+Reset all channel paths of the selected device. The channel paths
-+might be suspended due to high IFCC error rates or a High Performance
-+FICON failure. Use this option to resume considering all defined
-+channel paths for I/O.
- .\"
- .\".TP
- .\".BR "\-o" " or " "\-\-online"
-@@ -166,8 +178,13 @@ Reset profile info of device.
- .br
-
- tunedasd -c prestage -n 1 /dev/dasdc
-+
-+.br
-+3. Scenario: Reset failed channel path with CHPID 45
- .br
-
-+ tunedasd -p 45 /dev/dasdc
-+.br
- .SH "SEE ALSO"
- .BR dasdview (8),
- .BR dasdfmt (8),
---- a/tunedasd/src/Makefile
-+++ b/tunedasd/src/Makefile
-@@ -5,7 +5,7 @@ includes = $(wildcard ../include/*.h)
-
- all: tunedasd
-
--objects = tunedasd.o disk.o
-+objects = tunedasd.o disk.o ../../libdasd/dasd_sys.o ../../libu2s/u2s.o
- $(objects): $(includes)
-
- tunedasd: $(objects)
---- a/tunedasd/src/disk.c
-+++ b/tunedasd/src/disk.c
-@@ -9,6 +9,7 @@
-
- #include "disk.h"
- #include "tunedasd.h"
-+#include "dasd_sys.h"
-
- #include
- #include
-@@ -682,3 +683,37 @@ disk_reset_prof (char* device)
- return 0;
- }
-
-+int disk_reset_chpid(char *device, char *chpid)
-+{
-+ int rc;
-+
-+ if (chpid)
-+ printf("Resetting chpid %s for device <%s>...\n", chpid,
-+ device);
-+ else
-+ printf("Resetting all chpids for device <%s>...\n", device);
-+
-+ rc = dasd_reset_chpid(device, chpid);
-+ switch (rc) {
-+ case 0:
-+ printf("Done.\n");
-+ return 0;
-+ case ENODEV:
-+ error_print("%s: %s", device, strerror(errno));
-+ break;
-+ case EINVAL:
-+ error_print("%s: Could not reset chpid %s: Invalid CHPID",
-+ device, chpid);
-+ break;
-+ case ENOENT:
-+ error_print("%s: Could not reset chpid %s: CHPID not defined for device",
-+ device, chpid);
-+ break;
-+ default:
-+ error_print("%s: Could not reset chpid %s",
-+ device, chpid);
-+ break;
-+ }
-+
-+ return -1;
-+}
---- a/tunedasd/src/tunedasd.c
-+++ b/tunedasd/src/tunedasd.c
-@@ -34,28 +34,30 @@ static const char* usage_text[] = {
- "(e.g. '/dev/dasda') or a list of devices separated by a space "
- "character.",
- "",
-- "-h, --help Print this help, then exit",
-- "-v, --version Print version information, then exit",
-- "-g, --get_cache Get current storage server caching behaviour",
-- "-c, --cache Define caching behavior on storage server",
-- " (normal/bypass/inhibit/sequential/prestage/"
-- "record)",
-- "-n, --no_cyl Number of cylinders to be cached ",
-- " (only valid together with --cache)",
-- "-S, --reserve Reserve device",
-- "-L, --release Release device",
-- "-O, --slock Unconditional reserve device",
-- " Note: Use with care, this breaks an existing "
-- "lock",
-- "-Q, --query_reserve Print reserve status of device ",
-- "-P, --profile Print profile info of device",
-- "-I, --prof_item Print single profile item",
-- " (reqs/sects/sizes/total/totsect/start/irq/",
-- " irqsect/end/queue)",
-- "-R, --reset_prof Reset profile info of device"
-+ "-h, --help Print this help, then exit",
-+ "-v, --version Print version information, then exit",
-+ "-g, --get_cache Get current storage server caching behaviour",
-+ "-c, --cache Define caching behavior on storage server",
-+ " (normal/bypass/inhibit/sequential/prestage/"
-+ "record)",
-+ "-n, --no_cyl Number of cylinders to be cached ",
-+ " (only valid together with --cache)",
-+ "-S, --reserve Reserve device",
-+ "-L, --release Release device",
-+ "-O, --slock Unconditional reserve device",
-+ " Note: Use with care, this breaks an existing "
-+ "lock",
-+ "-Q, --query_reserve Print reserve status of device ",
-+ "-P, --profile Print profile info of device",
-+ "-I, --prof_item Print single profile item",
-+ " (reqs/sects/sizes/total/totsect/start/irq/",
-+ " irqsect/end/queue)",
-+ "-R, --reset_prof Reset profile info of device",
-+ "-p, --path_reset Reset channel path of a device",
-+ " --path_reset_all Reset all channel paths of a device"
- };
-
--#define CMD_KEYWORD_NUM 12
-+#define CMD_KEYWORD_NUM 14
- #define DEVICES_NUM 256
-
- enum cmd_keyword_id {
-@@ -71,6 +73,8 @@ enum cmd_keyword_id {
- cmd_keyword_prof_item = 9,
- cmd_keyword_reset_prof = 10,
- cmd_keyword_query_reserve = 11,
-+ cmd_keyword_path = 12,
-+ cmd_keyword_path_all = 13,
- };
-
-
-@@ -79,18 +83,20 @@ static const struct {
- char* keyword;
- enum cmd_keyword_id id;
- } keyword_list[] = {
-- { "help", cmd_keyword_help },
-- { "version", cmd_keyword_version },
-- { "get_cache", cmd_keyword_get_cache },
-- { "cache", cmd_keyword_cache },
-- { "no_cyl", cmd_keyword_no_cyl },
-- { "reserve", cmd_keyword_reserve },
-- { "release", cmd_keyword_release },
-- { "slock", cmd_keyword_slock },
-- { "profile", cmd_keyword_profile },
-- { "prof_item", cmd_keyword_prof_item },
-- { "reset_prof", cmd_keyword_reset_prof },
-- { "query_reserve", cmd_keyword_query_reserve }
-+ { "help", cmd_keyword_help },
-+ { "version", cmd_keyword_version },
-+ { "get_cache", cmd_keyword_get_cache },
-+ { "cache", cmd_keyword_cache },
-+ { "no_cyl", cmd_keyword_no_cyl },
-+ { "reserve", cmd_keyword_reserve },
-+ { "release", cmd_keyword_release },
-+ { "slock", cmd_keyword_slock },
-+ { "profile", cmd_keyword_profile },
-+ { "prof_item", cmd_keyword_prof_item },
-+ { "reset_prof", cmd_keyword_reset_prof },
-+ { "query_reserve", cmd_keyword_query_reserve },
-+ { "path_reset", cmd_keyword_path },
-+ { "path_reset_all", cmd_keyword_path_all }
- };
-
-
-@@ -103,22 +109,24 @@ enum cmd_key_state {
-
- /* Determines which combination of keywords are valid */
- enum cmd_key_state cmd_key_table[CMD_KEYWORD_NUM][CMD_KEYWORD_NUM] = {
-- /* help vers get_ cach no_c rese rele sloc prof prof rese quer
-- * ion cach e yl rve ase k ile _ite t_pr y_re
-+ /* help vers get_ cach no_c rese rele sloc prof prof rese quer path path
-+ * ion cach e yl rve ase k ile _ite t_pr y_re _all
- * e m of serv
- */
-- /* help */ { req, opt, opt, opt, opt, opt, opt, opt, opt, opt, opt, inv },
-- /* version */ { inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
-- /* get_cache */ { opt, opt, req, inv, inv, inv, inv, inv, inv, inv, inv, inv },
-- /* cache */ { opt, opt, inv, req, opt, inv, inv, inv, inv, inv, inv, inv },
-- /* no_cyl */ { opt, opt, inv, req, req, inv, inv, inv, inv, inv, inv, inv },
-- /* reserve */ { opt, opt, inv, inv, inv, req, inv, inv, inv, inv, inv, inv },
-- /* release */ { opt, opt, inv, inv, inv, inv, req, inv, inv, inv, inv, inv },
-- /* slock */ { opt, opt, inv, inv, inv, inv, inv, req, inv, inv, inv, inv },
-- /* profile */ { opt, opt, inv, inv, inv, inv, inv, inv, req, opt, inv, inv },
-- /* prof_item */ { opt, opt, inv, inv, inv, inv, inv, inv, req, req, inv, inv },
-- /* reset_prof */ { opt, opt, inv, inv, inv, inv, inv, inv, inv, inv, req, inv },
-- /* query_reserve */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req },
-+ /* help */ { req, opt, opt, opt, opt, opt, opt, opt, opt, opt, opt, inv, inv, inv },
-+ /* version */ { inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
-+ /* get_cache */ { opt, opt, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
-+ /* cache */ { opt, opt, inv, req, opt, inv, inv, inv, inv, inv, inv, inv, inv, inv },
-+ /* no_cyl */ { opt, opt, inv, req, req, inv, inv, inv, inv, inv, inv, inv, inv, inv },
-+ /* reserve */ { opt, opt, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv },
-+ /* release */ { opt, opt, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv },
-+ /* slock */ { opt, opt, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv },
-+ /* profile */ { opt, opt, inv, inv, inv, inv, inv, inv, req, opt, inv, inv, inv, inv },
-+ /* prof_item */ { opt, opt, inv, inv, inv, inv, inv, inv, req, req, inv, inv, inv, inv },
-+ /* reset_prof */ { opt, opt, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv },
-+ /* query_reserve */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv },
-+ /* path */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv },
-+ /* path_all */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req },
- };
-
- struct parameter {
-@@ -146,11 +154,13 @@ static struct option options[] = {
- { "prof_item", required_argument, NULL, 'I'},
- { "reset_prof", no_argument, NULL, 'R'},
- { "query_reserve", no_argument, NULL, 'Q'},
-+ { "path_reset", required_argument, NULL, 'p'},
-+ { "path_reset_all", no_argument, NULL, 'A'},
- { NULL, 0, NULL, 0 }
- };
-
- /* Command line option abbreviations */
--static const char option_string[] = "hvgc:n:SLOPI:RQ";
-+static const char option_string[] = "hvgc:n:SLOPI:RQp:";
-
-
- /* Error message string */
-@@ -348,6 +358,14 @@ get_command_line (int argc, char* argv[]
- optarg);
- }
- break;
-+ case 'p':
-+ rc = store_option(&cmdline, cmd_keyword_path,
-+ optarg);
-+ break;
-+ case 'A':
-+ rc = store_option(&cmdline, cmd_keyword_path_all,
-+ optarg);
-+ break;
- case 'S':
- rc = store_option (&cmdline, cmd_keyword_reserve,
- optarg);
-@@ -400,7 +418,6 @@ get_command_line (int argc, char* argv[]
- return 0;
- }
-
--
- /*
- * Execute the command.
- */
-@@ -444,6 +461,13 @@ do_command (char* device, struct command
- case cmd_keyword_query_reserve:
- rc = disk_query_reserve_status(device);
- break;
-+ case cmd_keyword_path:
-+ rc = disk_reset_chpid(device,
-+ cmdline.parm[cmd_keyword_path].data);
-+ break;
-+ case cmd_keyword_path_all:
-+ rc = disk_reset_chpid(device, NULL);
-+ break;
- default:
- error_print ("Unknown command '%s' specified",
- get_keyword_name (i));
---- a/zconf/lsdasd
-+++ b/zconf/lsdasd
-@@ -368,13 +368,15 @@ function extended()
- CABLEPM=0
- CUIRPM=0
- HPFPM=0
-+ IFCCPM=0
-
- # additional information
- read DIAG 2> /dev/null < $DEVPATH/use_diag || continue
- read EER 2> /dev/null < $DEVPATH/eer_enabled || continue
- read ERP 2> /dev/null < $DEVPATH/erplog || continue
-+ read HPF 2> /dev/null < $DEVPATH/hpf
- # in case the path_masks do not exist simply ignore it
-- read OPM NPPM CABLEPM CUIRPM HPFPM 2> /dev/null < $DEVPATH/path_masks
-+ read OPM NPPM CABLEPM CUIRPM HPFPM IFCCPM 2> /dev/null < $DEVPATH/path_masks
- read -a C 2> /dev/null < $DEVPATH/../chpids || continue
- read PIM PAM POM 2> /dev/null < $DEVPATH/../pimpampom || continue
-
-@@ -385,6 +387,7 @@ function extended()
- CABLEPM=0x$CABLEPM
- CUIRPM=0x$CUIRPM
- HPFPM=0x$HPFPM
-+ IFCCPM=0x$IFCCPM
-
- #-----------------------------------------------------------#
- # aggregate chpids and path mask to useful information #
-@@ -397,6 +400,7 @@ function extended()
- CUIR_PATHS=(" " " " " " " " " " " " " " " ")
- CABLE_PATHS=(" " " " " " " " " " " " " " " ")
- HPF_PATHS=(" " " " " " " " " " " " " " " ")
-+ IFCC_PATHS=(" " " " " " " " " " " " " " " ")
-
- # installed paths
- j=0
-@@ -470,13 +474,25 @@ function extended()
- (( mask>>=1 ))
- done
-
-+ # IFCC unusable paths
-+ j=0
-+ mask=0x80
-+ for (( i=0; i<8; i++ )) ;do
-+ PM=$(($IFCCPM&$mask))
-+ if [ $PM -gt 0 ] ;then
-+ IFCC_PATHS[j]=${C[$i]} ;
-+ ((j++)) ;
-+ fi
-+ (( mask>>=1 ))
-+ done
-+
- #-------------------------------------------#
- # format data for output #
- #-------------------------------------------#
-
- if [[ "$ONLINE" == 0 ]]; then
- ACTIVE="offline"
-- printf "%s:%s:%s# status:\t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# uid: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s#\n" \
-+ printf "%s:%s:%s# status:\t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s# uid: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \
- "$SORTKEYLEN" "$SORTKEY" \
- "$BUSID" \
- "$ACTIVE" \
-@@ -484,18 +500,20 @@ function extended()
- "$READONLY" \
- "$EER" \
- "$ERP" \
-+ "$HPF" \
- "$DEV_UID" \
- "${INSTALLED_PATHS[@]}" \
- "${USED_PATHS[@]}" \
- "${NP_PATHS[@]}" \
- "${CABLE_PATHS[@]}" \
- "${CUIR_PATHS[@]}" \
-- "${HPF_PATHS[@]}" ;
-+ "${HPF_PATHS[@]}" \
-+ "${IFCC_PATHS[@]}" ;
- continue
- elif [[ "$ALIAS" == 1 ]]; then
- if [[ "$BASEONLY" == "false" ]]; then
- ACTIVE="alias"
-- printf "%s:%s:%s# status:\t\t\t\t%s# type: \t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s # uid: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s#\n" \
-+ printf "%s:%s:%s# status:\t\t\t\t%s# type: \t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s # uid: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \
- "$SORTKEYLEN" "$SORTKEY" \
- "$BUSID" \
- "$ACTIVE" \
-@@ -504,13 +522,15 @@ function extended()
- "$READONLY" \
- "$EER" \
- "$ERP" \
-+ "$HPF" \
- "$DEV_UID" \
- "${INSTALLED_PATHS[@]}" \
- "${USED_PATHS[@]}" \
- "${NP_PATHS[@]}" \
- "${CABLE_PATHS[@]}" \
- "${CUIR_PATHS[@]}" \
-- "${HPF_PATHS[@]}" ;
-+ "${HPF_PATHS[@]}" \
-+ "${IFCC_PATHS[@]}" ;
- continue
- else
- continue
-@@ -533,7 +553,7 @@ function extended()
- COLON=":"
- fi
-
-- printf "%s:%s:%s/%s/%s%s%s# status:\t\t\t\t%s# type: \t\t\t\t%s# blksz:\t\t\t\t%s# size: \t\t\t\t%s# blocks:\t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# uid: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s#\n" \
-+ printf "%s:%s:%s/%s/%s%s%s# status:\t\t\t\t%s# type: \t\t\t\t%s# blksz:\t\t\t\t%s# size: \t\t\t\t%s# blocks:\t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s# uid: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \
- "$SORTKEYLEN" "$SORTKEY" \
- "$BUSID" \
- "$BLOCKNAME" \
-@@ -549,13 +569,15 @@ function extended()
- "$READONLY" \
- "$EER" \
- "$ERP" \
-+ "$HPF" \
- "$DEV_UID" \
- "${INSTALLED_PATHS[@]}" \
- "${USED_PATHS[@]}" \
- "${NP_PATHS[@]}" \
- "${CABLE_PATHS[@]}" \
- "${CUIR_PATHS[@]}" \
-- "${HPF_PATHS[@]}" ;
-+ "${HPF_PATHS[@]}" \
-+ "${IFCC_PATHS[@]}" ;
- }
-
- function host()
diff --git a/s390-tools-sles12sp3-mon_fsstatd-fix-double-free-in-error-path-and-skip-virtual-fs.patch b/s390-tools-sles12sp3-mon_fsstatd-fix-double-free-in-error-path-and-skip-virtual-fs.patch
deleted file mode 100644
index 0a5236a..0000000
--- a/s390-tools-sles12sp3-mon_fsstatd-fix-double-free-in-error-path-and-skip-virtual-fs.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-Subject: [PATCH] [BZ 151416] mon_fsstatd: fix double free in error path and skip virtual fs
-From: Gerald Schaefer
-
-Description: mon_fsstatd: fix double free in error path and skip virtual fs
-Symptom: The daemon is stopped and the following messages can be found
- in syslog: "statvfs error on /run/user/0: Permission denied"
- and "double free or corruption (!prev)".
-Problem: The error handling code for a failing statvfs() call erroneously
- does an extra fclose(), conflicting with the later fclose().
- Also, breaking out of the inner loop at this point doesn't make
- sense, because there may be other mounted filesystems that would
- be skipped.
- The reason for the failing statvfs() (on /run/user/0) is a wrong
- selinux context (when started via systemctl), and this error will
- spam the syslog if we only fix the double free. Since /run/user/0
- is a tmpfs, and mon_fsstatd is supposed to collect only physical
- filesystem data, it is wrong to even try to access /run/user/0.
-Solution: Remove the extra fclose(), replace the break with a continue,
- and add tmpfs (and others) to the list of ignored virtual
- filesystems.
-Reproduction: Start mon_fsstatd via service/systemctl.
-Upstream-ID: -
-Problem-ID: 151416
-
-Signed-off-by: Gerald Schaefer
----
- mon_tools/mon_fsstatd.c | 19 +++++++++++++++++--
- 1 file changed, 17 insertions(+), 2 deletions(-)
-
---- a/mon_tools/mon_fsstatd.c
-+++ b/mon_tools/mon_fsstatd.c
-@@ -323,16 +323,31 @@ static int fsstatd_do_work(void)
- strncmp(ent->mnt_type, "none", 4) == 0 ||
- strncmp(ent->mnt_type, "proc", 4) == 0 ||
- strncmp(ent->mnt_type, "subfs", 5) == 0 ||
-+ strncmp(ent->mnt_type, "nfsd", 4) == 0 ||
-+ strncmp(ent->mnt_type, "tmpfs", 5) == 0 ||
-+ strncmp(ent->mnt_type, "sysfs", 5) == 0 ||
-+ strncmp(ent->mnt_type, "pstore", 6) == 0 ||
-+ strncmp(ent->mnt_type, "cgroup", 6) == 0 ||
-+ strncmp(ent->mnt_type, "mqueue", 6) == 0 ||
-+ strncmp(ent->mnt_type, "devpts", 6) == 0 ||
-+ strncmp(ent->mnt_type, "debugfs", 7) == 0 ||
-+ strncmp(ent->mnt_type, "devtmpfs", 8) == 0 ||
-+ strncmp(ent->mnt_type, "configfs", 8) == 0 ||
-+ strncmp(ent->mnt_type, "selinuxfs", 9) == 0 ||
-+ strncmp(ent->mnt_type, "hugetlbfs", 9) == 0 ||
-+ strncmp(ent->mnt_type, "securityfs", 10) == 0 ||
-+ strncmp(ent->mnt_type, "rpc_pipefs", 10) == 0 ||
-+ strncmp(ent->mnt_type, "binfmt_misc", 11) == 0 ||
- strncmp(ent->mnt_type, "ignore", 6) == 0)) {
- ent = getmntent(mnttab);
- continue;
- }
- result = statvfs(ent->mnt_dir, &buf);
- if (result != 0) {
-- fclose(mnttab);
- syslog(LOG_ERR, "statvfs error on %s: %s\n",
- ent->mnt_dir, strerror(errno));
-- break;
-+ ent = getmntent(mnttab);
-+ continue;
- }
-
- if (buf.f_blocks > 0)
diff --git a/s390-tools-sles12sp3-util_proc-fix-memory-allocation-error-messages.patch b/s390-tools-sles12sp3-util_proc-fix-memory-allocation-error-messages.patch
deleted file mode 100644
index 8b19b8a..0000000
--- a/s390-tools-sles12sp3-util_proc-fix-memory-allocation-error-messages.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-util_proc: Fix memory allocation error messages
-
-Signed-off-by: Michael Holzheu
----
- libutil/util_proc.c | 7 +++----
- 1 file changed, 3 insertions(+), 4 deletions(-)
-
---- a/libutil/util_proc.c
-+++ b/libutil/util_proc.c
-@@ -54,8 +54,7 @@ util_proc_read_special_file(const char *
- count = 0;
- data = (char *) malloc(current_size);
- if (data == NULL) {
-- printf("Could not allocate %lld bytes of memory",
-- (unsigned long long) size);
-+ printf("Could not allocate %zu bytes of memory", current_size);
- fclose(file);
- return -1;
- }
-@@ -69,8 +68,8 @@ util_proc_read_special_file(const char *
- if (count >= current_size) {
- new_data = (char *) malloc(current_size * 2);
- if (new_data == NULL) {
-- printf("Could not allocate %lld bytes of memory",
-- (unsigned long long) size);
-+ printf("Could not allocate %zu bytes of memory",
-+ current_size * 2);
- free(data);
- fclose(file);
- return -1;
diff --git a/s390-tools-sles12sp3-ziomon-no-blktrace-kill-which-can-corrupt-kernel-blk.patch b/s390-tools-sles12sp3-ziomon-no-blktrace-kill-which-can-corrupt-kernel-blk.patch
deleted file mode 100644
index 7782dd1..0000000
--- a/s390-tools-sles12sp3-ziomon-no-blktrace-kill-which-can-corrupt-kernel-blk.patch
+++ /dev/null
@@ -1,144 +0,0 @@
-Subject: [PATCH] [BZ 149058] ziomon: no blktrace kill which can corrupt kernel blktrace state
-From: Steffen Maier
-
-Description: ziomon: no blktrace kill which can corrupt kernel blktrace state
-Symptom: Ziomon terminates with the following error messages:
-
- $ ziomon -d -o ...
- ...
- ziomon: Failed to stop trace on /dev/sdX
- ...
- ziomon: Failed to stop trace on /dev/sdY
- ziomon: blktrace has leftovers, manual cleanup required!
-
- Subsequent ziomon runs fail likely until the next reboot:
-
- $ ziomon -d -o ...
- ...
- Collecting data...BLKTRACESETUP(2) /dev/sdX failed: \
- 2/No such file or directory
- BLKTRACESETUP(2) /dev/sdY failed: 2/No such file or directory
- ...
- Thread Z failed open /sys/kernel/debug/block/(null)/traceZ: \
- 2/No such file or directory
- FAILED to start thread on CPU 0: 1/Operation not permitted
- ...
- Error: blktrace has errors, aborting
- ...
- ziomon: Failed to stop trace on /dev/sdX
- ...
- ziomon: Failed to stop trace on /dev/sdY
- ziomon: blktrace has leftovers, manual cleanup required!
-Problem: While we call blktrace with stopwatch option '-w $WRP_DURATION'
- to have itself terminate automatically after the (mandatory)
- sampling duration, there might be a race
- with our own timed blktrace checking loop between "Collecting
- data..." and "done"
- or any of SIGHUP SIGTERM SIGINT SIGQUIT from the user might
- prematurely trigger emergency_shutdown(),
- so blktrace might still be running or not have completed its
- cleanup when we reach the blktrace leftover checks in shutdown().
-
- In that case, ziomon uses the meanwhile hidden kill option of
- blktrace which can corrupt kernel state if blktrace user space
- has not yet completed its regular cleanup.
-Solution: The correct way to have the blktrace process terminate and
- cleanup properly including any dependent kernel state, before
- blktrace's stopwatch makes it terminate and cleanup
- automatically, is to only send SIGINT to it.
-
- http://git.kernel.org/cgit/linux/kernel/git/axboe/blktrace.git
- 86596c7579c6 ("blktrace: remove -k from manpage synopsis")
- fb7f86674a51 ("blktrace: disable kill option - take 2")
- Additional explanation for blktrace -k:
- http://marc.info/?l=linux-btrace&m=131245973528087&w=2i
- linux-btrace ("Re: Recent changes")
- The following kernel commits do not change above termination
- statement:
- http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git
- 39cbb602b543 ("Remove double removal of blktrace directory")
- fd51d251e4cd ("blktrace: remove debugfs entries on bad path")
- f48fc4d32e24
- ("block: get rid of the manual directory counting in blktrace")
-
- As of this writing, the (multithreaded) blktrace also wires
- SIGHUP SIGTERM SIGALRM with the same signal handler
- handle_sigint(), but to adhere to its documentation move from
- SIGTERM to SIGINT anyway.
-
- We must not use the meanwhile hidden kill option of blktrace
- because this corrupts kernel state if blktrace user space has not
- yet completed its regular cleanup.
-
- In order to avoid zombies we wait for all children. After all, we
- want everything to be completed before ziomon terminates and the
- user could safely run another instance of ziomon. Also, we get
- the possibility for users to detect and report issues with
- children that don't finish timely.
-
- Since we do not know how to manually cleanup, drop the check for
- blktrace leftovers in shutdown().
-Reproduction: Run ziomon with many devices on the command line.
- Possibly (other) load on the system increases probability.
-Upstream-ID: -
-Problem-ID: 149058
-
-Signed-off-by: Steffen Maier
----
- ziomon/ziomon | 17 ++++++-----------
- 1 file changed, 6 insertions(+), 11 deletions(-)
-
---- a/ziomon/ziomon
-+++ b/ziomon/ziomon
-@@ -5,7 +5,7 @@
- #
- # Wrapper script to start all processes
- #
--# Copyright IBM Corp. 2008
-+# Copyright IBM Corp. 2008, 2016
- #
- # Author(s): Stefan Raspl
- #
-@@ -84,7 +84,7 @@ function check_for_int() {
-
- function print_version() {
- echo "$WRP_TOOLNAME: I/O data collection utility, version %S390_TOOLS_VERSION%";
-- echo "Copyright IBM Corp. 2008";
-+ echo "Copyright IBM Corp. 2008, 2016";
- }
-
-
-@@ -356,8 +356,6 @@ function start_trace() {
-
-
- function shutdown() {
-- local failed=0;
--
- echo "Shutting down";
- # one more second to write final result
- sleep 2;
-@@ -365,7 +363,7 @@ function shutdown() {
- [ -d /proc/$WRP_ZIOMON_UTIL_PID ] && echo "Shutting down utilization process" && kill -s SIGTERM $WRP_ZIOMON_UTIL_PID;
- fi
- if [ "$WRP_BLKTRACE_PID" != "" ]; then
-- [ -d /proc/$WRP_BLKTRACE_PID ] && echo "Shutting down blktrace process" && kill -s SIGTERM $WRP_BLKTRACE_PID;
-+ [ -d /proc/$WRP_BLKTRACE_PID ] && echo "Shutting down blktrace process" && kill -s SIGINT $WRP_BLKTRACE_PID;
- fi
- if [ "$WRP_BLKIOMON_PID" != "" ]; then
- [ -d /proc/$WRP_BLKIOMON_PID ] && echo "Shutting down blkiomon process" && kill -s SIGTERM $WRP_BLKIOMON_PID;
-@@ -381,12 +379,9 @@ function shutdown() {
- kill -s SIGTERM $WRP_ZIOMON_MGR_PID;
- fi
- fi
-- # kill running traces on devices
-- for dev in ${WRP_DEVICES[@]}; do
-- [ -d /sys/kernel/debug/block/${dev##*/} ] && debug "Trace on $dev exists, attempt to kill..." && blktrace -k $dev >/dev/null 2>&1;
-- [ -d /sys/kernel/debug/block/${dev##*/} ] && echo "$WRP_TOOLNAME: Failed to stop trace on $dev" && (( failed++ ));
-- done
-- [ $failed -ne 0 ] && echo "$WRP_TOOLNAME: blktrace has leftovers, manual cleanup required!";
-+ # synchronize with all children to avoid zombies
-+ # and to prepare for a clean subsequent re-run of ziomon
-+ wait
-
- if [ -e $WRP_MSG_Q_PATH ]; then
- if [ $WRP_DEBUG -gt 1 ]; then
diff --git a/s390-tools.changes b/s390-tools.changes
index e6fabeb..e08e73e 100644
--- a/s390-tools.changes
+++ b/s390-tools.changes
@@ -1,3 +1,179 @@
+-------------------------------------------------------------------
+Thu Oct 5 20:47:52 UTC 2017 - mpost@suse.com
+
+- Modified mkdump perl script to work with the updated version
+ of the IBM tools dasdview, zipl and zgetdump. (bsc#1020336).
+
+-------------------------------------------------------------------
+Wed Oct 4 19:45:29 UTC 2017 - mpost@suse.com
+
+- Upgraded to version 2.1.0 (Fate#323291).
+ Changes from 2.0.0 to 2.1.0
+ * Added the following tools:
+ netboot: Scripts for building a PXE-style netboot image for KVM
+ 90-cpi.rules/cpictl: New udev rule to update CPI when KVM is used
+ * Modified lsqeth/zdev to add VNIC Characteristics support
+ Bug fixes
+ * chzcrypt: Corrected handling of insufficient permissions
+ * cpacfstats: Add size setting to perf event
+ * fdasd: Skip partition check with the force option
+ * ttyrun: Fix deprecated BindTo usage in ttyrun-getty@.service.in
+ * lszcrypt: Fix core dump caused by stack overwrite
+ * lszcrypt: Fix random domain printout when no config available
+ * zdev: Fix segfault with unknown qeth attribute
+ * zdev: Fix IPv6 NDP proxy description
+ * zdev: Fix zdev dracut module temp file location
+ * zkey: Correctly detect abbreviated commands
+ * zkey: Validate XTS key: ignore domain and card
+ * zkey: Use octal values instead of S_IRWX* constants
+ * zkey: Properly set umask to prohibit permissions to group and others
+ * zkey: Add -ldl to LDLIBS (not LDFLAGS)
+ * znetconf: Re-add missing line in lsznet.raw
+ * Fix several gcc 7 warnings
+- Modified s390-tools-sles12-fdasd-skip-partition-check-and-BLKRRPART-ioctl.patch
+ to apply cleanly to this version.
+- Removed the following obsolete patches:
+ * s390-tools-sles15-zgetdump-Fix-gcc-7-warning.patch
+ * s390-tools-sles15-lscss-Get-rid-of-gcc-7-buffer-truncation-warnings.patch
+ * s390-tools-sles15-Get-rid-of-gcc-7-fall-through-warnings.patch
+ * s390-tools-sles15-lszcrypt-Fix-core-dump-caused-by-stack-overwrite.patch
+ * s390-tools-sles15-dasdinfo-Fix-GCC-7-overflow-warning.patch
+
+-------------------------------------------------------------------
+Thu Sep 8 21:06:37 UTC 2017 - mpost@suse.com
+
+- Added the following patches (bsc#1056498)
+ - s390-tools-sles15-zgetdump-Fix-gcc-7-warning.patch
+ - s390-tools-sles15-lscss-Get-rid-of-gcc-7-buffer-truncation-warnings.patch
+ - s390-tools-sles15-Get-rid-of-gcc-7-fall-through-warnings.patch
+ - s390-tools-sles15-lszcrypt-Fix-core-dump-caused-by-stack-overwrite.patch
+ - s390-tools-sles15-dasdinfo-Fix-GCC-7-overflow-warning.patch
+
+-------------------------------------------------------------------
+Tue Sep 8 20:01:35 UTC 2017 - mpost@suse.com
+
+- Upgraded to version 2.0.0 (Fate#323291).
+ - Changes from 1.34.0 to 1.35.0
+ - cpuplugd: Make default config file location more distribution agnostic
+ Add systemd service unit to start/stop the cpuplug daemon
+ Add force-reload action to init script for LSB-compliance
+ - mon_statd: Add force-reload action to init script for LSB-compliance
+ - chiucvallow: corrected verification return code
+ - lczdev/chzdev: Add support for resolving iSCSI block devices
+ Bug fixes
+ - chzdev, lszdev: Fix incorrect zfcp module parameter name
+ - chreipl: Fix chreipl node for virtio devices
+ - libus2s: Fix busid parsing
+ - zipl/boot: Fix failed start subchannel in FBA loader
+ - Changes from 1.35.0 to 1.36.0
+ - chzdev/lszdev: Add device resolution for vlan and bonding devices
+ - dasdfmt: Add quick format support
+ - lsdasd/fdasd/dasdfmt/zdsfs: Add query host access to volume support
+ - zfcpdbf: Make timestamp the first field in record output
+ Exclude Payload hex field from log message record output
+ Add Area field to record output
+ Add missing header fields to area record output
+ Print the Record id field for Area area class records
+ Mark oldest and newest trace area records
+ Mark oldest and newest def_err pseudo area records
+ Mark oldest and newest foreign area records
+ Mark oldest and newest log message records
+ Add a warning about low resolution timestamps
+ Add Trace Area Statistics table to script output
+ Add time zone command line option
+ Add collection of domain xml files
+ Bug fixes
+ - zfcpdbf: Move and fix CPU id field output to print_header function
+ Include microseconds in warning threshold calculation
+ Fix parsing of precise syslog timestamps
+ Fix labels for REC ERP action status and ERP step fields
+ - Changes from 1.36.0 to 1.36.1
+ - zfcpdbf: Support basic HBA record type without warning
+ Restore tracing of handle for port and LUN with HBA records
+ Print full payload for all SAN traces (req, resp, iels)
+ Print payload length everywhere applicable
+ Disambiguate printing of payload record content
+ Bug fixes
+ - fdasd: Prevent buffer overflow
+ - znetconf: Fix detection of chpids as OSX instead of OSM
+ - Changes from 1.36.1 to 1.37.0
+ - Added dump2tar: sysfs collection helper for dbginfo.sh
+ - qethconf: Remove check for OSN-device
+ - znetconf: Remove OSN-support
+ - lsdasd/tunedasd: Add channel path aware erp
+ - zcrypt: Add multi domain support for zcrypt device driver
+ - scm: Reimplement lsscm in C
+ - chp: Reimplement chchp and lschp in C
+ - dbginfo.sh: Make use of sysinfo collection helper
+ Bug fixes
+ - zfcpdbf: Only cap SAN short payload if pl_len exists
+ - chzdev: Fix bug when configuring QETH devices
+ - libu2s: Prevent buffer overflow
+ - ziomon: No blktrace kill which can corrupt kernel blktrace state
+ - Changes from 1.37.0 to 1.37.1
+ - dbginfo.sh: Add Docker debug data
+ Bug fixes
+ - lsdasd: Replace continue with return
+ - lscss: Allow to specify devices from subchannel set 3
+ - mon_fsstatd: Only use physical filesystems
+ Fix double free in error path
+ - mon_procd: Fix segmentation fault
+ - Changes from 1.37.1 to 1.38.0
+ - systemd: Add new units for cpi, dumpconf, mon_fsstatd, and mon_procd
+ - fdasd: Add new command action 'l' to list known partition types
+ - chmem: Try to online memory to zone movable
+ Starting with kernel 4.13 (commit f1dd2cd1), the default zone for
+ hotplug memory is changed from zone movable to zone normal. In order
+ to preserve the previous default behaviour, chmem will now always try
+ to set memory online to the zone movable, before trying to set it
+ online to the default zone.
+ - zfcpdbf: Print high part of "new" 64 bit SCSI LUN
+ Print payload with full FCP_RSP IU in SCSI trace records
+ - util_opt: Add command specific command line parsing
+ - util_rec: Implement util_rec_iterate() function
+ - util_rec: Record field values can be stored and processed in argz format
+ Bug fixes
+ - zipl/zgetdump: Add missing SCSI multipath dump information to man pages
+ - lsqeth: Fix attributes name: ipa -> ipa_takeover and parp -> rxip
+ Fix lsqeth output of ipa/vipa/rxip addresses of interfaces
+ - zfcpdbf: Fix payload length for zfcp_dbf_hba_bit_err
+ - chzdev: Add implicit qeth layer settings handling
+ - qethqoat: Fix OSA 6S detection
+ - Changes from 1.38.0 to 2.0.0 (also known as 1.39.0)
+ - IBM changed the license to MIT.
+ - Added zkey: Generate, re-encipher, and validate secure AES keys
+ - cpumf: Add hardware counters for z13 and z13s
+ - lscss: Reimplement lscss script in C
+ - lsqeth: Reimplement lsqeth script in C
+ Bug fixes
+ - lscpumf: Fix Perl warnings
+ - Removed the following obsolete patches:
+ s390-tools-sles12sp2-chiucvallow-verify.patch
+ s390-tools-sles12sp2-chreipl-virtio.patch
+ s390-tools-sles12sp2-chzdev-disable-root-update.patch
+ s390-tools-sles12sp2-lscss-allow-to-specify-devices-from-ssid-3.patch
+ s390-tools-sles12sp2-zipl-fix-failed-start-subchannel.patch
+ s390-tools-sles12sp3-chmem-try-to-online-zone-movable.patch
+ s390-tools-sles12sp3-dasdfmt-01-Fix-behaviour-of-t-combined-with-y.patch
+ s390-tools-sles12sp3-dasdfmt-02-Fix-trailing-whitespace.patch
+ s390-tools-sles12sp3-dasdfmt-03-Apply-coding-convention.patch
+ s390-tools-sles12sp3-dasdfmt-04-Use-enhanced-DASD-information.patch
+ s390-tools-sles12sp3-dasdfmt-05-Refactor-do_format_dasd.patch
+ s390-tools-sles12sp3-dasdfmt-06-Make-the-IOCTL-BLKSSZGET-reusable.patch
+ s390-tools-sles12sp3-dasdfmt-07-Add-quick-format-support.patch
+ s390-tools-sles12sp3-dasdfmt-08-Make-progress-output-reusable-and-add-ETR.patch
+ s390-tools-sles12sp3-dasdfmt-09-Add-command-line-argument-check.patch
+ s390-tools-sles12sp3-dasdfmt-10-Add-expand-format-mode.patch
+ s390-tools-sles12sp3-dbginfo-01-libutil-Add-utility-functions.patch
+ s390-tools-sles12sp3-dbginfo-02-dump2tar-Add-sysfs-collection-helper-for-dbginfo.sh-v2.patch
+ s390-tools-sles12sp3-dbginfo-03-dbginfo.sh-Make-use-of-sysinfo-collection-helper.patch
+ s390-tools-sles12sp3-dbginfo-Collect-docker-debug-data.patch
+ s390-tools-sles12sp3-lsdasd-tunedasd-Add-channel-path-aware-erp.patch
+ s390-tools-sles12sp3-mon_fsstatd-fix-double-free-in-error-path-and-skip-virtual-fs.patch
+ s390-tools-sles12sp3-util_proc-fix-memory-allocation-error-messages.patch
+ s390-tools-sles12sp3-ziomon-no-blktrace-kill-which-can-corrupt-kernel-blk.patch
+- Added s390-tools-sles15-add--ldl-to-LDLIBS.patch to fix a problem with zkey/Makefile.
+
-------------------------------------------------------------------
Thu Sep 7 19:41:39 UTC 2017 - mpost@suse.com
diff --git a/s390-tools.spec b/s390-tools.spec
index 5d7cb49..bb08904 100644
--- a/s390-tools.spec
+++ b/s390-tools.spec
@@ -17,11 +17,11 @@
Name: s390-tools
-Version: 1.34.0
+Version: 2.1.0
Release: 0
-Url: https://www.ibm.com/developerworks/linux/linux390/
+Url: https://github.com/ibm-s390-tools/s390-tools
Summary: S/390 tools like zipl and dasdfmt
-License: GPL-2.0+ and BSD-2-Clause
+License: MIT
Group: System/Kernel
BuildRequires: dracut
BuildRequires: fuse-devel
@@ -46,7 +46,7 @@ Requires: util-linux
Provides: s390utils:/sbin/dasdfmt
# Don't build with pie to avoid problems with zipl
#!BuildIgnore: gcc-PIE
-Source: s390-tools-%{version}.tar.bz2
+Source: s390-tools-%{version}.tar.gz
Source1: s390-tools-rpmlintrc
Source2: zipl.conf
Source3: hsnc
@@ -62,8 +62,6 @@ Source12: mkdump.pl
Source13: sysconfig.osasnmpd
Source14: zfcp_san_disc
Source15: mkdump.8
-Source16: boot.cpi
-Source17: sysconfig.cpi
Source18: zpxe.rexx
Source19: rules.xpram
Source20: rules.hw_random
@@ -106,36 +104,10 @@ Patch1: s390-tools-sles12-zipl_boot_msg.patch
Patch2: s390-tools-sles12-sysconfig-compatible-dumpconf.patch
Patch3: s390-tools-sles12-create-filesystem-links.patch
Patch4: s390-tools-sles12-update-by_id-links-on-change-and-add-action.patch
-Patch5: s390-tools-sles12sp2-feat-01-dasd-query-host.patch
-Patch6: s390-tools-sles12-pardasdfmt.patch
-Patch7: dasdfmt-retry-BIODASDINFO-if-device-is-busy.patch
-Patch8: 59-dasd.rules-wait_for.patch
-Patch9: s390-tools-sles12-fdasd-skip-partition-check-and-BLKRRPART-ioctl.patch
-Patch10: s390-tools-sles12sp2-libu2s-Fix-busid-parsing.patch
-Patch11: s390-tools-sles12sp2-chiucvallow-verify.patch
-Patch12: s390-tools-sles12sp2-zipl-fix-failed-start-subchannel.patch
-Patch13: s390-tools-sles12sp2-chreipl-virtio.patch
-Patch14: s390-tools-sles12sp2-chzdev-disable-root-update.patch
-Patch15: s390-tools-sles12sp2-lscss-allow-to-specify-devices-from-ssid-3.patch
-Patch16: s390-tools-sles12sp3-dbginfo-01-libutil-Add-utility-functions.patch
-Patch17: s390-tools-sles12sp3-dbginfo-02-dump2tar-Add-sysfs-collection-helper-for-dbginfo.sh-v2.patch
-Patch18: s390-tools-sles12sp3-dbginfo-03-dbginfo.sh-Make-use-of-sysinfo-collection-helper.patch
-Patch19: s390-tools-sles12sp3-lsdasd-tunedasd-Add-channel-path-aware-erp.patch
-Patch20: s390-tools-sles12sp3-dasdfmt-01-Fix-behaviour-of-t-combined-with-y.patch
-Patch21: s390-tools-sles12sp3-dasdfmt-02-Fix-trailing-whitespace.patch
-Patch22: s390-tools-sles12sp3-dasdfmt-03-Apply-coding-convention.patch
-Patch23: s390-tools-sles12sp3-dasdfmt-04-Use-enhanced-DASD-information.patch
-Patch24: s390-tools-sles12sp3-dasdfmt-05-Refactor-do_format_dasd.patch
-Patch25: s390-tools-sles12sp3-dasdfmt-06-Make-the-IOCTL-BLKSSZGET-reusable.patch
-Patch26: s390-tools-sles12sp3-dasdfmt-07-Add-quick-format-support.patch
-Patch27: s390-tools-sles12sp3-dasdfmt-08-Make-progress-output-reusable-and-add-ETR.patch
-Patch28: s390-tools-sles12sp3-dasdfmt-09-Add-command-line-argument-check.patch
-Patch29: s390-tools-sles12sp3-dasdfmt-10-Add-expand-format-mode.patch
-Patch30: s390-tools-sles12sp3-util_proc-fix-memory-allocation-error-messages.patch
-Patch31: s390-tools-sles12sp3-mon_fsstatd-fix-double-free-in-error-path-and-skip-virtual-fs.patch
-Patch32: s390-tools-sles12sp3-dbginfo-Collect-docker-debug-data.patch
-Patch33: s390-tools-sles12sp3-ziomon-no-blktrace-kill-which-can-corrupt-kernel-blk.patch
-Patch34: s390-tools-sles12sp3-chmem-try-to-online-zone-movable.patch
+Patch5: s390-tools-sles12-pardasdfmt.patch
+Patch6: dasdfmt-retry-BIODASDINFO-if-device-is-busy.patch
+Patch7: 59-dasd.rules-wait_for.patch
+Patch8: s390-tools-sles12-fdasd-skip-partition-check-and-BLKRRPART-ioctl.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-build
ExclusiveArch: s390 s390x
@@ -196,36 +168,10 @@ to list files and directories.
%patch2 -p1
%patch3 -p1
%patch4 -p1
-%patch5 -p1
+#patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
-%patch9 -p1
-%patch10 -p1
-%patch11 -p1
-%patch12 -p1
-%patch13 -p1
-%patch14 -p1
-%patch15 -p1
-%patch16 -p1
-%patch17 -p1
-%patch18 -p1
-%patch19 -p1
-%patch20 -p1
-%patch21 -p1
-%patch22 -p1
-%patch23 -p1
-%patch24 -p1
-%patch25 -p1
-%patch26 -p1
-%patch27 -p1
-%patch28 -p1
-%patch29 -p1
-%patch30 -p1
-%patch31 -p1
-%patch32 -p1
-%patch33 -p1
-%patch34 -p1
cp -vi %{S:22} CAUTION
@@ -253,15 +199,15 @@ install -m644 -t $RPM_BUILD_ROOT/%{_mandir}/man8 %{S:87}
export ROOT_BUILD_DIR="$RPM_BUILD_DIR/%{name}-%{version}/zfcpdump/kernel"
install -D -m600 /boot/image-*-zfcpdump $RPM_BUILD_ROOT/usr/lib/s390-tools/zfcpdump/zfcpdump_part.image
-install -D -m644 etc/sysconfig/dumpconf $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.dumpconf
-install -D -m755 etc/init.d/dumpconf $RPM_BUILD_ROOT/etc/init.d/dumpconf
install -D -m644 etc/udev/rules.d/40-z90crypt.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/40-z90crypt.rules
-install -D -m644 etc/udev/rules.d/59-dasd.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/59-dasd.rules
install -D -m644 etc/udev/rules.d/57-osasnmpd.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/57-osasnmpd.rules
+install -D -m644 etc/udev/rules.d/59-dasd.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/59-dasd.rules
+install -D -m644 etc/udev/rules.d/90-cpi.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/90-cpi.rules
+install -D -m644 etc/sysconfig/cpi $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.cpi
+install -D -m644 etc/sysconfig/dumpconf $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.dumpconf
+install -D -m644 etc/sysconfig/mon_fsstatd $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.mon_fsstatd
+install -D -m644 etc/sysconfig/mon_procd $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.mon_procd
install -D -m644 etc/sysconfig/mon_statd $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.mon_statd
-install -D -m755 etc/init.d/mon_statd $RPM_BUILD_ROOT/etc/init.d/mon_statd
-install -D -m644 etc/sysconfig/cpuplugd $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.cpuplugd
-install -D -m755 etc/init.d/cpuplugd $RPM_BUILD_ROOT/etc/init.d/cpuplugd
mv iucvterm/doc/ts-shell/iucvconn_on_login $RPM_BUILD_ROOT/usr/bin/iucvconn_on_login
install -D -m644 %{S:26} $RPM_BUILD_ROOT/%{_unitdir}/cio_ignore.service
install -D -m755 %{S:27} $RPM_BUILD_ROOT/usr/lib/systemd/scripts/setup_cio_ignore.sh
@@ -287,8 +233,6 @@ install -D -m755 %{S:12} sbin/mkdump
install -D -m644 %{S:13} var/adm/fillup-templates/sysconfig.osasnmpd
install -D -m755 %{S:14} sbin/zfcp_san_disc
install -D -m644 %{S:15} $RPM_BUILD_ROOT/%{_mandir}/man8
-install -D -m755 %{S:16} etc/init.d/boot.cpi
-install -D -m644 %{S:17} var/adm/fillup-templates/sysconfig.cpi
install -D -m644 %{S:19} $RPM_BUILD_ROOT/usr/lib/udev/rules.d/52-xpram.rules
install -D -m644 %{S:20} $RPM_BUILD_ROOT/usr/lib/udev/rules.d/52-hw_random.rules
install -D -m644 %{S:21} $RPM_BUILD_ROOT/usr/lib/udev/rules.d/59-graf.rules
@@ -304,14 +248,16 @@ if [ ! -d %{_sbindir} ]; then
mkdir -p %{_sbindir}
fi
(cd usr/sbin; ln -s ../../etc/init.d/appldata rcappldata)
-(cd usr/sbin; ln -s ../../etc/init.d/cpuplugd rccpuplugd)
-(cd usr/sbin; ln -s ../../etc/init.d/dumpconf rcdumpconf)
(cd usr/sbin; ln -s ../../etc/init.d/hsnc rchsnc)
-(cd usr/sbin; ln -s ../../etc/init.d/mon_statd rcmon_statd)
(cd usr/sbin; ln -s ../../etc/init.d/vmlogrdr rcvmlogrdr)
(cd usr/sbin; ln -s ../../etc/init.d/xpram rcxpram)
(cd usr/sbin; ln -s service rccio_ignore)
(cd usr/sbin; ln -s service rccpacfstatsd)
+(cd usr/sbin; ln -s service rccpi)
+(cd usr/sbin; ln -s service rccpuplugd)
+(cd usr/sbin; ln -s service rcdumpconf)
+(cd usr/sbin; ln -s service rcmon_fsstatd)
+(cd usr/sbin; ln -s service rcmon_procd)
(cd usr/sbin; ln -s service rcvirtsetup)
if [ ! -d %{_bindir} ]; then
@@ -364,6 +310,13 @@ chmod 755 osasnmpd
getent group ts-shell >/dev/null 2>&1 || groupadd -r ts-shell
%service_add_pre cio_ignore.service
%service_add_pre cpacfstatsd.service
+%service_add_pre cpi.service
+%service_add_pre cpuplugd.service
+%service_add_pre dumpconf.service
+%service_add_pre iucvtty-login@.service
+%service_add_pre mon_fsstatd.service
+%service_add_pre mon_procd.service
+%service_add_pre ttyrun-getty@.service
%service_add_pre virtsetup.service
%post
@@ -378,17 +331,25 @@ fi
# Create symbolic links to the scripts from setup and boot directories
%service_add_post cio_ignore.service
%service_add_post cpacfstatsd.service
+%service_add_post cpi.service
+%service_add_post cpuplugd.service
+%service_add_post dumpconf.service
+%service_add_post iucvtty-login@.service
+%service_add_post mon_fsstatd.service
+%service_add_post mon_procd.service
+%service_add_post ttyrun-getty@.service
%service_add_post virtsetup.service
+
# -i: skip insserv parts - has to be configured before use:
%{fillup_and_insserv -i -n appldata}
-%{fillup_and_insserv -i -n cpuplugd}
+%{fillup_and_insserv -i -n cpi}
%{fillup_and_insserv -i -n dumpconf}
%{fillup_and_insserv -i -n hsnc}
+%{fillup_and_insserv -i -n mon_fsstatd}
+%{fillup_and_insserv -i -n mon_procd}
%{fillup_and_insserv -i -n mon_statd}
-%{fillup_and_insserv -i -n vmlogrdr}
%{fillup_and_insserv -i -n virtsetup}
%{fillup_and_insserv -i -n xpram}
-%{fillup_and_insserv -y -n cpi boot.cpi}
%triggerin -- kernel-default
grep -q '^/usr/bin/ts-shell$' /etc/shells \
@@ -399,28 +360,35 @@ grep -q '^/usr/bin/ts-shell$' /etc/shells \
%preun
%{stop_on_removal appldata}
-%{stop_on_removal cpuplugd}
-%{stop_on_removal dumpconf}
%{stop_on_removal hsnc}
-%{stop_on_removal mon_statd}
%{stop_on_removal vmlogrdr}
%{stop_on_removal xpram}
%service_del_preun cio_ignore.service
%service_del_preun cpacfstatsd.service
+%service_del_preun cpi.service
+%service_del_preun cpuplugd.service
+%service_del_preun dumpconf.service
+%service_del_preun iucvtty-login@.service
+%service_del_preun mon_fsstatd.service
+%service_del_preun mon_procd.service
%service_del_preun virtsetup.service
%postun
-%{restart_on_update boot.cpi}
%{restart_on_update appldata}
-%{restart_on_update cpuplugd}
-%{restart_on_update dumpconf}
%{restart_on_update hsnc}
-%{restart_on_update mon_statd}
%{restart_on_update vmlogrdr}
%{restart_on_update xpram}
%service_del_postun cio_ignore.service
%service_del_postun cpacfstatsd.service
+%service_del_postun cpi.service
+%service_del_postun cpuplugd.service
+%service_del_postun dumpconf.service
+%service_del_postun iucvtty-login@.service
+%service_del_postun mon_fsstatd.service
+%service_del_postun mon_procd.service
+%service_del_postun ttyrun-getty@.service
%service_del_postun virtsetup.service
+
read INITPGM < /proc/1/comm
if [ "${INITPGM}" == "systemd" ]; then
echo "Running systemctl daemon-reload."
@@ -447,7 +415,7 @@ rm -rf $RPM_BUILD_ROOT
%files -f %{_builddir}/%{name}.list
%defattr(-,root,root)
-%doc README
+%doc README.md
%doc README.SUSE
%doc iucvterm/doc/ts-shell
@@ -470,6 +438,7 @@ rm -rf $RPM_BUILD_ROOT
%dir %{_unitdir}
%dir /usr/share/s390-tools
%dir /usr/share/s390-tools/cpumf
+%dir /usr/share/s390-tools/netboot
%dir /boot/zipl
%dir /lib/s390-tools/
%exclude /usr/lib/udev/rules.d/57-osasnmpd.rules
diff --git a/sysconfig.cpi b/sysconfig.cpi
deleted file mode 100644
index 33651c8..0000000
--- a/sysconfig.cpi
+++ /dev/null
@@ -1,22 +0,0 @@
-## Path: Kernel/CPI
-## Description: set Control Program Indentification data
-## Type: list(yes,no)
-## Default: no
-#
-# Set Control Program Identification data
-#
-CPI_SET="yes"
-
-## Type: string
-## Default: ""
-#
-# CPI system name
-#
-CPI_SYSTEM_NAME=""
-
-## Type: string
-## Default: ""
-#
-# CPI sysplex name
-#
-CPI_SYSPLEX_NAME=""