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