[Top][All Lists]

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

Re: windows build failure

From: Eli Zaretskii
Subject: Re: windows build failure
Date: Fri, 20 Sep 2013 20:40:34 +0300

> From: Sean Sieger <address@hidden>
> Date: Fri, 20 Sep 2013 12:34:28 -0400
>     Does the below work as expected?
>       emacs -Q c*.c
>     If you do this from the src directory, you should end up with visiting
>     the 14 C files that match the wildcard in the Emacs's src directory.
>     What do you get in Emacs linked with the new MinGW runtime?
> Wait, wait, wait ...
> MinGW-Shell:
> address@hidden /c/trunk/src/
> $ emacs -Q c*.c
> ... I get the correct result.

In the MSYS Bash, the shell does the wildcard expansion, that's why
you get correct results.

> Command Prompt:
> c:\trunk\src>emacs -Q c*.c
> ... nope, visits the non-existent, `c*.c'.

Right, as I expected.

Here's why: MinGW runtime v4.x changed the layout of 'struct dirent',
the structure returned by 'readdir', in an incompatible way.  Where
previously we had

  struct dirent
          long                  d_ino;          /* Always zero. */
          unsigned short        d_reclen;       /* Always zero. */
          unsigned short        d_namlen;       /* Length of name in d_name. */
          char                  d_name[FILENAME_MAX]; /* File name. */

we now have

  struct dirent
          long                  d_ino;          /* Always zero. */
          unsigned short        d_reclen;       /* Always zero. */
          unsigned short        d_namlen;       /* Length of name in d_name. */

          /* The following exactly mimic the layout of _finddata_t ...
          unsigned              d_type;         /* File attributes */
          time_t                d_time_create;
          time_t                d_time_access;  /* always midnight local time */
          time_t                d_time_write;
          _fsize_t              d_size;
           * ...so that we may map a union of _finddata_t at the
           * location of d_type (corresponding to _finddata_t.attrib),
           * and thus map this directly to the _findfirst/_findnext
           * returned field.
          char                  d_name[FILENAME_MAX]; /* File name. */

As you see d_name[] moved, and is now at a different offset.

That in itself is already a bad idea, because linking a program with a
library that was compiled with an older version of dirent.h will now
produce a buggy program, which will look for the file name in a wrong
place.  However, it might still be OK for Emacs, because Emacs has its
own definition of 'struct dirent' and its own implementation of
'readdir', and thus does not use the ones provided by the MinGW

But then the MinGW developers added insult to injury, by calling
'readdir' from the startup code.  This is an absolute no-no for a
library, because a C program can legitimately have an incompatible
function named 'readdir' that might even have nothing to do with
reading a directory.

What happens in Emacs as result is that the startup code calls the
Emacs implementation of 'readdir', which uses an incompatible 'struct
dirent', and the result is that globbing of wildcards is broken.

At the time, I tried to convince the MinGW developers not to do this,


Evidently, I failed completely to convince them, as the incompatible
runtime went to print regardless, and the problems will now begin
unfolding before our eyes...

reply via email to

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