1*d8f5b04cSrillig# $NetBSD: t_psshfs.sh,v 1.10 2024/04/28 07:27:41 rillig Exp $ 27f396ca7Spooka# 37f396ca7Spooka# Copyright (c) 2007, 2008 The NetBSD Foundation, Inc. 47f396ca7Spooka# All rights reserved. 57f396ca7Spooka# 67f396ca7Spooka# Redistribution and use in source and binary forms, with or without 77f396ca7Spooka# modification, are permitted provided that the following conditions 87f396ca7Spooka# are met: 97f396ca7Spooka# 1. Redistributions of source code must retain the above copyright 107f396ca7Spooka# notice, this list of conditions and the following disclaimer. 117f396ca7Spooka# 2. Redistributions in binary form must reproduce the above copyright 127f396ca7Spooka# notice, this list of conditions and the following disclaimer in the 137f396ca7Spooka# documentation and/or other materials provided with the distribution. 147f396ca7Spooka# 157f396ca7Spooka# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 167f396ca7Spooka# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 177f396ca7Spooka# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 187f396ca7Spooka# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 197f396ca7Spooka# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 207f396ca7Spooka# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 217f396ca7Spooka# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 227f396ca7Spooka# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 237f396ca7Spooka# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 247f396ca7Spooka# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 257f396ca7Spooka# POSSIBILITY OF SUCH DAMAGE. 267f396ca7Spooka# 277f396ca7Spooka 287f396ca7Spooka# ------------------------------------------------------------------------- 297f396ca7Spooka# Auxiliary functions. 307f396ca7Spooka# ------------------------------------------------------------------------- 317f396ca7Spooka 327f396ca7Spooka# 337f396ca7Spooka# Skips the calling test case if puffs is not supported in the kernel 347f396ca7Spooka# or if the calling user does not have the necessary permissions to mount 357f396ca7Spooka# file systems. 367f396ca7Spooka# 377f396ca7Spookarequire_puffs() { 387f396ca7Spooka case "$($(atf_get_srcdir)/h_have_puffs)" in 397f396ca7Spooka eacces) 407f396ca7Spooka atf_skip "Cannot open /dev/puffs for read/write access" 417f396ca7Spooka ;; 427f396ca7Spooka enxio) 437f396ca7Spooka atf_skip "puffs support not built into the kernel" 447f396ca7Spooka ;; 457f396ca7Spooka failed) 467f396ca7Spooka atf_skip "Unknown error trying to access /dev/puffs" 477f396ca7Spooka ;; 487f396ca7Spooka yes) 497f396ca7Spooka ;; 507f396ca7Spooka *) 517f396ca7Spooka atf_fail "Unknown value returned by h_have_puffs" 527f396ca7Spooka ;; 537f396ca7Spooka esac 547f396ca7Spooka 557f396ca7Spooka if [ $(id -u) -ne 0 -a $(sysctl -n vfs.generic.usermount) -eq 0 ] 567f396ca7Spooka then 577f396ca7Spooka atf_skip "Regular users cannot mount file systems" \ 587f396ca7Spooka "(vfs.generic.usermount is set to 0)" 597f396ca7Spooka fi 607f396ca7Spooka} 617f396ca7Spooka 627f396ca7Spooka# 637f396ca7Spooka# Starts a SSH server and sets up the client to access it. 647f396ca7Spooka# Authentication is allowed and done using an RSA key exclusively, which 657f396ca7Spooka# is generated on the fly as part of the test case. 667f396ca7Spooka# XXX: Ideally, all the tests in this test program should be able to share 677f396ca7Spooka# the generated key, because creating it can be a very slow process on some 687f396ca7Spooka# machines. 697f396ca7Spooka# 707f396ca7Spookastart_ssh() { 717f396ca7Spooka echo "Setting up SSH server configuration" 727f396ca7Spooka sed -e "s,@SRCDIR@,$(atf_get_srcdir),g" -e "s,@WORKDIR@,$(pwd),g" \ 737f396ca7Spooka $(atf_get_srcdir)/sshd_config.in >sshd_config || \ 747f396ca7Spooka atf_fail "Failed to create sshd_config" 75*d8f5b04cSrillig atf_check -s exit:0 -o empty -e empty cp /usr/libexec/sftp-server . 76*d8f5b04cSrillig atf_check -s exit:0 -o empty -e empty \ 777f396ca7Spooka cp $(atf_get_srcdir)/ssh_host_key . 78*d8f5b04cSrillig atf_check -s exit:0 -o empty -e empty \ 797f396ca7Spooka cp $(atf_get_srcdir)/ssh_host_key.pub . 80*d8f5b04cSrillig atf_check -s exit:0 -o empty -e empty chmod 400 ssh_host_key 81*d8f5b04cSrillig atf_check -s exit:0 -o empty -e empty chmod 444 ssh_host_key.pub 827f396ca7Spooka 83bec0b44fSpooka /usr/sbin/sshd -e -f ./sshd_config >sshd.log 2>&1 & 84bec0b44fSpooka while [ ! -f sshd.pid ]; do 85bec0b44fSpooka sleep 0.01 86bec0b44fSpooka done 877f396ca7Spooka echo "SSH server started (pid $(cat sshd.pid))" 887f396ca7Spooka 897f396ca7Spooka echo "Setting up SSH client configuration" 90*d8f5b04cSrillig atf_check -s exit:0 -o empty -e empty \ 917f396ca7Spooka ssh-keygen -f ssh_user_key -t rsa -b 1024 -N "" -q 92*d8f5b04cSrillig atf_check -s exit:0 -o empty -e empty \ 937f396ca7Spooka cp ssh_user_key.pub authorized_keys 947f396ca7Spooka echo "[localhost]:10000,[127.0.0.1]:10000,[::1]:10000" \ 957f396ca7Spooka "$(cat $(atf_get_srcdir)/ssh_host_key.pub)" >known_hosts || \ 967f396ca7Spooka atf_fail "Failed to create known_hosts" 97*d8f5b04cSrillig atf_check -s exit:0 -o empty -e empty chmod 600 authorized_keys 987f396ca7Spooka sed -e "s,@SRCDIR@,$(atf_get_srcdir),g" -e "s,@WORKDIR@,$(pwd),g" \ 997f396ca7Spooka $(atf_get_srcdir)/ssh_config.in >ssh_config || \ 1007f396ca7Spooka atf_fail "Failed to create ssh_config" 1017f396ca7Spooka} 1027f396ca7Spooka 1037f396ca7Spooka# 1047f396ca7Spooka# Stops the SSH server spawned by start_ssh and prints diagnosis data. 1057f396ca7Spooka# 1067f396ca7Spookastop_ssh() { 1077f396ca7Spooka if [ -f sshd.pid ]; then 1087f396ca7Spooka echo "Stopping SSH server (pid $(cat sshd.pid))" 1097f396ca7Spooka kill $(cat sshd.pid) 1107f396ca7Spooka fi 1117f396ca7Spooka if [ -f sshd.log ]; then 1127f396ca7Spooka echo "Server output was:" 1137f396ca7Spooka sed -e 's,^, ,' sshd.log 1147f396ca7Spooka fi 1157f396ca7Spooka} 1167f396ca7Spooka 1177f396ca7Spooka# 1187f396ca7Spooka# Mounts the given source directory on the target directory using psshfs. 1197f396ca7Spooka# Both directories are supposed to live on the current directory. 1207f396ca7Spooka# 1217f396ca7Spookamount_psshfs() { 122*d8f5b04cSrillig atf_check -s exit:0 -o empty -e empty \ 1237f396ca7Spooka mount -t psshfs -o -F=$(pwd)/ssh_config localhost:$(pwd)/${1} ${2} 1247f396ca7Spooka} 1257f396ca7Spooka 1267f396ca7Spooka# ------------------------------------------------------------------------- 1277f396ca7Spooka# The test cases. 1287f396ca7Spooka# ------------------------------------------------------------------------- 1297f396ca7Spooka 1307f396ca7Spookaatf_test_case inode_nos cleanup 1317f396ca7Spookainode_nos_head() { 1327f396ca7Spooka atf_set "descr" "Checks that different files get different inode" \ 1337f396ca7Spooka "numbers" 1347f396ca7Spooka} 1357f396ca7Spookainode_nos_body() { 1367f396ca7Spooka require_puffs 1377f396ca7Spooka 1387f396ca7Spooka start_ssh 1397f396ca7Spooka 1407f396ca7Spooka mkdir root 1417f396ca7Spooka mkdir root/dir 1427f396ca7Spooka touch root/dir/file1 1437f396ca7Spooka touch root/dir/file2 1447f396ca7Spooka touch root/file3 1457f396ca7Spooka touch root/file4 1467f396ca7Spooka 1477f396ca7Spooka cat >ne_inodes.sh <<EOF 1486005599cSjmmv#! /bin/sh 1497f396ca7Spooka# 1507f396ca7Spooka# Compares the inodes of the two given files and returns true if they are 1517f396ca7Spooka# different; false otherwise. 1527f396ca7Spooka# 153471b2e43Spookaset -e 154471b2e43Spookaino1=\$(stat -f %i \${1}) 155471b2e43Spookaino2=\$(stat -f %i \${2}) 156471b2e43Spookatest \${ino1} -ne \${ino2} 1577f396ca7SpookaEOF 1587f396ca7Spooka chmod +x ne_inodes.sh 1597f396ca7Spooka 1607f396ca7Spooka mkdir mnt 1617f396ca7Spooka mount_psshfs root mnt 162*d8f5b04cSrillig atf_check -s exit:0 -o empty -e empty \ 1637f396ca7Spooka ./ne_inodes.sh root/dir root/dir/file1 164*d8f5b04cSrillig atf_check -s exit:0 -o empty -e empty \ 1657f396ca7Spooka ./ne_inodes.sh root/dir root/dir/file2 166*d8f5b04cSrillig atf_check -s exit:0 -o empty -e empty \ 1677f396ca7Spooka ./ne_inodes.sh root/dir/file1 root/dir/file2 168*d8f5b04cSrillig atf_check -s exit:0 -o empty -e empty \ 1697f396ca7Spooka ./ne_inodes.sh root/file3 root/file4 1707f396ca7Spooka} 1717f396ca7Spookainode_nos_cleanup() { 1727f396ca7Spooka umount mnt 1737f396ca7Spooka stop_ssh 1747f396ca7Spooka} 1757f396ca7Spooka 1767f396ca7Spookaatf_test_case pwd cleanup 1777f396ca7Spookapwd_head() { 1787f396ca7Spooka atf_set "descr" "Checks that pwd works correctly" 1797f396ca7Spooka} 1807f396ca7Spookapwd_body() { 1817f396ca7Spooka require_puffs 1827f396ca7Spooka 1837f396ca7Spooka start_ssh 1847f396ca7Spooka 1857f396ca7Spooka mkdir root 1867f396ca7Spooka mkdir root/dir 1877f396ca7Spooka 1887f396ca7Spooka mkdir mnt 189*d8f5b04cSrillig atf_check -s exit:0 -o save:stdout -e empty \ 1907f396ca7Spooka -x 'echo $(cd mnt && /bin/pwd)/dir' 1917f396ca7Spooka mv stdout expout 1927f396ca7Spooka mount_psshfs root mnt 193*d8f5b04cSrillig atf_check -s exit:0 -o file:expout -e empty \ 1947f396ca7Spooka -x 'cd mnt/dir && ls .. >/dev/null && /bin/pwd' 1957f396ca7Spooka} 1967f396ca7Spookapwd_cleanup() { 1977f396ca7Spooka umount mnt 1987f396ca7Spooka stop_ssh 1997f396ca7Spooka} 2007f396ca7Spooka 201edeb44ccSpookaatf_test_case ls cleanup 202edeb44ccSpookals_head() { 203edeb44ccSpooka atf_set "descr" "Uses ls, attempts to exercise puffs_cc" 204edeb44ccSpooka} 205edeb44ccSpookals_body() { 206edeb44ccSpooka require_puffs 207edeb44ccSpooka 208edeb44ccSpooka start_ssh 209edeb44ccSpooka 210edeb44ccSpooka mkdir mnt 211edeb44ccSpooka mkdir root 212edeb44ccSpooka mkdir root/dir 213edeb44ccSpooka touch root/dir/file1 214edeb44ccSpooka touch root/dir/file2 215edeb44ccSpooka touch root/file3 216edeb44ccSpooka touch root/file4 217edeb44ccSpooka 218edeb44ccSpooka mount_psshfs root mnt 219edeb44ccSpooka 220edeb44ccSpooka ls -l mnt & 221edeb44ccSpooka 222edeb44ccSpooka IFS=' ' 223edeb44ccSpookalsout='dir 224edeb44ccSpookafile3 225edeb44ccSpookafile4 226edeb44ccSpooka 227edeb44ccSpookamnt/dir: 228edeb44ccSpookafile1 229edeb44ccSpookafile2 230edeb44ccSpooka' 231edeb44ccSpooka atf_check -s exit:0 -o inline:"$lsout" ls -R mnt 232edeb44ccSpooka} 233edeb44ccSpookals_cleanup() { 234edeb44ccSpooka umount mnt 235edeb44ccSpooka stop_ssh 236edeb44ccSpooka} 237edeb44ccSpooka 238772f45cfSriastradhatf_test_case setattr_cache cleanup 239772f45cfSriastradhsetattr_cache_head() { 240772f45cfSriastradh atf_set "descr" "Checks that setattr caches" 241772f45cfSriastradh # Don't wait for the eternity that atf usually waits. Twenty 242772f45cfSriastradh # seconds should be good enough, except maybe on a VAX... 243772f45cfSriastradh atf_set "timeout" 20 244772f45cfSriastradh} 245772f45cfSriastradhsetattr_cache_body() { 246772f45cfSriastradh require_puffs 247772f45cfSriastradh start_ssh 248772f45cfSriastradh atf_check -s exit:0 mkdir root 249772f45cfSriastradh atf_check -s exit:0 mkdir mnt 250772f45cfSriastradh mount_psshfs root mnt 251772f45cfSriastradh atf_check -s exit:0 -x ': > mnt/loser' 252772f45cfSriastradh atf_check -s exit:0 -o save:stat stat mnt/loser 253772f45cfSriastradh # Oops -- this doesn't work. We need to stop the child of the 254772f45cfSriastradh # sshd that is handling the sftp session. 255772f45cfSriastradh atf_check -s exit:0 kill -STOP $(cat sshd.pid) 256772f45cfSriastradh atf_check -s exit:0 -x ': > mnt/loser' 257772f45cfSriastradh atf_check -s exit:0 -o file:stat stat mnt/loser 258772f45cfSriastradh} 259772f45cfSriastradhsetattr_cache_cleanup() { 260772f45cfSriastradh umount mnt 261772f45cfSriastradh kill -CONT $(cat sshd.pid) 262772f45cfSriastradh stop_ssh 263772f45cfSriastradh} 264772f45cfSriastradh 265781b35a2Schristosatf_test_case read_empty_file cleanup 266781b35a2Schristosread_empty_file_head() { 267781b35a2Schristos atf_set "descr" "Checks whether an empty file can be read" 268781b35a2Schristos # This test is supposed to make sure psshfs does not hang 269781b35a2Schristos # when reading from an empty file, hence the timeout. 270f54caa8bSchristos atf_set "timeout" 60 271781b35a2Schristos} 272781b35a2Schristosread_empty_file_body() { 273781b35a2Schristos require_puffs 274781b35a2Schristos start_ssh 275781b35a2Schristos atf_check mkdir root mnt 276781b35a2Schristos atf_check -x ': > root/empty' 277781b35a2Schristos mount_psshfs root mnt 278781b35a2Schristos atf_check cat mnt/empty 279781b35a2Schristos} 280781b35a2Schristosread_empty_file_cleanup() { 281781b35a2Schristos umount mnt 282781b35a2Schristos stop_ssh 283781b35a2Schristos} 284781b35a2Schristos 2857f396ca7Spooka# ------------------------------------------------------------------------- 2867f396ca7Spooka# Initialization. 2877f396ca7Spooka# ------------------------------------------------------------------------- 2887f396ca7Spooka 2897f396ca7Spookaatf_init_test_cases() { 2907f396ca7Spooka atf_add_test_case inode_nos 2917f396ca7Spooka atf_add_test_case pwd 292edeb44ccSpooka atf_add_test_case ls 293772f45cfSriastradh #atf_add_test_case setattr_cache 294781b35a2Schristos atf_add_test_case read_empty_file 2957f396ca7Spooka} 296