All checks were successful
Source release / source-package (push) Successful in 50s
Implement the WebSDK/NWAFP Get DOS Name From Entry ID subfunction (NCP 0x2222/35/18) as a conservative, read-only reverse lookup over mars_nwe's existing volume and AFP metadata infrastructure. The documented request carries a volume number and 32-bit Macintosh directory entry ID, and the reply returns a length-prefixed DOS path string. mars_nwe's current AFP entry IDs are not the namespace base handles maintained by namspace.c; they are mars_nwe/libatalk AFP metadata IDs cached through nwatalk. Reuse the existing volume table as the search root and nwatalk_get_entry_id() as the identity probe instead of inventing a parallel namespace handle mapping. The reverse lookup deliberately does not create fallback IDs while walking the volume. It only matches entries that already have mars_nwe or Netatalk AFP metadata, which is the normal smoke-test sequence after Get Entry ID, Get File Information, or Scan File Information has cached the target ID. This keeps the lookup read-only and avoids populating entry-id xattrs across an entire volume as a side effect. Add a Linux afp_dos_name_smoke helper and wire it into the AFP smoke suite. The helper can resolve the supplied VOL:PATH to an entry ID first, then sends the 0x12 request and verifies the returned path without the volume prefix. The suite continues to exercise the existing path-backed AFP compatibility flow before future create/rename/remove work. Tests:\n- git diff --check\n- bash -n tests/linux/afp_smoke_suite.sh\n- gcc -Iinclude -I/mnt/data/stubs -fsyntax-only tests/linux/afp_dos_name_smoke.c\n\nTODO:\n- Replace the volume walk with a real CNID/base-ID index when persistent AFP identity storage grows one.\n- Return true DOS 8.3 aliases once the AFP reverse lookup is wired to the namespace alias helpers rather than preserving the cached path component spelling.
355 lines
12 KiB
Bash
Executable File
355 lines
12 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_dos_name_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 Get DOS Name From Entry ID" \
|
|
"./afp_dos_name_smoke $COMMON_PRINT '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_dos_name_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 Open File Fork write access rejected" \
|
|
"./afp_open_file_fork_smoke --expect-completion 0x84 --access 0x02 $COMMON_PRINT '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_open_file_fork_smoke" --expect-completion 0x84 --access 0x02 \
|
|
-S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" "$NETWARE_PATH"
|
|
|
|
run_cmd \
|
|
"AFP Open File Fork resource fork rejected" \
|
|
"./afp_open_file_fork_smoke --expect-completion 0x9c --fork 1 $COMMON_PRINT '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_open_file_fork_smoke" --expect-completion 0x9c --fork 1 \
|
|
-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 Archive" \
|
|
"./afp_set_file_info_smoke $COMMON_PRINT --attributes-only --archive '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
|
--attributes-only --archive "$NETWARE_PATH"
|
|
|
|
run_cmd \
|
|
"AFP Set File Information Clear Archive" \
|
|
"./afp_set_file_info_smoke $COMMON_PRINT --attributes-only --clear-archive '$NETWARE_PATH'" \
|
|
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
|
--attributes-only --clear-archive "$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
|