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

📄 dir.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	/*	 * See if the result has any wildcards in it. If we find one, call	 * Dir_Expand right away, telling it to place the result on our list	 * of expansions.	 */	for (cp2 = file; *cp2 != '\0'; cp2++) {	    switch(*cp2) {	    case '*':	    case '?':	    case '{':	    case '[':		Dir_Expand(file, path, expansions);		goto next;	    }	}	if (*cp2 == '\0') {	    /*	     * Hit the end w/o finding any wildcards, so stick the expansion	     * on the end of the list.	     */	    (void)Lst_AtEnd(expansions, file);	} else {	next:	    free(file);	}	start = cp+1;    }}/*- *----------------------------------------------------------------------- * DirExpandInt -- *	Internal expand routine. Passes through the directories in the *	path one by one, calling DirMatchFiles for each. NOTE: This still *	doesn't handle patterns in directories... * * Results: *	None. * * Side Effects: *	Things are added to the expansions list. * *----------------------------------------------------------------------- */static voidDirExpandInt(word, path, expansions)    char    	  *word;    	/* Word to expand */    Lst	    	  path;	    	/* Path on which to look */    Lst	    	  expansions;	/* Place to store the result */{    LstNode 	  ln;	    	/* Current node */    Path	  *p;	    	/* Directory in the node */    if (Lst_Open(path) == SUCCESS) {	while ((ln = Lst_Next(path)) != NILLNODE) {	    p = (Path *)Lst_Datum(ln);	    DirMatchFiles(word, p, expansions);	}	Lst_Close(path);    }}/*- *----------------------------------------------------------------------- * DirPrintWord -- *	Print a word in the list of expansions. Callback for Dir_Expand *	when DEBUG(DIR), via Lst_ForEach. * * Results: *	=== 0 * * Side Effects: *	The passed word is printed, followed by a space. * *----------------------------------------------------------------------- */static intDirPrintWord(word)    char    *word;{    printf("%s ", word);    return(0);}/*- *----------------------------------------------------------------------- * Dir_Expand  -- *	Expand the given word into a list of words by globbing it looking *	in the directories on the given search path. * * Results: *	A list of words consisting of the files which exist along the search *	path matching the given pattern. * * Side Effects: *	Directories may be opened. Who knows? *----------------------------------------------------------------------- */voidDir_Expand (word, path, expansions)    char    *word;      /* the word to expand */    Lst     path;   	/* the list of directories in which to find			 * the resulting files */    Lst	    expansions;	/* the list on which to place the results */{    char    	  *cp;    if (DEBUG(DIR)) {	printf("expanding \"%s\"...", word);    }        cp = strchr(word, '{');    if (cp) {	DirExpandCurly(word, cp, path, expansions);    } else {	cp = strchr(word, '/');	if (cp) {	    /*	     * The thing has a directory component -- find the first wildcard	     * in the string.	     */	    for (cp = word; *cp; cp++) {		if (*cp == '?' || *cp == '[' || *cp == '*' || *cp == '{') {		    break;		}	    }	    if (*cp == '{') {		/*		 * This one will be fun.		 */		DirExpandCurly(word, cp, path, expansions);		return;	    } else if (*cp != '\0') {		/*		 * Back up to the start of the component		 */		char  *dirpath;		while (cp > word && *cp != '/') {		    cp--;		}		if (cp != word) {		    char sc;		    /*		     * If the glob isn't in the first component, try and find		     * all the components up to the one with a wildcard.		     */		    sc = cp[1];		    cp[1] = '\0';		    dirpath = Dir_FindFile(word, path);		    cp[1] = sc;		    /*		     * dirpath is null if can't find the leading component		     * XXX: Dir_FindFile won't find internal components.		     * i.e. if the path contains ../Etc/Object and we're		     * looking for Etc, it won't be found. Ah well.		     * Probably not important.		     */		    if (dirpath != (char *)NULL) {			char *dp = &dirpath[strlen(dirpath) - 1];			if (*dp == '/')			    *dp = '\0';			path = Lst_Init(FALSE);			Dir_AddDir(path, dirpath);			DirExpandInt(cp+1, path, expansions);			Lst_Destroy(path, NOFREE);		    }		} else {		    /*		     * Start the search from the local directory		     */		    DirExpandInt(word, path, expansions);		}	    } else {		/*		 * Return the file -- this should never happen.		 */		DirExpandInt(word, path, expansions);	    }	} else {	    /*	     * First the files in dot	     */	    DirMatchFiles(word, dot, expansions);    	    /*	     * Then the files in every other directory on the path.	     */	    DirExpandInt(word, path, expansions);	}    }    if (DEBUG(DIR)) {	Lst_ForEach(expansions, DirPrintWord, NULL);	fputc('\n', stdout);    }}/*- *----------------------------------------------------------------------- * Dir_FindFile  -- *	Find the file with the given name along the given search path. * * Results: *	The path to the file or NULL. This path is guaranteed to be in a *	different part of memory than name and so may be safely free'd. * * Side Effects: *	If the file is found in a directory which is not on the path *	already (either 'name' is absolute or it is a relative path *	[ dir1/.../dirn/file ] which exists below one of the directories *	already on the search path), its directory is added to the end *	of the path on the assumption that there will be more files in *	that directory later on. Sometimes this is true. Sometimes not. *----------------------------------------------------------------------- */char *Dir_FindFile (name, path)    char    	  *name;    /* the file to find */    Lst           path;	    /* the Lst of directories to search */{    register char *p1;	    /* pointer into p->name */    register char *p2;	    /* pointer into name */    LstNode       ln;	    /* a list element */    register char *file;    /* the current filename to check */    register Path *p;	    /* current path member */    register char *cp;	    /* index of first slash, if any */    Boolean	  hasSlash; /* true if 'name' contains a / */    struct stat	  stb;	    /* Buffer for stat, if necessary */    Hash_Entry	  *entry;   /* Entry for mtimes table */        /*     * Find the final component of the name and note whether it has a     * slash in it (the name, I mean)     */    cp = strrchr (name, '/');    if (cp) {	hasSlash = TRUE;	cp += 1;    } else {	hasSlash = FALSE;	cp = name;    }        if (DEBUG(DIR)) {	printf("Searching for %s...", name);    }    /*     * No matter what, we always look for the file in the current directory     * before anywhere else and we *do not* add the ./ to it if it exists.     * This is so there are no conflicts between what the user specifies     * (fish.c) and what pmake finds (./fish.c).     */    if ((!hasSlash || (cp - name == 2 && *name == '.')) &&	(Hash_FindEntry (&dot->files, cp) != (Hash_Entry *)NULL)) {	    if (DEBUG(DIR)) {		printf("in '.'\n");	    }	    hits += 1;	    dot->hits += 1;	    return (strdup (name));    }        if (Lst_Open (path) == FAILURE) {	if (DEBUG(DIR)) {	    printf("couldn't open path, file not found\n");	}	misses += 1;	return ((char *) NULL);    }        /*     * We look through all the directories on the path seeking one which     * contains the final component of the given name and whose final     * component(s) match the name's initial component(s). If such a beast     * is found, we concatenate the directory name and the final component     * and return the resulting string. If we don't find any such thing,     * we go on to phase two...     */    while ((ln = Lst_Next (path)) != NILLNODE) {	p = (Path *) Lst_Datum (ln);	if (DEBUG(DIR)) {	    printf("%s...", p->name);	}	if (Hash_FindEntry (&p->files, cp) != (Hash_Entry *)NULL) {	    if (DEBUG(DIR)) {		printf("here...");	    }	    if (hasSlash) {		/*		 * If the name had a slash, its initial components and p's		 * final components must match. This is false if a mismatch		 * is encountered before all of the initial components		 * have been checked (p2 > name at the end of the loop), or		 * we matched only part of one of the components of p		 * along with all the rest of them (*p1 != '/').		 */		p1 = p->name + strlen (p->name) - 1;		p2 = cp - 2;		while (p2 >= name && *p1 == *p2) {		    p1 -= 1; p2 -= 1;		}		if (p2 >= name || (p1 >= p->name && *p1 != '/')) {		    if (DEBUG(DIR)) {			printf("component mismatch -- continuing...");		    }		    continue;		}	    }	    file = str_concat (p->name, cp, STR_ADDSLASH);	    if (DEBUG(DIR)) {		printf("returning %s\n", file);	    }	    Lst_Close (path);	    p->hits += 1;	    hits += 1;	    return (file);	} else if (hasSlash) {	    /*	     * If the file has a leading path component and that component	     * exactly matches the entire name of the current search	     * directory, we assume the file doesn't exist and return NULL.	     */	    for (p1 = p->name, p2 = name; *p1 && *p1 == *p2; p1++, p2++) {		continue;	    }	    if (*p1 == '\0' && p2 == cp - 1) {		if (DEBUG(DIR)) {		    printf("must be here but isn't -- returing NULL\n");		}		Lst_Close (path);		return ((char *) NULL);	    }	}    }        /*     * We didn't find the file on any existing members of the directory.     * If the name doesn't contain a slash, that means it doesn't exist.     * If it *does* contain a slash, however, there is still hope: it     * could be in a subdirectory of one of the members of the search     * path. (eg. /usr/include and sys/types.h. The above search would     * fail to turn up types.h in /usr/include, but it *is* in     * /usr/include/sys/types.h) If we find such a beast, we assume there     * will be more (what else can we assume?) and add all but the last     * component of the resulting name onto the search path (at the     * end). This phase is only performed if the file is *not* absolute.     */    if (!hasSlash) {	if (DEBUG(DIR)) {	    printf("failed.\n");	}	misses += 1;	return ((char *) NULL);    }        if (*name != '/') {	Boolean	checkedDot = FALSE;		if (DEBUG(DIR)) {	    printf("failed. Trying subdirectories...");	}	(void) Lst_Open (path);	while ((ln = Lst_Next (path)) != NILLNODE) {	    p = (Path *) Lst_Datum (ln);	    if (p != dot) {		file = str_concat (p->name, name, STR_ADDSLASH);	    } else {		/*		 * Checking in dot -- DON'T put a leading ./ on the thing.		 */		file = strdup(name);		checkedDot = TRUE;	    }	    if (DEBUG(DIR)) {		printf("checking %s...", file);	    }	    			    if (stat (file, &stb) == 0) {		if (DEBUG(DIR)) {		    printf("got it.\n");		}				Lst_Close (path);				/*		 * We've found another directory to search. We know there's		 * a slash in 'file' because we put one there. We nuke it after		 * finding it and call Dir_AddDir to add this new directory		 * onto the existing search path. Once that's done, we restore		 * the slash and triumphantly return the file name, knowing		 * that should a file in this directory every be referenced		 * again in such a manner, we will find it without having to do		 * numerous numbers of access calls. Hurrah!		 */		cp = strrchr (file, '/');		*cp = '\0';		Dir_AddDir (path, file);		*cp = '/';				/*		 * Save the modification time so if it's needed, we don't have		 * to fetch it again.		 */		if (DEBUG(DIR)) {		    printf("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),			    file);		}		entry = Hash_CreateEntry(&mtimes, (char *) file,					 (Boolean *)NULL);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -