Ultrix-3.1/src/cmd/ipatch.c

Compare this file to the similar file:
Show the results in this format:


/**********************************************************************
 *   Copyright (c) Digital Equipment Corporation 1984, 1985, 1986.    *
 *   All Rights Reserved. 					      *
 *   Reference "/usr/src/COPYRIGHT" for applicable restrictions.      *
 **********************************************************************/

/*
 * ipatch - patch inodes
 *
 *	Written 11-12-80 by Bill Shannon - DEC
 *	based on ipatch by Tom Duff, converted to V7
 *	Modified for Unix/v7m 10-16-82 by Fred Canter
 *
 * Usage:
 *		/etc/ipatch dev inode
 *
 *		dev	- file system, i.e., /dev/rhp00
 *		inode	- inode number
 * Prompt:
 *		.
 *
 * Commands:
 *		q - quit
 *		p - print inode contents
 *		f - modify flags
 *		l - modify link count
 *		u - modify uid
 *		g - modify gid
 *		s - modify size
 *		a - modify addr (a naddr addr)
 *		w - write patched inode to file system
 *		! - shell escape (DOES NOT WORK !)
 *
 *	Only one inode may be patched/examined per ipatch execution.
 *
 *	Examining inodes may be done at will, HOWEVER patching can be
 *	very dangerous and must only be done on dismounted file systems.
 */
static char Sccsid[] = "@(#)ipatch.c 3.0 4/21/86";
#include <sys/param.h>	/* does not matter which one ! */
#include <sys/ino.h>
#include <sys/filsys.h>
#include <setjmp.h>
#include <signal.h>

struct filsys sb;

struct dinode *dp;

char buf[BSIZE];

#ifdef	UCB_NKB
#define	NADDR	7
#else
#define	NADDR	13
#endif	UCB_NKB

daddr_t i_addr[NADDR];

jmp_buf env;

int	ibo;
daddr_t block;
ino_t inum;
int rdonly;
int f;
int pflag;
char lastc;
char peekc = '\0';
getc(){
	if(peekc!='\0'){
		lastc=peekc;
		peekc='\0';
	}
	else if(read(0, &lastc, 1)!=1)
		lastc='\0';
	return(lastc);
}
endline(){
	register char c;
	while(any(c=getc(), " \t"));
	if(c=='p'){
		pflag++;
		while(any(c=getc(), " \t"));
	}
	if(c!='\n')
		error();
}
error(){
	printf("\7?\n");
	if(lastc!='\n')
		while(getc()!='\n');
	longjmp(env, 1);
}
any(ac, as)
char as[];
{
	register char c, *s;
	c=ac;
	s=as;
	while(*s)
		if(c == *s++)
			return(1);
	return(0);
}
intr(){
	signal(SIGINT, intr);
	lastc='\n'; /* cryptic */
	error();
}
main(argc, argv)
char *argv[];
{
	register j, i;
	int n;
	char c;
	int savintr, savquit;
	extern char *ctime();

	if(argc!=3){
		write(2,"arg count\n",10);
		exit(1);
	}
	if((f=open(argv[1],2))<0){
		if ((f = open(argv[1], 0)) < 0) {
			perror(argv[1]);
			exit(1);
		}
		rdonly++;
		write(2, "read only\n", 10);
	}
	lseek(f, (off_t)BSIZE, 0);
	if (read(f, (char *)&sb, sizeof sb) != sizeof sb) {
		perror("super block");
		exit(1);
	}
	if(!iget(inum=atoi(argv[2]))){
		write(2, "can't read inode\n", 16);
		exit(1);
	}
	setjmp(env);
	signal(SIGINT, intr);
	for(;;){
		write(2,".",1);
		while(any(c=getc(), " \t"));
		switch(c){
		default:
			error();
		case 'q':
			endline();
		case '\0':
			exit(0);
		case '\n':
			break;
		case 'e':
			i=rin();
			endline();
			if(iget(i))
				inum=i;
			else
				error();
			break;
		case '!':
/*
			savintr=signal(INTR, 1);
			savquit=signal(QUIT, 1);
			i=fork();
			if(i== -1)
				printf("Try again.\n");
			else if(i==0){
				execl("/bin/sh", "sh", "-t", 0);
				perror("/bin/sh");
				exit(1);
			}
			else{
				wait();
				printf("!\n");
				signal(INTR, savintr);
				signal(QUIT, savquit);
			}
*/
			break;
		case 'p':
			endline();
			pflag++;
			break;
		case 'f':
			i=rin();
			endline();
			dp->di_mode = i;
			break;
		case 'l':
			i=rin();
			endline();
			dp->di_nlink=i;
			break;
		case 'u':
			i=rin();
			endline();
			dp->di_uid=i;
			break;
		case 'g':
			i=rin();
			endline();
			dp->di_gid=i;
			break;
		case 's':
			i=rin();
			endline();
			dp->di_size = i;
			break;
		case 'a':
			n=rin();
			if (n < 0 || n >= NADDR)
				error();
			i=rin();
			endline();
			i_addr[n]=i;
			break;
		case 'w':
			endline();
			iput();
			break;
		}
		if(pflag){
			pflag=0;
			printf("\nFile System\tInode\tBlock\tOffset");
			printf("\n%s\t%u\t%D\t%d\n\n",argv[1],inum,block,ibo);
			printf("flags: %o links: %d uid: %d gid: %d  size: %ld (0%lo)\n",
				dp->di_mode, dp->di_nlink,
				dp->di_uid, dp->di_gid,
				dp->di_size,
				dp->di_size);
			printf("addr:\n");
			for(i=0;i<NADDR;i++)
				printf("%ld\t(0%lo)\n",i_addr[i],i_addr[i]);
			printf("accessed: %s", ctime(&dp->di_atime));
			printf("modified: %s",ctime(&dp->di_mtime));
			printf("created:  %s",ctime(&dp->di_ctime));
		}
	}
}
rin(){
	char c;
	register n, base;
	n=0;
	while(any(c=getc(), " \t"));
	if(c<'0' || c>'9'){
		peekc=c;
		error();
	}
	base=c=='0'?8:10;
	do
		n=n*base+c-'0';
	while('0'<=(c=getc()) && c<='9');
	peekc=c;
	return(n);
}
iget(inum)
{
	register nread;
	struct dinode *p;
	char *p1, *p2;
	int i;

	block = itod(inum);
	if(block>=sb.s_isize+2 || block<2)
		return(0);
	lseek(f, (off_t)(block*BSIZE), 0);
	if (read(f, buf, sizeof buf) != sizeof buf) {
		perror("iget");
		return(0);
	}
	p = (struct dinode *)buf;
	ibo = itoo(inum);
	p += ibo;
	dp = p;		/* save for later */
	p1 = (char *)i_addr;
	p2 = (char *)dp->di_addr;
	for(i=0; i<NADDR; i++) {
		*p1++ = *p2++;
		*p1++ = 0;
		*p1++ = *p2++;
		*p1++ = *p2++;
	}
	return(1);
}


iput()
{
	register char *p1, *p2;
	register int i;

	if (rdonly) {
		write(2, "read only\n", 10);
		return;
	}
	p1 = (char *)dp->di_addr;
	p2 = (char *)i_addr;
	for(i=0; i<NADDR; i++) {
		*p1++ = *p2++;
		if(*p2++ != 0)
			printf("iaddress > 2^24\n");
		*p1++ = *p2++;
		*p1++ = *p2++;
	}
	lseek(f, (off_t)(block*BSIZE), 0);
	if (write(f, buf, sizeof buf) != sizeof buf)
		write(2, "write error\n", 12);
}