xfs: fix old fuzz test invocations of xfs_repair
[xfstests-dev.git] / tests / generic / 001
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2000-2001 Silicon Graphics, Inc.  All Rights Reserved.
4 #
5 # FS QA Test No. 001
6 #
7 # Random file copier to produce chains of identical files so the head
8 # and the tail can be diff'd at the end of each iteration.
9 #
10 # Exercises creat, write and unlink for a variety of directory sizes, and
11 # checks for data corruption.
12 #
13 # run [config]
14 #
15 # config has one line per file with filename and byte size, else use
16 # the default one below.
17 #
18 seq=`basename $0`
19 seqres=$RESULT_DIR/$seq
20 echo "QA output created by $seq"
21
22 # get standard environment, filters and checks
23 . ./common/rc
24 . ./common/filter
25
26 tmp=/tmp/$$
27 here=`pwd`
28 status=1
29 done_cleanup=false
30 trap "_cleanup; rm -f $tmp.*; exit \$status" 0 1 2 3 15
31
32 # real QA test starts here
33 _supported_fs generic
34 _require_test
35
36 verbose=true
37 verify=$here/verify_fill
38
39 if [ $# -eq 0 ]
40 then
41     # use the default config
42     #
43     cat <<End-of-File >$tmp.config
44 # pathname      size in bytes
45 #
46 small           10
47 big             102400
48 sub/small       10
49 sub/big         102400
50 #
51 sub/a           1
52 sub/b           2
53 sub/c           4
54 sub/d           8
55 sub/e           16
56 sub/f           32
57 sub/g           64
58 sub/h           128
59 sub/i           256
60 sub/j           512
61 sub/k           1024
62 sub/l           2048
63 sub/m           4096
64 sub/n           8192
65 #
66 sub/a00         100
67 sub/b00         200
68 sub/c00         400
69 sub/d00         800
70 sub/e00         1600
71 sub/f00         3200
72 sub/g00         6400
73 sub/h00         12800
74 sub/i00         25600
75 sub/j00         51200
76 sub/k00         102400
77 sub/l00         204800
78 sub/m00         409600
79 sub/n00         819200
80 #
81 sub/a000        1000
82 sub/e000        16000
83 sub/h000        128000
84 sub/k000        1024000
85 End-of-File
86 elif [ $# -eq 1 ]
87 then
88     if [ -f $1 ]
89     then
90         cp $1 $tmp.config
91     else
92         echo "Error: cannot open config \"$1\""
93         exit 1
94     fi
95 else
96     echo "Usage: run [config]"
97     exit 1
98 fi
99
100 ncopy=200               # number of file copies in the chain step
101 udf_fsize=20240         # number of sectors for UDF
102
103 _setup()
104 {
105     if mkdir -p $TEST_DIR/$$
106     then
107         :
108     else
109         echo "Error: cannot mkdir \"$TEST_DIR/$$\""
110         exit 1
111     fi
112     cd $TEST_DIR/$$
113
114     $verbose && echo -n "setup "
115     sed -e '/^#/d' $tmp.config \
116     | while read file nbytes
117     do
118         dir=`dirname $file`
119         if [ "$dir" != "." ]
120         then
121             if [ ! -d $dir ]
122             then
123                 if mkdir $dir
124                 then
125                     :
126                 else
127                     $verbose && echo
128                     echo "Error: cannot mkdir \"$dir\""
129                     exit 1
130                 fi
131             fi
132         fi
133         rm -f $file
134         if $here/src/fill $file $file $nbytes
135         then
136             :
137         else
138             $verbose && echo
139             echo "Error: cannot create \"$file\""
140             exit 1
141         fi
142         $verbose && echo -n "."
143     done
144     $verbose && echo
145 }
146
147 _mark_iteration()
148 {
149     $verbose && echo -n "mark_iteration "
150     sed -e '/^#/d' $tmp.config \
151     | while read file nbytes
152     do
153         if [ ! -f $file ]
154         then
155             $verbose && echo
156             echo "Error: $file vanished!"
157             touch $tmp.bad
158             continue
159         fi
160         sed -e "s/ [0-9][0-9]* / $1 /" <$file >$file.tmp
161         mv $file.tmp $file
162         $verbose && echo -n "."
163     done
164     $verbose && echo
165 }
166
167 # for each file, make a number of copies forming a chain like foo.0,
168 # foo.1, foo.2, ... foo.N
169 #
170 # files are chosen at random, so the lengths of the chains are different
171 #
172 # then rename foo.N to foo.last and remove all of the other files in
173 # the chain
174 #
175 _chain()
176 {
177     $AWK_PROG -v full_file=$seqres.full -v verify=$verify <$tmp.config '
178 BEGIN   { nfile = 0 }
179 /^#/    { next }
180         { file[nfile] = $1
181           size[nfile] = $2
182           link[nfile] = 0
183           nfile++
184           total_size += $2
185         }
186 END     { srand('$iter')
187           for (i=0; i < '$ncopy'; i++) {
188             # choose a file at random, and add one copy to that chain
189             j = -1
190             while (j < 0 || j >= nfile)
191                 j = int(rand() * nfile)
192             if (link[j] == 0) {
193                 # previous should already exist and next one should not exist
194                 printf "if [ ! -f %s ]; then echo \"%s missing!\"; exit; fi\n",file[j],file[j]
195                 printf "if [ -f %s.0 ]; then echo \"%s.0 already present!\"; exit; fi\n",file[j],file[j]
196                 printf "cp %s %s.0 || exit 1\n",file[j],file[j]
197                 printf "ls -i %s.0\n", file[j] >full_file;
198                 total_size += size[j]
199                 printf "# total size = %d\n", total_size 
200             }
201             else {
202                 # previous should already exist and next one should not exist
203                 printf "if [ ! -f %s.%d ]; then echo \"%s.%d missing!\"; exit; fi\n",file[j],link[j]-1,file[j],link[j]-1
204                 printf "if [ -f %s.%d ]; then echo \"%s.%d already present!\"; exit; fi\n",file[j],link[j],file[j],link[j]
205                 printf "cp %s.%d %s.%d || exit 1\n",file[j],link[j]-1,file[j],link[j]
206                 printf "ls -i %s.%d\n", file[j], link[j] >full_file;
207                 total_size += size[j]
208                 printf "# total size = %d\n", total_size 
209             }
210             link[j]++
211           }
212           # close all the chains, 
213           # if have at least one copy then move the last copy to "file[j].last"
214           # and remove all of the other files except the head of the chain
215           for (j=0; j<nfile; j++) {
216             if (link[j] > 0) {
217                 printf "mv %s.%d %s.last\n",file[j],link[j]-1,file[j]
218                 printf "ls -i %s.last\n", file[j] >full_file;
219             }
220             for (i=0; i<link[j]-1; i++) {
221                 printf "rm -f %s.%d\n",file[j],i
222             }
223           }
224         }' \
225         | tee -a $seqres.full | sh
226 }
227
228 _check()
229 {
230     rm -f $tmp.bad
231     $verbose && echo -n "check "
232     sed -e '/^#/d' $tmp.config \
233     | while read file nbytes
234     do
235         # the file is never removed so it should exist
236         if [ ! -f $file ]
237         then
238             $verbose && echo
239             echo "Error: $file vanished!"
240             touch $tmp.bad
241             continue
242         fi
243         # checks that the file and its last copy are the same
244         if [ -f $file.last ]
245         then
246             if cmp $file $file.last >/dev/null 2>&1
247             then
248                 $verbose && echo -n "."
249             else
250                 $verbose && echo
251                 echo "Error: corruption for $file ..."
252                 diff -c $file $file.last
253                 touch $tmp.bad
254             fi
255         else
256             $verbose && echo -n "."
257         fi
258     done
259     $verbose && echo
260 }
261
262 _cleanup()
263 {
264     # cleanup
265     #
266     if $done_cleanup
267     then
268         :
269     elif [ $status -eq 0 ]
270     then
271         $verbose && echo "cleanup"
272         cd /
273         rm -rf $TEST_DIR/$$
274         done_cleanup=true
275     fi
276 }
277
278 rm -f $seqres.full
279 status=0
280 _cleanup
281 status=1
282 done_cleanup=false
283
284 _setup
285
286 # do the test
287 #
288 for iter in 1 2 3 4 5
289 do
290     echo -n "iter $iter chain ... "
291     echo "iter $iter" >> $seqres.full
292     _chain
293     _check
294     if [ -f $tmp.bad ]
295     then
296         echo "Fatal error: test abandoned without changes"
297         exit 1
298     fi
299 done
300
301 status=0
302 exit