[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
readdir on Windows, again
From: |
Eli Zaretskii |
Subject: |
readdir on Windows, again |
Date: |
Mon, 11 Dec 2023 21:52:27 +0200 |
Hi,
A user informed me privately that the following script fails on
MS-Windows to read directories when their names come from the script
(as opposed to being specified on the command line):
@load "readdir"
BEGIN {
Directory = ARGV[1]
n = (getline < Directory)
printf("File-based getline(%s) %s:
%d\n",Directory,((n>0)?"succeeded":"failed"),n)
n = getline
printf("Command line getline(%s) %s:
%d\n",Directory,((n>0)?"succeeded":"failed"),n)
exit
}
The first getline fails, the second succeeds. On GNU/Linux, both
succeed.
It turns out a change I posted during 5.2.1 development didn't make it
into the current sources. As result, in the above scenario,
find_input_parser was not being called because redirect_string
expected 'open' to succeed on directories.
The patches to fix this are below. Any objections to installing them
in Git?
--- io.c~0 2023-11-01 10:31:57.000000000 +0200
+++ io.c 2023-12-11 20:54:49.219500000 +0200
@@ -797,6 +797,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"));
@@ -979,15 +980,20 @@ 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;
+ iop_close(rp->iop);
+ rp->iop = NULL;
+ /* 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);
--- pc/gawkmisc.pc~0 2023-10-22 17:19:50.000000000 +0300
+++ pc/gawkmisc.pc 2023-12-11 21:38:34.594500000 +0200
@@ -106,9 +106,6 @@ optimal_bufsize(fd, stb)
int fd;
struct stat *stb;
{
- /* force all members to zero in case OS doesn't use all of them. */
- memset(stb, '\0', sizeof(struct stat));
-
/*
* DOS doesn't have the file system block size in the
* stat structure. So we have to make some sort of reasonable
@@ -117,6 +114,12 @@ struct stat *stb;
*/
#define DEFBLKSIZE BUFSIZ
+ if (S_ISDIR(stb->st_mode))
+ return DEFBLKSIZE;
+
+ /* force all members to zero in case OS doesn't use all of them. */
+ memset(stb, '\0', sizeof(struct stat));
+
if (fstat(fd, stb) == -1)
fatal("can't stat fd %d (%s)", fd, strerror(errno));
if (S_ISREG(stb->st_mode)
- readdir on Windows, again,
Eli Zaretskii <=