1*a678e87fSDag-Erling Smørgrav#!/bin/sh 2*a678e87fSDag-Erling Smørgrav#- 3*a678e87fSDag-Erling Smørgrav# SPDX-License-Identifier: BSD-2-Clause 4*a678e87fSDag-Erling Smørgrav# 5*a678e87fSDag-Erling Smørgrav# Copyright (c) 2025 Klara, Inc. 6*a678e87fSDag-Erling Smørgrav# 7*a678e87fSDag-Erling Smørgrav# Redistribution and use in source and binary forms, with or without 8*a678e87fSDag-Erling Smørgrav# modification, are permitted provided that the following conditions 9*a678e87fSDag-Erling Smørgrav# are met: 10*a678e87fSDag-Erling Smørgrav# 1. Redistributions of source code must retain the above copyright 11*a678e87fSDag-Erling Smørgrav# notice, this list of conditions and the following disclaimer. 12*a678e87fSDag-Erling Smørgrav# 2. Redistributions in binary form must reproduce the above copyright 13*a678e87fSDag-Erling Smørgrav# notice, this list of conditions and the following disclaimer in the 14*a678e87fSDag-Erling Smørgrav# documentation and/or other materials provided with the distribution. 15*a678e87fSDag-Erling Smørgrav# 16*a678e87fSDag-Erling Smørgrav# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17*a678e87fSDag-Erling Smørgrav# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18*a678e87fSDag-Erling Smørgrav# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19*a678e87fSDag-Erling Smørgrav# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20*a678e87fSDag-Erling Smørgrav# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21*a678e87fSDag-Erling Smørgrav# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22*a678e87fSDag-Erling Smørgrav# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23*a678e87fSDag-Erling Smørgrav# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24*a678e87fSDag-Erling Smørgrav# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25*a678e87fSDag-Erling Smørgrav# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26*a678e87fSDag-Erling Smørgrav# SUCH DAMAGE. 27*a678e87fSDag-Erling Smørgrav# 28*a678e87fSDag-Erling Smørgrav 29*a678e87fSDag-Erling Smørgrav# Create and mount a filesystem for use in our tests 30*a678e87fSDag-Erling Smørgravunionfs_mkfs() { 31*a678e87fSDag-Erling Smørgrav local name=$1 32*a678e87fSDag-Erling Smørgrav local size=${2:-1} 33*a678e87fSDag-Erling Smørgrav # Create mountpoint 34*a678e87fSDag-Erling Smørgrav atf_check mkdir ${name} 35*a678e87fSDag-Erling Smørgrav # Create filesystem image 36*a678e87fSDag-Erling Smørgrav atf_check -e ignore dd if=/dev/zero of=${name}.img bs=1m count=${size} 37*a678e87fSDag-Erling Smørgrav echo ${name} >>imgs 38*a678e87fSDag-Erling Smørgrav # Create memory disk 39*a678e87fSDag-Erling Smørgrav atf_check -o save:${name}.md mdconfig ${name}.img 40*a678e87fSDag-Erling Smørgrav md=$(cat ${name}.md) 41*a678e87fSDag-Erling Smørgrav echo ${md} >>mds 42*a678e87fSDag-Erling Smørgrav # Format and mount filesystem 43*a678e87fSDag-Erling Smørgrav atf_check -o ignore newfs /dev/${md} 44*a678e87fSDag-Erling Smørgrav atf_check mount /dev/${md} ${name} 45*a678e87fSDag-Erling Smørgrav echo ${name} >>mounts 46*a678e87fSDag-Erling Smørgrav} 47*a678e87fSDag-Erling Smørgrav 48*a678e87fSDag-Erling Smørgrav# Mount a unionfs 49*a678e87fSDag-Erling Smørgravunionfs_mount() { 50*a678e87fSDag-Erling Smørgrav local upper=$1 51*a678e87fSDag-Erling Smørgrav local lower=$2 52*a678e87fSDag-Erling Smørgrav # Mount upper over lower 53*a678e87fSDag-Erling Smørgrav atf_check mount -t unionfs ${upper} ${lower} 54*a678e87fSDag-Erling Smørgrav echo ${lower} >>mounts 55*a678e87fSDag-Erling Smørgrav} 56*a678e87fSDag-Erling Smørgrav 57*a678e87fSDag-Erling Smørgrav# Clean up after a test 58*a678e87fSDag-Erling Smørgravunionfs_cleanup() { 59*a678e87fSDag-Erling Smørgrav # Unmount filesystems 60*a678e87fSDag-Erling Smørgrav if [ -f mounts ]; then 61*a678e87fSDag-Erling Smørgrav tail -r mounts | while read mount; do 62*a678e87fSDag-Erling Smørgrav umount ${mount} || true 63*a678e87fSDag-Erling Smørgrav done 64*a678e87fSDag-Erling Smørgrav fi 65*a678e87fSDag-Erling Smørgrav # Destroy memory disks 66*a678e87fSDag-Erling Smørgrav if [ -f mds ]; then 67*a678e87fSDag-Erling Smørgrav tail -r mds | while read md; do 68*a678e87fSDag-Erling Smørgrav mdconfig -d -u ${md} || true 69*a678e87fSDag-Erling Smørgrav done 70*a678e87fSDag-Erling Smørgrav fi 71*a678e87fSDag-Erling Smørgrav # Delete filesystem images and mountpoints 72*a678e87fSDag-Erling Smørgrav if [ -f imgs ]; then 73*a678e87fSDag-Erling Smørgrav tail -r imgs | while read name; do 74*a678e87fSDag-Erling Smørgrav rm -f ${name}.img || true 75*a678e87fSDag-Erling Smørgrav rmdir ${name} || true 76*a678e87fSDag-Erling Smørgrav done 77*a678e87fSDag-Erling Smørgrav fi 78*a678e87fSDag-Erling Smørgrav} 79*a678e87fSDag-Erling Smørgrav 80*a678e87fSDag-Erling Smørgravatf_test_case unionfs_basic cleanup 81*a678e87fSDag-Erling Smørgravunionfs_basic_head() { 82*a678e87fSDag-Erling Smørgrav atf_set "descr" "Basic function test" 83*a678e87fSDag-Erling Smørgrav atf_set "require.user" "root" 84*a678e87fSDag-Erling Smørgrav atf_set "require.kmods" "unionfs" 85*a678e87fSDag-Erling Smørgrav} 86*a678e87fSDag-Erling Smørgravunionfs_basic_body() { 87*a678e87fSDag-Erling Smørgrav # Create upper and lower 88*a678e87fSDag-Erling Smørgrav unionfs_mkfs upper 89*a678e87fSDag-Erling Smørgrav unionfs_mkfs lower 90*a678e87fSDag-Erling Smørgrav # Mount upper over lower 91*a678e87fSDag-Erling Smørgrav unionfs_mount upper lower 92*a678e87fSDag-Erling Smørgrav # Create object on unionfs 93*a678e87fSDag-Erling Smørgrav atf_check touch upper/file 94*a678e87fSDag-Erling Smørgrav atf_check mkdir upper/dir 95*a678e87fSDag-Erling Smørgrav atf_check touch lower/dir/file 96*a678e87fSDag-Erling Smørgrav # Verify that objects were created on upper 97*a678e87fSDag-Erling Smørgrav atf_check test -f lower/file 98*a678e87fSDag-Erling Smørgrav atf_check test -d lower/dir 99*a678e87fSDag-Erling Smørgrav atf_check test -f upper/dir/file 100*a678e87fSDag-Erling Smørgrav} 101*a678e87fSDag-Erling Smørgravunionfs_basic_cleanup() { 102*a678e87fSDag-Erling Smørgrav unionfs_cleanup 103*a678e87fSDag-Erling Smørgrav} 104*a678e87fSDag-Erling Smørgrav 105*a678e87fSDag-Erling Smørgravatf_test_case unionfs_exec cleanup 106*a678e87fSDag-Erling Smørgravunionfs_exec_head() { 107*a678e87fSDag-Erling Smørgrav atf_set "descr" "Test executing programs" 108*a678e87fSDag-Erling Smørgrav atf_set "require.user" "root" 109*a678e87fSDag-Erling Smørgrav atf_set "require.kmods" "unionfs" 110*a678e87fSDag-Erling Smørgrav} 111*a678e87fSDag-Erling Smørgravunionfs_exec_body() { 112*a678e87fSDag-Erling Smørgrav # Create upper and copy a binary to it 113*a678e87fSDag-Erling Smørgrav unionfs_mkfs upper 114*a678e87fSDag-Erling Smørgrav atf_check cp -p /usr/bin/true upper/upper 115*a678e87fSDag-Erling Smørgrav # Create lower and copy a binary to it 116*a678e87fSDag-Erling Smørgrav unionfs_mkfs lower 117*a678e87fSDag-Erling Smørgrav atf_check cp -p /usr/bin/true lower/lower 118*a678e87fSDag-Erling Smørgrav # Mount upper over lower 119*a678e87fSDag-Erling Smørgrav unionfs_mount upper lower 120*a678e87fSDag-Erling Smørgrav # Execute both binaries 121*a678e87fSDag-Erling Smørgrav atf_check lower/lower 122*a678e87fSDag-Erling Smørgrav atf_check lower/upper 123*a678e87fSDag-Erling Smørgrav} 124*a678e87fSDag-Erling Smørgravunionfs_exec_cleanup() { 125*a678e87fSDag-Erling Smørgrav unionfs_cleanup 126*a678e87fSDag-Erling Smørgrav} 127*a678e87fSDag-Erling Smørgrav 128*a678e87fSDag-Erling Smørgravatf_test_case unionfs_rename cleanup 129*a678e87fSDag-Erling Smørgravunionfs_rename_head() { 130*a678e87fSDag-Erling Smørgrav atf_set "descr" "Test renaming objects on lower" 131*a678e87fSDag-Erling Smørgrav atf_set "require.user" "root" 132*a678e87fSDag-Erling Smørgrav atf_set "require.kmods" "unionfs" 133*a678e87fSDag-Erling Smørgrav} 134*a678e87fSDag-Erling Smørgravunionfs_rename_body() { 135*a678e87fSDag-Erling Smørgrav # Create upper and lower 136*a678e87fSDag-Erling Smørgrav unionfs_mkfs upper 137*a678e87fSDag-Erling Smørgrav unionfs_mkfs lower 138*a678e87fSDag-Erling Smørgrav # Create objects on lower 139*a678e87fSDag-Erling Smørgrav atf_check touch lower/file 140*a678e87fSDag-Erling Smørgrav atf_check mkdir lower/dir 141*a678e87fSDag-Erling Smørgrav atf_check ln -s dead lower/link 142*a678e87fSDag-Erling Smørgrav # Mount upper over lower 143*a678e87fSDag-Erling Smørgrav unionfs_mount upper lower 144*a678e87fSDag-Erling Smørgrav # Rename objects 145*a678e87fSDag-Erling Smørgrav atf_check mv lower/file lower/newfile 146*a678e87fSDag-Erling Smørgrav atf_check mv lower/dir lower/newdir 147*a678e87fSDag-Erling Smørgrav atf_check mv lower/link lower/newlink 148*a678e87fSDag-Erling Smørgrav # Verify that old names no longer exist 149*a678e87fSDag-Erling Smørgrav atf_check test ! -f lower/file 150*a678e87fSDag-Erling Smørgrav atf_check test ! -d lower/dir 151*a678e87fSDag-Erling Smørgrav atf_check test ! -L lower/link 152*a678e87fSDag-Erling Smørgrav # Verify that new names exist on upper 153*a678e87fSDag-Erling Smørgrav atf_check test -f upper/newfile 154*a678e87fSDag-Erling Smørgrav atf_check test -d upper/newdir 155*a678e87fSDag-Erling Smørgrav atf_check test -L upper/newlink 156*a678e87fSDag-Erling Smørgrav} 157*a678e87fSDag-Erling Smørgravunionfs_rename_cleanup() { 158*a678e87fSDag-Erling Smørgrav unionfs_cleanup 159*a678e87fSDag-Erling Smørgrav} 160*a678e87fSDag-Erling Smørgrav 161*a678e87fSDag-Erling Smørgravatf_init_test_cases() { 162*a678e87fSDag-Erling Smørgrav atf_add_test_case unionfs_basic 163*a678e87fSDag-Erling Smørgrav atf_add_test_case unionfs_exec 164*a678e87fSDag-Erling Smørgrav atf_add_test_case unionfs_rename 165*a678e87fSDag-Erling Smørgrav} 166