xref: /illumos-gate/usr/src/test/tz-tests/tests/tz_dump.ksh (revision 24a03f35583aede6d1aea859d90d76a3e6c2eb22)
1#!/usr/bin/ksh
2#
3# This file and its contents are supplied under the terms of the
4# Common Development and Distribution License ("CDDL"), version 1.0.
5# You may only use this file in accordance with the terms of version
6# 1.0 of the CDDL.
7#
8# A full copy of the text of the CDDL should have accompanied this
9# source.  A copy of the CDDL is also available via the Internet at
10# http://www.illumos.org/license/CDDL.
11#
12
13#
14# Copyright 2025 Oxide Computer Company
15#
16
17#
18# The purpose of this program is to go through and dump the internal libc state
19# from every time zone that we encounter so that we can go back and do a before
20# an after comparison of this information.
21#
22
23unalias -a
24set -o pipefail
25export LANG=C.UTF-8
26
27lc_arg0=$(basename $0)
28lc_dir=$(dirname $0)
29lc_print="*lclzonep::print -tL struct state"
30lc_prev=
31lc_out=
32lc_libc=0
33lc_zdump=0
34lc_prog=${ZDUMP:-/usr/sbin/zdump}
35
36#
37# These will be filled in with the variable size that we detect via a program so
38# we can survive some changes in libc without as much pain.
39#
40lc_chars=
41lc_times=
42
43#
44# List of timezones
45#
46lc_zones=
47
48usage()
49{
50	typeset msg="$*"
51	[[ -z "$msg" ]] || echo "$msg" >&2
52	cat <<USAGE >&2
53Usage:  $lc_arg0 [-c] [-z] -o dir
54Dump information about all timezones to a directory.
55
56	-c		dump state from inside of libc
57	-o directory	dump data to output directory
58	-z		dump zone with zdump(8)
59USAGE
60	exit 2
61}
62
63fatal()
64{
65        typeset msg="$*"
66        [[ -z "$msg" ]] && msg="failed"
67        echo "lcx_arg0: $msg" >&2
68        exit 1
69}
70
71get_tzparams()
72{
73	eval $($lc_dir/tzparams.64);
74	[[ -z "$TZ_MAX_TIMES" ]] && "failed to get TZ_MAX_TIMES"
75	[[ -z "$TZ_MAX_CHARS" ]] && "failed to get TZ_MAX_CHARS"
76
77	lc_chars="$TZ_MAX_CHARS"
78	lc_times="$TZ_MAX_TIMES"
79
80	for i in {0..$((lc_times - 1))}; do
81		lc_prev+="$lc_print prev[0t$i].std[] prev[0t$i].alt[]\n"
82	done
83
84	lc_zones=$($lc_dir/tzlist.64)
85	[[ -z "$lc_zones" ]] && fatal "failed to get time zones"
86}
87
88dump_one()
89{
90	typeset tz="$1"
91	typeset dir="$lc_out/$tz"
92
93	if ! mkdir -p $dir; then
94		fatal "failed to make output directory $dir"
95	fi
96
97	printf "Dumping %s\n" "$tz"
98	if (( lc_libc != 0 )); then
99		TZ=$tz mdb $lc_dir/tzload.32 > "$dir/libc-out.32" \
100		    2>"$dir/libc-err.32" <<EOF
101::bp mdb_hook
102::run
103*lclzonep::printf "name: [%s]\n" struct state zonename
104*lclzonep::printf "alt0: [%s]\n" struct state default_tzname0
105*lclzonep::printf "alt1: [%s]\n" struct state default_tzname1
106$lc_print zonerules daylight default_timezone default_altzone
107$lc_print leapcnt timecnt typecnt charcnt charsbuf_size
108$lc_print chars | ::dump -r -l 0t$lc_chars
109$(echo "$lc_prev")
110$lc_print ats types ttis lsis last_ats_idx start_rule end_rule
111\$q
112EOF
113
114		TZ=$tz mdb $lc_dir/tzload.64 > "$dir/libc-out.64" \
115		    2>"$dir/libc-err.64" <<EOF
116::bp mdb_hook
117::run
118*lclzonep::printf "name: [%s]\n" struct state zonename
119*lclzonep::printf "alt0: [%s]\n" struct state default_tzname0
120*lclzonep::printf "alt1: [%s]\n" struct state default_tzname1
121$lc_print zonerules daylight default_timezone default_altzone
122$lc_print leapcnt timecnt typecnt charcnt charsbuf_size
123$lc_print chars | ::dump -r -l 0t$lc_chars
124$(echo "$lc_prev")
125$lc_print ats types ttis lsis last_ats_idx start_rule end_rule
126\$q
127EOF
128	fi
129
130	if (( lc_zdump != 0 )); then
131		$lc_prog -v $tz 2>&1 >"$dir/zdump"
132	fi
133}
134
135while getopts ":co:z" c $@; do
136	case "$c" in
137	c)
138		lc_libc=1
139		;;
140	o)
141		[[ ! -d "$OPTARG" ]] && fatal "$OPTARG is not a directory"
142		lc_out="$OPTARG"
143		;;
144	z)
145		lc_zdump=1
146		;;
147	:)
148		usage "option requires an argument -- $OPTARG"
149		;;
150	*)
151		usage "invalid option -- $OPTARG"
152		;;
153	esac
154done
155
156[[ -z "$lc_out" ]] && usage "missing required output directory"
157(( lc_libc == 0 && lc_zdump == 0 )) && usage \
158    "at least one of -c or -z is required"
159
160get_tzparams
161for z in $lc_zones; do
162	dump_one "$z"
163done
164exit 0
165