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

📄 fverify.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
字号:
/* fverify.c * * Name:	fverify * Purpose:	Verify ULTRIX installation. * Usage:	fverify [-yn] <inventory *			-y quietly repair everything *			-n just report inconsistencies * *			Copyright (c) 1985, 1989 by *		Digital Equipment Corporation, Maynard, MA *			All rights reserved. *								 *	This software is furnished under a license and may be used and *	copied  only  in accordance with the terms of such license and *	with the  inclusion  of  the  above  copyright  notice.   This *	software  or  any  other copies thereof may not be provided or *	otherwise made available to any other person.  No title to and *	ownership of the software is hereby transferred.		 *								 *	The information in this software is subject to change  without *	notice  and should not be construed as a commitment by Digital *	Equipment Corporation.					 *								 *	Digital assumes no responsibility for the use  or  reliability *	of its software on equipment which is not supplied by Digital. * * Environment:	ULTRIX * Compile:	cc fverify.c getsum.c * Date:	1/11/84 * Author:	Alan Delorey * Remarks: *  Verifies the existence and attributes of files. *  It reads input lines(using scanf) from the inventory until EOF is reached. *  It calls lstat to get info about each file, and compares to master list. *  The master attributes file should be stdin. * *	HISTORY: *	001	ccb 	09-03-1985 *		Fix indirection bug preventing correct verification *		of directories and symbolic links. *		Increased performance in checksum(). *		Overall 25% performance increase. * *	002	ccb	1986.03.15 *		Add interactive repair, force repair, no repair. *		Add fast mode that ignores sizes and sums. *		Accelerate I/O. *		Stop repetitive checks for files hard linked together. *		Add mode checking for soft links and directories. *		Add time stamps for the output log. * *	003	ccb	1986.09.16 *		drop in code for interrupt handling *		drop in code for correction of symbolic links *		clean up informational messages. * *	004	04-apr-1989	ccb *		general cleanup *		quieter logging *		extensions: *			device support in inventories *			referent checking * *	005	29-apr-1989	ccb *		Lint. *	006	14-jun-1989	ccb *		add check for malloc return value when allocating storage *			directory queue entries * *	007	24-jul-1989	ccb *		inlcude sys/dir.h for setld.h *		more lint * *	008	16-aug-1989	ccb *		change method for inserting non-existent directories *		into the directory queue to use an alphabetizing insert *		routine from the Inv package. This fixes problems caused *		by unsorted inventories. * *	009 	13-Nov-1990	jps *		fverify -p addition * *	010	08-feb-1991	ech *		1) change path of fverifylog from ./usr/adm to ./var/adm. *		2) ignore verification errors on permissions of symbolic links. */#ifndef lintstatic	char *sccsid = "@(#)fverify.c	4.3	(ULTRIX)	2/21/91";#endif lint#include	<sys/param.h>#include	<sys/types.h>#include	<sys/stat.h>#include	<sys/file.h>#include	<sys/errno.h>#include	<sys/time.h>#include	<sys/dir.h>#include	<signal.h>#include	<string.h>#include	<stdio.h>#include	"setld.h"#define	VFYLOG	"./var/adm/fverifylog"		/* logfile */#define	PART(F)		( (F) & PARTIAL )#define	ISVOL(F)	( (F) & INVVOLATILE )#define S_ISLNK(F)      ( ((F) & S_IFMT) == S_IFLNK )/* command flag values*/#define	FIX	0x0001		/* fix all correctable problems */#define	ASK	0x0002		/* ask if problem should be fixed */#define PARTIAL	0x0004		/* partial verify, no volatile */#define	DEFAULT	(FIX|ASK)	/* default ask first, then fix */#define	UID	0#define	GID	1#define	PERMS	2extern errno;			/* errno(2) */extern char *sys_errlist[];	/* errno(2) *//* routine types */extern void	exit();		/* exit(3) *//* global types */char		buf[BUFSIZ];		/* generic buffer */int		errs;			/* error counter */int		fixed;			/* repair counter */FILE		*logfp;			/* logfile file pointer */int		pid;			/* process id, used for logging */char		*prog;			/* program name pointer */unsigned	flags = DEFAULT;	/* command flags */FILE		*ttyin;			/* input tty file pointer */FILE		*ttyout;		/* output tty file pointer */main(argc,argv)int argc;char *argv[];{	int		c;	/* option char from getopt(3) */	InvRecT		*mkq;	/* directories to be created */	InvT		*i;	/* inventory pointer */	InvRecT		*ip;	/* inventory record pointer */	unsigned	mask;	/* verification bits, used as shorthand */	InvRecT		*qp;	/* pointer for fresh ones */	InvRecT		*rp;	/* record pointer for file as found on disk */	(void) signal( SIGINT, SIG_IGN );	/* ignore keyboard interrupt */	(void) signal( SIGQUIT, SIG_IGN );	/* ignore keyboard quit */	prog = *argv;	/* get command flags */	while( (c = getopt( argc, argv, "npy" )) != EOF )	{		switch( c )		{		case 'n':			/* report only, no fixes */			flags &= ~(FIX|ASK);			break;		case 'p':			/* partial verify */			flags |= PARTIAL;			break;		case 'y':			/* fix everything, don't ask */			flags &= ~ASK;			break;		default:			(void) fprintf( stderr, "%s: usage: %s [-npy] < inventory\n",				prog, prog );			exit(1);		}	}	OpenLog();	/* start logging */	OpenTTY();	/* set up terminal access */	mkq = (InvRecT *) 0;	/* read lines and check file attributes */	i = InvInit( stdin );	for( fixed = errs = 0; (ip = InvRead(i)) != NULL; )	{		rp = FVerify( ip );		mask = ip->i_vflags;		if( mask & I_PATH )		{			/* file not in system. this is recoverable in the			 *  following cases:			 *  type d: directory, queue for later creation			 *  type s: symbolic link, stubbed.			 *  type p: fifo, stubbed.			 *  type l: hard link, stubbed.			*/			switch( ip->i_type )			{			case 'd':				/* directory, missing directories are queued				 *  for reconstruction later				*/				if( (qp = InvRecNew()) == NULL )				{					(void) sprintf( buf,						"%s: out of memory\n", prog );					Log( buf );					WriteTTY( buf );					exit(1);				}				(void) InvRecCopy( qp, ip );				mkq = InvRecInsertAlpha( mkq, qp );				break;			case 'l':			case 'p':			case 's':			default:				(void) sprintf( buf, "%s: cannot stat (%s)\n",					ip->i_path, sys_errlist[errno] );				Log( buf );				WriteTTY( buf );				++errs;			}			continue;		}		if( mask & I_TYPE )		{			(void) sprintf( buf,				"%s: file type '%c' should be '%c'\n",				ip->i_path, rp->i_type, ip->i_type );			Log( buf );			WriteTTY( buf );			++errs;		}		if( !PART(flags) || (PART(flags) && !ISVOL(ip->i_flags)) )		{			if( mask & I_SUM )			{				(void) sprintf( buf,					"%s: checksum %05u should be %05u\n",					ip->i_path, rp->i_sum, ip->i_sum );				Log( buf );				WriteTTY( buf );				++errs;			}			if( mask & I_SIZE )			{				(void) sprintf( buf,					"%s: size %d should be %d\n",					ip->i_path, rp->i_size, ip->i_size );				Log( buf );				WriteTTY( buf );				++errs;			}		}		if( mask & I_GID )		{			(void) sprintf( buf, "%s: gid %d should be %d\n",				ip->i_path, rp->i_gid, ip->i_gid );			Fix( GID, ip, rp );		}		if( mask & I_UID )		{			(void) sprintf( buf, "%s: uid %d should be %d\n",				ip->i_path, rp->i_uid, ip->i_uid );			Fix( UID, ip, rp );		}		if( mask & I_PERM )		{			char	ps1[11];						/* permissions differences on symbolic links are 			   ignored because permissions on symbolic links are			   meaningless and actually depend on the permissions			   of the files linked to */  			if( !S_ISLNK( ip->i_mode ) )                        {				/* establish private copy of one of the permissions			 	*  strings to avoid static overwrite				*/				(void) strcpy( ps1, PermString( ip->i_mode ) );				(void) sprintf( buf,					"%s: permissions %s should be %s\n",					ip->i_path, PermString( rp->i_mode ), ps1 );				Fix( PERMS, ip, rp );			}		}	}	/* attempt to create directories queued from lstat failure */	(void) umask(0);	for( qp = mkq; qp != (InvRecT *) 0; qp = qp->i_next )	{		(void) sprintf( buf, "\tCreating directory %s\n", qp->i_path);		Log( buf );		WriteTTY( buf );		/* attempt to create directory		*/		if( mkdir( qp->i_path, (int) qp->i_mode ) )		{			(void) sprintf( buf, "\tCannot create dir %s (%s)\n",				qp->i_path, sys_errlist[errno] );			++errs;			Log( buf );			WriteTTY( buf );		}		else		{			/*! should perform error checking */			(void) chown( qp->i_path, qp->i_uid, qp->i_gid );			(void) chmod( qp->i_path, (int) qp->i_mode);		}	}	Exit();}/*	Exit() - *		log exit information and exit*/Exit(){	long	t;	(void) sprintf(buf,"\t%d %s\n\t%d %s\n", errs,		"verification errors encountered.", fixed,		"corrections performed.");	WriteTTY(buf);	Log(buf);		(void) sprintf( buf, "%s%d end logging at %s\n", prog, pid,			asctime( localtime( ((void) time(&t),&t) ) ) );	Log( buf );	exit(errs-fixed);}/*	Fix() - *		fix a problem * *	given:	int code - problem code in [UID,GID,PERM] *		InvRecT *p - inventory record *		InvRecT *q - file snapshot *	does:	fixes the problem with the file *	return:	nothing *	effect:	will increment global int fixed if fix was made*/Fix( code, p, q )int code;InvRecT *p;InvRecT *q;{	int		FixUid(), FixGid(), FixPerm();	static int	(*ftab[])() = { FixUid, FixGid, FixPerm };	++errs;	Log( buf );	WriteTTY( buf );	if( ShouldFix() )	{		if( (*ftab[code]) ( p, q ) )		{			/* something went wrong			*/			(void) sprintf( buf, "\tcannot correct %s (%s)\n",				p->i_path, sys_errlist[errno] );		}		else		{			/* OK			*/			(void) sprintf( buf, "\t%s corrected.\n", p->i_path );			++fixed;		}		Log( buf );		WriteTTY( buf );	}}/*	FixGid() - *		gid is wrong, do something * *	given:	InvRecT *p - pointer to inventory record from input *		InvRecT *q - inventory record created from checking the state *			of the file on the disk *	does:	fix the gid if the user wants it fixed *	return:	nothing*/FixGid(p, q)InvRecT *p, *q;{	if( chown( p->i_path, q->i_uid, p->i_gid ) )		return(-1);	q->i_gid = p->i_gid;	/* update reality */	return(0);}/*	FixPerm() - *		permission modes are wrong, do something * *	given:	InvRecT *p - pointer to the inventory record from input *		InvRecT *q - unused. present to keep lint quiet because of *			calling sequence in Fix(). *	does:	fix permissions *	return:	0 if successful, -1 otherwise*//*ARGSUSED*/FixPerm( p, q )InvRecT *p;InvRecT *q;{	u_short	perms;	/* mode bits to be used */	int	n;	/* index for readlink(2) */	perms = PERM( p->i_mode );	if( !chmod( p->i_path, (int) perms ) )		return(0);	return(-1);}/*	FixUid() - *		uid is wrong, do something * *	given:	InvRecT *p - pointer to the inventory record from input *		InvRecT *q - inventory record generated when checking the *			state of the file on the disk *	does:	fix the uid if the user wants it fixed *	return:	nothing*/FixUid( p, q )InvRecT *p, *q;{	if( chown( p->i_path, p->i_uid, q->i_gid ) )		return(-1);	q->i_uid = p->i_uid;	/* update reality */	return(0);}/*	Log() - *		write entry to logfile * *	given:	char *p - pointer to a buffer to be logged *	does:	write the buffer to the logfile *	return:	nothing*/Log(p)char *p;{	(void) fputs( p, logfp );}/*	OpenTTY() *		get terminal to talk to * *	given:	nothing, uses global flags *	does:	if ASK, open /dev/tty for interaction with user *	return:	nothing, may exit if terminal interaction is not possible*/OpenTTY(){	ttyout = stderr;	if( !(flags&ASK) )	{	/* tty access unnecessary */		return;	}	if( (ttyin = fopen("/dev/tty", "r")) == NULL )	{		(void) fprintf( stderr, "%s: cannot open /dev/tty (%s)\n",			prog, sys_errlist[errno] );		exit(1);	}	if( (flags&ASK) && !isatty( fileno(ttyout) ) )	{		/* fverify is supposed to ask but can't.		 *  disable prompts and fixes.		*/		(void) sprintf( buf,			"error output is not a tty, fixes disabled\n", prog );		Log( buf );		WriteTTY( buf );		flags &= ~(FIX|ASK);	}}/*	OpenLog() *		open the logfile * *	given:	nothing *	does:	opens a channel to the logfile and writes an initial *		entry *	return: nothing*/OpenLog(){	long	t;	/* for use with ctime(3) */	if( freopen( VFYLOG, "a", stdout) == (FILE *) 0 )	{		(void) fprintf(stderr, "%s: cannot open log file (%s)\n",			prog, sys_errlist[errno]);		errno=0;	}	logfp = stdout;	pid = getpid();	(void) sprintf( buf, "%s%d (%x) begin logging at %s\n", prog, pid,		flags, asctime( localtime( ((void) time(&t),&t) ) ) );	Log( buf );}/*	WriteTTY() - *		write a buffer to the terminal * *	given:	char *p - a pointer to the buffer to be written *	does:	puts the buffer on the terminal output stream *	return:	nothing*/WriteTTY(p)char *p;{	(void) fputs( p, ttyout );}/*	ShouldFix() - *		determine if a discrepancy should be fixed * *	given:	uses global flags *	does:	determines if fix is needed based on flags and/or user input *	return:	1 if fix is needed, 0 if not. *		may exit program on user input.*/ShouldFix(){	char	*cp;	/* user input token pointer */	if( (flags & (FIX|ASK)) == (FIX|ASK) )	{		/* interactive fixing */		for( ;; )		{			WriteTTY( "Fix (y/n/q) [n]? " );			(void) fgets( buf, sizeof(buf), ttyin );			/* elide begining spaces */			if( (cp = strtok( buf, "\t " )) == NULL || *cp == 'n' ||				*cp == 'N' || *cp == '\n' )			{				/* no or default assumed				*/				return(0);			}			else if( *cp == 'q' || *cp == 'Q' )			{				/* user wants out				*/				Exit();			}			else if( *cp == 'Y' || *cp == 'y' )			{				/* fix it */				return( 1 );			}			/* invalid input, go back to top of the loop			*/		}	}	/* non-interactive, return fix flag value */	return( flags & FIX );}/*END*/

⌨️ 快捷键说明

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