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);