From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 2884 invoked from network); 27 Feb 2009 00:51:00 -0000 X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.6 required=5.0 tests=AWL,BAYES_00,URIBL_SBL autolearn=no version=3.2.5 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by ns1.primenet.com.au with SMTP; 27 Feb 2009 00:51:00 -0000 Received-SPF: none (ns1.primenet.com.au: domain at sunsite.dk does not designate permitted sender hosts) Received: (qmail 459 invoked from network); 27 Feb 2009 00:50:56 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 27 Feb 2009 00:50:56 -0000 Received: (qmail 652 invoked by alias); 27 Feb 2009 00:50:52 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 26619 Received: (qmail 638 invoked from network); 27 Feb 2009 00:50:51 -0000 Received: from bifrost.dotsrc.org (130.225.254.106) by sunsite.dk with SMTP; 27 Feb 2009 00:50:51 -0000 Received: from smtp.bredband2.net (mail3.brikks.com [82.209.166.4]) by bifrost.dotsrc.org (Postfix) with ESMTP id 018938058F83 for ; Fri, 27 Feb 2009 01:50:47 +0100 (CET) Received: (qmail 15646 invoked from network); 26 Feb 2009 22:04:55 -0000 Received: from c-83-233-200-194.cust.bredband2.com (HELO mika.l3ib.org) ([83.233.200.194]) (envelope-sender ) by smtp.bredband2.net (qmail-ldap-1.03) with SMTP for ; 26 Feb 2009 22:04:55 -0000 Date: Thu, 26 Feb 2009 22:55:47 +0100 (CET) From: Mikael Magnusson To: zsh workers Subject: [wip patch] new zsh/attr module Message-ID: User-Agent: Alpine 2.00 (LNX ) MIME-Version: 1.0 Content-Type: TEXT/PLAIN; format=flowed; charset=US-ASCII X-Virus-Scanned: ClamAV 0.92.1/9051/Thu Feb 26 14:08:01 2009 on bifrost X-Virus-Status: Clean Hi, in my .zshrc I have this short function: #usage, *(e:fattr name:) or *(e:fattr name value:) function fattr() { local val="$(getfattr -n user.$1 --only-values $REPLY 2>/dev/null)" [[ -n "$val" && ( -z "$2" || "$val" =~ "$2" ) ]] } The problem is it takes a long time when you run it on some significant set of files since it forks for every file (~10 seconds for hundreds of files). So I cobbled together this module to make three builtins, zgetattr, zsetattr and zdelattr. #usage, *(e:fattr name:) or *(e:fattr name value:) function fattr() { local val zgetattr $REPLY user.$1 val 2>/dev/null [[ -n "$val" && ( -z "$2" || "$val" =~ "$2" ) ]] } This runs in 280ms for the same set of files. I'm not sure if I should mention it being copied from cap.c since pretty much only the skeleton remains. I guess I would have to write some documentation too. The builtins should probably handle more than one file and parse options in a better way. A builtin for listing attrs on a file would be useful too (could at least be used for completion of the second argument :) ). Maybe the module should be called xattr instead of just attr? I also didn't bother checking what happens when the system doesn't support xattrs or doesn't have the includes. I guess something similar to what db_gdbm.mdd does is needed? I noticed just now that I was lazy and used the ?: extension so that's something to fix too. Do I need to nul terminate strings I give to metafy() and/or setsparam()? I think the AC_CHECK_LIB isn't exactly right either, it adds a second -lc to $LIBS. diff --git a/Src/Modules/.distfiles b/Src/Modules/.distfiles index 40d3114..9231cec 100644 --- a/Src/Modules/.distfiles +++ b/Src/Modules/.distfiles @@ -2,6 +2,8 @@ DISTFILES_SRC=' .cvsignore .distfiles .exrc +attr.mdd +attr.c cap.mdd cap.c clone.mdd diff --git a/Src/Modules/attr.c b/Src/Modules/attr.c new file mode 100644 index 0000000..fc9c70a --- /dev/null +++ b/Src/Modules/attr.c @@ -0,0 +1,140 @@ +/* + * attr.c - extended attributes (xattr) manipulation + * (based on cap.c) + * + * This file is part of zsh, the Z shell. + * + * Copyright (c) 2009 Mikael Magnusson + * Copyright (c) 1997 Andrew Main + * All rights reserved. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and to distribute modified versions of this software for any + * purpose, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * In no event shall Mikael Magnusson or the Zsh Development Group be liable + * to any party for direct, indirect, special, incidental, or consequential + * damages arising out of the use of this software and its documentation, + * even if Andrew Main and the Zsh Development Group have been advised of + * the possibility of such damage. + * + * Mikael Magnusson and the Zsh Development Group specifically disclaim any + * warranties, including, but not limited to, the implied warranties of + * merchantability and fitness for a particular purpose. The software + * provided hereunder is on an "as is" basis, and Mikael Magnusson and the + * Zsh Development Group have no obligation to provide maintenance, + * support, updates, enhancements, or modifications. + * + */ + +#include "attr.mdh" +#include "attr.pro" + +#include +#include + +static int +bin_getattr(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) +{ + int ret = 0; + int len; + char value[256]; + + if (listxattr(*argv, NULL, 0) > 0) { + if (0 < (len = getxattr(*argv, *(argv+1), value, 255))) { + if (len < 256) { + value[len] = '\0'; + setsparam(*(argv+2) ?: "REPLY", metafy(value, len, META_DUP)); + } + } else { + zwarnnam(nam, "%s: %e", *argv, errno); + ret = 1; + } + } + return ret; +} + +static int +bin_setattr(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) +{ + int ret = 0; + + if (setxattr(*argv, *(argv+1), *(argv+2), strlen(*(argv+2)), 0)) { + zwarnnam(nam, "%s: %e", *argv, errno); + ret = 1; + } + return ret; +} + +static int +bin_delattr(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) +{ + int ret = 0; + + if (removexattr(*argv, *(argv+1))) { + zwarnnam(nam, "%s: %e", *argv, errno); + ret = 1; + } + return ret; +} + +/* 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), +}; + +static struct features module_features = { + bintab, sizeof(bintab)/sizeof(*bintab), + NULL, 0, + NULL, 0, + NULL, 0, + 0 +}; + +/**/ +int +setup_(UNUSED(Module m)) +{ + return 0; +} + +/**/ +int +features_(Module m, char ***features) +{ + *features = featuresarray(m, &module_features); + return 0; +} + +/**/ +int +enables_(Module m, int **enables) +{ + return handlefeatures(m, &module_features, enables); +} + +/**/ +int +boot_(UNUSED(Module m)) +{ + return 0; +} + +/**/ +int +cleanup_(Module m) +{ + return setfeatureenables(m, &module_features, NULL); +} + +/**/ +int +finish_(UNUSED(Module m)) +{ + return 0; +} diff --git a/Src/Modules/attr.mdd b/Src/Modules/attr.mdd new file mode 100644 index 0000000..fc4f7b9 --- /dev/null +++ b/Src/Modules/attr.mdd @@ -0,0 +1,7 @@ +name=zsh/attr +link=dynamic +load=no + +autofeatures="b:zgetattr b:zsetattr b:zdelattr" + +objects="attr.o" diff --git a/configure.ac b/configure.ac index 50658e5..fe3f229 100644 --- a/configure.ac +++ b/configure.ac @@ -852,6 +852,9 @@ if test x$gdbm != xno; then AC_CHECK_LIB(gdbm, gdbm_open) fi +AC_CHECK_HEADERS(sys/xattr.h) +AC_CHECK_LIB(c, getxattr) + dnl -------------- dnl CHECK TYPEDEFS dnl -------------- -- Mikael Magnusson