1 # SPDX-License-Identifier: GPL-2.0+
5 # Test the basic functionality of filesystems with case-insensitive
9 seqres=$RESULT_DIR/$seq
10 echo "QA output created by $seq"
11 status=1 # failure is thea default
20 _require_scratch_nocheck
21 _require_scratch_casefold
25 sdev=$(_short_dev ${SCRATCH_DEV})
30 pt_file1=$(echo -e "coração")
31 pt_file2=$(echo -e "corac\xcc\xa7\xc3\xa3o" | tr a-z A-Z)
33 fr_file2=$(echo -e "french_caf\xc3\xa9.txt")
34 fr_file1=$(echo -e "french_cafe\xcc\x81.txt")
36 ar_file1=$(echo -e "arabic_\xdb\x92\xd9\x94.txt")
37 ar_file2=$(echo -e "arabic_\xdb\x93.txt" | tr a-z A-Z)
39 jp_file1=$(echo -e "japanese_\xe3\x82\xb2.txt")
40 jp_file2=$(echo -e "japanese_\xe3\x82\xb1\xe3\x82\x99.txt")
42 # '\xc3\x00' is an invalid sequence. Despite that, the sequences
43 # below could match, if we ignored the error. But we don't want
44 # to be greedy at normalization, so at the first error we treat
45 # the entire sequence as an opaque blob. Therefore, these two
47 blob_file1=$(echo -e "corac\xcc\xa7\xc3")
48 blob_file2=$(echo -e "coraç\xc3")
57 touch "${basedir}/${exact}"
58 [ -f "${basedir}/${lookup}" ] || \
59 echo "lookup of ${exact} using ${lookup} failed"
60 _casefold_check_exact_name "${basedir}" "${exact}" || \
61 echo "Created file ${exact} with wrong name."
64 # CI search should fail.
65 bad_basic_create_lookup()
71 touch "${basedir}/${exact}"
72 [ -f "${basedir}/${lookup}" ] && \
73 echo "Lookup of ${exact} using ${lookup} should fail"
77 test_casefold_lookup()
79 local basedir=${SCRATCH_MNT}/casefold_lookup
82 _casefold_set_attr ${basedir}
84 basic_create_lookup "${basedir}" "${filename1}" "${filename2}"
85 basic_create_lookup "${basedir}" "${pt_file1}" "${pt_file2}"
86 basic_create_lookup "${basedir}" "${fr_file1}" "${fr_file2}"
87 basic_create_lookup "${basedir}" "${ar_file1}" "${ar_file2}"
88 basic_create_lookup "${basedir}" "${jp_file1}" "${jp_file2}"
91 test_bad_casefold_lookup()
93 local basedir=${SCRATCH_MNT}/casefold_lookup
97 bad_basic_create_lookup ${basedir} ${blob_file1} ${blob_file2}
100 do_create_and_remove()
106 basic_create_lookup ${basedir} ${exact} ${casefold}
107 rm -f ${basedir}/${exact}
108 [ -f ${basedir}/${exact} ] && \
109 echo "File ${exact} was not removed using exact name"
111 basic_create_lookup ${basedir} ${exact} ${casefold}
112 rm -f ${basedir}/${casefold}
113 [ -f ${basedir}/${exact} ] && \
114 echo "File ${exact} was not removed using inexact name"
117 # remove and recreate
118 test_create_and_remove()
120 local basedir=${SCRATCH_MNT}/create_and_remove
123 _casefold_set_attr ${basedir}
124 do_create_and_remove "${basedir}" "${pt_file1}" "${pt_file2}"
125 do_create_and_remove "${basedir}" "${jp_file1}" "${jp_file2}"
126 do_create_and_remove "${basedir}" "${ar_file1}" "${ar_file2}"
127 do_create_and_remove "${basedir}" "${fr_file1}" "${fr_file2}"
130 test_casefold_flag_basic()
132 local basedir=${SCRATCH_MNT}/basic
135 _casefold_set_attr ${basedir}
136 _casefold_lsattr_dir ${basedir} | _filter_scratch
138 _casefold_unset_attr ${basedir}
139 _casefold_lsattr_dir ${basedir} | _filter_scratch
142 test_casefold_flag_removal()
144 local basedir=${SCRATCH_MNT}/casefold_flag_removal
147 _casefold_set_attr ${basedir}
148 _casefold_lsattr_dir ${basedir} | _filter_scratch
150 # Try to remove +F attribute on non empty directory
151 touch ${basedir}/${filename1}
152 _casefold_unset_attr ${basedir} &>/dev/null
153 _casefold_lsattr_dir ${basedir} | _filter_scratch
156 # Test Inheritance of casefold flag
157 test_casefold_flag_inheritance()
159 local basedir=${SCRATCH_MNT}/flag_inheritance
160 local dirpath1="d1/d2/d3"
161 local dirpath2="D1/D2/D3"
164 _casefold_set_attr ${basedir}
166 mkdir -p ${basedir}/${dirpath1}
167 _casefold_lsattr_dir ${basedir}/${dirpath1} | _filter_scratch
169 [ -d ${basedir}/${dirpath2} ] || \
170 echo "Directory CI Lookup failed."
171 _casefold_check_exact_name "${basedir}" "${dirpath1}" || \
172 echo "Created directory with wrong name."
174 touch ${basedir}/${dirpath2}/${filename1}
175 [ -f ${basedir}/${dirpath1}/${filename2} ] || \
176 echo "Couldn't create file on casefolded parent."
179 # Test nesting of sensitive directory inside insensitive directory.
180 test_nesting_sensitive_insensitive_tree_simple()
182 local basedir=${SCRATCH_MNT}/sd1
185 _casefold_set_attr ${basedir}
187 mkdir -p ${basedir}/sd1
188 _casefold_set_attr ${basedir}/sd1
190 mkdir ${basedir}/sd1/sd2
191 _casefold_unset_attr ${basedir}/sd1/sd2
193 touch ${basedir}/sd1/sd2/${filename1}
194 [ -f ${basedir}/sd1/sd2/${filename1} ] || \
195 echo "Exact nested file lookup failed."
196 [ -f ${basedir}/sd1/SD2/${filename1} ] || \
197 echo "Nested file lookup failed."
198 [ -f ${basedir}/sd1/SD2/${filename2} ] && \
199 echo "Wrong file lookup passed, should have fail."
202 test_nesting_sensitive_insensitive_tree_complex()
204 # Test nested-directories
205 local basedir=${SCRATCH_MNT}/nesting
208 _casefold_set_attr ${basedir}
211 _casefold_set_attr ${basedir}/nd1
212 mkdir ${basedir}/nd1/nd2
213 _casefold_unset_attr ${basedir}/nd1/nd2
214 mkdir ${basedir}/nd1/nd2/nd3
215 _casefold_set_attr ${basedir}/nd1/nd2/nd3
216 mkdir ${basedir}/nd1/nd2/nd3/nd4
217 _casefold_unset_attr ${basedir}/nd1/nd2/nd3/nd4
218 mkdir ${basedir}/nd1/nd2/nd3/nd4/nd5
219 _casefold_set_attr ${basedir}/nd1/nd2/nd3/nd4/nd5
221 [ -d ${basedir}/ND1/ND2/nd3/ND4/nd5 ] || \
222 echo "Nest-dir Lookup failed."
223 [ -d ${basedir}/nd1/nd2/nd3/nd4/ND5 ] && \
224 echo "ND5: Nest-dir Lookup passed, it should fail."
225 [ -d ${basedir}/nd1/nd2/nd3/ND4/nd5 ] || \
226 echo "Nest-dir Lookup failed."
227 [ -d ${basedir}/nd1/nd2/ND3/nd4/ND5 ] && \
228 echo "ND3: Nest-dir Lookup passed, it should fail."
231 test_symlink_with_inexact_name()
233 local basedir=${SCRATCH_MNT}/symlink
236 _casefold_set_attr ${basedir}
238 mkdir ${basedir}/ind1
239 mkdir ${basedir}/ind2
240 _casefold_set_attr ${basedir}/ind1
241 touch ${basedir}/ind1/target
243 ln -s ${basedir}/ind1/TARGET ${basedir}/ind2/link
244 [ -L ${basedir}/ind2/link ] || echo "Not a symlink."
245 readlink -e ${basedir}/ind2/link | _filter_scratch
248 do_test_name_preserve()
254 touch ${basedir}/${exact}
255 rm ${basedir}/${exact}
257 touch ${basedir}/${casefold}
258 _casefold_check_exact_name ${basedir} ${casefold} ||
259 echo "${casefold} was not created with exact name"
262 # Name-preserving tests
263 # We create a file with a name, delete it and create again with an
264 # equivalent name. If the negative dentry wasn't invalidated, the
265 # file might be created using $1 instead of $2.
268 local basedir=${SCRATCH_MNT}/test_name_preserve
271 _casefold_set_attr ${basedir}
273 do_test_name_preserve "${basedir}" "${pt_file1}" "${pt_file2}"
274 do_test_name_preserve "${basedir}" "${jp_file1}" "${jp_file2}"
275 do_test_name_preserve "${basedir}" "${ar_file1}" "${ar_file2}"
276 do_test_name_preserve "${basedir}" "${fr_file1}" "${fr_file2}"
279 do_test_dir_name_preserve()
285 mkdir ${basedir}/${exact}
286 rmdir ${basedir}/${exact}
288 mkdir ${basedir}/${casefold}
289 _casefold_check_exact_name ${basedir} ${casefold} ||
290 echo "${casefold} was not created with exact name"
293 test_dir_name_preserve()
295 local basedir=${SCRATCH_MNT}/"dir-test_name_preserve"
298 _casefold_set_attr ${basedir}
300 do_test_dir_name_preserve "${basedir}" "${pt_file1}" "${pt_file2}"
301 do_test_dir_name_preserve "${basedir}" "${jp_file1}" "${jp_file2}"
302 do_test_dir_name_preserve "${basedir}" "${ar_file1}" "${ar_file2}"
303 do_test_dir_name_preserve "${basedir}" "${fr_file1}" "${fr_file2}"
308 local basedir=${SCRATCH_MNT}/reuse
313 _casefold_set_attr ${basedir}
315 touch ${basedir}/${reuse1}
316 rm -f ${basedir}/${reuse1} || echo "File lookup failed."
317 touch ${basedir}/${reuse2}
318 _casefold_check_exact_name "${basedir}" "${reuse2}" || \
319 echo "File created with wrong name"
320 _casefold_check_exact_name "${basedir}" "${reuse1}" && \
321 echo "File created with the old name"
324 test_create_with_same_name()
326 local basedir=${SCRATCH_MNT}/same_name
329 _casefold_set_attr ${basedir}
331 mkdir -p ${basedir}/same1/same1
332 touch ${basedir}/SAME1/sAME1/sAMe1
333 touch -c ${basedir}/SAME1/sAME1/same1 ||
334 echo "Would create a new file instead of using old one"
339 local basedir=${SCRATCH_MNT}/rename
342 _casefold_set_attr ${basedir}
344 # Move to an equivalent name should not work
345 mv ${basedir}/rename ${basedir}/rename 2>&1 | \
348 _casefold_check_exact_name ${basedir} "rename" || \
349 echo "Name shouldn't change."
352 # Test openfd with casefold.
353 # 1. Delete a file after gettings its fd.
354 # 2. Then create new dir with same name
355 test_casefold_openfd()
357 local basedir=${SCRATCH_MNT}/openfd
362 _casefold_set_attr ${basedir}
364 exec 3<> ${basedir}/${ofd1}
365 rm -rf ${basedir}/${ofd1}
366 mkdir ${basedir}/${ofd2}
367 [ -d ${basedir}/${ofd2} ] || echo "Not a directory"
368 _casefold_check_exact_name ${basedir} "${ofd2}" ||
369 echo "openfd file was created using old name"
370 rm -rf ${basedir}/${ofd2}
374 # Test openfd with casefold.
375 # 1. Delete a file after gettings its fd.
376 # 2. Then create new file with same name
377 # 3. Read from open-fd and write into new file.
378 test_casefold_openfd2()
380 local basedir=${SCRATCH_MNT}/openfd2
385 _casefold_set_attr ${basedir}
387 date > ${basedir}/${ofd1}
388 exec 3<> ${basedir}/${ofd1}
389 rm -rf ${basedir}/${ofd1}
390 touch ${basedir}/${ofd1}
391 [ -f ${basedir}/${ofd2} ] || echo "Not a file"
393 echo $data >> ${basedir}/${ofd1}
397 test_hard_link_lookups()
399 local basedir=${SCRATCH_MNT}/hard_link
402 _casefold_set_attr ${basedir}
405 ln ${basedir}/H1 ${SCRATCH_MNT}/h1
406 cnt=`stat -c %h ${basedir}/h1`
407 [ $cnt -eq 1 ] && echo "Unable to create hardlink"
409 # Create hardlink for casefold dir file and inside regular dir.
410 touch ${SCRATCH_MNT}/h2
411 ln ${SCRATCH_MNT}/h2 ${basedir}/H2
412 cnt=`stat -c %h ${basedir}/h2`
413 [ $cnt -eq 1 ] && echo "Unable to create hardlink"
416 test_xattrs_lookups()
418 local basedir=${SCRATCH_MNT}/xattrs
421 _casefold_set_attr ${basedir}
423 mkdir -p ${basedir}/x
425 ${SETFATTR_PROG} -n user.foo -v bar ${basedir}/x
426 ${GETFATTR_PROG} --absolute-names -n user.foo \
427 ${basedir}/x | _filter_scratch
429 touch ${basedir}/x/f1
430 ${SETFATTR_PROG} -n user.foo -v bar ${basedir}/x/f1
431 ${GETFATTR_PROG} --absolute-names -n user.foo \
432 ${basedir}/x/f1 | _filter_scratch
435 test_lookup_large_directory()
437 local basedir=${SCRATCH_MNT}/large
440 _casefold_set_attr ${basedir}
442 touch $(seq -f "${basedir}/file%g" 0 2000)
444 # We really want to spawn a single process here, to speed up the
445 # test, but we don't want the output of 2k files, except for
447 cat $(seq -f "${basedir}/FILE%g" 0 2000) || \
448 echo "Case on large dir failed"
451 test_strict_mode_invalid_filename()
453 local basedir=${SCRATCH_MNT}/strict
456 _casefold_set_attr ${basedir}
458 # These creation commands should fail, since we are on strict
460 touch "${basedir}/${blob_file1}" 2>&1 | _filter_scratch
461 touch "${basedir}/${blob_file2}" 2>&1 | _filter_scratch
468 _scratch_mkfs_casefold >>$seqres.full 2>&1
473 "\(${sdev}\): Using encoding defined by superblock: utf8" || \
474 _fail "Could not mount with encoding: utf8"
476 test_casefold_flag_basic
478 test_bad_casefold_lookup
479 test_create_and_remove
480 test_casefold_flag_removal
481 test_casefold_flag_inheritance
482 test_nesting_sensitive_insensitive_tree_simple
483 test_nesting_sensitive_insensitive_tree_complex
484 test_symlink_with_inexact_name
486 test_dir_name_preserve
488 test_create_with_same_name
491 test_casefold_openfd2
492 test_hard_link_lookups
494 test_lookup_large_directory
500 _scratch_mkfs_casefold_strict >>$seqres.full 2>&1
503 test_strict_mode_invalid_filename