200 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			200 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* elvrec.c */
 | 
						|
 | 
						|
/* This file contains the file recovery program */
 | 
						|
 | 
						|
/* Author:
 | 
						|
 *	Steve Kirkendall
 | 
						|
 *	14407 SW Teal Blvd. #C
 | 
						|
 *	Beaverton, OR 97005
 | 
						|
 *	kirkenda@cs.pdx.edu
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include "config.h"
 | 
						|
#include "vi.h"
 | 
						|
#include <sys/stat.h>
 | 
						|
 | 
						|
void recover(basename, outname)
 | 
						|
	char	*basename;	/* the name of the file to recover */
 | 
						|
	char	*outname;	/* the name of the file to write to */
 | 
						|
{
 | 
						|
	char	pathname[500];	/* full pathname of the file to recover */
 | 
						|
	char	line[600];	/* a line from the /usr/preserve/Index file */
 | 
						|
	int	ch;		/* a character from the text being recovered */
 | 
						|
	FILE	*from;		/* the /usr/preserve file, or /usr/preserve/Index */
 | 
						|
	FILE	*to;		/* the user's text file */
 | 
						|
	char	*ptr;
 | 
						|
	struct stat st;
 | 
						|
#if OSK
 | 
						|
	int		uid;
 | 
						|
#endif
 | 
						|
 | 
						|
	/* convert basename to a full pathname */
 | 
						|
	if (basename)
 | 
						|
	{
 | 
						|
#ifndef CRUNCH
 | 
						|
# if MSDOS || TOS
 | 
						|
		if (!basename[0] || basename[1] != ':')
 | 
						|
# else
 | 
						|
		if (basename[0] != SLASH)
 | 
						|
# endif
 | 
						|
		{
 | 
						|
			ptr = getcwd(pathname, sizeof pathname);
 | 
						|
			if (ptr != pathname)
 | 
						|
			{
 | 
						|
				strcpy(pathname, ptr);
 | 
						|
			}
 | 
						|
			ptr = pathname + strlen(pathname);
 | 
						|
			*ptr++ = SLASH;
 | 
						|
			strcpy(ptr, basename);
 | 
						|
		}
 | 
						|
		else
 | 
						|
#endif
 | 
						|
		{
 | 
						|
			strcpy(pathname, basename);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
#if OSK
 | 
						|
	uid = getuid();
 | 
						|
	if(setuid(0))
 | 
						|
		exit(_errmsg(errno, "Can't set uid\n"));
 | 
						|
#endif
 | 
						|
	/* scan the /usr/preserve/Index file, for the *oldest* unrecovered
 | 
						|
	 * version of this file.
 | 
						|
	 */
 | 
						|
	from = fopen(PRSVINDEX, "r");
 | 
						|
	while (from && fgets(line, sizeof line, from))
 | 
						|
	{
 | 
						|
		/* strip off the newline from the end of the string */
 | 
						|
		line[strlen(line) - 1] = '\0';
 | 
						|
 | 
						|
		/* parse the line into a "preserve" name and a "text" name */
 | 
						|
		for (ptr = line; *ptr != ' '; ptr++)
 | 
						|
		{
 | 
						|
		}
 | 
						|
		*ptr++ = '\0';
 | 
						|
 | 
						|
		/* If the "preserve" file is missing, then ignore this line
 | 
						|
		 * because it describes a file that has already been recovered.
 | 
						|
		 */
 | 
						|
		if (stat(line, &st) < 0)
 | 
						|
		{
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
 | 
						|
		/* are we looking for a specific file? */
 | 
						|
		if (basename)
 | 
						|
		{
 | 
						|
			/* quit if we found it */
 | 
						|
			if (!strcmp(ptr, pathname))
 | 
						|
			{
 | 
						|
				break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			/* list this file as "available for recovery" */
 | 
						|
			puts(ptr);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* file not found? */
 | 
						|
	if (!basename || !from || feof(from))
 | 
						|
	{
 | 
						|
		if (from != NULL) fclose(from);
 | 
						|
		if (basename)
 | 
						|
		{
 | 
						|
			fprintf(stderr, "%s: no recovered file has that exact name\n", pathname);
 | 
						|
		}
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	if (from != NULL) fclose(from);
 | 
						|
 | 
						|
	/* copy the recovered text back into the user's file... */
 | 
						|
 | 
						|
	/* open the /usr/preserve file for reading */
 | 
						|
	from = fopen(line, "r");
 | 
						|
	if (!from)
 | 
						|
	{
 | 
						|
		perror(line);
 | 
						|
		exit(2);
 | 
						|
	}
 | 
						|
 | 
						|
#if ANY_UNIX
 | 
						|
	/* Be careful about user-id.  We want to be running under the user's
 | 
						|
	 * real id when we open/create the user's text file... but we want
 | 
						|
	 * to be superuser when we delete the /usr/preserve file.  For UNIX,
 | 
						|
	 * we accomplish this by deleting the /usr/preserve file *now*,
 | 
						|
	 * when it is open but before we've read it.  Then we revert to the
 | 
						|
	 * user's real id.
 | 
						|
	 */
 | 
						|
	unlink(line);
 | 
						|
	setuid(getuid());
 | 
						|
#endif
 | 
						|
#if OSK
 | 
						|
	setuid(uid);
 | 
						|
#endif
 | 
						|
 | 
						|
	if (outname == NULL) return;
 | 
						|
 | 
						|
	/* open the user's file for writing */
 | 
						|
	to = fopen(outname, "w");
 | 
						|
	if (!to)
 | 
						|
	{
 | 
						|
		perror(ptr);
 | 
						|
		exit(2);
 | 
						|
	}
 | 
						|
 | 
						|
	/* copy the text */
 | 
						|
	while ((ch = getc(from)) != EOF)
 | 
						|
	{
 | 
						|
		putc(ch, to);
 | 
						|
	}
 | 
						|
 | 
						|
#if !ANY_UNIX
 | 
						|
#if OSK
 | 
						|
	fclose(from);
 | 
						|
	setuid(0);
 | 
						|
#endif
 | 
						|
	/* delete the /usr/preserve file */
 | 
						|
	unlink(line);
 | 
						|
#if OSK
 | 
						|
	setuid(uid);
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
main(argc, argv)
 | 
						|
	int	argc;
 | 
						|
	char	**argv;
 | 
						|
{
 | 
						|
	/* check arguments */
 | 
						|
	if (argc > 3)
 | 
						|
	{
 | 
						|
		fprintf(stderr, "usage: %s [preserved_file [recovery_file]]\n", argv[0]);
 | 
						|
		exit(1);
 | 
						|
	}
 | 
						|
 | 
						|
	/* recover the requested file, or list recoverable files */
 | 
						|
	if (argc == 3)
 | 
						|
	{
 | 
						|
		/* recover the file, but write it to a different filename */
 | 
						|
		recover (argv[1], argv[2]);
 | 
						|
	}
 | 
						|
	else if (argc == 2)
 | 
						|
	{
 | 
						|
		/* recover the file */
 | 
						|
		recover(argv[1], argv[1]);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		/* list the recoverable files */
 | 
						|
		recover((char *)0, (char *)0);
 | 
						|
	}
 | 
						|
 | 
						|
	/* success! */
 | 
						|
	exit(0);
 | 
						|
}
 |