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