⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dir.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
		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 + -