1/* 2 * Copyright (c) 1988, 1989, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1988, 1989 by Adam de Boor 5 * Copyright (c) 1989 by Berkeley Softworks 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by --- 26 unchanged lines hidden (view full) --- 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * @(#)dir.c 8.2 (Berkeley) 1/2/94 40 */ 41 42#include <sys/cdefs.h> |
43__FBSDID("$FreeBSD: head/usr.bin/make/dir.c 138264 2004-12-01 10:29:20Z harti $"); |
44 45/*- 46 * dir.c -- 47 * Directory searching using wildcards and/or normal names... 48 * Used both for source wildcarding in the Makefile and for finding 49 * implicit sources. 50 * 51 * The interface for this module is: --- 206 unchanged lines hidden (view full) --- 258 * none 259 *----------------------------------------------------------------------- 260 */ 261void 262Dir_End(void) 263{ 264 265 dot->refCount -= 1; |
266 Dir_Destroy(dot); |
267 Dir_ClearPath(dirSearchPath); 268 Lst_Destroy(dirSearchPath, NOFREE); 269 Dir_ClearPath(openDirectories); 270 Lst_Destroy(openDirectories, NOFREE); 271 Hash_DeleteTable(&mtimes); 272} 273 274/*- --- 8 unchanged lines hidden (view full) --- 283 * 284 * Side Effects: 285 * None 286 *----------------------------------------------------------------------- 287 */ 288static int 289DirFindName(void *p, void *dname) 290{ |
291 |
292 return (strcmp(((Path *)p)->name, (char *)dname)); 293} 294 295/*- 296 *----------------------------------------------------------------------- 297 * Dir_HasWildcards -- 298 * See if the given name has any wildcard characters in it. 299 * --- 59 unchanged lines hidden (view full) --- 359{ 360 Hash_Search search; /* Index into the directory's table */ 361 Hash_Entry *entry; /* Current entry in the table */ 362 Boolean isDot; /* TRUE if the directory being searched is . */ 363 364 isDot = (*p->name == '.' && p->name[1] == '\0'); 365 366 for (entry = Hash_EnumFirst(&p->files, &search); |
367 entry != NULL; |
368 entry = Hash_EnumNext(&search)) 369 { 370 /* 371 * See if the file matches the given pattern. Note we follow the UNIX 372 * convention that dot files will only be found if the pattern 373 * begins with a dot (note also that as a side effect of the hashing 374 * scheme, .* won't match . or .. since they aren't hashed). 375 */ --- 142 unchanged lines hidden (view full) --- 518static void 519DirExpandInt(char *word, Lst path, Lst expansions) 520{ 521 LstNode ln; /* Current node */ 522 Path *p; /* Directory in the node */ 523 524 if (Lst_Open(path) == SUCCESS) { 525 while ((ln = Lst_Next(path)) != NULL) { |
526 p = Lst_Datum(ln); |
527 DirMatchFiles(word, p, expansions); 528 } 529 Lst_Close(path); 530 } 531} 532 533/*- 534 *----------------------------------------------------------------------- --- 81 unchanged lines hidden (view full) --- 616 cp[1] = sc; 617 /* 618 * dirpath is null if can't find the leading component 619 * XXX: Dir_FindFile won't find internal components. 620 * i.e. if the path contains ../Etc/Object and we're 621 * looking for Etc, it won't be found. Ah well. 622 * Probably not important. 623 */ |
624 if (dirpath != NULL) { |
625 char *dp = &dirpath[strlen(dirpath) - 1]; 626 if (*dp == '/') 627 *dp = '\0'; 628 path = Lst_Init(FALSE); 629 Dir_AddDir(path, dirpath); 630 DirExpandInt(cp+1, path, expansions); 631 Lst_Destroy(path, NOFREE); 632 } --- 17 unchanged lines hidden (view full) --- 650 651 /* 652 * Then the files in every other directory on the path. 653 */ 654 DirExpandInt(word, path, expansions); 655 } 656 } 657 if (DEBUG(DIR)) { |
658 Lst_ForEach(expansions, DirPrintWord, (void *)NULL); |
659 DEBUGF(DIR, ("\n")); 660 } 661} 662 663/*- 664 *----------------------------------------------------------------------- 665 * Dir_FindFile -- 666 * Find the file with the given name along the given search path. --- 40 unchanged lines hidden (view full) --- 707 DEBUGF(DIR, ("Searching for %s...", name)); 708 /* 709 * No matter what, we always look for the file in the current directory 710 * before anywhere else and we *do not* add the ./ to it if it exists. 711 * This is so there are no conflicts between what the user specifies 712 * (fish.c) and what pmake finds (./fish.c). 713 */ 714 if ((!hasSlash || (cp - name == 2 && *name == '.')) && |
715 (Hash_FindEntry(&dot->files, cp) != NULL)) { |
716 DEBUGF(DIR, ("in '.'\n")); 717 hits += 1; 718 dot->hits += 1; 719 return (estrdup(name)); 720 } 721 722 if (Lst_Open(path) == FAILURE) { 723 DEBUGF(DIR, ("couldn't open path, file not found\n")); 724 misses += 1; |
725 return (NULL); |
726 } 727 728 /* 729 * We look through all the directories on the path seeking one which 730 * contains the final component of the given name and whose final 731 * component(s) match the name's initial component(s). If such a beast 732 * is found, we concatenate the directory name and the final component 733 * and return the resulting string. If we don't find any such thing, 734 * we go on to phase two... 735 */ 736 while ((ln = Lst_Next(path)) != NULL) { |
737 p = Lst_Datum (ln); |
738 DEBUGF(DIR, ("%s...", p->name)); |
739 if (Hash_FindEntry(&p->files, cp) != NULL) { |
740 DEBUGF(DIR, ("here...")); 741 if (hasSlash) { 742 /* 743 * If the name had a slash, its initial components and p's 744 * final components must match. This is false if a mismatch 745 * is encountered before all of the initial components 746 * have been checked (p2 > name at the end of the loop), or 747 * we matched only part of one of the components of p --- 26 unchanged lines hidden (view full) --- 774 } 775 if (*p1 == '\0' && p2 == cp - 1) { 776 Lst_Close(path); 777 if (*cp == '\0' || ISDOT(cp) || ISDOTDOT(cp)) { 778 DEBUGF(DIR, ("returning %s\n", name)); 779 return (estrdup(name)); 780 } else { 781 DEBUGF(DIR, ("must be here but isn't -- returning NULL\n")); |
782 return (NULL); |
783 } 784 } 785 } 786 } 787 788 /* 789 * We didn't find the file on any existing members of the directory. 790 * If the name doesn't contain a slash, that means it doesn't exist. --- 4 unchanged lines hidden (view full) --- 795 * /usr/include/sys/types.h) If we find such a beast, we assume there 796 * will be more (what else can we assume?) and add all but the last 797 * component of the resulting name onto the search path (at the 798 * end). This phase is only performed if the file is *not* absolute. 799 */ 800 if (!hasSlash) { 801 DEBUGF(DIR, ("failed.\n")); 802 misses += 1; |
803 return (NULL); |
804 } 805 806 if (*name != '/') { 807 Boolean checkedDot = FALSE; 808 809 DEBUGF(DIR, ("failed. Trying subdirectories...")); |
810 Lst_Open(path); |
811 while ((ln = Lst_Next(path)) != NULL) { |
812 p = Lst_Datum(ln); |
813 if (p != dot) { 814 file = str_concat(p->name, name, STR_ADDSLASH); 815 } else { 816 /* 817 * Checking in dot -- DON'T put a leading ./ on the thing. 818 */ 819 file = estrdup(name); 820 checkedDot = TRUE; --- 20 unchanged lines hidden (view full) --- 841 Dir_AddDir(path, file); 842 *cp = '/'; 843 844 /* 845 * Save the modification time so if it's needed, we don't have 846 * to fetch it again. 847 */ 848 DEBUGF(DIR, ("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime), file)); |
849 entry = Hash_CreateEntry(&mtimes, file, (Boolean *)NULL); 850 Hash_SetValue(entry, (void *)(long)stb.st_mtime); |
851 nearmisses += 1; 852 return (file); 853 } else { 854 free(file); 855 } 856 } 857 858 DEBUGF(DIR, ("failed. ")); --- 29 unchanged lines hidden (view full) --- 888#ifdef notdef 889 cp[-1] = '\0'; 890 Dir_AddDir(path, name); 891 cp[-1] = '/'; 892 893 bigmisses += 1; 894 ln = Lst_Last(path); 895 if (ln == NULL) { |
896 return (NULL); |
897 } else { |
898 p = Lst_Datum(ln); |
899 } 900 |
901 if (Hash_FindEntry(&p->files, cp) != NULL) { |
902 return (estrdup(name)); 903 } else { |
904 return (NULL); |
905 } 906#else /* !notdef */ 907 DEBUGF(DIR, ("Looking for \"%s\"...", name)); 908 909 bigmisses += 1; 910 entry = Hash_FindEntry(&mtimes, name); |
911 if (entry != NULL) { |
912 DEBUGF(DIR, ("got it (in mtime cache)\n")); 913 return (estrdup(name)); 914 } else if (stat (name, &stb) == 0) { 915 entry = Hash_CreateEntry(&mtimes, name, (Boolean *)NULL); 916 DEBUGF(DIR, ("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime), name)); |
917 Hash_SetValue(entry, (void *)(long)stb.st_mtime); |
918 return (estrdup(name)); 919 } else { 920 DEBUGF(DIR, ("failed. Returning NULL\n")); |
921 return (NULL); |
922 } 923#endif /* notdef */ 924} 925 926/*- 927 *----------------------------------------------------------------------- 928 * Dir_MTime -- 929 * Find the modification time of the file described by gn along the --- 12 unchanged lines hidden (view full) --- 942Dir_MTime(GNode *gn) 943{ 944 char *fullName; /* the full pathname of name */ 945 struct stat stb; /* buffer for finding the mod time */ 946 Hash_Entry *entry; 947 948 if (gn->type & OP_ARCHV) { 949 return (Arch_MTime(gn)); |
950 } else if (gn->path == NULL) { |
951 fullName = Dir_FindFile(gn->name, dirSearchPath); 952 } else { 953 fullName = gn->path; 954 } 955 |
956 if (fullName == NULL) { |
957 fullName = estrdup(gn->name); 958 } 959 960 entry = Hash_FindEntry(&mtimes, fullName); |
961 if (entry != NULL) { |
962 /* 963 * Only do this once -- the second time folks are checking to 964 * see if the file was actually updated, so we need to actually go 965 * to the filesystem. 966 */ 967 DEBUGF(DIR, ("Using cached time %s for %s\n", 968 Targ_FmtTime((time_t)(long)Hash_GetValue(entry)), fullName)); 969 stb.st_mtime = (time_t)(long)Hash_GetValue(entry); --- 33 unchanged lines hidden (view full) --- 1003void 1004Dir_AddDir(Lst path, char *name) 1005{ 1006 LstNode ln; /* node in case Path structure is found */ 1007 Path *p; /* pointer to new Path structure */ 1008 DIR *d; /* for reading directory */ 1009 struct dirent *dp; /* entry in directory */ 1010 |
1011 ln = Lst_Find(openDirectories, name, DirFindName); |
1012 if (ln != NULL) { |
1013 p = Lst_Datum(ln); 1014 if (Lst_Member(path, p) == NULL) { |
1015 p->refCount += 1; |
1016 Lst_AtEnd(path, p); |
1017 } 1018 } else { 1019 DEBUGF(DIR, ("Caching %s...", name)); 1020 1021 if ((d = opendir(name)) != (DIR *)NULL) { |
1022 p = emalloc(sizeof(Path)); |
1023 p->name = estrdup(name); 1024 p->hits = 0; 1025 p->refCount = 1; 1026 Hash_InitTable(&p->files, -1); 1027 |
1028 while ((dp = readdir(d)) != NULL) { |
1029#if defined(sun) && defined(d_ino) /* d_ino is a sunos4 #define for d_fileno */ 1030 /* 1031 * The sun directory library doesn't check for a 0 inode 1032 * (0-inode slots just take up space), so we have to do 1033 * it ourselves. 1034 */ 1035 if (dp->d_fileno == 0) { 1036 continue; --- 8 unchanged lines hidden (view full) --- 1045 * from readdir(). 1046 */ 1047 if (ISDOT(dp->d_name) || ISDOTDOT(dp->d_name)) 1048 continue; 1049 1050 Hash_CreateEntry(&p->files, dp->d_name, (Boolean *)NULL); 1051 } 1052 closedir(d); |
1053 Lst_AtEnd(openDirectories, p); |
1054 if (path != openDirectories) |
1055 Lst_AtEnd(path, p); |
1056 } 1057 DEBUGF(DIR, ("done\n")); 1058 } 1059} 1060 1061/*- 1062 *----------------------------------------------------------------------- 1063 * Dir_CopyDir -- --- 9 unchanged lines hidden (view full) --- 1073 *----------------------------------------------------------------------- 1074 */ 1075void * 1076Dir_CopyDir(void *p) 1077{ 1078 1079 ((Path *)p)->refCount += 1; 1080 |
1081 return (p); |
1082} 1083 1084/*- 1085 *----------------------------------------------------------------------- 1086 * Dir_MakeFlags -- 1087 * Make a string by taking all the directories in the given search 1088 * path and preceding them by the given flag. Used by the suffix 1089 * module to create variables for compilers based on suffix search --- 15 unchanged lines hidden (view full) --- 1105 char *tstr; /* the current directory preceded by 'flag' */ 1106 LstNode ln; /* the node of the current directory */ 1107 Path *p; /* the structure describing the current directory */ 1108 1109 str = estrdup(""); 1110 1111 if (Lst_Open(path) == SUCCESS) { 1112 while ((ln = Lst_Next(path)) != NULL) { |
1113 p = Lst_Datum(ln); |
1114 tstr = str_concat(flag, p->name, 0); 1115 str = str_concat(str, tstr, STR_ADDSPACE | STR_DOFREE); 1116 } 1117 Lst_Close(path); 1118 } 1119 1120 return (str); 1121} --- 11 unchanged lines hidden (view full) --- 1133 * If no other path references this directory (refCount == 0), 1134 * the Path and all its data are freed. 1135 * 1136 *----------------------------------------------------------------------- 1137 */ 1138void 1139Dir_Destroy(void *pp) 1140{ |
1141 Path *p = pp; 1142 |
1143 p->refCount -= 1; 1144 1145 if (p->refCount == 0) { 1146 LstNode ln; 1147 |
1148 ln = Lst_Member(openDirectories, p); |
1149 Lst_Remove(openDirectories, ln); 1150 1151 Hash_DeleteTable(&p->files); 1152 free(p->name); 1153 free(p); 1154 } 1155} 1156 --- 12 unchanged lines hidden (view full) --- 1169 *----------------------------------------------------------------------- 1170 */ 1171void 1172Dir_ClearPath(Lst path) 1173{ 1174 Path *p; 1175 1176 while (!Lst_IsEmpty(path)) { |
1177 p = Lst_DeQueue(path); 1178 Dir_Destroy(p); |
1179 } 1180} 1181 1182 1183/*- 1184 *----------------------------------------------------------------------- 1185 * Dir_Concat -- 1186 * Concatenate two paths, adding the second to the end of the first. --- 9 unchanged lines hidden (view full) --- 1196 */ 1197void 1198Dir_Concat(Lst path1, Lst path2) 1199{ 1200 LstNode ln; 1201 Path *p; 1202 1203 for (ln = Lst_First(path2); ln != NULL; ln = Lst_Succ(ln)) { |
1204 p = Lst_Datum(ln); 1205 if (Lst_Member(path1, p) == NULL) { |
1206 p->refCount += 1; |
1207 Lst_AtEnd(path1, p); |
1208 } 1209 } 1210} 1211 1212/********** DEBUG INFO **********/ 1213void 1214Dir_PrintDirectories(void) 1215{ 1216 LstNode ln; 1217 Path *p; 1218 1219 printf("#*** Directory Cache:\n"); 1220 printf("# Stats: %d hits %d misses %d near misses %d losers (%d%%)\n", 1221 hits, misses, nearmisses, bigmisses, 1222 (hits + bigmisses + nearmisses ? 1223 hits * 100 / (hits + bigmisses + nearmisses) : 0)); 1224 printf("# %-20s referenced\thits\n", "directory"); 1225 if (Lst_Open(openDirectories) == SUCCESS) { 1226 while ((ln = Lst_Next(openDirectories)) != NULL) { |
1227 p = Lst_Datum(ln); |
1228 printf("# %-20s %10d\t%4d\n", p->name, p->refCount, p->hits); 1229 } 1230 Lst_Close(openDirectories); 1231 } 1232} 1233 1234static int 1235DirPrintDir(void *p, void *dummy __unused) 1236{ 1237 1238 printf("%s ", ((Path *)p)->name); 1239 1240 return (0); 1241} 1242 1243void 1244Dir_PrintPath(Lst path) 1245{ 1246 |
1247 Lst_ForEach(path, DirPrintDir, (void *)NULL); |
1248} |