tombstones-expunge: Add a test for deleting links to recycled objects
[Samba.git] / source3 / script / tests / test_shadow_copy.sh
blob783e7f324a6c504ed29013f5bf8b16036c579c4f
1 #!/bin/bash
3 # Blackbox test for shadow_copy2 VFS.
6 if [ $# -lt 7 ]; then
7 cat <<EOF
8 Usage: test_shadow_copy SERVER SERVER_IP DOMAIN USERNAME PASSWORD WORKDIR SMBCLIENT PARAMS
9 EOF
10 exit 1;
13 SERVER=${1}
14 SERVER_IP=${2}
15 DOMAIN=${3}
16 USERNAME=${4}
17 PASSWORD=${5}
18 WORKDIR=${6}
19 SMBCLIENT=${7}
20 shift 7
21 ADDARGS="$*"
22 SMBCLIENT="$VALGRIND ${SMBCLIENT} ${ADDARGS}"
24 incdir=`dirname $0`/../../../testprogs/blackbox
25 . $incdir/subunit.sh
27 SNAPSHOTS[0]='@GMT-2015.10.31-19.40.30'
28 SNAPSHOTS[1]='@GMT-2016.10.31-19.40.30'
29 SNAPSHOTS[2]='@GMT-2017.10.31-19.40.30'
30 SNAPSHOTS[3]='@GMT-2018.10.31-19.40.30'
31 SNAPSHOTS[4]='@GMT-2019.10.31-19.40.30'
32 SNAPSHOTS[5]='@GMT-2020.10.31-19.40.30'
33 SNAPSHOTS[6]='@GMT-2021.10.31-19.40.30'
34 SNAPSHOTS[7]='@GMT-2022.10.31-19.40.30'
35 SNAPSHOTS[8]='@GMT-2023.10.31-19.40.30'
36 SNAPSHOTS[9]='@GMT-2024.10.31-19.40.30'
37 SNAPSHOTS[10]='@GMT-2010-11-11'
38 SNAPSHOTS[11]='@GMT-2011.11.11-11.40.30'
39 SNAPSHOTS[12]='snap@GMT-2012.11.11-11.40.30'
40 SNAPSHOTS[13]='@GMT-2013.11.11-11_40_33-snap'
41 SNAPSHOTS[14]='@GMT-2014.11.11-11.40.30'
42 SNAPSHOTS[15]='daily@GMT-2015.11.11-11.40.30'
43 SNAPSHOTS[16]='snap_GMT-2016.11.11-11.40.30'
44 SNAPSHOTS[17]='sysp_GMT-2017.11.11-11.40.30'
45 SNAPSHOTS[18]='monthly@GMT-2018.11.11-11.40.30'
46 SNAPSHOTS[19]='straps_GMT-2019.11.11-11.40.33'
48 # build a hierarchy of files, symlinks, and directories
49 build_files()
51 local rootdir
52 local prefix
53 local version
54 local destdir
55 local content
56 rootdir=$1
57 prefix=$2
58 version=$3
59 content=$4
60 if [ -n "$prefix" ] ; then
61 destdir=$rootdir/$prefix
62 else
63 destdir=$rootdir
66 mkdir -p $destdir
67 if [ "$version" = "latest" ] ; then
68 #non-snapshot files
69 # for non-snapshot version, create legit files
70 # so that wide-link checks focus on snapshot files
71 echo "$content" > $destdir/foo
72 mkdir -p $destdir/bar
73 echo "$content" > $destdir/bar/baz
74 echo "$content" > $destdir/bar/lfoo
75 echo "$content" > $destdir/bar/letcpasswd
76 echo "$content" > $destdir/bar/loutside
77 elif [ "$version" = "fullsnap" ] ; then
78 #snapshot files
79 echo "$content" > $destdir/foo
80 mkdir -p $destdir/bar
81 echo "$content" > $destdir/bar/baz
82 ln -fs ../foo $destdir/bar/lfoo
83 ln -fs /etc/passwd $destdir/bar/letcpasswd
84 ln -fs ../../outside $destdir/bar/loutside
85 echo "$content" > `dirname $destdir`/outside
86 else #subshare snapshot - at bar
87 echo "$content" > $destdir/baz
88 ln -fs ../foo $destdir/lfoo
89 ln -fs /etc/passwd $destdir/letcpasswd
90 ln -fs ../../outside $destdir/loutside
91 echo "$content" > `dirname $destdir`/../outside
96 # build a snapshots directory
97 build_snapshots()
99 local where #where to build snapshots
100 local prefix #prefix from snapshot dir to share root
101 local start #timestamp index of first snapshot
102 local end #timestamp index of last snapshot
103 local sub #creat a snapshot of subtree of share
104 local snapdir
105 local snapname
106 local i
107 local version
109 where=$1
110 prefix=$2
111 start=$3
112 end=$4
113 sub=$5
115 snapdir=$where/.snapshots
116 mkdir -p $snapdir
118 version="fullsnap"
119 if [ "$sub" = "1" ] ; then
120 version="subsnap"
121 prefix=""
123 # a valid link target for an inner symlink -
124 # the link is not broken yet should be blocked
125 # by wide link checks
126 touch $snapdir/foo
129 for i in `seq $start $end` ; do
130 snapname=${SNAPSHOTS[$i]}
131 mkdir $snapdir/$snapname
132 build_files $snapdir/$snapname "$prefix" $version "$snapname"
133 done
136 # Test listing previous versions of a file
137 test_count_versions()
139 local share
140 local path
141 local expected_count
142 local skip_content
143 local versions
144 local tstamps
145 local tstamp
146 local content
147 local is_dir
149 share=$1
150 path=$2
151 expected_count=$3
152 skip_content=$4
153 versions=`$SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "allinfo $path" | grep "^create_time:" | wc -l`
154 if [ "$versions" != "$expected_count" ] ; then
155 echo "expected $expected_count versions of $path, got $versions"
156 return 1
159 is_dir=0
160 $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "allinfo $path" | grep "^attributes:.*D" && is_dir=1
161 if [ $is_dir = 1 ] ; then
162 skip_content=1
165 #readable snapshots
166 tstamps=`$SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "allinfo $path" | awk '/^@GMT-/ {snapshot=$1} /^create_time:/ {printf "%s\n", snapshot}'`
167 for tstamp in $tstamps ; do
168 if [ $is_dir = 0 ] ;
169 then
170 if ! $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "get $tstamp\\$path $WORKDIR/foo" ; then
171 echo "Failed getting \\\\$SERVER\\$share\\$tstamp\\$path"
172 return 1
174 else
175 if ! $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "ls $tstamp\\$path\\*" ; then
176 echo "Failed listing \\\\$SERVER\\$share\\$tstamp\\$path"
177 return 1
181 #also check the content, but not for wide links
182 if [ "x$skip_content" != "x1" ] ; then
183 content=`cat $WORKDIR/foo`
184 if [ "$content" != "$tstamp" ] ; then
185 echo "incorrect content of \\\\$SERVER\\$share\\$tstamp\\$path expected [$tstamp] got [$content]"
186 return 1
189 done
191 #non-readable snapshots
192 tstamps=`$SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "allinfo $path" | \
193 awk '/^@GMT-/ {if (snapshot!=""){printf "%s\n", snapshot} ; snapshot=$1} /^create_time:/ {snapshot=""} END {if (snapshot!=""){printf "%s\n", snapshot}}'`
194 for tstamp in $tstamps ; do
195 if [ $is_dir = 0 ] ;
196 then
197 if $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "get $tstamp\\$path $WORKDIR/foo" ; then
198 echo "Unexpected success getting \\\\$SERVER\\$share\\$tstamp\\$path"
199 return 1
201 else
202 if $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "ls $tstamp\\$path\\*" ; then
203 echo "Unexpected success listing \\\\$SERVER\\$share\\$tstamp\\$path"
204 return 1
207 done
210 # Test fetching a previous version of a file
211 test_fetch_snap_file()
213 local share
214 local path
215 local snapidx
217 share=$1
218 path=$2
219 snapidx=$3
220 $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP \
221 -c "get ${SNAPSHOTS[$snapidx]}/$path $WORKDIR/foo"
224 test_shadow_copy_fixed()
226 local share #share to contact
227 local where #where to place snapshots
228 local prefix #prefix to files inside snapshot
229 local msg
230 local allow_wl
231 local ncopies_allowd
232 local ncopies_blocked
234 share=$1
235 where=$2
236 prefix=$3
237 msg=$4
238 allow_wl=$5
240 ncopies_allowed=4
241 ncopies_blocked=1
242 if [ -n "$allow_wl" ] ; then
243 ncopies_blocked=4
246 #delete snapshots from previous tests
247 find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1
248 build_snapshots $WORKDIR/$where "$prefix" 0 2
250 testit "$msg - regular file" \
251 test_count_versions $share foo $ncopies_allowed || \
252 failed=`expr $failed + 1`
254 testit "$msg - regular file in subdir" \
255 test_count_versions $share bar/baz $ncopies_allowed || \
256 failed=`expr $failed + 1`
258 testit "$msg - local symlink" \
259 test_count_versions $share bar/lfoo $ncopies_allowed || \
260 failed=`expr $failed + 1`
262 testit "$msg - abs symlink outside" \
263 test_count_versions $share bar/letcpasswd $ncopies_blocked 1 || \
264 failed=`expr $failed + 1`
266 testit "$msg - rel symlink outside" \
267 test_count_versions $share bar/loutside $ncopies_blocked 1 || \
268 failed=`expr $failed + 1`
270 testit "$msg - list directory" \
271 test_count_versions $share bar $ncopies_allowed || \
272 failed=`expr $failed + 1`
275 test_shadow_copy_everywhere()
277 local share #share to contact
279 share=$1
281 #delete snapshots from previous tests
282 find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1
283 build_snapshots "$WORKDIR/mount" "base/share" 0 0
284 build_snapshots "$WORKDIR/mount/base" "share" 1 2
285 build_snapshots "$WORKDIR/mount/base/share" "" 3 5
286 build_snapshots "$WORKDIR/mount/base/share/bar" "" 6 9 1
288 testit "snapshots in each dir - regular file" \
289 test_count_versions $share foo 4 || \
290 failed=`expr $failed + 1`
292 testit "snapshots in each dir - regular file in subdir" \
293 test_count_versions $share bar/baz 5 || \
294 failed=`expr $failed + 1`
296 testit "snapshots in each dir - local symlink (but outside snapshot)" \
297 test_count_versions $share bar/lfoo 1 || \
298 failed=`expr $failed + 1`
300 testit "snapshots in each dir - abs symlink outside" \
301 test_count_versions $share bar/letcpasswd 1 || \
302 failed=`expr $failed + 1`
304 testit "snapshots in each dir - rel symlink outside" \
305 test_count_versions $share bar/loutside 1 || \
306 failed=`expr $failed + 1`
308 #the previous versions of the file bar/lfoo points to are outside its
309 #snapshot, and are not reachable. However, but previous versions
310 #taken at different, non-overlapping times higher up the
311 #hierarchy are still reachable.
312 testit "fetch a previous version of a regular file" \
313 test_fetch_snap_file $share "bar/baz" 6 || \
314 failed=`expr $failed + 1`
316 testit_expect_failure "fetch a (non-existent) previous version of a symlink" \
317 test_fetch_snap_file $share "bar/lfoo" 6 || \
318 failed=`expr $failed + 1`
320 testit "fetch a previous version of a symlink via browsing (1)" \
321 test_fetch_snap_file $share "bar/lfoo" 0 || \
322 failed=`expr $failed + 1`
324 testit "fetch a previous version of a symlink via browsing (2)" \
325 test_fetch_snap_file $share "bar/lfoo" 1 || \
326 failed=`expr $failed + 1`
328 testit "fetch a previous version of a symlink via browsing (3)" \
329 test_fetch_snap_file $share "bar/lfoo" 3 || \
330 failed=`expr $failed + 1`
334 test_shadow_copy_format()
336 local share #share to contact
337 local where #where to place snapshots
338 local prefix #prefix to files inside snapshot
339 local ncopies_allowd
340 local msg
342 share=$1
343 where=$2
344 prefix=$3
345 ncopies_allowed=$4
346 msg=$5
348 #delete snapshots from previous tests
349 find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1
350 build_snapshots $WORKDIR/$where "$prefix" 10 19
352 testit "$msg - regular file" \
353 test_count_versions $share foo $ncopies_allowed 1 || \
354 failed=`expr $failed + 1`
357 #build "latest" files
358 build_files $WORKDIR/mount base/share "latest" "latest"
360 failed=0
362 # a test with wide links allowed - also to verify that what's later
363 # being blocked is a result of server security measures and not
364 # a testing artifact.
365 test_shadow_copy_fixed shadow_wl mount base/share "shadow copies with wide links allowed" 1
367 # tests for a fixed snapshot location
368 test_shadow_copy_fixed shadow1 mount base/share "full volume snapshots mounted under volume"
369 test_shadow_copy_fixed shadow2 . base/share "full volume snapshots mounted outside volume"
370 test_shadow_copy_fixed shadow3 mount/base share "sub volume snapshots mounted under snapshot point"
371 test_shadow_copy_fixed shadow4 . share "sub volume snapshots mounted outside"
372 test_shadow_copy_fixed shadow5 mount/base/share "" "full volume snapshots and share mounted under volume"
373 test_shadow_copy_fixed shadow6 . "" "full volume snapshots and share mounted outside"
374 test_shadow_copy_fixed shadow8 . share "logical snapshot layout"
376 # tests for snapshot everywhere - one snapshot location
377 test_shadow_copy_fixed shadow7 mount base/share "'everywhere' full volume snapshots"
378 test_shadow_copy_fixed shadow7 mount/base share "'everywhere' sub volume snapshots"
379 test_shadow_copy_fixed shadow7 mount/base/share "" "'everywhere' share snapshots"
381 # a test for snapshots everywhere - multiple snapshot locations
382 test_shadow_copy_everywhere shadow7
384 # tests for testing snapshot selection via shadow:format
385 test_shadow_copy_format shadow_fmt0 mount/base share 3 "basic shadow:format test"
386 test_shadow_copy_format shadow_fmt1 mount/base share 2 "shadow:format with only date"
387 test_shadow_copy_format shadow_fmt2 mount/base share 2 "shadow:format with some prefix"
388 test_shadow_copy_format shadow_fmt3 mount/base share 2 "shadow:format with modified format"
389 test_shadow_copy_format shadow_fmt4 mount/base share 3 "shadow:format with snapprefix"
390 test_shadow_copy_format shadow_fmt5 mount/base share 6 "shadow:format with delimiter"
392 exit $failed