From abc74473ed37336a924b135e656ba40eeecc064b Mon Sep 17 00:00:00 2001
From: Kaz Kyheku <kaz@kylheku.com>
Date: Tue, 28 Jan 2020 08:28:21 -0800
Subject: ftw: throw exception on failure.

The ftw function just returns -1 if, for instance, given a bad
path (nonexistent or no permissions).  The documentation also
has issues.

* ftw.c (ftw_wrap): If the return value is -1, convert it to a
file-error using errno_to_file_error and throw a diagnostic
exception. This situation can, of course, arise if the
callback function returns -1, in which case it should prepare
a value in errno.

* txr.1: Return value of callbackfn documented better.
Documented exception throwing behavior, and failed termination
if the callback returns -1.
---
 ftw.c |  8 +++++++-
 txr.1 | 58 ++++++++++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 55 insertions(+), 11 deletions(-)

diff --git a/ftw.c b/ftw.c
index 27b8e790..537e6d4f 100644
--- a/ftw.c
+++ b/ftw.c
@@ -30,6 +30,8 @@
 #include <signal.h>
 #include <stdlib.h>
 #include <stddef.h>
+#include <string.h>
+#include <errno.h>
 #include <ftw.h>
 #include "config.h"
 #include "alloca.h"
@@ -122,7 +124,11 @@ val ftw_wrap(val dirpath, val fn, val flags_in, val nopenfd_in)
     case 0:
       return t;
     case -1:
-      return nil;
+      {
+        int eno = errno;
+        uw_throwf(errno_to_file_error(eno), lit("ftw ~a: ~d/~s"),
+                  dirpath, num(eno), string_utf8(strerror(eno)), nao);
+      }
     default:
       return num(res);
     }
diff --git a/txr.1 b/txr.1
index ebce3c06..a97e3246 100644
--- a/txr.1
+++ b/txr.1
@@ -60270,7 +60270,12 @@ bitmask arguments.
 
 For each visited entry, it calls the supplied
 .meta callbackfun
-function, which receives five arguments.
+function, which receives five arguments. If this function returns
+normally, it must return either
+.codn nil ,
+.codn t ,
+or an integer value in the range of the C type
+.codn int .
 
 The
 .code ftw
@@ -60290,7 +60295,9 @@ stops the traversal.  (Non-integer return values behave like
 
 The
 .meta path
-argument of the callback function gives the path of the
+argument of
+.meta callbackfun
+gives the path of the
 visited filesystem object.
 
 The
@@ -60334,19 +60341,50 @@ calculates the base name.
 
 The
 .code ftw
-function returns
+function returns either
 .code t
-upon successful completion and
-.code nil
-on failure. If
-.code ftw
-is terminated by a return value from
+upon successful completion, or an integer value returned by
 .metn callbackfun ,
-then that value is returned. Such a value is always a nonzero integer.
+as described below.
+On failure it throws an exception derived from
+.codn file-error ,
+whose specific type is based on analyzing the POSIX
+.code errno
+value.
 
 The
 .meta callbackfun
-may terminate the traversal by a nonlocal exit, such as by throwing
+may return a value of any type. If it returns a value that is not of integer
+type, then zero is returned to the
+.code nftw
+function and traversal continues. Similarly, traversal continues
+if the function returns an integer zero.
+
+If
+.meta callbackfun
+returns an integer value, that value must be in the range of the C type
+.codn int .
+That
+.code int
+value is returned to
+.codn nftw .
+If the value is not zero, and is not -1, then
+.code nftw
+will terminate, and return that value, which
+.code ftw
+then returns. If the value is -1, then
+.code nftw
+is deemed to have failed, and
+.code ftw
+will thrown an exception of type
+.codn file-error ,
+whose specific type is based on analyzing the POSIX
+.code errno
+value. If the value is zero, then the traversal continues.
+
+The
+.meta callbackfun
+may also terminate the traversal by a nonlocal exit, such as by throwing
 an exception or performing a block return.
 
 The
-- 
cgit v1.2.3