aboutsummaryrefslogtreecommitdiffstats
path: root/common/renameat2
blob: 9737dff54a2bb4f1018bdf2b7747da15cd16c49d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
##/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2014 Miklos Szeredi.  All Rights Reserved.
#
# renameat2 helpers

# Setup source or dest
#
_setup_one()
{
	local path=$1
	local type=$2

	case $type in
		none)	;;
		regu)	echo foo > $path;;
		symb)	ln -s foo $path;;
		dire)	mkdir $path;;
		tree)	mkdir $path; echo foo > $path/bar;;
	esac
}

#
# Cleanup source or dest
#
_cleanup_one()
{
	local path=$1

	if test -d $path; then
		rm -f $path/bar
		rmdir $path
	else
		rm -f $path
	fi
}

#
# Check type of source or destination
#
_showtype_one()
{
	local path=$1

	if test -e $path -o -h $path; then
		if test -d $path -a -e $path/bar; then
			echo -n "tree"
		else
			echo -n `stat -c %F $path | cut -b-4`
		fi
	else
		echo -n "none"
	fi
}

#
# This runs renameat2 on all combinations of source and dest
#
_rename_tests_source_dest()
{
	local source=$1
	local dest=$2
	local options=$3
	local flags=$4

	for stype in none regu symb dire tree; do
		for dtype in none regu symb dire tree; do
			echo -n "$options $stype/$dtype -> "
			_setup_one $source $stype
			_setup_one $dest $dtype
			$here/src/renameat2 $source $dest $flags
			if test $? == 0; then
				_showtype_one $source
				echo -n "/"
				_showtype_one $dest
				echo "."
			fi
			_cleanup_one $source
			_cleanup_one $dest
		done
	done
}

#
# This runs _rename_tests_source_dest() for both same-directory and
# cross-directory renames
#
_rename_tests()
{
	local testdir=$1
	local flags=$2

	#same directory renames
	_rename_tests_source_dest $testdir/src $testdir/dst     "samedir " $flags

	#cross directory renames
	mkdir $testdir/x $testdir/y
	_rename_tests_source_dest $testdir/x/src $testdir/y/dst "crossdir" $flags
	rmdir $testdir/x $testdir/y
}

#
# This checks whether the renameat2 syscall is supported
#
_require_renameat2()
{
	local flags=$1
	local rename_dir=`mktemp -d -p $TEST_DIR`
	local cmd=""

	if test ! -x $here/src/renameat2; then
		_notrun "renameat2 binary not found"
	fi

	touch $rename_dir/foo
	case $flags in
	"noreplace")
		cmd="-n $rename_dir/foo $rename_dir/bar"
		;;
	"exchange")
		touch $rename_dir/bar
		cmd="-x $rename_dir/foo $rename_dir/bar"
		;;
	"whiteout")
		touch $rename_dir/bar
		cmd="-w $rename_dir/foo $rename_dir/bar"
		;;
	"")
		cmd=""
		;;
	*)
		rm -rf $rename_dir
		_fail "_require_renameat2: only support noreplace,exchange,whiteout rename flags"
		;;
	esac
	if ! $here/src/renameat2 -t $cmd; then
		rm -rf $rename_dir
		_notrun "kernel doesn't support renameat2 syscall"
	fi
	rm -rf $rename_dir
}