Changeset 3140 in kBuild for trunk/src/kmk/dir.c
- Timestamp:
- Mar 14, 2018 9:28:10 PM (7 years ago)
- Location:
- trunk/src/kmk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk
-
Property svn:mergeinfo
set to
/vendor/gnumake/current merged eligible
-
Property svn:mergeinfo
set to
-
trunk/src/kmk/dir.c
r3065 r3140 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) … … 97 97 98 98 /* First, transform the name part. */ 99 for (i = 0; *filename != '\0' && i < 8 && *filename != '.'; ++i)99 for (i = 0; i < 8 && ! STOP_SET (*filename, MAP_DOT|MAP_NUL); ++i) 100 100 *df++ = tolower ((unsigned char)*filename++); 101 101 102 102 /* Now skip to the next dot. */ 103 while ( *filename != '\0' && *filename != '.')103 while (! STOP_SET (*filename, MAP_DOT|MAP_NUL)) 104 104 ++filename; 105 105 if (*filename != '\0') 106 106 { 107 107 *df++ = *filename++; 108 for (i = 0; *filename != '\0' && i < 3 && *filename != '.'; ++i)109 108 for (i = 0; i < 3 && ! STOP_SET (*filename, MAP_DOT|MAP_NUL); ++i) 109 *df++ = tolower ((unsigned char)*filename++); 110 110 } 111 111 112 112 /* Look for more dots. */ 113 while ( *filename != '\0' && *filename != '.')113 while (! STOP_SET (*filename, MAP_DOT|MAP_NUL)) 114 114 ++filename; 115 115 if (*filename == '.') … … 154 154 #ifdef VMS 155 155 156 static char * 157 downcase_inplace(char *filename) 158 { 159 char *name; 160 name = filename; 161 while (*name != '\0') 162 { 163 *name = tolower ((unsigned char)*name); 164 ++name; 165 } 166 return filename; 167 } 168 169 #ifndef _USE_STD_STAT 170 /* VMS 8.2 fixed the VMS stat output to have unique st_dev and st_ino 171 when _USE_STD_STAT is used on the compile line. 172 173 Prior to _USE_STD_STAT support, the st_dev is a pointer to thread 174 static memory containing the device of the last filename looked up. 175 176 Todo: find out if the ino_t still needs to be faked on a directory. 177 */ 178 179 /* Define this if the older VMS_INO_T is needed */ 180 #define VMS_INO_T 1 181 156 182 static int 157 183 vms_hash (const char *name) 158 184 { 159 185 int h = 0; 160 int g;161 186 162 187 while (*name) 163 188 { 164 189 unsigned char uc = *name; 190 int g; 165 191 #ifdef HAVE_CASE_INSENSITIVE_FS 166 192 h = (h << 4) + (isupper (uc) ? tolower (uc) : uc); … … 171 197 g = h & 0xf0000000; 172 198 if (g) 173 174 175 176 199 { 200 h = h ^ (g >> 24); 201 h = h ^ g; 202 } 177 203 } 178 204 return h; … … 191 217 return -1; 192 218 closedir (dir); 193 s = strchr (name, ':'); 219 s = strchr (name, ':'); /* find device */ 194 220 if (s) 195 221 { … … 212 238 return 0; 213 239 } 240 241 # define stat(__path, __sbuf) vmsstat_dir (__path, __sbuf) 242 243 #endif /* _USE_STD_STAT */ 214 244 #endif /* VMS */ 215 245 … … 217 247 /* Hash table of directories. */ 218 248 219 #ifndef 249 #ifndef DIRECTORY_BUCKETS 220 250 #ifdef KMK 221 251 # define DIRECTORY_BUCKETS 4096 … … 227 257 struct directory_contents 228 258 { 229 dev_t dev; 259 dev_t dev; /* Device and inode numbers of this dir. */ 230 260 #ifdef WINDOWS32 231 261 /* Inode means nothing on WINDOWS32. Even file key information is … … 239 269 char const *path_key; /* strcache'ed */ 240 270 # endif 241 intctime;242 intmtime; /* controls check for stale directory cache */243 int 271 time_t ctime; 272 time_t mtime; /* controls check for stale directory cache */ 273 int fs_flags; /* FS_FAT, FS_NTFS, ... */ 244 274 # define FS_FAT 0x1 245 275 # define FS_NTFS 0x2 … … 249 279 # endif 250 280 #else 251 # ifdef VMS 281 # ifdef VMS_INO_T 252 282 ino_t ino[3]; 253 283 # else … … 255 285 # endif 256 286 #endif /* WINDOWS32 */ 257 struct hash_table dirfiles; 258 DIR *dirstream; 287 struct hash_table dirfiles; /* Files in this directory. */ 288 DIR *dirstream; /* Stream reading this directory. */ 259 289 }; 260 290 … … 274 304 hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) key->ctime; 275 305 #else 276 # ifdef VMS 306 # ifdef VMS_INO_T 277 307 hash = (((unsigned int) key->dev << 4) 278 279 280 308 ^ ((unsigned int) key->ino[0] 309 + (unsigned int) key->ino[1] 310 + (unsigned int) key->ino[2])); 281 311 # else 282 312 hash = ((unsigned int) key->dev << 4) ^ (unsigned int) key->ino; … … 301 331 hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ctime; 302 332 #else 303 # ifdef VMS 333 # ifdef VMS_INO_T 304 334 hash = (((unsigned int) key->dev << 4) 305 306 307 335 ^ ~((unsigned int) key->ino[0] 336 + (unsigned int) key->ino[1] 337 + (unsigned int) key->ino[2])); 308 338 # else 309 339 hash = ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ino; … … 345 375 return result; 346 376 #else 347 # ifdef VMS 377 # ifdef VMS_INO_T 348 378 result = MAKECMP(x->ino[0], y->ino[0]); 349 379 if (result) … … 375 405 struct directory 376 406 { 377 const char *name; 407 const char *name; /* Name of the directory. */ 378 408 379 409 /* The directory's contents. This data may be shared by several 380 410 entries in the hash table, which refer to the same directory 381 (identified uniquely by `dev' and `ino') under different names. */411 (identified uniquely by 'dev' and 'ino') under different names. */ 382 412 struct directory_contents *contents; 383 413 }; … … 400 430 { 401 431 return_ISTRING_COMPARE (((const struct directory *) x)->name, 402 432 ((const struct directory *) y)->name); 403 433 } 404 434 #endif /* !CONFIG_WITH_STRCACHE2 */ … … 423 453 struct dirfile 424 454 { 425 const char *name; 426 s hort length;427 short impossible; 455 const char *name; /* Name of the file. */ 456 size_t length; 457 short impossible; /* This file is impossible. */ 428 458 }; 429 459 … … 453 483 #endif /* !CONFIG_WITH_STRCACHE2 */ 454 484 455 #ifndef 485 #ifndef DIRFILE_BUCKETS 456 486 #define DIRFILE_BUCKETS 107 457 487 #endif … … 468 498 static struct directory *find_directory (const char *name); 469 499 470 /* Find the directory named NAME and return its `struct directory'. */500 /* Find the directory named NAME and return its 'struct directory'. */ 471 501 472 502 static struct directory * 473 503 find_directory (const char *name) 474 504 { 475 const char *p;476 505 struct directory *dir; 477 506 struct directory **dir_slot; 478 507 struct directory dir_key; 479 int r;480 #ifdef WINDOWS32481 char* w32_path;482 char fs_label[BUFSIZ];483 char fs_type[BUFSIZ];484 unsigned long fs_serno;485 unsigned long fs_flags;486 unsigned long fs_len;487 #endif488 #ifdef VMS489 if ((*name == '.') && (*(name+1) == 0))490 name = "[]";491 else492 name = vmsify (name,1);493 #endif494 508 495 509 #ifndef CONFIG_WITH_STRCACHE2 … … 497 511 dir_slot = (struct directory **) hash_find_slot (&directories, &dir_key); 498 512 #else 499 p = name + strlen (name);513 const char *p = name + strlen (name); 500 514 # if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) 501 515 dir_key.name = strcache_add_len (downcase(name), p - name); … … 509 523 if (HASH_VACANT (dir)) 510 524 { 525 /* The directory was not found. Create a new entry for it. */ 526 #ifndef CONFIG_WITH_STRCACHE2 527 const char *p = name + strlen (name); 528 #endif 511 529 struct stat st; 512 513 /* The directory was not found. Create a new entry for it. */ 514 515 #ifndef CONFIG_WITH_STRCACHE2 516 p = name + strlen (name); 517 #endif 530 int r; 531 518 532 #ifndef CONFIG_WITH_ALLOC_CACHES 519 533 dir = xmalloc (sizeof (struct directory)); … … 523 537 #ifndef CONFIG_WITH_STRCACHE2 524 538 #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) 525 dir->name = strcache_add_len (downcase(name), p - name); 539 /* Todo: Why is this only needed on VMS? */ 540 { 541 char *lname = downcase_inplace (xstrdup (name)); 542 dir->name = strcache_add_len (lname, p - name); 543 free (lname); 544 } 526 545 #else 527 546 dir->name = strcache_add_len (name, p - name); … … 532 551 hash_insert_at (&directories, dir, dir_slot); 533 552 /* The directory is not in the name hash table. 534 Find its device and inode numbers, and look it up by them. */ 535 536 #ifdef VMS 537 r = vmsstat_dir (name, &st); 538 #elif defined(WINDOWS32) 553 Find its device and inode numbers, and look it up by them. */ 554 555 #if defined(WINDOWS32) 539 556 { 540 557 char tem[MAXPATHLEN], *tstart, *tend; … … 559 576 if (r < 0) 560 577 { 561 562 setting the `contents' member to a nil pointer. */563 564 578 /* Couldn't stat the directory. Mark this by 579 setting the 'contents' member to a nil pointer. */ 580 dir->contents = 0; 581 } 565 582 else 566 { 567 /* Search the contents hash table; device and inode are the key. */ 568 569 struct directory_contents *dc; 570 struct directory_contents **dc_slot; 571 struct directory_contents dc_key; 572 573 dc_key.dev = st.st_dev; 583 { 584 /* Search the contents hash table; device and inode are the key. */ 585 586 #ifdef WINDOWS32 587 char *w32_path; 588 #endif 589 struct directory_contents *dc; 590 struct directory_contents **dc_slot; 591 struct directory_contents dc_key; 592 593 dc_key.dev = st.st_dev; 574 594 #ifdef WINDOWS32 575 595 # ifndef CONFIG_WITH_STRCACHE2 … … 581 601 dc_key.ctime = st.st_ctime; 582 602 #else 583 # ifdef VMS 584 585 586 603 # ifdef VMS_INO_T 604 dc_key.ino[0] = st.st_ino[0]; 605 dc_key.ino[1] = st.st_ino[1]; 606 dc_key.ino[2] = st.st_ino[2]; 587 607 # else 588 dc_key.ino = st.st_ino; 589 # endif 590 #endif 591 dc_slot = (struct directory_contents **) hash_find_slot (&directory_contents, &dc_key); 592 dc = *dc_slot; 593 594 if (HASH_VACANT (dc)) 595 { 608 dc_key.ino = st.st_ino; 609 # endif 610 #endif 611 dc_slot = (struct directory_contents **) hash_find_slot (&directory_contents, &dc_key); 612 dc = *dc_slot; 613 614 if (HASH_VACANT (dc)) 615 { 616 /* Nope; this really is a directory we haven't seen before. */ 617 #ifdef WINDOWS32 618 char fs_label[BUFSIZ]; 619 char fs_type[BUFSIZ]; 620 unsigned long fs_serno; 621 unsigned long fs_flags; 622 unsigned long fs_len; 623 #endif 596 624 #if defined(WINDOWS32) && defined(KMK) 597 625 static char s_last_volume[4]; 598 626 static int s_last_flags; 599 627 #endif 600 /* Nope; this really is a directory we haven't seen before. */601 628 602 629 #ifndef CONFIG_WITH_ALLOC_CACHES … … 608 635 #endif 609 636 610 611 637 /* Enter it in the contents hash table. */ 638 dc->dev = st.st_dev; 612 639 #ifdef WINDOWS32 613 640 # ifndef CONFIG_WITH_STRCACHE2 … … 617 644 # endif /* CONFIG_WITH_STRCACHE2 */ 618 645 619 646 dc->ctime = st.st_ctime; 620 647 dc->mtime = st.st_mtime; 621 648 # ifdef KMK … … 623 650 # endif 624 651 625 /* 626 * NTFS is the only WINDOWS32 filesystem that bumps mtime 627 * on a directory when files are added/deleted from 628 * a directory. 629 */ 652 /* NTFS is the only WINDOWS32 filesystem that bumps mtime on a 653 directory when files are added/deleted from a directory. */ 630 654 w32_path[3] = '\0'; 655 631 656 # ifdef KMK /* Need for speed: Cache the GetVolumeInformation result. */ 632 657 if ( s_last_volume[0] == w32_path[0] … … 638 663 { 639 664 # endif 640 if (GetVolumeInformation(w32_path, 641 fs_label, sizeof (fs_label), 642 &fs_serno, &fs_len, 643 &fs_flags, fs_type, sizeof (fs_type)) == FALSE) 665 if (GetVolumeInformation (w32_path, fs_label, sizeof (fs_label), 666 &fs_serno, &fs_len, &fs_flags, fs_type, 667 sizeof (fs_type)) == FALSE) 644 668 dc->fs_flags = FS_UNKNOWN; 645 else if (!strcmp (fs_type, "FAT"))669 else if (!strcmp (fs_type, "FAT")) 646 670 dc->fs_flags = FS_FAT; 647 else if (!strcmp (fs_type, "NTFS"))671 else if (!strcmp (fs_type, "NTFS")) 648 672 dc->fs_flags = FS_NTFS; 649 673 else 650 674 dc->fs_flags = FS_UNKNOWN; 651 675 # ifdef KMK 652 s_last_volume[0] = w32_path[0]; 653 s_last_volume[1] = w32_path[1]; 654 s_last_volume[2] = w32_path[2]; 655 s_last_volume[3] = w32_path[3]; 656 s_last_flags = dc->fs_flags; 657 } 658 # endif 659 #else 660 # ifdef VMS 661 dc->ino[0] = st.st_ino[0]; 662 dc->ino[1] = st.st_ino[1]; 663 dc->ino[2] = st.st_ino[2]; 676 s_last_volume[0] = w32_path[0]; 677 s_last_volume[1] = w32_path[1]; 678 s_last_volume[2] = w32_path[2]; 679 s_last_volume[3] = w32_path[3]; 680 s_last_flags = dc->fs_flags; 681 # endif 682 #else 683 # ifdef VMS_INO_T 684 dc->ino[0] = st.st_ino[0]; 685 dc->ino[1] = st.st_ino[1]; 686 dc->ino[2] = st.st_ino[2]; 664 687 # else 665 688 dc->ino = st.st_ino; 666 689 # endif 667 690 #endif /* WINDOWS32 */ 668 669 670 691 hash_insert_at (&directory_contents, dc, dc_slot); 692 ENULLLOOP (dc->dirstream, opendir (name)); 693 if (dc->dirstream == 0) 671 694 /* Couldn't open the directory. Mark this by setting the 672 `files' member to a nil pointer. */695 'files' member to a nil pointer. */ 673 696 dc->dirfiles.ht_vec = 0; 674 697 else … … 682 705 #else 683 706 # ifndef CONFIG_WITH_STRCACHE2 684 685 707 hash_init (&dc->dirfiles, DIRFILE_BUCKETS, 708 dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp); 686 709 # else /* CONFIG_WITH_STRCACHE2 */ 687 710 hash_init_strcached (&dc->dirfiles, DIRFILE_BUCKETS, … … 690 713 # endif /* CONFIG_WITH_STRCACHE2 */ 691 714 #endif 692 /* Keep track of how many directories are open. */ 693 ++open_directories; 694 if (open_directories == MAX_OPEN_DIRECTORIES) 695 /* We have too many directories open already. 696 Read the entire directory and then close it. */ 697 dir_contents_file_exists_p (dc, 0); 698 } 699 } 700 701 /* Point the name-hashed entry for DIR at its contents data. */ 702 dir->contents = dc; 703 } 715 ++open_directories; 716 if (open_directories == MAX_OPEN_DIRECTORIES) 717 /* We have too many directories open already. 718 Read the entire directory and then close it. */ 719 dir_contents_file_exists_p (dc, 0); 720 } 721 } 722 723 /* Point the name-hashed entry for DIR at its contents data. */ 724 dir->contents = dc; 725 } 704 726 } 705 727 … … 715 737 const char *filename) 716 738 { 717 /*unsigned int hash;*/718 739 struct dirfile *df; 719 740 struct dirent *d; … … 744 765 _fnlwr (filename); /* lower case for FAT drives */ 745 766 #endif 746 747 #ifdef VMS748 filename = vmsify (filename,0);749 #endif750 751 /*hash = 0;*/752 767 if (filename != 0) 753 768 { … … 755 770 756 771 if (*filename == '\0') 757 758 759 760 772 { 773 /* Checking if the directory exists. */ 774 return 1; 775 } 761 776 #ifndef CONFIG_WITH_STRCACHE2 762 777 dirfile_key.name = filename; … … 789 804 if (dir->path_key) 790 805 # endif 791 806 { 792 807 if ((dir->fs_flags & FS_FAT) != 0) 793 808 { … … 801 816 else if (stat (dir->path_key, &st) == 0 && st.st_mtime > dir->mtime) 802 817 # endif 803 804 805 806 807 818 { 819 /* reset date stamp to show most recent re-process. */ 820 dir->mtime = st.st_mtime; 821 rehash = 1; 822 } 808 823 809 824 810 825 /* If it has been already read in, all done. */ 811 812 826 if (!rehash) 827 return 0; 813 828 814 829 /* make sure directory can still be opened; if not return. */ … … 819 834 dc->last_updated = time(NULL); 820 835 # endif 821 836 } 822 837 else 823 838 #endif 824 825 839 /* The directory has been all read in. */ 840 return 0; 826 841 } 827 842 … … 857 872 /* bird: end */ 858 873 if (errno) 859 fatal (NILF, "INTERNAL: readdir(%p): %s (filename=%s)\n", (void *)dir, strerror (errno), filename);874 pfatal_with_name ("INTERNAL: readdir"); 860 875 break; 861 876 } 862 877 863 878 #if defined(VMS) && defined(HAVE_DIRENT_H) 864 /* In VMS we get file versions too, which have to be stripped off */ 879 /* In VMS we get file versions too, which have to be stripped off. 880 Some versions of VMS return versions on Unix files even when 881 the feature option to strip them is set. */ 865 882 { 866 883 char *p = strrchr (d->d_name, ';'); … … 870 887 #endif 871 888 if (!REAL_DIR_ENTRY (d)) 872 889 continue; 873 890 874 891 len = NAMLEN (d); … … 895 912 { 896 913 #ifndef CONFIG_WITH_ALLOC_CACHES 897 914 df = xmalloc (sizeof (struct dirfile)); 898 915 #else 899 916 df = alloccache_alloc (&dirfile_cache); … … 901 918 #ifndef CONFIG_WITH_STRCACHE2 902 919 #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) 903 df->name = strcache_add_len (downcase(d->d_name), len); 904 #else 905 df->name = strcache_add_len (d->d_name, len); 920 /* TODO: Why is this only needed on VMS? */ 921 df->name = strcache_add_len (downcase_inplace (d->d_name), len); 922 #else 923 df->name = strcache_add_len (d->d_name, len); 906 924 #endif 907 925 #else /* CONFIG_WITH_STRCACHE2 */ 908 926 df->name = dirfile_key.name; 909 927 #endif /* CONFIG_WITH_STRCACHE2 */ 910 911 912 913 928 df->length = len; 929 df->impossible = 0; 930 hash_insert_at (&dir->dirfiles, df, dirfile_slot); 931 } 914 932 /* Check if the name matches the one we're searching for. */ 915 933 #ifndef CONFIG_WITH_STRCACHE2 … … 947 965 dir_file_exists_p (const char *dirname, const char *filename) 948 966 { 967 #ifdef VMS 968 if ((filename != NULL) && (dirname != NULL)) 969 { 970 int want_vmsify; 971 want_vmsify = (strpbrk (dirname, ":<[") != NULL); 972 if (want_vmsify) 973 filename = vmsify (filename, 0); 974 } 975 #endif 949 976 return dir_contents_file_exists_p (find_directory (dirname)->contents, 950 977 filename); 951 978 } 952 979 … … 961 988 const char *slash; 962 989 963 #ifndef 990 #ifndef NO_ARCHIVES 964 991 if (ar_name (name)) 965 992 return ar_member_date (name) != (time_t) -1; 966 993 #endif 967 994 995 dirend = strrchr (name, '/'); 968 996 #ifdef VMS 969 dirend = strrchr (name, ']');970 997 if (dirend == 0) 971 dirend = strrchr (name, ':'); 998 { 999 dirend = strrchr (name, ']'); 1000 dirend == NULL ? dirend : dirend++; 1001 } 972 1002 if (dirend == 0) 973 return dir_file_exists_p ("[]", name); 974 #else /* !VMS */ 975 dirend = strrchr (name, '/'); 1003 { 1004 dirend = strrchr (name, '>'); 1005 dirend == NULL ? dirend : dirend++; 1006 } 1007 if (dirend == 0) 1008 { 1009 dirend = strrchr (name, ':'); 1010 dirend == NULL ? dirend : dirend++; 1011 } 1012 #endif /* VMS */ 976 1013 #ifdef HAVE_DOS_PATHS 977 1014 /* Forward and backslashes might be mixed. We need the rightmost one. */ 978 1015 { 979 const char *bslash = strrchr (name, '\\');1016 const char *bslash = strrchr (name, '\\'); 980 1017 if (!dirend || bslash > dirend) 981 1018 dirend = bslash; … … 988 1025 #ifndef _AMIGA 989 1026 return dir_file_exists_p (".", name); 990 #else /* ! VMS && !AMIGA */1027 #else /* !AMIGA */ 991 1028 return dir_file_exists_p ("", name); 992 1029 #endif /* AMIGA */ 993 #endif /* VMS */994 1030 995 1031 slash = dirend; … … 1002 1038 /* d:/ and d: are *very* different... */ 1003 1039 if (dirend < name + 3 && name[1] == ':' && 1004 1005 1040 (*dirend == '/' || *dirend == '\\' || *dirend == ':')) 1041 dirend++; 1006 1042 #endif 1007 1043 p = alloca (dirend - name + 1); … … 1010 1046 dirname = p; 1011 1047 } 1012 return dir_file_exists_p (dirname, slash + 1); 1013 } 1014 1015 1016 /* Mark FILENAME as `impossible' for `file_impossible_p'. 1048 #ifdef VMS 1049 if (*slash == '/') 1050 slash++; 1051 #else 1052 slash++; 1053 #endif 1054 return dir_file_exists_p (dirname, slash); 1055 } 1056 1057 1058 /* Mark FILENAME as 'impossible' for 'file_impossible_p'. 1017 1059 This means an attempt has been made to search for FILENAME 1018 1060 as an intermediate file, and it has failed. */ … … 1026 1068 struct dirfile *new; 1027 1069 1070 dirend = strrchr (p, '/'); 1028 1071 #ifdef VMS 1029 dirend = strrchr (p, ']'); 1030 if (dirend == 0) 1031 dirend = strrchr (p, ':'); 1032 dirend++; 1033 if (dirend == (char *)1) 1034 dir = find_directory ("[]"); 1035 #else 1036 dirend = strrchr (p, '/'); 1037 # ifdef HAVE_DOS_PATHS 1072 if (dirend == NULL) 1073 { 1074 dirend = strrchr (p, ']'); 1075 dirend == NULL ? dirend : dirend++; 1076 } 1077 if (dirend == NULL) 1078 { 1079 dirend = strrchr (p, '>'); 1080 dirend == NULL ? dirend : dirend++; 1081 } 1082 if (dirend == NULL) 1083 { 1084 dirend = strrchr (p, ':'); 1085 dirend == NULL ? dirend : dirend++; 1086 } 1087 #endif 1088 #ifdef HAVE_DOS_PATHS 1038 1089 /* Forward and backslashes might be mixed. We need the rightmost one. */ 1039 1090 { 1040 const char *bslash = strrchr (p, '\\');1091 const char *bslash = strrchr (p, '\\'); 1041 1092 if (!dirend || bslash > dirend) 1042 1093 dirend = bslash; … … 1045 1096 dirend = p + 1; 1046 1097 } 1047 # 1098 #endif /* HAVE_DOS_PATHS */ 1048 1099 if (dirend == 0) 1049 # 1100 #ifdef _AMIGA 1050 1101 dir = find_directory (""); 1051 # else /* !VMS &&!AMIGA */1102 #else /* !AMIGA */ 1052 1103 dir = find_directory ("."); 1053 # endif /* AMIGA */ 1054 #endif /* VMS */ 1104 #endif /* AMIGA */ 1055 1105 else 1056 1106 { … … 1058 1108 const char *slash = dirend; 1059 1109 if (dirend == p) 1060 1110 dirname = "/"; 1061 1111 else 1062 1112 { 1063 1113 char *cp; 1064 1114 #ifdef HAVE_DOS_PATHS 1065 1066 1067 1068 1069 #endif 1070 1071 1072 1115 /* d:/ and d: are *very* different... */ 1116 if (dirend < p + 3 && p[1] == ':' && 1117 (*dirend == '/' || *dirend == '\\' || *dirend == ':')) 1118 dirend++; 1119 #endif 1120 cp = alloca (dirend - p + 1); 1121 memcpy (cp, p, dirend - p); 1122 cp[dirend - p] = '\0'; 1073 1123 dirname = cp; 1074 1124 } 1075 1125 dir = find_directory (dirname); 1126 #ifdef VMS 1127 if (*slash == '/') 1128 filename = p = slash + 1; 1129 else 1130 filename = p = slash; 1131 #else 1076 1132 filename = p = slash + 1; 1133 #endif 1077 1134 } 1078 1135 … … 1090 1147 #ifndef CONFIG_WITH_STRCACHE2 1091 1148 hash_init (&dir->contents->dirfiles, DIRFILE_BUCKETS, 1092 1149 dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp); 1093 1150 #else /* CONFIG_WITH_STRCACHE2 */ 1094 1151 hash_init_strcached (&dir->contents->dirfiles, DIRFILE_BUCKETS, … … 1106 1163 new->length = strlen (filename); 1107 1164 #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) 1108 new->name = strcache_add_len (downcase(filename), new->length); 1165 /* todo: Why is this only needed on VMS? */ 1166 new->name = strcache_add_len (downcase (filename), new->length); 1109 1167 #else 1110 1168 new->name = strcache_add_len (filename, new->length); … … 1125 1183 { 1126 1184 const char *dirend; 1127 const char *p = filename;1128 1185 struct directory_contents *dir; 1129 1186 struct dirfile *dirfile; 1130 1187 struct dirfile dirfile_key; 1131 1132 1188 #ifdef VMS 1133 dirend = strrchr (filename, ']'); 1134 if (dirend == 0) 1135 dir = find_directory ("[]")->contents; 1136 #else 1189 int want_vmsify = 0; 1190 #endif 1191 1137 1192 dirend = strrchr (filename, '/'); 1193 #ifdef VMS 1194 if (dirend == NULL) 1195 { 1196 want_vmsify = (strpbrk (filename, "]>:^") != NULL); 1197 dirend = strrchr (filename, ']'); 1198 } 1199 if (dirend == NULL && want_vmsify) 1200 dirend = strrchr (filename, '>'); 1201 if (dirend == NULL && want_vmsify) 1202 dirend = strrchr (filename, ':'); 1203 #endif 1138 1204 #ifdef HAVE_DOS_PATHS 1139 1205 /* Forward and backslashes might be mixed. We need the rightmost one. */ 1140 1206 { 1141 const char *bslash = strrchr (filename, '\\');1207 const char *bslash = strrchr (filename, '\\'); 1142 1208 if (!dirend || bslash > dirend) 1143 1209 dirend = bslash; … … 1150 1216 #ifdef _AMIGA 1151 1217 dir = find_directory ("")->contents; 1152 #else /* ! VMS && !AMIGA */1218 #else /* !AMIGA */ 1153 1219 dir = find_directory (".")->contents; 1154 1220 #endif /* AMIGA */ 1155 #endif /* VMS */1156 1221 else 1157 1222 { … … 1159 1224 const char *slash = dirend; 1160 1225 if (dirend == filename) 1161 1226 dirname = "/"; 1162 1227 else 1163 1228 { 1164 1229 char *cp; 1165 1230 #ifdef HAVE_DOS_PATHS 1166 1167 1168 1169 1170 #endif 1171 1172 memcpy (cp, p, dirend - p);1173 cp[dirend - p] = '\0';1231 /* d:/ and d: are *very* different... */ 1232 if (dirend < filename + 3 && filename[1] == ':' && 1233 (*dirend == '/' || *dirend == '\\' || *dirend == ':')) 1234 dirend++; 1235 #endif 1236 cp = alloca (dirend - filename + 1); 1237 memcpy (cp, filename, dirend - filename); 1238 cp[dirend - filename] = '\0'; 1174 1239 dirname = cp; 1175 1240 } 1176 1241 dir = find_directory (dirname)->contents; 1177 p = filename = slash + 1; 1242 #ifdef VMS 1243 if (*slash == '/') 1244 filename = slash + 1; 1245 else 1246 filename = slash; 1247 #else 1248 filename = slash + 1; 1249 #endif 1178 1250 } 1179 1251 … … 1183 1255 1184 1256 #ifdef __MSDOS__ 1185 filename = dosify ( p);1257 filename = dosify (filename); 1186 1258 #endif 1187 1259 #ifdef HAVE_CASE_INSENSITIVE_FS 1188 filename = downcase ( p);1260 filename = downcase (filename); 1189 1261 #endif 1190 1262 #ifdef VMS 1191 filename = vmsify (p, 1); 1263 if (want_vmsify) 1264 filename = vmsify (filename, 1); 1192 1265 #endif 1193 1266 … … 1238 1311 struct directory *dir = *dir_slot; 1239 1312 if (! HASH_VACANT (dir)) 1240 1241 1242 1243 1244 1313 { 1314 if (dir->contents == 0) 1315 printf (_("# %s: could not be stat'd.\n"), dir->name); 1316 else if (dir->contents->dirfiles.ht_vec == 0) 1317 { 1245 1318 #ifdef WINDOWS32 1246 printf (_("# %s (key %s, mtime %d): could not be opened.\n"), 1247 dir->name, dir->contents->path_key,dir->contents->mtime); 1319 printf (_("# %s (key %s, mtime %I64u): could not be opened.\n"), 1320 dir->name, dir->contents->path_key, 1321 (unsigned long long)dir->contents->mtime); 1248 1322 #else /* WINDOWS32 */ 1249 #ifdef VMS 1250 1251 1252 1253 1254 #else 1255 1256 1257 1323 #ifdef VMS_INO_T 1324 printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"), 1325 dir->name, dir->contents->dev, 1326 dir->contents->ino[0], dir->contents->ino[1], 1327 dir->contents->ino[2]); 1328 #else 1329 printf (_("# %s (device %ld, inode %ld): could not be opened.\n"), 1330 dir->name, (long int) dir->contents->dev, 1331 (long int) dir->contents->ino); 1258 1332 #endif 1259 1333 #endif /* WINDOWS32 */ 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1334 } 1335 else 1336 { 1337 unsigned int f = 0; 1338 unsigned int im = 0; 1339 struct dirfile **files_slot; 1340 struct dirfile **files_end; 1341 1342 files_slot = (struct dirfile **) dir->contents->dirfiles.ht_vec; 1343 files_end = files_slot + dir->contents->dirfiles.ht_size; 1344 for ( ; files_slot < files_end; files_slot++) 1345 { 1346 struct dirfile *df = *files_slot; 1347 if (! HASH_VACANT (df)) 1348 { 1349 if (df->impossible) 1350 ++im; 1351 else 1352 ++f; 1353 } 1354 } 1281 1355 #ifdef WINDOWS32 1282 printf (_("# %s (key %s, mtime %d): "), 1283 dir->name, dir->contents->path_key, dir->contents->mtime); 1356 printf (_("# %s (key %s, mtime %I64u): "), 1357 dir->name, dir->contents->path_key, 1358 (unsigned long long)dir->contents->mtime); 1284 1359 #else /* WINDOWS32 */ 1285 #ifdef VMS 1286 1287 1288 1289 1290 #else 1291 1292 1293 1360 #ifdef VMS_INO_T 1361 printf (_("# %s (device %d, inode [%d,%d,%d]): "), 1362 dir->name, dir->contents->dev, 1363 dir->contents->ino[0], dir->contents->ino[1], 1364 dir->contents->ino[2]); 1365 #else 1366 printf (_("# %s (device %ld, inode %ld): "), 1367 dir->name, 1368 (long)dir->contents->dev, (long)dir->contents->ino); 1294 1369 #endif 1295 1370 #endif /* WINDOWS32 */ 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1371 if (f == 0) 1372 fputs (_("No"), stdout); 1373 else 1374 printf ("%u", f); 1375 fputs (_(" files, "), stdout); 1376 if (im == 0) 1377 fputs (_("no"), stdout); 1378 else 1379 printf ("%u", im); 1380 fputs (_(" impossibilities"), stdout); 1381 if (dir->contents->dirstream == 0) 1382 puts ("."); 1383 else 1384 puts (_(" so far.")); 1385 files += f; 1386 impossible += im; 1312 1387 #ifdef KMK 1313 1388 fputs ("# ", stdout); … … 1315 1390 fputs ("\n", stdout); 1316 1391 #endif 1317 1318 1392 } 1393 } 1319 1394 } 1320 1395 … … 1352 1427 /* Hooks for globbing. */ 1353 1428 1354 #include <glob.h>1355 1356 1429 /* Structure describing state of iterating through a directory hash table. */ 1357 1430 … … 1403 1476 struct dirfile *df = *ds->dirfile_slot++; 1404 1477 if (! HASH_VACANT (df) && !df->impossible) 1405 1406 /* The glob interface wants a `struct dirent', so mock one up. */1407 1408 1478 { 1479 /* The glob interface wants a 'struct dirent', so mock one up. */ 1480 struct dirent *d; 1481 unsigned int len = df->length + 1; 1409 1482 unsigned int sz = sizeof (*d) - sizeof (d->d_name) + len; 1410 1411 1412 1413 1414 1415 1416 1417 1483 if (sz > bufsz) 1484 { 1485 bufsz *= 2; 1486 if (sz > bufsz) 1487 bufsz = sz; 1488 buf = xrealloc (buf, bufsz); 1489 } 1490 d = (struct dirent *) buf; 1418 1491 #ifdef __MINGW32__ 1419 1492 # if __MINGW32_MAJOR_VERSION < 3 || (__MINGW32_MAJOR_VERSION == 3 && \ 1420 1421 d->d_name = xmalloc(len);1422 # endif 1423 #endif 1424 1493 __MINGW32_MINOR_VERSION == 0) 1494 d->d_name = xmalloc (len); 1495 # endif 1496 #endif 1497 FAKE_DIR_ENTRY (d); 1425 1498 #ifdef _DIRENT_HAVE_D_NAMLEN 1426 1499 d->d_namlen = len - 1; 1427 1500 #endif 1428 1501 #ifdef _DIRENT_HAVE_D_TYPE 1429 1430 #endif 1431 1432 1433 1502 d->d_type = DT_UNKNOWN; 1503 #endif 1504 memcpy (d->d_name, df->name, len); 1505 return d; 1506 } 1434 1507 } 1435 1508 1436 1509 return 0; 1437 }1438 1439 static void1440 ansi_free (void *p)1441 {1442 if (p)1443 free(p);1444 1510 } 1445 1511 … … 1447 1513 * macro for stat64(). If stat is a macro, make a local wrapper function to 1448 1514 * invoke it. 1515 * 1516 * On MS-Windows, stat() "succeeds" for foo/bar/. where foo/bar is a 1517 * regular file; fix that here. 1449 1518 */ 1450 #if ndef stat1519 #if !defined(stat) && !defined(WINDOWS32) || defined(VMS) 1451 1520 # ifndef VMS 1521 # ifndef HAVE_SYS_STAT_H 1452 1522 int stat (const char *path, struct stat *sbuf); 1523 # endif 1524 # else 1525 /* We are done with the fake stat. Go back to the real stat */ 1526 # ifdef stat 1527 # undef stat 1528 # endif 1453 1529 # endif 1454 1530 # define local_stat stat … … 1458 1534 { 1459 1535 int e; 1536 #ifdef WINDOWS32 1537 size_t plen = strlen (path); 1538 1539 /* Make sure the parent of "." exists and is a directory, not a 1540 file. This is because 'stat' on Windows normalizes the argument 1541 foo/. => foo without checking first that foo is a directory. */ 1542 if (plen > 1 && path[plen - 1] == '.' 1543 && (path[plen - 2] == '/' || path[plen - 2] == '\\')) 1544 { 1545 char parent[MAXPATHLEN]; 1546 1547 strncpy (parent, path, plen - 2); 1548 parent[plen - 2] = '\0'; 1549 if (stat (parent, buf) < 0 || !_S_ISDIR (buf->st_mode)) 1550 return -1; 1551 } 1552 #endif 1460 1553 1461 1554 EINTRLOOP (e, stat (path, buf)); … … 1482 1575 gl->gl_opendir = open_dirstream; 1483 1576 gl->gl_readdir = read_dirstream; 1484 gl->gl_closedir = ansi_free;1577 gl->gl_closedir = free; 1485 1578 gl->gl_stat = local_stat; 1486 1579 #ifdef __EMX__ /* The FreeBSD implementation actually uses gl_lstat!! */ … … 1500 1593 #ifndef CONFIG_WITH_STRCACHE2 1501 1594 hash_init (&directories, DIRECTORY_BUCKETS, 1502 1595 directory_hash_1, directory_hash_2, directory_hash_cmp); 1503 1596 #else /* CONFIG_WITH_STRCACHE2 */ 1504 1597 hash_init_strcached (&directories, DIRECTORY_BUCKETS, &file_strcache, … … 1506 1599 #endif /* CONFIG_WITH_STRCACHE2 */ 1507 1600 hash_init (&directory_contents, DIRECTORY_BUCKETS, 1508 1601 directory_contents_hash_1, directory_contents_hash_2, 1509 1602 directory_contents_hash_cmp); 1510 1603 #ifdef CONFIG_WITH_ALLOC_CACHES
Note:
See TracChangeset
for help on using the changeset viewer.