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

[PATCH 3/4] attr: dynamically allocate memory for attributes



If there is a race condition and the attribute grows between the two
calls, we return an error instead of trying again.
---
 Doc/Zsh/mod_attr.yo |    5 ++++
 Src/Modules/attr.c  |   63 ++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 47 insertions(+), 21 deletions(-)

diff --git a/Doc/Zsh/mod_attr.yo b/Doc/Zsh/mod_attr.yo
index ed444d0..517bb63 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 way, the calling function can
+check for this case and try again for as long as they want.
diff --git a/Src/Modules/attr.c b/Src/Modules/attr.c
index 1a9c323..bb30ebb 100644
--- a/Src/Modules/attr.c
+++ b/Src/Modules/attr.c
@@ -98,26 +98,37 @@ static int
 bin_getattr(char *nam, char **argv, Options ops, UNUSED(int func))
 {
     int ret = 0;
-    int len, slen;
-    char value[256];
+    int list_len, val_len, attr_len, slen;
+    char *value;
     int symlink = OPT_ISSET(ops, 'h');

     unmetafy(*argv, &slen);
     unmetafy(*(argv+1), NULL);
-    if (xlistxattr(*argv, NULL, 0, symlink) > 0) {
-        if (0 < (len = xgetxattr(*argv, *(argv+1), value, 255, symlink))) {
-            if (len < 256) {
-                value[len] = '\0';
+    list_len = xlistxattr(*argv, NULL, 0, symlink);
+    if (list_len > 0) {
+        val_len = xgetxattr(*argv, *(argv+1), NULL, 0, symlink);
+        if (val_len == 0) {
+            if (*(argv+2))
+                unsetparam(*(argv+2));
+            return 0;
+        }
+        if (val_len > 0) {
+            value = (char *)zalloc(val_len+1);
+            attr_len = xgetxattr(*argv, *(argv+1), value, val_len, symlink);
+            if (attr_len > 0 && attr_len <= val_len) {
+                value[attr_len] = '\0';
                 if (*(argv+2))
-                    setsparam(*(argv+2), metafy(value, len, META_DUP));
+                    setsparam(*(argv+2), 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(*argv, slen, META_NOALLOC), errno);
+        ret = 1 + (attr_len > val_len);
+    }
     return ret;
 }

@@ -160,41 +171,51 @@ static int
 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;
     int symlink = OPT_ISSET(ops, 'h');

     unmetafy(*argv, &slen);
-    if (0 < (len = xlistxattr(*argv, value, 256, symlink))) {
-        if (len < 256) {
+    val_len = xlistxattr(*argv, NULL, 0, symlink);
+    if (val_len == 0) {
+        if (*(argv+1))
+            unsetparam(*(argv+1));
+        return 0;
+    }
+    if (val_len > 0) {
+        value = (char *)zalloc(val_len+1);
+        list_len = xlistxattr(*argv, value, val_len, symlink);
+        if (list_len > 0 && list_len <= val_len) {
             char *p = value;
             if (*(argv+1)) {
-                if (strlen(value) + 1 == len)
-                    setsparam(*(argv+1), metafy(value, len-1, META_DUP));
+                if (strlen(value) + 1 == list_len)
+                    setsparam(*(argv+1), metafy(value, list_len-1, META_DUP));
                 else {
                     int arrlen = 0;
                     char **array = NULL, **arrptr = NULL;

-                    while (p < &value[len]) {
+                    while (p < &value[list_len]) {
                         arrlen++;
                         p += strlen(p) + 1;
                     }
                     arrptr = array = (char **)zshcalloc((arrlen+1) * sizeof(char *));
                     p = value;
-                    while (p < &value[len]) {
+                    while (p < &value[list_len]) {
                         *arrptr++ = metafy(p, -1, META_DUP);
                         p += strlen(p) + 1;
                     }
                     setaparam(*(argv+1), array);
                 }
-            } else while (p < &value[len]) {
+            } else while (p < &value[list_len]) {
                 printf("%s\n", p);
                 p += strlen(p) + 1;
             }
         }
-    } else if (len < 0) {
+        zfree(value, val_len+1);
+    }
+    if (val_len < 0 || list_len < 0) {
         zwarnnam(nam, "%s: %e", metafy(*argv, slen, META_NOALLOC), errno);
-        ret = 1;
+        ret = 1 + (list_len > val_len);
     }
     return ret;
 }
--
1.6.5



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