Module Name: src
Committed By: manu
Date: Thu Jul 14 15:25:27 UTC 2011
Modified Files:
src/usr.bin/extattr: getextattr.1 getextattr.c
Log Message:
Improve extended attribute commands:
- allow namespace to be omitted when using a namespace-prefixed attribute
name, a la Linux.
- Improve hexdump for getextattr -x
- Add more display option for binary attributes, using vis(3)
- Add a -i option to setextattr to get the attribute value from file, so
that we can set binary values
To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/usr.bin/extattr/getextattr.1
cvs rdiff -u -r1.7 -r1.8 src/usr.bin/extattr/getextattr.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.bin/extattr/getextattr.1
diff -u src/usr.bin/extattr/getextattr.1:1.3 src/usr.bin/extattr/getextattr.1:1.4
--- src/usr.bin/extattr/getextattr.1:1.3 Fri Jun 17 18:19:58 2011
+++ src/usr.bin/extattr/getextattr.1 Thu Jul 14 15:25:27 2011
@@ -1,4 +1,4 @@
-.\" $NetBSD: getextattr.1,v 1.3 2011/06/17 18:19:58 wiz Exp $
+.\" $NetBSD: getextattr.1,v 1.4 2011/07/14 15:25:27 manu Exp $
.\"
.\"-
.\" Copyright (c) 2000, 2001 Robert N. M. Watson
@@ -44,35 +44,61 @@
.Nd manipulate extended attributes
.Sh SYNOPSIS
.Nm getextattr
-.Op Fl fhqsx
-.Ar attrnamespace
+.Op Fl fhq
+.Op Fl s | Fl x | Fl v Ar style
+.Op Ar namespace
.Ar attrname
.Ar filename ...
.Nm lsextattr
.Op Fl fhq
-.Ar attrnamespace
+.Ar namespace
.Ar filename ...
.Nm rmextattr
.Op Fl fhq
-.Ar attrnamespace
+.Op Ar namespace
.Ar attrname
.Ar filename ...
.Nm setextattr
.Op Fl fhnq
-.Ar attrnamespace
+.Op Ar namespace
.Ar attrname
.Ar attrvalue
.Ar filename ...
+.Nm setextattr
+.Op Fl fhnq
+.Fl i Ar valuefile
+.Op Ar namespace
+.Ar attrname
+.Ar filename ...
.Sh DESCRIPTION
These utilities are user tools to manipulate the named extended
attributes on files and directories.
+.Pp
The
-.Ar attrnamespace
+.Ar namespace
argument should be the namespace of the attribute to retrieve: legal
values are
.Cm user
and
.Cm system .
+For all operations except
+.Nm lsextattr ,
+the namespace argument may be omitted if the attribute name is namespace
+prefixed, like in
+.Cm user.test .
+In that later case, the
+.Cm user
+namespace prefix obviously selects
+.Cm user
+namespace.
+.Cm system ,
+.Cm security ,
+and
+.Cm trusted
+namespace prefixes select the
+.Cm system
+namespace.
+.Pp
The
.Ar attrname
argument should be the name of the attribute,
@@ -91,6 +117,11 @@
(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 Ar valuefile
+(Input file.)
+Read the attribute value from file
+.Ar valuefile .
+Use this flag in order to set a binary value for an attribute.
.It Fl n
.Dv ( NUL Ns
-terminate.)
@@ -102,6 +133,39 @@
.It Fl s
(Stringify.)
Escape nonprinting characters and put quotes around the output.
+.It Fl v Ar style
+(Visual.)
+Process the attribute value through
+.Xr vis 3 ,
+using
+.Ar style .
+Valid values for
+.Ar style
+are:
+.Bl -tag -width indent
+.It Ar default
+Use default
+.Xr vis 3
+encoding.
+.It Ar c
+Use C-style backslash sequences, like in
+.Nm vis Fl c .
+.It Ar http
+Use URI encoding from RFC 1808, like in
+.Nm vis Fl h .
+.It Ar octal
+Display in octal, like in
+.Nm vis Fl o .
+.It Ar vis
+Alias for
+.Ar default .
+.It Ar cstyle
+Alias for
+.Ar c .
+.It Ar httpstyle
+Alias for
+.Ar http .
+.El
.It Fl x
(Hex.)
Print the output in hexadecimal.
@@ -113,6 +177,12 @@
lsextattr system /boot/kernel/kernel
rmextattr system md5 /boot/kernel/kernel
.Ed
+.Pp
+Examples omitting namespace (and attribute value) argument:
+.Bd -literal
+setextattr -i valuefile trusted.gfid /export/wd3a
+getextattr -x trusted.gfid /export/wd3a
+.Ed
.Sh SEE ALSO
.\" .Xr extattr 2 ,
.Xr extattr 3 ,
@@ -128,10 +198,10 @@
.Nx 3.0 .
It was developed to support security extensions requiring additional labels
to be associated with each file or directory.
+.Pp
+Exented attribute support was resurected and made more usable in
+.Nx 5.2 .
.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.
+.An Emmanuel Dreyfus
Index: src/usr.bin/extattr/getextattr.c
diff -u src/usr.bin/extattr/getextattr.c:1.7 src/usr.bin/extattr/getextattr.c:1.8
--- src/usr.bin/extattr/getextattr.c:1.7 Mon Jul 4 08:07:32 2011
+++ src/usr.bin/extattr/getextattr.c Thu Jul 14 15:25:27 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: getextattr.c,v 1.7 2011/07/04 08:07:32 manu Exp $ */
+/* $NetBSD: getextattr.c,v 1.8 2011/07/14 15:25:27 manu Exp $ */
/*-
* Copyright (c) 2002, 2003 Networks Associates Technology, Inc.
@@ -50,6 +50,8 @@
#include <string.h>
#include <unistd.h>
#include <vis.h>
+#include <fcntl.h>
+#include <sys/stat.h>
//#include <util.h>
static enum { EADUNNO, EAGET, EASET, EARM, EALS } what = EADUNNO;
@@ -60,7 +62,7 @@
switch (what) {
case EAGET:
- fprintf(stderr, "usage: %s [-fhqsx] "
+ fprintf(stderr, "usage: %s [-fhq] [-s | -x | -v style] "
"attrnamespace attrname filename ...\n", getprogname());
exit(1);
@@ -68,6 +70,9 @@
fprintf(stderr, "usage: %s [-fhnq] "
"attrnamespace attrname attrvalue filename ...\n",
getprogname());
+ fprintf(stderr, "usage: %s [-fhnq] -i attrvalue_file "
+ "attrnamespace attrname filename ...\n",
+ getprogname());
exit(1);
case EARM:
@@ -103,6 +108,58 @@
return;
}
+static int
+parse_flag_vis(const char *opt)
+{
+ if (strcmp(opt, "default") == 0)
+ return 0;
+ else if (strcmp(opt, "cstyle") == 0)
+ return VIS_CSTYLE;
+ else if (strcmp(opt, "octal") == 0)
+ return VIS_OCTAL;
+ else if (strcmp(opt, "httpstyle") == 0)
+ return VIS_HTTPSTYLE;
+
+ /* Convenient aliases */
+ else if (strcmp(opt, "vis") == 0)
+ return 0;
+ else if (strcmp(opt, "c") == 0)
+ return VIS_CSTYLE;
+ else if (strcmp(opt, "http") == 0)
+ return VIS_HTTPSTYLE;
+ else
+ fprintf(stderr, "%s: invalid -s option \"%s\"",
+ getprogname(), opt);
+
+ return -1;
+}
+
+#define HEXDUMP_PRINT(x) ((uint8_t)x >= 32 && (uint8_t)x < 128) ? x : '.'
+static void
+hexdump(const char *addr, size_t len)
+{
+ unsigned int i, j;
+
+ for (i = 0; i < len; i += 16) {
+ printf(" %03x ", i);
+ for (j = 0; j < 16; j++) {
+ if (i + j > len)
+ printf(" ");
+ else
+ printf("%02x ", addr[i + j] & 0xff);
+ }
+ printf(" ");
+ for (j = 0; j < 16; j++) {
+ if (i + j > len)
+ printf(" ");
+ else
+ printf("%c", HEXDUMP_PRINT(addr[i + j]));
+ }
+ printf("\n");
+ }
+}
+#undef HEXDUMP_PRINT
+
int
main(int argc, char *argv[])
{
@@ -111,14 +168,15 @@
const char *options, *attrname;
int buflen, visbuflen, ch, error, i, arg_counter, attrnamespace,
- minargc;
+ minargc, val_len = 0;
int flag_force = 0;
int flag_nofollow = 0;
int flag_null = 0;
int flag_quiet = 0;
- int flag_string = 0;
+ int flag_vis = -1;
int flag_hex = 0;
+ char *filename = NULL;
options = NULL;
minargc = 0;
@@ -128,16 +186,16 @@
p = getprogname();
if (strcmp(p, "getextattr") == 0) {
what = EAGET;
- options = "fhqsx";
- minargc = 3;
+ options = "fhqsxv:";
+ minargc = 2;
} else if (strcmp(p, "setextattr") == 0) {
what = EASET;
- options = "fhnq";
- minargc = 4;
+ options = "fhnqi:";
+ minargc = 3;
} else if (strcmp(p, "rmextattr") == 0) {
what = EARM;
options = "fhq";
- minargc = 3;
+ minargc = 2;
} else if (strcmp(p, "lsextattr") == 0) {
what = EALS;
options = "fhq";
@@ -160,11 +218,18 @@
flag_quiet = 1;
break;
case 's':
- flag_string = 1;
+ flag_vis = VIS_SAFE | VIS_WHITE;
+ break;
+ case 'v':
+ flag_vis = parse_flag_vis(optarg);
break;
case 'x':
flag_hex = 1;
break;
+ case 'i':
+ filename = optarg;
+ minargc--;
+ break;
default:
usage();
}
@@ -173,13 +238,43 @@
argc -= optind;
argv += optind;
+ /*
+ * Check for missing argument.
+ */
if (argc < minargc)
usage();
+ /*
+ * Normal case "namespace attribute".
+ */
error = extattr_string_to_namespace(argv[0], &attrnamespace);
- if (error)
- err(1, "%s", argv[0]);
- argc--; argv++;
+ if (error == 0) {
+ /*
+ * Namespace was specified, so we need one more argument
+ * for the attribute (except for listing)
+ */
+ if ((what != EALS) && (argc < minargc + 1))
+ usage();
+ argc--; argv++;
+ } else {
+ /*
+ * The namespace was not valid. Perhaps it was omited.
+ * Try to guess a missing namespace by using
+ * linux layout "namespace.attribute". While
+ * we are here, also test the Linux namespaces.
+ */
+ if (strstr(argv[0], "user.") == argv[0]) {
+ attrnamespace = EXTATTR_NAMESPACE_USER;
+ } else
+ if ((strstr(argv[0], "system.") == argv[0]) ||
+ (strstr(argv[0], "trusted.") == argv[0]) ||
+ (strstr(argv[0], "security.") == argv[0])) {
+ attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
+ } else {
+ err(1, "%s", argv[0]);
+ }
+ }
+
if (what != EALS) {
attrname = argv[0];
@@ -188,9 +283,38 @@
attrname = NULL;
if (what == EASET) {
- mkbuf(&buf, &buflen, strlen(argv[0]) + 1);
- strcpy(buf, argv[0]); /* safe */
- argc--; argv++;
+ /*
+ * Handle -i option, reading value from a file.
+ */
+ if (filename != NULL) {
+ int fd;
+ struct stat st;
+ ssize_t readen, remain;
+
+ if ((fd = open(filename, O_RDONLY, 0)) == -1)
+ err(1, "%s: cannot open \"%s\"",
+ getprogname(), filename);
+
+ if (fstat(fd, &st) != 0)
+ err(1, "%s: cannot stat \"%s\"",
+ getprogname(), filename);
+
+ val_len = st.st_size;
+ mkbuf(&buf, &buflen, val_len);
+
+ for (remain = val_len; remain > 0; remain -= readen) {
+ if ((readen = read(fd, buf, remain)) == -1)
+ err(1, "%s: cannot read \"%s\"",
+ getprogname(), filename);
+ }
+
+ (void)close(fd);
+ } else {
+ val_len = strlen(argv[0]) + 1;
+ mkbuf(&buf, &buflen, val_len);
+ strcpy(buf, argv[0]); /* safe */
+ argc--; argv++;
+ }
}
for (arg_counter = 0; arg_counter < argc; arg_counter++) {
@@ -209,11 +333,11 @@
if (flag_nofollow)
error = extattr_set_link(argv[arg_counter],
attrnamespace, attrname, buf,
- strlen(buf) + flag_null);
+ val_len + flag_null);
else
error = extattr_set_file(argv[arg_counter],
attrnamespace, attrname, buf,
- strlen(buf) + flag_null);
+ val_len + flag_null);
if (error >= 0)
continue;
break;
@@ -262,17 +386,24 @@
break;
if (!flag_quiet)
printf("%s\t", argv[arg_counter]);
- if (flag_string) {
+
+ /*
+ * Check for binary string and terminal output
+ */
+#if 0
+ for (i = 0; i < error; i++)
+ if (!isprint((int)buf[i]))
+ err(1, "binary data, use -x flag");
+#endif
+
+ if (flag_vis != -1) {
mkbuf(&visbuf, &visbuflen, error * 4 + 1);
- strvisx(visbuf, buf, error,
- VIS_SAFE | VIS_WHITE);
+ strvisx(visbuf, buf, error, flag_vis);
printf("\"%s\"\n", visbuf);
continue;
} else if (flag_hex) {
- for (i = 0; i < error; i++)
- printf("%s%02x", i ? " " : "",
- buf[i]);
printf("\n");
+ hexdump(buf, error);
continue;
} else {
fwrite(buf, buflen, 1, stdout);