Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

[wip patch] new zsh/attr module



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 <sys/types.h>
+#include <sys/xattr.h>
+
+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



Messages sorted by: Reverse Date, Date, Thread, Author