Changeset 3138 in kBuild for vendor/gnumake/current/dir.c
- Timestamp:
- Mar 12, 2018 7:32:29 PM (7 years ago)
- File:
-
- 1 edited
-
vendor/gnumake/current/dir.c (modified) (51 diffs)
Legend:
- Unmodified
- Added
- Removed
-
vendor/gnumake/current/dir.c
r2596 r3138 1 1 /* Directory hashing for GNU Make. 2 Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 3 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 4 2010 Free Software Foundation, Inc. 2 Copyright (C) 1988-2016 Free Software Foundation, Inc. 5 3 This file is part of GNU Make. 6 4 … … 17 15 this program. If not, see <http://www.gnu.org/licenses/>. */ 18 16 19 #include "make .h"17 #include "makeint.h" 20 18 #include "hash.h" 21 22 #ifdef HAVE_DIRENT_H 19 #include "filedef.h" 20 #include "dep.h" 21 22 #ifdef HAVE_DIRENT_H 23 23 # include <dirent.h> 24 24 # define NAMLEN(dirent) strlen((dirent)->d_name) … … 88 88 89 89 /* First, transform the name part. */ 90 for (i = 0; *filename != '\0' && i < 8 && *filename != '.'; ++i)90 for (i = 0; i < 8 && ! STOP_SET (*filename, MAP_DOT|MAP_NUL); ++i) 91 91 *df++ = tolower ((unsigned char)*filename++); 92 92 93 93 /* Now skip to the next dot. */ 94 while ( *filename != '\0' && *filename != '.')94 while (! STOP_SET (*filename, MAP_DOT|MAP_NUL)) 95 95 ++filename; 96 96 if (*filename != '\0') 97 97 { 98 98 *df++ = *filename++; 99 for (i = 0; *filename != '\0' && i < 3 && *filename != '.'; ++i)100 *df++ = tolower ((unsigned char)*filename++);99 for (i = 0; i < 3 && ! STOP_SET (*filename, MAP_DOT|MAP_NUL); ++i) 100 *df++ = tolower ((unsigned char)*filename++); 101 101 } 102 102 103 103 /* Look for more dots. */ 104 while ( *filename != '\0' && *filename != '.')104 while (! STOP_SET (*filename, MAP_DOT|MAP_NUL)) 105 105 ++filename; 106 106 if (*filename == '.') … … 144 144 #ifdef VMS 145 145 146 static char * 147 downcase_inplace(char *filename) 148 { 149 char *name; 150 name = filename; 151 while (*name != '\0') 152 { 153 *name = tolower ((unsigned char)*name); 154 ++name; 155 } 156 return filename; 157 } 158 159 #ifndef _USE_STD_STAT 160 /* VMS 8.2 fixed the VMS stat output to have unique st_dev and st_ino 161 when _USE_STD_STAT is used on the compile line. 162 163 Prior to _USE_STD_STAT support, the st_dev is a pointer to thread 164 static memory containing the device of the last filename looked up. 165 166 Todo: find out if the ino_t still needs to be faked on a directory. 167 */ 168 169 /* Define this if the older VMS_INO_T is needed */ 170 #define VMS_INO_T 1 171 146 172 static int 147 173 vms_hash (const char *name) 148 174 { 149 175 int h = 0; 150 int g;151 176 152 177 while (*name) 153 178 { 154 179 unsigned char uc = *name; 180 int g; 155 181 #ifdef HAVE_CASE_INSENSITIVE_FS 156 182 h = (h << 4) + (isupper (uc) ? tolower (uc) : uc); … … 161 187 g = h & 0xf0000000; 162 188 if (g) 163 {164 h = h ^ (g >> 24);165 h = h ^ g;166 }189 { 190 h = h ^ (g >> 24); 191 h = h ^ g; 192 } 167 193 } 168 194 return h; … … 181 207 return -1; 182 208 closedir (dir); 183 s = strchr (name, ':'); /* find device */209 s = strchr (name, ':'); /* find device */ 184 210 if (s) 185 211 { … … 202 228 return 0; 203 229 } 230 231 # define stat(__path, __sbuf) vmsstat_dir (__path, __sbuf) 232 233 #endif /* _USE_STD_STAT */ 204 234 #endif /* VMS */ 205 235 … … 207 237 /* Hash table of directories. */ 208 238 209 #ifndef DIRECTORY_BUCKETS239 #ifndef DIRECTORY_BUCKETS 210 240 #define DIRECTORY_BUCKETS 199 211 241 #endif … … 213 243 struct directory_contents 214 244 { 215 dev_t dev; /* Device and inode numbers of this dir. */245 dev_t dev; /* Device and inode numbers of this dir. */ 216 246 #ifdef WINDOWS32 217 247 /* Inode means nothing on WINDOWS32. Even file key information is … … 221 251 * unreliable. I'm open to suggestion on a better way to emulate inode. */ 222 252 char *path_key; 223 intctime;224 intmtime; /* controls check for stale directory cache */225 int fs_flags; /* FS_FAT, FS_NTFS, ... */253 time_t ctime; 254 time_t mtime; /* controls check for stale directory cache */ 255 int fs_flags; /* FS_FAT, FS_NTFS, ... */ 226 256 # define FS_FAT 0x1 227 257 # define FS_NTFS 0x2 228 258 # define FS_UNKNOWN 0x4 229 259 #else 230 # ifdef VMS 260 # ifdef VMS_INO_T 231 261 ino_t ino[3]; 232 262 # else … … 234 264 # endif 235 265 #endif /* WINDOWS32 */ 236 struct hash_table dirfiles; /* Files in this directory. */237 DIR *dirstream; /* Stream reading this directory. */266 struct hash_table dirfiles; /* Files in this directory. */ 267 DIR *dirstream; /* Stream reading this directory. */ 238 268 }; 239 269 … … 249 279 hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) key->ctime; 250 280 #else 251 # ifdef VMS 281 # ifdef VMS_INO_T 252 282 hash = (((unsigned int) key->dev << 4) 253 ^ ((unsigned int) key->ino[0]254 + (unsigned int) key->ino[1]255 + (unsigned int) key->ino[2]));283 ^ ((unsigned int) key->ino[0] 284 + (unsigned int) key->ino[1] 285 + (unsigned int) key->ino[2])); 256 286 # else 257 287 hash = ((unsigned int) key->dev << 4) ^ (unsigned int) key->ino; … … 272 302 hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ctime; 273 303 #else 274 # ifdef VMS 304 # ifdef VMS_INO_T 275 305 hash = (((unsigned int) key->dev << 4) 276 ^ ~((unsigned int) key->ino[0]277 + (unsigned int) key->ino[1]278 + (unsigned int) key->ino[2]));306 ^ ~((unsigned int) key->ino[0] 307 + (unsigned int) key->ino[1] 308 + (unsigned int) key->ino[2])); 279 309 # else 280 310 hash = ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ino; … … 311 341 return result; 312 342 #else 313 # ifdef VMS 343 # ifdef VMS_INO_T 314 344 result = MAKECMP(x->ino[0], y->ino[0]); 315 345 if (result) … … 336 366 struct directory 337 367 { 338 const char *name; /* Name of the directory. */368 const char *name; /* Name of the directory. */ 339 369 340 370 /* The directory's contents. This data may be shared by several 341 371 entries in the hash table, which refer to the same directory 342 (identified uniquely by `dev' and `ino') under different names. */372 (identified uniquely by 'dev' and 'ino') under different names. */ 343 373 struct directory_contents *contents; 344 374 }; … … 360 390 { 361 391 return_ISTRING_COMPARE (((const struct directory *) x)->name, 362 ((const struct directory *) y)->name);392 ((const struct directory *) y)->name); 363 393 } 364 394 … … 377 407 struct dirfile 378 408 { 379 const char *name; /* Name of the file. */380 s hort length;381 short impossible; /* This file is impossible. */409 const char *name; /* Name of the file. */ 410 size_t length; 411 short impossible; /* This file is impossible. */ 382 412 }; 383 413 … … 405 435 } 406 436 407 #ifndef DIRFILE_BUCKETS437 #ifndef DIRFILE_BUCKETS 408 438 #define DIRFILE_BUCKETS 107 409 439 #endif … … 414 444 static struct directory *find_directory (const char *name); 415 445 416 /* Find the directory named NAME and return its `struct directory'. */446 /* Find the directory named NAME and return its 'struct directory'. */ 417 447 418 448 static struct directory * 419 449 find_directory (const char *name) 420 450 { 421 const char *p;422 451 struct directory *dir; 423 452 struct directory **dir_slot; 424 453 struct directory dir_key; 425 int r;426 #ifdef WINDOWS32427 char* w32_path;428 char fs_label[BUFSIZ];429 char fs_type[BUFSIZ];430 unsigned long fs_serno;431 unsigned long fs_flags;432 unsigned long fs_len;433 #endif434 #ifdef VMS435 if ((*name == '.') && (*(name+1) == 0))436 name = "[]";437 else438 name = vmsify (name,1);439 #endif440 454 441 455 dir_key.name = name; … … 445 459 if (HASH_VACANT (dir)) 446 460 { 461 /* The directory was not found. Create a new entry for it. */ 462 const char *p = name + strlen (name); 447 463 struct stat st; 448 449 /* The directory was not found. Create a new entry for it. */ 450 451 p = name + strlen (name); 464 int r; 465 452 466 dir = xmalloc (sizeof (struct directory)); 453 467 #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) 454 dir->name = strcache_add_len (downcase(name), p - name); 468 /* Todo: Why is this only needed on VMS? */ 469 { 470 char *lname = downcase_inplace (xstrdup (name)); 471 dir->name = strcache_add_len (lname, p - name); 472 free (lname); 473 } 455 474 #else 456 475 dir->name = strcache_add_len (name, p - name); … … 458 477 hash_insert_at (&directories, dir, dir_slot); 459 478 /* The directory is not in the name hash table. 460 Find its device and inode numbers, and look it up by them. */ 461 462 #ifdef VMS 463 r = vmsstat_dir (name, &st); 464 #elif defined(WINDOWS32) 479 Find its device and inode numbers, and look it up by them. */ 480 481 #if defined(WINDOWS32) 465 482 { 466 483 char tem[MAXPATHLEN], *tstart, *tend; … … 485 502 if (r < 0) 486 503 { 487 /* Couldn't stat the directory. Mark this by488 setting the `contents' member to a nil pointer. */489 dir->contents = 0;490 }504 /* Couldn't stat the directory. Mark this by 505 setting the 'contents' member to a nil pointer. */ 506 dir->contents = 0; 507 } 491 508 else 492 { 493 /* Search the contents hash table; device and inode are the key. */ 494 495 struct directory_contents *dc; 496 struct directory_contents **dc_slot; 497 struct directory_contents dc_key; 498 499 dc_key.dev = st.st_dev; 500 #ifdef WINDOWS32 501 dc_key.path_key = w32_path = w32ify (name, 1); 502 dc_key.ctime = st.st_ctime; 503 #else 504 # ifdef VMS 505 dc_key.ino[0] = st.st_ino[0]; 506 dc_key.ino[1] = st.st_ino[1]; 507 dc_key.ino[2] = st.st_ino[2]; 509 { 510 /* Search the contents hash table; device and inode are the key. */ 511 512 #ifdef WINDOWS32 513 char *w32_path; 514 #endif 515 struct directory_contents *dc; 516 struct directory_contents **dc_slot; 517 struct directory_contents dc_key; 518 519 dc_key.dev = st.st_dev; 520 #ifdef WINDOWS32 521 dc_key.path_key = w32_path = w32ify (name, 1); 522 dc_key.ctime = st.st_ctime; 523 #else 524 # ifdef VMS_INO_T 525 dc_key.ino[0] = st.st_ino[0]; 526 dc_key.ino[1] = st.st_ino[1]; 527 dc_key.ino[2] = st.st_ino[2]; 508 528 # else 509 dc_key.ino = st.st_ino;529 dc_key.ino = st.st_ino; 510 530 # endif 511 531 #endif 512 dc_slot = (struct directory_contents **) hash_find_slot (&directory_contents, &dc_key); 513 dc = *dc_slot; 514 515 if (HASH_VACANT (dc)) 516 { 517 /* Nope; this really is a directory we haven't seen before. */ 518 519 dc = (struct directory_contents *) 520 xmalloc (sizeof (struct directory_contents)); 521 522 /* Enter it in the contents hash table. */ 523 dc->dev = st.st_dev; 532 dc_slot = (struct directory_contents **) hash_find_slot (&directory_contents, &dc_key); 533 dc = *dc_slot; 534 535 if (HASH_VACANT (dc)) 536 { 537 /* Nope; this really is a directory we haven't seen before. */ 538 #ifdef WINDOWS32 539 char fs_label[BUFSIZ]; 540 char fs_type[BUFSIZ]; 541 unsigned long fs_serno; 542 unsigned long fs_flags; 543 unsigned long fs_len; 544 #endif 545 dc = (struct directory_contents *) 546 xmalloc (sizeof (struct directory_contents)); 547 548 /* Enter it in the contents hash table. */ 549 dc->dev = st.st_dev; 524 550 #ifdef WINDOWS32 525 551 dc->path_key = xstrdup (w32_path); 526 dc->ctime = st.st_ctime;552 dc->ctime = st.st_ctime; 527 553 dc->mtime = st.st_mtime; 528 554 529 /* 530 * NTFS is the only WINDOWS32 filesystem that bumps mtime 531 * on a directory when files are added/deleted from 532 * a directory. 533 */ 555 /* NTFS is the only WINDOWS32 filesystem that bumps mtime on a 556 directory when files are added/deleted from a directory. */ 534 557 w32_path[3] = '\0'; 535 if (GetVolumeInformation(w32_path, 536 fs_label, sizeof (fs_label), 537 &fs_serno, &fs_len, 538 &fs_flags, fs_type, sizeof (fs_type)) == FALSE) 558 if (GetVolumeInformation (w32_path, fs_label, sizeof (fs_label), 559 &fs_serno, &fs_len, &fs_flags, fs_type, 560 sizeof (fs_type)) == FALSE) 539 561 dc->fs_flags = FS_UNKNOWN; 540 else if (!strcmp (fs_type, "FAT"))562 else if (!strcmp (fs_type, "FAT")) 541 563 dc->fs_flags = FS_FAT; 542 else if (!strcmp (fs_type, "NTFS"))564 else if (!strcmp (fs_type, "NTFS")) 543 565 dc->fs_flags = FS_NTFS; 544 566 else 545 567 dc->fs_flags = FS_UNKNOWN; 546 568 #else 547 # ifdef VMS 548 dc->ino[0] = st.st_ino[0];549 dc->ino[1] = st.st_ino[1];550 dc->ino[2] = st.st_ino[2];569 # ifdef VMS_INO_T 570 dc->ino[0] = st.st_ino[0]; 571 dc->ino[1] = st.st_ino[1]; 572 dc->ino[2] = st.st_ino[2]; 551 573 # else 552 dc->ino = st.st_ino;574 dc->ino = st.st_ino; 553 575 # endif 554 576 #endif /* WINDOWS32 */ 555 hash_insert_at (&directory_contents, dc, dc_slot);556 ENULLLOOP (dc->dirstream, opendir (name));557 if (dc->dirstream == 0)577 hash_insert_at (&directory_contents, dc, dc_slot); 578 ENULLLOOP (dc->dirstream, opendir (name)); 579 if (dc->dirstream == 0) 558 580 /* Couldn't open the directory. Mark this by setting the 559 `files' member to a nil pointer. */581 'files' member to a nil pointer. */ 560 582 dc->dirfiles.ht_vec = 0; 561 else562 {563 hash_init (&dc->dirfiles, DIRFILE_BUCKETS,564 dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);565 /* Keep track of how many directories are open. */566 ++open_directories;567 if (open_directories == MAX_OPEN_DIRECTORIES)568 /* We have too many directories open already.569 Read the entire directory and then close it. */570 dir_contents_file_exists_p (dc, 0);571 }572 }573 574 /* Point the name-hashed entry for DIR at its contents data. */575 dir->contents = dc;576 }583 else 584 { 585 hash_init (&dc->dirfiles, DIRFILE_BUCKETS, 586 dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp); 587 /* Keep track of how many directories are open. */ 588 ++open_directories; 589 if (open_directories == MAX_OPEN_DIRECTORIES) 590 /* We have too many directories open already. 591 Read the entire directory and then close it. */ 592 dir_contents_file_exists_p (dc, 0); 593 } 594 } 595 596 /* Point the name-hashed entry for DIR at its contents data. */ 597 dir->contents = dc; 598 } 577 599 } 578 600 … … 588 610 const char *filename) 589 611 { 590 unsigned int hash;591 612 struct dirfile *df; 592 613 struct dirent *d; … … 612 633 _fnlwr (filename); /* lower case for FAT drives */ 613 634 #endif 614 615 #ifdef VMS616 filename = vmsify (filename,0);617 #endif618 619 hash = 0;620 635 if (filename != 0) 621 636 { … … 623 638 624 639 if (*filename == '\0') 625 {626 /* Checking if the directory exists. */627 return 1;628 }640 { 641 /* Checking if the directory exists. */ 642 return 1; 643 } 629 644 dirfile_key.name = filename; 630 645 dirfile_key.length = strlen (filename); … … 646 661 */ 647 662 if (dir->path_key) 648 {663 { 649 664 if ((dir->fs_flags & FS_FAT) != 0) 650 {651 dir->mtime = time ((time_t *) 0);652 rehash = 1;653 }654 else if (stat (dir->path_key, &st) == 0 && st.st_mtime > dir->mtime)655 {656 /* reset date stamp to show most recent re-process. */657 dir->mtime = st.st_mtime;658 rehash = 1;659 }665 { 666 dir->mtime = time ((time_t *) 0); 667 rehash = 1; 668 } 669 else if (stat (dir->path_key, &st) == 0 && st.st_mtime > dir->mtime) 670 { 671 /* reset date stamp to show most recent re-process. */ 672 dir->mtime = st.st_mtime; 673 rehash = 1; 674 } 660 675 661 676 /* If it has been already read in, all done. */ 662 if (!rehash)663 return 0;677 if (!rehash) 678 return 0; 664 679 665 680 /* make sure directory can still be opened; if not return. */ … … 667 682 if (!dir->dirstream) 668 683 return 0; 669 }684 } 670 685 else 671 686 #endif 672 /* The directory has been all read in. */673 return 0;687 /* The directory has been all read in. */ 688 return 0; 674 689 } 675 690 … … 685 700 { 686 701 if (errno) 687 fatal (NILF, "INTERNAL: readdir: %s\n", strerror (errno));702 pfatal_with_name ("INTERNAL: readdir"); 688 703 break; 689 704 } 690 705 691 706 #if defined(VMS) && defined(HAVE_DIRENT_H) 692 /* In VMS we get file versions too, which have to be stripped off */ 707 /* In VMS we get file versions too, which have to be stripped off. 708 Some versions of VMS return versions on Unix files even when 709 the feature option to strip them is set. */ 693 710 { 694 711 char *p = strrchr (d->d_name, ';'); … … 698 715 #endif 699 716 if (!REAL_DIR_ENTRY (d)) 700 continue;717 continue; 701 718 702 719 len = NAMLEN (d); … … 711 728 if (! rehash || HASH_VACANT (*dirfile_slot)) 712 729 #endif 713 {714 df = xmalloc (sizeof (struct dirfile));730 { 731 df = xmalloc (sizeof (struct dirfile)); 715 732 #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) 716 df->name = strcache_add_len (downcase(d->d_name), len); 717 #else 718 df->name = strcache_add_len (d->d_name, len); 719 #endif 720 df->length = len; 721 df->impossible = 0; 722 hash_insert_at (&dir->dirfiles, df, dirfile_slot); 723 } 733 /* TODO: Why is this only needed on VMS? */ 734 df->name = strcache_add_len (downcase_inplace (d->d_name), len); 735 #else 736 df->name = strcache_add_len (d->d_name, len); 737 #endif 738 df->length = len; 739 df->impossible = 0; 740 hash_insert_at (&dir->dirfiles, df, dirfile_slot); 741 } 724 742 /* Check if the name matches the one we're searching for. */ 725 743 if (filename != 0 && patheq (d->d_name, filename)) … … 745 763 dir_file_exists_p (const char *dirname, const char *filename) 746 764 { 765 #ifdef VMS 766 if ((filename != NULL) && (dirname != NULL)) 767 { 768 int want_vmsify; 769 want_vmsify = (strpbrk (dirname, ":<[") != NULL); 770 if (want_vmsify) 771 filename = vmsify (filename, 0); 772 } 773 #endif 747 774 return dir_contents_file_exists_p (find_directory (dirname)->contents, 748 filename);775 filename); 749 776 } 750 777 … … 759 786 const char *slash; 760 787 761 #ifndef NO_ARCHIVES788 #ifndef NO_ARCHIVES 762 789 if (ar_name (name)) 763 790 return ar_member_date (name) != (time_t) -1; 764 791 #endif 765 792 793 dirend = strrchr (name, '/'); 766 794 #ifdef VMS 767 dirend = strrchr (name, ']');768 795 if (dirend == 0) 769 dirend = strrchr (name, ':'); 796 { 797 dirend = strrchr (name, ']'); 798 dirend == NULL ? dirend : dirend++; 799 } 770 800 if (dirend == 0) 771 return dir_file_exists_p ("[]", name); 772 #else /* !VMS */ 773 dirend = strrchr (name, '/'); 801 { 802 dirend = strrchr (name, '>'); 803 dirend == NULL ? dirend : dirend++; 804 } 805 if (dirend == 0) 806 { 807 dirend = strrchr (name, ':'); 808 dirend == NULL ? dirend : dirend++; 809 } 810 #endif /* VMS */ 774 811 #ifdef HAVE_DOS_PATHS 775 812 /* Forward and backslashes might be mixed. We need the rightmost one. */ 776 813 { 777 const char *bslash = strrchr (name, '\\');814 const char *bslash = strrchr (name, '\\'); 778 815 if (!dirend || bslash > dirend) 779 816 dirend = bslash; … … 786 823 #ifndef _AMIGA 787 824 return dir_file_exists_p (".", name); 788 #else /* ! VMS && !AMIGA */825 #else /* !AMIGA */ 789 826 return dir_file_exists_p ("", name); 790 827 #endif /* AMIGA */ 791 #endif /* VMS */792 828 793 829 slash = dirend; … … 800 836 /* d:/ and d: are *very* different... */ 801 837 if (dirend < name + 3 && name[1] == ':' && 802 (*dirend == '/' || *dirend == '\\' || *dirend == ':'))803 dirend++;838 (*dirend == '/' || *dirend == '\\' || *dirend == ':')) 839 dirend++; 804 840 #endif 805 841 p = alloca (dirend - name + 1); … … 808 844 dirname = p; 809 845 } 810 return dir_file_exists_p (dirname, slash + 1); 811 } 812 813 814 /* Mark FILENAME as `impossible' for `file_impossible_p'. 846 #ifdef VMS 847 if (*slash == '/') 848 slash++; 849 #else 850 slash++; 851 #endif 852 return dir_file_exists_p (dirname, slash); 853 } 854 855 856 /* Mark FILENAME as 'impossible' for 'file_impossible_p'. 815 857 This means an attempt has been made to search for FILENAME 816 858 as an intermediate file, and it has failed. */ … … 824 866 struct dirfile *new; 825 867 868 dirend = strrchr (p, '/'); 826 869 #ifdef VMS 827 dirend = strrchr (p, ']'); 828 if (dirend == 0) 829 dirend = strrchr (p, ':'); 830 dirend++; 831 if (dirend == (char *)1) 832 dir = find_directory ("[]"); 833 #else 834 dirend = strrchr (p, '/'); 835 # ifdef HAVE_DOS_PATHS 870 if (dirend == NULL) 871 { 872 dirend = strrchr (p, ']'); 873 dirend == NULL ? dirend : dirend++; 874 } 875 if (dirend == NULL) 876 { 877 dirend = strrchr (p, '>'); 878 dirend == NULL ? dirend : dirend++; 879 } 880 if (dirend == NULL) 881 { 882 dirend = strrchr (p, ':'); 883 dirend == NULL ? dirend : dirend++; 884 } 885 #endif 886 #ifdef HAVE_DOS_PATHS 836 887 /* Forward and backslashes might be mixed. We need the rightmost one. */ 837 888 { 838 const char *bslash = strrchr (p, '\\');889 const char *bslash = strrchr (p, '\\'); 839 890 if (!dirend || bslash > dirend) 840 891 dirend = bslash; … … 843 894 dirend = p + 1; 844 895 } 845 # endif /* HAVE_DOS_PATHS */896 #endif /* HAVE_DOS_PATHS */ 846 897 if (dirend == 0) 847 # ifdef _AMIGA898 #ifdef _AMIGA 848 899 dir = find_directory (""); 849 # else /* !VMS &&!AMIGA */900 #else /* !AMIGA */ 850 901 dir = find_directory ("."); 851 # endif /* AMIGA */ 852 #endif /* VMS */ 902 #endif /* AMIGA */ 853 903 else 854 904 { … … 856 906 const char *slash = dirend; 857 907 if (dirend == p) 858 dirname = "/";908 dirname = "/"; 859 909 else 860 {910 { 861 911 char *cp; 862 912 #ifdef HAVE_DOS_PATHS 863 /* d:/ and d: are *very* different... */864 if (dirend < p + 3 && p[1] == ':' &&865 (*dirend == '/' || *dirend == '\\' || *dirend == ':'))866 dirend++;867 #endif 868 cp = alloca (dirend - p + 1);869 memcpy (cp, p, dirend - p);870 cp[dirend - p] = '\0';913 /* d:/ and d: are *very* different... */ 914 if (dirend < p + 3 && p[1] == ':' && 915 (*dirend == '/' || *dirend == '\\' || *dirend == ':')) 916 dirend++; 917 #endif 918 cp = alloca (dirend - p + 1); 919 memcpy (cp, p, dirend - p); 920 cp[dirend - p] = '\0'; 871 921 dirname = cp; 872 }922 } 873 923 dir = find_directory (dirname); 924 #ifdef VMS 925 if (*slash == '/') 926 filename = p = slash + 1; 927 else 928 filename = p = slash; 929 #else 874 930 filename = p = slash + 1; 931 #endif 875 932 } 876 933 … … 883 940 { 884 941 hash_init (&dir->contents->dirfiles, DIRFILE_BUCKETS, 885 dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);942 dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp); 886 943 } 887 944 … … 891 948 new->length = strlen (filename); 892 949 #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) 893 new->name = strcache_add_len (downcase(filename), new->length); 950 /* todo: Why is this only needed on VMS? */ 951 new->name = strcache_add_len (downcase (filename), new->length); 894 952 #else 895 953 new->name = strcache_add_len (filename, new->length); … … 906 964 { 907 965 const char *dirend; 908 const char *p = filename;909 966 struct directory_contents *dir; 910 967 struct dirfile *dirfile; 911 968 struct dirfile dirfile_key; 912 913 969 #ifdef VMS 914 dirend = strrchr (filename, ']'); 915 if (dirend == 0) 916 dir = find_directory ("[]")->contents; 917 #else 970 int want_vmsify = 0; 971 #endif 972 918 973 dirend = strrchr (filename, '/'); 974 #ifdef VMS 975 if (dirend == NULL) 976 { 977 want_vmsify = (strpbrk (filename, "]>:^") != NULL); 978 dirend = strrchr (filename, ']'); 979 } 980 if (dirend == NULL && want_vmsify) 981 dirend = strrchr (filename, '>'); 982 if (dirend == NULL && want_vmsify) 983 dirend = strrchr (filename, ':'); 984 #endif 919 985 #ifdef HAVE_DOS_PATHS 920 986 /* Forward and backslashes might be mixed. We need the rightmost one. */ 921 987 { 922 const char *bslash = strrchr (filename, '\\');988 const char *bslash = strrchr (filename, '\\'); 923 989 if (!dirend || bslash > dirend) 924 990 dirend = bslash; … … 931 997 #ifdef _AMIGA 932 998 dir = find_directory ("")->contents; 933 #else /* ! VMS && !AMIGA */999 #else /* !AMIGA */ 934 1000 dir = find_directory (".")->contents; 935 1001 #endif /* AMIGA */ 936 #endif /* VMS */937 1002 else 938 1003 { … … 940 1005 const char *slash = dirend; 941 1006 if (dirend == filename) 942 dirname = "/";1007 dirname = "/"; 943 1008 else 944 {1009 { 945 1010 char *cp; 946 1011 #ifdef HAVE_DOS_PATHS 947 /* d:/ and d: are *very* different... */948 if (dirend < filename + 3 && filename[1] == ':' &&949 (*dirend == '/' || *dirend == '\\' || *dirend == ':'))950 dirend++;951 #endif 952 cp = alloca (dirend - filename + 1);953 memcpy (cp, p, dirend - p);954 cp[dirend - p] = '\0';1012 /* d:/ and d: are *very* different... */ 1013 if (dirend < filename + 3 && filename[1] == ':' && 1014 (*dirend == '/' || *dirend == '\\' || *dirend == ':')) 1015 dirend++; 1016 #endif 1017 cp = alloca (dirend - filename + 1); 1018 memcpy (cp, filename, dirend - filename); 1019 cp[dirend - filename] = '\0'; 955 1020 dirname = cp; 956 }1021 } 957 1022 dir = find_directory (dirname)->contents; 958 p = filename = slash + 1; 1023 #ifdef VMS 1024 if (*slash == '/') 1025 filename = slash + 1; 1026 else 1027 filename = slash; 1028 #else 1029 filename = slash + 1; 1030 #endif 959 1031 } 960 1032 … … 964 1036 965 1037 #ifdef __MSDOS__ 966 filename = dosify ( p);1038 filename = dosify (filename); 967 1039 #endif 968 1040 #ifdef HAVE_CASE_INSENSITIVE_FS 969 filename = downcase ( p);1041 filename = downcase (filename); 970 1042 #endif 971 1043 #ifdef VMS 972 filename = vmsify (p, 1); 1044 if (want_vmsify) 1045 filename = vmsify (filename, 1); 973 1046 #endif 974 1047 … … 1013 1086 struct directory *dir = *dir_slot; 1014 1087 if (! HASH_VACANT (dir)) 1015 { 1016 if (dir->contents == 0) 1017 printf (_("# %s: could not be stat'd.\n"), dir->name); 1018 else if (dir->contents->dirfiles.ht_vec == 0) 1019 { 1020 #ifdef WINDOWS32 1021 printf (_("# %s (key %s, mtime %d): could not be opened.\n"), 1022 dir->name, dir->contents->path_key,dir->contents->mtime); 1088 { 1089 if (dir->contents == 0) 1090 printf (_("# %s: could not be stat'd.\n"), dir->name); 1091 else if (dir->contents->dirfiles.ht_vec == 0) 1092 { 1093 #ifdef WINDOWS32 1094 printf (_("# %s (key %s, mtime %I64u): could not be opened.\n"), 1095 dir->name, dir->contents->path_key, 1096 (unsigned long long)dir->contents->mtime); 1023 1097 #else /* WINDOWS32 */ 1024 #ifdef VMS 1025 printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"),1026 dir->name, dir->contents->dev,1027 dir->contents->ino[0], dir->contents->ino[1],1028 dir->contents->ino[2]);1029 #else 1030 printf (_("# %s (device %ld, inode %ld): could not be opened.\n"),1031 dir->name, (long int) dir->contents->dev,1032 (long int) dir->contents->ino);1098 #ifdef VMS_INO_T 1099 printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"), 1100 dir->name, dir->contents->dev, 1101 dir->contents->ino[0], dir->contents->ino[1], 1102 dir->contents->ino[2]); 1103 #else 1104 printf (_("# %s (device %ld, inode %ld): could not be opened.\n"), 1105 dir->name, (long int) dir->contents->dev, 1106 (long int) dir->contents->ino); 1033 1107 #endif 1034 1108 #endif /* WINDOWS32 */ 1035 } 1036 else 1037 { 1038 unsigned int f = 0; 1039 unsigned int im = 0; 1040 struct dirfile **files_slot; 1041 struct dirfile **files_end; 1042 1043 files_slot = (struct dirfile **) dir->contents->dirfiles.ht_vec; 1044 files_end = files_slot + dir->contents->dirfiles.ht_size; 1045 for ( ; files_slot < files_end; files_slot++) 1046 { 1047 struct dirfile *df = *files_slot; 1048 if (! HASH_VACANT (df)) 1049 { 1050 if (df->impossible) 1051 ++im; 1052 else 1053 ++f; 1054 } 1055 } 1056 #ifdef WINDOWS32 1057 printf (_("# %s (key %s, mtime %d): "), 1058 dir->name, dir->contents->path_key, dir->contents->mtime); 1109 } 1110 else 1111 { 1112 unsigned int f = 0; 1113 unsigned int im = 0; 1114 struct dirfile **files_slot; 1115 struct dirfile **files_end; 1116 1117 files_slot = (struct dirfile **) dir->contents->dirfiles.ht_vec; 1118 files_end = files_slot + dir->contents->dirfiles.ht_size; 1119 for ( ; files_slot < files_end; files_slot++) 1120 { 1121 struct dirfile *df = *files_slot; 1122 if (! HASH_VACANT (df)) 1123 { 1124 if (df->impossible) 1125 ++im; 1126 else 1127 ++f; 1128 } 1129 } 1130 #ifdef WINDOWS32 1131 printf (_("# %s (key %s, mtime %I64u): "), 1132 dir->name, dir->contents->path_key, 1133 (unsigned long long)dir->contents->mtime); 1059 1134 #else /* WINDOWS32 */ 1060 #ifdef VMS 1061 printf (_("# %s (device %d, inode [%d,%d,%d]): "),1062 dir->name, dir->contents->dev,1063 dir->contents->ino[0], dir->contents->ino[1],1064 dir->contents->ino[2]);1065 #else 1066 printf (_("# %s (device %ld, inode %ld): "),1067 dir->name,1068 (long)dir->contents->dev, (long)dir->contents->ino);1135 #ifdef VMS_INO_T 1136 printf (_("# %s (device %d, inode [%d,%d,%d]): "), 1137 dir->name, dir->contents->dev, 1138 dir->contents->ino[0], dir->contents->ino[1], 1139 dir->contents->ino[2]); 1140 #else 1141 printf (_("# %s (device %ld, inode %ld): "), 1142 dir->name, 1143 (long)dir->contents->dev, (long)dir->contents->ino); 1069 1144 #endif 1070 1145 #endif /* WINDOWS32 */ 1071 if (f == 0)1072 fputs (_("No"), stdout);1073 else1074 printf ("%u", f);1075 fputs (_(" files, "), stdout);1076 if (im == 0)1077 fputs (_("no"), stdout);1078 else1079 printf ("%u", im);1080 fputs (_(" impossibilities"), stdout);1081 if (dir->contents->dirstream == 0)1082 puts (".");1083 else1084 puts (_(" so far."));1085 files += f;1086 impossible += im;1087 }1088 }1146 if (f == 0) 1147 fputs (_("No"), stdout); 1148 else 1149 printf ("%u", f); 1150 fputs (_(" files, "), stdout); 1151 if (im == 0) 1152 fputs (_("no"), stdout); 1153 else 1154 printf ("%u", im); 1155 fputs (_(" impossibilities"), stdout); 1156 if (dir->contents->dirstream == 0) 1157 puts ("."); 1158 else 1159 puts (_(" so far.")); 1160 files += f; 1161 impossible += im; 1162 } 1163 } 1089 1164 } 1090 1165 … … 1105 1180 /* Hooks for globbing. */ 1106 1181 1107 #include <glob.h>1108 1109 1182 /* Structure describing state of iterating through a directory hash table. */ 1110 1183 … … 1156 1229 struct dirfile *df = *ds->dirfile_slot++; 1157 1230 if (! HASH_VACANT (df) && !df->impossible) 1158 {1159 /* The glob interface wants a `struct dirent', so mock one up. */1160 struct dirent *d;1161 unsigned int len = df->length + 1;1231 { 1232 /* The glob interface wants a 'struct dirent', so mock one up. */ 1233 struct dirent *d; 1234 unsigned int len = df->length + 1; 1162 1235 unsigned int sz = sizeof (*d) - sizeof (d->d_name) + len; 1163 if (sz > bufsz)1164 {1165 bufsz *= 2;1166 if (sz > bufsz)1167 bufsz = sz;1168 buf = xrealloc (buf, bufsz);1169 }1170 d = (struct dirent *) buf;1236 if (sz > bufsz) 1237 { 1238 bufsz *= 2; 1239 if (sz > bufsz) 1240 bufsz = sz; 1241 buf = xrealloc (buf, bufsz); 1242 } 1243 d = (struct dirent *) buf; 1171 1244 #ifdef __MINGW32__ 1172 1245 # if __MINGW32_MAJOR_VERSION < 3 || (__MINGW32_MAJOR_VERSION == 3 && \ 1173 __MINGW32_MINOR_VERSION == 0)1174 d->d_name = xmalloc(len);1246 __MINGW32_MINOR_VERSION == 0) 1247 d->d_name = xmalloc (len); 1175 1248 # endif 1176 1249 #endif 1177 FAKE_DIR_ENTRY (d);1250 FAKE_DIR_ENTRY (d); 1178 1251 #ifdef _DIRENT_HAVE_D_NAMLEN 1179 d->d_namlen = len - 1;1252 d->d_namlen = len - 1; 1180 1253 #endif 1181 1254 #ifdef _DIRENT_HAVE_D_TYPE 1182 d->d_type = DT_UNKNOWN;1183 #endif 1184 memcpy (d->d_name, df->name, len);1185 return d;1186 }1255 d->d_type = DT_UNKNOWN; 1256 #endif 1257 memcpy (d->d_name, df->name, len); 1258 return d; 1259 } 1187 1260 } 1188 1261 1189 1262 return 0; 1190 }1191 1192 static void1193 ansi_free (void *p)1194 {1195 if (p)1196 free(p);1197 1263 } 1198 1264 … … 1200 1266 * macro for stat64(). If stat is a macro, make a local wrapper function to 1201 1267 * invoke it. 1268 * 1269 * On MS-Windows, stat() "succeeds" for foo/bar/. where foo/bar is a 1270 * regular file; fix that here. 1202 1271 */ 1203 #if ndef stat1272 #if !defined(stat) && !defined(WINDOWS32) || defined(VMS) 1204 1273 # ifndef VMS 1274 # ifndef HAVE_SYS_STAT_H 1205 1275 int stat (const char *path, struct stat *sbuf); 1276 # endif 1277 # else 1278 /* We are done with the fake stat. Go back to the real stat */ 1279 # ifdef stat 1280 # undef stat 1281 # endif 1206 1282 # endif 1207 1283 # define local_stat stat … … 1211 1287 { 1212 1288 int e; 1289 #ifdef WINDOWS32 1290 size_t plen = strlen (path); 1291 1292 /* Make sure the parent of "." exists and is a directory, not a 1293 file. This is because 'stat' on Windows normalizes the argument 1294 foo/. => foo without checking first that foo is a directory. */ 1295 if (plen > 1 && path[plen - 1] == '.' 1296 && (path[plen - 2] == '/' || path[plen - 2] == '\\')) 1297 { 1298 char parent[MAXPATHLEN]; 1299 1300 strncpy (parent, path, plen - 2); 1301 parent[plen - 2] = '\0'; 1302 if (stat (parent, buf) < 0 || !_S_ISDIR (buf->st_mode)) 1303 return -1; 1304 } 1305 #endif 1213 1306 1214 1307 EINTRLOOP (e, stat (path, buf)); … … 1222 1315 gl->gl_opendir = open_dirstream; 1223 1316 gl->gl_readdir = read_dirstream; 1224 gl->gl_closedir = ansi_free;1317 gl->gl_closedir = free; 1225 1318 gl->gl_stat = local_stat; 1226 1319 /* We don't bother setting gl_lstat, since glob never calls it. … … 1232 1325 { 1233 1326 hash_init (&directories, DIRECTORY_BUCKETS, 1234 directory_hash_1, directory_hash_2, directory_hash_cmp);1327 directory_hash_1, directory_hash_2, directory_hash_cmp); 1235 1328 hash_init (&directory_contents, DIRECTORY_BUCKETS, 1236 directory_contents_hash_1, directory_contents_hash_2,1329 directory_contents_hash_1, directory_contents_hash_2, 1237 1330 directory_contents_hash_cmp); 1238 1331 }
Note:
See TracChangeset
for help on using the changeset viewer.

