diff options
author | Peter Stephenson <pws@users.sourceforge.net> | 2009-11-04 11:33:59 +0000 |
---|---|---|
committer | Peter Stephenson <pws@users.sourceforge.net> | 2009-11-04 11:33:59 +0000 |
commit | eeb5b6c941c7ae0ec832e9ce569b23ee02169b26 (patch) | |
tree | 8eb29700ba4d455fc2e96620ebbff96546dfb7c3 | |
parent | a92507d2b8c41daaed6e9a018086392d9600a37a (diff) | |
download | zsh-eeb5b6c941c7ae0ec832e9ce569b23ee02169b26.tar.gz zsh-eeb5b6c941c7ae0ec832e9ce569b23ee02169b26.tar.xz zsh-eeb5b6c941c7ae0ec832e9ce569b23ee02169b26.zip |
Mikael: 27347: enhance extended attribute support
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | Completion/Zsh/Command/_zattr | 4 | ||||
-rw-r--r-- | Doc/Zsh/mod_attr.yo | 5 | ||||
-rw-r--r-- | Src/Modules/attr.c | 210 |
4 files changed, 163 insertions, 64 deletions
diff --git a/ChangeLog b/ChangeLog index 01f1cb8f9..40214da3c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-11-04 Peter Stephenson <pws@csr.com> + + * Mikael: 27347: Completion/Zsh/Command/_zattr, + Doc/Zsh/mod_attr.yo, Src/Modules/attr.c: enhance the + extended attribute support. + 2009-11-03 Peter Stephenson <pws@csr.com> * Mikael: 27337: Src/utils.c: fix bug with cd checking symlinks @@ -12286,5 +12292,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.4800 $ +* $Revision: 1.4801 $ ***************************************************** diff --git a/Completion/Zsh/Command/_zattr b/Completion/Zsh/Command/_zattr index 56c754be6..cdc52281d 100644 --- a/Completion/Zsh/Command/_zattr +++ b/Completion/Zsh/Command/_zattr @@ -29,6 +29,6 @@ _arguments \ esac if [[ $state = attrs ]]; then - zlistattr $~line[1] REPLY - _wanted attrs expl 'attribute' compadd ${(0)REPLY} + zlistattr $~line[1] REPLY 2> /dev/null + _wanted attrs expl 'attribute' compadd $REPLY fi diff --git a/Doc/Zsh/mod_attr.yo b/Doc/Zsh/mod_attr.yo index ed444d0d7..96ac2e011 100644 --- a/Doc/Zsh/mod_attr.yo +++ b/Doc/Zsh/mod_attr.yo @@ -32,3 +32,8 @@ var(filename). If the optional argument var(parameter) is given, the list of attributes is set on that parameter instead of being printed to stdout. ) enditem() + +tt(zgetattr) and tt(zlistattr) allocate memory dynamically. If the +attribute or list of attributes grows between the allocation and the call +to get them, they return 2. On all other errors, 1 is returned. This +allows the calling function to check for this case and retry. diff --git a/Src/Modules/attr.c b/Src/Modules/attr.c index ec3b1e421..88ebb1618 100644 --- a/Src/Modules/attr.c +++ b/Src/Modules/attr.c @@ -33,102 +33,190 @@ #include <sys/types.h> #include <sys/xattr.h> -static int -bin_getattr(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) +static ssize_t +xgetxattr(const char *path, const char *name, void *value, size_t size, int symlink) { - int ret = 0; - int len, slen; - char value[256]; +#ifdef XATTR_EXTRA_ARGS + return getxattr(path, name, value, size, 0, symlink ? XATTR_NOFOLLOW: 0); +#else + switch (symlink) { + case 0: + return getxattr(path, name, value, size); + case 1: + return lgetxattr(path, name, value, size); + } +#endif +} + +static ssize_t +xlistxattr(const char *path, char *list, size_t size, int symlink) +{ +#ifdef XATTR_EXTRA_ARGS + return listxattr(path, list, size, symlink ? XATTR_NOFOLLOW : 0); +#else + switch (symlink) { + case 0: + return listxattr(path, list, size); + case 1: + return llistxattr(path, list, size); + } +#endif +} - unmetafy(*argv, &slen); - unmetafy(*(argv+1), NULL); - if (listxattr(*argv, NULL, 0 +static int +xsetxattr(const char *path, const char *name, const void *value, + size_t size, int flags, int symlink) +{ #ifdef XATTR_EXTRA_ARGS - , 0 + return setxattr(path, name, value, size, 0, flags | symlink ? XATTR_NOFOLLOW : 0); +#else + switch (symlink) { + case 0: + return setxattr(path, name, value, size, flags); + case 1: + return lsetxattr(path, name, value, size, flags); + } #endif - ) > 0) { - if (0 < (len = getxattr(*argv, *(argv+1), value, 255 +} + +static int +xremovexattr(const char *path, const char *name, int symlink) +{ #ifdef XATTR_EXTRA_ARGS - , 0, 0 + return removexattr(path, name, symlink ? XATTR_NOFOLLOW : 0); +#else + switch (symlink) { + case 0: + return removexattr(path, name); + case 1: + return lremovexattr(path, name); + } #endif - ))) { - if (len < 256) { - value[len] = '\0'; - if (*(argv+2)) - setsparam(*(argv+2), metafy(value, len, META_DUP)); +} + +static int +bin_getattr(char *nam, char **argv, Options ops, UNUSED(int func)) +{ + int ret = 0; + int list_len, val_len, attr_len, slen; + char *value, *file = argv[0], *attr = argv[1], *param = argv[2]; + int symlink = OPT_ISSET(ops, 'h'); + + unmetafy(file, &slen); + unmetafy(attr, NULL); + list_len = xlistxattr(file, NULL, 0, symlink); + if (list_len > 0) { + val_len = xgetxattr(file, attr, NULL, 0, symlink); + if (val_len == 0) { + if (param) + unsetparam(param); + return 0; + } + if (val_len > 0) { + value = (char *)zalloc(val_len+1); + attr_len = xgetxattr(file, attr, value, val_len, symlink); + if (attr_len > 0 && attr_len <= val_len) { + value[attr_len] = '\0'; + if (param) + setsparam(param, metafy(value, attr_len, META_DUP)); else printf("%s\n", value); } - } else if (len < 0) { - zwarnnam(nam, "%s: %e", metafy(*argv, slen, META_NOALLOC), errno); - ret = 1; + zfree(value, val_len+1); } } + if (list_len < 0 || val_len < 0 || attr_len < 0) { + zwarnnam(nam, "%s: %e", metafy(file, slen, META_NOALLOC), errno); + ret = 1 + (attr_len > val_len); + } return ret; } static int -bin_setattr(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) +bin_setattr(char *nam, char **argv, Options ops, UNUSED(int func)) { - int ret = 0, slen; + int ret = 0, slen, vlen; + int symlink = OPT_ISSET(ops, 'h'); + char *file = argv[0], *attr = argv[1], *value = argv[2]; - unmetafy(*argv, &slen); - unmetafy(*(argv+1), NULL); - unmetafy(*(argv+2), NULL); - if (setxattr(*argv, *(argv+1), *(argv+2), strlen(*(argv+2)), 0 -#ifdef XATTR_EXTRA_ARGS - , 0 -#endif - )) { - zwarnnam(nam, "%s: %e", metafy(*argv, slen, META_NOALLOC), errno); + unmetafy(file, &slen); + unmetafy(attr, NULL); + unmetafy(value, &vlen); + if (xsetxattr(file, attr, value, vlen, 0, symlink)) { + zwarnnam(nam, "%s: %e", metafy(file, slen, META_NOALLOC), errno); ret = 1; } return ret; } static int -bin_delattr(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) +bin_delattr(char *nam, char **argv, Options ops, UNUSED(int func)) { int ret = 0, slen; + int symlink = OPT_ISSET(ops, 'h'); + char *file = argv[0], **attr = &argv[1]; - unmetafy(*argv, &slen); - unmetafy(*(argv+1), NULL); - if (removexattr(*argv, *(argv+1) -#ifdef XATTR_EXTRA_ARGS - , 0 -#endif - )) { - zwarnnam(nam, "%s: %e", metafy(*argv, slen, META_NOALLOC), errno); - ret = 1; + unmetafy(file, &slen); + while (*++attr) { + unmetafy(*attr, NULL); + if (xremovexattr(file, *attr, symlink)) { + zwarnnam(nam, "%s: %e", metafy(file, slen, META_NOALLOC), errno); + ret = 1; + break; + } } return ret; } static int -bin_listattr(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) +bin_listattr(char *nam, char **argv, Options ops, UNUSED(int func)) { int ret = 0; - int len, slen; - char value[256]; + int val_len, list_len, slen; + char *value, *file = argv[0], *param = argv[1]; + int symlink = OPT_ISSET(ops, 'h'); - unmetafy(*argv, &slen); - if (0 < (len = listxattr(*argv, value, 256 -#ifdef XATTR_EXTRA_ARGS - , 0 -#endif - ))) { - if (len < 256) { + unmetafy(file, &slen); + val_len = xlistxattr(file, NULL, 0, symlink); + if (val_len == 0) { + if (param) + unsetparam(param); + return 0; + } + if (val_len > 0) { + value = (char *)zalloc(val_len+1); + list_len = xlistxattr(file, value, val_len, symlink); + if (list_len > 0 && list_len <= val_len) { char *p = value; - if (*(argv+1)) - setsparam(*(argv+1), metafy(value, len, META_DUP)); - else while (p < &value[len]) { + if (param) { + if (strlen(value) + 1 == list_len) + setsparam(param, metafy(value, list_len-1, META_DUP)); + else { + int arrlen = 0; + char **array = NULL, **arrptr = NULL; + + while (p < &value[list_len]) { + arrlen++; + p += strlen(p) + 1; + } + arrptr = array = (char **)zshcalloc((arrlen+1) * sizeof(char *)); + p = value; + while (p < &value[list_len]) { + *arrptr++ = metafy(p, -1, META_DUP); + p += strlen(p) + 1; + } + setaparam(param, array); + } + } else while (p < &value[list_len]) { printf("%s\n", p); p += strlen(p) + 1; } } - } else if (len < 0) { - zwarnnam(nam, "%s: %e", metafy(*argv, slen, META_NOALLOC), errno); - ret = 1; + zfree(value, val_len+1); + } + if (val_len < 0 || list_len < 0) { + zwarnnam(nam, "%s: %e", metafy(file, slen, META_NOALLOC), errno); + ret = 1 + (list_len > val_len); } return ret; } @@ -136,10 +224,10 @@ bin_listattr(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) /* module paraphernalia */ static struct builtin bintab[] = { - BUILTIN("zgetattr", 0, bin_getattr, 2, 3, 0, NULL, NULL), - BUILTIN("zsetattr", 0, bin_setattr, 3, 3, 0, NULL, NULL), - BUILTIN("zdelattr", 0, bin_delattr, 2, 2, 0, NULL, NULL), - BUILTIN("zlistattr", 0, bin_listattr, 1, 2, 0, NULL, NULL), + BUILTIN("zgetattr", 0, bin_getattr, 2, 3, 0, "h", NULL), + BUILTIN("zsetattr", 0, bin_setattr, 3, 3, 0, "h", NULL), + BUILTIN("zdelattr", 0, bin_delattr, 2, -1, 0, "h", NULL), + BUILTIN("zlistattr", 0, bin_listattr, 1, 2, 0, "h", NULL), }; static struct features module_features = { |