summaryrefslogtreecommitdiff
path: root/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'dir.c')
-rw-r--r--dir.c537
1 files changed, 275 insertions, 262 deletions
diff --git a/dir.c b/dir.c
index 5529019..d046bd9 100644
--- a/dir.c
+++ b/dir.c
@@ -1,7 +1,5 @@
/* Directory hashing for GNU Make.
-Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-2010 Free Software Foundation, Inc.
+Copyright (C) 1988-2013 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@@ -16,10 +14,12 @@ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>. */
-#include "make.h"
+#include "makeint.h"
#include "hash.h"
+#include "filedef.h"
+#include "dep.h"
-#ifdef HAVE_DIRENT_H
+#ifdef HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
# ifdef VMS
@@ -86,21 +86,21 @@ dosify (const char *filename)
df = dos_filename;
/* First, transform the name part. */
- for (i = 0; *filename != '\0' && i < 8 && *filename != '.'; ++i)
+ for (i = 0; i < 8 && ! STOP_SET (*filename, MAP_DOT|MAP_NUL); ++i)
*df++ = tolower ((unsigned char)*filename++);
/* Now skip to the next dot. */
- while (*filename != '\0' && *filename != '.')
+ while (! STOP_SET (*filename, MAP_DOT|MAP_NUL))
++filename;
if (*filename != '\0')
{
*df++ = *filename++;
- for (i = 0; *filename != '\0' && i < 3 && *filename != '.'; ++i)
- *df++ = tolower ((unsigned char)*filename++);
+ for (i = 0; i < 3 && ! STOP_SET (*filename, MAP_DOT|MAP_NUL); ++i)
+ *df++ = tolower ((unsigned char)*filename++);
}
/* Look for more dots. */
- while (*filename != '\0' && *filename != '.')
+ while (! STOP_SET (*filename, MAP_DOT|MAP_NUL))
++filename;
if (*filename == '.')
return filename;
@@ -146,11 +146,11 @@ static int
vms_hash (const char *name)
{
int h = 0;
- int g;
while (*name)
{
unsigned char uc = *name;
+ int g;
#ifdef HAVE_CASE_INSENSITIVE_FS
h = (h << 4) + (isupper (uc) ? tolower (uc) : uc);
#else
@@ -159,10 +159,10 @@ vms_hash (const char *name)
name++;
g = h & 0xf0000000;
if (g)
- {
- h = h ^ (g >> 24);
- h = h ^ g;
- }
+ {
+ h = h ^ (g >> 24);
+ h = h ^ g;
+ }
}
return h;
}
@@ -179,7 +179,7 @@ vmsstat_dir (const char *name, struct stat *st)
if (dir == 0)
return -1;
closedir (dir);
- s = strchr (name, ':'); /* find device */
+ s = strchr (name, ':'); /* find device */
if (s)
{
/* to keep the compiler happy we said "const char *name", now we cheat */
@@ -204,13 +204,13 @@ vmsstat_dir (const char *name, struct stat *st)
/* Hash table of directories. */
-#ifndef DIRECTORY_BUCKETS
+#ifndef DIRECTORY_BUCKETS
#define DIRECTORY_BUCKETS 199
#endif
struct directory_contents
{
- dev_t dev; /* Device and inode numbers of this dir. */
+ dev_t dev; /* Device and inode numbers of this dir. */
#ifdef WINDOWS32
/* Inode means nothing on WINDOWS32. Even file key information is
* unreliable because it is random per file open and undefined for remote
@@ -231,8 +231,8 @@ struct directory_contents
ino_t ino;
# endif
#endif /* WINDOWS32 */
- struct hash_table dirfiles; /* Files in this directory. */
- DIR *dirstream; /* Stream reading this directory. */
+ struct hash_table dirfiles; /* Files in this directory. */
+ DIR *dirstream; /* Stream reading this directory. */
};
static unsigned long
@@ -248,9 +248,9 @@ directory_contents_hash_1 (const void *key_0)
#else
# ifdef VMS
hash = (((unsigned int) key->dev << 4)
- ^ ((unsigned int) key->ino[0]
- + (unsigned int) key->ino[1]
- + (unsigned int) key->ino[2]));
+ ^ ((unsigned int) key->ino[0]
+ + (unsigned int) key->ino[1]
+ + (unsigned int) key->ino[2]));
# else
hash = ((unsigned int) key->dev << 4) ^ (unsigned int) key->ino;
# endif
@@ -271,9 +271,9 @@ directory_contents_hash_2 (const void *key_0)
#else
# ifdef VMS
hash = (((unsigned int) key->dev << 4)
- ^ ~((unsigned int) key->ino[0]
- + (unsigned int) key->ino[1]
- + (unsigned int) key->ino[2]));
+ ^ ~((unsigned int) key->ino[0]
+ + (unsigned int) key->ino[1]
+ + (unsigned int) key->ino[2]));
# else
hash = ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ino;
# endif
@@ -333,11 +333,11 @@ static struct hash_table directory_contents;
struct directory
{
- const char *name; /* Name of the directory. */
+ const char *name; /* Name of the directory. */
/* The directory's contents. This data may be shared by several
entries in the hash table, which refer to the same directory
- (identified uniquely by `dev' and `ino') under different names. */
+ (identified uniquely by 'dev' and 'ino') under different names. */
struct directory_contents *contents;
};
@@ -357,7 +357,7 @@ static int
directory_hash_cmp (const void *x, const void *y)
{
return_ISTRING_COMPARE (((const struct directory *) x)->name,
- ((const struct directory *) y)->name);
+ ((const struct directory *) y)->name);
}
/* Table of directories hashed by name. */
@@ -374,9 +374,9 @@ static unsigned int open_directories = 0;
struct dirfile
{
- const char *name; /* Name of the file. */
+ const char *name; /* Name of the file. */
short length;
- short impossible; /* This file is impossible. */
+ short impossible; /* This file is impossible. */
};
static unsigned long
@@ -402,7 +402,7 @@ dirfile_hash_cmp (const void *xv, const void *yv)
return_ISTRING_COMPARE (x->name, y->name);
}
-#ifndef DIRFILE_BUCKETS
+#ifndef DIRFILE_BUCKETS
#define DIRFILE_BUCKETS 107
#endif
@@ -410,24 +410,15 @@ static int dir_contents_file_exists_p (struct directory_contents *dir,
const char *filename);
static struct directory *find_directory (const char *name);
-/* Find the directory named NAME and return its `struct directory'. */
+/* Find the directory named NAME and return its 'struct directory'. */
static struct directory *
find_directory (const char *name)
{
- const char *p;
struct directory *dir;
struct directory **dir_slot;
struct directory dir_key;
- int r;
-#ifdef WINDOWS32
- char* w32_path;
- char fs_label[BUFSIZ];
- char fs_type[BUFSIZ];
- unsigned long fs_serno;
- unsigned long fs_flags;
- unsigned long fs_len;
-#endif
+
#ifdef VMS
if ((*name == '.') && (*(name+1) == 0))
name = "[]";
@@ -441,20 +432,20 @@ find_directory (const char *name)
if (HASH_VACANT (dir))
{
- struct stat st;
-
/* The directory was not found. Create a new entry for it. */
+ const char *p = name + strlen (name);
+ struct stat st;
+ int r;
- p = name + strlen (name);
dir = xmalloc (sizeof (struct directory));
#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
- dir->name = strcache_add_len (downcase(name), p - name);
+ dir->name = strcache_add_len (downcase (name), p - name);
#else
dir->name = strcache_add_len (name, p - name);
#endif
hash_insert_at (&directories, dir, dir_slot);
/* The directory is not in the name hash table.
- Find its device and inode numbers, and look it up by them. */
+ Find its device and inode numbers, and look it up by them. */
#ifdef VMS
r = vmsstat_dir (name, &st);
@@ -481,96 +472,101 @@ find_directory (const char *name)
if (r < 0)
{
- /* Couldn't stat the directory. Mark this by
- setting the `contents' member to a nil pointer. */
- dir->contents = 0;
- }
+ /* Couldn't stat the directory. Mark this by
+ setting the 'contents' member to a nil pointer. */
+ dir->contents = 0;
+ }
else
- {
- /* Search the contents hash table; device and inode are the key. */
+ {
+ /* Search the contents hash table; device and inode are the key. */
- struct directory_contents *dc;
- struct directory_contents **dc_slot;
- struct directory_contents dc_key;
+#ifdef WINDOWS32
+ char *w32_path;
+#endif
+ struct directory_contents *dc;
+ struct directory_contents **dc_slot;
+ struct directory_contents dc_key;
- dc_key.dev = st.st_dev;
+ dc_key.dev = st.st_dev;
#ifdef WINDOWS32
- dc_key.path_key = w32_path = w32ify (name, 1);
- dc_key.ctime = st.st_ctime;
+ dc_key.path_key = w32_path = w32ify (name, 1);
+ dc_key.ctime = st.st_ctime;
#else
# ifdef VMS
- dc_key.ino[0] = st.st_ino[0];
- dc_key.ino[1] = st.st_ino[1];
- dc_key.ino[2] = st.st_ino[2];
+ dc_key.ino[0] = st.st_ino[0];
+ dc_key.ino[1] = st.st_ino[1];
+ dc_key.ino[2] = st.st_ino[2];
# else
- dc_key.ino = st.st_ino;
+ dc_key.ino = st.st_ino;
# endif
#endif
- dc_slot = (struct directory_contents **) hash_find_slot (&directory_contents, &dc_key);
- dc = *dc_slot;
+ dc_slot = (struct directory_contents **) hash_find_slot (&directory_contents, &dc_key);
+ dc = *dc_slot;
- if (HASH_VACANT (dc))
- {
- /* Nope; this really is a directory we haven't seen before. */
-
- dc = (struct directory_contents *)
- xmalloc (sizeof (struct directory_contents));
+ if (HASH_VACANT (dc))
+ {
+ /* Nope; this really is a directory we haven't seen before. */
+#ifdef WINDOWS32
+ char fs_label[BUFSIZ];
+ char fs_type[BUFSIZ];
+ unsigned long fs_serno;
+ unsigned long fs_flags;
+ unsigned long fs_len;
+#endif
+ dc = (struct directory_contents *)
+ xmalloc (sizeof (struct directory_contents));
- /* Enter it in the contents hash table. */
- dc->dev = st.st_dev;
+ /* Enter it in the contents hash table. */
+ dc->dev = st.st_dev;
#ifdef WINDOWS32
dc->path_key = xstrdup (w32_path);
- dc->ctime = st.st_ctime;
+ dc->ctime = st.st_ctime;
dc->mtime = st.st_mtime;
- /*
- * NTFS is the only WINDOWS32 filesystem that bumps mtime
- * on a directory when files are added/deleted from
- * a directory.
- */
+ /* NTFS is the only WINDOWS32 filesystem that bumps mtime on a
+ directory when files are added/deleted from a directory. */
w32_path[3] = '\0';
- if (GetVolumeInformation(w32_path,
- fs_label, sizeof (fs_label),
- &fs_serno, &fs_len,
- &fs_flags, fs_type, sizeof (fs_type)) == FALSE)
+ if (GetVolumeInformation (w32_path, fs_label, sizeof (fs_label),
+ &fs_serno, &fs_len, &fs_flags, fs_type,
+ sizeof (fs_type)) == FALSE)
dc->fs_flags = FS_UNKNOWN;
- else if (!strcmp(fs_type, "FAT"))
+ else if (!strcmp (fs_type, "FAT"))
dc->fs_flags = FS_FAT;
- else if (!strcmp(fs_type, "NTFS"))
+ else if (!strcmp (fs_type, "NTFS"))
dc->fs_flags = FS_NTFS;
else
dc->fs_flags = FS_UNKNOWN;
#else
# ifdef VMS
- dc->ino[0] = st.st_ino[0];
- dc->ino[1] = st.st_ino[1];
- dc->ino[2] = st.st_ino[2];
+ dc->ino[0] = st.st_ino[0];
+ dc->ino[1] = st.st_ino[1];
+ dc->ino[2] = st.st_ino[2];
# else
- dc->ino = st.st_ino;
+ dc->ino = st.st_ino;
# endif
#endif /* WINDOWS32 */
- hash_insert_at (&directory_contents, dc, dc_slot);
- ENULLLOOP (dc->dirstream, opendir (name));
- if (dc->dirstream == 0)
+ hash_insert_at (&directory_contents, dc, dc_slot);
+ ENULLLOOP (dc->dirstream, opendir (name));
+ if (dc->dirstream == 0)
/* Couldn't open the directory. Mark this by setting the
- `files' member to a nil pointer. */
+ 'files' member to a nil pointer. */
dc->dirfiles.ht_vec = 0;
- else
- {
- hash_init (&dc->dirfiles, DIRFILE_BUCKETS,
- dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
- /* Keep track of how many directories are open. */
- ++open_directories;
- if (open_directories == MAX_OPEN_DIRECTORIES)
- /* We have too many directories open already.
- Read the entire directory and then close it. */
- dir_contents_file_exists_p (dc, 0);
- }
- }
-
- /* Point the name-hashed entry for DIR at its contents data. */
- dir->contents = dc;
- }
+ else
+ {
+ hash_init (&dc->dirfiles, DIRFILE_BUCKETS,
+ dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
+ /* Keep track of how many directories are open. */
+ ++open_directories;
+ if (open_directories == MAX_OPEN_DIRECTORIES)
+ /* We have too many directories open already.
+ Read the entire directory and then close it. */
+ dir_contents_file_exists_p (dc, 0);
+ }
+ }
+
+ /* Point the name-hashed entry for DIR at its contents data. */
+ dir->contents = dc;
+ }
}
return dir;
@@ -583,7 +579,6 @@ static int
dir_contents_file_exists_p (struct directory_contents *dir,
const char *filename)
{
- unsigned int hash;
struct dirfile *df;
struct dirent *d;
#ifdef WINDOWS32
@@ -612,16 +607,15 @@ dir_contents_file_exists_p (struct directory_contents *dir,
filename = vmsify (filename,0);
#endif
- hash = 0;
if (filename != 0)
{
struct dirfile dirfile_key;
if (*filename == '\0')
- {
- /* Checking if the directory exists. */
- return 1;
- }
+ {
+ /* Checking if the directory exists. */
+ return 1;
+ }
dirfile_key.name = filename;
dirfile_key.length = strlen (filename);
df = hash_find_item (&dir->dirfiles, &dirfile_key);
@@ -641,32 +635,32 @@ dir_contents_file_exists_p (struct directory_contents *dir,
* on directories (ugh!).
*/
if (dir->path_key)
- {
+ {
if ((dir->fs_flags & FS_FAT) != 0)
- {
- dir->mtime = time ((time_t *) 0);
- rehash = 1;
- }
- else if (stat (dir->path_key, &st) == 0 && st.st_mtime > dir->mtime)
- {
- /* reset date stamp to show most recent re-process. */
- dir->mtime = st.st_mtime;
- rehash = 1;
- }
+ {
+ dir->mtime = time ((time_t *) 0);
+ rehash = 1;
+ }
+ else if (stat (dir->path_key, &st) == 0 && st.st_mtime > dir->mtime)
+ {
+ /* reset date stamp to show most recent re-process. */
+ dir->mtime = st.st_mtime;
+ rehash = 1;
+ }
/* If it has been already read in, all done. */
- if (!rehash)
- return 0;
+ if (!rehash)
+ return 0;
/* make sure directory can still be opened; if not return. */
dir->dirstream = opendir (dir->path_key);
if (!dir->dirstream)
return 0;
- }
+ }
else
#endif
- /* The directory has been all read in. */
- return 0;
+ /* The directory has been all read in. */
+ return 0;
}
while (1)
@@ -693,7 +687,7 @@ dir_contents_file_exists_p (struct directory_contents *dir,
}
#endif
if (!REAL_DIR_ENTRY (d))
- continue;
+ continue;
len = NAMLEN (d);
dirfile_key.name = d->d_name;
@@ -706,17 +700,17 @@ dir_contents_file_exists_p (struct directory_contents *dir,
*/
if (! rehash || HASH_VACANT (*dirfile_slot))
#endif
- {
- df = xmalloc (sizeof (struct dirfile));
+ {
+ df = xmalloc (sizeof (struct dirfile));
#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
- df->name = strcache_add_len (downcase(d->d_name), len);
+ df->name = strcache_add_len (downcase (d->d_name), len);
#else
- df->name = strcache_add_len (d->d_name, len);
+ df->name = strcache_add_len (d->d_name, len);
#endif
- df->length = len;
- df->impossible = 0;
- hash_insert_at (&dir->dirfiles, df, dirfile_slot);
- }
+ df->length = len;
+ df->impossible = 0;
+ hash_insert_at (&dir->dirfiles, df, dirfile_slot);
+ }
/* Check if the name matches the one we're searching for. */
if (filename != 0 && patheq (d->d_name, filename))
return 1;
@@ -741,7 +735,7 @@ int
dir_file_exists_p (const char *dirname, const char *filename)
{
return dir_contents_file_exists_p (find_directory (dirname)->contents,
- filename);
+ filename);
}
/* Return 1 if the file named NAME exists. */
@@ -753,7 +747,7 @@ file_exists_p (const char *name)
const char *dirname;
const char *slash;
-#ifndef NO_ARCHIVES
+#ifndef NO_ARCHIVES
if (ar_name (name))
return ar_member_date (name) != (time_t) -1;
#endif
@@ -769,7 +763,7 @@ file_exists_p (const char *name)
#ifdef HAVE_DOS_PATHS
/* Forward and backslashes might be mixed. We need the rightmost one. */
{
- const char *bslash = strrchr(name, '\\');
+ const char *bslash = strrchr (name, '\\');
if (!dirend || bslash > dirend)
dirend = bslash;
/* The case of "d:file". */
@@ -794,8 +788,8 @@ file_exists_p (const char *name)
#ifdef HAVE_DOS_PATHS
/* d:/ and d: are *very* different... */
if (dirend < name + 3 && name[1] == ':' &&
- (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
- dirend++;
+ (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
+ dirend++;
#endif
p = alloca (dirend - name + 1);
memcpy (p, name, dirend - name);
@@ -805,7 +799,7 @@ file_exists_p (const char *name)
return dir_file_exists_p (dirname, slash + 1);
}
-/* Mark FILENAME as `impossible' for `file_impossible_p'.
+/* Mark FILENAME as 'impossible' for 'file_impossible_p'.
This means an attempt has been made to search for FILENAME
as an intermediate file, and it has failed. */
@@ -829,7 +823,7 @@ file_impossible (const char *filename)
# ifdef HAVE_DOS_PATHS
/* Forward and backslashes might be mixed. We need the rightmost one. */
{
- const char *bslash = strrchr(p, '\\');
+ const char *bslash = strrchr (p, '\\');
if (!dirend || bslash > dirend)
dirend = bslash;
/* The case of "d:file". */
@@ -849,21 +843,21 @@ file_impossible (const char *filename)
const char *dirname;
const char *slash = dirend;
if (dirend == p)
- dirname = "/";
+ dirname = "/";
else
- {
+ {
char *cp;
#ifdef HAVE_DOS_PATHS
- /* d:/ and d: are *very* different... */
- if (dirend < p + 3 && p[1] == ':' &&
- (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
- dirend++;
+ /* d:/ and d: are *very* different... */
+ if (dirend < p + 3 && p[1] == ':' &&
+ (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
+ dirend++;
#endif
- cp = alloca (dirend - p + 1);
- memcpy (cp, p, dirend - p);
- cp[dirend - p] = '\0';
+ cp = alloca (dirend - p + 1);
+ memcpy (cp, p, dirend - p);
+ cp[dirend - p] = '\0';
dirname = cp;
- }
+ }
dir = find_directory (dirname);
filename = p = slash + 1;
}
@@ -876,7 +870,7 @@ file_impossible (const char *filename)
if (dir->contents->dirfiles.ht_vec == 0)
{
hash_init (&dir->contents->dirfiles, DIRFILE_BUCKETS,
- dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
+ dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
}
/* Make a new entry and put it in the table. */
@@ -884,7 +878,7 @@ file_impossible (const char *filename)
new = xmalloc (sizeof (struct dirfile));
new->length = strlen (filename);
#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
- new->name = strcache_add_len (downcase(filename), new->length);
+ new->name = strcache_add_len (downcase (filename), new->length);
#else
new->name = strcache_add_len (filename, new->length);
#endif
@@ -898,7 +892,6 @@ int
file_impossible_p (const char *filename)
{
const char *dirend;
- const char *p = filename;
struct directory_contents *dir;
struct dirfile *dirfile;
struct dirfile dirfile_key;
@@ -912,7 +905,7 @@ file_impossible_p (const char *filename)
#ifdef HAVE_DOS_PATHS
/* Forward and backslashes might be mixed. We need the rightmost one. */
{
- const char *bslash = strrchr(filename, '\\');
+ const char *bslash = strrchr (filename, '\\');
if (!dirend || bslash > dirend)
dirend = bslash;
/* The case of "d:file". */
@@ -932,23 +925,23 @@ file_impossible_p (const char *filename)
const char *dirname;
const char *slash = dirend;
if (dirend == filename)
- dirname = "/";
+ dirname = "/";
else
- {
+ {
char *cp;
#ifdef HAVE_DOS_PATHS
- /* d:/ and d: are *very* different... */
- if (dirend < filename + 3 && filename[1] == ':' &&
- (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
- dirend++;
+ /* d:/ and d: are *very* different... */
+ if (dirend < filename + 3 && filename[1] == ':' &&
+ (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
+ dirend++;
#endif
- cp = alloca (dirend - filename + 1);
- memcpy (cp, p, dirend - p);
- cp[dirend - p] = '\0';
+ cp = alloca (dirend - filename + 1);
+ memcpy (cp, filename, dirend - filename);
+ cp[dirend - filename] = '\0';
dirname = cp;
- }
+ }
dir = find_directory (dirname)->contents;
- p = filename = slash + 1;
+ filename = slash + 1;
}
if (dir == 0 || dir->dirfiles.ht_vec == 0)
@@ -956,13 +949,13 @@ file_impossible_p (const char *filename)
return 0;
#ifdef __MSDOS__
- filename = dosify (p);
+ filename = dosify (filename);
#endif
#ifdef HAVE_CASE_INSENSITIVE_FS
- filename = downcase (p);
+ filename = downcase (filename);
#endif
#ifdef VMS
- filename = vmsify (p, 1);
+ filename = vmsify (filename, 1);
#endif
dirfile_key.name = filename;
@@ -1003,80 +996,80 @@ print_dir_data_base (void)
{
struct directory *dir = *dir_slot;
if (! HASH_VACANT (dir))
- {
- if (dir->contents == 0)
- printf (_("# %s: could not be stat'd.\n"), dir->name);
- else if (dir->contents->dirfiles.ht_vec == 0)
- {
+ {
+ if (dir->contents == 0)
+ printf (_("# %s: could not be stat'd.\n"), dir->name);
+ else if (dir->contents->dirfiles.ht_vec == 0)
+ {
#ifdef WINDOWS32
- printf (_("# %s (key %s, mtime %d): could not be opened.\n"),
- dir->name, dir->contents->path_key,dir->contents->mtime);
+ printf (_("# %s (key %s, mtime %d): could not be opened.\n"),
+ dir->name, dir->contents->path_key,dir->contents->mtime);
#else /* WINDOWS32 */
#ifdef VMS
- printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"),
- dir->name, dir->contents->dev,
- dir->contents->ino[0], dir->contents->ino[1],
- dir->contents->ino[2]);
+ printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"),
+ dir->name, dir->contents->dev,
+ dir->contents->ino[0], dir->contents->ino[1],
+ dir->contents->ino[2]);
#else
- printf (_("# %s (device %ld, inode %ld): could not be opened.\n"),
- dir->name, (long int) dir->contents->dev,
- (long int) dir->contents->ino);
+ printf (_("# %s (device %ld, inode %ld): could not be opened.\n"),
+ dir->name, (long int) dir->contents->dev,
+ (long int) dir->contents->ino);
#endif
#endif /* WINDOWS32 */
- }
- else
- {
- unsigned int f = 0;
- unsigned int im = 0;
- struct dirfile **files_slot;
- struct dirfile **files_end;
-
- files_slot = (struct dirfile **) dir->contents->dirfiles.ht_vec;
- files_end = files_slot + dir->contents->dirfiles.ht_size;
- for ( ; files_slot < files_end; files_slot++)
- {
- struct dirfile *df = *files_slot;
- if (! HASH_VACANT (df))
- {
- if (df->impossible)
- ++im;
- else
- ++f;
- }
- }
+ }
+ else
+ {
+ unsigned int f = 0;
+ unsigned int im = 0;
+ struct dirfile **files_slot;
+ struct dirfile **files_end;
+
+ files_slot = (struct dirfile **) dir->contents->dirfiles.ht_vec;
+ files_end = files_slot + dir->contents->dirfiles.ht_size;
+ for ( ; files_slot < files_end; files_slot++)
+ {
+ struct dirfile *df = *files_slot;
+ if (! HASH_VACANT (df))
+ {
+ if (df->impossible)
+ ++im;
+ else
+ ++f;
+ }
+ }
#ifdef WINDOWS32
- printf (_("# %s (key %s, mtime %d): "),
- dir->name, dir->contents->path_key, dir->contents->mtime);
+ printf (_("# %s (key %s, mtime %d): "),
+ dir->name, dir->contents->path_key, dir->contents->mtime);
#else /* WINDOWS32 */
#ifdef VMS
- printf (_("# %s (device %d, inode [%d,%d,%d]): "),
- dir->name, dir->contents->dev,
- dir->contents->ino[0], dir->contents->ino[1],
- dir->contents->ino[2]);
+ printf (_("# %s (device %d, inode [%d,%d,%d]): "),
+ dir->name, dir->contents->dev,
+ dir->contents->ino[0], dir->contents->ino[1],
+ dir->contents->ino[2]);
#else
- printf (_("# %s (device %ld, inode %ld): "),
- dir->name,
- (long)dir->contents->dev, (long)dir->contents->ino);
+ printf (_("# %s (device %ld, inode %ld): "),
+ dir->name,
+ (long)dir->contents->dev, (long)dir->contents->ino);
#endif
#endif /* WINDOWS32 */
- if (f == 0)
- fputs (_("No"), stdout);
- else
- printf ("%u", f);
- fputs (_(" files, "), stdout);
- if (im == 0)
- fputs (_("no"), stdout);
- else
- printf ("%u", im);
- fputs (_(" impossibilities"), stdout);
- if (dir->contents->dirstream == 0)
- puts (".");
- else
- puts (_(" so far."));
- files += f;
- impossible += im;
- }
- }
+ if (f == 0)
+ fputs (_("No"), stdout);
+ else
+ printf ("%u", f);
+ fputs (_(" files, "), stdout);
+ if (im == 0)
+ fputs (_("no"), stdout);
+ else
+ printf ("%u", im);
+ fputs (_(" impossibilities"), stdout);
+ if (dir->contents->dirstream == 0)
+ puts (".");
+ else
+ puts (_(" so far."));
+ files += f;
+ impossible += im;
+ }
+ }
}
fputs ("\n# ", stdout);
@@ -1145,35 +1138,35 @@ read_dirstream (__ptr_t stream)
{
struct dirfile *df = *ds->dirfile_slot++;
if (! HASH_VACANT (df) && !df->impossible)
- {
- /* The glob interface wants a `struct dirent', so mock one up. */
- struct dirent *d;
- unsigned int len = df->length + 1;
+ {
+ /* The glob interface wants a 'struct dirent', so mock one up. */
+ struct dirent *d;
+ unsigned int len = df->length + 1;
unsigned int sz = sizeof (*d) - sizeof (d->d_name) + len;
- if (sz > bufsz)
- {
- bufsz *= 2;
- if (sz > bufsz)
- bufsz = sz;
- buf = xrealloc (buf, bufsz);
- }
- d = (struct dirent *) buf;
+ if (sz > bufsz)
+ {
+ bufsz *= 2;
+ if (sz > bufsz)
+ bufsz = sz;
+ buf = xrealloc (buf, bufsz);
+ }
+ d = (struct dirent *) buf;
#ifdef __MINGW32__
# if __MINGW32_MAJOR_VERSION < 3 || (__MINGW32_MAJOR_VERSION == 3 && \
- __MINGW32_MINOR_VERSION == 0)
- d->d_name = xmalloc(len);
+ __MINGW32_MINOR_VERSION == 0)
+ d->d_name = xmalloc (len);
# endif
#endif
- FAKE_DIR_ENTRY (d);
+ FAKE_DIR_ENTRY (d);
#ifdef _DIRENT_HAVE_D_NAMLEN
- d->d_namlen = len - 1;
+ d->d_namlen = len - 1;
#endif
#ifdef _DIRENT_HAVE_D_TYPE
- d->d_type = DT_UNKNOWN;
+ d->d_type = DT_UNKNOWN;
#endif
- memcpy (d->d_name, df->name, len);
- return d;
- }
+ memcpy (d->d_name, df->name, len);
+ return d;
+ }
}
return 0;
@@ -1183,14 +1176,17 @@ static void
ansi_free (void *p)
{
if (p)
- free(p);
+ free (p);
}
/* On 64 bit ReliantUNIX (5.44 and above) in LFS mode, stat() is actually a
* macro for stat64(). If stat is a macro, make a local wrapper function to
* invoke it.
+ *
+ * On MS-Windows, stat() "succeeds" for foo/bar/. where foo/bar is a
+ * regular file; fix that here.
*/
-#ifndef stat
+#if !defined(stat) && !defined(WINDOWS32)
# ifndef VMS
int stat (const char *path, struct stat *sbuf);
# endif
@@ -1200,6 +1196,23 @@ static int
local_stat (const char *path, struct stat *buf)
{
int e;
+#ifdef WINDOWS32
+ size_t plen = strlen (path);
+
+ /* Make sure the parent of "." exists and is a directory, not a
+ file. This is because 'stat' on Windows normalizes the argument
+ foo/. => foo without checking first that foo is a directory. */
+ if (plen > 1 && path[plen - 1] == '.'
+ && (path[plen - 2] == '/' || path[plen - 2] == '\\'))
+ {
+ char parent[MAXPATHLEN];
+
+ strncpy (parent, path, plen - 2);
+ parent[plen - 2] = '\0';
+ if (stat (parent, buf) < 0 || !_S_ISDIR (buf->st_mode))
+ return -1;
+ }
+#endif
EINTRLOOP (e, stat (path, buf));
return e;
@@ -1221,8 +1234,8 @@ void
hash_init_directories (void)
{
hash_init (&directories, DIRECTORY_BUCKETS,
- directory_hash_1, directory_hash_2, directory_hash_cmp);
+ directory_hash_1, directory_hash_2, directory_hash_cmp);
hash_init (&directory_contents, DIRECTORY_BUCKETS,
- directory_contents_hash_1, directory_contents_hash_2,
+ directory_contents_hash_1, directory_contents_hash_2,
directory_contents_hash_cmp);
}