1# 2# Copyright (c) 2016 Spectra Logic Corp 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions 7# are met: 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 14# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24# SUCH DAMAGE. 25# 26 27atf_test_case bad_namespace 28bad_namespace_head() { 29 atf_set "descr" "Can't set attributes for nonexistent namespaces" 30} 31bad_namespace_body() { 32 check_fs 33 touch foo 34 atf_check -s not-exit:0 -e match:"Invalid argument" \ 35 setextattr badnamespace myattr X foo 36 atf_check -s not-exit:0 -e match:"Invalid argument" \ 37 lsextattr -q badnamespace foo 38} 39 40atf_test_case hex 41hex_head() { 42 atf_set "descr" "Set and get attribute values in hexadecimal" 43} 44hex_body() { 45 check_fs 46 touch foo 47 atf_check -s exit:0 -o empty setextattr user myattr XYZ foo 48 atf_check -s exit:0 -o inline:"58 59 5a\n" \ 49 getextattr -qx user myattr foo 50} 51 52atf_test_case hex_nonascii 53hex_nonascii_head() { 54 atf_set "descr" "Get binary attribute values in hexadecimal" 55} 56hex_nonascii_body() { 57 check_fs 58 touch foo 59 BINSTUFF=`echo $'\x20\x30\x40\x55\x66\x70\x81\xa2\xb3\xee\xff'` 60 atf_check -s exit:0 -o empty setextattr user myattr "$BINSTUFF" foo 61 getextattr user myattr foo 62 atf_check -s exit:0 -o inline:"20 30 40 55 66 70 81 a2 b3 ee ff\n" \ 63 getextattr -qx user myattr foo 64} 65 66atf_test_case long_name 67long_name_head() { 68 atf_set "descr" "A maximum length attribute name" 69} 70long_name_body() { 71 check_fs 72 73 if ! NAME_MAX=$(getconf NAME_MAX .); then 74 atf_skip "Filesystem not reporting NAME_MAX; skipping testcase" 75 fi 76 77 ATTRNAME=`jot -b X -s "" $NAME_MAX 0` 78 touch foo 79 atf_check -s exit:0 -o empty setextattr user $ATTRNAME myvalue foo 80 atf_check -s exit:0 -o inline:"${ATTRNAME}\n" lsextattr -q user foo 81 atf_check -s exit:0 -o inline:"myvalue\n" \ 82 getextattr -q user ${ATTRNAME} foo 83 atf_check -s exit:0 -o empty rmextattr user ${ATTRNAME} foo 84 atf_check -s exit:0 -o empty lsextattr -q user foo 85} 86 87atf_test_case loud 88loud_head() { 89 atf_set "descr" "Loud (non -q) output for each command" 90} 91loud_body() { 92 check_fs 93 touch foo 94 # setextattr(8) and friends print hard tabs. Use printf to convert 95 # them to spaces before checking the output. 96 atf_check -s exit:0 -o empty setextattr user myattr myvalue foo 97 atf_check -s exit:0 -o inline:"foo myattr" \ 98 printf "%s %s" $(lsextattr user foo) 99 atf_check -s exit:0 -o inline:"foo myvalue" \ 100 printf "%s %s" $(getextattr user myattr foo) 101 atf_check -s exit:0 -o empty rmextattr user myattr foo 102 atf_check -s exit:0 -o inline:"foo" printf %s $(lsextattr user foo) 103} 104 105atf_test_case noattrs 106noattrs_head() { 107 atf_set "descr" "A file with no extended attributes" 108} 109noattrs_body() { 110 check_fs 111 touch foo 112 atf_check -s exit:0 -o empty lsextattr -q user foo 113} 114 115atf_test_case nonexistent_file 116nonexistent_file_head() { 117 atf_set "descr" "A file that does not exist" 118} 119nonexistent_file_body() { 120 check_fs 121 atf_check -s exit:1 -e match:"No such file or directory" \ 122 lsextattr user foo 123 atf_check -s exit:1 -e match:"No such file or directory" \ 124 setextattr user myattr myvalue foo 125 atf_check -s exit:1 -e match:"No such file or directory" \ 126 getextattr user myattr foo 127 atf_check -s exit:1 -e match:"No such file or directory" \ 128 rmextattr user myattr foo 129} 130 131atf_test_case null 132null_head() { 133 atf_set "descr" "NUL-terminate an attribute value" 134} 135null_body() { 136 check_fs 137 touch foo 138 atf_check -s exit:0 -o empty setextattr -n user myattr myvalue foo 139 atf_check -s exit:0 -o inline:"myvalue\0\n" getextattr -q user myattr foo 140} 141 142atf_test_case one_user_attr 143one_user_attr_head() { 144 atf_set "descr" "A file with one extended attribute" 145} 146one_user_attr_body() { 147 check_fs 148 touch foo 149 atf_check -s exit:0 -o empty setextattr user myattr myvalue foo 150 atf_check -s exit:0 -o inline:"myattr\n" lsextattr -q user foo 151 atf_check -s exit:0 -o inline:"myvalue\n" getextattr -q user myattr foo 152 atf_check -s exit:0 -o empty rmextattr user myattr foo 153 atf_check -s exit:0 -o empty lsextattr -q user foo 154} 155 156atf_test_case one_system_attr 157one_system_attr_head() { 158 atf_set "descr" "A file with one extended attribute" 159 atf_set "require.user" "root" 160} 161one_system_attr_body() { 162 check_fs 163 touch foo 164 atf_check -s exit:0 -o empty setextattr system myattr myvalue foo 165 atf_check -s exit:0 -o inline:"myattr\n" lsextattr -q system foo 166 atf_check -s exit:0 -o inline:"myvalue\n" getextattr -q system myattr foo 167 atf_check -s exit:0 -o empty rmextattr system myattr foo 168 atf_check -s exit:0 -o empty lsextattr -q system foo 169} 170 171atf_test_case stdin 172stdin_head() { 173 atf_set "descr" "Set attribute value from stdin" 174} 175stdin_body() { 176 check_fs 177 dd if=/dev/random of=infile bs=1k count=8 178 touch foo 179 setextattr -i user myattr foo < infile || atf_fail "setextattr failed" 180 atf_check -s exit:0 -o inline:"myattr\n" lsextattr -q user foo 181 getextattr -qq user myattr foo > outfile || atf_fail "getextattr failed" 182 atf_check -s exit:0 cmp -s infile outfile 183} 184 185atf_test_case stringify 186stringify_head() { 187 atf_set "descr" "Stringify the output of getextattr" 188} 189stringify_body() { 190 check_fs 191 touch foo 192 atf_check -s exit:0 -o empty setextattr user myattr "my value" foo 193 atf_check -s exit:0 -o inline:"\"my\\\040value\"\n" \ 194 getextattr -qs user myattr foo 195} 196 197atf_test_case symlink 198symlink_head() { 199 atf_set "descr" "A symlink to an ordinary file" 200} 201symlink_body() { 202 check_fs 203 touch foo 204 ln -s foo foolink 205 atf_check -s exit:0 -o empty setextattr user myattr myvalue foolink 206 atf_check -s exit:0 -o inline:"myvalue\n" \ 207 getextattr -q user myattr foolink 208 atf_check -s exit:0 -o inline:"myvalue\n" getextattr -q user myattr foo 209} 210 211atf_test_case symlink_nofollow 212symlink_nofollow_head() { 213 atf_set "descr" "Operating directly on a symlink" 214} 215symlink_nofollow_body() { 216 check_fs 217 touch foo 218 ln -s foo foolink 219 # Check that with -h we can operate directly on the link 220 atf_check -s exit:0 -o empty setextattr -h user myattr myvalue foolink 221 atf_check -s exit:0 -o inline:"myvalue\n" \ 222 getextattr -qh user myattr foolink 223 atf_check -s exit:1 -e match:"Attribute not found" \ 224 getextattr user myattr foolink 225 atf_check -s exit:1 -e match:"Attribute not found" \ 226 getextattr user myattr foo 227 228 # Check that with -h we cannot operate on the destination file 229 atf_check -s exit:0 -o empty setextattr user otherattr othervalue foo 230 atf_check -s exit:1 getextattr -qh user otherattr foolink 231} 232 233atf_test_case system_and_user_attrs 234system_and_user_attrs_head() { 235 atf_set "descr" "A file with both system and user extended attributes" 236 atf_set "require.user" "root" 237} 238system_and_user_attrs_body() { 239 check_fs 240 touch foo 241 atf_check -s exit:0 -o empty setextattr user userattr userval foo 242 atf_check -s exit:0 -o empty setextattr system sysattr sysval foo 243 atf_check -s exit:0 -o inline:"userattr\n" lsextattr -q user foo 244 atf_check -s exit:0 -o inline:"sysattr\n" lsextattr -q system foo 245 246 atf_check -s exit:0 -o inline:"userval\n" getextattr -q user userattr foo 247 atf_check -s exit:0 -o inline:"sysval\n" getextattr -q system sysattr foo 248 atf_check -s exit:0 -o empty rmextattr user userattr foo 249 atf_check -s exit:0 -o empty rmextattr system sysattr foo 250 atf_check -s exit:0 -o empty lsextattr -q user foo 251 atf_check -s exit:0 -o empty lsextattr -q system foo 252} 253 254atf_test_case two_files 255two_files_head() { 256 atf_set "descr" "Manipulate two files" 257} 258two_files_body() { 259 check_fs 260 touch foo bar 261 atf_check -s exit:0 -o empty setextattr user myattr myvalue foo bar 262 atf_check -s exit:0 -o inline:"foo\tmyattr\nbar\tmyattr\n" \ 263 lsextattr user foo bar 264 atf_check -s exit:0 \ 265 -o inline:"foo\tmyvalue\nbar\tmyvalue\n" \ 266 getextattr user myattr foo bar 267 atf_check -s exit:0 -o empty rmextattr user myattr foo bar 268 atf_check -s exit:0 -o empty lsextattr -q user foo bar 269} 270 271atf_test_case two_files_force 272two_files_force_head() { 273 atf_set "descr" "Manipulate two files. The first does not exist" 274} 275two_files_force_body() { 276 check_fs 277 touch bar 278 atf_check -s exit:1 -e match:"No such file or directory" \ 279 setextattr user myattr myvalue foo bar 280 atf_check -s exit:0 -e ignore setextattr -f user myattr myvalue foo bar 281 atf_check -s exit:1 -e match:"No such file or directory" \ 282 lsextattr user foo bar 283 atf_check -s exit:0 -e ignore -o inline:"bar\tmyattr\n" \ 284 lsextattr -f user foo bar 285 atf_check -s exit:1 -e match:"No such file or directory" \ 286 getextattr user myattr foo bar 287 atf_check -s exit:0 -e ignore \ 288 -o inline:"bar\tmyvalue\n" \ 289 getextattr -f user myattr foo bar 290 atf_check -s exit:1 -e match:"No such file or directory" \ 291 rmextattr user myattr foo bar 292 atf_check -s exit:0 -e ignore \ 293 rmextattr -f user myattr foo bar 294 atf_check -s exit:0 -o empty lsextattr -q user bar 295} 296 297atf_test_case two_user_attrs 298two_user_attrs_head() { 299 atf_set "descr" "A file with two extended attributes" 300} 301two_user_attrs_body() { 302 check_fs 303 touch foo 304 atf_check -s exit:0 -o empty setextattr user myattr1 myvalue1 foo 305 atf_check -s exit:0 -o empty setextattr user myattr2 myvalue2 foo 306 # lsextattr could return the attributes in any order, so we must be 307 # careful how we compare them. 308 raw_output=`lsextattr -q user foo` || atf_fail "lsextattr failed" 309 tabless_output=`printf "%s %s" ${raw_output}` 310 if [ "myattr1 myattr2" != "${tabless_output}" -a \ 311 "myattr2 myattr1" != "${tabless_output}" ]; then 312 atf_fail "lsextattr printed ${tabless_output}" 313 fi 314 atf_check -s exit:0 -o inline:"myvalue1\n" getextattr -q user myattr1 foo 315 atf_check -s exit:0 -o inline:"myvalue2\n" getextattr -q user myattr2 foo 316 atf_check -s exit:0 -o empty rmextattr user myattr2 foo 317 atf_check -s exit:0 -o empty rmextattr user myattr1 foo 318 atf_check -s exit:0 -o empty lsextattr -q user foo 319} 320 321atf_test_case unprivileged_user_cannot_set_system_attr 322unprivileged_user_cannot_set_system_attr_head() { 323 atf_set "descr" "Unprivileged users can't set system attributes" 324 atf_set "require.user" "unprivileged" 325} 326unprivileged_user_cannot_set_system_attr_body() { 327 check_fs 328 touch foo 329 atf_check -s exit:1 -e match:"Operation not permitted" \ 330 setextattr system myattr myvalue foo 331} 332 333 334atf_init_test_cases() { 335 atf_add_test_case bad_namespace 336 atf_add_test_case hex 337 atf_add_test_case hex_nonascii 338 atf_add_test_case long_name 339 atf_add_test_case loud 340 atf_add_test_case noattrs 341 atf_add_test_case nonexistent_file 342 atf_add_test_case null 343 atf_add_test_case symlink_nofollow 344 atf_add_test_case one_user_attr 345 atf_add_test_case one_system_attr 346 atf_add_test_case stdin 347 atf_add_test_case stringify 348 atf_add_test_case symlink 349 atf_add_test_case symlink_nofollow 350 atf_add_test_case system_and_user_attrs 351 atf_add_test_case two_files 352 atf_add_test_case two_files_force 353 atf_add_test_case two_user_attrs 354 atf_add_test_case unprivileged_user_cannot_set_system_attr 355} 356 357check_fs() { 358 case `df -T . | tail -n 1 | cut -wf 2` in 359 "ufs") 360 case `dumpfs . | head -1 | awk -F'[()]' '{print $2}'` in 361 "UFS1") atf_skip "UFS1 is not supported by this test";; 362 "UFS2") ;; # UFS2 is fine 363 esac ;; 364 "zfs") ;; # ZFS is fine 365 "tmpfs") atf_skip "tmpfs does not support extended attributes";; 366 esac 367} 368