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