diff options
Diffstat (limited to 'dir.c')
-rw-r--r-- | dir.c | 537 |
1 files changed, 275 insertions, 262 deletions
@@ -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); } |