Files
mars-nwe/tests/linux/afp_smoke_suite.sh
OpenAI 63f5fa699a
All checks were successful
Source release / source-package (push) Successful in 51s
nwconn: route AFP set file timestamps via NetWare helper
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
2026-05-30 14:29:24 +02:00

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