Index: stable/10/usr.sbin/extattr/Makefile =================================================================== --- stable/10/usr.sbin/extattr/Makefile (revision 301144) +++ stable/10/usr.sbin/extattr/Makefile (revision 301145) @@ -1,14 +1,22 @@ # $FreeBSD$ +.include + PROG= rmextattr MAN= rmextattr.8 +LDADD= -lsbuf + LINKS+= ${BINDIR}/rmextattr ${BINDIR}/getextattr LINKS+= ${BINDIR}/rmextattr ${BINDIR}/setextattr LINKS+= ${BINDIR}/rmextattr ${BINDIR}/lsextattr MLINKS+= rmextattr.8 setextattr.8 MLINKS+= rmextattr.8 getextattr.8 MLINKS+= rmextattr.8 lsextattr.8 + +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif .include Index: stable/10/usr.sbin/extattr/rmextattr.8 =================================================================== --- stable/10/usr.sbin/extattr/rmextattr.8 (revision 301144) +++ stable/10/usr.sbin/extattr/rmextattr.8 (revision 301145) @@ -1,135 +1,143 @@ .\"- .\" Copyright (c) 2000, 2001 Robert N. M. Watson .\" Copyright (c) 2002 Networks Associates Technology, Inc. .\" All rights reserved. .\" .\" This software was developed for the FreeBSD Project by Poul-Henning .\" Kamp and Network Associates Laboratories, the Security Research Division .\" of Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 .\" ("CBOSS"), as part of the DARPA CHATS research program .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" -.Dd August 30, 2000 +.Dd April 27, 2016 .Dt RMEXTATTR 8 .Os .Sh NAME .Nm getextattr , .Nm lsextattr , .Nm rmextattr , .Nm setextattr .Nd manipulate extended attributes .Sh SYNOPSIS .Nm getextattr .Op Fl fhqsx .Ar attrnamespace .Ar attrname .Ar filename ... .Nm lsextattr .Op Fl fhq .Ar attrnamespace .Ar filename ... .Nm rmextattr .Op Fl fhq .Ar attrnamespace .Ar attrname .Ar filename ... .Nm setextattr .Op Fl fhnq .Ar attrnamespace .Ar attrname .Ar attrvalue .Ar filename ... +.Nm setextattr +.Fl i +.Op Fl fhnq +.Ar attrnamespace +.Ar attrname +.Ar filename ... .Sh DESCRIPTION These utilities are user tools to manipulate the named extended attributes on files and directories. The .Ar attrnamespace argument should be the namespace of the attribute to retrieve: legal values are .Cm user and .Cm system . The .Ar attrname argument should be the name of the attribute, .Ar filename the name of the target file or directory, .Ar attrvalue a string to store in the attribute. .Pp The following options are available: .Bl -tag -width indent .It Fl f (Force.) Ignore errors on individual filenames and continue with the remaining arguments. .It Fl h (No follow.) If the file is a symbolic link, perform the operation on the link itself rather than the file that the link points to. +.It Fl i +(From stdin.) +Read attribute data from stdin instead of as an argument. .It Fl n .Dv ( NUL Ns -terminate.) .Dv NUL Ns -terminate the extent content written out. .It Fl q (Quiet.) Do not print out the pathname and suppress error messages. +When given twice, print only the attribute value, with no trailing newline. .It Fl s (Stringify.) Escape nonprinting characters and put quotes around the output. .It Fl x (Hex.) Print the output in hexadecimal. .El .Sh EXAMPLES .Bd -literal setextattr system md5 `md5 -q /boot/kernel/kernel` /boot/kernel/kernel +md5 -q /boot/kernel/kernel | setextattr -i system md5 /boot/kernel/kernel getextattr system md5 /boot/kernel/kernel +getextattr -qq system md5 /boot/kernel/kernel | od -x lsextattr system /boot/kernel/kernel rmextattr system md5 /boot/kernel/kernel .Ed .Sh SEE ALSO .Xr extattr 2 , .Xr extattr 3 , .Xr extattrctl 8 , .Xr extattr 9 .Sh HISTORY Extended attribute support was developed as part of the .Tn TrustedBSD Project, and introduced in .Fx 5.0 . It was developed to support security extensions requiring additional labels to be associated with each file or directory. .Sh AUTHORS .An Robert N M Watson .An Poul-Henning Kamp -.Sh BUGS -The -.Nm setextattr -utility can only be used to set attributes to strings. Index: stable/10/usr.sbin/extattr/rmextattr.c =================================================================== --- stable/10/usr.sbin/extattr/rmextattr.c (revision 301144) +++ stable/10/usr.sbin/extattr/rmextattr.c (revision 301145) @@ -1,296 +1,315 @@ /*- * Copyright (c) 2002, 2003 Networks Associates Technology, Inc. * Copyright (c) 2002 Poul-Henning Kamp. * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson * All rights reserved. * * This software was developed for the FreeBSD Project by Poul-Henning * Kamp and Network Associates Laboratories, the Security Research Division * of Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 * ("CBOSS"), as part of the DARPA CHATS research program * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include +#include #include #include #include #include #include #include #include #include #include #include #include static enum { EADUNNO, EAGET, EASET, EARM, EALS } what = EADUNNO; static void __dead2 usage(void) { switch (what) { case EAGET: fprintf(stderr, "usage: getextattr [-fhqsx] attrnamespace"); fprintf(stderr, " attrname filename ...\n"); exit(-1); case EASET: fprintf(stderr, "usage: setextattr [-fhnq] attrnamespace"); fprintf(stderr, " attrname attrvalue filename ...\n"); + fprintf(stderr, " or setextattr -i [-fhnq] attrnamespace"); + fprintf(stderr, " attrname filename ...\n"); exit(-1); case EARM: fprintf(stderr, "usage: rmextattr [-fhq] attrnamespace"); fprintf(stderr, " attrname filename ...\n"); exit(-1); case EALS: fprintf(stderr, "usage: lsextattr [-fhq] attrnamespace"); fprintf(stderr, " filename ...\n"); exit(-1); case EADUNNO: default: fprintf(stderr, "usage: (getextattr|lsextattr|rmextattr"); fprintf(stderr, "|setextattr)\n"); exit (-1); } } static void mkbuf(char **buf, int *oldlen, int newlen) { if (*oldlen >= newlen) return; if (*buf != NULL) free(*buf); *buf = malloc(newlen); if (*buf == NULL) err(1, "malloc"); *oldlen = newlen; return; } int main(int argc, char *argv[]) { - char *buf, *visbuf, *p; +#define STDIN_BUF_SZ 1024 + char stdin_data[STDIN_BUF_SZ]; + char *p; const char *options, *attrname; size_t len; ssize_t ret; - int buflen, visbuflen, ch, error, i, arg_counter, attrnamespace, - minargc; + int ch, error, i, arg_counter, attrnamespace, minargc; + char *visbuf = NULL; + int visbuflen = 0; + char *buf = NULL; + int buflen = 0; + struct sbuf *attrvalue = NULL; int flag_force = 0; int flag_nofollow = 0; int flag_null = 0; - int flag_quiet = 0; + int count_quiet = 0; + int flag_from_stdin = 0; int flag_string = 0; int flag_hex = 0; - visbuflen = buflen = 0; - visbuf = buf = NULL; - p = basename(argv[0]); if (p == NULL) p = argv[0]; if (!strcmp(p, "getextattr")) { what = EAGET; options = "fhqsx"; minargc = 3; } else if (!strcmp(p, "setextattr")) { what = EASET; - options = "fhnq"; - minargc = 4; + options = "fhinq"; + minargc = 3; } else if (!strcmp(p, "rmextattr")) { what = EARM; options = "fhq"; minargc = 3; } else if (!strcmp(p, "lsextattr")) { what = EALS; options = "fhq"; minargc = 2; } else { usage(); } while ((ch = getopt(argc, argv, options)) != -1) { switch (ch) { case 'f': flag_force = 1; break; case 'h': flag_nofollow = 1; break; + case 'i': + flag_from_stdin = 1; + break; case 'n': flag_null = 1; break; case 'q': - flag_quiet = 1; + count_quiet += 1; break; case 's': flag_string = 1; break; case 'x': flag_hex = 1; break; case '?': default: usage(); } } argc -= optind; argv += optind; + if (what == EASET && flag_from_stdin == 0) + minargc++; + if (argc < minargc) usage(); error = extattr_string_to_namespace(argv[0], &attrnamespace); if (error) err(-1, "%s", argv[0]); argc--; argv++; if (what != EALS) { attrname = argv[0]; argc--; argv++; } else attrname = NULL; if (what == EASET) { - mkbuf(&buf, &buflen, strlen(argv[0]) + 1); - strcpy(buf, argv[0]); - argc--; argv++; + attrvalue = sbuf_new_auto(); + if (flag_from_stdin) { + while ((error = read(0, stdin_data, STDIN_BUF_SZ)) > 0) + sbuf_bcat(attrvalue, stdin_data, error); + } else { + sbuf_cpy(attrvalue, argv[0]); + argc--; argv++; + } + sbuf_finish(attrvalue); } for (arg_counter = 0; arg_counter < argc; arg_counter++) { switch (what) { case EARM: if (flag_nofollow) error = extattr_delete_link(argv[arg_counter], attrnamespace, attrname); else error = extattr_delete_file(argv[arg_counter], attrnamespace, attrname); if (error >= 0) continue; break; case EASET: - len = strlen(buf) + flag_null; + len = sbuf_len(attrvalue) + flag_null; if (flag_nofollow) ret = extattr_set_link(argv[arg_counter], - attrnamespace, attrname, buf, len); + attrnamespace, attrname, + sbuf_data(attrvalue), len); else ret = extattr_set_file(argv[arg_counter], - attrnamespace, attrname, buf, len); + attrnamespace, attrname, + sbuf_data(attrvalue), len); if (ret >= 0) { - if ((size_t)ret != len && !flag_quiet) { + if ((size_t)ret != len && !count_quiet) { warnx("Set %zd bytes of %zu for %s", ret, len, attrname); } continue; } break; case EALS: if (flag_nofollow) ret = extattr_list_link(argv[arg_counter], attrnamespace, NULL, 0); else ret = extattr_list_file(argv[arg_counter], attrnamespace, NULL, 0); if (ret < 0) break; mkbuf(&buf, &buflen, ret); if (flag_nofollow) ret = extattr_list_link(argv[arg_counter], attrnamespace, buf, buflen); else ret = extattr_list_file(argv[arg_counter], attrnamespace, buf, buflen); if (ret < 0) break; - if (!flag_quiet) + if (!count_quiet) printf("%s\t", argv[arg_counter]); for (i = 0; i < ret; i += ch + 1) { /* The attribute name length is unsigned. */ ch = (unsigned char)buf[i]; printf("%s%*.*s", i ? "\t" : "", ch, ch, buf + i + 1); } - if (!flag_quiet || ret > 0) + if (!count_quiet || ret > 0) printf("\n"); continue; case EAGET: if (flag_nofollow) ret = extattr_get_link(argv[arg_counter], attrnamespace, attrname, NULL, 0); else ret = extattr_get_file(argv[arg_counter], attrnamespace, attrname, NULL, 0); if (ret < 0) break; mkbuf(&buf, &buflen, ret); if (flag_nofollow) ret = extattr_get_link(argv[arg_counter], attrnamespace, attrname, buf, buflen); else ret = extattr_get_file(argv[arg_counter], attrnamespace, attrname, buf, buflen); if (ret < 0) break; - if (!flag_quiet) + if (!count_quiet) printf("%s\t", argv[arg_counter]); if (flag_string) { mkbuf(&visbuf, &visbuflen, ret * 4 + 1); strvisx(visbuf, buf, ret, VIS_SAFE | VIS_WHITE); - printf("\"%s\"\n", visbuf); - continue; + printf("\"%s\"", visbuf); } else if (flag_hex) { for (i = 0; i < ret; i++) printf("%s%02x", i ? " " : "", - buf[i]); - printf("\n"); - continue; + (unsigned char)buf[i]); } else { fwrite(buf, ret, 1, stdout); - printf("\n"); - continue; } + if (count_quiet < 2) + printf("\n"); + continue; default: break; } - if (!flag_quiet) + if (!count_quiet) warn("%s: failed", argv[arg_counter]); if (flag_force) continue; return(1); } return (0); } Index: stable/10/usr.sbin/extattr/tests/Makefile =================================================================== --- stable/10/usr.sbin/extattr/tests/Makefile (nonexistent) +++ stable/10/usr.sbin/extattr/tests/Makefile (revision 301145) @@ -0,0 +1,7 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/usr.sbin/extattr + +ATF_TESTS_SH= extattr_test + +.include Property changes on: stable/10/usr.sbin/extattr/tests/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/usr.sbin/extattr/tests/extattr_test.sh =================================================================== --- stable/10/usr.sbin/extattr/tests/extattr_test.sh (nonexistent) +++ stable/10/usr.sbin/extattr/tests/extattr_test.sh (revision 301145) @@ -0,0 +1,335 @@ +# +# Copyright (c) 2016 Spectra Logic Corp +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ + +atf_test_case bad_namespace +bad_namespace_head() { + atf_set "descr" "Can't set attributes for nonexistent namespaces" +} +bad_namespace_body() { + touch foo + atf_check -s not-exit:0 -e match:"Invalid argument" \ + setextattr badnamespace myattr X foo + atf_check -s not-exit:0 -e match:"Invalid argument" \ + lsextattr -q badnamespace foo +} + +atf_test_case hex +hex_head() { + atf_set "descr" "Set and get attribute values in hexadecimal" +} +hex_body() { + touch foo + atf_check -s exit:0 -o empty setextattr user myattr XYZ foo + atf_check -s exit:0 -o inline:"58 59 5a\n" \ + getextattr -qx user myattr foo +} + +atf_test_case hex_nonascii +hex_nonascii_head() { + atf_set "descr" "Get binary attribute values in hexadecimal" +} +hex_nonascii_body() { + touch foo + BINSTUFF=`echo $'\x20\x30\x40\x55\x66\x70\x81\xa2\xb3\xee\xff'` + atf_check -s exit:0 -o empty setextattr user myattr "$BINSTUFF" foo + getextattr user myattr foo + atf_check -s exit:0 -o inline:"20 30 40 55 66 70 81 a2 b3 ee ff\n" \ + getextattr -qx user myattr foo +} + +atf_test_case long_name +long_name_head() { + atf_set "descr" "A maximum length attribute name" +} +long_name_body() { + # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=208965 + atf_expect_fail "BUG 208965 extattr(2) doesn't allow maxlen attr names" + + ATTRNAME=`jot -b X -s "" 255 0` + touch foo + atf_check -s exit:0 -o empty setextattr user $ATTRNAME myvalue foo + atf_check -s exit:0 -o inline:"${ATTRNAME}\n" lsextattr -q user foo + atf_check -s exit:0 -o inline:"myvalue\n" \ + getextattr -q user ${ATTRNAME} foo + atf_check -s exit:0 -o empty rmextattr user ${ATTRNAME} foo + atf_check -s exit:0 -o empty lsextattr -q user foo +} + +atf_test_case loud +loud_head() { + atf_set "descr" "Loud (non -q) output for each command" +} +loud_body() { + touch foo + # setextattr(8) and friends print hard tabs. Use printf to convert + # them to spaces before checking the output. + atf_check -s exit:0 -o empty setextattr user myattr myvalue foo + atf_check -s exit:0 -o inline:"foo myattr" \ + printf "%s %s" $(lsextattr user foo) + atf_check -s exit:0 -o inline:"foo myvalue" \ + printf "%s %s" $(getextattr user myattr foo) + atf_check -s exit:0 -o empty rmextattr user myattr foo + atf_check -s exit:0 -o inline:"foo" printf %s $(lsextattr user foo) +} + +atf_test_case noattrs +noattrs_head() { + atf_set "descr" "A file with no extended attributes" +} +noattrs_body() { + touch foo + atf_check -s exit:0 -o empty lsextattr -q user foo +} + +atf_test_case nonexistent_file +nonexistent_file_head() { + atf_set "descr" "A file that does not exist" +} +nonexistent_file_body() { + atf_check -s exit:1 -e match:"No such file or directory" \ + lsextattr user foo + atf_check -s exit:1 -e match:"No such file or directory" \ + setextattr user myattr myvalue foo + atf_check -s exit:1 -e match:"No such file or directory" \ + getextattr user myattr foo + atf_check -s exit:1 -e match:"No such file or directory" \ + rmextattr user myattr foo +} + +atf_test_case null +null_head() { + atf_set "descr" "NUL-terminate an attribute value" +} +null_body() { + touch foo + atf_check -s exit:0 -o empty setextattr -n user myattr myvalue foo + atf_check -s exit:0 -o inline:"myvalue\0\n" getextattr -q user myattr foo +} + +atf_test_case one_user_attr +one_user_attr_head() { + atf_set "descr" "A file with one extended attribute" +} +one_user_attr_body() { + touch foo + atf_check -s exit:0 -o empty setextattr user myattr myvalue foo + atf_check -s exit:0 -o inline:"myattr\n" lsextattr -q user foo + atf_check -s exit:0 -o inline:"myvalue\n" getextattr -q user myattr foo + atf_check -s exit:0 -o empty rmextattr user myattr foo + atf_check -s exit:0 -o empty lsextattr -q user foo +} + +atf_test_case one_system_attr +one_system_attr_head() { + atf_set "descr" "A file with one extended attribute" + atf_set "require.user" "root" +} +one_system_attr_body() { + touch foo + atf_check -s exit:0 -o empty setextattr system myattr myvalue foo + atf_check -s exit:0 -o inline:"myattr\n" lsextattr -q system foo + atf_check -s exit:0 -o inline:"myvalue\n" getextattr -q system myattr foo + atf_check -s exit:0 -o empty rmextattr system myattr foo + atf_check -s exit:0 -o empty lsextattr -q system foo +} + +atf_test_case stdin +stdin_head() { + atf_set "descr" "Set attribute value from stdin" +} +stdin_body() { + dd if=/dev/random of=infile bs=1k count=8 + touch foo + setextattr -i user myattr foo < infile || atf_fail "setextattr failed" + atf_check -s exit:0 -o inline:"myattr\n" lsextattr -q user foo + getextattr -qq user myattr foo > outfile || atf_fail "getextattr failed" + atf_check -s exit:0 cmp -s infile outfile +} + +atf_test_case stringify +stringify_head() { + atf_set "descr" "Stringify the output of getextattr" +} +stringify_body() { + touch foo + atf_check -s exit:0 -o empty setextattr user myattr "my value" foo + atf_check -s exit:0 -o inline:"\"my\\\040value\"\n" \ + getextattr -qs user myattr foo +} + +atf_test_case symlink +symlink_head() { + atf_set "descr" "A symlink to an ordinary file" +} +symlink_body() { + touch foo + ln -s foo foolink + atf_check -s exit:0 -o empty setextattr user myattr myvalue foolink + atf_check -s exit:0 -o inline:"myvalue\n" \ + getextattr -q user myattr foolink + atf_check -s exit:0 -o inline:"myvalue\n" getextattr -q user myattr foo +} + +atf_test_case symlink_nofollow +symlink_nofollow_head() { + atf_set "descr" "Operating directly on a symlink" +} +symlink_nofollow_body() { + touch foo + ln -s foo foolink + # Check that with -h we can operate directly on the link + atf_check -s exit:0 -o empty setextattr -h user myattr myvalue foolink + atf_check -s exit:0 -o inline:"myvalue\n" \ + getextattr -qh user myattr foolink + atf_check -s exit:1 -e match:"Attribute not found" \ + getextattr user myattr foolink + atf_check -s exit:1 -e match:"Attribute not found" \ + getextattr user myattr foo + + # Check that with -h we cannot operate on the destination file + atf_check -s exit:0 -o empty setextattr user otherattr othervalue foo + atf_check -s exit:1 getextattr -qh user otherattr foolink +} + +atf_test_case system_and_user_attrs +system_and_user_attrs_head() { + atf_set "descr" "A file with both system and user extended attributes" + atf_set "require.user" "root" +} +system_and_user_attrs_body() { + touch foo + atf_check -s exit:0 -o empty setextattr user userattr userval foo + atf_check -s exit:0 -o empty setextattr system sysattr sysval foo + atf_check -s exit:0 -o inline:"userattr\n" lsextattr -q user foo + atf_check -s exit:0 -o inline:"sysattr\n" lsextattr -q system foo + + atf_check -s exit:0 -o inline:"userval\n" getextattr -q user userattr foo + atf_check -s exit:0 -o inline:"sysval\n" getextattr -q system sysattr foo + atf_check -s exit:0 -o empty rmextattr user userattr foo + atf_check -s exit:0 -o empty rmextattr system sysattr foo + atf_check -s exit:0 -o empty lsextattr -q user foo + atf_check -s exit:0 -o empty lsextattr -q system foo +} + +atf_test_case two_files +two_files_head() { + atf_set "descr" "Manipulate two files" +} +two_files_body() { + touch foo bar + atf_check -s exit:0 -o empty setextattr user myattr myvalue foo bar + atf_check -s exit:0 -o inline:"foo\tmyattr\nbar\tmyattr\n" \ + lsextattr user foo bar + atf_check -s exit:0 \ + -o inline:"foo\tmyvalue\nbar\tmyvalue\n" \ + getextattr user myattr foo bar + atf_check -s exit:0 -o empty rmextattr user myattr foo bar + atf_check -s exit:0 -o empty lsextattr -q user foo bar +} + +atf_test_case two_files_force +two_files_force_head() { + atf_set "descr" "Manipulate two files. The first does not exist" +} +two_files_force_body() { + touch bar + atf_check -s exit:1 -e match:"No such file or directory" \ + setextattr user myattr myvalue foo bar + atf_check -s exit:0 -e ignore setextattr -f user myattr myvalue foo bar + atf_check -s exit:1 -e match:"No such file or directory" \ + lsextattr user foo bar + atf_check -s exit:0 -e ignore -o inline:"bar\tmyattr\n" \ + lsextattr -f user foo bar + atf_check -s exit:1 -e match:"No such file or directory" \ + getextattr user myattr foo bar + atf_check -s exit:0 -e ignore \ + -o inline:"bar\tmyvalue\n" \ + getextattr -f user myattr foo bar + atf_check -s exit:1 -e match:"No such file or directory" \ + rmextattr user myattr foo bar + atf_check -s exit:0 -e ignore \ + rmextattr -f user myattr foo bar + atf_check -s exit:0 -o empty lsextattr -q user bar +} + +atf_test_case two_user_attrs +two_user_attrs_head() { + atf_set "descr" "A file with two extended attributes" +} +two_user_attrs_body() { + touch foo + atf_check -s exit:0 -o empty setextattr user myattr1 myvalue1 foo + atf_check -s exit:0 -o empty setextattr user myattr2 myvalue2 foo + # lsextattr could return the attributes in any order, so we must be + # careful how we compare them. + raw_output=`lsextattr -q user foo` || atf_fail "lsextattr failed" + tabless_output=`printf "%s %s" ${raw_output}` + if [ "myattr1 myattr2" != "${tabless_output}" -a \ + "myattr2 myattr1" != "${tabless_output}" ]; then + atf_fail "lsextattr printed ${tabless_output}" + fi + atf_check -s exit:0 -o inline:"myvalue1\n" getextattr -q user myattr1 foo + atf_check -s exit:0 -o inline:"myvalue2\n" getextattr -q user myattr2 foo + atf_check -s exit:0 -o empty rmextattr user myattr2 foo + atf_check -s exit:0 -o empty rmextattr user myattr1 foo + atf_check -s exit:0 -o empty lsextattr -q user foo +} + +atf_test_case unprivileged_user_cannot_set_system_attr +unprivileged_user_cannot_set_system_attr_head() { + atf_set "descr" "Unprivileged users can't set system attributes" + atf_set "require.user" "unprivileged" +} +unprivileged_user_cannot_set_system_attr_body() { + touch foo + atf_check -s exit:1 -e match:"Operation not permitted" \ + setextattr system myattr myvalue foo +} + + +atf_init_test_cases() { + atf_add_test_case bad_namespace + atf_add_test_case hex + atf_add_test_case hex_nonascii + atf_add_test_case long_name + atf_add_test_case loud + atf_add_test_case noattrs + atf_add_test_case nonexistent_file + atf_add_test_case null + atf_add_test_case symlink_nofollow + atf_add_test_case one_user_attr + atf_add_test_case one_system_attr + atf_add_test_case stdin + atf_add_test_case stringify + atf_add_test_case symlink + atf_add_test_case symlink_nofollow + atf_add_test_case system_and_user_attrs + atf_add_test_case two_files + atf_add_test_case two_files_force + atf_add_test_case two_user_attrs + atf_add_test_case unprivileged_user_cannot_set_system_attr +} Property changes on: stable/10/usr.sbin/extattr/tests/extattr_test.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property