mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Compare commits
164 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
997343f841 | ||
|
|
6a767408b3 | ||
|
|
3aa5c38714 | ||
|
|
c04a0919f6 | ||
|
|
c803cb925e | ||
|
|
1741ecff96 | ||
|
|
20de1fce2a | ||
|
|
a5af5bcf70 | ||
|
|
7730f2489f | ||
|
|
6dbc5646f9 | ||
|
|
f70991ab1e | ||
|
|
e9ee658492 | ||
|
|
35d5f41232 | ||
|
|
260a0a2428 | ||
|
|
b444e71ee3 | ||
|
|
31d576a595 | ||
|
|
68309ccb7f | ||
|
|
755ea88d5d | ||
|
|
af99efaab2 | ||
|
|
3b55ca085e | ||
|
|
9fdfd1a6dc | ||
|
|
c459ec08c6 | ||
|
|
eb63434f44 | ||
|
|
0eae712cc2 | ||
|
|
e7e9f137c1 | ||
|
|
364cb9d869 | ||
|
|
a64e9cab67 | ||
|
|
74cb6ee40e | ||
|
|
8c99c3878e | ||
|
|
f302f5734b | ||
|
|
3485192791 | ||
|
|
715da84030 | ||
|
|
6e53be736e | ||
|
|
88bf638487 | ||
|
|
182892da12 | ||
|
|
f9e07c3916 | ||
|
|
3aaf3c067e | ||
|
|
801e404160 | ||
|
|
280b8509d1 | ||
|
|
0f56416d82 | ||
|
|
c88e0276c1 | ||
|
|
5b7f08624b | ||
|
|
b94d5e8f87 | ||
|
|
a4f171d4ba | ||
|
|
93f8d093ce | ||
|
|
7e68d7f61a | ||
|
|
7755d35995 | ||
|
|
211431abc2 | ||
|
|
0ae29148f0 | ||
|
|
43cf7873be | ||
|
|
d8cea21e1e | ||
|
|
7093a70b51 | ||
|
|
06984cd9ee | ||
|
|
3a05ab769d | ||
|
|
bcbc69c77f | ||
|
|
b385b8cc38 | ||
|
|
2b282bdacd | ||
|
|
bd2610d275 | ||
|
|
5cf2cefa94 | ||
|
|
984e008127 | ||
|
|
fcfee1aa84 | ||
|
|
b401ad0da0 | ||
|
|
50f909db8f | ||
|
|
d0046257b6 | ||
|
|
daad3bf0e7 | ||
|
|
6537f711a6 | ||
|
|
7c75df9e96 | ||
|
|
376ddfbd22 | ||
|
|
1afa6efb26 | ||
|
|
69c89416b0 | ||
|
|
81e0d02d90 | ||
|
|
d41d968792 | ||
|
|
c81ca8f01b | ||
|
|
73ab25f419 | ||
|
|
6fc1ed1a67 | ||
|
|
1c3547d205 | ||
|
|
b6bb87f377 | ||
|
|
bd0bb9dd5c | ||
|
|
075f7f7186 | ||
|
|
5af1e8cc69 | ||
|
|
145c21a9ca | ||
|
|
1bd8ee4b79 | ||
|
|
4f0dfae97e | ||
|
|
3d6bb988c2 | ||
|
|
8f83002e37 | ||
|
|
d92f419836 | ||
|
|
8ff8b40182 | ||
|
|
5e07b30bdf | ||
|
|
35596e1dd7 | ||
|
|
0311cf7c5e | ||
|
|
78fdf56d38 | ||
|
|
b5c4ff68d7 | ||
|
|
3b0fc8cfda | ||
|
|
8d40b5c97a | ||
|
|
ad4075804f | ||
|
|
126ba7e336 | ||
|
|
1d2a89b387 | ||
|
|
7c4b029020 | ||
|
|
b5a750c2cc | ||
|
|
893667e73e | ||
|
|
95fb1e2b03 | ||
|
|
87966251c4 | ||
|
|
012025595f | ||
|
|
48c8fc8321 | ||
|
|
19995638e9 | ||
|
|
91ee8e0593 | ||
|
|
238ca83b99 | ||
|
|
df8aac7084 | ||
|
|
8ad28f7856 | ||
|
|
dd818ccc15 | ||
|
|
e7203069cc | ||
|
|
d4ee1ff01f | ||
|
|
9c60ceccd4 | ||
|
|
6da56acf4b | ||
|
|
365be71dfc | ||
|
|
789b097d3a | ||
|
|
06df08ae49 | ||
|
|
56a656f1c9 | ||
|
|
8efd4da53b | ||
|
|
d2efda1ac2 | ||
|
|
aa29a5f1f9 | ||
|
|
28815d3928 | ||
|
|
65a891fa35 | ||
|
|
5dc39e87e7 | ||
|
|
3358a30dae | ||
|
|
d7ba322d69 | ||
|
|
3123f56765 | ||
|
|
eb881c2a39 | ||
|
|
5c2e6fd730 | ||
|
|
47cac92ca2 | ||
|
|
11f2ccb957 | ||
|
|
5b909a40cb | ||
|
|
591eb30854 | ||
|
|
3083f5dc85 | ||
|
|
2325d94453 | ||
|
|
fef70e3e95 | ||
|
|
808b766407 | ||
|
|
346a69e5a9 | ||
|
|
52ddd291d4 | ||
|
|
4cf239b8b6 | ||
|
|
b292ce565f | ||
|
|
75ab455cf6 | ||
|
|
25088b340b | ||
|
|
8edc5558b5 | ||
|
|
cd93949d17 | ||
|
|
97136585da | ||
|
|
96d5b0bb02 | ||
|
|
771c794580 | ||
|
|
f11c71237e | ||
|
|
8dd5758341 | ||
|
|
20cc99feb7 | ||
|
|
9fa165de7a | ||
|
|
103a99fa34 | ||
|
|
c161c04392 | ||
|
|
8e74293c2d | ||
|
|
e14e0aa858 | ||
|
|
355700d606 | ||
|
|
ddf30feb89 | ||
|
|
0047fc162e | ||
|
|
d9eee82ab0 | ||
|
|
a9059449b9 | ||
|
|
c3d8208a57 | ||
|
|
a2663ec8d3 | ||
|
|
12d9d24437 |
52
.gitignore
vendored
52
.gitignore
vendored
@@ -25,7 +25,7 @@ compile_commands.json
|
||||
#
|
||||
**/.detect-openssl.dep.c
|
||||
*.debug
|
||||
*/autocompletion_generator_host
|
||||
**/autocompletion_generator_host
|
||||
ap_tools/ap-check
|
||||
cmsfs-fuse/cmsfs-fuse
|
||||
cpacfstats/cpacfstats
|
||||
@@ -50,12 +50,22 @@ dasdfmt/dasdfmt
|
||||
dasdfmt/_dasdfmt
|
||||
dasdfmt/dasdfmt.bash
|
||||
dasdinfo/dasdinfo
|
||||
dasdinfo/_dasdinfo
|
||||
dasdinfo/dasdinfo.bash
|
||||
dasdview/dasdview
|
||||
dasdview/_dasdview
|
||||
dasdview/dasdview.bash
|
||||
dump2tar/src/dump2tar
|
||||
dump2tar/src/_dump2tar
|
||||
dump2tar/src/dump2tar.bash
|
||||
fdasd/fdasd
|
||||
fdasd/_fdasd
|
||||
fdasd/fdasd.bash
|
||||
hmcdrvfs/hmcdrvfs
|
||||
hsavmcore/check-dep-fuse
|
||||
hsavmcore/hsavmcore
|
||||
hsavmcore/_hsavmcore
|
||||
hsavmcore/hsavmcore.bash
|
||||
hyptop/hyptop
|
||||
ip_watcher/xcec-bridge
|
||||
ipl_tools/chreipl
|
||||
@@ -88,34 +98,58 @@ libutil/*_example
|
||||
libvmcp/vmcp_example
|
||||
libzds/libzds.a
|
||||
lsstp/lsstp
|
||||
lsstp/_lsstp
|
||||
lsstp/lsstp.bash
|
||||
mon_tools/mon_fsstatd
|
||||
mon_tools/mon_procd
|
||||
opticsmon/opticsmon
|
||||
opticsmon/_opticsmon
|
||||
opticsmon/opticsmon.bash
|
||||
osasnmpd/osasnmpd
|
||||
qetharp/qetharp
|
||||
qethqoat/qethqoat
|
||||
systemd/cpacfstatsd.service
|
||||
systemd/iucvtty-login@.service
|
||||
systemd/ttyrun-getty@.service
|
||||
tape390/tape390_crypt
|
||||
tape390/tape390_display
|
||||
tunedasd/src/tunedasd
|
||||
tunedasd/src/_tunedasd
|
||||
tunedasd/src/tunedasd.bash
|
||||
vmcp/vmcp
|
||||
vmcp/_vmcp
|
||||
vmcp/vmcp.bash
|
||||
vmur/vmur
|
||||
zconf/chp/chchp
|
||||
zconf/chp/_chchp
|
||||
zconf/chp/chchp.bash
|
||||
zconf/chp/lschp
|
||||
zconf/chp/_lschp
|
||||
zconf/chp/lschp.bash
|
||||
zconf/chp/chpstat/chpstat
|
||||
zconf/chp/chpstat/_chpstat
|
||||
zconf/chp/chpstat/chpstat.bash
|
||||
zconf/css/lscss
|
||||
zconf/css/_lscss
|
||||
zconf/css/lscss.bash
|
||||
zconf/qeth/lsqeth
|
||||
zconf/qeth/_lsqeth
|
||||
zconf/qeth/lsqeth.bash
|
||||
zconf/scm/lsscm
|
||||
zconf/scm/_lsscm
|
||||
zconf/scm/lsscm.bash
|
||||
zconf/zcrypt/chzcrypt
|
||||
zconf/zcrypt/_chzcrypt
|
||||
zconf/zcrypt/chzcrypt.bash
|
||||
zconf/zcrypt/lszcrypt
|
||||
zconf/zcrypt/_lszcrypt
|
||||
zconf/zcrypt/lszcrypt.bash
|
||||
zconf/zcrypt/zcryptctl
|
||||
zconf/zcrypt/zcryptstats
|
||||
zconf/zcrypt/_zcryptstats
|
||||
zconf/zcrypt/zcryptstats.bash
|
||||
zdev/src/chzdev
|
||||
zdev/src/chzdev_usage.c
|
||||
zdev/src/chzdev_usage.h
|
||||
zdev/src/lszdev
|
||||
zdev/src/lszdev_usage.c
|
||||
zdev/src/lszdev_usage.h
|
||||
zdev/src/zdev_id
|
||||
zdsfs/zdsfs
|
||||
zdump/.check_dep_fuse
|
||||
@@ -139,6 +173,8 @@ zipl/src/chreipl_helper.device-mapper
|
||||
zipl/src/chreipl_helper.md
|
||||
zipl/src/zipl
|
||||
zipl/src/zipl-editenv
|
||||
zipl/src/_zipl-editenv
|
||||
zipl/src/zipl-editenv.bash
|
||||
zipl/src/zipl_helper.device-mapper
|
||||
zipl/src/zipl_helper.md
|
||||
zkey/check-dep-zkey
|
||||
@@ -151,5 +187,11 @@ zkey/kmip/zkey-kmip.so
|
||||
zkey/zkey
|
||||
zkey/zkey-cryptsetup
|
||||
zmemtopo/zmemtopo
|
||||
zmemtopo/_zmemtopo
|
||||
zmemtopo/zmemtopo.bash
|
||||
zpcictl/zpcictl
|
||||
zpcictl/_zpcictl
|
||||
zpcictl/zpcictl.bash
|
||||
zpwr/zpwr
|
||||
zpwr/_zpwr
|
||||
zpwr/zpwr.bash
|
||||
|
||||
@@ -10,12 +10,14 @@ List of all individuals having contributed content to s390-tools
|
||||
- Annu Sharma
|
||||
- Antoinette Kaschner
|
||||
- Arnd Bergmann
|
||||
- Aswin Karuvally
|
||||
- Axel Wirbser
|
||||
- Balint Reczey
|
||||
- Benjamin Block
|
||||
- Bjoern Walk
|
||||
- Brian C. Lane
|
||||
- Carsten Otte
|
||||
- Chinmaya Kajagar
|
||||
- Christian Borntraeger
|
||||
- Christian Ehrhardt
|
||||
- Christof Schmitt
|
||||
@@ -25,6 +27,7 @@ List of all individuals having contributed content to s390-tools
|
||||
- Dan Horak
|
||||
- Dan Horák
|
||||
- Daniel S. Haischt
|
||||
- Dean Doyle
|
||||
- Despina Papadopoulou
|
||||
- Dimitri John Ledkov
|
||||
- Eberhard Pasch
|
||||
@@ -154,7 +157,9 @@ List of all individuals having contributed content to s390-tools
|
||||
- Vasily Gorbik
|
||||
- Viktor Mihajlovski
|
||||
- Vineeth Vijayan
|
||||
- Volkan Unal
|
||||
- Volker Sameske
|
||||
- Wenjia Zhang
|
||||
- Wisdom Erhimwionsobo
|
||||
- Wolfgang Taphorn
|
||||
- Yaakov Selkowitz
|
||||
|
||||
58
CHANGELOG.md
58
CHANGELOG.md
@@ -1,6 +1,64 @@
|
||||
Release history for s390-tools (MIT version)
|
||||
--------------------------------------------
|
||||
|
||||
* __v2.42.0 (2026-04-30)__
|
||||
|
||||
For Linux kernel version: 7.0
|
||||
|
||||
Add new tools / libraries:
|
||||
- Enable zsh and bash autocompletion for various tools
|
||||
- pvebc: Resolve ASR integrity structure for EBC
|
||||
- pvics: Generate SEL guests from base images
|
||||
|
||||
Remove:
|
||||
- tape390_display and tape390_crypt removed due to long gone hardware support
|
||||
- znetcontrolunits: Remove znetcontrolunits library
|
||||
|
||||
Changes of existing tools:
|
||||
- cpumf/pai: Install SIGINT/SIGTERM handler for graceful termination
|
||||
- dbginfo.sh: Add command zmemtopo
|
||||
- libutil/util_fmt: Add support for JSON Lines text format
|
||||
- lstape: Remove 3480 and 3590 tape support
|
||||
- lsznet: Remove support for lcs device type
|
||||
- pvsecret: Add support for ASR integrity structure for EBC
|
||||
- zfcpdbf: Print plogi and prli within open port response as payload
|
||||
- zfcpdbf: Trace all fsf status read buffer fields under HBA
|
||||
- zipl/boot: Add secure boot option to the dump programm
|
||||
- zkey, libekmfweb, libseckey, libkmipclient: Adjust for OpenSSL v4.0.0 API
|
||||
changes and deprecations
|
||||
|
||||
Bug Fixes:
|
||||
- hyptop/opts: Fix long command line option abbreviations
|
||||
- libutil/util_autocomp: Fix default file completion
|
||||
- zipl/boot: Fix stage3 secure boot trailer placement
|
||||
|
||||
* __v2.41.0 (2026-02-16)__
|
||||
|
||||
For Linux kernel version: 6.19
|
||||
|
||||
Changes of existing tools:
|
||||
- chreipl: Make --bootparms work for ECKD re-IPL
|
||||
- cpacfstats: Add 'unauthorized' state to CPU-MF counters
|
||||
- cpictl: Detect RHCOS using VARIANT_ID
|
||||
- hsci: Automatically set appropriate MTU for HSCI
|
||||
- libutil: Add util_readlink() and util_readlinkat() helpers
|
||||
- libutil: Add util_startswith() to util_str
|
||||
- libutil: Add utility parsing functions
|
||||
- lschp: Add support for structured output (--format)
|
||||
- lsreipl: Suppress 'clear' output if not supported
|
||||
- pvimg: Add '--format text' support to 'pvimg info'
|
||||
- pvimg: Add '--print-schema <FORMAT>' option to 'pvimg info'
|
||||
- pvimg: Add '--show-secrets' flag to 'pvimg info'
|
||||
- pvimg: Provide improved JSON output to 'pvimg info --format json'
|
||||
- pvinfo: Improve User experience on non-SE enabled systems
|
||||
- zipl/ngdump: Ensure ext4 file system is used on dump partition
|
||||
- zkey: Add support for integrity protected disks using HMAC keys
|
||||
|
||||
Bug Fixes:
|
||||
- cpumf/pai: Handle different size of perf_event_attr
|
||||
- lscss: Fix memory leak
|
||||
- zipl: Fix dump job on tape devices
|
||||
|
||||
* __v2.40.0 (2025-12-11)__
|
||||
|
||||
For Linux kernel version: 6.18
|
||||
|
||||
2
Makefile
2
Makefile
@@ -11,7 +11,7 @@ BASELIB_DIRS = libutil libseckey
|
||||
LIB_DIRS = libvtoc libzds libdasd libccw libvmcp libekmfweb \
|
||||
libkmipclient libcpumf libap libpv libzpci
|
||||
TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \
|
||||
tape390 osasnmpd qetharp ip_watcher qethconf scripts zconf \
|
||||
osasnmpd qetharp ip_watcher qethconf scripts zconf \
|
||||
vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \
|
||||
ziomon iucvterm hyptop cmsfs-fuse qethqoat zfcpdump zdsfs cpumf \
|
||||
systemd hmcdrvfs cpacfstats zdev dump2tar zkey netboot etc zpcictl \
|
||||
|
||||
24
README.md
24
README.md
@@ -30,6 +30,8 @@ Package contents
|
||||
Manage secrets for IBM Secure Execution guests
|
||||
- pvimg:
|
||||
Create and inspect IBM Secure Execution images
|
||||
- pvebc:
|
||||
Verify a secret structure for IBM Secure Execution for Linux.
|
||||
|
||||
* dasdfmt:
|
||||
Low-level format ECKD DASDs with the classical Linux disk layout or the new
|
||||
@@ -50,6 +52,10 @@ Package contents
|
||||
Create an IBM Secure Execution (protected virtualization) image. The
|
||||
genprotimg command is a symbolic link to the `pvimg create` command.
|
||||
|
||||
* pvics:
|
||||
Convert a qcow2 image to a qcow2 image ready to boot as IBM Secure Execution
|
||||
for Linux guest.
|
||||
|
||||
* udev rules:
|
||||
- 59-dasd.rules: rules for unique DASD device nodes created in /dev/disk/.
|
||||
- 57-osasnmpd.rules: udev rules for osasnmpd.
|
||||
@@ -79,13 +85,6 @@ Package contents
|
||||
* qetharp:
|
||||
Read and flush the ARP cache on OSA Express network cards.
|
||||
|
||||
* tape390_display:
|
||||
Display information on the message display facility of a s390 tape
|
||||
device.
|
||||
|
||||
* tape390_crypt:
|
||||
Control and query crypto settings for 3592 tape devices.
|
||||
|
||||
* osasnmpd:
|
||||
NET-SNMP subagent implementing MIBs provided by OSA-Express
|
||||
features Fast Ethernet, Gigabit Ethernet, 10 Gigabit Ethernet.
|
||||
@@ -415,7 +414,7 @@ the different tools are provided:
|
||||
Removing the inflate modules and function prototypes are the only major
|
||||
modifications made to the kernel version of zlib.
|
||||
For stand-alone NVMe and list-directed DASD dump, the following tools/packages
|
||||
are required to populate dumper's initramfs:
|
||||
are required to populate dumper's initramfs and prepare a dump partition:
|
||||
- cat
|
||||
- cut
|
||||
- findmnt
|
||||
@@ -426,6 +425,7 @@ the different tools are provided:
|
||||
- sha256sum
|
||||
- sync
|
||||
- umount
|
||||
- mkfs.ext4
|
||||
|
||||
* zgetdump
|
||||
For building zgetdump you need OpenSSL version 1.1.0 or newer
|
||||
@@ -517,11 +517,11 @@ the different tools are provided:
|
||||
|
||||
* zkey:
|
||||
For building the zkey tools you need openssl version 0.9.7 or newer installed
|
||||
(openssl-devel.rpm). Also required are cryptsetup version 2.0.3 or newer
|
||||
(openssl-devel.rpm). Also required are cryptsetup version 2.8.2 or newer
|
||||
(cryptsetup-devel.rpm), and json-c version 0.12 or newer (json-c-devel.rpm).
|
||||
Tip: you may skip the zkey build by adding `HAVE_OPENSSL=0`, and you may
|
||||
may skip the zkey-cryptsetup build by adding `HAVE_CRYPTSETUP2=0`, or
|
||||
`HAVE_JSONC=0` to the make invocation.
|
||||
Tip: you may skip the zkey build by adding `HAVE_OPENSSL=0` or
|
||||
`HAVE_CRYPTSETUP2=0`, and you may skip the zkey-cryptsetup build
|
||||
by adding `HAVE_JSONC=0` to the make invocation.
|
||||
A new group 'zkeyadm' needs to be created and all users intending to use the
|
||||
tool must be added to this group. The owner of the default key repository
|
||||
'/etc/zkey/repository' must be set to group 'zkeyadm' with write permission
|
||||
|
||||
@@ -303,11 +303,11 @@ static void conflict_error(const char *uuid, unsigned int a, unsigned int d,
|
||||
}
|
||||
} else {
|
||||
if (persistent) {
|
||||
fprintf(stderr, "AQPN %u.%u is not defined for "
|
||||
fprintf(stderr, "APQN %u.%u is not defined for "
|
||||
"vfio_ap-passthrough use by the persistent "
|
||||
"ap bus mask settings\n", a, d);
|
||||
} else {
|
||||
fprintf(stderr, "AQPN %u.%u is not allowed for "
|
||||
fprintf(stderr, "APQN %u.%u is not allowed for "
|
||||
"vfio_ap-passthrough use by the active ap "
|
||||
"bus mask settings\n", a, d);
|
||||
}
|
||||
@@ -531,7 +531,7 @@ out:
|
||||
* Determine if there are any conflicts between the specified device and
|
||||
* the apmask/aqmask settings stored in udev. This is done by treating
|
||||
* the masks as a temporary vfio_ap_device with all of the associated
|
||||
* AQPNs owned by the system.
|
||||
* APQNs owned by the system.
|
||||
*/
|
||||
static int check_cfg_mask_conflicts(struct ap_check_anchor *anc)
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ endif
|
||||
# The variable "DISTRELEASE" should be overwritten in rpm spec files with:
|
||||
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
|
||||
VERSION := 2
|
||||
RELEASE := 40
|
||||
RELEASE := 42
|
||||
PATCHLEVEL := 0
|
||||
DISTRELEASE := build-$(shell date +%Y%m%d)
|
||||
S390_TOOLS_RELEASE := $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
|
||||
|
||||
@@ -179,6 +179,12 @@ the errno value.
|
||||
ECC counters are only available since z15. cpacfstats will show the
|
||||
counters as \fIunsupported\fR if the hardware does not support ECC
|
||||
counters.
|
||||
|
||||
CPU-MF counters have to be authorized on HMC or SE to be available and are
|
||||
otherwise shown as \fIunauthorized\fR. On the HMC or SE, authorize the LPAR
|
||||
for each counter set you want to use. Customize the LPAR activation profile
|
||||
and modify the Counter Facility Security Options. You need to activate the
|
||||
\fICrypto activity counter set authorization control\fR checkbox.
|
||||
.
|
||||
.SH APPENDIX
|
||||
The detailed pai counter names are:
|
||||
|
||||
@@ -175,9 +175,10 @@ static void print_virtual_counter_answer(int s,
|
||||
int ctr, int state, uint64_t value)
|
||||
{
|
||||
static const char *const states[] = {
|
||||
[DISABLED] = "disabled",
|
||||
[ENABLED] = "enabled",
|
||||
[UNSUPPORTED] = "unsupported"
|
||||
[DISABLED] = "disabled",
|
||||
[ENABLED] = "enabled",
|
||||
[UNSUPPORTED] = "unsupported",
|
||||
[UNAUTHORIZED] = "unauthorized"
|
||||
};
|
||||
int paictr = 0, paistate = 0, ec;
|
||||
uint64_t i, paivalue = 0;
|
||||
@@ -242,6 +243,8 @@ static void print_answer(int s, int ctr, int state, uint64_t value)
|
||||
printf(" %s counter: disabled\n", counter_str[ctr]);
|
||||
else if (state == UNSUPPORTED)
|
||||
printf(" %s counter: unsupported\n", counter_str[ctr]);
|
||||
else if (state == UNAUTHORIZED)
|
||||
printf(" %s counter: unauthorized\n", counter_str[ctr]);
|
||||
else
|
||||
printf(" %s counter: %lu\n", counter_str[ctr], value);
|
||||
}
|
||||
|
||||
@@ -74,7 +74,8 @@ enum cmd_e {
|
||||
enum state_e {
|
||||
DISABLED = 0,
|
||||
ENABLED,
|
||||
UNSUPPORTED
|
||||
UNSUPPORTED,
|
||||
UNAUTHORIZED
|
||||
};
|
||||
|
||||
enum counter_type {
|
||||
|
||||
@@ -179,7 +179,7 @@ static int do_enable(int s, enum ctr_e ctr, unsigned int *supported_counters)
|
||||
}
|
||||
state = ENABLED;
|
||||
}
|
||||
if (state != UNSUPPORTED) {
|
||||
if (state != UNSUPPORTED && state != UNAUTHORIZED) {
|
||||
rc = perf_read_ctr(i, &value, supported_counters);
|
||||
if (rc != 0) {
|
||||
send_answer(s, i, rc, 0);
|
||||
|
||||
@@ -141,6 +141,10 @@ static int perf_counter_supported(const char *pmu, const char *counter)
|
||||
return !access(buf, R_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 1 if counters are authorized, -1 if counters are unauthorized,
|
||||
* and 0 otherwise which indicates that the counters are unsupported
|
||||
*/
|
||||
static int cpumf_authorized(void)
|
||||
{
|
||||
unsigned vermin, vermax, auth;
|
||||
@@ -159,10 +163,12 @@ static int cpumf_authorized(void)
|
||||
if (sscanf(line,
|
||||
"CPU-MF: Counter facility: version=%d.%d authorization=%x",
|
||||
&vermin, &vermax, &auth) == 3) {
|
||||
if (auth & 0x8)
|
||||
if (auth & 0x8) {
|
||||
res = 1;
|
||||
else
|
||||
} else {
|
||||
eprint("CPU-MF counters not authorized.\n");
|
||||
res = -1;
|
||||
}
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
@@ -233,7 +239,7 @@ static int activatecpu(unsigned int cpu, unsigned int *supported_counters)
|
||||
}
|
||||
/* activate CPU-MF */
|
||||
for (i = 0; i < ALL_COUNTER; ++i) {
|
||||
if (ctr_state[i] == UNSUPPORTED)
|
||||
if (ctr_state[i] == UNSUPPORTED || ctr_state[i] == UNAUTHORIZED)
|
||||
continue;
|
||||
memset(&pfm_event, 0, sizeof(pfm_event));
|
||||
pfm_event.size = sizeof(pfm_event);
|
||||
@@ -398,7 +404,7 @@ static int perf_load_counter_data(void)
|
||||
int i, res = 0;
|
||||
|
||||
for (i = 0; i < ALL_COUNTER; ++i) {
|
||||
if (ctr_state[i] != UNSUPPORTED)
|
||||
if (ctr_state[i] != UNSUPPORTED && ctr_state[i] != UNAUTHORIZED)
|
||||
res |= perf_event_encode(&pmf_counter_data[i].pmutype,
|
||||
&pmf_counter_data[i].eventid,
|
||||
pmf_counter_name[i].pmu,
|
||||
@@ -474,6 +480,7 @@ int perf_init(unsigned int *supported_counters)
|
||||
};
|
||||
unsigned long maxfd;
|
||||
struct rlimit rlim;
|
||||
int cpumf_state;
|
||||
int i, num;
|
||||
FILE *f;
|
||||
|
||||
@@ -487,10 +494,15 @@ int perf_init(unsigned int *supported_counters)
|
||||
* counters for PAI. */
|
||||
num = ALL_COUNTER + 2;
|
||||
|
||||
if (!cpumf_authorized()) {
|
||||
cpumf_state = cpumf_authorized();
|
||||
if (cpumf_state == 0) {
|
||||
for (i = 0; i < ALL_COUNTER; ++i)
|
||||
ctr_state[i] = UNSUPPORTED;
|
||||
num -= ALL_COUNTER;
|
||||
} else if (cpumf_state == -1) {
|
||||
for (i = 0; i < ALL_COUNTER; ++i)
|
||||
ctr_state[i] = UNAUTHORIZED;
|
||||
num -= ALL_COUNTER;
|
||||
} else {
|
||||
for (i = 0; i < ALL_COUNTER; i++) {
|
||||
if (!perf_counter_supported("cpum_cf", cpum_cf[i])) {
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Autocompletion generation - for cpumf family of tools
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#include "lib/util_autocomp.h"
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Command line utilities - for chcpumf
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#ifndef CHCPUMF_CLI_H
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Command line utilities - for lscpumf
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#ifndef LSCPUMF_CLI_H
|
||||
|
||||
@@ -700,7 +700,7 @@ static int do_it(char *s)
|
||||
|
||||
if (output_format == FMT_CSV)
|
||||
flags |= FMT_NOMETA;
|
||||
if (output_format == FMT_JSON || output_format == FMT_JSONSEQ)
|
||||
if (util_fmt_is_json(output_format))
|
||||
flags |= FMT_HANDLEINT;
|
||||
if (quote_all)
|
||||
flags |= FMT_QUOTEALL;
|
||||
@@ -708,7 +708,7 @@ static int do_it(char *s)
|
||||
mk_labels();
|
||||
util_fmt_init(stdout, output_format, flags, 1);
|
||||
util_fmt_obj_start(FMT_DEFAULT, "lshwc");
|
||||
if (output_format == FMT_JSON || output_format == FMT_JSONSEQ) {
|
||||
if (util_fmt_is_json(output_format)) {
|
||||
util_fmt_obj_start(FMT_ROW, "cpumcf info");
|
||||
util_fmt_pair(FMT_PERSIST, "counter first", "%d", cfvn);
|
||||
util_fmt_pair(FMT_PERSIST, "counter second", "%d", csvn);
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Command line utilities - for lshwc
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#ifndef LSHWC_CLI_H
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Command line utilities - for lspai
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#ifndef LSPAI_CLI_H
|
||||
|
||||
@@ -138,7 +138,7 @@ Apply quoting to every output element, regardless of content or format.
|
||||
.TP
|
||||
.BR \-f ", " \-\-format \fI\ FORMAT\fP
|
||||
Retrieve output in one of the following formats:
|
||||
JSON, CSV, JSON-SEQ or PAIRS.
|
||||
JSON, CSV, JSON-SEQ, JSONL or PAIRS.
|
||||
If no format is specified, the output defaults to CSV.
|
||||
.
|
||||
.SS JSON Output Structure
|
||||
|
||||
@@ -136,7 +136,7 @@ Default sort order is PAI counter name.
|
||||
.TP
|
||||
.BI \-\-format "\ FORMAT"
|
||||
Retrieve output in one of the following formats:
|
||||
JSON, csv, json-seq or pairs.
|
||||
JSON, csv, json-seq, jsonl or pairs.
|
||||
If no format is specified,
|
||||
the output defaults to a human-readable format.
|
||||
.
|
||||
|
||||
23
cpumf/pai.c
23
cpumf/pai.c
@@ -14,6 +14,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
@@ -47,6 +48,8 @@
|
||||
#define S390_EVT_PAI_CRYPTO 0x1000
|
||||
#define S390_EVT_PAI_NNPA 0x1800
|
||||
|
||||
/* SIGINT or SIGTERM signal received */
|
||||
static volatile unsigned int sigterm;
|
||||
/* Default values for select() timeout: 1 second */
|
||||
static unsigned long read_interval = 1000;
|
||||
/* Size of mapped perf event ring buffer in 4KB pages.
|
||||
@@ -350,6 +353,10 @@ static int collect(unsigned long cnt)
|
||||
if (FD_ISSET(i, &r_fds))
|
||||
readmap(i);
|
||||
}
|
||||
} else if (errno == EINTR && sigterm) {
|
||||
/* Interrupt by signal SIGINT/SIGTERM, one more iteration */
|
||||
cnt = 2;
|
||||
rc = 0;
|
||||
}
|
||||
} while (rc != -1 && --cnt > 0);
|
||||
return rc;
|
||||
@@ -503,7 +510,7 @@ static int evt_scan(char *fn, unsigned char *buf, size_t len,
|
||||
__u64 sample_type = pa->sample_type;
|
||||
int allcnt = 0, cnt = 0, rawok = 0;
|
||||
struct perf_event_header *hdr;
|
||||
size_t offset = sizeof(*pa);
|
||||
size_t offset = pa->size;
|
||||
__u64 evtnum = pa->config;
|
||||
struct pai_event_out ev;
|
||||
size_t limit;
|
||||
@@ -514,6 +521,8 @@ static int evt_scan(char *fn, unsigned char *buf, size_t len,
|
||||
unsigned char valid;
|
||||
} last_csout = { 0, 0, 0 };
|
||||
|
||||
if (verbose && (sizeof(*pa) != pa->size))
|
||||
printf("size perf_event_attr mismatch %zu/%zu\n", sizeof(*pa), offset);
|
||||
while (offset < len) {
|
||||
hdr = (struct perf_event_header *)(buf + offset);
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
@@ -835,7 +844,7 @@ static int map_check(char *fn, int (*fct)(char *, unsigned char *, size_t,
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
p = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (p == MAP_FAILED) {
|
||||
warnx("%s cannot map file", fn);
|
||||
close(fd);
|
||||
@@ -981,6 +990,12 @@ static void setprio(const char *prio)
|
||||
err(EXIT_FAILURE, "Could not set realtime priority");
|
||||
}
|
||||
|
||||
static void sig_handler(int no)
|
||||
{
|
||||
if (no == SIGINT || no == SIGTERM)
|
||||
sigterm = 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
bool crypto_record = false, report = false;
|
||||
@@ -1068,6 +1083,10 @@ int main(int argc, char **argv)
|
||||
errx(EXIT_FAILURE, "Invalid argument for runtime");
|
||||
}
|
||||
|
||||
if (signal(SIGTERM, sig_handler) == SIG_ERR ||
|
||||
signal(SIGINT, sig_handler) == SIG_ERR)
|
||||
errx(EXIT_FAILURE, "Failed to set signal handler");
|
||||
|
||||
ev_install(group);
|
||||
ev_enable();
|
||||
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Command line utilities - for pai
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#ifndef PAI_CLI_H
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Autocompletion generation - for dasdfmt tool
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#include "lib/util_autocomp.h"
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Command line utilities - for dasdfmt
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#ifndef DASDFMT_CLI_H
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
include ../common.mak
|
||||
|
||||
zsh-completions = _dasdinfo
|
||||
bash-completions = dasdinfo.bash
|
||||
|
||||
include ../common_autocomp.mak
|
||||
|
||||
libs = $(rootdir)/libutil/libutil.a \
|
||||
$(rootdir)/libdasd/libdasd.a
|
||||
|
||||
|
||||
16
dasdinfo/autocompletion_generator_host.c
Normal file
16
dasdinfo/autocompletion_generator_host.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#include "lib/util_autocomp.h"
|
||||
|
||||
#include "dasdinfo_cli.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
generate_autocomp(opt_vec, "dasdinfo");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -30,6 +30,8 @@
|
||||
#include "lib/util_path.h"
|
||||
#include "lib/zt_common.h"
|
||||
|
||||
#include "dasdinfo_cli.h"
|
||||
|
||||
#define RD_BUFFER_SIZE 80
|
||||
#define TEMP_DEV_MAX_RETRIES 1000
|
||||
|
||||
@@ -50,49 +52,6 @@ static const struct util_prg prg = {
|
||||
}
|
||||
};
|
||||
|
||||
static struct util_opt opt_vec[] = {
|
||||
UTIL_OPT_SECTION("DEVICE"),
|
||||
{
|
||||
.option = { "block", required_argument, NULL, 'b' },
|
||||
.argument = "BLOCKDEV",
|
||||
.desc = "Block device name, e.g. dasdb",
|
||||
},
|
||||
{
|
||||
.option = { "devnode", required_argument, NULL, 'd' },
|
||||
.argument = "DEVNODE",
|
||||
.desc = "Device node, e.g. /dev/dasda",
|
||||
},
|
||||
{
|
||||
.option = { "busid", required_argument, NULL, 'i' },
|
||||
.argument = "BUSID",
|
||||
.desc = "Bus ID, e.g. 0.0.e910",
|
||||
},
|
||||
UTIL_OPT_SECTION("OPTIONS"),
|
||||
{
|
||||
.option = { "label", no_argument, NULL, 'l' },
|
||||
.desc = "Print DASD volume label (volser)",
|
||||
},
|
||||
{
|
||||
.option = { "uid", no_argument, NULL, 'u' },
|
||||
.desc = "Print DASD uid (without z/VM minidisk token)",
|
||||
},
|
||||
{
|
||||
.option = { "extended-uid", no_argument, NULL, 'x' },
|
||||
.desc = "Print DASD uid (including z/VM minidisk token)",
|
||||
},
|
||||
{
|
||||
.option = { "all", no_argument, NULL, 'a' },
|
||||
.desc = "Same as -u -x -l",
|
||||
},
|
||||
{
|
||||
.option = { "export", no_argument, NULL, 'e' },
|
||||
.desc = "Export ID_BUS, ID_TYPE, ID_SERIAL for use in udev",
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
/* needed because ftw can not pass arbitrary arguments */
|
||||
static char *searchbusid;
|
||||
static char *busiddir;
|
||||
@@ -101,9 +60,9 @@ struct volume_label {
|
||||
char volkey[4];
|
||||
char vollbl[4];
|
||||
char volid[6];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
static char EBCtoASC[256] = {
|
||||
static char ebc_to_asc[256] = {
|
||||
/* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */
|
||||
0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
|
||||
/* 0x08 -GE -SPS -RPT VT FF CR SO SI */
|
||||
@@ -175,7 +134,7 @@ static char *dinfo_ebcdic_dec(char *source, char *target, int l)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < l; i++)
|
||||
target[i] = EBCtoASC[(unsigned char)(source[i])];
|
||||
target[i] = ebc_to_asc[(unsigned char)(source[i])];
|
||||
|
||||
return target;
|
||||
}
|
||||
@@ -261,7 +220,7 @@ static void *dinfo_malloc(size_t size)
|
||||
void *result;
|
||||
|
||||
result = malloc(size);
|
||||
if (result == NULL)
|
||||
if (!result)
|
||||
warnx("Could not allocate %lu bytes of memory", size);
|
||||
|
||||
return result;
|
||||
@@ -274,7 +233,7 @@ static char *dinfo_make_path(char *dirname, char *filename)
|
||||
|
||||
len = strlen(dirname) + strlen(filename) + 2;
|
||||
result = (char *)dinfo_malloc(len);
|
||||
if (result == NULL)
|
||||
if (!result)
|
||||
return NULL;
|
||||
sprintf(result, "%s/%s", dirname, filename);
|
||||
return result;
|
||||
@@ -296,12 +255,12 @@ static int dinfo_create_devnode(dev_t dev, char **devno)
|
||||
|
||||
/* Try several locations for the temporary device node. */
|
||||
for (path = 0; path < ARRAY_SIZE(pathname); path++) {
|
||||
if (pathname[path] == NULL)
|
||||
if (!pathname[path])
|
||||
continue;
|
||||
for (retry = 0; retry < TEMP_DEV_MAX_RETRIES; retry++) {
|
||||
snprintf(filename, sizeof(filename), "dasdinfo%04d", retry);
|
||||
result = dinfo_make_path(pathname[path], filename);
|
||||
if (result == NULL)
|
||||
if (!result)
|
||||
return -1;
|
||||
rc = mknod(result, mode, dev);
|
||||
if (rc == 0) {
|
||||
@@ -342,7 +301,7 @@ static int dinfo_extract_dev(dev_t *dev, char *str)
|
||||
memset(tmp, 0, RD_BUFFER_SIZE);
|
||||
util_strlcpy(tmp, str, RD_BUFFER_SIZE);
|
||||
p = strchr(tmp, ':');
|
||||
if (p == NULL) {
|
||||
if (!p) {
|
||||
warnx("Error: unable to extract major/minor");
|
||||
return -1;
|
||||
}
|
||||
@@ -386,10 +345,8 @@ static int
|
||||
dinfo_is_busiddir(const char *fpath, const struct stat *UNUSED(sb),
|
||||
int tflag, struct FTW *ftwbuf)
|
||||
{
|
||||
enum { LINK_DIR_SIZE = 128 };
|
||||
char linkdir[LINK_DIR_SIZE];
|
||||
char *tempdir;
|
||||
ssize_t i;
|
||||
char *linkdir;
|
||||
|
||||
if (tflag != FTW_D || (strncmp((fpath + ftwbuf->base), searchbusid,
|
||||
strlen(searchbusid)) != 0))
|
||||
@@ -401,17 +358,16 @@ dinfo_is_busiddir(const char *fpath, const struct stat *UNUSED(sb),
|
||||
*/
|
||||
if (asprintf(&tempdir, "%s/driver", fpath) < 0)
|
||||
return -1;
|
||||
i = readlink(tempdir, linkdir, LINK_DIR_SIZE);
|
||||
linkdir = util_readlink(tempdir);
|
||||
free(tempdir);
|
||||
if (i < 0 || i >= LINK_DIR_SIZE)
|
||||
return -1;
|
||||
/* append '\0' because readlink returns non zero terminated string */
|
||||
linkdir[i] = '\0';
|
||||
if (strstr(linkdir, "dasd") == NULL)
|
||||
if (!strstr(linkdir, "dasd")) {
|
||||
free(linkdir);
|
||||
return FTW_CONTINUE;
|
||||
}
|
||||
free(linkdir);
|
||||
free(busiddir);
|
||||
busiddir = strdup(fpath);
|
||||
if (busiddir == NULL)
|
||||
if (!busiddir)
|
||||
return -1;
|
||||
return FTW_STOP;
|
||||
}
|
||||
@@ -424,7 +380,7 @@ dinfo_find_entry(const char *dir, const char *searchstring,
|
||||
struct dirent *dir_entry = NULL;
|
||||
|
||||
directory = opendir(dir);
|
||||
if (directory == NULL)
|
||||
if (!directory)
|
||||
return -1;
|
||||
while ((dir_entry = readdir(directory)) != NULL) {
|
||||
/* compare if the found entry has exactly the same name and type
|
||||
@@ -434,7 +390,7 @@ dinfo_find_entry(const char *dir, const char *searchstring,
|
||||
strlen(searchstring)) == 0) &&
|
||||
(dir_entry->d_type & type)) {
|
||||
*result = strdup(dir_entry->d_name);
|
||||
if (*result == NULL)
|
||||
if (!*result)
|
||||
goto out;
|
||||
closedir(directory);
|
||||
return 0; /* found */
|
||||
@@ -480,7 +436,7 @@ dinfo_get_blockdev_from_busid(char *busid, char **blkdev)
|
||||
if (rc != 0)
|
||||
goto out2;
|
||||
*blkdev = strdup(strchr(result, ':') + 1);
|
||||
if (*blkdev == NULL)
|
||||
if (!*blkdev)
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
@@ -513,7 +469,7 @@ static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
|
||||
|
||||
path = util_path_sysfs("block/");
|
||||
directory = opendir(path);
|
||||
if (directory == NULL) {
|
||||
if (!directory) {
|
||||
warnx("Error: could not open directory %s", path);
|
||||
free(path);
|
||||
return -1;
|
||||
@@ -553,8 +509,6 @@ static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct utsname uname_buf;
|
||||
int version, release;
|
||||
char *uidfile = NULL;
|
||||
char *device = NULL;
|
||||
char *readbuf = NULL;
|
||||
@@ -614,35 +568,19 @@ int main(int argc, char *argv[])
|
||||
util_prg_print_version();
|
||||
exit(EXIT_SUCCESS);
|
||||
default:
|
||||
fprintf(stderr, "Try 'dasdinfo --help' for more "
|
||||
"information.\n");
|
||||
fprintf(stderr, "Try 'dasdinfo --help' for more information.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uname(&uname_buf);
|
||||
sscanf(uname_buf.release, "%d.%d", &version, &release);
|
||||
if (strcmp(uname_buf.sysname, "Linux") ||
|
||||
version < 2 || (version == 2 && release < 6)) {
|
||||
warnx("%s %d.%d is not supported", uname_buf.sysname,
|
||||
version, release);
|
||||
exit(1);
|
||||
}
|
||||
if (!busid && !blockdev && !devnode)
|
||||
errx(EXIT_FAILURE, "Error: please specify a device using either -b, -i or -d");
|
||||
|
||||
if (!busid && !blockdev && !devnode) {
|
||||
warnx("Error: please specify a device using either -b, -i or -d");
|
||||
exit(1);
|
||||
}
|
||||
if ((busid && blockdev) || (busid && devnode) || (blockdev && devnode))
|
||||
errx(EXIT_FAILURE, "Error: please specify device only once, either -b, -i or -d");
|
||||
|
||||
if ((busid && blockdev) || (busid && devnode) || (blockdev && devnode)) {
|
||||
warnx("Error: please specify device only once, either -b, -i or -d");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!print_uid && !print_extended_uid && !print_vlabel) {
|
||||
warnx("Error: no action specified (e.g. -u)");
|
||||
exit(1);
|
||||
}
|
||||
if (!print_uid && !print_extended_uid && !print_vlabel)
|
||||
errx(EXIT_FAILURE, "Error: no action specified (e.g. -u)");
|
||||
|
||||
readbuf = dinfo_malloc(RD_BUFFER_SIZE);
|
||||
if (!readbuf)
|
||||
|
||||
55
dasdinfo/dasdinfo_cli.h
Normal file
55
dasdinfo/dasdinfo_cli.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#ifndef DASDINFO_CLI_H
|
||||
#define DASDINFO_CLI_H
|
||||
|
||||
#include "lib/util_opt.h"
|
||||
|
||||
static struct util_opt opt_vec[] = {
|
||||
UTIL_OPT_SECTION("DEVICE"),
|
||||
{
|
||||
.option = { "block", required_argument, NULL, 'b' },
|
||||
.argument = "BLOCKDEV",
|
||||
.desc = "Block device name, e.g. dasdb",
|
||||
},
|
||||
{
|
||||
.option = { "devnode", required_argument, NULL, 'd' },
|
||||
.argument = "DEVNODE",
|
||||
.desc = "Device node, e.g. /dev/dasda",
|
||||
},
|
||||
{
|
||||
.option = { "busid", required_argument, NULL, 'i' },
|
||||
.argument = "BUSID",
|
||||
.desc = "Bus ID, e.g. 0.0.e910",
|
||||
},
|
||||
UTIL_OPT_SECTION("OPTIONS"),
|
||||
{
|
||||
.option = { "label", no_argument, NULL, 'l' },
|
||||
.desc = "Print DASD volume label (volser)",
|
||||
},
|
||||
{
|
||||
.option = { "uid", no_argument, NULL, 'u' },
|
||||
.desc = "Print DASD uid (without z/VM minidisk token)",
|
||||
},
|
||||
{
|
||||
.option = { "extended-uid", no_argument, NULL, 'x' },
|
||||
.desc = "Print DASD uid (including z/VM minidisk token)",
|
||||
},
|
||||
{
|
||||
.option = { "all", no_argument, NULL, 'a' },
|
||||
.desc = "Same as -u -x -l",
|
||||
},
|
||||
{
|
||||
.option = { "export", no_argument, NULL, 'e' },
|
||||
.desc = "Export ID_BUS, ID_TYPE, ID_SERIAL for use in udev",
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,10 @@
|
||||
include ../common.mak
|
||||
|
||||
zsh-completions = _dasdview
|
||||
bash-completions = dasdview.bash
|
||||
|
||||
include ../common_autocomp.mak
|
||||
|
||||
libs = $(rootdir)/libdasd/libdasd.a \
|
||||
$(rootdir)/libzds/libzds.a \
|
||||
$(rootdir)/libvtoc/libvtoc.a \
|
||||
|
||||
16
dasdview/autocompletion_generator_host.c
Normal file
16
dasdview/autocompletion_generator_host.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#include "lib/util_autocomp.h"
|
||||
|
||||
#include "dasdview_cli.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
generate_autocomp(opt_vec, "dasdview");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "lib/zt_common.h"
|
||||
|
||||
#include "dasdview.h"
|
||||
#include "dasdview_cli.h"
|
||||
|
||||
/* Characters per line */
|
||||
#define DASDVIEW_CPL 16
|
||||
@@ -56,61 +57,6 @@ static const struct util_prg prg = {
|
||||
}
|
||||
};
|
||||
|
||||
static struct util_opt opt_vec[] = {
|
||||
UTIL_OPT_SECTION("DUMP OPTIONS"),
|
||||
{
|
||||
.option = { NULL, no_argument, NULL, '1' },
|
||||
.desc = "Show DASD content in short Hex/EBCDIC/ASCII format",
|
||||
.flags = UTIL_OPT_FLAG_NOLONG,
|
||||
},
|
||||
{
|
||||
.option = { NULL, no_argument, NULL, '2' },
|
||||
.desc = "Show DASD content in detailed Hex/EBCDIC/ASCII format",
|
||||
.flags = UTIL_OPT_FLAG_NOLONG,
|
||||
},
|
||||
{
|
||||
.option = { "begin", required_argument, NULL, 'b' },
|
||||
.argument = "BEGIN",
|
||||
.desc = "Specify start of dump in kilobytes (suffix k), "
|
||||
"megabytes (m), blocks (b), tracks (t), or cylinders (c)",
|
||||
},
|
||||
{
|
||||
.option = { "size", required_argument, NULL, 's' },
|
||||
.argument = "SIZE",
|
||||
.desc = "Specify size of dump in kilobytes (suffix k), "
|
||||
"megabytes (m), blocks (b), tracks (t), or cylinders (c)",
|
||||
},
|
||||
UTIL_OPT_SECTION("MISC"),
|
||||
{
|
||||
.option = { "characteristic", no_argument, NULL, 'c' },
|
||||
.desc = "Print the characteristics of a device",
|
||||
},
|
||||
{
|
||||
.option = { "info", no_argument, NULL, 'i' },
|
||||
.desc = "Print general DASD information and geometry",
|
||||
},
|
||||
{
|
||||
.option = { "volser", no_argument, NULL, 'j' },
|
||||
.desc = "Print the volume serial number",
|
||||
},
|
||||
{
|
||||
.option = { "label", no_argument, NULL, 'l' },
|
||||
.desc = "Print information about the volume label",
|
||||
},
|
||||
{
|
||||
.option = { "vtoc", required_argument, NULL, 't' },
|
||||
.argument = "SPEC",
|
||||
.desc = "Print the table of content (VTOC)",
|
||||
},
|
||||
{
|
||||
.option = { "extended", no_argument, NULL, 'x' },
|
||||
.desc = "Print extended DASD information",
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
/*
|
||||
* Generate and print an error message based on the formatted
|
||||
* text string FMT and a variable amount of extra arguments.
|
||||
|
||||
67
dasdview/dasdview_cli.h
Normal file
67
dasdview/dasdview_cli.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#ifndef DASDVIEW_CLI_H
|
||||
#define DASDVIEW_CLI_H
|
||||
|
||||
#include "lib/util_opt.h"
|
||||
|
||||
static struct util_opt opt_vec[] = {
|
||||
UTIL_OPT_SECTION("DUMP OPTIONS"),
|
||||
{
|
||||
.option = { NULL, no_argument, NULL, '1' },
|
||||
.desc = "Show DASD content in short Hex/EBCDIC/ASCII format",
|
||||
.flags = UTIL_OPT_FLAG_NOLONG,
|
||||
},
|
||||
{
|
||||
.option = { NULL, no_argument, NULL, '2' },
|
||||
.desc = "Show DASD content in detailed Hex/EBCDIC/ASCII format",
|
||||
.flags = UTIL_OPT_FLAG_NOLONG,
|
||||
},
|
||||
{
|
||||
.option = { "begin", required_argument, NULL, 'b' },
|
||||
.argument = "BEGIN",
|
||||
.desc = "Specify start of dump in kilobytes (suffix k), "
|
||||
"megabytes (m), blocks (b), tracks (t), or cylinders (c)",
|
||||
},
|
||||
{
|
||||
.option = { "size", required_argument, NULL, 's' },
|
||||
.argument = "SIZE",
|
||||
.desc = "Specify size of dump in kilobytes (suffix k), "
|
||||
"megabytes (m), blocks (b), tracks (t), or cylinders (c)",
|
||||
},
|
||||
UTIL_OPT_SECTION("MISC"),
|
||||
{
|
||||
.option = { "characteristic", no_argument, NULL, 'c' },
|
||||
.desc = "Print the characteristics of a device",
|
||||
},
|
||||
{
|
||||
.option = { "info", no_argument, NULL, 'i' },
|
||||
.desc = "Print general DASD information and geometry",
|
||||
},
|
||||
{
|
||||
.option = { "volser", no_argument, NULL, 'j' },
|
||||
.desc = "Print the volume serial number",
|
||||
},
|
||||
{
|
||||
.option = { "label", no_argument, NULL, 'l' },
|
||||
.desc = "Print information about the volume label",
|
||||
},
|
||||
{
|
||||
.option = { "vtoc", required_argument, NULL, 't' },
|
||||
.argument = "SPEC",
|
||||
.desc = "Print the table of content (VTOC)",
|
||||
},
|
||||
{
|
||||
.option = { "extended", no_argument, NULL, 'x' },
|
||||
.desc = "Print extended DASD information",
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
#endif
|
||||
136
dump2tar/include/dump2tar_cli.h
Normal file
136
dump2tar/include/dump2tar_cli.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#ifndef DUMP2TAR_CLI_H
|
||||
#define DUMP2TAR_CLI_H
|
||||
|
||||
#include "lib/util_opt.h"
|
||||
|
||||
#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)
|
||||
|
||||
/* 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",
|
||||
.argument = "SEC",
|
||||
},
|
||||
{
|
||||
.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,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,11 @@
|
||||
# Common definitions
|
||||
include ../../common.mak
|
||||
|
||||
zsh-completions = _dump2tar
|
||||
bash-completions = dump2tar.bash
|
||||
|
||||
include ../../common_autocomp.mak
|
||||
|
||||
ALL_CPPFLAGS += -I../include -Wno-unused-parameter
|
||||
LDLIBS += -lpthread -lrt
|
||||
ifneq ($(HAVE_ZLIB),0)
|
||||
|
||||
16
dump2tar/src/autocompletion_generator_host.c
Normal file
16
dump2tar/src/autocompletion_generator_host.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#include "lib/util_autocomp.h"
|
||||
|
||||
#include "../include/dump2tar_cli.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
generate_autocomp(dump2tar_opts, "dump2tar");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -655,16 +655,18 @@ static int read_symlink(struct task *task, const char *filename,
|
||||
task->opts->read_chunk_size;
|
||||
int rc = EXIT_OK;
|
||||
|
||||
/* If @relname is NULL, use @filename with AT_FDCWD. */
|
||||
if (!relname) {
|
||||
relname = filename;
|
||||
dirfd = AT_FDCWD;
|
||||
}
|
||||
|
||||
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);
|
||||
actual = readlinkat(dirfd, relname, buffer->addr, buffer->size);
|
||||
cancel_disable();
|
||||
|
||||
if (actual == -1) {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "lib/util_prg.h"
|
||||
|
||||
#include "dump.h"
|
||||
#include "dump2tar_cli.h"
|
||||
#include "global.h"
|
||||
#include "idcache.h"
|
||||
#include "misc.h"
|
||||
@@ -28,12 +29,6 @@
|
||||
|
||||
#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 "
|
||||
@@ -52,124 +47,6 @@ static const struct util_prg dump2tar_prg = {
|
||||
},
|
||||
};
|
||||
|
||||
/* 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",
|
||||
.argument = "SEC",
|
||||
},
|
||||
{
|
||||
.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)
|
||||
|
||||
@@ -4,3 +4,4 @@ pkey_pckmo
|
||||
pkey_ep11
|
||||
pkey_cca
|
||||
paes_s390
|
||||
phmac_s390
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
include ../common.mak
|
||||
|
||||
zsh-completions = _fdasd
|
||||
bash-completions = fdasd.bash
|
||||
|
||||
include ../common_autocomp.mak
|
||||
|
||||
libs = $(rootdir)/libvtoc/libvtoc.a \
|
||||
$(rootdir)/libzds/libzds.a \
|
||||
$(rootdir)/libdasd/libdasd.a \
|
||||
|
||||
16
fdasd/autocompletion_generator_host.c
Normal file
16
fdasd/autocompletion_generator_host.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#include "lib/util_autocomp.h"
|
||||
|
||||
#include "fdasd_cli.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
generate_autocomp(opt_vec, "fdasd");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "lib/zt_common.h"
|
||||
|
||||
#include "fdasd.h"
|
||||
#include "fdasd_cli.h"
|
||||
|
||||
/* global variables */
|
||||
static struct hd_geometry geo;
|
||||
@@ -138,58 +139,6 @@ static const struct util_prg prg = {
|
||||
}
|
||||
};
|
||||
|
||||
static struct util_opt opt_vec[] = {
|
||||
UTIL_OPT_SECTION("NON-INTERACTIVE MODE"),
|
||||
{
|
||||
.option = { "auto", no_argument, NULL, 'a' },
|
||||
.desc = "Create a single partition spanning the entire disk",
|
||||
},
|
||||
{
|
||||
.option = { "config", required_argument, NULL, 'c' },
|
||||
.argument = "FILE",
|
||||
.desc = "Create partitions(s) based on content of FILE",
|
||||
},
|
||||
{
|
||||
.option = { "keep_volser", no_argument, NULL, 'k' },
|
||||
.desc = "Do not change the current volume serial",
|
||||
},
|
||||
{
|
||||
.option = { "label", required_argument, NULL, 'l' },
|
||||
.argument = "VOLSER",
|
||||
.desc = "Set the volume serial to VOLSER",
|
||||
},
|
||||
UTIL_OPT_SECTION("MISC"),
|
||||
{
|
||||
.option = { "check_host_count", no_argument, NULL, 'C' },
|
||||
.desc = "Check if device is in use by other hosts",
|
||||
},
|
||||
{
|
||||
.option = { "force", optional_argument, NULL, 'f' },
|
||||
.argument = "TYPE,SIZE",
|
||||
.desc = "Force fdasd to work on non DASD devices with assumed "
|
||||
"TYPE (3390, 3380, or 9345) and blocksize SIZE",
|
||||
},
|
||||
{
|
||||
.option = { "volser", no_argument, NULL, 'i' },
|
||||
.desc = "Print volume serial",
|
||||
},
|
||||
{
|
||||
.option = { "table", no_argument, NULL, 'p' },
|
||||
.desc = "Print partition table",
|
||||
},
|
||||
{
|
||||
.option = { "verbose", no_argument, NULL, 'r' },
|
||||
.desc = "Provide more verbose output",
|
||||
},
|
||||
{
|
||||
.option = { "silent", no_argument, NULL, 's' },
|
||||
.desc = "Suppress messages",
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
static int getpos(fdasd_anchor_t *anc, int dsn)
|
||||
{
|
||||
return anc->partno[dsn];
|
||||
|
||||
64
fdasd/fdasd_cli.h
Normal file
64
fdasd/fdasd_cli.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#ifndef FDASD_CLI_H
|
||||
#define FDASD_CLI_H
|
||||
|
||||
#include "lib/util_opt.h"
|
||||
|
||||
static struct util_opt opt_vec[] = {
|
||||
UTIL_OPT_SECTION("NON-INTERACTIVE MODE"),
|
||||
{
|
||||
.option = { "auto", no_argument, NULL, 'a' },
|
||||
.desc = "Create a single partition spanning the entire disk",
|
||||
},
|
||||
{
|
||||
.option = { "config", required_argument, NULL, 'c' },
|
||||
.argument = "FILE",
|
||||
.desc = "Create partitions(s) based on content of FILE",
|
||||
},
|
||||
{
|
||||
.option = { "keep_volser", no_argument, NULL, 'k' },
|
||||
.desc = "Do not change the current volume serial",
|
||||
},
|
||||
{
|
||||
.option = { "label", required_argument, NULL, 'l' },
|
||||
.argument = "VOLSER",
|
||||
.desc = "Set the volume serial to VOLSER",
|
||||
},
|
||||
UTIL_OPT_SECTION("MISC"),
|
||||
{
|
||||
.option = { "check_host_count", no_argument, NULL, 'C' },
|
||||
.desc = "Check if device is in use by other hosts",
|
||||
},
|
||||
{
|
||||
.option = { "force", optional_argument, NULL, 'f' },
|
||||
.argument = "TYPE,SIZE",
|
||||
.desc = "Force fdasd to work on non DASD devices with assumed "
|
||||
"TYPE (3390, 3380, or 9345) and blocksize SIZE",
|
||||
},
|
||||
{
|
||||
.option = { "volser", no_argument, NULL, 'i' },
|
||||
.desc = "Print volume serial",
|
||||
},
|
||||
{
|
||||
.option = { "table", no_argument, NULL, 'p' },
|
||||
.desc = "Print partition table",
|
||||
},
|
||||
{
|
||||
.option = { "verbose", no_argument, NULL, 'r' },
|
||||
.desc = "Provide more verbose output",
|
||||
},
|
||||
{
|
||||
.option = { "silent", no_argument, NULL, 's' },
|
||||
.desc = "Suppress messages",
|
||||
},
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -7,6 +7,11 @@
|
||||
|
||||
include ../common.mak
|
||||
|
||||
zsh-completions = _hsavmcore
|
||||
bash-completions = hsavmcore.bash
|
||||
|
||||
include ../common_autocomp.mak
|
||||
|
||||
ALL_CPPFLAGS += -D_FILE_OFFSET_BITS=64
|
||||
|
||||
ifeq (${HAVE_FUSE},0)
|
||||
@@ -41,7 +46,7 @@ endif
|
||||
ALL_CFLAGS += $(FUSE_CFLAGS) $(SYSTEMD_CFLAGS)
|
||||
LDLIBS += $(FUSE_LDLIBS) $(SYSTEMD_LDLIBS) -lpthread
|
||||
|
||||
sources := $(wildcard *.c)
|
||||
sources := $(filter-out %_host.c, $(wildcard *.c))
|
||||
objects := $(patsubst %.c,%.o,$(sources))
|
||||
|
||||
libs = $(rootdir)/libutil/libutil.a
|
||||
|
||||
16
hsavmcore/autocompletion_generator_host.c
Normal file
16
hsavmcore/autocompletion_generator_host.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#include "lib/util_autocomp.h"
|
||||
|
||||
#include "hsavmcore_cli.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
generate_autocomp(opt_vec, "hsavmcore");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "lib/util_log.h"
|
||||
|
||||
#include "cmdline_options.h"
|
||||
#include "hsavmcore_cli.h"
|
||||
|
||||
static const struct util_prg prg = {
|
||||
.desc = "hsavmcore is designed to make the dump process with kdump more "
|
||||
@@ -32,91 +33,6 @@ static const struct util_prg prg = {
|
||||
}
|
||||
};
|
||||
|
||||
static struct util_opt opt_vec[] = {
|
||||
UTIL_OPT_SECTION("CONFIGURATION"),
|
||||
{
|
||||
.option = { "config", required_argument, NULL, 'c' },
|
||||
.argument = "CONFIGFILE",
|
||||
.desc = "Path to the configuration file.\n"
|
||||
"Default: no configuration file is used",
|
||||
},
|
||||
{
|
||||
.option = { "vmcore", required_argument, NULL, 'C' },
|
||||
.argument = "VMCOREFILE",
|
||||
.desc = "Path to the vmcore file.\n"
|
||||
"Default: " PROC_VMCORE,
|
||||
},
|
||||
{
|
||||
.option = { "hsa", required_argument, NULL, 'H' },
|
||||
.argument = "ZCOREHSAFILE",
|
||||
.desc = "Path to the zcore HSA file.\n"
|
||||
"Default: " ZCORE_HSA,
|
||||
},
|
||||
{
|
||||
.option = { "workdir", required_argument, NULL, 'W' },
|
||||
.argument = "WORKDIR",
|
||||
.desc = "Path to the work directory where temporary files can be "
|
||||
"stored.\nDefault: " WORKDIR,
|
||||
},
|
||||
{
|
||||
.option = { "bmvmcore", required_argument, NULL, 'B' },
|
||||
.argument = "VMCOREFILE",
|
||||
.desc = "Path to the target of the bind mount for the vmcore "
|
||||
"replacement.\nDefault: " PROC_VMCORE,
|
||||
},
|
||||
{
|
||||
.option = { "swap", required_argument, NULL, 'S' },
|
||||
.argument = "PATH",
|
||||
.desc = "Path to a swap device or file. The specified swap "
|
||||
"device or file must exist and have the proper swap "
|
||||
"format.\nDefault: no swap device or file is activated",
|
||||
},
|
||||
{
|
||||
.option = { "hsasize", required_argument, NULL, 'T' },
|
||||
.argument = "HSASIZE",
|
||||
.desc = "HSA size in bytes.\n"
|
||||
"Default: -1 (read from the zcore HSA file)",
|
||||
},
|
||||
{
|
||||
.option = { "dbgfsmnt", no_argument, NULL, 'D' },
|
||||
.desc = "Mount the debug file system.\n"
|
||||
"Default: the debug file system is not mounted",
|
||||
},
|
||||
{
|
||||
.option = { "hsamem", no_argument, NULL, 'F' },
|
||||
.desc = "Cache the HSA memory in regular memory.\n"
|
||||
"Default: the HSA memory is cached as a file within "
|
||||
"WORKDIR",
|
||||
},
|
||||
{
|
||||
.option = { "norelhsa", no_argument, NULL, 'R' },
|
||||
.desc = "Do NOT release the HSA memory after caching.\n"
|
||||
"Default: the HSA memory is released",
|
||||
},
|
||||
{
|
||||
.option = { "nobindmnt", no_argument, NULL, 'N' },
|
||||
.desc = "Do NOT replace the system's vmcore.\n"
|
||||
"Default: the system's vmcore is replaced",
|
||||
},
|
||||
UTIL_OPT_SECTION("LOGGING"),
|
||||
{
|
||||
.option = { "verbose", no_argument, NULL, 'V' },
|
||||
.desc = "Print verbose messages to stdout. Repeat this option "
|
||||
"for increased verbosity from just error messages to "
|
||||
"also include warning, information, debug, and trace "
|
||||
"messages. This option is intended for debugging",
|
||||
},
|
||||
{
|
||||
.option = { "fusedbg", no_argument, NULL, 'G' },
|
||||
.desc = "Enable FUSE debugging.\n"
|
||||
"Default: FUSE debugging is disabled",
|
||||
},
|
||||
UTIL_OPT_SECTION("GENERAL OPTIONS"),
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
void parse_cmdline_options(int argc, char *argv[], struct config *config)
|
||||
{
|
||||
int opt, ret;
|
||||
|
||||
99
hsavmcore/hsavmcore_cli.h
Normal file
99
hsavmcore/hsavmcore_cli.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#ifndef HSAVMCORE_CLI_H
|
||||
#define HSAVMCORE_CLI_H
|
||||
|
||||
#include "lib/util_opt.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static struct util_opt opt_vec[] = {
|
||||
UTIL_OPT_SECTION("CONFIGURATION"),
|
||||
{
|
||||
.option = { "config", required_argument, NULL, 'c' },
|
||||
.argument = "CONFIGFILE",
|
||||
.desc = "Path to the configuration file.\n"
|
||||
"Default: no configuration file is used",
|
||||
},
|
||||
{
|
||||
.option = { "vmcore", required_argument, NULL, 'C' },
|
||||
.argument = "VMCOREFILE",
|
||||
.desc = "Path to the vmcore file.\n"
|
||||
"Default: " PROC_VMCORE,
|
||||
},
|
||||
{
|
||||
.option = { "hsa", required_argument, NULL, 'H' },
|
||||
.argument = "ZCOREHSAFILE",
|
||||
.desc = "Path to the zcore HSA file.\n"
|
||||
"Default: " ZCORE_HSA,
|
||||
},
|
||||
{
|
||||
.option = { "workdir", required_argument, NULL, 'W' },
|
||||
.argument = "WORKDIR",
|
||||
.desc = "Path to the work directory where temporary files can be "
|
||||
"stored.\nDefault: " WORKDIR,
|
||||
},
|
||||
{
|
||||
.option = { "bmvmcore", required_argument, NULL, 'B' },
|
||||
.argument = "VMCOREFILE",
|
||||
.desc = "Path to the target of the bind mount for the vmcore "
|
||||
"replacement.\nDefault: " PROC_VMCORE,
|
||||
},
|
||||
{
|
||||
.option = { "swap", required_argument, NULL, 'S' },
|
||||
.argument = "PATH",
|
||||
.desc = "Path to a swap device or file. The specified swap "
|
||||
"device or file must exist and have the proper swap "
|
||||
"format.\nDefault: no swap device or file is activated",
|
||||
},
|
||||
{
|
||||
.option = { "hsasize", required_argument, NULL, 'T' },
|
||||
.argument = "HSASIZE",
|
||||
.desc = "HSA size in bytes.\n"
|
||||
"Default: -1 (read from the zcore HSA file)",
|
||||
},
|
||||
{
|
||||
.option = { "dbgfsmnt", no_argument, NULL, 'D' },
|
||||
.desc = "Mount the debug file system.\n"
|
||||
"Default: the debug file system is not mounted",
|
||||
},
|
||||
{
|
||||
.option = { "hsamem", no_argument, NULL, 'F' },
|
||||
.desc = "Cache the HSA memory in regular memory.\n"
|
||||
"Default: the HSA memory is cached as a file within "
|
||||
"WORKDIR",
|
||||
},
|
||||
{
|
||||
.option = { "norelhsa", no_argument, NULL, 'R' },
|
||||
.desc = "Do NOT release the HSA memory after caching.\n"
|
||||
"Default: the HSA memory is released",
|
||||
},
|
||||
{
|
||||
.option = { "nobindmnt", no_argument, NULL, 'N' },
|
||||
.desc = "Do NOT replace the system's vmcore.\n"
|
||||
"Default: the system's vmcore is replaced",
|
||||
},
|
||||
UTIL_OPT_SECTION("LOGGING"),
|
||||
{
|
||||
.option = { "verbose", no_argument, NULL, 'V' },
|
||||
.desc = "Print verbose messages to stdout. Repeat this option "
|
||||
"for increased verbosity from just error messages to "
|
||||
"also include warning, information, debug, and trace "
|
||||
"messages. This option is intended for debugging",
|
||||
},
|
||||
{
|
||||
.option = { "fusedbg", no_argument, NULL, 'G' },
|
||||
.desc = "Enable FUSE debugging.\n"
|
||||
"Default: FUSE debugging is disabled",
|
||||
},
|
||||
UTIL_OPT_SECTION("GENERAL OPTIONS"),
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -365,6 +365,13 @@ function add_hsci {
|
||||
fi
|
||||
fi
|
||||
|
||||
#### Set MTU for the veth pair
|
||||
ndev_mtu="$(cat /sys/class/net/${ndev}/mtu)"
|
||||
hsdev_mtu="$(cat /sys/class/net/${hsdev}/mtu)"
|
||||
hsci_mtu=$(( ndev_mtu < hsdev_mtu ? ndev_mtu : hsdev_mtu ))
|
||||
ip link set dev $hscibp mtu $hsci_mtu
|
||||
ip link set dev $hsci mtu $hsci_mtu
|
||||
|
||||
#### Set veth pair to UP
|
||||
ip link set dev $hscibp up >/dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
|
||||
@@ -96,6 +96,17 @@ with an ASCII Record Separator character (0x1e) and suffixed with an ASCII Line
|
||||
Feed character (0x0a) in accordance with RFC7464.
|
||||
.BR
|
||||
|
||||
See section "OUTPUT FORMAT" for more details.
|
||||
.BR
|
||||
.PP
|
||||
.IP \(bu 3
|
||||
.B jsonl:
|
||||
Line-delimited JSON data structures
|
||||
|
||||
Data for each iteration is formatted as a separate JSON data structure
|
||||
separated by ASCII Line Feed character (0x0a, LF).
|
||||
.BR
|
||||
|
||||
See section "OUTPUT FORMAT" for more details.
|
||||
.BR
|
||||
.PP
|
||||
@@ -458,6 +469,14 @@ Subsequent objects each represent performance data for one iteration
|
||||
.br
|
||||
.PP
|
||||
|
||||
.SS jsonl
|
||||
|
||||
The jsonl output format is a data streaming variation of the JSON output format
|
||||
described above with the same properties as the json\-seq output with the
|
||||
difference that JSON data is separated only by an ASCII Line Feed character
|
||||
(0x0a, LF).
|
||||
|
||||
|
||||
.SH EXAMPLES
|
||||
To start hyptop with the "sys_list" window in interactive mode, enter:
|
||||
.br
|
||||
|
||||
@@ -233,7 +233,7 @@ static void l_fmt_init(void)
|
||||
flags |= FMT_QUOTEALL;
|
||||
if (g.o.format == FMT_CSV || g.o.format_all)
|
||||
flags |= FMT_KEEPINVAL;
|
||||
if (g.o.format == FMT_JSON || g.o.format == FMT_JSONSEQ)
|
||||
if (util_fmt_is_json(g.o.format))
|
||||
flags |= FMT_HANDLEINT;
|
||||
util_fmt_init(stdout, g.o.format, flags, 1);
|
||||
}
|
||||
|
||||
@@ -54,14 +54,6 @@ static char HELP_TEXT[] =
|
||||
#define OPT_FORMAT 256 /* --format */
|
||||
#define OPT_FORMAT_ALL 261 /* --all*/
|
||||
|
||||
/*
|
||||
* Options with underscore to keep compatibility
|
||||
*/
|
||||
#define OPT_BATCH_MODE 257 /* --batch_mode */
|
||||
#define OPT_SORT_FIELD 258 /* --sort | --sort_field */
|
||||
#define OPT_CPU_TYPES 259 /* --cpu_types */
|
||||
#define OPT_SMT_FACTOR 260 /* --smt_factor */
|
||||
|
||||
/*
|
||||
* Initialize default settings
|
||||
*/
|
||||
@@ -224,7 +216,7 @@ static void l_fields_set(char *str)
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the "--sort_field" option
|
||||
* Set the "--sort" option
|
||||
*/
|
||||
static void l_sort_field_set(char *str)
|
||||
{
|
||||
@@ -362,19 +354,18 @@ void opts_parse(int argc, char *argv[])
|
||||
{ "version", no_argument, NULL, 'v'},
|
||||
{ "help", no_argument, NULL, 'h'},
|
||||
{ "batch-mode", no_argument, NULL, 'b'},
|
||||
{ "batch_mode", no_argument, NULL, OPT_BATCH_MODE},
|
||||
{ "batch_mode", no_argument, NULL, 'b'},
|
||||
{ "all", no_argument, NULL, OPT_FORMAT_ALL },
|
||||
{ "delay", required_argument, NULL, 'd'},
|
||||
{ "smt-factor", required_argument, NULL, 'm'},
|
||||
{ "smt_factor", required_argument, NULL, OPT_SMT_FACTOR},
|
||||
{ "smt_factor", required_argument, NULL, 'm'},
|
||||
{ "window", required_argument, NULL, 'w'},
|
||||
{ "sys", required_argument, NULL, 's'},
|
||||
{ "iterations", required_argument, NULL, 'n'},
|
||||
{ "fields", required_argument, NULL, 'f'},
|
||||
{ "sort-field", required_argument, NULL, 'S'},
|
||||
{ "sort_field", required_argument, NULL, OPT_SORT_FIELD},
|
||||
{ "sort", required_argument, NULL, 'S'},
|
||||
{ "cpu-types", required_argument, NULL, 't'},
|
||||
{ "cpu_types", required_argument, NULL, OPT_CPU_TYPES},
|
||||
{ "cpu_types", required_argument, NULL, 't'},
|
||||
{ "format", required_argument, NULL, OPT_FORMAT },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
@@ -393,14 +384,12 @@ void opts_parse(int argc, char *argv[])
|
||||
case 'h':
|
||||
l_usage();
|
||||
hyptop_exit(0);
|
||||
case OPT_BATCH_MODE:
|
||||
case 'b':
|
||||
l_batch_mode_set();
|
||||
break;
|
||||
case 'd':
|
||||
l_delay_set(optarg);
|
||||
break;
|
||||
case OPT_SMT_FACTOR:
|
||||
case 'm':
|
||||
l_factor_set(optarg);
|
||||
break;
|
||||
@@ -413,14 +402,12 @@ void opts_parse(int argc, char *argv[])
|
||||
case 'n':
|
||||
l_iterations_set(optarg);
|
||||
break;
|
||||
case OPT_CPU_TYPES:
|
||||
case 't':
|
||||
l_cpu_types_set(optarg);
|
||||
break;
|
||||
case 'f':
|
||||
l_fields_set(optarg);
|
||||
break;
|
||||
case OPT_SORT_FIELD:
|
||||
case 'S':
|
||||
l_sort_field_set(optarg);
|
||||
break;
|
||||
|
||||
@@ -1037,7 +1037,7 @@ void table_fmt_start(void)
|
||||
{
|
||||
if (!g.o.format_specified)
|
||||
return;
|
||||
if (g.o.format != FMT_JSONSEQ)
|
||||
if (!util_fmt_is_json_stream(g.o.format))
|
||||
util_fmt_obj_start(FMT_LIST, "hyptop");
|
||||
}
|
||||
|
||||
@@ -1045,7 +1045,7 @@ void table_fmt_end(void)
|
||||
{
|
||||
if (!g.o.format_specified)
|
||||
return;
|
||||
if (g.o.format != FMT_JSONSEQ)
|
||||
if (!util_fmt_is_json_stream(g.o.format))
|
||||
util_fmt_obj_end(); /* hyptop[] */
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* autocomp - command line autocompletion
|
||||
*
|
||||
* Generating autocompletion scripts for bash and zsh
|
||||
* based on util_opt struct
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#ifndef LIB_UTIL_AUTOCOMP_H
|
||||
|
||||
@@ -45,12 +45,13 @@
|
||||
#define FMT_DEFAULT 0
|
||||
|
||||
/* Names of supported output format types. */
|
||||
#define FMT_TYPE_NAMES "json json-seq pairs csv"
|
||||
#define FMT_TYPE_NAMES "json json-seq jsonl pairs csv"
|
||||
|
||||
/**
|
||||
* enum util_fmt_t - Output format types.
|
||||
* @FMT_JSON: JavaScript Object Notation output data structure
|
||||
* @FMT_JSONSEQ: Sequence of JSON data structures according to RFC7464
|
||||
* @FMT_JSONL: Line-delimited JSON
|
||||
* @FMT_PAIRS: Textual key=value pairs
|
||||
* @FMT_CSV: Comma-separated-values output
|
||||
*
|
||||
@@ -59,6 +60,7 @@
|
||||
enum util_fmt_t {
|
||||
FMT_JSON,
|
||||
FMT_JSONSEQ,
|
||||
FMT_JSONL,
|
||||
FMT_PAIRS,
|
||||
FMT_CSV,
|
||||
};
|
||||
@@ -232,4 +234,23 @@ void util_fmt_obj_end(void);
|
||||
*/
|
||||
void util_fmt_pair(unsigned int mflags, const char *key, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* util_fmt_is_json() - Determine whether format is JSON.
|
||||
* @type: Format type identifier.
|
||||
*
|
||||
* Return: %true if type is JSON, %false otherwise.
|
||||
*/
|
||||
bool util_fmt_is_json(enum util_fmt_t type);
|
||||
|
||||
/**
|
||||
* util_fmt_is_json_stream() - Determine whether format is JSON stream.
|
||||
* @type: Format type identifier.
|
||||
*
|
||||
* Determine whether a given format @type represents a JSON streaming format
|
||||
* such as json-seq (@FMT_JSONSEQ) or jsonl (@FMT_JSONL).
|
||||
*
|
||||
* Return: %true if type is either @FMT_JSONSEQ or @FMT_JSONL, %false otherwise.
|
||||
*/
|
||||
bool util_fmt_is_json_stream(enum util_fmt_t type);
|
||||
|
||||
#endif /* LIB_UTIL_FMT_H */
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#ifndef LIB_UTIL_LIBC_H
|
||||
#define LIB_UTIL_LIBC_H
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -124,6 +125,29 @@ do { \
|
||||
va_end(ap); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Reads the target of a symbolic link at the given path.
|
||||
*
|
||||
* @param[in] path Path to the symbolic link
|
||||
* @return Newly allocated string with the link target, or NULL on error
|
||||
*/
|
||||
#define util_readlink(path) __util_readlinkat(__func__, __FILE__, __LINE__, AT_FDCWD, path)
|
||||
|
||||
/**
|
||||
* Reads the target of a symbolic link relative to a directory file descriptor.
|
||||
*
|
||||
* Semantics:
|
||||
* - If path is absolute, dirfd is ignored, per readlinkat semantics.
|
||||
* - If path is relative, it is resolved relative to dirfd.
|
||||
*
|
||||
* @param[in] dirfd Directory file descriptor or AT_FDCWD
|
||||
* @param[in] path Path to the symbolic link
|
||||
* @return Newly allocated string with the link target, or NULL on error
|
||||
*/
|
||||
#define util_readlinkat(dirfd, path) __util_readlinkat(__func__, __FILE__, __LINE__, dirfd, path)
|
||||
|
||||
char *__util_readlinkat(const char *func, const char *file, int line, int dirfd, const char *path);
|
||||
|
||||
int __util_vsprintf(const char *func, const char *file, int line,
|
||||
char *str, const char *fmt, va_list ap);
|
||||
char *util_strcat_realloc(char *str1, const char *str2);
|
||||
|
||||
58
include/lib/util_parse.h
Normal file
58
include/lib/util_parse.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* util - Utility function library
|
||||
*
|
||||
* String parsing utility functions
|
||||
*
|
||||
* Copyright IBM Corp. 2026
|
||||
*/
|
||||
|
||||
#ifndef LIB_UTIL_PARSE_H
|
||||
#define LIB_UTIL_PARSE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct util_range {
|
||||
size_t start;
|
||||
size_t end;
|
||||
};
|
||||
|
||||
/*
|
||||
* Parse a boolean input string into a boolean value
|
||||
* Accepts: "0"/"1", "n"/"y", "no"/"yes", "f"/"t", "false"/"true", "off"/"on"
|
||||
* Case-insensitive
|
||||
* @param input: Input string to parse
|
||||
* @return: 1 for true, 0 for false, -EINVAL for invalid input
|
||||
*/
|
||||
int util_parse_bool(const char *input);
|
||||
|
||||
/*
|
||||
* Parse byte sizes with optional unit suffixes
|
||||
* Supports: K/KiB, M/MiB, G/GiB, T/TiB, P/PiB, E/EiB
|
||||
* K/M/G/T/P/E use 1000-based multipliers
|
||||
* KiB/MiB/GiB/TiB/PiB/EiB use 1024-based multipliers
|
||||
* @param input: Input string to parse
|
||||
* @param bytes: Pointer to store parsed byte size
|
||||
* @return: 0 on success, negative error code on failure
|
||||
*/
|
||||
int util_parse_byte_size(const char *input, size_t *bytes);
|
||||
|
||||
/*
|
||||
* Parse numeric ranges in the format "start-end"
|
||||
* @param input: Input string to parse (format: "start-end")
|
||||
* @param range: Pointer to util_range struct to store result
|
||||
* @return: 0 on success, negative error code on failure
|
||||
*/
|
||||
int util_parse_range(const char *input, struct util_range *range);
|
||||
|
||||
/*
|
||||
* Parse integers with support for different bases
|
||||
* Supports: decimal, hex (0x prefix), binary (0b prefix), octal (0o prefix)
|
||||
* @param input: Input string to parse
|
||||
* @param value: Pointer to store parsed integer value
|
||||
* @return: 0 on success, negative error code on failure
|
||||
*/
|
||||
int util_parse_int(const char *input, size_t *value);
|
||||
|
||||
#endif
|
||||
@@ -13,5 +13,7 @@
|
||||
#define LIB_UTIL_STR_H
|
||||
|
||||
void util_str_rm_whitespace(const char *src, char *dest);
|
||||
const char *util_startswith(const char *s, const char *prefix);
|
||||
const char *util_startswith_no_case(const char *s, const char *prefix);
|
||||
|
||||
#endif /** LIB_UTIL_STR_H @} */
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#define BOOTPARMS_NSS_MAX 56
|
||||
#define BOOTPARMS_CCW_MAX 64
|
||||
#define BOOTPARMS_FCP_MAX 3452
|
||||
#define BOOTPARMS_SCPDATA_MAX 3452
|
||||
|
||||
#define OPT_BRCHR 0x80
|
||||
|
||||
@@ -835,6 +835,12 @@ static void chreipl_eckd(void)
|
||||
ERR_EXIT("Could not find DASD ECKD device \"%s\"", l.busid);
|
||||
}
|
||||
|
||||
check_exists("reipl/eckd/device", "\"eckd\" re-IPL target");
|
||||
if (l.bootparms_set && strlen(l.bootparms) > BOOTPARMS_SCPDATA_MAX) {
|
||||
ERR_EXIT("Maximum boot parameter length exceeded (%zu/%u)",
|
||||
strlen(l.bootparms), BOOTPARMS_SCPDATA_MAX);
|
||||
}
|
||||
|
||||
if (l.reipl_clear >= 0) {
|
||||
check_exists("reipl/eckd/clear", "ECKD re-IPL clear attribute");
|
||||
write_str(l.reipl_clear ? "1" : "0", "reipl/eckd/clear");
|
||||
@@ -848,6 +854,8 @@ static void chreipl_eckd(void)
|
||||
write_str(l.bootprog, "reipl/eckd/bootprog");
|
||||
write_str(l.busid, "reipl/eckd/device");
|
||||
write_str_optional(l.loadparm, "reipl/eckd/loadparm", l.loadparm_set, "loadparm");
|
||||
write_str_optional(l.bootparms, "reipl/eckd/scp_data", l.bootparms_set,
|
||||
"boot parameters");
|
||||
write_str("eckd", "reipl/reipl_type");
|
||||
print_eckd(0, "eckd");
|
||||
}
|
||||
@@ -862,9 +870,9 @@ static void chreipl_fcp(void)
|
||||
ERR_EXIT("Could not find FCP device \"%s\"", l.busid);
|
||||
}
|
||||
check_exists("reipl/fcp/device", "\"fcp\" re-IPL target");
|
||||
if (l.bootparms_set && strlen(l.bootparms) > BOOTPARMS_FCP_MAX) {
|
||||
if (l.bootparms_set && strlen(l.bootparms) > BOOTPARMS_SCPDATA_MAX) {
|
||||
ERR_EXIT("Maximum boot parameter length exceeded (%zu/%u)",
|
||||
strlen(l.bootparms), BOOTPARMS_FCP_MAX);
|
||||
strlen(l.bootparms), BOOTPARMS_SCPDATA_MAX);
|
||||
}
|
||||
|
||||
if (l.reipl_clear >= 0) {
|
||||
@@ -905,9 +913,9 @@ static void chreipl_nvme(void)
|
||||
}
|
||||
check_exists("reipl/nvme/fid", "\"nvme\" re-IPL target");
|
||||
|
||||
if (l.bootparms_set && strlen(l.bootparms) > BOOTPARMS_FCP_MAX) {
|
||||
if (l.bootparms_set && strlen(l.bootparms) > BOOTPARMS_SCPDATA_MAX) {
|
||||
ERR_EXIT("Maximum boot parameter length exceeded (%zu/%u)",
|
||||
strlen(l.bootparms), BOOTPARMS_FCP_MAX);
|
||||
strlen(l.bootparms), BOOTPARMS_SCPDATA_MAX);
|
||||
}
|
||||
|
||||
if (l.reipl_clear >= 0) {
|
||||
|
||||
@@ -157,6 +157,7 @@ void print_eckd(int show_ipl, const char *name)
|
||||
{
|
||||
char *dir = show_ipl ? "ipl" : "reipl/eckd";
|
||||
char *path_loadparm = util_path_sysfs("firmware/%s/loadparm", dir);
|
||||
char *path_reipl_clear = util_path_sysfs("firmware/reipl/eckd/clear");
|
||||
char *path_secure_boot = util_path_sysfs("firmware/ipl/secure");
|
||||
char *loadparm;
|
||||
|
||||
@@ -172,7 +173,7 @@ void print_eckd(int show_ipl, const char *name)
|
||||
printf("Loadparm: \"%s\"\n", loadparm);
|
||||
free(loadparm);
|
||||
}
|
||||
if (!show_ipl)
|
||||
if (!show_ipl && access(path_reipl_clear, R_OK) == 0)
|
||||
print_fw_str("clear: %s\n", dir, "clear");
|
||||
if (access(path_secure_boot, R_OK) == 0)
|
||||
print_fw_str("Secure boot: %s\n", "ipl", "secure");
|
||||
|
||||
@@ -2172,7 +2172,7 @@ int write_public_key(const char *pem_filename, EVP_PKEY *pkey)
|
||||
*/
|
||||
static bool is_duplicate_name_entry(X509_NAME *name, X509_NAME_ENTRY *entry)
|
||||
{
|
||||
X509_NAME_ENTRY *ne;
|
||||
const X509_NAME_ENTRY *ne;
|
||||
int count, i;
|
||||
|
||||
count = X509_NAME_entry_count(name);
|
||||
|
||||
@@ -378,8 +378,14 @@ int kmip_connection_tls_init(struct kmip_connection *conn, bool debug)
|
||||
if (conn->config.tls_verify_host) {
|
||||
SSL_set_hostflags(conn->plain_tls.ssl,
|
||||
X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
|
||||
#if OPENSSL_VERSION_PREREQ(4, 0)
|
||||
if (SSL_set1_ipaddr(conn->plain_tls.ssl, hostname) != 1 &&
|
||||
SSL_set1_dnsname(conn->plain_tls.ssl, hostname) != 1) {
|
||||
kmip_debug(debug, "SSL_set1_ipaddr/dnsname failed");
|
||||
#else
|
||||
if (SSL_set1_host(conn->plain_tls.ssl, hostname) != 1) {
|
||||
kmip_debug(debug, "SSL_set1_host failed");
|
||||
#endif
|
||||
if (debug)
|
||||
ERR_print_errors_fp(stderr);
|
||||
rc = -EIO;
|
||||
|
||||
@@ -395,7 +395,7 @@ const struct sk_digest_info *SK_UTIL_get_digest_info(int digest_nid)
|
||||
static bool SK_UTILS_is_duplicate_name_entry(const X509_NAME *name,
|
||||
const X509_NAME_ENTRY *entry)
|
||||
{
|
||||
X509_NAME_ENTRY *ne;
|
||||
const X509_NAME_ENTRY *ne;
|
||||
int count, i;
|
||||
|
||||
count = X509_NAME_entry_count(name);
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* autocomp - command line autocompletion
|
||||
*
|
||||
* Generating autocompletion scripts for bash and zsh
|
||||
* based on util_opt struct
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
@@ -22,18 +14,19 @@
|
||||
#include "lib/util_autocomp.h"
|
||||
#include "lib/util_opt.h"
|
||||
|
||||
static const char *bash_script_part1 = "() {\n\n\
|
||||
\tlocal current_word previous_word options_array\n\n\
|
||||
static const char *bash_script_part1 = "() {\n\
|
||||
\tlocal current_word options_array\n\
|
||||
\tCOMPREPLY=()\n\n\
|
||||
\tcurrent_word=\"${COMP_WORDS[COMP_CWORD]}\"\n\n\
|
||||
\tprevious_word=\"${COMP_WORDS[COMP_CWORD-1]}\"\n\n\
|
||||
\tcurrent_word=\"${COMP_WORDS[COMP_CWORD]}\"\n\
|
||||
\toptions_array=\"";
|
||||
|
||||
static const char *bash_script_part2 = "\tif [[ ${current_word} == -* || ${COMP_CWORD} -eq 1 ]] ; then\n\n\
|
||||
\t\tCOMPREPLY=( $(compgen -W \"${options_array}\" -- ${current_word} ) )\n\n\
|
||||
\t\treturn 0\n\n\
|
||||
\tfi\n\n\
|
||||
}\n\n\
|
||||
static const char *bash_script_part2 = "\tif [[ ${current_word} == -* ]] ; then\n\
|
||||
\t\tmapfile -t \"COMPREPLY\" < <(compgen -W \"${options_array}\" -- \"$current_word\")\n\
|
||||
\telse\n\
|
||||
\t\tcompopt -o bashdefault -o default\n\
|
||||
\tfi\n\
|
||||
\treturn 0\n\
|
||||
}\n\
|
||||
complete -F ";
|
||||
|
||||
static char *format_name(const char *fmt, char *tool_name)
|
||||
@@ -63,7 +56,7 @@ static int init_scriptfile(char *file_path)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open(file_path, O_CREAT | O_WRONLY, 0644);
|
||||
fd = open(file_path, O_CREAT | O_WRONLY | O_TRUNC, 0644);
|
||||
if (fd < 0)
|
||||
return -EIO;
|
||||
return fd;
|
||||
@@ -86,7 +79,7 @@ static int start_bash_scriptfile(int fd, char *func_name)
|
||||
|
||||
static int start_zsh_scriptfile(int fd, char *func_name, char *tool_name)
|
||||
{
|
||||
const char *part3 = " {\n\n\t_arguments -C \\\n";
|
||||
const char *part3 = " {\n\n\t_arguments -C -A \"*\" \\\n";
|
||||
const char *part2 = "\n\nfunction ";
|
||||
const char *part1 = "#compdef ";
|
||||
int len, ret = 0;
|
||||
@@ -127,6 +120,7 @@ static int write_bash_command_options(struct util_opt *opt_vec, int fd)
|
||||
|
||||
static int write_zsh_command_options(struct util_opt *opt_vec, int fd)
|
||||
{
|
||||
const char *end = "\t\t\"*:files:_files\"\n}\n";
|
||||
const char *name, *desc;
|
||||
char *str;
|
||||
int len;
|
||||
@@ -145,8 +139,14 @@ static int write_zsh_command_options(struct util_opt *opt_vec, int fd)
|
||||
free(str);
|
||||
}
|
||||
}
|
||||
if (write(fd, "\n}\n", 3) != 3)
|
||||
len = asprintf(&str, "%s", end);
|
||||
if (len == -1)
|
||||
return -EIO;
|
||||
if (write(fd, str, len) != len) {
|
||||
free(str);
|
||||
return -EIO;
|
||||
}
|
||||
free(str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -169,35 +169,6 @@ static int finish_bash_scriptfile(char *tool_name, int fd, char *func_name)
|
||||
* Adds tab completion in bash for a command.
|
||||
* Works by generating an autocompletion
|
||||
* script file at '/usr/share/bash-completion/completions'.
|
||||
*
|
||||
* The full script will be as follows, supposing the tool name is
|
||||
* 'example' and it only has the options '--help' and
|
||||
* '--version':
|
||||
*
|
||||
* _example() {
|
||||
*
|
||||
* local current_word previous_word options_array
|
||||
*
|
||||
* COMPREPLY=()
|
||||
*
|
||||
* current_word="${COMP_WORDS[COMP_CWORD]}"
|
||||
*
|
||||
* previous_word="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
*
|
||||
* options_array="--version --help"
|
||||
*
|
||||
* if [[ ${current_word} == -* || ${COMP_CWORD} -eq 1 ]] ; then
|
||||
*
|
||||
* COMPREPLY=( $(compgen -W "${options_array}" -- ${current_word} ) )
|
||||
*
|
||||
* return 0
|
||||
*
|
||||
* fi
|
||||
*
|
||||
* }
|
||||
*
|
||||
* complete -F _example example
|
||||
*
|
||||
*/
|
||||
static void generate_bash_autocomp(struct util_opt *opt_vec, char *tool_name)
|
||||
{
|
||||
@@ -244,22 +215,6 @@ end:
|
||||
* Adds tab completion in zsh for a command.
|
||||
* Works by generating an autocompletion
|
||||
* script file at '/usr/share/zsh/site-functions'.
|
||||
*
|
||||
* The full script will be as follows, supposing the tool name is
|
||||
* 'example' and it only has the options '--help', -h and
|
||||
* '--version' (the descriptions, as well as the flags are
|
||||
* taken from a util_opt struct):
|
||||
*
|
||||
* #compdef example_completion
|
||||
*
|
||||
* function _example_completion {
|
||||
*
|
||||
* _arguments -C \
|
||||
* "-h[Show help information]" \
|
||||
* "--help[Show help but long format]" \
|
||||
* "--version[Show version]"
|
||||
* }
|
||||
*
|
||||
*/
|
||||
static void generate_zsh_autocomp(struct util_opt *opt_vec, char *tool_name)
|
||||
{
|
||||
|
||||
@@ -544,19 +544,6 @@ int util_file_read_va(const char *path, const char *fmt, ...)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an error message indicating an out-of-memory situation and exit.
|
||||
*/
|
||||
static void oom(void)
|
||||
{
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
|
||||
/* We can't rely on our clean-up routines to work reliably during an
|
||||
* OOM situation, so just exit here.
|
||||
*/
|
||||
exit(UTIL_EXIT_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all data from @fd and return address of resulting buffer in
|
||||
* @buffer_ptr. If @size_ptr is non-zero, use it to store the size of the
|
||||
@@ -576,9 +563,7 @@ util_exit_code_t util_file_read_fd_buf(FILE *fd, void **buffer_ptr,
|
||||
size_t done = 0;
|
||||
|
||||
while (!feof(fd)) {
|
||||
buffer = realloc(buffer, done + READ_CHUNK_SIZE);
|
||||
if (!buffer)
|
||||
oom();
|
||||
buffer = util_realloc(buffer, done + READ_CHUNK_SIZE);
|
||||
done += fread(&buffer[done], 1, READ_CHUNK_SIZE, fd);
|
||||
if (ferror(fd)) {
|
||||
free(buffer);
|
||||
@@ -586,9 +571,7 @@ util_exit_code_t util_file_read_fd_buf(FILE *fd, void **buffer_ptr,
|
||||
}
|
||||
}
|
||||
|
||||
buffer = realloc(buffer, done);
|
||||
if (!buffer && done > 0)
|
||||
oom();
|
||||
buffer = util_realloc(buffer, done);
|
||||
|
||||
*buffer_ptr = buffer;
|
||||
if (size_ptr)
|
||||
@@ -635,9 +618,7 @@ char *util_file_read_fd(FILE *fd, int chomp)
|
||||
done--;
|
||||
|
||||
/* NULL-terminate. */
|
||||
buffer = realloc(buffer, done + 1);
|
||||
if (!buffer)
|
||||
oom();
|
||||
buffer = util_realloc(buffer, done + 1);
|
||||
buffer[done] = 0;
|
||||
|
||||
return buffer;
|
||||
|
||||
@@ -91,6 +91,7 @@ static const struct {
|
||||
} formats[] = {
|
||||
{ "json", FMT_JSON },
|
||||
{ "json-seq", FMT_JSONSEQ },
|
||||
{ "jsonl", FMT_JSONL },
|
||||
{ "pairs", FMT_PAIRS },
|
||||
{ "csv", FMT_CSV },
|
||||
};
|
||||
@@ -111,6 +112,29 @@ bool util_fmt_name_to_type(const char *name, enum util_fmt_t *type)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool util_fmt_is_json(enum util_fmt_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case FMT_JSON:
|
||||
case FMT_JSONSEQ:
|
||||
case FMT_JSONL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool util_fmt_is_json_stream(enum util_fmt_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case FMT_JSONSEQ:
|
||||
case FMT_JSONL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void safe_write(const char *str)
|
||||
{
|
||||
size_t done, todo;
|
||||
@@ -129,7 +153,7 @@ static void _indent(unsigned int off, bool safe)
|
||||
{
|
||||
unsigned int num, i;
|
||||
|
||||
if (f.type == FMT_JSONSEQ)
|
||||
if (util_fmt_is_json_stream(f.type))
|
||||
return;
|
||||
num = f.ind_base + off;
|
||||
if (f.type == FMT_JSON && f.lvl > 0)
|
||||
@@ -408,8 +432,8 @@ static void emit_meta_object(void)
|
||||
util_fmt_pair(quoted, "time", "%s", date);
|
||||
_util_fmt_obj_end();
|
||||
|
||||
if (f.type == FMT_JSONSEQ) {
|
||||
/* Tool meta-data is a separate object for JSONSEQ. */
|
||||
if (util_fmt_is_json_stream(f.type)) {
|
||||
/* Tool meta-data is a separate object for JSON streams. */
|
||||
util_fmt_obj_end();
|
||||
}
|
||||
}
|
||||
@@ -478,7 +502,7 @@ void util_fmt_obj_end(void)
|
||||
{
|
||||
_util_fmt_obj_end();
|
||||
|
||||
if (f.lvl == 1 && f.meta_done && f.type != FMT_JSONSEQ) {
|
||||
if (f.lvl == 1 && f.meta_done && !util_fmt_is_json_stream(f.type)) {
|
||||
/* Emit closure for top-level meta-container object. */
|
||||
util_fmt_obj_end();
|
||||
}
|
||||
@@ -737,7 +761,7 @@ void util_fmt_init(FILE *fd, enum util_fmt_t type, unsigned int flags,
|
||||
f.do_warn = (flags & FMT_WARN);
|
||||
f.handle_int = (flags & FMT_HANDLEINT);
|
||||
f.api_level = api_level;
|
||||
if (type == FMT_JSONSEQ)
|
||||
if (util_fmt_is_json_stream(type))
|
||||
f.nl = "";
|
||||
else
|
||||
f.nl = "\n";
|
||||
@@ -750,6 +774,7 @@ void util_fmt_init(FILE *fd, enum util_fmt_t type, unsigned int flags,
|
||||
break;
|
||||
case FMT_JSON:
|
||||
case FMT_JSONSEQ:
|
||||
case FMT_JSONL:
|
||||
f.obj_start = &json_obj_start;
|
||||
f.obj_end = &json_obj_end;
|
||||
f.map = &json_map;
|
||||
|
||||
@@ -193,6 +193,9 @@ int main(int UNUSED(argc), char *UNUSED(argv[]))
|
||||
announce("JSON formatted as sequence");
|
||||
simple_example(FMT_JSONSEQ, FMT_DEFAULT);
|
||||
|
||||
announce("JSON Lines format");
|
||||
simple_example(FMT_JSONL, FMT_DEFAULT);
|
||||
|
||||
announce("Pairs output");
|
||||
simple_example(FMT_PAIRS, FMT_KEEPINVAL);
|
||||
|
||||
@@ -232,6 +235,9 @@ int main(int UNUSED(argc), char *UNUSED(argv[]))
|
||||
announce("JSON sequence output with meta-data");
|
||||
meta_example(FMT_JSONSEQ);
|
||||
|
||||
announce("JSON Lines output with meta-data");
|
||||
meta_example(FMT_JSONL);
|
||||
|
||||
announce("Pairs output with meta-data");
|
||||
meta_example(FMT_PAIRS);
|
||||
|
||||
|
||||
@@ -10,11 +10,15 @@
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "lib/util_base.h"
|
||||
#include "lib/util_libc.h"
|
||||
@@ -89,6 +93,11 @@ void *__util_realloc(const char *func, const char *file, int line,
|
||||
{
|
||||
void *buf;
|
||||
|
||||
if (size == 0) {
|
||||
free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = realloc(ptr, size);
|
||||
|
||||
if (buf == NULL)
|
||||
@@ -290,3 +299,31 @@ size_t util_strlcpy(char *dest, const char *src, size_t size)
|
||||
|
||||
return str_len;
|
||||
}
|
||||
|
||||
char *__util_readlinkat(const char *func, const char *file, int line, int dirfd, const char *path)
|
||||
{
|
||||
ssize_t link_len = PATH_MAX;
|
||||
struct stat st;
|
||||
char *linkdir;
|
||||
ssize_t len;
|
||||
|
||||
if (fstatat(dirfd, path, &st, AT_SYMLINK_NOFOLLOW) == 0 && st.st_size > 0)
|
||||
link_len = st.st_size + 1;
|
||||
|
||||
linkdir = __util_malloc(func, file, line, link_len);
|
||||
|
||||
len = readlinkat(dirfd, path, linkdir, link_len);
|
||||
if (len == -1) {
|
||||
free(linkdir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len >= link_len) {
|
||||
warnx("%s: Link target too long", path);
|
||||
free(linkdir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
linkdir[len] = '\0';
|
||||
return __util_realloc(func, file, line, linkdir, (size_t)len + 1);
|
||||
}
|
||||
|
||||
220
libutil/util_parse.c
Normal file
220
libutil/util_parse.c
Normal file
@@ -0,0 +1,220 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* util - Utility function library
|
||||
*
|
||||
* String parsing utility functions
|
||||
*
|
||||
* Copyright IBM Corp. 2026
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/util_libc.h"
|
||||
#include "lib/util_parse.h"
|
||||
#include "lib/util_str.h"
|
||||
#include "lib/zt_common.h"
|
||||
|
||||
enum size_unit {
|
||||
UNIT_BYTES = 0,
|
||||
UNIT_KIB, /* 1024 */
|
||||
UNIT_K, /* 1000 */
|
||||
UNIT_MIB, /* 1024^2 */
|
||||
UNIT_M, /* 1000^2 */
|
||||
UNIT_GIB, /* 1024^3 */
|
||||
UNIT_G, /* 1000^3 */
|
||||
UNIT_TIB, /* 1024^4 */
|
||||
UNIT_T, /* 1000^4 */
|
||||
UNIT_PIB, /* 1024^5 */
|
||||
UNIT_P, /* 1000^5 */
|
||||
UNIT_EIB, /* 1024^6 */
|
||||
UNIT_E, /* 1000^6 */
|
||||
};
|
||||
|
||||
struct unit_mapping {
|
||||
const char *suffix;
|
||||
enum size_unit unit;
|
||||
uint64_t multiplier;
|
||||
};
|
||||
|
||||
static const struct unit_mapping unit_table[] = {
|
||||
{ "EiB", UNIT_EIB, 1024ULL * 1024 * 1024 * 1024 * 1024 * 1024 },
|
||||
{ "E", UNIT_E, 1000ULL * 1000 * 1000 * 1000 * 1000 * 1000 },
|
||||
{ "PiB", UNIT_PIB, 1024ULL * 1024 * 1024 * 1024 * 1024 },
|
||||
{ "P", UNIT_P, 1000ULL * 1000 * 1000 * 1000 * 1000 },
|
||||
{ "TiB", UNIT_TIB, 1024ULL * 1024 * 1024 * 1024 },
|
||||
{ "T", UNIT_T, 1000ULL * 1000 * 1000 * 1000 },
|
||||
{ "GiB", UNIT_GIB, 1024ULL * 1024 * 1024 },
|
||||
{ "G", UNIT_G, 1000ULL * 1000 * 1000 },
|
||||
{ "MiB", UNIT_MIB, 1024ULL * 1024 },
|
||||
{ "M", UNIT_M, 1000ULL * 1000 },
|
||||
{ "KiB", UNIT_KIB, 1024ULL },
|
||||
{ "K", UNIT_K, 1000ULL },
|
||||
{ "", UNIT_BYTES, 1ULL }
|
||||
};
|
||||
|
||||
static const char *const bool_false_values[] = { "0", "n", "no", "f", "false", "off" };
|
||||
static const char *const bool_true_values[] = { "1", "y", "yes", "t", "true", "on" };
|
||||
|
||||
/* Ensure both arrays have the same size for consistency */
|
||||
STATIC_ASSERT(ARRAY_SIZE(bool_false_values) == ARRAY_SIZE(bool_true_values));
|
||||
|
||||
static const struct unit_mapping *find_unit_suffix(const char *suffix)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!suffix || *suffix == '\0')
|
||||
return &unit_table[ARRAY_SIZE(unit_table) - 1];
|
||||
for (i = 0; i < ARRAY_SIZE(unit_table); i++) {
|
||||
if (strcasecmp(suffix, unit_table[i].suffix) == 0)
|
||||
return &unit_table[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* util_parse_bool - Parse a boolean value from a string
|
||||
* @input: Input string to parse
|
||||
*
|
||||
* Returns: 1 for true, 0 for false, -EINVAL on error
|
||||
*/
|
||||
int util_parse_bool(const char *input)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!input)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bool_false_values); i++) {
|
||||
if (strcasecmp(input, bool_false_values[i]) == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bool_true_values); i++) {
|
||||
if (strcasecmp(input, bool_true_values[i]) == 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int util_parse_byte_size(const char *input, size_t *bytes)
|
||||
{
|
||||
const struct unit_mapping *unit;
|
||||
uint64_t multiplier = 1;
|
||||
unsigned long value;
|
||||
char *endptr;
|
||||
|
||||
if (!input || !bytes)
|
||||
return -EINVAL;
|
||||
|
||||
errno = 0;
|
||||
value = strtoul(input, &endptr, 10);
|
||||
if (errno == ERANGE)
|
||||
return -ERANGE;
|
||||
if (errno != 0)
|
||||
return -errno;
|
||||
if (endptr == input)
|
||||
return -EINVAL;
|
||||
|
||||
if (*endptr != '\0') {
|
||||
unit = find_unit_suffix(endptr);
|
||||
if (!unit)
|
||||
return -EINVAL;
|
||||
multiplier = unit->multiplier;
|
||||
}
|
||||
|
||||
if (value > SIZE_MAX / multiplier)
|
||||
return -ERANGE;
|
||||
|
||||
*bytes = (size_t)(value * multiplier);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int util_parse_range(const char *input, struct util_range *range)
|
||||
{
|
||||
char *start_str, *end_str;
|
||||
char *input_copy;
|
||||
char *dash_pos;
|
||||
int ret = 0;
|
||||
|
||||
if (!input || !range)
|
||||
return -EINVAL;
|
||||
|
||||
input_copy = util_strdup(input);
|
||||
|
||||
dash_pos = strchr(input_copy, '-');
|
||||
if (!dash_pos) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*dash_pos = '\0';
|
||||
start_str = input_copy;
|
||||
end_str = dash_pos + 1;
|
||||
|
||||
ret = util_parse_int(start_str, &range->start);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = util_parse_int(end_str, &range->end);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (range->start > range->end) {
|
||||
ret = -ERANGE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
free(input_copy);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int util_parse_int(const char *input, size_t *value)
|
||||
{
|
||||
const char *num_start, *rest;
|
||||
char *endptr = NULL;
|
||||
int base = 0;
|
||||
|
||||
if (!input || !value)
|
||||
return -EINVAL;
|
||||
if (*input == '\0')
|
||||
return -EINVAL;
|
||||
|
||||
num_start = input;
|
||||
|
||||
/* Determine base from prefix */
|
||||
/* Supports: 0x (hex), 0b (binary), 0o/0 (octal), decimal */
|
||||
rest = util_startswith_no_case(input, "0b");
|
||||
if (rest) {
|
||||
base = 2;
|
||||
num_start = rest;
|
||||
if (*num_start == '\0')
|
||||
return -EINVAL;
|
||||
} else {
|
||||
rest = util_startswith_no_case(input, "0o");
|
||||
if (rest) {
|
||||
base = 8;
|
||||
num_start = rest;
|
||||
if (*num_start == '\0')
|
||||
return -EINVAL;
|
||||
}
|
||||
/* base=0: strtoull handles 0x (hex) and 0 (octal) */
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
*value = strtoull(num_start, &endptr, base);
|
||||
|
||||
if (errno == ERANGE)
|
||||
return -ERANGE;
|
||||
if (!endptr || endptr == num_start || *endptr != '\0')
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -68,7 +68,7 @@ static int __scandir(struct dirent ***de_vec, const char *path,
|
||||
continue;
|
||||
de_new = util_malloc(sizeof(*de_new));
|
||||
*de_new = *de;
|
||||
de_vec_new = realloc(de_vec_new, sizeof(void *) * (count + 1));
|
||||
de_vec_new = util_realloc(de_vec_new, sizeof(void *) * (count + 1));
|
||||
de_vec_new[count++] = de_new;
|
||||
}
|
||||
closedir(dirp);
|
||||
|
||||
@@ -3,14 +3,16 @@
|
||||
*
|
||||
* Manipulate and work with strings
|
||||
*
|
||||
* Copyright IBM Corp. 2025
|
||||
* Copyright IBM Corp. 2026
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/util_panic.h"
|
||||
#include "lib/util_str.h"
|
||||
|
||||
/**
|
||||
@@ -31,3 +33,45 @@ void util_str_rm_whitespace(const char *src, char *dest)
|
||||
}
|
||||
*dest = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if string \a s starts with \a prefix
|
||||
*
|
||||
* @param[in] s String to check
|
||||
* @param[in] prefix Prefix to match
|
||||
*
|
||||
* @returns Pointer to the character after the prefix if match is found,
|
||||
* NULL otherwise
|
||||
*/
|
||||
const char *util_startswith(const char *s, const char *prefix)
|
||||
{
|
||||
size_t sz;
|
||||
|
||||
util_assert(s != NULL, "Internal error: s input is NULL");
|
||||
util_assert(prefix != NULL, "Internal error: prefix input is NULL");
|
||||
sz = strlen(prefix);
|
||||
if (strncmp(s, prefix, sz) == 0)
|
||||
return s + sz;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if string \a s starts with \a prefix (case-insensitive)
|
||||
*
|
||||
* @param[in] s String to check
|
||||
* @param[in] prefix Prefix to match (case-insensitive)
|
||||
*
|
||||
* @returns Pointer to the character after the prefix if match is found,
|
||||
* NULL otherwise
|
||||
*/
|
||||
const char *util_startswith_no_case(const char *s, const char *prefix)
|
||||
{
|
||||
size_t sz;
|
||||
|
||||
util_assert(s != NULL, "Internal error: s input is NULL");
|
||||
util_assert(prefix != NULL, "Internal error: prefix input is NULL");
|
||||
sz = strlen(prefix);
|
||||
if (strncasecmp(s, prefix, sz) == 0)
|
||||
return s + sz;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
#include "lib/util_path.h"
|
||||
#include "lib/util_sys.h"
|
||||
|
||||
/* lstat() doesn't work for sysfs files, a fixed size is therefore inevitable */
|
||||
#define READLINK_SIZE 256
|
||||
#define PAGE_SIZE 4096
|
||||
|
||||
/**
|
||||
@@ -137,10 +135,10 @@ int util_sys_get_base_dev(dev_t dev, dev_t *base_dev)
|
||||
*/
|
||||
int util_sys_get_dev_addr(const char *dev, char *addr)
|
||||
{
|
||||
char device[READLINK_SIZE], *result;
|
||||
unsigned int maj, min;
|
||||
struct stat s;
|
||||
ssize_t len;
|
||||
char *linkdir;
|
||||
char *result;
|
||||
dev_t base;
|
||||
char *path;
|
||||
|
||||
@@ -160,19 +158,18 @@ int util_sys_get_dev_addr(const char *dev, char *addr)
|
||||
else
|
||||
return -1;
|
||||
|
||||
len = readlink(path, device, READLINK_SIZE - 1);
|
||||
linkdir = util_readlink(path);
|
||||
free(path);
|
||||
if (len != -1)
|
||||
device[len] = '\0';
|
||||
else
|
||||
if (!linkdir)
|
||||
return -1;
|
||||
|
||||
result = strrchr(device, '/');
|
||||
result = strrchr(linkdir, '/');
|
||||
if (result)
|
||||
result++;
|
||||
else
|
||||
result = device;
|
||||
result = linkdir;
|
||||
strcpy(addr, result);
|
||||
free(linkdir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
214
libvtoc/vtoc.c
214
libvtoc/vtoc.c
@@ -26,23 +26,23 @@ static unsigned char EBCtoASC[256] =
|
||||
-INP */
|
||||
0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
|
||||
/* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL
|
||||
-SW */
|
||||
-SW */
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
|
||||
/* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */
|
||||
0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
|
||||
/* 0x38 -SBS -IT -RFF -CU3 DC4 NAK ---- SUB */
|
||||
0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
|
||||
/* 0x40 SP RSP <EFBFBD> ---- */
|
||||
/* 0x40 SP RSP ä ---- */
|
||||
0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
|
||||
/* 0x48 . < ( + | */
|
||||
0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
|
||||
/* 0x50 & ---- */
|
||||
0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
|
||||
/* 0x58 <EFBFBD> ! $ * ) ; */
|
||||
/* 0x58 ß ! $ * ) ; */
|
||||
0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA,
|
||||
/* 0x60 - / ---- <EFBFBD> ---- ---- ---- */
|
||||
/* 0x60 - / ---- Ä ---- ---- ---- */
|
||||
0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
|
||||
/* 0x68 ---- , % _ > ? */
|
||||
/* 0x68 ---- , % _ > ? */
|
||||
0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
|
||||
/* 0x70 --- ---- ---- ---- ---- ---- ---- */
|
||||
0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
@@ -52,7 +52,7 @@ static unsigned char EBCtoASC[256] =
|
||||
0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
||||
/* 0x88 h i ---- ---- ---- */
|
||||
0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
|
||||
/* 0x90 <EFBFBD> j k l m n o p */
|
||||
/* 0x90 ° j k l m n o p */
|
||||
0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
|
||||
/* 0x98 q r ---- ---- */
|
||||
0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
|
||||
@@ -60,25 +60,25 @@ static unsigned char EBCtoASC[256] =
|
||||
0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
|
||||
/* 0xA8 y z ---- ---- ---- ---- */
|
||||
0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
|
||||
/* 0xB0 ^ ---- <EFBFBD> ---- */
|
||||
/* 0xB0 ^ ---- § ---- */
|
||||
0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
|
||||
/* 0xB8 ---- [ ] ---- ---- ---- ---- */
|
||||
0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07,
|
||||
/* 0xC0 { A B C D E F G */
|
||||
0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||||
/* 0xC8 H I ---- <EFBFBD> ---- */
|
||||
/* 0xC8 H I ---- ö ---- */
|
||||
0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
|
||||
/* 0xD0 } J K L M N O P */
|
||||
0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
|
||||
/* 0xD8 Q R ---- <EFBFBD> */
|
||||
/* 0xD8 Q R ---- ü */
|
||||
0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
|
||||
/* 0xE0 \ S T U V W X */
|
||||
0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
|
||||
/* 0xE8 Y Z ---- <EFBFBD> ---- ---- ---- */
|
||||
/* 0xE8 Y Z ---- Ö ---- ---- ---- */
|
||||
0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
|
||||
/* 0xF0 0 1 2 3 4 5 6 7 */
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
/* 0xF8 8 9 ---- ---- <EFBFBD> ---- ---- ---- */
|
||||
/* 0xF8 8 9 ---- ---- Ü ---- ---- ---- */
|
||||
0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
|
||||
};
|
||||
|
||||
@@ -144,7 +144,7 @@ static char buffer[85];
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static void vtoc_error(enum failure why, char *s1, char *s2)
|
||||
static void vtoc_error(enum failure why, char *s1, char *s2)
|
||||
{
|
||||
switch (why) {
|
||||
case unable_to_open:
|
||||
@@ -172,11 +172,11 @@ static void vtoc_error(enum failure why, char *s1, char *s2)
|
||||
/*
|
||||
*
|
||||
*/
|
||||
char * vtoc_ebcdic_enc (char *source, char *target, int l)
|
||||
char * vtoc_ebcdic_enc (char *source, char *target, int l)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < l; i++)
|
||||
for (i = 0; i < l; i++)
|
||||
target[i]=ASCtoEBC[(unsigned char)(source[i])];
|
||||
|
||||
return target;
|
||||
@@ -186,11 +186,11 @@ char * vtoc_ebcdic_enc (char *source, char *target, int l)
|
||||
/*
|
||||
*
|
||||
*/
|
||||
char * vtoc_ebcdic_dec (char *source, char *target, int l)
|
||||
char * vtoc_ebcdic_dec (char *source, char *target, int l)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < l; i++)
|
||||
for (i = 0; i < l; i++)
|
||||
target[i]=EBCtoASC[(unsigned char)(source[i])];
|
||||
|
||||
return target;
|
||||
@@ -201,8 +201,8 @@ char * vtoc_ebcdic_dec (char *source, char *target, int l)
|
||||
*
|
||||
*/
|
||||
void vtoc_set_extent (extent_t *ext, uint8_t typeind, uint8_t seqno,
|
||||
cchh_t *lower, cchh_t *upper)
|
||||
{
|
||||
cchh_t *lower, cchh_t *upper)
|
||||
{
|
||||
ext->typeind = typeind;
|
||||
ext->seqno = seqno;
|
||||
memcpy(&ext->llimit,lower,sizeof(cchh_t));
|
||||
@@ -307,7 +307,7 @@ uint32_t cchh2trk (cchh_t *p, struct hd_geometry *geo) {
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void vtoc_set_date (labeldate_t * d, uint8_t year, uint16_t day)
|
||||
void vtoc_set_date (labeldate_t * d, uint8_t year, uint16_t day)
|
||||
{
|
||||
d->year = year;
|
||||
d->day = day;
|
||||
@@ -320,7 +320,7 @@ void vtoc_set_date (labeldate_t * d, uint8_t year, uint16_t day)
|
||||
void vtoc_volume_label_init (volume_label_t *vlabel)
|
||||
{
|
||||
sprintf(buffer, "%84s", " ");
|
||||
vtoc_ebcdic_enc(buffer, buffer, 84);
|
||||
vtoc_ebcdic_enc(buffer, buffer, 84);
|
||||
memcpy(vlabel, buffer, 84);
|
||||
}
|
||||
|
||||
@@ -329,7 +329,7 @@ void vtoc_volume_label_init (volume_label_t *vlabel)
|
||||
* reads the volume label from dasd
|
||||
*/
|
||||
int vtoc_read_volume_label (char *device, unsigned long vlabel_start,
|
||||
volume_label_t *vlabel)
|
||||
volume_label_t *vlabel)
|
||||
{
|
||||
int f, rc;
|
||||
|
||||
@@ -360,7 +360,7 @@ int vtoc_read_volume_label (char *device, unsigned long vlabel_start,
|
||||
* writes the volume label to dasd
|
||||
*/
|
||||
int vtoc_write_volume_label (char *device, unsigned long vlabel_start,
|
||||
volume_label_t *vlabel)
|
||||
volume_label_t *vlabel)
|
||||
{
|
||||
int rc, f;
|
||||
|
||||
@@ -375,8 +375,8 @@ int vtoc_write_volume_label (char *device, unsigned long vlabel_start,
|
||||
"Could not write volume label.");
|
||||
}
|
||||
|
||||
rc = write(f, vlabel, sizeof(volume_label_t));
|
||||
if (rc != sizeof(volume_label_t))
|
||||
rc = write(f, vlabel, sizeof(volume_label_t));
|
||||
if (rc != sizeof(volume_label_t))
|
||||
{
|
||||
close(f);
|
||||
vtoc_error(unable_to_write, device,
|
||||
@@ -418,7 +418,7 @@ void vtoc_volume_label_set_volser (volume_label_t *vlabel, char *volser)
|
||||
|
||||
|
||||
/*
|
||||
* returns the volume serial number right after it is translated
|
||||
* returns the volume serial number right after it is translated
|
||||
* to ASCII
|
||||
*/
|
||||
char * vtoc_volume_label_get_volser (volume_label_t *vlabel, char *volser)
|
||||
@@ -436,11 +436,11 @@ char * vtoc_volume_label_get_volser (volume_label_t *vlabel, char *volser)
|
||||
void vtoc_volume_label_set_key (volume_label_t *vlabel, char *key)
|
||||
{
|
||||
char s[4];
|
||||
|
||||
|
||||
vtoc_ebcdic_enc(key, s, 4);
|
||||
strncpy(vlabel->volkey, s, 4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -475,12 +475,12 @@ char * vtoc_volume_label_get_label (volume_label_t *vlabel, char *lbl)
|
||||
*/
|
||||
void vtoc_read_label (char *device, unsigned long position,
|
||||
format1_label_t *f1, format4_label_t *f4,
|
||||
format5_label_t *f5, format7_label_t *f7)
|
||||
{
|
||||
format5_label_t *f5, format7_label_t *f7)
|
||||
{
|
||||
int f,t;
|
||||
|
||||
if ((f = open(device, O_RDONLY)) < 0)
|
||||
vtoc_error(unable_to_open, device,
|
||||
vtoc_error(unable_to_open, device,
|
||||
"Could not read VTOC labels.");
|
||||
|
||||
if (lseek(f, position, SEEK_SET) < 0) {
|
||||
@@ -536,7 +536,7 @@ void vtoc_read_label (char *device, unsigned long position,
|
||||
void
|
||||
vtoc_write_label (char *device,
|
||||
unsigned long position,
|
||||
format1_label_t *f1,
|
||||
format1_label_t *f1,
|
||||
format4_label_t *f4,
|
||||
format5_label_t *f5,
|
||||
format7_label_t *f7,
|
||||
@@ -550,7 +550,7 @@ vtoc_write_label (char *device,
|
||||
"Could not write VTOC labels.");
|
||||
}
|
||||
|
||||
if (lseek(f, position, SEEK_SET) == -1)
|
||||
if (lseek(f, position, SEEK_SET) == -1)
|
||||
{
|
||||
close(f);
|
||||
vtoc_error(unable_to_seek, device,
|
||||
@@ -560,7 +560,7 @@ vtoc_write_label (char *device,
|
||||
if (f1 != NULL)
|
||||
{
|
||||
t = sizeof(format1_label_t);
|
||||
if (write(f, f1, t) != t)
|
||||
if (write(f, f1, t) != t)
|
||||
{
|
||||
close(f);
|
||||
vtoc_error(unable_to_write, device,
|
||||
@@ -571,7 +571,7 @@ vtoc_write_label (char *device,
|
||||
if (f4 != NULL)
|
||||
{
|
||||
t = sizeof(format4_label_t);
|
||||
if (write(f, f4, t) != t)
|
||||
if (write(f, f4, t) != t)
|
||||
{
|
||||
close(f);
|
||||
vtoc_error(unable_to_write, device,
|
||||
@@ -582,7 +582,7 @@ vtoc_write_label (char *device,
|
||||
if (f5 != NULL)
|
||||
{
|
||||
t = sizeof(format5_label_t);
|
||||
if (write(f, f5, t) != t)
|
||||
if (write(f, f5, t) != t)
|
||||
{
|
||||
close(f);
|
||||
vtoc_error(unable_to_write, device,
|
||||
@@ -593,7 +593,7 @@ vtoc_write_label (char *device,
|
||||
if (f7 != NULL)
|
||||
{
|
||||
t = sizeof(format7_label_t);
|
||||
if (write(f, f7, t) != t)
|
||||
if (write(f, f7, t) != t)
|
||||
{
|
||||
close(f);
|
||||
vtoc_error(unable_to_write, device,
|
||||
@@ -619,7 +619,7 @@ vtoc_write_label (char *device,
|
||||
/*
|
||||
* initializes a format4 label
|
||||
*/
|
||||
void
|
||||
void
|
||||
vtoc_init_format4_label (
|
||||
format4_label_t *f4,
|
||||
unsigned int compat_cylinders,
|
||||
@@ -627,7 +627,7 @@ vtoc_init_format4_label (
|
||||
unsigned int tracks,
|
||||
unsigned int blocks,
|
||||
unsigned int blksize,
|
||||
uint16_t dev_type)
|
||||
uint16_t dev_type)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -701,7 +701,7 @@ vtoc_init_format4_label (
|
||||
* initializes a format5 label
|
||||
*/
|
||||
void
|
||||
vtoc_init_format5_label (format5_label_t *f5)
|
||||
vtoc_init_format5_label (format5_label_t *f5)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -715,7 +715,7 @@ vtoc_init_format5_label (format5_label_t *f5)
|
||||
* initializes a format7 label
|
||||
*/
|
||||
void
|
||||
vtoc_init_format7_label (format7_label_t *f7)
|
||||
vtoc_init_format7_label (format7_label_t *f7)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -829,11 +829,11 @@ void vtoc_init_format9_label (
|
||||
/*
|
||||
* do some updates to the VTOC format4 label
|
||||
*/
|
||||
void
|
||||
void
|
||||
vtoc_update_format4_label (
|
||||
format4_label_t *f4,
|
||||
cchhb_t *highest_f1,
|
||||
uint16_t unused_update)
|
||||
uint16_t unused_update)
|
||||
{
|
||||
/* update highest address of a format 1 label */
|
||||
memcpy(&f4->DS4HPCHR, highest_f1, sizeof(cchhb_t));
|
||||
@@ -847,15 +847,15 @@ vtoc_update_format4_label (
|
||||
* reorganizes all extents within a FMT5 label
|
||||
*/
|
||||
static void
|
||||
vtoc_reorganize_FMT5_extents (format5_label_t *f5)
|
||||
vtoc_reorganize_FMT5_extents (format5_label_t *f5)
|
||||
{
|
||||
ds5ext_t *ext, *last, tmp;
|
||||
int i, j;
|
||||
|
||||
for (i=0; i<26; i++)
|
||||
{
|
||||
if (i==0)
|
||||
last = &f5->DS5AVEXT;
|
||||
if (i==0)
|
||||
last = &f5->DS5AVEXT;
|
||||
else if ((i > 0) && (i < 8))
|
||||
last = &f5->DS5EXTAV[i-1];
|
||||
else
|
||||
@@ -863,14 +863,14 @@ vtoc_reorganize_FMT5_extents (format5_label_t *f5)
|
||||
|
||||
for (j=i; j<26; j++)
|
||||
{
|
||||
if (j==0)
|
||||
ext = &f5->DS5AVEXT;
|
||||
if (j==0)
|
||||
ext = &f5->DS5AVEXT;
|
||||
else if ((j > 0) && (j < 8))
|
||||
ext = &f5->DS5EXTAV[j-1];
|
||||
else
|
||||
ext = &f5->DS5MAVET[j-8];
|
||||
|
||||
if (((ext->t > 0) && (last->t == 0)) ||
|
||||
if (((ext->t > 0) && (last->t == 0)) ||
|
||||
((ext->t > 0) && (ext->t < last->t)))
|
||||
{
|
||||
tmp.t = last->t;
|
||||
@@ -891,27 +891,27 @@ vtoc_reorganize_FMT5_extents (format5_label_t *f5)
|
||||
/*
|
||||
* add a free space extent description to the VTOC FMT5 DSCB
|
||||
*/
|
||||
void
|
||||
void
|
||||
vtoc_update_format5_label_add (format5_label_t *f5,
|
||||
int verbose,
|
||||
int trk,
|
||||
uint16_t a,
|
||||
uint16_t b,
|
||||
uint8_t c)
|
||||
uint16_t a,
|
||||
uint16_t b,
|
||||
uint8_t c)
|
||||
{
|
||||
ds5ext_t *ext = NULL, *tmp = NULL;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
for (i=0; i<26; i++)
|
||||
{
|
||||
if (i==0)
|
||||
ext = &f5->DS5AVEXT;
|
||||
if (i==0)
|
||||
ext = &f5->DS5AVEXT;
|
||||
else if ((i > 0) && (i < 8))
|
||||
ext = &f5->DS5EXTAV[i-1];
|
||||
else
|
||||
ext = &f5->DS5MAVET[i-8];
|
||||
|
||||
if (((a < ext->t) && (a + b*trk + c > ext->t)) ||
|
||||
if (((a < ext->t) && (a + b*trk + c > ext->t)) ||
|
||||
((a > ext->t) && (ext->t + ext->fc*trk + ext->ft > a)))
|
||||
{
|
||||
printf("BUG: overlapping free space extents " \
|
||||
@@ -925,7 +925,7 @@ vtoc_update_format5_label_add (format5_label_t *f5,
|
||||
ext->fc = b;
|
||||
ext->ft = c;
|
||||
tmp = ext;
|
||||
if (verbose)
|
||||
if (verbose)
|
||||
printf("FMT5 add extent: " \
|
||||
"add new extent\n");
|
||||
break;
|
||||
@@ -958,12 +958,12 @@ vtoc_update_format5_label_add (format5_label_t *f5,
|
||||
ext->ft = (tmp->ft + ext->ft) % trk;
|
||||
memset(tmp, 0, sizeof(ds5ext_t));
|
||||
tmp = ext;
|
||||
if (verbose)
|
||||
if (verbose)
|
||||
printf("FMT5 add extent: " \
|
||||
"merge with predecessor\n");
|
||||
i = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((tmp->t + tmp->fc*trk + tmp->ft) == ext->t)
|
||||
{
|
||||
@@ -973,12 +973,12 @@ vtoc_update_format5_label_add (format5_label_t *f5,
|
||||
ext->ft = (tmp->ft + ext->ft) % trk;
|
||||
memset(tmp, 0, sizeof(ds5ext_t));
|
||||
tmp = ext;
|
||||
if (verbose)
|
||||
if (verbose)
|
||||
printf("FMT5 add extent: " \
|
||||
"merge with successor\n");
|
||||
i = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -986,21 +986,21 @@ vtoc_update_format5_label_add (format5_label_t *f5,
|
||||
/*
|
||||
* remove a free space extent description from the VTOC FMT5 DSCB
|
||||
*/
|
||||
void
|
||||
void
|
||||
vtoc_update_format5_label_del (format5_label_t *f5,
|
||||
int verbose,
|
||||
int trk,
|
||||
uint16_t a,
|
||||
uint16_t b,
|
||||
uint8_t c)
|
||||
uint8_t c)
|
||||
{
|
||||
ds5ext_t *ext;
|
||||
int i, counter=0;
|
||||
|
||||
|
||||
for (i=0; i<26; i++)
|
||||
{
|
||||
if (i==0)
|
||||
ext = &f5->DS5AVEXT;
|
||||
if (i==0)
|
||||
ext = &f5->DS5AVEXT;
|
||||
else if ((i > 0) && (i < 8))
|
||||
ext = &f5->DS5EXTAV[i-1];
|
||||
else
|
||||
@@ -1010,7 +1010,7 @@ vtoc_update_format5_label_del (format5_label_t *f5,
|
||||
{
|
||||
/* fills up whole free space gap */
|
||||
memset(ext, 0, sizeof(ds5ext_t));
|
||||
if (verbose)
|
||||
if (verbose)
|
||||
printf("FMT5 del extent: fills whole gap\n");
|
||||
counter++;
|
||||
break;
|
||||
@@ -1030,13 +1030,13 @@ vtoc_update_format5_label_del (format5_label_t *f5,
|
||||
ext->fc -= b;
|
||||
ext->ft -= c;
|
||||
}
|
||||
if (verbose)
|
||||
if (verbose)
|
||||
printf("FMT5 del extent: left bounded\n");
|
||||
counter++;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((ext->t < a) &&
|
||||
if ((ext->t < a) &&
|
||||
((ext->t + ext->fc*trk + ext->ft) == (a + b*trk + c)))
|
||||
{
|
||||
/* right-bounded in free space gap */
|
||||
@@ -1050,7 +1050,7 @@ vtoc_update_format5_label_del (format5_label_t *f5,
|
||||
ext->fc -= b;
|
||||
ext->ft -= c;
|
||||
}
|
||||
if (verbose)
|
||||
if (verbose)
|
||||
printf("FMT5 del extent: right bounded\n");
|
||||
counter++;
|
||||
break;
|
||||
@@ -1074,7 +1074,7 @@ vtoc_update_format5_label_del (format5_label_t *f5,
|
||||
vtoc_update_format5_label_add(f5, verbose,
|
||||
trk, x, y, z);
|
||||
|
||||
if (verbose)
|
||||
if (verbose)
|
||||
printf("FMT5 del extent: 2 pieces\n");
|
||||
counter++;
|
||||
break;
|
||||
@@ -1088,8 +1088,8 @@ vtoc_update_format5_label_del (format5_label_t *f5,
|
||||
"in FMT5 DSCB!\nexiting...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((a > ext->t) && (a < ext->t + ext->fc*trk + ext->ft) &&
|
||||
|
||||
if ((a > ext->t) && (a < ext->t + ext->fc*trk + ext->ft) &&
|
||||
(a + b*trk + c > ext->t + ext->fc*trk + ext->ft))
|
||||
{
|
||||
printf("BUG: specified free space extent for " \
|
||||
@@ -1113,26 +1113,26 @@ vtoc_update_format5_label_del (format5_label_t *f5,
|
||||
* reorganizes all extents within a FMT7 label
|
||||
*/
|
||||
static void
|
||||
vtoc_reorganize_FMT7_extents (format7_label_t *f7)
|
||||
vtoc_reorganize_FMT7_extents (format7_label_t *f7)
|
||||
{
|
||||
ds7ext_t *ext, *last, tmp;
|
||||
int i, j;
|
||||
|
||||
for (i=0; i<16; i++)
|
||||
{
|
||||
if (i<5)
|
||||
last = &f7->DS7EXTNT[i];
|
||||
else
|
||||
if (i<5)
|
||||
last = &f7->DS7EXTNT[i];
|
||||
else
|
||||
last = &f7->DS7ADEXT[i-5];
|
||||
|
||||
for (j=i; j<16; j++)
|
||||
{
|
||||
if (j<5)
|
||||
ext = &f7->DS7EXTNT[j];
|
||||
else
|
||||
if (j<5)
|
||||
ext = &f7->DS7EXTNT[j];
|
||||
else
|
||||
ext = &f7->DS7ADEXT[j-5];
|
||||
|
||||
if (((ext->a > 0) && (last->a == 0)) ||
|
||||
if (((ext->a > 0) && (last->a == 0)) ||
|
||||
((ext->a > 0) && (ext->a < last->a)))
|
||||
{
|
||||
tmp.a = last->a;
|
||||
@@ -1150,19 +1150,19 @@ vtoc_reorganize_FMT7_extents (format7_label_t *f7)
|
||||
/*
|
||||
* add a free space extent description to the VTOC FMT7 DSCB
|
||||
*/
|
||||
void vtoc_update_format7_label_add (format7_label_t *f7, int verbose,
|
||||
uint32_t a, uint32_t b)
|
||||
void vtoc_update_format7_label_add (format7_label_t *f7, int verbose,
|
||||
uint32_t a, uint32_t b)
|
||||
{
|
||||
ds7ext_t *ext = NULL, *tmp = NULL;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
for (i=0; i<16; i++) {
|
||||
if (i<5)
|
||||
ext = &f7->DS7EXTNT[i];
|
||||
else
|
||||
if (i<5)
|
||||
ext = &f7->DS7EXTNT[i];
|
||||
else
|
||||
ext = &f7->DS7ADEXT[i-5];
|
||||
|
||||
if (((a < ext->a) && (b > ext->a) && (b < ext->b)) ||
|
||||
if (((a < ext->a) && (b > ext->a) && (b < ext->b)) ||
|
||||
((a > ext->a) && (a < ext->b) && (b > ext->b))) {
|
||||
printf("BUG: overlapping free space extents "
|
||||
"in FMT7 DSCB!\nexiting...\n");
|
||||
@@ -1173,7 +1173,7 @@ void vtoc_update_format7_label_add (format7_label_t *f7, int verbose,
|
||||
ext->a = a;
|
||||
ext->b = b;
|
||||
tmp = ext;
|
||||
if (verbose)
|
||||
if (verbose)
|
||||
printf("FMT7 add extent: add new extent\n");
|
||||
break;
|
||||
}
|
||||
@@ -1185,9 +1185,9 @@ void vtoc_update_format7_label_add (format7_label_t *f7, int verbose,
|
||||
}
|
||||
|
||||
for (i=0; i<16; i++) {
|
||||
if (i<5)
|
||||
ext = &f7->DS7EXTNT[i];
|
||||
else
|
||||
if (i<5)
|
||||
ext = &f7->DS7EXTNT[i];
|
||||
else
|
||||
ext = &f7->DS7ADEXT[i-5];
|
||||
|
||||
if ((ext->a + ext->b) == 0x00000000)
|
||||
@@ -1198,12 +1198,12 @@ void vtoc_update_format7_label_add (format7_label_t *f7, int verbose,
|
||||
ext->b = tmp->b;
|
||||
memset(tmp, 0, sizeof(ds7ext_t));
|
||||
tmp = ext;
|
||||
if (verbose)
|
||||
if (verbose)
|
||||
printf("FMT7 add extent: " \
|
||||
"merge with predecessor\n");
|
||||
i = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (ext->a == (tmp->b))
|
||||
{
|
||||
@@ -1211,12 +1211,12 @@ void vtoc_update_format7_label_add (format7_label_t *f7, int verbose,
|
||||
ext->a = tmp->a;
|
||||
memset(tmp, 0, sizeof(ds7ext_t));
|
||||
tmp = ext;
|
||||
if (verbose)
|
||||
if (verbose)
|
||||
printf("FMT7 add extent: " \
|
||||
"merge with successor\n");
|
||||
i = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1224,22 +1224,22 @@ void vtoc_update_format7_label_add (format7_label_t *f7, int verbose,
|
||||
/*
|
||||
* remove a free space extent description from the VTOC FMT7 DSCB
|
||||
*/
|
||||
void vtoc_update_format7_label_del (format7_label_t *f7, int verbose,
|
||||
uint32_t a, uint32_t b)
|
||||
void vtoc_update_format7_label_del (format7_label_t *f7, int verbose,
|
||||
uint32_t a, uint32_t b)
|
||||
{
|
||||
ds7ext_t *ext;
|
||||
int i, counter=0;
|
||||
|
||||
for (i=0; i<16; i++) {
|
||||
if (i<5)
|
||||
ext = &f7->DS7EXTNT[i];
|
||||
else
|
||||
if (i<5)
|
||||
ext = &f7->DS7EXTNT[i];
|
||||
else
|
||||
ext = &f7->DS7ADEXT[i-5];
|
||||
|
||||
if ((a == ext->a) && (b == ext->b)) {
|
||||
/* fills up whole free space gap */
|
||||
memset(ext, 0, sizeof(ds7ext_t));
|
||||
if (verbose)
|
||||
if (verbose)
|
||||
printf("FMT7 del extent: fills whole gap\n");
|
||||
counter++;
|
||||
break;
|
||||
@@ -1248,7 +1248,7 @@ void vtoc_update_format7_label_del (format7_label_t *f7, int verbose,
|
||||
if ((a == ext->a) && (b < ext->b)) {
|
||||
/* left-bounded in free space gap */
|
||||
ext->a = b;
|
||||
if (verbose)
|
||||
if (verbose)
|
||||
printf("FMT7 add extent: left-bounded\n");
|
||||
counter++;
|
||||
break;
|
||||
@@ -1257,7 +1257,7 @@ void vtoc_update_format7_label_del (format7_label_t *f7, int verbose,
|
||||
if ((a > ext->a) && (b == ext->b)) {
|
||||
/* right-bounded in free space gap */
|
||||
ext->b = a;
|
||||
if (verbose)
|
||||
if (verbose)
|
||||
printf("FMT7 add extent: right-bounded\n");
|
||||
counter++;
|
||||
break;
|
||||
@@ -1265,16 +1265,16 @@ void vtoc_update_format7_label_del (format7_label_t *f7, int verbose,
|
||||
|
||||
if ((a > ext->a) && (b < ext->b)) {
|
||||
/* partition divides free space into 2 pieces */
|
||||
vtoc_update_format7_label_add(f7, verbose,
|
||||
vtoc_update_format7_label_add(f7, verbose,
|
||||
b, ext->b);
|
||||
ext->b = a;
|
||||
if (verbose)
|
||||
if (verbose)
|
||||
printf("FMT7 add extent: 2 pieces\n");
|
||||
counter++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (((a < ext->a) && (b > ext->a)) ||
|
||||
if (((a < ext->a) && (b > ext->a)) ||
|
||||
((a < ext->b) && (b > ext->b))) {
|
||||
printf("BUG: specified free space extent for deleting "
|
||||
"doesn't match free space currently shown in "
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
include ../common.mak
|
||||
|
||||
zsh-completions = _lsstp
|
||||
bash-completions = lsstp.bash
|
||||
|
||||
include ../common_autocomp.mak
|
||||
|
||||
libs = $(rootdir)/libutil/libutil.a
|
||||
all: lsstp
|
||||
|
||||
|
||||
16
lsstp/autocompletion_generator_host.c
Normal file
16
lsstp/autocompletion_generator_host.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#include "lib/util_autocomp.h"
|
||||
|
||||
#include "lsstp_cli.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
generate_autocomp(opt_vec, "lsstp");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "lib/util_prg.h"
|
||||
#include "lib/util_path.h"
|
||||
|
||||
#include "lsstp_cli.h"
|
||||
|
||||
static const struct util_prg prg = {
|
||||
.desc = "Display STP system information",
|
||||
.args = "",
|
||||
@@ -34,12 +36,6 @@ static const struct util_prg prg = {
|
||||
}
|
||||
};
|
||||
|
||||
static struct util_opt opt_vec[] = {
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
struct stp_parms {
|
||||
uint64_t ctn_id;
|
||||
unsigned int online;
|
||||
|
||||
18
lsstp/lsstp_cli.h
Normal file
18
lsstp/lsstp_cli.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#ifndef LSSTP_CLI_H
|
||||
#define LSSTP_CLI_H
|
||||
|
||||
#include "lib/util_opt.h"
|
||||
|
||||
static struct util_opt opt_vec[] = {
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -2,6 +2,11 @@ include ../common.mak
|
||||
|
||||
TESTS := tests/
|
||||
|
||||
zsh-completions = _opticsmon
|
||||
bash-completions = opticsmon.bash
|
||||
|
||||
include ../common_autocomp.mak
|
||||
|
||||
libs =$(rootdir)/libzpci/libzpci.a $(rootdir)/libutil/libutil.a
|
||||
|
||||
ifneq (${HAVE_OPENSSL},0)
|
||||
|
||||
16
opticsmon/autocompletion_generator_host.c
Normal file
16
opticsmon/autocompletion_generator_host.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#include "lib/util_autocomp.h"
|
||||
|
||||
#include "opticsmon_cli.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
generate_autocomp(opt_vec, "opticsmon");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -45,7 +45,7 @@ opticsmon - Monitor optical modules for directly attached PCI based NICs
|
||||
Use
|
||||
.B opticsmon
|
||||
to monitor the health of the optical modules of directly attached PCI based
|
||||
NICs. When executed without the \fB--daemon\fR option it will collect optical
|
||||
NICs. When executed without the \fB--monitor\fR option it will collect optical
|
||||
module data from all available PCI network interface physical functions and
|
||||
print a summary in JSON format. Add the \fB--send-report\fR option to report
|
||||
this data to the support element.
|
||||
@@ -55,7 +55,7 @@ this data to the support element.
|
||||
.
|
||||
.SH OPTIONS
|
||||
.SS Operation Options
|
||||
.OD daemon "d"
|
||||
.OD monitor "m"
|
||||
Run continuously and report on link state changes and periodically
|
||||
.PP
|
||||
.
|
||||
|
||||
@@ -27,10 +27,11 @@
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include "optics_info.h"
|
||||
#include "optics_sclp.h"
|
||||
#include "ethtool.h"
|
||||
#include "link_mon.h"
|
||||
#include "optics_info.h"
|
||||
#include "optics_sclp.h"
|
||||
#include "opticsmon_cli.h"
|
||||
|
||||
#define API_LEVEL 1
|
||||
|
||||
@@ -61,44 +62,6 @@ static const struct util_prg prg = {
|
||||
UTIL_PRG_COPYRIGHT_END }
|
||||
};
|
||||
|
||||
#define OPT_DUMP 128
|
||||
|
||||
static struct util_opt opt_vec[] = {
|
||||
UTIL_OPT_SECTION("OPERATION OPTIONS"),
|
||||
{
|
||||
.option = { "monitor", no_argument, NULL, 'm' },
|
||||
.desc = "Run continuously and report on link state changes "
|
||||
"collecting optics health data when a change is detected",
|
||||
},
|
||||
{
|
||||
.option = { "send-report", no_argument, NULL, 'r' },
|
||||
.desc = "Report the optics health data to the Support Element",
|
||||
},
|
||||
{
|
||||
.option = { "quiet", no_argument, NULL, 'q' },
|
||||
.desc = "Be quiet and don't print optics health summary",
|
||||
},
|
||||
{
|
||||
.option = { "module-info", no_argument, NULL, OPT_DUMP },
|
||||
.desc = "Include a base64 encoded binary dump of the module's "
|
||||
"SFF-8636/8472/8024 standard data for each netdev. "
|
||||
"This matches \"ethtool --module-info <netdev> raw on\"",
|
||||
.flags = UTIL_OPT_FLAG_NOSHORT,
|
||||
},
|
||||
UTIL_OPT_SECTION("OPTIONS WITH ARGUMENTS"),
|
||||
{
|
||||
.option = { "interval", required_argument, NULL, 'i' },
|
||||
.argument = "seconds",
|
||||
.desc = "Interval in seconds at which to collect monitoring data "
|
||||
"in the absence of link state changes. A value larger than "
|
||||
"24 hours (86400 seconds) is clamped down to 24 hours.",
|
||||
},
|
||||
UTIL_OPT_SECTION("GENERAL OPTIONS"),
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
static void parse_cmdline(int argc, char *argv[], struct options *opts)
|
||||
{
|
||||
uint32_t seconds;
|
||||
|
||||
50
opticsmon/opticsmon_cli.h
Normal file
50
opticsmon/opticsmon_cli.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright IBM Corp.
|
||||
*/
|
||||
|
||||
#ifndef OPTICSMON_CLI_H
|
||||
#define OPTICSMON_CLI_H
|
||||
|
||||
#include "lib/util_opt.h"
|
||||
|
||||
#define OPT_DUMP 128
|
||||
|
||||
static struct util_opt opt_vec[] = {
|
||||
UTIL_OPT_SECTION("OPERATION OPTIONS"),
|
||||
{
|
||||
.option = { "monitor", no_argument, NULL, 'm' },
|
||||
.desc = "Run continuously and report on link state changes "
|
||||
"collecting optics health data when a change is detected",
|
||||
},
|
||||
{
|
||||
.option = { "send-report", no_argument, NULL, 'r' },
|
||||
.desc = "Report the optics health data to the Support Element",
|
||||
},
|
||||
{
|
||||
.option = { "quiet", no_argument, NULL, 'q' },
|
||||
.desc = "Be quiet and don't print optics health summary",
|
||||
},
|
||||
{
|
||||
.option = { "module-info", no_argument, NULL, OPT_DUMP },
|
||||
.desc = "Include a base64 encoded binary dump of the module's "
|
||||
"SFF-8636/8472/8024 standard data for each netdev. "
|
||||
"This matches 'ethtool --module-info <netdev> raw on'",
|
||||
.flags = UTIL_OPT_FLAG_NOSHORT,
|
||||
},
|
||||
UTIL_OPT_SECTION("OPTIONS WITH ARGUMENTS"),
|
||||
{
|
||||
.option = { "interval", required_argument, NULL, 'i' },
|
||||
.argument = "seconds",
|
||||
.desc = "Interval in seconds at which to collect monitoring data "
|
||||
"in the absence of link state changes. A value larger than "
|
||||
"24 hours (86400 seconds) is clamped down to 24 hours.",
|
||||
},
|
||||
UTIL_OPT_SECTION("GENERAL OPTIONS"),
|
||||
UTIL_OPT_HELP,
|
||||
UTIL_OPT_VERSION,
|
||||
UTIL_OPT_END
|
||||
};
|
||||
|
||||
#endif
|
||||
149
rust/Cargo.lock
generated
149
rust/Cargo.lock
generated
@@ -62,9 +62,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.95"
|
||||
version = "1.0.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
|
||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
@@ -111,6 +111,15 @@ dependencies = [
|
||||
"wyz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
@@ -132,6 +141,15 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.23"
|
||||
@@ -203,6 +221,25 @@ dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curl"
|
||||
version = "0.4.49"
|
||||
@@ -293,6 +330,16 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum_dispatch"
|
||||
version = "0.3.13"
|
||||
@@ -354,6 +401,16 @@ version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.16"
|
||||
@@ -395,6 +452,12 @@ version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
@@ -632,11 +695,26 @@ dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pvebc"
|
||||
version = "0.12.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"hex",
|
||||
"s390_pv_core",
|
||||
"sha2",
|
||||
"utils",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pvimg"
|
||||
version = "0.12.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"deku",
|
||||
@@ -677,6 +755,7 @@ dependencies = [
|
||||
"s390_pv",
|
||||
"serde_yaml",
|
||||
"utils",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -881,6 +960,7 @@ dependencies = [
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_test",
|
||||
"sha2",
|
||||
"thiserror",
|
||||
"zerocopy",
|
||||
]
|
||||
@@ -896,18 +976,28 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.217"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.217"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -916,13 +1006,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.99"
|
||||
version = "1.0.149"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3"
|
||||
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"memchr",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"zmij",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -947,6 +1039,17 @@ dependencies = [
|
||||
"unsafe-libyaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
@@ -1047,6 +1150,12 @@ dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
|
||||
|
||||
[[package]]
|
||||
name = "unarray"
|
||||
version = "0.1.4"
|
||||
@@ -1075,11 +1184,13 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
name = "utils"
|
||||
version = "0.12.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clap",
|
||||
"libc",
|
||||
"log",
|
||||
"s390_pv",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1088,6 +1199,12 @@ version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "wait-timeout"
|
||||
version = "0.2.0"
|
||||
@@ -1214,20 +1331,26 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.25"
|
||||
version = "0.8.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
|
||||
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.25"
|
||||
version = "0.8.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
|
||||
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
||||
|
||||
@@ -5,6 +5,7 @@ members = [
|
||||
"pv_core",
|
||||
"pvapconfig",
|
||||
"pvattest",
|
||||
"pvebc",
|
||||
"pvimg",
|
||||
"pvinfo",
|
||||
"pvsecret",
|
||||
|
||||
@@ -10,8 +10,10 @@ CARGO_TARGETS :=
|
||||
PV_TARGETS :=
|
||||
CARGO_TEST_TARGETS :=
|
||||
|
||||
SEL_EBC_MODDIR := 95sel-ebc
|
||||
|
||||
ifneq (${HAVE_CARGO},0)
|
||||
CARGO_TARGETS :=
|
||||
CARGO_TARGETS := pvebc
|
||||
|
||||
BUILD_TARGETS = $(CARGO_TARGETS)
|
||||
INSTALL_TARGETS := install-rust-tools install-man install-shell-completions
|
||||
@@ -29,6 +31,7 @@ ifneq (${HAVE_LIBCURL},0)
|
||||
|
||||
ifeq ($(HOST_ARCH),s390x)
|
||||
PV_TARGETS += pvapconfig pvinfo
|
||||
INSTALL_TARGETS += install-ebc-dracut-module
|
||||
else
|
||||
BUILD_TARGETS += skip-pvapconfig skip-pvinfo
|
||||
endif #HOSTARCH
|
||||
@@ -104,6 +107,23 @@ endif # CARGO
|
||||
|
||||
rust-test: $(CARGO_TEST_TARGETS)
|
||||
|
||||
install-ebc-dracut-module:
|
||||
ifneq ($(HAVE_DRACUT),0)
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(DRACUTMODDIR)/
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(DRACUTMODDIR)/$(SEL_EBC_MODDIR)
|
||||
$(INSTALL) -m 755 pvebc/$(SEL_EBC_MODDIR)/module-setup.sh \
|
||||
pvebc/$(SEL_EBC_MODDIR)/override-crypttab.sh \
|
||||
pvebc/$(SEL_EBC_MODDIR)/pvebc-wrapper.sh \
|
||||
$(DESTDIR)$(DRACUTMODDIR)/$(SEL_EBC_MODDIR)
|
||||
$(INSTALL) -m 644 pvebc/$(SEL_EBC_MODDIR)/boot.mount \
|
||||
pvebc/$(SEL_EBC_MODDIR)/sel-ebc-override-crypttab.service \
|
||||
pvebc/$(SEL_EBC_MODDIR)/sel-ebc-paes-enforce.service \
|
||||
pvebc/$(SEL_EBC_MODDIR)/sel-ebc-pvebc.service \
|
||||
pvebc/$(SEL_EBC_MODDIR)/sel-ebc.crypttab \
|
||||
pvebc/$(SEL_EBC_MODDIR)/sel-ebc.target \
|
||||
$(DESTDIR)$(DRACUTMODDIR)/$(SEL_EBC_MODDIR)
|
||||
endif
|
||||
|
||||
install-rust-tools: $(BUILD_TARGETS)
|
||||
$(INSTALL) -d -m 755 $(DESTDIR)$(USRBINDIR)
|
||||
$(foreach target,$(CARGO_TARGETS),\
|
||||
|
||||
@@ -104,7 +104,14 @@ pub mod request {
|
||||
|
||||
/// Reexports some useful OpenSSL symbols
|
||||
pub mod openssl {
|
||||
pub use openssl::{error::ErrorStack, hash::DigestBytes, nid::Nid, pkey, x509};
|
||||
pub use openssl::{
|
||||
error::ErrorStack,
|
||||
hash::DigestBytes,
|
||||
nid::Nid,
|
||||
pkey,
|
||||
sha::{Sha256, Sha512},
|
||||
x509,
|
||||
};
|
||||
// rust-OpenSSL does not define these NIDs
|
||||
#[allow(missing_docs)]
|
||||
pub const NID_ED25519: Nid = Nid::from_raw(openssl_sys::NID_ED25519);
|
||||
@@ -113,6 +120,8 @@ pub mod request {
|
||||
}
|
||||
|
||||
pub use pv_core::request::*;
|
||||
|
||||
pub use pv_core::PolicyReference;
|
||||
}
|
||||
|
||||
/// Functionalities for creating add-secret requests
|
||||
|
||||
@@ -53,14 +53,14 @@ pub enum GuestSecret {
|
||||
},
|
||||
/// Retrievable key
|
||||
///
|
||||
/// Create Retrievables using [`GuestSecret::retrievable`]
|
||||
/// Create Retrievables using [`GuestSecret::Retrievable`]
|
||||
/// Secret size is always valid for the type/kind
|
||||
Retrievable {
|
||||
/// Retrievable secret type
|
||||
kind: RetrievableSecret,
|
||||
/// Name of the secret
|
||||
name: String,
|
||||
/// SHA256 hash of [`GuestSecret::RetrievableKey::name`]
|
||||
/// SHA256 hash of [`GuestSecret::Retrievable::name`]
|
||||
id: SecretId,
|
||||
/// Confidential actual retrievable secret
|
||||
#[serde(skip)]
|
||||
|
||||
@@ -248,7 +248,7 @@ fn check_key_format(kind: UserDataType, key: &PKeyRef<Public>) -> Result<()> {
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Extracrted user-data if available
|
||||
/// Extracted user-data if available
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
|
||||
@@ -23,6 +23,7 @@ zerocopy = {version = "0.8", features = ["derive"]}
|
||||
serde = { version = "1.0.217", features = ["derive"]}
|
||||
byteorder = "1.5"
|
||||
regex = "1.10"
|
||||
sha2 = "0.10.9"
|
||||
|
||||
[dev-dependencies]
|
||||
serde_test = "1.0.177"
|
||||
|
||||
@@ -6,6 +6,7 @@ mod apdevice;
|
||||
mod confidential;
|
||||
mod error;
|
||||
mod macros;
|
||||
mod policy;
|
||||
mod utils;
|
||||
mod uvattest;
|
||||
mod uvdevice;
|
||||
@@ -13,6 +14,13 @@ mod uvsecret;
|
||||
|
||||
pub use error::{Error, FileAccessErrorType, FileIoErrorType, Result};
|
||||
|
||||
/// Early Boot Customization (EBC) utilities.
|
||||
///
|
||||
/// This module provides types and functions for working with Early Boot
|
||||
/// Customization. The integrity and completeness of ASRs are ensured through
|
||||
/// cryptographically protected table of contents files.
|
||||
pub use policy::PolicyReference;
|
||||
|
||||
/// Functionalities for reading attestation requests
|
||||
pub mod attest {
|
||||
pub use crate::uvattest::{AttestationMagic, AttestationMeasAlg};
|
||||
|
||||
112
rust/pv_core/src/policy.rs
Normal file
112
rust/pv_core/src/policy.rs
Normal file
@@ -0,0 +1,112 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright IBM Corp.
|
||||
|
||||
use crate::misc::encode_hex;
|
||||
use crate::utils::open_file;
|
||||
use crate::{Error, Result};
|
||||
use std::{
|
||||
fmt::{Display, Formatter, Result as Resfmt},
|
||||
fs::File,
|
||||
os::unix::ffi::OsStrExt,
|
||||
path::{Path, PathBuf},
|
||||
str::from_utf8,
|
||||
};
|
||||
use zerocopy::{FromBytes, Immutable, IntoBytes};
|
||||
|
||||
const HASH_LEN: usize = 32;
|
||||
// UserDataType::Unsigned.max() returns 512
|
||||
const USER_DATA_MAX_SIZE: usize = 512;
|
||||
|
||||
/// A reference to a policy file containing its SHA-256 hash and file path.
|
||||
///
|
||||
/// This structure is used in Early Boot Customization (EBC) to store
|
||||
/// a reference to a policy file. It contains the SHA-256 hash of the policy
|
||||
/// file content and the file path as a fixed-size byte array.
|
||||
///
|
||||
/// The total size is constrained by `USER_DATA_MAX_SIZE` (512 bytes), with
|
||||
/// 32 bytes allocated for the hash and the remaining bytes for the file path.
|
||||
#[derive(Debug, FromBytes, IntoBytes, Immutable, Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct PolicyReference {
|
||||
/// SHA-256 hash of the policy file content (32 bytes)
|
||||
pub hash: [u8; HASH_LEN],
|
||||
/// File path stored as a null-terminated byte array
|
||||
pub name: [u8; USER_DATA_MAX_SIZE - HASH_LEN],
|
||||
}
|
||||
|
||||
impl PolicyReference {
|
||||
/// Creates a new `PolicyReference` from a file path.
|
||||
///
|
||||
/// Opens the file, reads its content, and computes the SHA-256 hash.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// * `src` - The path to the policy file
|
||||
/// * `sha256` - A function that computes the SHA-256 hash of the content
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns a `PolicyReference` containing the SHA-256 hash and the file path,
|
||||
/// or an error if the file cannot be opened or the hash computation fails.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// The file path is truncated if it exceeds the available space in the `name` field.
|
||||
pub fn new<P, H>(src: P, sha256: H) -> Result<Self>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
H: Fn(File) -> Result<Vec<u8>>,
|
||||
{
|
||||
let mut ret = Self {
|
||||
hash: [0; HASH_LEN],
|
||||
name: [0; USER_DATA_MAX_SIZE - HASH_LEN],
|
||||
};
|
||||
|
||||
let file = open_file(src.as_ref())?;
|
||||
ret.hash.copy_from_slice(sha256(file)?.as_bytes());
|
||||
let strbytes = src.as_ref().as_os_str().as_bytes();
|
||||
let nbytes = strbytes.len().min(ret.name.len());
|
||||
ret.name[..nbytes].copy_from_slice(&strbytes[..nbytes]);
|
||||
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
/// Converts the stored file path back to a `PathBuf`.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns the file path as a `PathBuf`, or an error if the stored name
|
||||
/// is not valid UTF-8.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// * `Error::ParseError` - If the name contains invalid UTF-8
|
||||
pub fn to_path(&self) -> Result<PathBuf> {
|
||||
// Extract bytes until the first null byte (null-terminated string)
|
||||
let name_bytes: Vec<u8> = self
|
||||
.name
|
||||
.iter()
|
||||
.copied()
|
||||
.take_while(|&byte| byte != 0)
|
||||
.collect();
|
||||
|
||||
let rust_string = String::from_utf8(name_bytes).map_err(|e| Error::ParseError {
|
||||
subject: "PolicyReference name".to_string(),
|
||||
content: format!("Invalid UTF-8 in name: {}", e),
|
||||
})?;
|
||||
|
||||
Ok(Path::new(&rust_string).to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for PolicyReference {
|
||||
fn fmt(&self, f: &mut Formatter) -> Resfmt {
|
||||
write!(
|
||||
f,
|
||||
"{} {}",
|
||||
encode_hex(self.hash),
|
||||
from_utf8(&self.name).expect("unable to convert name")
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--
|
||||
Copyright 2024 IBM Corp.
|
||||
Copyright 2024, 2026 IBM Corp.
|
||||
s390-tools is free software; you can redistribute it and/or modify
|
||||
it under the terms of the MIT license. See LICENSE for details.
|
||||
-->
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\"
|
||||
|
||||
.TH "PVATTEST-CREATE" "1" "2025-03-12" "s390-tools" "Attestation Manual"
|
||||
.TH "PVATTEST-CREATE" "1" "2026-02-12" "s390-tools" "Attestation Manual"
|
||||
.nh
|
||||
.ad l
|
||||
.SH NAME
|
||||
@@ -11,7 +11,7 @@ pvattest-create \- Create an attestation measurement request
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.fam C
|
||||
pvattest create [OPTIONS] --host-key-document <FILE> --output <FILE> --arpk <FILE> <--no-verify|--cert <FILE>>
|
||||
pvattest create [OPTIONS] \-\-host\-key\-document <FILE> \-\-output <FILE> \-\-arpk <FILE> <\-\-no\-verify|\-\-cert <FILE>>
|
||||
.fam C
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
@@ -107,15 +107,15 @@ Print help (see a summary with \fB\-h\fR).
|
||||
.RE
|
||||
|
||||
.SH EXAMPLES
|
||||
Create an attestation request with the protection key 'arp.key', write the request to 'arcb.bin', and verify the host-key document using the CA-signed key 'DigiCertCA.crt' and the intermediate key 'IbmSigningKey.crt'.
|
||||
Create an attestation request with the protection key 'arp.key', write the request to 'arcb.bin', and verify the host\-key document using the CA\-signed key 'DigiCertCA.crt' and the intermediate key 'IbmSigningKey.crt'.
|
||||
.PP
|
||||
.nf
|
||||
.fam C
|
||||
$ pvattest create \-k hkd.crt -\-\arpk arp.key \-o attreq.bin \-\-cert DigiCertCA.crt \-\-cert IbmSigningKey.crt
|
||||
$ pvattest create \-k hkd.crt \-\-\arpk arp.key \-o attreq.bin \-\-cert DigiCertCA.crt \-\-cert IbmSigningKey.crt
|
||||
|
||||
.fam T
|
||||
.fi
|
||||
Create an attestation request with the protection key 'arp.key', write the request to 'arcb.bin', verify the host-key document using the CA-signed key 'DigiCertCA.crt' and the intermediate key 'IbmSigningKey.crt', and instead of downloading the certificate revocation list use certificate revocation lists 'DigiCertCA.crl', 'IbmSigningKey.crl', and 'rootCA.crl'.
|
||||
Create an attestation request with the protection key 'arp.key', write the request to 'arcb.bin', verify the host\-key document using the CA\-signed key 'DigiCertCA.crt' and the intermediate key 'IbmSigningKey.crt', and instead of downloading the certificate revocation list use certificate revocation lists 'DigiCertCA.crl', 'IbmSigningKey.crl', and 'rootCA.crl'.
|
||||
.PP
|
||||
.nf
|
||||
.fam C
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\"
|
||||
|
||||
.TH "PVATTEST-VERIFY" "1" "2025-03-12" "s390-tools" "Attestation Manual"
|
||||
.TH "PVATTEST-VERIFY" "1" "2026-02-12" "s390-tools" "Attestation Manual"
|
||||
.nh
|
||||
.ad l
|
||||
.SH NAME
|
||||
@@ -11,7 +11,7 @@ pvattest-verify \- Verify an attestation response
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.fam C
|
||||
pvattest verify [OPTIONS] --input <FILE> --hdr <FILE> --arpk <FILE>
|
||||
pvattest verify [OPTIONS] \-\-input <FILE> \-\-hdr <FILE> \-\-arpk <FILE>
|
||||
.fam C
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
@@ -83,25 +83,25 @@ Print help (see a summary with \fB\-h\fR).
|
||||
|
||||
.SH EXIT STATUS
|
||||
.TP 8
|
||||
.B 0 - Attestation Verified
|
||||
.B 0 \- Attestation Verified
|
||||
Attesatation measurement verified successfully. Measured guest is in Secure Execution mode.
|
||||
.RE
|
||||
|
||||
.TP 8
|
||||
.B 1 - Program Error
|
||||
.B 1 \- Program Error
|
||||
Something went wrong during the local calculation or receiving of the measurement value. Refer to the error message.
|
||||
.RE
|
||||
|
||||
.TP 8
|
||||
.B 2 - Attestation NOT Verified
|
||||
.B 2 \- Attestation NOT Verified
|
||||
Attesation measurement calculation does not match the received value. Measured guest is very likely not in Secure Execution mode.
|
||||
.RE
|
||||
.SH EXAMPLES
|
||||
To verify a measurement in 'measurement.bin' with the protection key 'arp.kep' and SE-guest header 'se_guest.hdr'.
|
||||
To verify a measurement in 'measurement.bin' with the protection key 'arp.kep' and SE\-guest header 'se_guest.hdr'.
|
||||
.PP
|
||||
.nf
|
||||
.fam C
|
||||
$ pvattest verify --input attresp.bin --arpk arp.key --hdr se_guest.hdr
|
||||
$ pvattest verify \-\-input attresp.bin \-\-arpk arp.key \-\-hdr se_guest.hdr
|
||||
|
||||
.fam T
|
||||
.fi
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\"
|
||||
|
||||
.TH "PVATTEST" "1" "2025-03-12" "s390-tools" "Attestation Manual"
|
||||
.TH "PVATTEST" "1" "2026-02-12" "s390-tools" "Attestation Manual"
|
||||
.nh
|
||||
.ad l
|
||||
.SH NAME
|
||||
@@ -20,28 +20,28 @@ guest systems.
|
||||
.SH "PVATTEST COMMANDS"
|
||||
.PP
|
||||
|
||||
\fBpvattest-create(1)\fR
|
||||
\fBpvattest\-create(1)\fR
|
||||
.RS 4
|
||||
Create an attestation measurement request
|
||||
.RE
|
||||
|
||||
.PP
|
||||
|
||||
\fBpvattest-perform(1)\fR
|
||||
\fBpvattest\-perform(1)\fR
|
||||
.RS 4
|
||||
Send the attestation request to the Ultravisor
|
||||
.RE
|
||||
|
||||
.PP
|
||||
|
||||
\fBpvattest-verify(1)\fR
|
||||
\fBpvattest\-verify(1)\fR
|
||||
.RS 4
|
||||
Verify an attestation response
|
||||
.RE
|
||||
|
||||
.PP
|
||||
|
||||
\fBpvattest-check(1)\fR
|
||||
\fBpvattest\-check(1)\fR
|
||||
.RS 4
|
||||
Check if the attestation result matches defined policies
|
||||
.RE
|
||||
@@ -83,7 +83,7 @@ Create the request on a trusted system.
|
||||
|
||||
.fam T
|
||||
.fi
|
||||
On the SE-guest, \fIperform\fP the attestation.
|
||||
On the SE\-guest, \fIperform\fP the attestation.
|
||||
.PP
|
||||
.nf
|
||||
.fam C
|
||||
@@ -91,7 +91,7 @@ On the SE-guest, \fIperform\fP the attestation.
|
||||
|
||||
.fam T
|
||||
.fi
|
||||
On a trusted system, \fIverify\fP that the response is correct. Here, the protection key from the creation and the SE-guest’s header is used to \fIverify\fP the measurement.
|
||||
On a trusted system, \fIverify\fP that the response is correct. Here, the protection key from the creation and the SE\-guest’s header is used to \fIverify\fP the measurement.
|
||||
.PP
|
||||
.nf
|
||||
.fam C
|
||||
@@ -102,7 +102,7 @@ On a trusted system, \fIverify\fP that the response is correct. Here, the protec
|
||||
.fam T
|
||||
.fi
|
||||
|
||||
If the measurements do not match \fBpvattest\fP exits with code 2 and emits an error message. The SE-guest attestation failed.
|
||||
If the measurements do not match \fBpvattest\fP exits with code 2 and emits an error message. The SE\-guest attestation failed.
|
||||
.PP
|
||||
.nf
|
||||
.fam C
|
||||
@@ -116,4 +116,4 @@ If the measurements do not match \fBpvattest\fP exits with code 2 and emits an e
|
||||
.fi
|
||||
.SH "SEE ALSO"
|
||||
.sp
|
||||
\fBpvattest-create\fR(1) \fBpvattest-perform\fR(1) \fBpvattest-verify\fR(1) \fBpvattest-check\fR(1)
|
||||
\fBpvattest\-create\fR(1) \fBpvattest\-perform\fR(1) \fBpvattest\-verify\fR(1) \fBpvattest\-check\fR(1)
|
||||
|
||||
@@ -35,12 +35,12 @@ pub enum Command {
|
||||
/// shred it after verification. Every 'create' will generate a new, random protection key.
|
||||
Create(Box<CreateAttOpt>),
|
||||
|
||||
/// Send the attestation request to the Ultravisor.
|
||||
/// Send the attestation request to the Ultravisor (s390x only.)
|
||||
///
|
||||
/// Run a measurement of this system through ’/dev/uv’. This device must be accessible and the
|
||||
/// attestation Ultravisor facility must be present. The input must be an attestation request
|
||||
/// created with ’pvattest create’. Output will contain the original request and the response
|
||||
/// from the Ultravisor.
|
||||
/// from the Ultravisor. Only available on s390x.
|
||||
Perform(PerformAttOpt),
|
||||
|
||||
/// Verify an attestation response.
|
||||
@@ -110,27 +110,22 @@ pub enum AttAddFlags {
|
||||
FirmwareState,
|
||||
}
|
||||
|
||||
// all members s390x only
|
||||
#[derive(Args, Debug)]
|
||||
pub struct PerformAttOpt {
|
||||
/// Specify the request to be sent.
|
||||
#[cfg(target_arch = "s390x")]
|
||||
#[arg(hide=true, short, long, value_name = "FILE", value_hint = ValueHint::FilePath,)]
|
||||
pub input: Option<String>,
|
||||
|
||||
/// Specify the request to be sent.
|
||||
#[cfg(target_arch = "s390x")]
|
||||
#[arg(value_name = "IN", value_hint = ValueHint::FilePath, required_unless_present("input"), conflicts_with("input"))]
|
||||
pub input_pos: Option<String>,
|
||||
|
||||
/// Write the result to FILE.
|
||||
#[cfg(target_arch = "s390x")]
|
||||
#[arg(hide=true, short, long, value_name = "FILE", value_hint = ValueHint::FilePath,)]
|
||||
pub output: Option<String>,
|
||||
|
||||
/// Write the result to FILE.
|
||||
#[arg(value_name = "OUT", value_hint = ValueHint::FilePath, required_unless_present("output"), conflicts_with("output"))]
|
||||
#[cfg(target_arch = "s390x")]
|
||||
pub output_pos: Option<String>,
|
||||
|
||||
/// Provide up to 256 bytes of user input
|
||||
|
||||
@@ -13,8 +13,8 @@ use serde::{Deserialize, Serialize};
|
||||
use super::{bail_check, CheckState};
|
||||
use crate::{additional::AttestationResult, cli::CheckOpt};
|
||||
|
||||
const CHECK_DEFAULT_ENDP: &str = "https://www.ibm.com/support/resourcelink/api";
|
||||
const VERIFY_API: &str = "firmware-attestation/verify/v1";
|
||||
const CHECK_DEFAULT_ENDP: &str = "https://esupport.ibm.com/eccedge/ent/z";
|
||||
const VERIFY_API: &str = "hmrs/firmware/attestation/v1/verify";
|
||||
const TIMEOUT_MAX: Duration = Duration::from_secs(3);
|
||||
const USER_AGENT: &str = "s390-tools-pvattest";
|
||||
const CONTENT_TYPE: &str = "Content-Type: application/json";
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright IBM Corp. 2024
|
||||
#![allow(unused)]
|
||||
use anyhow::{anyhow, bail, Error, Result};
|
||||
use pv::{assert_size, request::MagicValue, uv::AttestationCmd, uv::ConfigUid};
|
||||
use std::{
|
||||
|
||||
28
rust/pvebc/95sel-ebc/boot.mount
Normal file
28
rust/pvebc/95sel-ebc/boot.mount
Normal file
@@ -0,0 +1,28 @@
|
||||
[Unit]
|
||||
Description=Mount /boot early in initramfs
|
||||
|
||||
# Initramfs requirement
|
||||
DefaultDependencies=no
|
||||
# Make absolutely sure this only runs in initramfs (and not post-pivot if the
|
||||
# unit ever appears there)
|
||||
ConditionPathExists=/etc/initrd-release
|
||||
ConditionKernelCommandLine=root
|
||||
|
||||
# we use /dev/disk/by-label because it identifies the boot partition system
|
||||
# independently IF set up correctly
|
||||
Requires=dev-disk-by\x2dlabel-boot.device
|
||||
|
||||
# Ordering dependencies
|
||||
After=dev-disk-by\x2dlabel-boot.device
|
||||
Before=sel-ebc-pvebc.service
|
||||
|
||||
[Mount]
|
||||
# system independent identification of boot partition requires that the label
|
||||
# boot is set for the boot partition
|
||||
What=/dev/disk/by-label/boot
|
||||
Where=/boot
|
||||
Type=auto
|
||||
Options=defaults
|
||||
|
||||
[Install]
|
||||
WantedBy=sel-ebc-pvebc.service
|
||||
76
rust/pvebc/95sel-ebc/module-setup.sh
Normal file
76
rust/pvebc/95sel-ebc/module-setup.sh
Normal file
@@ -0,0 +1,76 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# Copyright IBM Corp.
|
||||
|
||||
|
||||
# Called by dracut
|
||||
check() {
|
||||
# always include
|
||||
return 0
|
||||
}
|
||||
|
||||
# Called by dracut
|
||||
depends() {
|
||||
# We need systemd in the initramfs
|
||||
echo systemd
|
||||
echo systemd-udevd
|
||||
echo crypt
|
||||
echo dm
|
||||
return 0
|
||||
}
|
||||
|
||||
# Called by dracut
|
||||
installkernel() {
|
||||
# kernel modules needed for opening an encrypted rfs
|
||||
instmods -c uvdevice
|
||||
instmods -c paes_s390
|
||||
instmods -c pkey_uv
|
||||
instmods -c pkey_pckmo
|
||||
instmods -c pkey
|
||||
}
|
||||
|
||||
# Called by dracut
|
||||
install() {
|
||||
# shellcheck disable=SC2154
|
||||
# moddir, systemdsystemunitdir, and initdir are provided by dracut
|
||||
# Copy the units into the initramfs' systemd unit dir
|
||||
inst_simple "$moddir/sel-ebc.target" \
|
||||
"$systemdsystemunitdir/sel-ebc.target"
|
||||
inst_simple "$moddir/sel-ebc-pvebc.service" \
|
||||
"$systemdsystemunitdir/sel-ebc-pvebc.service"
|
||||
inst_simple "$moddir/sel-ebc-paes-enforce.service" \
|
||||
"$systemdsystemunitdir/sel-ebc-paes-enforce.service"
|
||||
inst_simple "$moddir/sel-ebc-override-crypttab.service" \
|
||||
"$systemdsystemunitdir/sel-ebc-override-crypttab.service"
|
||||
inst_simple "$moddir/boot.mount" \
|
||||
"$systemdsystemunitdir/boot.mount"
|
||||
|
||||
# already exisitng unit we depend on for kernel modules
|
||||
inst_simple /usr/lib/systemd/system/systemd-modules-load.service \
|
||||
"$systemdsystemunitdir/systemd-modules-load.service"
|
||||
|
||||
# wrapper for sel-ebc.service
|
||||
inst_simple "$moddir/pvebc-wrapper.sh" \
|
||||
"/etc/sel-ebc/pvebc-wrapper.sh"
|
||||
|
||||
# override crypttab
|
||||
inst_simple "$moddir/override-crypttab.sh" \
|
||||
"/etc/sel-ebc/override-crypttab.sh"
|
||||
|
||||
# copy main application
|
||||
inst_binary "/usr/bin/pvebc"
|
||||
inst_binary "/usr/bin/pvsecret"
|
||||
|
||||
inst_simple "$moddir/sel-ebc.crypttab" "/etc/sel-ebc/crypttab"
|
||||
|
||||
# Create the enablement symlinks in the image using host systemctl:
|
||||
# shellcheck disable=SC2154
|
||||
inst_dir "$initdir/etc/systemd/system"
|
||||
systemctl --root "$initdir" --no-reload --quiet enable sel-ebc.target
|
||||
systemctl --root "$initdir" --no-reload --quiet enable sel-ebc-pvebc.service
|
||||
systemctl --root "$initdir" --no-reload --quiet enable sel-ebc-override-crypttab.service
|
||||
systemctl --root "$initdir" --no-reload --quiet enable sel-ebc-paes-enforce.service
|
||||
systemctl --root "$initdir" --no-reload --quiet enable systemd-modules-load.service
|
||||
systemctl --root "$initdir" --no-reload --quiet enable boot.mount
|
||||
}
|
||||
20
rust/pvebc/95sel-ebc/override-crypttab.sh
Normal file
20
rust/pvebc/95sel-ebc/override-crypttab.sh
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# Copyright IBM Corp.
|
||||
|
||||
IBM_RSRC_DIR="/etc/sel-ebc"
|
||||
|
||||
if [[ ! -f "${IBM_RSRC_DIR}/crypttab" ]]; then
|
||||
echo "Error: source file $IBM_RSRC_DIR/crypttab does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Unconditionally override /etc/crypttab to ensure correct EBC configuration
|
||||
cp "${IBM_RSRC_DIR}/crypttab" "/etc/crypttab"
|
||||
|
||||
systemctl daemon-reload
|
||||
|
||||
systemctl restart systemd-cryptsetup@cryptroot_mapper.service
|
||||
|
||||
exit 0
|
||||
63
rust/pvebc/95sel-ebc/pvebc-wrapper.sh
Normal file
63
rust/pvebc/95sel-ebc/pvebc-wrapper.sh
Normal file
@@ -0,0 +1,63 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# Copyright IBM Corp.
|
||||
|
||||
SYSFS=/sys/firmware/uv/prot_virt_guest
|
||||
SICS=/boot/sics
|
||||
EBC_TMPFS=/run/sel-ebc
|
||||
TOC=toc.asr
|
||||
ASR_NAME=luks-rfs-passphrase
|
||||
|
||||
# Early exit for non SEL guests
|
||||
if [[ ! -e $SYSFS ]]; then
|
||||
echo "Not running in a SEL guest."
|
||||
exit 1
|
||||
fi
|
||||
if [[ $(cat $SYSFS) -ne 1 ]]; then
|
||||
echo "Not running in a SEL guest."
|
||||
exit 1
|
||||
fi
|
||||
echo "Running in SEL guest."
|
||||
|
||||
# Copy EBC resources from /boot/sics to tmpfs for security
|
||||
# This protects against host injection attacks by moving resources to UV-protected RAM
|
||||
echo "Copying EBC resources from $SICS to $EBC_TMPFS"
|
||||
if ! mkdir -p "$EBC_TMPFS"; then
|
||||
echo "Failed to create $EBC_TMPFS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Copy only .asr and .pol files
|
||||
for file in "$SICS"/*.asr "$SICS"/*.pol; do
|
||||
if [[ -f "$file" && ! -L "$file" ]]; then
|
||||
cp "$file" "$EBC_TMPFS/" || {
|
||||
echo "Failed to copy $file to $EBC_TMPFS"
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
done
|
||||
|
||||
# Verify toc.asr was copied
|
||||
if [[ ! -f "$EBC_TMPFS/$TOC" ]]; then
|
||||
echo "Error: $EBC_TMPFS/$TOC does not exist after copy"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# execute the actual tool with the copied toc.asr
|
||||
pvebc --toc "$EBC_TMPFS/$TOC"
|
||||
rc=$?
|
||||
if [[ $rc -ne 0 ]]; then
|
||||
exit $rc
|
||||
fi
|
||||
|
||||
# Retrieve and check for dummy LUKS passphrase
|
||||
pvsecret retrieve --inform name -o "$EBC_TMPFS/$ASR_NAME" --outform bin "$ASR_NAME"
|
||||
|
||||
if [[ ! -f "$EBC_TMPFS/$ASR_NAME" ]]; then
|
||||
echo "$EBC_TMPFS/$ASR_NAME does not exist"
|
||||
fi
|
||||
|
||||
chmod 400 "$EBC_TMPFS/$ASR_NAME"
|
||||
|
||||
exit 0
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user