(root)/
make-4.4/
src/
dir.c
       1  /* Directory hashing for GNU Make.
       2  Copyright (C) 1988-2022 Free Software Foundation, Inc.
       3  This file is part of GNU Make.
       4  
       5  GNU Make is free software; you can redistribute it and/or modify it under the
       6  terms of the GNU General Public License as published by the Free Software
       7  Foundation; either version 3 of the License, or (at your option) any later
       8  version.
       9  
      10  GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
      11  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
      12  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
      13  
      14  You should have received a copy of the GNU General Public License along with
      15  this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  #include "makeint.h"
      18  #include "hash.h"
      19  #include "filedef.h"
      20  #include "dep.h"
      21  #include "debug.h"
      22  
      23  #ifdef  HAVE_DIRENT_H
      24  # include <dirent.h>
      25  # define NAMLEN(dirent) strlen((dirent)->d_name)
      26  # ifdef VMS
      27  /* its prototype is in vmsdir.h, which is not needed for HAVE_DIRENT_H */
      28  const char *vmsify (const char *name, int type);
      29  # endif
      30  #else
      31  # define dirent direct
      32  # define NAMLEN(dirent) (dirent)->d_namlen
      33  # ifdef HAVE_SYS_NDIR_H
      34  #  include <sys/ndir.h>
      35  # endif
      36  # ifdef HAVE_SYS_DIR_H
      37  #  include <sys/dir.h>
      38  # endif
      39  # ifdef HAVE_NDIR_H
      40  #  include <ndir.h>
      41  # endif
      42  # ifdef HAVE_VMSDIR_H
      43  #  include "vmsdir.h"
      44  # endif /* HAVE_VMSDIR_H */
      45  #endif
      46  
      47  /* In GNU systems, <dirent.h> defines this macro for us.  */
      48  #ifdef _D_NAMLEN
      49  # undef NAMLEN
      50  # define NAMLEN(d) _D_NAMLEN(d)
      51  #endif
      52  
      53  #if (defined (POSIX) || defined (VMS) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__)
      54  /* Posix does not require that the d_ino field be present, and some
      55     systems do not provide it. */
      56  # define REAL_DIR_ENTRY(dp) 1
      57  # define FAKE_DIR_ENTRY(dp)
      58  #else
      59  # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
      60  # define FAKE_DIR_ENTRY(dp) (dp->d_ino = 1)
      61  #endif /* POSIX */
      62  
      63  #ifdef __MSDOS__
      64  #include <ctype.h>
      65  #include <fcntl.h>
      66  
      67  /* If it's MSDOS that doesn't have _USE_LFN, disable LFN support.  */
      68  #ifndef _USE_LFN
      69  #define _USE_LFN 0
      70  #endif
      71  
      72  static const char *
      73  dosify (const char *filename)
      74  {
      75    static char dos_filename[14];
      76    char *df;
      77    int i;
      78  
      79    if (filename == 0 || _USE_LFN)
      80      return filename;
      81  
      82    /* FIXME: what about filenames which violate
      83       8+3 constraints, like "config.h.in", or ".emacs"?  */
      84    if (strpbrk (filename, "\"*+,;<=>?[\\]|") != 0)
      85      return filename;
      86  
      87    df = dos_filename;
      88  
      89    /* First, transform the name part.  */
      90    for (i = 0; i < 8 && ! STOP_SET (*filename, MAP_DOT|MAP_NUL); ++i)
      91      *df++ = tolower ((unsigned char)*filename++);
      92  
      93    /* Now skip to the next dot.  */
      94    while (! STOP_SET (*filename, MAP_DOT|MAP_NUL))
      95      ++filename;
      96    if (*filename != '\0')
      97      {
      98        *df++ = *filename++;
      99        for (i = 0; i < 3 && ! STOP_SET (*filename, MAP_DOT|MAP_NUL); ++i)
     100          *df++ = tolower ((unsigned char)*filename++);
     101      }
     102  
     103    /* Look for more dots.  */
     104    while (! STOP_SET (*filename, MAP_DOT|MAP_NUL))
     105      ++filename;
     106    if (*filename == '.')
     107      return filename;
     108    *df = 0;
     109    return dos_filename;
     110  }
     111  #endif /* __MSDOS__ */
     112  
     113  #ifdef WINDOWS32
     114  #include "pathstuff.h"
     115  #endif
     116  
     117  #ifdef _AMIGA
     118  #include <ctype.h>
     119  #endif
     120  
     121  #ifdef HAVE_CASE_INSENSITIVE_FS
     122  static const char *
     123  downcase (const char *filename)
     124  {
     125    static PATH_VAR (new_filename);
     126    char *df;
     127  
     128    if (filename == 0)
     129      return 0;
     130  
     131    df = new_filename;
     132    while (*filename != '\0')
     133      {
     134        *df++ = tolower ((unsigned char)*filename);
     135        ++filename;
     136      }
     137  
     138    *df = 0;
     139  
     140    return new_filename;
     141  }
     142  #endif /* HAVE_CASE_INSENSITIVE_FS */
     143  
     144  #ifdef VMS
     145  
     146  static char *
     147  downcase_inplace(char *filename)
     148  {
     149    char *name;
     150    name = filename;
     151    while (*name != '\0')
     152      {
     153        *name = tolower ((unsigned char)*name);
     154        ++name;
     155      }
     156    return filename;
     157  }
     158  
     159  #ifndef _USE_STD_STAT
     160  /* VMS 8.2 fixed the VMS stat output to have unique st_dev and st_ino
     161     when _USE_STD_STAT is used on the compile line.
     162  
     163     Prior to _USE_STD_STAT support, the st_dev is a pointer to thread
     164     static memory containing the device of the last filename looked up.
     165  
     166     Todo: find out if the ino_t still needs to be faked on a directory.
     167   */
     168  
     169  /* Define this if the older VMS_INO_T is needed */
     170  #define VMS_INO_T 1
     171  
     172  static int
     173  vms_hash (const char *name)
     174  {
     175    int h = 0;
     176  
     177    while (*name)
     178      {
     179        unsigned char uc = (unsigned char) *name;
     180        int g;
     181  #ifdef HAVE_CASE_INSENSITIVE_FS
     182        h = (h << 4) + (isupper (uc) ? tolower (uc) : uc);
     183  #else
     184        h = (h << 4) + uc;
     185  #endif
     186        name++;
     187        g = h & 0xf0000000;
     188        if (g)
     189          {
     190            h = h ^ (g >> 24);
     191            h = h ^ g;
     192          }
     193      }
     194    return h;
     195  }
     196  
     197  /* fake stat entry for a directory */
     198  static int
     199  vmsstat_dir (const char *name, struct stat *st)
     200  {
     201    char *s;
     202    int h;
     203    DIR *dir;
     204  
     205    dir = opendir (name);
     206    if (dir == 0)
     207      return -1;
     208    closedir (dir);
     209    s = strchr (name, ':');       /* find device */
     210    if (s)
     211      {
     212        /* to keep the compiler happy we said "const char *name", now we cheat */
     213        *s++ = 0;
     214        st->st_dev = (char *)vms_hash (name);
     215        h = vms_hash (s);
     216        *(s-1) = ':';
     217      }
     218    else
     219      {
     220        st->st_dev = 0;
     221        h = vms_hash (name);
     222      }
     223  
     224    st->st_ino[0] = h & 0xff;
     225    st->st_ino[1] = h & 0xff00;
     226    st->st_ino[2] = h >> 16;
     227  
     228    return 0;
     229  }
     230  
     231  # define stat(__path, __sbuf) vmsstat_dir (__path, __sbuf)
     232  
     233  #endif /* _USE_STD_STAT */
     234  #endif /* VMS */
     235  
     236  /* Never have more than this many directories open at once.  */
     237  
     238  #define MAX_OPEN_DIRECTORIES 10
     239  
     240  static unsigned int open_directories = 0;
     241  
     242  /* Hash table of directories.  */
     243  
     244  #ifndef DIRECTORY_BUCKETS
     245  #define DIRECTORY_BUCKETS 199
     246  #endif
     247  
     248  struct directory_contents
     249    {
     250      dev_t dev;                  /* Device and inode numbers of this dir.  */
     251  #ifdef WINDOWS32
     252      /* Inode means nothing on WINDOWS32. Even file key information is
     253       * unreliable because it is random per file open and undefined for remote
     254       * filesystems. The most unique attribute I can come up with is the fully
     255       * qualified name of the directory. Beware though, this is also
     256       * unreliable. I'm open to suggestion on a better way to emulate inode.  */
     257      char *path_key;
     258      time_t ctime;
     259      time_t mtime;        /* controls check for stale directory cache */
     260      int fs_flags;     /* FS_FAT, FS_NTFS, ... */
     261  # define FS_FAT      0x1
     262  # define FS_NTFS     0x2
     263  # define FS_UNKNOWN  0x4
     264  #else
     265  # ifdef VMS_INO_T
     266      ino_t ino[3];
     267  # else
     268      ino_t ino;
     269  # endif
     270  #endif /* WINDOWS32 */
     271      struct hash_table dirfiles; /* Files in this directory.  */
     272      unsigned long counter;      /* command_count value when last read. */
     273      DIR *dirstream;             /* Stream reading this directory.  */
     274    };
     275  
     276  static struct directory_contents *
     277  clear_directory_contents (struct directory_contents *dc)
     278  {
     279    dc->counter = 0;
     280    if (dc->dirstream)
     281      {
     282        --open_directories;
     283        closedir (dc->dirstream);
     284        dc->dirstream = 0;
     285      }
     286    hash_free (&dc->dirfiles, 1);
     287  
     288    return NULL;
     289  }
     290  
     291  static unsigned long
     292  directory_contents_hash_1 (const void *key_0)
     293  {
     294    const struct directory_contents *key = key_0;
     295    unsigned long hash;
     296  
     297  #ifdef WINDOWS32
     298    hash = 0;
     299    ISTRING_HASH_1 (key->path_key, hash);
     300    hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) key->ctime;
     301  #else
     302  # ifdef VMS_INO_T
     303    hash = (((unsigned int) key->dev << 4)
     304            ^ ((unsigned int) key->ino[0]
     305               + (unsigned int) key->ino[1]
     306               + (unsigned int) key->ino[2]));
     307  # else
     308    hash = ((unsigned int) key->dev << 4) ^ (unsigned int) key->ino;
     309  # endif
     310  #endif /* WINDOWS32 */
     311    return hash;
     312  }
     313  
     314  static unsigned long
     315  directory_contents_hash_2 (const void *key_0)
     316  {
     317    const struct directory_contents *key = key_0;
     318    unsigned long hash;
     319  
     320  #ifdef WINDOWS32
     321    hash = 0;
     322    ISTRING_HASH_2 (key->path_key, hash);
     323    hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ctime;
     324  #else
     325  # ifdef VMS_INO_T
     326    hash = (((unsigned int) key->dev << 4)
     327            ^ ~((unsigned int) key->ino[0]
     328                + (unsigned int) key->ino[1]
     329                + (unsigned int) key->ino[2]));
     330  # else
     331    hash = ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ino;
     332  # endif
     333  #endif /* WINDOWS32 */
     334  
     335    return hash;
     336  }
     337  
     338  /* Sometimes it's OK to use subtraction to get this value:
     339       result = X - Y;
     340     But, if we're not sure of the type of X and Y they may be too large for an
     341     int (on a 64-bit system for example).  So, use ?: instead.
     342     See Savannah bug #15534.
     343  
     344     NOTE!  This macro has side-effects!
     345  */
     346  
     347  #define MAKECMP(_x,_y)  ((_x)<(_y)?-1:((_x)==(_y)?0:1))
     348  
     349  static int
     350  directory_contents_hash_cmp (const void *xv, const void *yv)
     351  {
     352    const struct directory_contents *x = xv;
     353    const struct directory_contents *y = yv;
     354    int result;
     355  
     356  #ifdef WINDOWS32
     357    ISTRING_COMPARE (x->path_key, y->path_key, result);
     358    if (result)
     359      return result;
     360    result = MAKECMP(x->ctime, y->ctime);
     361    if (result)
     362      return result;
     363  #else
     364  # ifdef VMS_INO_T
     365    result = MAKECMP(x->ino[0], y->ino[0]);
     366    if (result)
     367      return result;
     368    result = MAKECMP(x->ino[1], y->ino[1]);
     369    if (result)
     370      return result;
     371    result = MAKECMP(x->ino[2], y->ino[2]);
     372    if (result)
     373      return result;
     374  # else
     375    result = MAKECMP(x->ino, y->ino);
     376    if (result)
     377      return result;
     378  # endif
     379  #endif /* WINDOWS32 */
     380  
     381    return MAKECMP(x->dev, y->dev);
     382  }
     383  
     384  /* Table of directory contents hashed by device and inode number.  */
     385  static struct hash_table directory_contents;
     386  
     387  struct directory
     388    {
     389      const char *name;           /* Name of the directory.  */
     390      unsigned long counter;      /* command_count value when last read.
     391                                     Used for non-existent directories.  */
     392  
     393      /* The directory's contents.  This data may be shared by several
     394         entries in the hash table, which refer to the same directory
     395         (identified uniquely by 'dev' and 'ino') under different names.  */
     396      struct directory_contents *contents;
     397    };
     398  
     399  static unsigned long
     400  directory_hash_1 (const void *key)
     401  {
     402    return_ISTRING_HASH_1 (((const struct directory *) key)->name);
     403  }
     404  
     405  static unsigned long
     406  directory_hash_2 (const void *key)
     407  {
     408    return_ISTRING_HASH_2 (((const struct directory *) key)->name);
     409  }
     410  
     411  static int
     412  directory_hash_cmp (const void *x, const void *y)
     413  {
     414    return_ISTRING_COMPARE (((const struct directory *) x)->name,
     415                            ((const struct directory *) y)->name);
     416  }
     417  
     418  /* Table of directories hashed by name.  */
     419  static struct hash_table directories;
     420  
     421  
     422  /* Hash table of files in each directory.  */
     423  
     424  struct dirfile
     425    {
     426      const char *name;           /* Name of the file.  */
     427      size_t length;
     428      short impossible;           /* This file is impossible.  */
     429      unsigned char type;
     430    };
     431  
     432  static unsigned long
     433  dirfile_hash_1 (const void *key)
     434  {
     435    return_ISTRING_HASH_1 (((struct dirfile const *) key)->name);
     436  }
     437  
     438  static unsigned long
     439  dirfile_hash_2 (const void *key)
     440  {
     441    return_ISTRING_HASH_2 (((struct dirfile const *) key)->name);
     442  }
     443  
     444  static int
     445  dirfile_hash_cmp (const void *xv, const void *yv)
     446  {
     447    const struct dirfile *x = xv;
     448    const struct dirfile *y = yv;
     449    int result = (int) (x->length - y->length);
     450    if (result)
     451      return result;
     452    return_ISTRING_COMPARE (x->name, y->name);
     453  }
     454  
     455  #ifndef DIRFILE_BUCKETS
     456  #define DIRFILE_BUCKETS 107
     457  #endif
     458  
     459  static int dir_contents_file_exists_p (struct directory_contents *dir,
     460                                         const char *filename);
     461  static struct directory *find_directory (const char *name);
     462  
     463  /* Find the directory named NAME and return its 'struct directory'.  */
     464  
     465  static struct directory *
     466  find_directory (const char *name)
     467  {
     468    struct directory *dir;
     469    struct directory **dir_slot;
     470    struct directory dir_key;
     471    struct directory_contents *dc;
     472    struct directory_contents **dc_slot;
     473    struct directory_contents dc_key;
     474  
     475    struct stat st;
     476    int r;
     477  #ifdef WINDOWS32
     478    char *w32_path;
     479  #endif
     480  
     481    dir_key.name = name;
     482    dir_slot = (struct directory **) hash_find_slot (&directories, &dir_key);
     483    dir = *dir_slot;
     484  
     485    if (!HASH_VACANT (dir))
     486      {
     487        unsigned long ctr = dir->contents ? dir->contents->counter : dir->counter;
     488  
     489        /* No commands have run since we parsed this directory so it's good.  */
     490        if (ctr == command_count)
     491          return dir;
     492  
     493        DB (DB_VERBOSE, ("Directory %s cache invalidated (count %lu != command %lu)\n",
     494                         name, ctr, command_count));
     495  
     496        if (dir->contents)
     497          clear_directory_contents (dir->contents);
     498      }
     499    else
     500      {
     501        /* The directory was not found.  Create a new entry for it.  */
     502        size_t len = strlen (name);
     503  
     504        dir = xmalloc (sizeof (struct directory));
     505  #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
     506        /* Todo: Why is this only needed on VMS? */
     507        {
     508          char *lname = downcase_inplace (xstrdup (name));
     509          dir->name = strcache_add_len (lname, len);
     510          free (lname);
     511        }
     512  #else
     513        dir->name = strcache_add_len (name, len);
     514  #endif
     515        hash_insert_at (&directories, dir, dir_slot);
     516      }
     517  
     518    dir->contents = NULL;
     519    dir->counter = command_count;
     520  
     521    /* See if the directory exists.  */
     522  #if defined(WINDOWS32)
     523    {
     524      char tem[MAX_PATH+1], *tstart, *tend;
     525      size_t len = strlen (name);
     526  
     527      /* Remove any trailing slashes.  Windows32 stat fails even on
     528         valid directories if they end in a slash. */
     529      memcpy (tem, name, len + 1);
     530      tstart = tem;
     531      if (tstart[1] == ':')
     532        tstart += 2;
     533      for (tend = tem + (len - 1); tend > tstart && ISDIRSEP (*tend); tend--)
     534        *tend = '\0';
     535  
     536      r = stat (tem, &st);
     537    }
     538  #else
     539    EINTRLOOP (r, stat (name, &st));
     540  #endif
     541  
     542    if (r < 0)
     543      /* Couldn't stat the directory; nothing else to do.  */
     544      return dir;
     545  
     546    /* Search the contents hash table; device and inode are the key.  */
     547  
     548    memset (&dc_key, '\0', sizeof (dc_key));
     549    dc_key.dev = st.st_dev;
     550  #ifdef WINDOWS32
     551    dc_key.path_key = w32_path = w32ify (name, 1);
     552    dc_key.ctime = st.st_ctime;
     553  #else
     554  # ifdef VMS_INO_T
     555    dc_key.ino[0] = st.st_ino[0];
     556    dc_key.ino[1] = st.st_ino[1];
     557    dc_key.ino[2] = st.st_ino[2];
     558  # else
     559    dc_key.ino = st.st_ino;
     560  # endif
     561  #endif
     562    dc_slot = (struct directory_contents **) hash_find_slot (&directory_contents, &dc_key);
     563    dc = *dc_slot;
     564  
     565    if (HASH_VACANT (dc))
     566      {
     567        /* Nope; this really is a directory we haven't seen before.  */
     568  #ifdef WINDOWS32
     569        char  fs_label[BUFSIZ];
     570        char  fs_type[BUFSIZ];
     571        unsigned long  fs_serno;
     572        unsigned long  fs_flags;
     573        unsigned long  fs_len;
     574  #endif
     575        /* Enter it in the contents hash table.  */
     576        dc = xcalloc (sizeof (struct directory_contents));
     577        *dc = dc_key;
     578  
     579  #ifdef WINDOWS32
     580        dc->path_key = xstrdup (w32_path);
     581        dc->mtime = st.st_mtime;
     582  
     583        /* NTFS is the only WINDOWS32 filesystem that bumps mtime on a
     584           directory when files are added/deleted from a directory.  */
     585        w32_path[3] = '\0';
     586        if (GetVolumeInformation (w32_path, fs_label, sizeof (fs_label),
     587                                  &fs_serno, &fs_len, &fs_flags, fs_type,
     588                                  sizeof (fs_type)) == FALSE)
     589          dc->fs_flags = FS_UNKNOWN;
     590        else if (!strcmp (fs_type, "FAT"))
     591          dc->fs_flags = FS_FAT;
     592        else if (!strcmp (fs_type, "NTFS"))
     593          dc->fs_flags = FS_NTFS;
     594        else
     595          dc->fs_flags = FS_UNKNOWN;
     596  #endif /* WINDOWS32 */
     597  
     598        hash_insert_at (&directory_contents, dc, dc_slot);
     599      }
     600  
     601    /* Point the name-hashed entry for DIR at its contents data.  */
     602    dir->contents = dc;
     603  
     604    /* If the contents have changed, we need to reseed.  */
     605    if (dc->counter != command_count)
     606      {
     607        if (dc->counter)
     608          clear_directory_contents (dc);
     609  
     610        dc->counter = command_count;
     611  
     612        ENULLLOOP (dc->dirstream, opendir (name));
     613        if (dc->dirstream == 0)
     614          /* Couldn't open the directory.  Mark this by setting the
     615             'files' member to a nil pointer.  */
     616          dc->dirfiles.ht_vec = 0;
     617        else
     618          {
     619            hash_init (&dc->dirfiles, DIRFILE_BUCKETS,
     620                       dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
     621            /* Keep track of how many directories are open.  */
     622            ++open_directories;
     623            if (open_directories == MAX_OPEN_DIRECTORIES)
     624              /* We have too many directories open already.
     625                 Read the entire directory and then close it.  */
     626              dir_contents_file_exists_p (dc, 0);
     627          }
     628      }
     629  
     630    return dir;
     631  }
     632  
     633  /* Return 1 if the name FILENAME is entered in DIR's hash table.
     634     FILENAME must contain no slashes.  */
     635  
     636  static int
     637  dir_contents_file_exists_p (struct directory_contents *dir,
     638                              const char *filename)
     639  {
     640    struct dirfile *df;
     641    struct dirent *d;
     642  #ifdef WINDOWS32
     643    struct stat st;
     644    int rehash = 0;
     645  #endif
     646  
     647    if (dir == 0 || dir->dirfiles.ht_vec == 0)
     648      /* The directory could not be stat'd or opened.  */
     649      return 0;
     650  
     651  #ifdef __MSDOS__
     652    filename = dosify (filename);
     653  #endif
     654  
     655  #ifdef HAVE_CASE_INSENSITIVE_FS
     656    filename = downcase (filename);
     657  #endif
     658  
     659  #ifdef __EMX__
     660    if (filename != 0)
     661      _fnlwr (filename); /* lower case for FAT drives */
     662  #endif
     663    if (filename != 0)
     664      {
     665        struct dirfile dirfile_key;
     666  
     667        if (*filename == '\0')
     668          {
     669            /* Checking if the directory exists.  */
     670            return 1;
     671          }
     672        dirfile_key.name = filename;
     673        dirfile_key.length = strlen (filename);
     674        df = hash_find_item (&dir->dirfiles, &dirfile_key);
     675        if (df)
     676          return !df->impossible;
     677      }
     678  
     679    /* The file was not found in the hashed list.
     680       Try to read the directory further.  */
     681  
     682    if (dir->dirstream == 0)
     683      {
     684  #ifdef WINDOWS32
     685        /*
     686         * Check to see if directory has changed since last read. FAT
     687         * filesystems force a rehash always as mtime does not change
     688         * on directories (ugh!).
     689         */
     690        if (dir->path_key)
     691          {
     692            if ((dir->fs_flags & FS_FAT) != 0)
     693              {
     694                dir->mtime = time ((time_t *) 0);
     695                rehash = 1;
     696              }
     697            else if (stat (dir->path_key, &st) == 0 && st.st_mtime > dir->mtime)
     698              {
     699                /* reset date stamp to show most recent re-process.  */
     700                dir->mtime = st.st_mtime;
     701                rehash = 1;
     702              }
     703  
     704            /* If it has been already read in, all done.  */
     705            if (!rehash)
     706              return 0;
     707  
     708            /* make sure directory can still be opened; if not return.  */
     709            dir->dirstream = opendir (dir->path_key);
     710            if (!dir->dirstream)
     711              return 0;
     712          }
     713        else
     714  #endif
     715          /* The directory has been all read in.  */
     716          return 0;
     717      }
     718  
     719    while (1)
     720      {
     721        /* Enter the file in the hash table.  */
     722        size_t len;
     723        struct dirfile dirfile_key;
     724        struct dirfile **dirfile_slot;
     725  
     726        ENULLLOOP (d, readdir (dir->dirstream));
     727        if (d == 0)
     728          {
     729            if (errno)
     730              pfatal_with_name ("INTERNAL: readdir");
     731            break;
     732          }
     733  
     734  #if defined(VMS) && defined(HAVE_DIRENT_H)
     735        /* In VMS we get file versions too, which have to be stripped off.
     736           Some versions of VMS return versions on Unix files even when
     737           the feature option to strip them is set.  */
     738        {
     739          char *p = strrchr (d->d_name, ';');
     740          if (p)
     741            *p = '\0';
     742        }
     743  #endif
     744        if (!REAL_DIR_ENTRY (d))
     745          continue;
     746  
     747        len = NAMLEN (d);
     748        dirfile_key.name = d->d_name;
     749        dirfile_key.length = len;
     750        dirfile_slot = (struct dirfile **) hash_find_slot (&dir->dirfiles, &dirfile_key);
     751  #ifdef WINDOWS32
     752        /*
     753         * If re-reading a directory, don't cache files that have
     754         * already been discovered.
     755         */
     756        if (! rehash || HASH_VACANT (*dirfile_slot))
     757  #endif
     758          {
     759            df = xmalloc (sizeof (struct dirfile));
     760  #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
     761            /* TODO: Why is this only needed on VMS? */
     762            df->name = strcache_add_len (downcase_inplace (d->d_name), len);
     763  #else
     764            df->name = strcache_add_len (d->d_name, len);
     765  #endif
     766  #ifdef HAVE_STRUCT_DIRENT_D_TYPE
     767            df->type = d->d_type;
     768  #endif
     769            df->length = len;
     770            df->impossible = 0;
     771            hash_insert_at (&dir->dirfiles, df, dirfile_slot);
     772          }
     773        /* Check if the name matches the one we're searching for.  */
     774        if (filename != 0 && patheq (d->d_name, filename))
     775          return 1;
     776      }
     777  
     778    /* If the directory has been completely read in,
     779       close the stream and reset the pointer to nil.  */
     780    if (d == 0)
     781      {
     782        --open_directories;
     783        closedir (dir->dirstream);
     784        dir->dirstream = 0;
     785      }
     786    return 0;
     787  }
     788  
     789  /* Return 1 if the name FILENAME in directory DIRNAME
     790     is entered in the dir hash table.
     791     FILENAME must contain no slashes.  */
     792  
     793  int
     794  dir_file_exists_p (const char *dirname, const char *filename)
     795  {
     796  #ifdef VMS
     797    if ((filename != NULL) && (dirname != NULL))
     798      {
     799        int want_vmsify;
     800        want_vmsify = (strpbrk (dirname, ":<[") != NULL);
     801        if (want_vmsify)
     802          filename = vmsify (filename, 0);
     803      }
     804  #endif
     805    return dir_contents_file_exists_p (find_directory (dirname)->contents,
     806                                       filename);
     807  }
     808  
     809  /* Return 1 if the file named NAME exists.  */
     810  
     811  int
     812  file_exists_p (const char *name)
     813  {
     814    const char *dirend;
     815    const char *dirname;
     816    const char *slash;
     817  
     818  #ifndef NO_ARCHIVES
     819    if (ar_name (name))
     820      return ar_member_date (name) != (time_t) -1;
     821  #endif
     822  
     823    dirend = strrchr (name, '/');
     824  #ifdef VMS
     825    if (dirend == 0)
     826      {
     827        dirend = strrchr (name, ']');
     828        dirend == NULL ? dirend : dirend++;
     829      }
     830    if (dirend == 0)
     831      {
     832        dirend = strrchr (name, '>');
     833        dirend == NULL ? dirend : dirend++;
     834      }
     835    if (dirend == 0)
     836      {
     837        dirend = strrchr (name, ':');
     838        dirend == NULL ? dirend : dirend++;
     839      }
     840  #endif /* VMS */
     841  #ifdef HAVE_DOS_PATHS
     842    /* Forward and backslashes might be mixed.  We need the rightmost one.  */
     843    {
     844      const char *bslash = strrchr (name, '\\');
     845      if (!dirend || bslash > dirend)
     846        dirend = bslash;
     847      /* The case of "d:file".  */
     848      if (!dirend && name[0] && name[1] == ':')
     849        dirend = name + 1;
     850    }
     851  #endif /* HAVE_DOS_PATHS */
     852    if (dirend == 0)
     853  #ifndef _AMIGA
     854      return dir_file_exists_p (".", name);
     855  #else /* !AMIGA */
     856      return dir_file_exists_p ("", name);
     857  #endif /* AMIGA */
     858  
     859    slash = dirend;
     860    if (dirend == name)
     861      dirname = "/";
     862    else
     863      {
     864        char *p;
     865  #ifdef HAVE_DOS_PATHS
     866    /* d:/ and d: are *very* different...  */
     867        if (dirend < name + 3 && name[1] == ':' &&
     868            (ISDIRSEP (*dirend) || *dirend == ':'))
     869          dirend++;
     870  #endif
     871        p = alloca (dirend - name + 1);
     872        memcpy (p, name, dirend - name);
     873        p[dirend - name] = '\0';
     874        dirname = p;
     875      }
     876  #ifdef VMS
     877    if (*slash == '/')
     878      slash++;
     879  #else
     880    slash++;
     881  #endif
     882    return dir_file_exists_p (dirname, slash);
     883  }
     884  
     885  /* Mark FILENAME as 'impossible' for 'file_impossible_p'.
     886     This means an attempt has been made to search for FILENAME
     887     as an intermediate file, and it has failed.  */
     888  
     889  void
     890  file_impossible (const char *filename)
     891  {
     892    const char *dirend;
     893    const char *p = filename;
     894    struct directory *dir;
     895    struct dirfile *new;
     896  
     897    dirend = strrchr (p, '/');
     898  #ifdef VMS
     899    if (dirend == NULL)
     900      {
     901        dirend = strrchr (p, ']');
     902        dirend == NULL ? dirend : dirend++;
     903      }
     904    if (dirend == NULL)
     905      {
     906        dirend = strrchr (p, '>');
     907        dirend == NULL ? dirend : dirend++;
     908      }
     909    if (dirend == NULL)
     910      {
     911        dirend = strrchr (p, ':');
     912        dirend == NULL ? dirend : dirend++;
     913      }
     914  #endif
     915  #ifdef HAVE_DOS_PATHS
     916    /* Forward and backslashes might be mixed.  We need the rightmost one.  */
     917    {
     918      const char *bslash = strrchr (p, '\\');
     919      if (!dirend || bslash > dirend)
     920        dirend = bslash;
     921      /* The case of "d:file".  */
     922      if (!dirend && p[0] && p[1] == ':')
     923        dirend = p + 1;
     924    }
     925  #endif /* HAVE_DOS_PATHS */
     926    if (dirend == 0)
     927  #ifdef _AMIGA
     928      dir = find_directory ("");
     929  #else /* !AMIGA */
     930      dir = find_directory (".");
     931  #endif /* AMIGA */
     932    else
     933      {
     934        const char *dirname;
     935        const char *slash = dirend;
     936        if (dirend == p)
     937          dirname = "/";
     938        else
     939          {
     940            char *cp;
     941  #ifdef HAVE_DOS_PATHS
     942            /* d:/ and d: are *very* different...  */
     943            if (dirend < p + 3 && p[1] == ':' &&
     944                (ISDIRSEP (*dirend) || *dirend == ':'))
     945              dirend++;
     946  #endif
     947            cp = alloca (dirend - p + 1);
     948            memcpy (cp, p, dirend - p);
     949            cp[dirend - p] = '\0';
     950            dirname = cp;
     951          }
     952        dir = find_directory (dirname);
     953  #ifdef VMS
     954        if (*slash == '/')
     955          filename = p = slash + 1;
     956        else
     957          filename = p = slash;
     958  #else
     959        filename = p = slash + 1;
     960  #endif
     961      }
     962  
     963    if (dir->contents == 0)
     964      /* The directory could not be stat'd.  We allocate a contents
     965         structure for it, but leave it out of the contents hash table.  */
     966      dir->contents = xcalloc (sizeof (struct directory_contents));
     967  
     968    if (dir->contents->dirfiles.ht_vec == 0)
     969      {
     970        hash_init (&dir->contents->dirfiles, DIRFILE_BUCKETS,
     971                   dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
     972      }
     973  
     974    /* Make a new entry and put it in the table.  */
     975  
     976    new = xmalloc (sizeof (struct dirfile));
     977    new->length = strlen (filename);
     978  #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
     979    /* todo: Why is this only needed on VMS? */
     980    new->name = strcache_add_len (downcase (filename), new->length);
     981  #else
     982    new->name = strcache_add_len (filename, new->length);
     983  #endif
     984    new->impossible = 1;
     985    hash_insert (&dir->contents->dirfiles, new);
     986  }
     987  
     988  /* Return nonzero if FILENAME has been marked impossible.  */
     989  
     990  int
     991  file_impossible_p (const char *filename)
     992  {
     993    const char *dirend;
     994    struct directory_contents *dir;
     995    struct dirfile *dirfile;
     996    struct dirfile dirfile_key;
     997  #ifdef VMS
     998    int want_vmsify = 0;
     999  #endif
    1000  
    1001    dirend = strrchr (filename, '/');
    1002  #ifdef VMS
    1003    if (dirend == NULL)
    1004      {
    1005        want_vmsify = (strpbrk (filename, "]>:^") != NULL);
    1006        dirend = strrchr (filename, ']');
    1007      }
    1008    if (dirend == NULL && want_vmsify)
    1009      dirend = strrchr (filename, '>');
    1010    if (dirend == NULL && want_vmsify)
    1011      dirend = strrchr (filename, ':');
    1012  #endif
    1013  #ifdef HAVE_DOS_PATHS
    1014    /* Forward and backslashes might be mixed.  We need the rightmost one.  */
    1015    {
    1016      const char *bslash = strrchr (filename, '\\');
    1017      if (!dirend || bslash > dirend)
    1018        dirend = bslash;
    1019      /* The case of "d:file".  */
    1020      if (!dirend && filename[0] && filename[1] == ':')
    1021        dirend = filename + 1;
    1022    }
    1023  #endif /* HAVE_DOS_PATHS */
    1024    if (dirend == 0)
    1025  #ifdef _AMIGA
    1026      dir = find_directory ("")->contents;
    1027  #else /* !AMIGA */
    1028      dir = find_directory (".")->contents;
    1029  #endif /* AMIGA */
    1030    else
    1031      {
    1032        const char *dirname;
    1033        const char *slash = dirend;
    1034        if (dirend == filename)
    1035          dirname = "/";
    1036        else
    1037          {
    1038            char *cp;
    1039  #ifdef HAVE_DOS_PATHS
    1040            /* d:/ and d: are *very* different...  */
    1041            if (dirend < filename + 3 && filename[1] == ':' &&
    1042                (ISDIRSEP (*dirend) || *dirend == ':'))
    1043              dirend++;
    1044  #endif
    1045            cp = alloca (dirend - filename + 1);
    1046            memcpy (cp, filename, dirend - filename);
    1047            cp[dirend - filename] = '\0';
    1048            dirname = cp;
    1049          }
    1050        dir = find_directory (dirname)->contents;
    1051  #ifdef VMS
    1052        if (*slash == '/')
    1053          filename = slash + 1;
    1054        else
    1055          filename = slash;
    1056  #else
    1057        filename = slash + 1;
    1058  #endif
    1059      }
    1060  
    1061    if (dir == 0 || dir->dirfiles.ht_vec == 0)
    1062      /* There are no files entered for this directory.  */
    1063      return 0;
    1064  
    1065  #ifdef __MSDOS__
    1066    filename = dosify (filename);
    1067  #endif
    1068  #ifdef HAVE_CASE_INSENSITIVE_FS
    1069    filename = downcase (filename);
    1070  #endif
    1071  #ifdef VMS
    1072    if (want_vmsify)
    1073      filename = vmsify (filename, 1);
    1074  #endif
    1075  
    1076    dirfile_key.name = filename;
    1077    dirfile_key.length = strlen (filename);
    1078    dirfile = hash_find_item (&dir->dirfiles, &dirfile_key);
    1079    if (dirfile)
    1080      return dirfile->impossible;
    1081  
    1082    return 0;
    1083  }
    1084  
    1085  /* Return the already allocated name in the
    1086     directory hash table that matches DIR.  */
    1087  
    1088  const char *
    1089  dir_name (const char *dir)
    1090  {
    1091    return find_directory (dir)->name;
    1092  }
    1093  
    1094  /* Print the data base of directories.  */
    1095  
    1096  void
    1097  print_dir_data_base (void)
    1098  {
    1099    unsigned int files;
    1100    unsigned int impossible;
    1101    struct directory **dir_slot;
    1102    struct directory **dir_end;
    1103  #ifdef WINDOWS32
    1104    char buf[INTSTR_LENGTH + 1];
    1105  #endif
    1106  
    1107    puts (_("\n# Directories\n"));
    1108  
    1109    files = impossible = 0;
    1110  
    1111    dir_slot = (struct directory **) directories.ht_vec;
    1112    dir_end = dir_slot + directories.ht_size;
    1113    for ( ; dir_slot < dir_end; dir_slot++)
    1114      {
    1115        struct directory *dir = *dir_slot;
    1116        if (! HASH_VACANT (dir))
    1117          {
    1118            if (dir->contents == 0)
    1119              printf (_("# %s: could not be stat'd.\n"), dir->name);
    1120            else if (dir->contents->dirfiles.ht_vec == 0)
    1121  #ifdef WINDOWS32
    1122              printf (_("# %s (key %s, mtime %s): could not be opened.\n"),
    1123                      dir->name, dir->contents->path_key,
    1124                      make_ulltoa ((unsigned long long)dir->contents->mtime, buf));
    1125  #elif defined(VMS_INO_T)
    1126              printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"),
    1127                      dir->name, dir->contents->dev,
    1128                      dir->contents->ino[0], dir->contents->ino[1],
    1129                      dir->contents->ino[2]);
    1130  #else
    1131              printf (_("# %s (device %ld, inode %ld): could not be opened.\n"),
    1132                      dir->name, (long) dir->contents->dev, (long) dir->contents->ino);
    1133  #endif
    1134            else
    1135              {
    1136                unsigned int f = 0;
    1137                unsigned int im = 0;
    1138                struct dirfile **files_slot;
    1139                struct dirfile **files_end;
    1140  
    1141                files_slot = (struct dirfile **) dir->contents->dirfiles.ht_vec;
    1142                files_end = files_slot + dir->contents->dirfiles.ht_size;
    1143                for ( ; files_slot < files_end; files_slot++)
    1144                  {
    1145                    struct dirfile *df = *files_slot;
    1146                    if (! HASH_VACANT (df))
    1147                      {
    1148                        if (df->impossible)
    1149                          ++im;
    1150                        else
    1151                          ++f;
    1152                      }
    1153                  }
    1154  #ifdef WINDOWS32
    1155                printf (_("# %s (key %s, mtime %s): "),
    1156                        dir->name, dir->contents->path_key,
    1157                        make_ulltoa ((unsigned long long)dir->contents->mtime, buf));
    1158  #elif defined(VMS_INO_T)
    1159                printf (_("# %s (device %d, inode [%d,%d,%d]): "),
    1160                        dir->name, dir->contents->dev,
    1161                        dir->contents->ino[0], dir->contents->ino[1],
    1162                        dir->contents->ino[2]);
    1163  #else
    1164                printf (_("# %s (device %ld, inode %ld): "), dir->name,
    1165                        (long)dir->contents->dev, (long)dir->contents->ino);
    1166  #endif
    1167                if (f == 0)
    1168                  fputs (_("No"), stdout);
    1169                else
    1170                  printf ("%u", f);
    1171                fputs (_(" files, "), stdout);
    1172                if (im == 0)
    1173                  fputs (_("no"), stdout);
    1174                else
    1175                  printf ("%u", im);
    1176                fputs (_(" impossibilities"), stdout);
    1177                if (dir->contents->dirstream == 0)
    1178                  puts (".");
    1179                else
    1180                  puts (_(" so far."));
    1181                files += f;
    1182                impossible += im;
    1183              }
    1184          }
    1185      }
    1186  
    1187    fputs ("\n# ", stdout);
    1188    if (files == 0)
    1189      fputs (_("No"), stdout);
    1190    else
    1191      printf ("%u", files);
    1192    fputs (_(" files, "), stdout);
    1193    if (impossible == 0)
    1194      fputs (_("no"), stdout);
    1195    else
    1196      printf ("%u", impossible);
    1197    printf (_(" impossibilities in %lu directories.\n"), directories.ht_fill);
    1198  }
    1199  
    1200  /* Hooks for globbing.  */
    1201  
    1202  /* Structure describing state of iterating through a directory hash table.  */
    1203  
    1204  struct dirstream
    1205    {
    1206      struct directory_contents *contents; /* The directory being read.  */
    1207      struct dirfile **dirfile_slot; /* Current slot in table.  */
    1208    };
    1209  
    1210  /* Forward declarations.  */
    1211  static __ptr_t open_dirstream (const char *);
    1212  static struct dirent *read_dirstream (__ptr_t);
    1213  
    1214  static __ptr_t
    1215  open_dirstream (const char *directory)
    1216  {
    1217    struct dirstream *new;
    1218    struct directory *dir = find_directory (directory);
    1219  
    1220    if (dir->contents == 0 || dir->contents->dirfiles.ht_vec == 0)
    1221      /* DIR->contents is nil if the directory could not be stat'd.
    1222         DIR->contents->dirfiles is nil if it could not be opened.  */
    1223      return 0;
    1224  
    1225    /* Read all the contents of the directory now.  There is no benefit
    1226       in being lazy, since glob will want to see every file anyway.  */
    1227  
    1228    dir_contents_file_exists_p (dir->contents, 0);
    1229  
    1230    new = xmalloc (sizeof (struct dirstream));
    1231    new->contents = dir->contents;
    1232    new->dirfile_slot = (struct dirfile **) new->contents->dirfiles.ht_vec;
    1233  
    1234    return (__ptr_t) new;
    1235  }
    1236  
    1237  static struct dirent *
    1238  read_dirstream (__ptr_t stream)
    1239  {
    1240    static char *buf;
    1241    static size_t bufsz;
    1242  
    1243    struct dirstream *const ds = (struct dirstream *) stream;
    1244    struct directory_contents *dc = ds->contents;
    1245    struct dirfile **dirfile_end = (struct dirfile **) dc->dirfiles.ht_vec + dc->dirfiles.ht_size;
    1246  
    1247    while (ds->dirfile_slot < dirfile_end)
    1248      {
    1249        struct dirfile *df = *ds->dirfile_slot++;
    1250        if (! HASH_VACANT (df) && !df->impossible)
    1251          {
    1252            /* The glob interface wants a 'struct dirent', so mock one up.  */
    1253            struct dirent *d;
    1254            size_t len = df->length + 1;
    1255            size_t sz = sizeof (*d) - sizeof (d->d_name) + len;
    1256            if (sz > bufsz)
    1257              {
    1258                bufsz *= 2;
    1259                if (sz > bufsz)
    1260                  bufsz = sz;
    1261                buf = xrealloc (buf, bufsz);
    1262              }
    1263            d = (struct dirent *) buf;
    1264  #ifdef __MINGW32__
    1265  # if __MINGW32_MAJOR_VERSION < 3 || (__MINGW32_MAJOR_VERSION == 3 && \
    1266                                       __MINGW32_MINOR_VERSION == 0)
    1267            d->d_name = xmalloc (len);
    1268  # endif
    1269  #endif
    1270            FAKE_DIR_ENTRY (d);
    1271  #ifdef _DIRENT_HAVE_D_NAMLEN
    1272            d->d_namlen = len - 1;
    1273  #endif
    1274  #ifdef HAVE_STRUCT_DIRENT_D_TYPE
    1275            d->d_type = df->type;
    1276  #endif
    1277            memcpy (d->d_name, df->name, len);
    1278            return d;
    1279          }
    1280      }
    1281  
    1282    return 0;
    1283  }
    1284  
    1285  /* On 64 bit ReliantUNIX (5.44 and above) in LFS mode, stat() is actually a
    1286   * macro for stat64().  If stat is a macro, make a local wrapper function to
    1287   * invoke it.
    1288   *
    1289   * On MS-Windows, stat() "succeeds" for foo/bar/. where foo/bar is a
    1290   * regular file; fix that here.
    1291   */
    1292  #if !defined(stat) && !defined(WINDOWS32) || defined(VMS)
    1293  # ifndef VMS
    1294  #  ifndef HAVE_SYS_STAT_H
    1295  int stat (const char *path, struct stat *sbuf);
    1296  #  endif
    1297  # else
    1298      /* We are done with the fake stat.  Go back to the real stat */
    1299  #   ifdef stat
    1300  #     undef stat
    1301  #   endif
    1302  # endif
    1303  # define local_stat stat
    1304  #else
    1305  static int
    1306  local_stat (const char *path, struct stat *buf)
    1307  {
    1308    int e;
    1309  #ifdef WINDOWS32
    1310    size_t plen = strlen (path);
    1311  
    1312    /* Make sure the parent of "." exists and is a directory, not a
    1313       file.  This is because 'stat' on Windows normalizes the argument
    1314       foo/. => foo without checking first that foo is a directory.  */
    1315    if (plen > 2 && path[plen - 1] == '.' && ISDIRSEP (path[plen - 2]))
    1316      {
    1317        char parent[MAX_PATH+1];
    1318  
    1319        strncpy (parent, path, MAX_PATH);
    1320        parent[MIN(plen - 2, MAX_PATH)] = '\0';
    1321        if (stat (parent, buf) < 0 || !_S_ISDIR (buf->st_mode))
    1322          return -1;
    1323      }
    1324  #endif
    1325  
    1326    EINTRLOOP (e, stat (path, buf));
    1327    return e;
    1328  }
    1329  #endif
    1330  
    1331  /* Similarly for lstat.  */
    1332  #if !defined(lstat) && !defined(WINDOWS32) || defined(VMS)
    1333  # ifndef VMS
    1334  #  ifndef HAVE_SYS_STAT_H
    1335  int lstat (const char *path, struct stat *sbuf);
    1336  #  endif
    1337  # else
    1338      /* We are done with the fake lstat.  Go back to the real lstat */
    1339  #   ifdef lstat
    1340  #     undef lstat
    1341  #   endif
    1342  # endif
    1343  # define local_lstat lstat
    1344  #elif defined(WINDOWS32)
    1345  /* Windows doesn't support lstat().  */
    1346  # define local_lstat local_stat
    1347  #else
    1348  static int
    1349  local_lstat (const char *path, struct stat *buf)
    1350  {
    1351    int e;
    1352    EINTRLOOP (e, lstat (path, buf));
    1353    return e;
    1354  }
    1355  #endif
    1356  
    1357  void
    1358  dir_setup_glob (glob_t *gl)
    1359  {
    1360    gl->gl_offs = 0;
    1361    gl->gl_opendir = open_dirstream;
    1362    gl->gl_readdir = read_dirstream;
    1363    gl->gl_closedir = free;
    1364    gl->gl_lstat = local_lstat;
    1365    gl->gl_stat = local_stat;
    1366  }
    1367  
    1368  void
    1369  hash_init_directories (void)
    1370  {
    1371    hash_init (&directories, DIRECTORY_BUCKETS,
    1372               directory_hash_1, directory_hash_2, directory_hash_cmp);
    1373    hash_init (&directory_contents, DIRECTORY_BUCKETS,
    1374               directory_contents_hash_1, directory_contents_hash_2,
    1375               directory_contents_hash_cmp);
    1376  }