fix zero size case for getxattr and listxattr
diff --git a/lib/fuse.c b/lib/fuse.c
index 77532a4..fddcc33 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -390,7 +390,7 @@
     size_t outsize;
     struct fuse_out_header *out;
 
-    if(error <= -512 || error > 0) {
+    if(error <= -1000 || error > 0) {
         fprintf(stderr, "fuse: bad error value: %i\n",  error);
         error = -ERANGE;
     }
@@ -991,26 +991,32 @@
     send_reply(f, in, res, NULL, 0);
 }
 
-static void do_getxattr(struct fuse *f, struct fuse_in_header *in,
-                        struct fuse_getlistxattr_in *arg)
+static int common_getxattr(struct fuse *f, struct fuse_in_header *in,
+                           const char *name, char *value, size_t size)
 {
     int res;
     char *path;
-    char *name = PARAM(arg);
-    char *outbuf = (char *) malloc(sizeof(struct fuse_out_header) + arg->size);
-    struct fuse_out_header *out = (struct fuse_out_header *) outbuf;
-    char *value = outbuf + sizeof(struct fuse_out_header);
-    size_t size;
-    size_t outsize;
 
     res = -ENOENT;
     path = get_path(f, in->ino);
     if (path != NULL) {
         res = -EOPNOTSUPP; /* or is it ENOTSUPP ??? */
         if (f->op.getxattr)
-            res = f->op.getxattr(path, name, value, arg->size);
+            res = f->op.getxattr(path, name, value, size);
         free(path);
     }    
+    return res;
+}
+
+static void do_getxattr_read(struct fuse *f, struct fuse_in_header *in,
+                             const char *name, size_t size)
+{
+    int res;
+    char *outbuf = (char *) malloc(sizeof(struct fuse_out_header) + size);
+    struct fuse_out_header *out = (struct fuse_out_header *) outbuf;
+    char *value = outbuf + sizeof(struct fuse_out_header);
+
+    res = common_getxattr(f, in, name, value, size);
     size = 0;
     if(res > 0) {
         size = res;
@@ -1019,31 +1025,62 @@
     memset(out, 0, sizeof(struct fuse_out_header));
     out->unique = in->unique;
     out->error = res;
-    outsize = sizeof(struct fuse_out_header) + size;
 
-    send_reply_raw(f, outbuf, outsize);
+    send_reply_raw(f, outbuf, sizeof(struct fuse_out_header) + size);
     free(outbuf);
 }
 
-static void do_listxattr(struct fuse *f, struct fuse_in_header *in,
-                         struct fuse_getlistxattr_in *arg)
+static void do_getxattr_size(struct fuse *f, struct fuse_in_header *in,
+                             const char *name)
+{
+    int res;
+    struct fuse_getxattr_out arg;
+
+    res = common_getxattr(f, in, name, NULL, 0);
+    if(res >= 0) {
+        arg.size = res;
+        res = 0;
+    }
+    send_reply(f, in, res, &arg, sizeof(arg));
+}
+
+static void do_getxattr(struct fuse *f, struct fuse_in_header *in,
+                        struct fuse_getxattr_in *arg)
+{
+    char *name = PARAM(arg);
+    
+    if(arg->size)
+        do_getxattr_read(f, in, name, arg->size);
+    else
+        do_getxattr_size(f, in, name);
+}
+
+static int common_listxattr(struct fuse *f, struct fuse_in_header *in,
+                            char *list, size_t size)
 {
     int res;
     char *path;
-    char *outbuf = (char *) malloc(sizeof(struct fuse_out_header) + arg->size);
-    struct fuse_out_header *out = (struct fuse_out_header *) outbuf;
-    char *value = outbuf + sizeof(struct fuse_out_header);
-    size_t size;
-    size_t outsize;
 
     res = -ENOENT;
     path = get_path(f, in->ino);
     if (path != NULL) {
         res = -EOPNOTSUPP; /* or is it ENOTSUPP ??? */
         if (f->op.listxattr)
-            res = f->op.listxattr(path, value, arg->size);
+            res = f->op.listxattr(path, list, size);
         free(path);
     }    
+    return res;
+}
+
+static void do_listxattr_read(struct fuse *f, struct fuse_in_header *in,
+                              size_t size)
+{
+    int res;
+    char *outbuf = (char *) malloc(sizeof(struct fuse_out_header) + size);
+    struct fuse_out_header *out = (struct fuse_out_header *) outbuf;
+    char *list = outbuf + sizeof(struct fuse_out_header);
+
+    res = common_listxattr(f, in, list, size);
     size = 0;
     if(res > 0) {
         size = res;
@@ -1052,12 +1089,33 @@
     memset(out, 0, sizeof(struct fuse_out_header));
     out->unique = in->unique;
     out->error = res;
-    outsize = sizeof(struct fuse_out_header) + size;
 
-    send_reply_raw(f, outbuf, outsize);
+    send_reply_raw(f, outbuf, sizeof(struct fuse_out_header) + size);
     free(outbuf);
 }
 
+static void do_listxattr_size(struct fuse *f, struct fuse_in_header *in)
+{
+    int res;
+    struct fuse_getxattr_out arg;
+
+    res = common_listxattr(f, in, NULL, 0);
+    if (res >= 0) {
+        arg.size = res;
+        res = 0;
+    }
+    send_reply(f, in, res, &arg, sizeof(arg));
+}
+
+static void do_listxattr(struct fuse *f, struct fuse_in_header *in,
+                         struct fuse_getxattr_in *arg)
+{
+    if(arg->size)
+        do_listxattr_read(f, in, arg->size);
+    else
+        do_listxattr_size(f, in);
+}
+
 static void do_removexattr(struct fuse *f, struct fuse_in_header *in,
                            char *name)
 {
@@ -1182,11 +1240,11 @@
         break;
 
     case FUSE_GETXATTR:
-        do_getxattr(f, in, (struct fuse_getlistxattr_in *) inarg);
+        do_getxattr(f, in, (struct fuse_getxattr_in *) inarg);
         break;
 
     case FUSE_LISTXATTR:
-        do_listxattr(f, in, (struct fuse_getlistxattr_in *) inarg);
+        do_listxattr(f, in, (struct fuse_getxattr_in *) inarg);
         break;
 
     case FUSE_REMOVEXATTR: