fstests: use _require_symlinks on all necessary tests
[xfstests-dev.git] / tests / generic / 556
1 # SPDX-License-Identifier: GPL-2.0+
2 #!/bin/bash
3 # FS QA Test No. 556
4 #
5 # Test the basic functionality of filesystems with case-insensitive
6 # support.
7
8 seq=`basename $0`
9 seqres=$RESULT_DIR/$seq
10 echo "QA output created by $seq"
11 status=1 # failure is thea default
12
13 . ./common/rc
14 . ./common/filter
15 . ./common/casefold
16 . ./common/attr
17
18 _supported_os Linux
19 _supported_fs generic
20 _require_scratch_nocheck
21 _require_scratch_casefold
22 _require_symlinks
23 _require_check_dmesg
24 _require_attrs
25
26 sdev=$(_short_dev ${SCRATCH_DEV})
27
28 filename1="file.txt"
29 filename2="FILE.TXT"
30
31 pt_file1=$(echo -e "coração")
32 pt_file2=$(echo -e "corac\xcc\xa7\xc3\xa3o" | tr a-z A-Z)
33
34 fr_file2=$(echo -e "french_caf\xc3\xa9.txt")
35 fr_file1=$(echo -e "french_cafe\xcc\x81.txt")
36
37 ar_file1=$(echo -e "arabic_\xdb\x92\xd9\x94.txt")
38 ar_file2=$(echo -e "arabic_\xdb\x93.txt" | tr a-z A-Z)
39
40 jp_file1=$(echo -e "japanese_\xe3\x82\xb2.txt")
41 jp_file2=$(echo -e "japanese_\xe3\x82\xb1\xe3\x82\x99.txt")
42
43 # '\xc3\x00' is an invalid sequence. Despite that, the sequences
44 # below could match, if we ignored the error.  But we don't want
45 # to be greedy at normalization, so at the first error we treat
46 # the entire sequence as an opaque blob.  Therefore, these two
47 # must NOT match.
48 blob_file1=$(echo -e "corac\xcc\xa7\xc3")
49 blob_file2=$(echo -e "coraç\xc3")
50
51 # Test helpers
52 basic_create_lookup()
53 {
54         local basedir=${1}
55         local exact=${2}
56         local lookup=${3}
57
58         touch "${basedir}/${exact}"
59         [ -f "${basedir}/${lookup}" ] || \
60                 echo "lookup of ${exact} using ${lookup} failed"
61         _casefold_check_exact_name "${basedir}" "${exact}" || \
62                 echo "Created file ${exact} with wrong name."
63 }
64
65 # CI search should fail.
66 bad_basic_create_lookup()
67 {
68         local basedir=${1}
69         local exact=${2}
70         local lookup=${3}
71
72         touch "${basedir}/${exact}"
73         [ -f "${basedir}/${lookup}" ] && \
74                 echo "Lookup of ${exact} using ${lookup} should fail"
75 }
76
77 # Testcases
78 test_casefold_lookup()
79 {
80         local basedir=${SCRATCH_MNT}/casefold_lookup
81
82         mkdir -p ${basedir}
83         _casefold_set_attr ${basedir}
84
85         basic_create_lookup "${basedir}" "${filename1}" "${filename2}"
86         basic_create_lookup "${basedir}" "${pt_file1}" "${pt_file2}"
87         basic_create_lookup "${basedir}" "${fr_file1}" "${fr_file2}"
88         basic_create_lookup "${basedir}" "${ar_file1}" "${ar_file2}"
89         basic_create_lookup "${basedir}" "${jp_file1}" "${jp_file2}"
90 }
91
92 test_bad_casefold_lookup()
93 {
94         local basedir=${SCRATCH_MNT}/casefold_lookup
95
96         mkdir -p ${basedir}
97
98         bad_basic_create_lookup ${basedir} ${blob_file1} ${blob_file2}
99 }
100
101 do_create_and_remove()
102 {
103         local basedir=${1}
104         local exact=${2}
105         local casefold=${3}
106
107         basic_create_lookup ${basedir} ${exact} ${casefold}
108         rm -f ${basedir}/${exact}
109         [ -f ${basedir}/${exact} ] && \
110                 echo "File ${exact} was not removed using exact name"
111
112         basic_create_lookup ${basedir} ${exact} ${casefold}
113         rm -f ${basedir}/${casefold}
114         [ -f ${basedir}/${exact} ] && \
115                 echo "File ${exact} was not removed using inexact name"
116 }
117
118 # remove and recreate
119 test_create_and_remove()
120 {
121         local basedir=${SCRATCH_MNT}/create_and_remove
122         mkdir -p ${basedir}
123
124         _casefold_set_attr ${basedir}
125         do_create_and_remove "${basedir}" "${pt_file1}" "${pt_file2}"
126         do_create_and_remove "${basedir}" "${jp_file1}" "${jp_file2}"
127         do_create_and_remove "${basedir}" "${ar_file1}" "${ar_file2}"
128         do_create_and_remove "${basedir}" "${fr_file1}" "${fr_file2}"
129 }
130
131 test_casefold_flag_basic()
132 {
133         local basedir=${SCRATCH_MNT}/basic
134
135         mkdir -p ${basedir}
136         _casefold_set_attr ${basedir}
137         _casefold_lsattr_dir ${basedir} | _filter_scratch
138
139         _casefold_unset_attr ${basedir}
140         _casefold_lsattr_dir ${basedir} | _filter_scratch
141 }
142
143 test_casefold_flag_removal()
144 {
145         local basedir=${SCRATCH_MNT}/casefold_flag_removal
146
147         mkdir -p ${basedir}
148         _casefold_set_attr ${basedir}
149         _casefold_lsattr_dir ${basedir} | _filter_scratch
150
151         # Try to remove +F attribute on non empty directory
152         touch ${basedir}/${filename1}
153         _casefold_unset_attr ${basedir} &>/dev/null
154         _casefold_lsattr_dir ${basedir} | _filter_scratch
155 }
156
157 # Test Inheritance of casefold flag
158 test_casefold_flag_inheritance()
159 {
160         local basedir=${SCRATCH_MNT}/flag_inheritance
161         local dirpath1="d1/d2/d3"
162         local dirpath2="D1/D2/D3"
163
164         mkdir -p ${basedir}
165         _casefold_set_attr ${basedir}
166
167         mkdir -p ${basedir}/${dirpath1}
168         _casefold_lsattr_dir ${basedir}/${dirpath1} | _filter_scratch
169
170         [ -d ${basedir}/${dirpath2} ] || \
171                 echo "Directory CI Lookup failed."
172         _casefold_check_exact_name "${basedir}" "${dirpath1}" || \
173                 echo "Created directory with wrong name."
174
175         touch ${basedir}/${dirpath2}/${filename1}
176         [ -f ${basedir}/${dirpath1}/${filename2} ] || \
177                 echo "Couldn't create file on casefolded parent."
178 }
179
180 # Test nesting of sensitive directory inside insensitive directory.
181 test_nesting_sensitive_insensitive_tree_simple()
182 {
183         local basedir=${SCRATCH_MNT}/sd1
184
185         mkdir -p ${basedir}
186         _casefold_set_attr ${basedir}
187
188         mkdir -p ${basedir}/sd1
189         _casefold_set_attr ${basedir}/sd1
190
191         mkdir ${basedir}/sd1/sd2
192         _casefold_unset_attr ${basedir}/sd1/sd2
193
194         touch ${basedir}/sd1/sd2/${filename1}
195         [ -f ${basedir}/sd1/sd2/${filename1} ] || \
196                 echo "Exact nested file lookup failed."
197         [ -f ${basedir}/sd1/SD2/${filename1} ] || \
198                 echo "Nested file lookup failed."
199         [ -f ${basedir}/sd1/SD2/${filename2} ] && \
200                 echo "Wrong file lookup passed, should have fail."
201 }
202
203 test_nesting_sensitive_insensitive_tree_complex()
204 {
205         # Test nested-directories
206         local basedir=${SCRATCH_MNT}/nesting
207
208         mkdir -p ${basedir}
209         _casefold_set_attr ${basedir}
210
211         mkdir ${basedir}/nd1
212         _casefold_set_attr ${basedir}/nd1
213         mkdir ${basedir}/nd1/nd2
214         _casefold_unset_attr ${basedir}/nd1/nd2
215         mkdir ${basedir}/nd1/nd2/nd3
216         _casefold_set_attr ${basedir}/nd1/nd2/nd3
217         mkdir ${basedir}/nd1/nd2/nd3/nd4
218         _casefold_unset_attr ${basedir}/nd1/nd2/nd3/nd4
219         mkdir ${basedir}/nd1/nd2/nd3/nd4/nd5
220         _casefold_set_attr ${basedir}/nd1/nd2/nd3/nd4/nd5
221
222         [ -d ${basedir}/ND1/ND2/nd3/ND4/nd5 ] || \
223                 echo "Nest-dir Lookup failed."
224         [ -d ${basedir}/nd1/nd2/nd3/nd4/ND5 ] && \
225                 echo "ND5: Nest-dir Lookup passed, it should fail."
226         [ -d ${basedir}/nd1/nd2/nd3/ND4/nd5 ] || \
227                 echo "Nest-dir Lookup failed."
228         [ -d ${basedir}/nd1/nd2/ND3/nd4/ND5 ] && \
229                 echo "ND3: Nest-dir Lookup passed, it should fail."
230 }
231
232 test_symlink_with_inexact_name()
233 {
234         local basedir=${SCRATCH_MNT}/symlink
235
236         mkdir -p ${basedir}
237         _casefold_set_attr ${basedir}
238
239         mkdir ${basedir}/ind1
240         mkdir ${basedir}/ind2
241         _casefold_set_attr ${basedir}/ind1
242         touch ${basedir}/ind1/target
243
244         ln -s ${basedir}/ind1/TARGET ${basedir}/ind2/link
245         [ -L ${basedir}/ind2/link ] || echo "Not a symlink."
246         readlink -e ${basedir}/ind2/link | _filter_scratch
247 }
248
249 do_test_name_preserve()
250 {
251         local basedir=${1}
252         local exact=${2}
253         local casefold=${3}
254
255         touch ${basedir}/${exact}
256         rm ${basedir}/${exact}
257
258         touch ${basedir}/${casefold}
259         _casefold_check_exact_name ${basedir} ${casefold} ||
260                 echo "${casefold} was not created with exact name"
261 }
262
263 # Name-preserving tests
264 # We create a file with a name, delete it and create again with an
265 # equivalent name.  If the negative dentry wasn't invalidated, the
266 # file might be created using $1 instead of $2.
267 test_name_preserve()
268 {
269         local basedir=${SCRATCH_MNT}/test_name_preserve
270
271         mkdir -p ${basedir}
272         _casefold_set_attr ${basedir}
273
274         do_test_name_preserve "${basedir}" "${pt_file1}" "${pt_file2}"
275         do_test_name_preserve "${basedir}" "${jp_file1}" "${jp_file2}"
276         do_test_name_preserve "${basedir}" "${ar_file1}" "${ar_file2}"
277         do_test_name_preserve "${basedir}" "${fr_file1}" "${fr_file2}"
278 }
279
280 do_test_dir_name_preserve()
281 {
282         local basedir=${1}
283         local exact=${2}
284         local casefold=${3}
285
286         mkdir ${basedir}/${exact}
287         rmdir ${basedir}/${exact}
288
289         mkdir ${basedir}/${casefold}
290         _casefold_check_exact_name ${basedir} ${casefold} ||
291                 echo "${casefold} was not created with exact name"
292 }
293
294 test_dir_name_preserve()
295 {
296         local basedir=${SCRATCH_MNT}/"dir-test_name_preserve"
297
298         mkdir -p ${basedir}
299         _casefold_set_attr ${basedir}
300
301         do_test_dir_name_preserve "${basedir}" "${pt_file1}" "${pt_file2}"
302         do_test_dir_name_preserve "${basedir}" "${jp_file1}" "${jp_file2}"
303         do_test_dir_name_preserve "${basedir}" "${ar_file1}" "${ar_file2}"
304         do_test_dir_name_preserve "${basedir}" "${fr_file1}" "${fr_file2}"
305 }
306
307 test_name_reuse()
308 {
309         local basedir=${SCRATCH_MNT}/reuse
310         local reuse1=fileX
311         local reuse2=FILEX
312
313         mkdir ${basedir}
314         _casefold_set_attr ${basedir}
315
316         touch ${basedir}/${reuse1}
317         rm -f ${basedir}/${reuse1} || echo "File lookup failed."
318         touch ${basedir}/${reuse2}
319         _casefold_check_exact_name "${basedir}" "${reuse2}" || \
320                 echo "File created with wrong name"
321         _casefold_check_exact_name "${basedir}" "${reuse1}" && \
322                 echo "File created with the old name"
323 }
324
325 test_create_with_same_name()
326 {
327         local basedir=${SCRATCH_MNT}/same_name
328
329         mkdir ${basedir}
330         _casefold_set_attr ${basedir}
331
332         mkdir -p ${basedir}/same1/same1
333         touch ${basedir}/SAME1/sAME1/sAMe1
334         touch -c ${basedir}/SAME1/sAME1/same1 ||
335                 echo "Would create a new file instead of using old one"
336 }
337
338 test_file_rename()
339 {
340         local basedir=${SCRATCH_MNT}/rename
341
342         mkdir -p ${basedir}
343         _casefold_set_attr ${basedir}
344
345         # Move to an equivalent name should not work
346         mv ${basedir}/rename ${basedir}/rename 2>&1 | \
347                 _filter_scratch
348
349         _casefold_check_exact_name ${basedir} "rename" || \
350                 echo "Name shouldn't change."
351 }
352
353 # Test openfd with casefold.
354 # 1. Delete a file after gettings its fd.
355 # 2. Then create new dir with same name
356 test_casefold_openfd()
357 {
358         local basedir=${SCRATCH_MNT}/openfd
359         local ofd1="openfd"
360         local ofd2="OPENFD"
361
362         mkdir -p ${basedir}
363         _casefold_set_attr ${basedir}
364
365         exec 3<> ${basedir}/${ofd1}
366         rm -rf ${basedir}/${ofd1}
367         mkdir ${basedir}/${ofd2}
368         [ -d ${basedir}/${ofd2} ] || echo "Not a directory"
369         _casefold_check_exact_name ${basedir} "${ofd2}" ||
370                 echo "openfd file was created using old name"
371         rm -rf ${basedir}/${ofd2}
372         exec 3>&-
373 }
374
375 # Test openfd with casefold.
376 # 1. Delete a file after gettings its fd.
377 # 2. Then create new file with same name
378 # 3. Read from open-fd and write into new file.
379 test_casefold_openfd2()
380 {
381         local basedir=${SCRATCH_MNT}/openfd2
382         local ofd1="openfd"
383         local ofd2="OPENFD"
384
385         mkdir ${basedir}
386         _casefold_set_attr ${basedir}
387
388         date > ${basedir}/${ofd1}
389         exec 3<> ${basedir}/${ofd1}
390         rm -rf ${basedir}/${ofd1}
391         touch ${basedir}/${ofd1}
392         [ -f ${basedir}/${ofd2} ] || echo "Not a file"
393         read data <&3
394         echo $data >> ${basedir}/${ofd1}
395         exec 3>&-
396 }
397
398 test_hard_link_lookups()
399 {
400         local basedir=${SCRATCH_MNT}/hard_link
401
402         mkdir ${basedir}
403         _casefold_set_attr ${basedir}
404
405         touch ${basedir}/h1
406         ln ${basedir}/H1 ${SCRATCH_MNT}/h1
407         cnt=`stat -c %h ${basedir}/h1`
408         [ $cnt -eq 1 ] && echo "Unable to create hardlink"
409
410         # Create hardlink for casefold dir file and inside regular dir.
411         touch ${SCRATCH_MNT}/h2
412         ln ${SCRATCH_MNT}/h2 ${basedir}/H2
413         cnt=`stat -c %h ${basedir}/h2`
414         [ $cnt -eq 1 ] && echo "Unable to create hardlink"
415 }
416
417 test_xattrs_lookups()
418 {
419         local basedir=${SCRATCH_MNT}/xattrs
420
421         mkdir ${basedir}
422         _casefold_set_attr ${basedir}
423
424         mkdir -p ${basedir}/x
425
426         ${SETFATTR_PROG} -n user.foo -v bar ${basedir}/x
427         ${GETFATTR_PROG} --absolute-names -n user.foo \
428                 ${basedir}/x | _filter_scratch
429
430         touch ${basedir}/x/f1
431         ${SETFATTR_PROG} -n user.foo -v bar ${basedir}/x/f1
432         ${GETFATTR_PROG} --absolute-names -n user.foo \
433                 ${basedir}/x/f1 | _filter_scratch
434 }
435
436 test_lookup_large_directory()
437 {
438         local basedir=${SCRATCH_MNT}/large
439
440         mkdir -p ${basedir}
441         _casefold_set_attr ${basedir}
442
443         touch $(seq -f "${basedir}/file%g" 0 2000)
444
445         # We really want to spawn a single process here, to speed up the
446         # test, but we don't want the output of 2k files, except for
447         # errors.
448         cat $(seq -f "${basedir}/FILE%g" 0 2000) || \
449                 echo "Case on large dir failed"
450 }
451
452 test_strict_mode_invalid_filename()
453 {
454         local basedir=${SCRATCH_MNT}/strict
455
456         mkdir -p ${basedir}
457         _casefold_set_attr ${basedir}
458
459         # These creation commands should fail, since we are on strict
460         # mode.
461         touch "${basedir}/${blob_file1}" 2>&1 | _filter_scratch
462         touch "${basedir}/${blob_file2}" 2>&1 | _filter_scratch
463 }
464
465 #############
466 # Run tests #
467 #############
468
469 _scratch_mkfs_casefold >>$seqres.full 2>&1
470
471 _scratch_mount
472
473 _check_dmesg_for \
474         "\(${sdev}\): Using encoding defined by superblock: utf8" || \
475         _fail "Could not mount with encoding: utf8"
476
477 test_casefold_flag_basic
478 test_casefold_lookup
479 test_bad_casefold_lookup
480 test_create_and_remove
481 test_casefold_flag_removal
482 test_casefold_flag_inheritance
483 test_nesting_sensitive_insensitive_tree_simple
484 test_nesting_sensitive_insensitive_tree_complex
485 test_symlink_with_inexact_name
486 test_name_preserve
487 test_dir_name_preserve
488 test_name_reuse
489 test_create_with_same_name
490 test_file_rename
491 test_casefold_openfd
492 test_casefold_openfd2
493 test_hard_link_lookups
494 test_xattrs_lookups
495 test_lookup_large_directory
496
497 _scratch_unmount
498 _check_scratch_fs
499
500 # Test Strict Mode
501 _scratch_mkfs_casefold_strict >>$seqres.full 2>&1
502 _scratch_mount
503
504 test_strict_mode_invalid_filename
505
506 _scratch_unmount
507 _check_scratch_fs
508
509 status=0
510 exit