📄 dir.c
字号:
Hash_SetValue(entry, stb.st_mtime); nearmisses += 1; return (file); } else { free (file); } } if (DEBUG(DIR)) { printf("failed. "); } Lst_Close (path); if (checkedDot) { /* * Already checked by the given name, since . was in the path, * so no point in proceeding... */ if (DEBUG(DIR)) { printf("Checked . already, returning NULL\n"); } return(NULL); } } /* * Didn't find it that way, either. Sigh. Phase 3. Add its directory * onto the search path in any case, just in case, then look for the * thing in the hash table. If we find it, grand. We return a new * copy of the name. Otherwise we sadly return a NULL pointer. Sigh. * Note that if the directory holding the file doesn't exist, this will * do an extra search of the final directory on the path. Unless something * weird happens, this search won't succeed and life will be groovy. * * Sigh. We cannot add the directory onto the search path because * of this amusing case: * $(INSTALLDIR)/$(FILE): $(FILE) * * $(FILE) exists in $(INSTALLDIR) but not in the current one. * When searching for $(FILE), we will find it in $(INSTALLDIR) * b/c we added it here. This is not good... */#ifdef notdef cp[-1] = '\0'; Dir_AddDir (path, name); cp[-1] = '/'; bigmisses += 1; ln = Lst_Last (path); if (ln == NILLNODE) { return ((char *) NULL); } else { p = (Path *) Lst_Datum (ln); } if (Hash_FindEntry (&p->files, cp) != (Hash_Entry *)NULL) { return (strdup (name)); } else { return ((char *) NULL); }#else /* !notdef */ if (DEBUG(DIR)) { printf("Looking for \"%s\"...", name); } bigmisses += 1; entry = Hash_FindEntry(&mtimes, name); if (entry != (Hash_Entry *)NULL) { if (DEBUG(DIR)) { printf("got it (in mtime cache)\n"); } return(strdup(name)); } else if (stat (name, &stb) == 0) { entry = Hash_CreateEntry(&mtimes, name, (Boolean *)NULL); if (DEBUG(DIR)) { printf("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime), name); } Hash_SetValue(entry, stb.st_mtime); return (strdup (name)); } else { if (DEBUG(DIR)) { printf("failed. Returning NULL\n"); } return ((char *)NULL); }#endif /* notdef */}/*- *----------------------------------------------------------------------- * Dir_MTime -- * Find the modification time of the file described by gn along the * search path dirSearchPath. * * Results: * The modification time or 0 if it doesn't exist * * Side Effects: * The modification time is placed in the node's mtime slot. * If the node didn't have a path entry before, and Dir_FindFile * found one for it, the full name is placed in the path slot. *----------------------------------------------------------------------- */intDir_MTime (gn) GNode *gn; /* the file whose modification time is * desired */{ char *fullName; /* the full pathname of name */ struct stat stb; /* buffer for finding the mod time */ Hash_Entry *entry; if (gn->type & OP_ARCHV) { return Arch_MTime (gn); } else if (gn->path == (char *)NULL) { fullName = Dir_FindFile (gn->name, dirSearchPath); } else { fullName = gn->path; } if (fullName == (char *)NULL) { fullName = gn->name; } entry = Hash_FindEntry(&mtimes, fullName); if (entry != (Hash_Entry *)NULL) { /* * Only do this once -- the second time folks are checking to * see if the file was actually updated, so we need to actually go * to the file system. */ if (DEBUG(DIR)) { printf("Using cached time %s for %s\n", Targ_FmtTime((time_t) Hash_GetValue(entry)), fullName); } stb.st_mtime = (time_t)Hash_GetValue(entry); Hash_DeleteEntry(&mtimes, entry); } else if (stat (fullName, &stb) < 0) { if (gn->type & OP_MEMBER) { return Arch_MemMTime (gn); } else { stb.st_mtime = 0; } } if (fullName && gn->path == (char *)NULL) { gn->path = fullName; } gn->mtime = stb.st_mtime; return (gn->mtime);}/*- *----------------------------------------------------------------------- * Dir_AddDir -- * Add the given name to the end of the given path. The order of * the arguments is backwards so ParseDoDependency can do a * Lst_ForEach of its list of paths... * * Results: * none * * Side Effects: * A structure is added to the list and the directory is * read and hashed. *----------------------------------------------------------------------- */voidDir_AddDir (path, name) Lst path; /* the path to which the directory should be * added */ char *name; /* the name of the directory to add */{ LstNode ln; /* node in case Path structure is found */ register Path *p; /* pointer to new Path structure */ DIR *d; /* for reading directory */ register struct dirent *dp; /* entry in directory */ ln = Lst_Find (openDirectories, (ClientData)name, DirFindName); if (ln != NILLNODE) { p = (Path *)Lst_Datum (ln); if (Lst_Member(path, (ClientData)p) == NILLNODE) { p->refCount += 1; (void)Lst_AtEnd (path, (ClientData)p); } } else { if (DEBUG(DIR)) { printf("Caching %s...", name); fflush(stdout); } if ((d = opendir (name)) != (DIR *) NULL) { p = (Path *) emalloc (sizeof (Path)); p->name = strdup (name); p->hits = 0; p->refCount = 1; Hash_InitTable (&p->files, -1); /* * Skip the first two entries -- these will *always* be . and .. */ (void)readdir(d); (void)readdir(d); while ((dp = readdir (d)) != (struct dirent *) NULL) {#ifdef sun /* * The sun directory library doesn't check for a 0 inode * (0-inode slots just take up space), so we have to do * it ourselves. */ if (dp->d_fileno == 0) { continue; }#endif sun (void)Hash_CreateEntry(&p->files, dp->d_name, (Boolean *)NULL); } (void) closedir (d); (void)Lst_AtEnd (openDirectories, (ClientData)p); (void)Lst_AtEnd (path, (ClientData)p); } if (DEBUG(DIR)) { printf("done\n"); } }}/*- *----------------------------------------------------------------------- * Dir_CopyDir -- * Callback function for duplicating a search path via Lst_Duplicate. * Ups the reference count for the directory. * * Results: * Returns the Path it was given. * * Side Effects: * The refCount of the path is incremented. * *----------------------------------------------------------------------- */ClientDataDir_CopyDir(p) Path *p; /* Directory descriptor to copy */{ p->refCount += 1; return ((ClientData)p);}/*- *----------------------------------------------------------------------- * Dir_MakeFlags -- * Make a string by taking all the directories in the given search * path and preceding them by the given flag. Used by the suffix * module to create variables for compilers based on suffix search * paths. * * Results: * The string mentioned above. Note that there is no space between * the given flag and each directory. The empty string is returned if * Things don't go well. * * Side Effects: * None *----------------------------------------------------------------------- */char *Dir_MakeFlags (flag, path) char *flag; /* flag which should precede each directory */ Lst path; /* list of directories */{ char *str; /* the string which will be returned */ char *tstr; /* the current directory preceded by 'flag' */ LstNode ln; /* the node of the current directory */ Path *p; /* the structure describing the current directory */ str = strdup (""); if (Lst_Open (path) == SUCCESS) { while ((ln = Lst_Next (path)) != NILLNODE) { p = (Path *) Lst_Datum (ln); tstr = str_concat (flag, p->name, 0); str = str_concat (str, tstr, STR_ADDSPACE | STR_DOFREE); } Lst_Close (path); } return (str);}/*- *----------------------------------------------------------------------- * Dir_Destroy -- * Nuke a directory descriptor, if possible. Callback procedure * for the suffixes module when destroying a search path. * * Results: * None. * * Side Effects: * If no other path references this directory (refCount == 0), * the Path and all its data are freed. * *----------------------------------------------------------------------- */voidDir_Destroy (p) Path *p; /* The directory descriptor to nuke */{ p->refCount -= 1; if (p->refCount == 0) { LstNode ln; ln = Lst_Member (openDirectories, (ClientData)p); (void) Lst_Remove (openDirectories, ln); Hash_DeleteTable (&p->files); free((Address)p->name); free((Address)p); }}/*- *----------------------------------------------------------------------- * Dir_ClearPath -- * Clear out all elements of the given search path. This is different * from destroying the list, notice. * * Results: * None. * * Side Effects: * The path is set to the empty list. * *----------------------------------------------------------------------- */voidDir_ClearPath(path) Lst path; /* Path to clear */{ Path *p; while (!Lst_IsEmpty(path)) { p = (Path *)Lst_DeQueue(path); Dir_Destroy(p); }} /*- *----------------------------------------------------------------------- * Dir_Concat -- * Concatenate two paths, adding the second to the end of the first. * Makes sure to avoid duplicates. * * Results: * None * * Side Effects: * Reference counts for added dirs are upped. * *----------------------------------------------------------------------- */voidDir_Concat(path1, path2) Lst path1; /* Dest */ Lst path2; /* Source */{ LstNode ln; Path *p; for (ln = Lst_First(path2); ln != NILLNODE; ln = Lst_Succ(ln)) { p = (Path *)Lst_Datum(ln); if (Lst_Member(path1, (ClientData)p) == NILLNODE) { p->refCount += 1; (void)Lst_AtEnd(path1, (ClientData)p); } }}/********** DEBUG INFO **********/voidDir_PrintDirectories(){ LstNode ln; Path *p; printf ("#*** Directory Cache:\n"); printf ("# Stats: %d hits %d misses %d near misses %d losers (%d%%)\n", hits, misses, nearmisses, bigmisses, (hits+bigmisses+nearmisses ? hits * 100 / (hits + bigmisses + nearmisses) : 0)); printf ("# %-20s referenced\thits\n", "directory"); if (Lst_Open (openDirectories) == SUCCESS) { while ((ln = Lst_Next (openDirectories)) != NILLNODE) { p = (Path *) Lst_Datum (ln); printf ("# %-20s %10d\t%4d\n", p->name, p->refCount, p->hits); } Lst_Close (openDirectories); }}static int DirPrintDir (p) Path *p; { printf ("%s ", p->name); return (0); }voidDir_PrintPath (path) Lst path;{ Lst_ForEach (path, DirPrintDir, (ClientData)0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -