199 lines
3.8 KiB
C
199 lines
3.8 KiB
C
/* 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);
|
|
}
|