[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: readdir on Windows, again
From: |
arnold |
Subject: |
Re: readdir on Windows, again |
Date: |
Mon, 11 Dec 2023 13:31:57 -0700 |
User-agent: |
Heirloom mailx 12.5 7/5/10 |
Hi.
Can you explain the change in pc/gawkmisc.pc:optimal_bufsize? Why are
you checking the contents of the stat buffer before calling fstat?
The calling code expects optimal_bufsize() to call fstat for it.
Thanks,
Arnold
Eli Zaretskii <eliz@gnu.org> wrote:
> 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)