Changeset 3138 for vendor/gnumake/current/dir.c
- Timestamp:
- Mar 12, 2018, 8:32:29 PM (7 years ago)
- File:
-
- 1 edited
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 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 165 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, ':'); 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 239 #ifndef DIRECTORY_BUCKETS 210 240 #define DIRECTORY_BUCKETS 199 211 241 #endif … … 213 243 struct directory_contents 214 244 { 215 dev_t dev; 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 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; 237 DIR *dirstream; 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 254 255 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 277 278 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; 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 392 ((const struct directory *) y)->name); 363 393 } 364 394 … … 377 407 struct dirfile 378 408 { 379 const char *name; 380 s hort length;381 short 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 437 #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 488 setting the `contents' member to a nil pointer. */489 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 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 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 549 550 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 574 dc->ino = st.st_ino; 553 575 # endif 554 576 #endif /* WINDOWS32 */ 555 556 557 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 562 563 564 565 566 567 568 569 570 571 572 573 574 575 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 627 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 652 653 654 655 656 657 658 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 663 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 673 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 717 continue; 701 718 702 719 len = NAMLEN (d); … … 711 728 if (! rehash || HASH_VACANT (*dirfile_slot)) 712 729 #endif 713 714 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 775 filename); 749 776 } 750 777 … … 759 786 const char *slash; 760 787 761 #ifndef 788 #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 803 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 # 896 #endif /* HAVE_DOS_PATHS */ 846 897 if (dirend == 0) 847 # 898 #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 908 dirname = "/"; 859 909 else 860 910 { 861 911 char *cp; 862 912 #ifdef HAVE_DOS_PATHS 863 864 865 866 867 #endif 868 869 870 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 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 1007 dirname = "/"; 943 1008 else 944 1009 { 945 1010 char *cp; 946 1011 #ifdef HAVE_DOS_PATHS 947 948 949 950 951 #endif 952 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 1026 1027 1028 1029 #else 1030 1031 1032 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 1062 1063 1064 1065 #else 1066 1067 1068 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 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 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 1161 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 1164 1165 1166 1167 1168 1169 1170 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 1174 d->d_name = xmalloc(len);1246 __MINGW32_MINOR_VERSION == 0) 1247 d->d_name = xmalloc (len); 1175 1248 # endif 1176 1249 #endif 1177 1250 FAKE_DIR_ENTRY (d); 1178 1251 #ifdef _DIRENT_HAVE_D_NAMLEN 1179 1252 d->d_namlen = len - 1; 1180 1253 #endif 1181 1254 #ifdef _DIRENT_HAVE_D_TYPE 1182 1183 #endif 1184 1185 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 1327 directory_hash_1, directory_hash_2, directory_hash_cmp); 1235 1328 hash_init (&directory_contents, DIRECTORY_BUCKETS, 1236 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.