All checks were successful
Source release / source-package (push) Successful in 51s
Extend the conservative AFP Set File Information implementation to accept the file modification timestamp bitmap for path-backed file requests. The WebSDK/NWAFP Set File Information payload carries the timestamp in the same bitmap-ordered parameter stream as file attributes and FinderInfo, so the parser now admits the documented modification timestamp field while continuing to reject every other Set File Information bitmap bit. Do not implement a new AFP-specific timestamp backend. After resolving the raw VOL:-style smoke path to the effective mars_nwe volume and Unix path, convert the AFP/NW DOS date+time fields to time_t and route the update through the existing nw_utime_node() helper. That keeps trustee Modify-right checks and the established utime(2) fallback behavior shared with classic NetWare/NCP timestamp updates. Keep the implementation deliberately file-only and path-backed. Directory timestamps, create/access/backup timestamp fields, Entry-ID-only Set File Information, resource-fork semantics, DOS attribute mapping, Delete, Rename, Create, and Remove stay TODO so later patches can wire them to the existing NetWare helpers with focused smoke coverage. Update afp_set_file_info_smoke with --mtime-epoch and --timestamp-only, verify the written AFP date/time via the follow-up Get File Information record, and extend afp_smoke_suite.sh to run the timestamp probe and record the backing Linux stat output. The suite helper is already copied as a build target, so the new test is propagated into the build tree by the normal tests build. Tests: - git diff --check - bash -n tests/linux/afp_smoke_suite.sh - gcc -Iinclude -I/mnt/data/stubs -fsyntax-only tests/linux/afp_set_file_info_smoke.c
337 lines
11 KiB
Bash
Executable File
337 lines
11 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Run the mars_nwe AFP Linux smoke helpers as one collectable report.
|
|
#
|
|
# The helper intentionally keeps the password out of the printed command lines,
|
|
# captures AFP server diagnostics from the mars_nwe log while the probes run, and
|
|
# appends Linux xattr checks for the tested Unix file.
|
|
|
|
set -u
|
|
|
|
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
|
SERVER="MARS"
|
|
USER_NAME="SUPERVISOR"
|
|
PASSWORD=""
|
|
NETWARE_PATH="SYS:PUBLIC/pmdflts.ini"
|
|
UNIX_PATH="/var/mars_nwe/SYS/public/pmdflts.ini"
|
|
LOG_FILE="/var/log/mars_nwe/nw.log"
|
|
OUT_FILE=""
|
|
FINDER_TYPE="TEXT"
|
|
FINDER_CREATOR="MARS"
|
|
TIMESTAMP_EPOCH="1700000000"
|
|
KEEP_GOING=1
|
|
CAPTURE_LOG=1
|
|
|
|
usage() {
|
|
cat <<USAGE
|
|
Usage: $0 -S SERVER -U USER -P PASSWORD [options]
|
|
|
|
Options:
|
|
--path NETWARE_PATH NetWare path to test (default: $NETWARE_PATH)
|
|
--unix-path UNIX_PATH Unix path for getfattr checks (default: $UNIX_PATH)
|
|
--log LOGFILE mars_nwe log to tail for AFP lines (default: $LOG_FILE)
|
|
--out FILE Write the complete report to FILE as well as stdout
|
|
--type FOURCC FinderInfo type written by Set File Info (default: $FINDER_TYPE)
|
|
--creator FOURCC FinderInfo creator written by Set File Info (default: $FINDER_CREATOR)
|
|
--mtime-epoch SECONDS AFP modify timestamp to write (default: $TIMESTAMP_EPOCH)
|
|
--no-log Do not tail/grep the server log
|
|
--stop-on-failure Stop after the first failing smoke command
|
|
-h, --help Show this help
|
|
|
|
The script expects the compiled smoke helpers in the same directory as this
|
|
script. It prints commands with the password masked, writes an AFP-only log
|
|
snippet, and runs getfattr checks for mars_nwe AFP xattrs.
|
|
USAGE
|
|
}
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
-S|--server)
|
|
SERVER=$2; shift 2 ;;
|
|
-U|--user)
|
|
USER_NAME=$2; shift 2 ;;
|
|
-P|--password)
|
|
PASSWORD=$2; shift 2 ;;
|
|
--path)
|
|
NETWARE_PATH=$2; shift 2 ;;
|
|
--unix-path)
|
|
UNIX_PATH=$2; shift 2 ;;
|
|
--log)
|
|
LOG_FILE=$2; shift 2 ;;
|
|
--out)
|
|
OUT_FILE=$2; shift 2 ;;
|
|
--type)
|
|
FINDER_TYPE=$2; shift 2 ;;
|
|
--creator)
|
|
FINDER_CREATOR=$2; shift 2 ;;
|
|
--mtime-epoch)
|
|
TIMESTAMP_EPOCH=$2; shift 2 ;;
|
|
--no-log)
|
|
CAPTURE_LOG=0; shift ;;
|
|
--stop-on-failure)
|
|
KEEP_GOING=0; shift ;;
|
|
-h|--help)
|
|
usage; exit 0 ;;
|
|
*)
|
|
echo "Unknown argument: $1" >&2
|
|
usage >&2
|
|
exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
if [ -z "$PASSWORD" ]; then
|
|
echo "Missing password. Use -P PASSWORD." >&2
|
|
usage >&2
|
|
exit 2
|
|
fi
|
|
|
|
case "$FINDER_TYPE" in
|
|
???? ) ;;
|
|
*) echo "--type must be exactly four characters" >&2; exit 2 ;;
|
|
esac
|
|
case "$FINDER_CREATOR" in
|
|
???? ) ;;
|
|
*) echo "--creator must be exactly four characters" >&2; exit 2 ;;
|
|
esac
|
|
|
|
DIR_PATH=$NETWARE_PATH
|
|
case "$NETWARE_PATH" in
|
|
*/*) DIR_PATH=${NETWARE_PATH%/*} ;;
|
|
esac
|
|
|
|
REPORT_TMP=$(mktemp "${TMPDIR:-/tmp}/mars-afp-smoke.XXXXXX")
|
|
LOG_TMP=$(mktemp "${TMPDIR:-/tmp}/mars-afp-log.XXXXXX")
|
|
LOG_PID=""
|
|
FAILURES=0
|
|
|
|
cleanup() {
|
|
if [ -n "$LOG_PID" ] && kill -0 "$LOG_PID" 2>/dev/null; then
|
|
kill "$LOG_PID" 2>/dev/null || true
|
|
wait "$LOG_PID" 2>/dev/null || true
|
|
fi
|
|
rm -f "$LOG_TMP"
|
|
}
|
|
trap cleanup EXIT INT TERM
|
|
|
|
emit() {
|
|
printf '%s\n' "$*" | tee -a "$REPORT_TMP"
|
|
}
|
|
|
|
section() {
|
|
emit ""
|
|
emit "## $*"
|
|
}
|
|
|
|
run_cmd() {
|
|
local label=$1
|
|
local printable=$2
|
|
shift 2
|
|
|
|
section "$label"
|
|
emit "\$ $printable"
|
|
"$@" 2>&1 | tee -a "$REPORT_TMP"
|
|
local status=${PIPESTATUS[0]}
|
|
emit "[exit=$status]"
|
|
if [ "$status" -ne 0 ]; then
|
|
FAILURES=$((FAILURES + 1))
|
|
if [ "$KEEP_GOING" -eq 0 ]; then
|
|
finish_report
|
|
exit "$status"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
finish_report() {
|
|
if [ "$CAPTURE_LOG" -eq 1 ]; then
|
|
sleep 1
|
|
if [ -n "$LOG_PID" ] && kill -0 "$LOG_PID" 2>/dev/null; then
|
|
kill "$LOG_PID" 2>/dev/null || true
|
|
wait "$LOG_PID" 2>/dev/null || true
|
|
LOG_PID=""
|
|
fi
|
|
section "AFP server log excerpt"
|
|
if [ -s "$LOG_TMP" ]; then
|
|
cat "$LOG_TMP" | tee -a "$REPORT_TMP"
|
|
else
|
|
emit "No AFP lines captured from $LOG_FILE."
|
|
fi
|
|
fi
|
|
|
|
section "Summary"
|
|
emit "failures=$FAILURES"
|
|
if [ -n "$OUT_FILE" ]; then
|
|
cp "$REPORT_TMP" "$OUT_FILE"
|
|
emit "report=$OUT_FILE"
|
|
fi
|
|
}
|
|
|
|
section "mars_nwe AFP smoke suite"
|
|
emit "date=$(date -Is)"
|
|
emit "server=$SERVER"
|
|
emit "user=$USER_NAME"
|
|
emit "path=$NETWARE_PATH"
|
|
emit "dir_path=$DIR_PATH"
|
|
emit "unix_path=$UNIX_PATH"
|
|
emit "log=$LOG_FILE"
|
|
emit "finder_type=$FINDER_TYPE"
|
|
emit "finder_creator=$FINDER_CREATOR"
|
|
emit "mtime_epoch=$TIMESTAMP_EPOCH"
|
|
|
|
for helper in \
|
|
afp_entry_id_smoke \
|
|
afp_file_info_smoke \
|
|
afp_scan_info_smoke \
|
|
afp_temp_dir_handle_smoke \
|
|
afp_open_file_fork_smoke \
|
|
afp_set_file_info_smoke
|
|
do
|
|
if [ ! -x "$SCRIPT_DIR/$helper" ]; then
|
|
emit "Missing executable: $SCRIPT_DIR/$helper"
|
|
exit 2
|
|
fi
|
|
done
|
|
|
|
if [ "$CAPTURE_LOG" -eq 1 ]; then
|
|
if [ -r "$LOG_FILE" ]; then
|
|
# Capture only lines appended while this script is running.
|
|
tail -n 0 -F "$LOG_FILE" 2>/dev/null | grep --line-buffered AFP >"$LOG_TMP" &
|
|
LOG_PID=$!
|
|
sleep 1
|
|
else
|
|
emit "Log file is not readable, disabling log capture: $LOG_FILE"
|
|
CAPTURE_LOG=0
|
|
fi
|
|
fi
|
|
|
|
COMMON_PRINT="-S $SERVER -U $USER_NAME -P ******"
|
|
|
|
run_cmd \
|
|
"AFP Entry ID From Path Name" \
|
|
"./afp_entry_id_smoke $COMMON_PRINT '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_entry_id_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" "$NETWARE_PATH"
|
|
|
|
run_cmd \
|
|
"AFP Entry ID From NetWare Handle" \
|
|
"./afp_entry_id_smoke --from-handle $COMMON_PRINT '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_entry_id_smoke" --from-handle -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" "$NETWARE_PATH"
|
|
|
|
run_cmd \
|
|
"AFP 2.0 Get File Information" \
|
|
"./afp_file_info_smoke $COMMON_PRINT '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" "$NETWARE_PATH"
|
|
|
|
run_cmd \
|
|
"AFP 2.0 Scan File Information" \
|
|
"./afp_scan_info_smoke $COMMON_PRINT '$DIR_PATH'" \
|
|
"$SCRIPT_DIR/afp_scan_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" "$DIR_PATH"
|
|
|
|
run_cmd \
|
|
"AFP Alloc Temporary Directory Handle" \
|
|
"./afp_temp_dir_handle_smoke $COMMON_PRINT '$DIR_PATH'" \
|
|
"$SCRIPT_DIR/afp_temp_dir_handle_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" "$DIR_PATH"
|
|
|
|
run_cmd \
|
|
"AFP Open File Fork" \
|
|
"./afp_open_file_fork_smoke $COMMON_PRINT '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_open_file_fork_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" "$NETWARE_PATH"
|
|
|
|
run_cmd \
|
|
"AFP Set File Information FinderInfo" \
|
|
"./afp_set_file_info_smoke $COMMON_PRINT --finder-info-only --type '$FINDER_TYPE' --creator '$FINDER_CREATOR' '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
|
--finder-info-only --type "$FINDER_TYPE" --creator "$FINDER_CREATOR" "$NETWARE_PATH"
|
|
|
|
run_cmd \
|
|
"AFP Set File Information FinderInfo legacy" \
|
|
"./afp_set_file_info_smoke $COMMON_PRINT --afp09 --finder-info-only --type '$FINDER_TYPE' --creator '$FINDER_CREATOR' '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
|
--afp09 --finder-info-only --type "$FINDER_TYPE" --creator "$FINDER_CREATOR" "$NETWARE_PATH"
|
|
|
|
run_cmd \
|
|
"AFP Set File Information Invisible" \
|
|
"./afp_set_file_info_smoke $COMMON_PRINT --attributes-only --invisible '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
|
--attributes-only --invisible "$NETWARE_PATH"
|
|
|
|
run_cmd \
|
|
"AFP Set File Information Clear Invisible" \
|
|
"./afp_set_file_info_smoke $COMMON_PRINT --attributes-only --clear-invisible '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
|
--attributes-only --clear-invisible "$NETWARE_PATH"
|
|
|
|
run_cmd \
|
|
"AFP Set File Information Invisible legacy" \
|
|
"./afp_set_file_info_smoke $COMMON_PRINT --afp09 --attributes-only --invisible '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
|
--afp09 --attributes-only --invisible "$NETWARE_PATH"
|
|
|
|
run_cmd \
|
|
"AFP Set File Information Clear Invisible legacy" \
|
|
"./afp_set_file_info_smoke $COMMON_PRINT --afp09 --attributes-only --clear-invisible '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
|
--afp09 --attributes-only --clear-invisible "$NETWARE_PATH"
|
|
|
|
run_cmd \
|
|
"AFP Set File Information Modify Timestamp" \
|
|
"./afp_set_file_info_smoke $COMMON_PRINT --timestamp-only --mtime-epoch '$TIMESTAMP_EPOCH' '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
|
--timestamp-only --mtime-epoch "$TIMESTAMP_EPOCH" "$NETWARE_PATH"
|
|
|
|
run_cmd \
|
|
"AFP Set File Information System" \
|
|
"./afp_set_file_info_smoke $COMMON_PRINT --attributes-only --system '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
|
--attributes-only --system "$NETWARE_PATH"
|
|
|
|
run_cmd \
|
|
"AFP Set File Information Clear System" \
|
|
"./afp_set_file_info_smoke $COMMON_PRINT --attributes-only --clear-system '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
|
--attributes-only --clear-system "$NETWARE_PATH"
|
|
|
|
run_cmd \
|
|
"AFP Set File Information Backup" \
|
|
"./afp_set_file_info_smoke $COMMON_PRINT --attributes-only --backup '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
|
--attributes-only --backup "$NETWARE_PATH"
|
|
|
|
run_cmd \
|
|
"AFP Set File Information Clear Backup" \
|
|
"./afp_set_file_info_smoke $COMMON_PRINT --attributes-only --clear-backup '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
|
--attributes-only --clear-backup "$NETWARE_PATH"
|
|
|
|
if command -v stat >/dev/null 2>&1; then
|
|
run_cmd \
|
|
"Linux stat: AFP Modify Timestamp" \
|
|
"stat -c 'mtime_epoch=%Y mtime=%y' '$UNIX_PATH'" \
|
|
stat -c 'mtime_epoch=%Y mtime=%y' "$UNIX_PATH"
|
|
fi
|
|
|
|
if command -v getfattr >/dev/null 2>&1; then
|
|
run_cmd \
|
|
"Linux xattr: AFP FinderInfo" \
|
|
"getfattr -n user.org.mars-nwe.afp.finder-info -e hex '$UNIX_PATH'" \
|
|
getfattr -n user.org.mars-nwe.afp.finder-info -e hex "$UNIX_PATH"
|
|
|
|
run_cmd \
|
|
"Linux xattr: AFP Attributes" \
|
|
"getfattr -n user.org.mars-nwe.afp.attributes -e hex '$UNIX_PATH'" \
|
|
getfattr -n user.org.mars-nwe.afp.attributes -e hex "$UNIX_PATH"
|
|
|
|
run_cmd \
|
|
"Linux xattr: AFP Entry ID" \
|
|
"getfattr -n user.org.mars-nwe.afp.entry-id -e hex '$UNIX_PATH'" \
|
|
getfattr -n user.org.mars-nwe.afp.entry-id -e hex "$UNIX_PATH"
|
|
else
|
|
section "Linux xattr checks"
|
|
emit "getfattr not found; install the attr package to collect xattr output."
|
|
FAILURES=$((FAILURES + 1))
|
|
fi
|
|
|
|
finish_report
|
|
|
|
if [ "$FAILURES" -ne 0 ]; then
|
|
exit 1
|
|
fi
|
|
exit 0
|