From: Dmitry Bogatov <kact...@gnu.org>

  * module/ice-9/xattr.scm (xattr-get): convert exception to #f
    if errno was ENOATTR
---
 module/ice-9/xattr.scm | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/module/ice-9/xattr.scm b/module/ice-9/xattr.scm
index 090b233..804d374 100644
--- a/module/ice-9/xattr.scm
+++ b/module/ice-9/xattr.scm
@@ -101,14 +101,25 @@
       (%ret = (if (port? file)
                   (c-attr-getf (port->fdes file) attrname attrvalue 
valuelength flags)
                   (c-attr-get file attrname attrvalue valuelength flags)))
-    (unless (zero? %ret)
-      (c-scm-syserror "xattr-get"))
     ;; No matter how long actual value is, attrvalue is bytevector
     ;; with length of `max-valuelen'. We need only first `valuelength'
     ;; from it. It is unexpectedly complicated to splice bytevectory.
-    (let ()
-      (define value
-        (pointer->bytevector (bytevector->pointer attrvalue) valuelength))
-      (if decode?
-          (bytevector->string value "utf-8")
-          (bytevector-copy value)))))
+    (define result
+      (delay
+        (let ((value (pointer->bytevector (bytevector->pointer attrvalue)
+                                          valuelength)))
+              (if decode?
+                  (bytevector->string value "utf-8")
+                  (bytevector-copy value))))) ; unshare with 64Kb bytevector
+    (define (xattr-get/syserror) (c-scm-syserror "xattr-get"))
+    ;; Really ugly way to get errno. We throw exception via internal
+    ;; Guile function 'scm_syserror' just to catch it and extract errno.
+    ;; If it is ENODATA (ENOATTR in manual page) it is not exceptional,
+    ;; and we return #f.
+    (if (zero? %ret)
+        (force result)
+        (catch #t xattr-get/syserror
+          (lambda _args
+            (unless (eqv? ENODATA (system-error-errno _args))
+              (xattr-get/syserror))
+            #f)))))
-- 
I may be not subscribed. Please, keep me in carbon copy.


Reply via email to