bug-gawk
[Top][All Lists]
Advanced

[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)



reply via email to

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