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