|
|
1.1 root 1: /* virec.c */
2:
3: /* This file contains the file recovery program */
4:
5: /* Author:
6: * Steve Kirkendall
7: * 16820 SW Tallac Way
8: * Beaverton, OR 97006
9: * [email protected], or ...uunet!tektronix!psueea!jove!kirkenda
10: */
11:
12:
13: #include "config.h"
14: #include <stdio.h>
15: #include <ctype.h>
16: #include "vi.h"
17: #if TOS
18: # include <stat.h>
19: #else
20: # if OSK
21: # include "osk.h"
22: # else
23: # include <sys/stat.h>
24: # endif
25: #endif
26:
27: extern char *getenv();
28: struct stat stbuf;
29: BLK hdr;
30: BLK text;
31:
32: /* the name of the directory where tmp files are stored. */
33: char o_directory[30] = TMPDIR;
34:
35: char *progname;
36:
37: main(argc, argv)
38: int argc;
39: char **argv;
40: {
41: char *tmp;
42: void recover();
43: #if MSDOS || TOS
44: char **wildexpand();
45: argv = wildexpand(&argc, argv);
46: #endif
47: progname = argv[0];
48: /* set the o_directory variable */
49: if ((tmp = getenv("TMP")) /* yes, ASSIGNMENT! */
50: || (tmp = getenv("TEMP"))) /* yes, ASSIGNMENT! */
51: {
52: strcpy(o_directory, tmp);
53: }
54: if (argc >= 3 && !strcmp(argv[1], "-d"))
55: {
56: strcpy(o_directory, argv[2]);
57: argc -= 2;
58: argv += 2;
59: }
60: /* process the arguments */
61: if (argc < 2)
62: {
63: /* maybe stdin comes from a file? */
64: if (isatty(0))
65: {
66: fprintf(stderr, "usage: %s [-d tmpdir] lostfile...\n", progname);
67: }
68: else if (read(0, &hdr, (unsigned)BLKSIZE) != BLKSIZE)
69: {
70: fprintf(stderr, "couldn't get header\n");
71: }
72: else
73: {
74: copytext(0, stdout);
75: }
76: }
77: else
78: {
79: while (--argc > 0)
80: {
81: recover(*++argv);
82: }
83: }
84: exit(0);
85: }
86:
87:
88: /* This function recovers a single file */
89: void recover(filename)
90: char *filename;
91: {
92: char tmpname[100];
93: int tmpfd;
94: FILE *fp;
95: long mtime;
96: int i, j;
97: int sum; /* used for calculating a checksum for this */
98: char *scan;
99:
100: /* get the file's status info */
101: if (stat(filename, &stbuf) < 0)
102: {
103: /* if serious error, give up on this file */
104: if (errno != ENOENT)
105: {
106: perror(filename);
107: return;
108: }
109:
110: /* else fake it for a new file */
111: stat(".", &stbuf);
112: #if OSK
113: stbuf.st_mode = S_IREAD;
114: #else
115: stbuf.st_mode = S_IFREG;
116: #endif
117: stbuf.st_mtime = 0L;
118: }
119:
120: /* generate a checksum from the file's name */
121: for (sum = 0, scan = filename + strlen(filename);
122: --scan >= filename && (isascii(*scan) && isalnum(*scan) || *scan == '.');
123: sum = sum + *scan)
124: {
125: }
126: sum &= 0xf;
127:
128: /* find the tmp file */
129: #if MSDOS || TOS
130: /* MS-Dos doesn't allow multiple slashes, but supports drives
131: * with current directories.
132: * This relies on TMPNAME beginning with "%s\\"!!!!
133: */
134: strcpy(tmpname, o_directory);
135: if ((i = strlen(tmpname)) && !strchr(":/\\", tmpname[i-1]))
136: tmpname[i++]=SLASH;
137: sprintf(tmpname+i, TMPNAME+3, sum, stbuf.st_ino, stbuf.st_dev);
138: #else
139: sprintf(tmpname, TMPNAME, o_directory, sum, stbuf.st_ino, stbuf.st_dev);
140: #endif
141: tmpfd = open(tmpname, O_RDONLY | O_BINARY);
142: if (tmpfd < 0)
143: {
144: perror(tmpname);
145: return;
146: }
147:
148: /* make sure the file hasn't been modified more recently */
149: mtime = stbuf.st_mtime;
150: fstat(tmpfd, &stbuf);
151: if (stbuf.st_mtime < mtime)
152: {
153: printf("\"%s\" has been modified more recently than its recoverable version\n", filename);
154: puts("Do you still want to recover it?\n");
155: puts("\ty - Yes, discard the current version and recover it.\n");
156: puts("\tn - No, discard the recoverable version and keep the current version\n");
157: puts("\tq - Quit without doing anything for this file.\n");
158: puts("Enter y, n, or q --> ");
159: fflush(stdout);
160: for (;;)
161: {
162: switch (getchar())
163: {
164: case 'y':
165: case 'Y':
166: goto BreakBreak;
167:
168: case 'n':
169: case 'N':
170: close(tmpfd);
171: unlink(tmpname);
172: return;
173:
174: case 'q':
175: case 'Q':
176: close(tmpfd);
177: return;
178: }
179: }
180: BreakBreak:;
181: }
182:
183: /* make sure this tmp file is intact */
184: if (read(tmpfd, &hdr, (unsigned)BLKSIZE) != BLKSIZE)
185: {
186: fprintf(stderr, "%s: bad header in tmp file\n", filename);
187: close(tmpfd);
188: unlink(tmpname);
189: return;
190: }
191: for (i = j = 1; i < MAXBLKS && hdr.n[i]; i++)
192: {
193: if (hdr.n[i] > j)
194: {
195: j = hdr.n[i];
196: }
197: }
198: lseek(tmpfd, (long)j * (long)BLKSIZE, 0);
199: if (read(tmpfd, &text, (unsigned)BLKSIZE) != BLKSIZE)
200: {
201: fprintf(stderr, "%s: bad data block in tmp file\n", filename);
202: close(tmpfd);
203: unlink(tmpname);
204: return;
205: }
206:
207: /* open the normal text file for writing */
208: fp = fopen(filename, "w");
209: if (!fp)
210: {
211: perror(filename);
212: close(tmpfd);
213: return;
214: }
215:
216: /* copy the text */
217: copytext(tmpfd, fp);
218:
219: /* cleanup */
220: close(tmpfd);
221: fclose(fp);
222: unlink(tmpname);
223: }
224:
225:
226: /* This function moves text from the tmp file to the normal file */
227: copytext(tmpfd, fp)
228: int tmpfd; /* fd of the tmp file */
229: FILE *fp; /* the stream to write it to */
230: {
231: int i;
232:
233: /* write the data blocks to the normal text file */
234: for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
235: {
236: lseek(tmpfd, (long)hdr.n[i] * (long)BLKSIZE, 0);
237: read(tmpfd, &text, (unsigned)BLKSIZE);
238: fputs(text.c, fp);
239: }
240: }
241:
242: #if MSDOS || TOS
243: #define WILDCARD_NO_MAIN
244: #include "wildcard.c"
245: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.