help-gawk
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: readdir extension on windows with getline


From: Eli Zaretskii
Subject: Re: readdir extension on windows with getline
Date: Thu, 26 Jan 2023 20:15:51 +0200

> Date: Thu, 26 Jan 2023 18:52:46 +0200
> From: Eli Zaretskii <eliz@gnu.org>
> CC: help-gawk@gnu.org
> 
> I stand corrected: the OP's script does work on GNU/Linux.  So I guess
> this is Windows specific.  I will try to look at this when I have
> time.

I found the reason: the code in redirect_string relies on devopen to
succeed when passed a directory name, and only _after_ it succeeds,
redirect_string tries to find an input parser.  But on Windows,
open'ing a directory always fails, and thus the logic in
redirect_string doesn't give a chance to registered parsers to try to
take control of reading directories.

Fixing that boils down to rearranging the code a bit:

--- io.c~0      2022-11-17 17:43:09.000000000 +0200
+++ io.c        2023-01-26 20:08:07.952496100 +0200
@@ -788,6 +788,7 @@ redirect_string(const char *str, size_t 
        static struct redirect *save_rp = NULL; /* hold onto rp that should
                                                 * be freed for reuse
                                                 */
+       int save_errno;
 
        if (do_sandbox)
                fatal(_("redirection not allowed in sandbox mode"));
@@ -966,15 +967,18 @@ redirect_string(const char *str, size_t 
                case redirect_input:
                        direction = "from";
                        fd = (extfd >= 0) ? extfd : devopen(str, binmode("r"));
-                       if (fd == INVALID_HANDLE && errno == EISDIR) {
-                               *errflg = EISDIR;
-                               /* do not free rp, saving it for reuse (save_rp 
= rp) */
-                               return NULL;
-                       }
+                       save_errno = errno;
+                       /* don't fail before letting registered
+                          parsers a chance to take control */
                        rp->iop = iop_alloc(fd, str, errno);
                        find_input_parser(rp->iop);
                        iop_finish(rp->iop);
                        if (! rp->iop->valid) {
+                               if (fd == INVALID_HANDLE && save_errno == 
EISDIR) {
+                                       *errflg = EISDIR;
+                                       /* do not free rp, saving it for reuse 
(save_rp = rp) */
+                                       return NULL;
+                               }
                                if (! do_traditional && rp->iop->errcode != 0)
                                        update_ERRNO_int(rp->iop->errcode);
                                iop_close(rp->iop);
@@ -3422,6 +3426,13 @@ iop_finish(IOBUF *iop)
 
        if (! iop->valid || iop->public.fd == INVALID_HANDLE)
                return iop;
+#ifdef __MINGW32__
+       /* If we wind up here, some extension (readdir?) took control
+          of reading directories, so let that extension DTRT and
+          don't bother with the rest of the initializations below. */
+       if (iop->errcode == EISDIR)
+               return iop;
+#endif
 
        if (os_isatty(iop->public.fd))
                iop->flag |= IOP_IS_TTY;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]