|
|
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.