function.c

来自「早期freebsd实现」· C语言 代码 · 共 1,070 行 · 第 1/2 页

C
1,070
字号
/*- * Copyright (c) 1990, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Cimarron D. Taylor of the University of California, Berkeley. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)function.c	8.6 (Berkeley) 4/1/94";#endif /* not lint */#include <sys/param.h>#include <sys/ucred.h>#include <sys/stat.h>#include <sys/wait.h>#include <sys/mount.h>#include <err.h>#include <errno.h>#include <fnmatch.h>#include <fts.h>#include <grp.h>#include <pwd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <tzfile.h>#include <unistd.h>#include "find.h"#define	COMPARE(a, b) {							\	switch (plan->flags) {						\	case F_EQUAL:							\		return (a == b);					\	case F_LESSTHAN:						\		return (a < b);						\	case F_GREATER:							\		return (a > b);						\	default:							\		abort();						\	}								\}static PLAN *palloc __P((enum ntype, int (*) __P((PLAN *, FTSENT *))));/* * find_parsenum -- *	Parse a string of the form [+-]# and return the value. */static longfind_parsenum(plan, option, vp, endch)	PLAN *plan;	char *option, *vp, *endch;{	long value;	char *endchar, *str;	/* Pointer to character ending conversion. */    	/* Determine comparison from leading + or -. */	str = vp;	switch (*str) {	case '+':		++str;		plan->flags = F_GREATER;		break;	case '-':		++str;		plan->flags = F_LESSTHAN;		break;	default:		plan->flags = F_EQUAL;		break;	}    	/*	 * Convert the string with strtol().  Note, if strtol() returns zero	 * and endchar points to the beginning of the string we know we have	 * a syntax error.	 */	value = strtol(str, &endchar, 10);	if (value == 0 && endchar == str)		errx(1, "%s: %s: illegal numeric value", option, vp);	if (endchar[0] && (endch == NULL || endchar[0] != *endch))		errx(1, "%s: %s: illegal trailing character", option, vp);	if (endch)		*endch = endchar[0];	return (value);}/* * The value of n for the inode times (atime, ctime, and mtime) is a range, * i.e. n matches from (n - 1) to n 24 hour periods.  This interacts with * -n, such that "-mtime -1" would be less than 0 days, which isn't what the * user wanted.  Correct so that -1 is "less than 1". */#define	TIME_CORRECT(p, ttype)						\	if ((p)->type == ttype && (p)->flags == F_LESSTHAN)		\		++((p)->t_data);/* * -atime n functions -- * *	True if the difference between the file access time and the *	current time is n 24 hour periods. */intf_atime(plan, entry)	PLAN *plan;	FTSENT *entry;{	extern time_t now;	COMPARE((now - entry->fts_statp->st_atime +	    SECSPERDAY - 1) / SECSPERDAY, plan->t_data);} PLAN *c_atime(arg)	char *arg;{	PLAN *new;	ftsoptions &= ~FTS_NOSTAT;	new = palloc(N_ATIME, f_atime);	new->t_data = find_parsenum(new, "-atime", arg, NULL);	TIME_CORRECT(new, N_ATIME);	return (new);}/* * -ctime n functions -- * *	True if the difference between the last change of file *	status information and the current time is n 24 hour periods. */intf_ctime(plan, entry)	PLAN *plan;	FTSENT *entry;{	extern time_t now;	COMPARE((now - entry->fts_statp->st_ctime +	    SECSPERDAY - 1) / SECSPERDAY, plan->t_data);} PLAN *c_ctime(arg)	char *arg;{	PLAN *new;	ftsoptions &= ~FTS_NOSTAT;	new = palloc(N_CTIME, f_ctime);	new->t_data = find_parsenum(new, "-ctime", arg, NULL);	TIME_CORRECT(new, N_CTIME);	return (new);}/* * -depth functions -- * *	Always true, causes descent of the directory hierarchy to be done *	so that all entries in a directory are acted on before the directory *	itself. */intf_always_true(plan, entry)	PLAN *plan;	FTSENT *entry;{	return (1);} PLAN *c_depth(){	isdepth = 1;	return (palloc(N_DEPTH, f_always_true));} /* * [-exec | -ok] utility [arg ... ] ; functions -- * *	True if the executed utility returns a zero value as exit status. *	The end of the primary expression is delimited by a semicolon.  If *	"{}" occurs anywhere, it gets replaced by the current pathname. *	The current directory for the execution of utility is the same as *	the current directory when the find utility was started. * *	The primary -ok is different in that it requests affirmation of the *	user before executing the utility. */intf_exec(plan, entry)	register PLAN *plan;	FTSENT *entry;{	extern int dotfd;	register int cnt;	pid_t pid;	int status;	for (cnt = 0; plan->e_argv[cnt]; ++cnt)		if (plan->e_len[cnt])			brace_subst(plan->e_orig[cnt], &plan->e_argv[cnt],			    entry->fts_path, plan->e_len[cnt]);	if (plan->flags == F_NEEDOK && !queryuser(plan->e_argv))		return (0);	switch (pid = vfork()) {	case -1:		err(1, "fork");		/* NOTREACHED */	case 0:		if (fchdir(dotfd)) {			warn("chdir");			_exit(1);		}		execvp(plan->e_argv[0], plan->e_argv);		warn("%s", plan->e_argv[0]);		_exit(1);	}	pid = waitpid(pid, &status, 0);	return (pid != -1 && WIFEXITED(status) && !WEXITSTATUS(status));} /* * c_exec -- *	build three parallel arrays, one with pointers to the strings passed *	on the command line, one with (possibly duplicated) pointers to the *	argv array, and one with integer values that are lengths of the *	strings, but also flags meaning that the string has to be massaged. */PLAN *c_exec(argvp, isok)	char ***argvp;	int isok;{	PLAN *new;			/* node returned */	register int cnt;	register char **argv, **ap, *p;	isoutput = 1;    	new = palloc(N_EXEC, f_exec);	if (isok)		new->flags = F_NEEDOK;	for (ap = argv = *argvp;; ++ap) {		if (!*ap)			errx(1,			    "%s: no terminating \";\"", isok ? "-ok" : "-exec");		if (**ap == ';')			break;	}	cnt = ap - *argvp + 1;	new->e_argv = (char **)emalloc((u_int)cnt * sizeof(char *));	new->e_orig = (char **)emalloc((u_int)cnt * sizeof(char *));	new->e_len = (int *)emalloc((u_int)cnt * sizeof(int));	for (argv = *argvp, cnt = 0; argv < ap; ++argv, ++cnt) {		new->e_orig[cnt] = *argv;		for (p = *argv; *p; ++p)			if (p[0] == '{' && p[1] == '}') {				new->e_argv[cnt] = emalloc((u_int)MAXPATHLEN);				new->e_len[cnt] = MAXPATHLEN;				break;			}		if (!*p) {			new->e_argv[cnt] = *argv;			new->e_len[cnt] = 0;		}	}	new->e_argv[cnt] = new->e_orig[cnt] = NULL;	*argvp = argv + 1;	return (new);} /* * -follow functions -- * *	Always true, causes symbolic links to be followed on a global *	basis. */PLAN *c_follow(){	ftsoptions &= ~FTS_PHYSICAL;	ftsoptions |= FTS_LOGICAL;	return (palloc(N_FOLLOW, f_always_true));} /* * -fstype functions -- * *	True if the file is of a certain type. */intf_fstype(plan, entry)	PLAN *plan;	FTSENT *entry;{	static dev_t curdev;	/* need a guaranteed illegal dev value */	static int first = 1;	struct statfs sb;	static short val;	char *p, save[2];	/* Only check when we cross mount point. */	if (first || curdev != entry->fts_statp->st_dev) {		curdev = entry->fts_statp->st_dev;		/*		 * Statfs follows symlinks; find wants the link's file system,		 * not where it points.		 */		if (entry->fts_info == FTS_SL ||		    entry->fts_info == FTS_SLNONE) {			if ((p = strrchr(entry->fts_accpath, '/')) != NULL)				++p;			else				p = entry->fts_accpath;			save[0] = p[0];			p[0] = '.';			save[1] = p[1];			p[1] = '\0';					} else 			p = NULL;		if (statfs(entry->fts_accpath, &sb))			err(1, "%s", entry->fts_accpath);		if (p) {			p[0] = save[0];			p[1] = save[1];		}		first = 0;		switch (plan->flags) {		case F_MTFLAG:			val = sb.f_flags;			break;		case F_MTTYPE:			val = sb.f_type;			break;		default:			abort();		}	}	switch(plan->flags) {	case F_MTFLAG:		return (val & plan->mt_data);		case F_MTTYPE:		return (val == plan->mt_data);	default:		abort();	}} PLAN *c_fstype(arg)	char *arg;{	register PLAN *new;    	ftsoptions &= ~FTS_NOSTAT;    	new = palloc(N_FSTYPE, f_fstype);	switch (*arg) {	case 'l':		if (!strcmp(arg, "local")) {			new->flags = F_MTFLAG;			new->mt_data = MNT_LOCAL;			return (new);		}		break;	case 'm':		if (!strcmp(arg, "mfs")) {			new->flags = F_MTTYPE;			new->mt_data = MOUNT_MFS;			return (new);		}		break;	case 'n':		if (!strcmp(arg, "nfs")) {			new->flags = F_MTTYPE;			new->mt_data = MOUNT_NFS;			return (new);		}		break;	case 'p':		if (!strcmp(arg, "msdos")) {			new->flags = F_MTTYPE;			new->mt_data = MOUNT_MSDOS;			return (new);		}		break;	case 'r':		if (!strcmp(arg, "rdonly")) {			new->flags = F_MTFLAG;			new->mt_data = MNT_RDONLY;			return (new);		}		break;	case 'u':		if (!strcmp(arg, "ufs")) {			new->flags = F_MTTYPE;			new->mt_data = MOUNT_UFS;			return (new);		}		break;	}	errx(1, "%s: unknown file type", arg);	/* NOTREACHED */} /* * -group gname functions -- * *	True if the file belongs to the group gname.  If gname is numeric and *	an equivalent of the getgrnam() function does not return a valid group *	name, gname is taken as a group ID. */intf_group(plan, entry)	PLAN *plan;	FTSENT *entry;{	return (entry->fts_statp->st_gid == plan->g_data);} PLAN *c_group(gname)	char *gname;{	PLAN *new;	struct group *g;	gid_t gid;    	ftsoptions &= ~FTS_NOSTAT;	g = getgrnam(gname);	if (g == NULL) {		gid = atoi(gname);		if (gid == 0 && gname[0] != '0')			errx(1, "-group: %s: no such group", gname);	} else		gid = g->gr_gid;    	new = palloc(N_GROUP, f_group);	new->g_data = gid;	return (new);}/* * -inum n functions -- * *	True if the file has inode # n. */intf_inum(plan, entry)	PLAN *plan;	FTSENT *entry;{	COMPARE(entry->fts_statp->st_ino, plan->i_data);} PLAN *c_inum(arg)	char *arg;{	PLAN *new;    	ftsoptions &= ~FTS_NOSTAT;    	new = palloc(N_INUM, f_inum);	new->i_data = find_parsenum(new, "-inum", arg, NULL);	return (new);} /* * -links n functions -- * *	True if the file has n links. */intf_links(plan, entry)	PLAN *plan;	FTSENT *entry;{	COMPARE(entry->fts_statp->st_nlink, plan->l_data);} PLAN *c_links(arg)	char *arg;{	PLAN *new;

⌨️ 快捷键说明

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