📄 recover.c
字号:
}private char **scanvec(args, str)register char **args, *str;{ while (*args) { if (strcmp(*args, str) == 0) return args; args += 1; } return NULL;}private voidread_rec(recptr)struct rec_entry *recptr;{ if (fread((UnivPtr) recptr, sizeof *recptr, (size_t)1, ptrs_fp) != 1) fprintf(stderr, "recover: cannot read record.\n");}private voidseekto(which)int which;{ long offset; int i; offset = sizeof (Header) + (Header.Nbuffers * sizeof (struct rec_entry)); for (i = 1; i < which; i++) offset += buflist[i]->r_nlines * sizeof (daddr); fseek(ptrs_fp, offset, L_SET);}private voidmakblist(){ int i; fseek(ptrs_fp, (long) sizeof (Header), L_SET); for (i = 1; i <= Header.Nbuffers; i++) { if (buflist[i] == NULL) buflist[i] = (struct rec_entry *) malloc (sizeof (struct rec_entry)); read_rec(buflist[i]); } while (buflist[i]) { free((UnivPtr) buflist[i]); buflist[i] = NULL; i += 1; }}private daddrgetaddr(fp)register FILE *fp;{ register int nchars = sizeof (daddr); daddr addr; register char *cp = (char *) &addr; while (--nchars >= 0) *cp++ = getc(fp); return addr;}private voiddump_file(which, out)int which;FILE *out;{ register int nlines; register daddr addr; char buf[JBUFSIZ]; seekto(which); nlines = buflist[which]->r_nlines; Nchars = Nlines = 0L; while (--nlines >= 0) { addr = getaddr(ptrs_fp); getline(addr, buf); Nlines += 1; Nchars += 1 + strlen(buf); fputs(buf, out); if (nlines > 0) fputc('\n', out); }}/* List all the buffers. */private voidlist(){ int i; for (i = 1; i <= Header.Nbuffers; i++) printf("%d) buffer %s \"%s\" (%d lines)\n", i, buflist[i]->r_bname, buflist[i]->r_fname, buflist[i]->r_nlines);}private void ask_del proto((char *prompt, struct file_pair *fp));private intdoit(fp)struct file_pair *fp;{ char answer[30]; char *datafile = fp->file_data, *pntrfile = fp->file_rec; ptrs_fp = fopen(pntrfile, "r"); if (ptrs_fp == NULL) { if (Verbose) fprintf(stderr, "recover: cannot read rec file (%s).\n", pntrfile); return 0; } fread((UnivPtr) &Header, sizeof Header, (size_t)1, ptrs_fp); if (Header.Uid != UserID) return 0; /* Don't ask about JOVE's that are still running ... */#ifdef KILL0 if (kill(Header.Pid, 0) == 0) return 0;#endif /* KILL0 */ if (Header.Nbuffers == 0) { printf("There are no modified buffers in %s; should I delete the tmp file?", pntrfile); ask_del(" ", fp); return 1; } if (Header.Nbuffers < 0) { fprintf(stderr, "recover: %s doesn't look like a jove file.\n", pntrfile); ask_del("Should I delete it? ", fp); return 1; /* We'll, we sort of found something. */ } printf("Found %d buffer%s last updated: %s", Header.Nbuffers, Header.Nbuffers != 1 ? "s" : "", ctime(&Header.UpdTime)); data_fd = open(datafile, 0); if (data_fd == -1) { fprintf(stderr, "recover: but I can't read the data file (%s).\n", datafile); ask_del("Should I delete the tmp files? ", fp); return 1; } makblist(); list(); for (;;) { tellme("(Type '?' for options): ", answer); switch (answer[0]) { case '\0': continue; case '?': options(); break; case 'l': list(); break; case 'p': get(getsrc(), tty); break; case 'q': ask_del("Shall I delete the tmp files? ", fp); return 1; case 'g': { /* So it asks for src first. */ char *dest; struct rec_entry **src; if ((src = getsrc()) == NULL) break; dest = getdest(); get(src, dest); break; } case 'r': restore(); break; default: printf("I don't know how to \"%s\"!\n", answer); break; } }}private void del_files proto((struct file_pair *fp));private voidask_del(prompt, fp)char *prompt;struct file_pair *fp;{ char yorn[20]; tellme(prompt, yorn); if (yorn[0] == 'y') del_files(fp);}private voiddel_files(fp)struct file_pair *fp;{ (void) unlink(fp->file_data); (void) unlink(fp->file_rec);}private voidMailUser(rec)struct rec_head *rec;{#ifdef SYSV struct utsname mach;#else char mach[BUFSIZ];#endif char mail_cmd[BUFSIZ]; char *last_update; char *buf_string; FILE *mail_pipe; struct passwd *pw; if ((pw = getpwuid(rec->Uid))== NULL) return;#ifdef SYSV if (uname(&mach) < 0) strcpy(mach.sysname, "unknown");#else {#ifndef BSD386 extern int gethostname proto((const char *, size_t));#endif gethostname(mach, sizeof(mach)); }#endif last_update = ctime(&(rec->UpdTime)); /* Start up mail */ sprintf(mail_cmd, "/bin/mail %s", pw->pw_name); setuid(getuid()); if ((mail_pipe = popen(mail_cmd, "w")) == NULL) return; setbuf(mail_pipe, mail_cmd); /* Let's be grammatically correct! */ if (rec->Nbuffers == 1) buf_string = "buffer"; else buf_string = "buffers"; fprintf(mail_pipe, "Subject: System crash\n"); fprintf(mail_pipe, " \n"); fprintf(mail_pipe, "Jove saved %d %s when the system \"%s\"\n", rec->Nbuffers, buf_string,#ifdef SYSV mach.sysname#else mach#endif ); fprintf(mail_pipe, "crashed on %s\n\n", last_update); fprintf(mail_pipe, "You can retrieve the %s using Jove's -r\n", buf_string); fprintf(mail_pipe, "(recover option) i.e. give the command.\n"); fprintf(mail_pipe, "\tjove -r\n"); fprintf(mail_pipe, "See the Jove manual for more details\n"); pclose(mail_pipe);}private voidsavetmps(){ struct file_pair *fp; union wait status; int pid, fd; struct rec_head header; char buf[BUFSIZ]; char *fname; struct stat stbuf; if (strcmp(TMP_DIR, REC_DIR) == 0) return; /* Files are moved to the same place. */ get_files(TMP_DIR); for (fp = First; fp != NULL; fp = fp->file_next) { stat(fp->file_data, &stbuf); switch (pid = fork()) { case -1: fprintf(stderr, "recover: can't fork\n!"); exit(-1); /*NOTREACHED*/ case 0: fprintf(stderr, "Recovering: %s, %s\n", fp->file_data, fp->file_rec); if ((fd = open(fp->file_rec, 0)) != -1) { if ((read(fd, (UnivPtr) &header, sizeof header) != sizeof header)) { close(fd); return; } else close(fd); } MailUser(&header); execl("/bin/mv", "mv", fp->file_data, fp->file_rec, REC_DIR, (char *)NULL); fprintf(stderr, "recover: cannot execl /bin/mv.\n"); exit(-1); /*NOTREACHED*/ default: do ; while (wait(&status) != pid); if (status.w_status != 0) fprintf(stderr, "recover: non-zero status (%d) returned from copy.\n", status.w_status); fname = fp->file_data + strlen(TMP_DIR); strcpy(buf, REC_DIR); strcat(buf, fname); if (chown(buf, (int) stbuf.st_uid, (int) stbuf.st_gid) != 0) perror("recover: chown failed."); fname = fp->file_rec + strlen(TMP_DIR); strcpy(buf, REC_DIR); strcat(buf, fname); if (chown(buf, (int) stbuf.st_uid, (int) stbuf.st_gid) != 0) perror("recover: chown failed."); } }}private intlookup(dir)char *dir;{ struct file_pair *fp; int nfound = 0; printf("Checking %s ...\n", dir); Directory = dir; get_files(dir); for (fp = First; fp != NULL; fp = fp->file_next) { nfound += doit(fp); if (ptrs_fp) (void) fclose(ptrs_fp); if (data_fd > 0) (void) close(data_fd); } return nfound;}intmain(argc, argv)int argc;char *argv[];{ int nfound; char **argvp; char *tmp_dir; UserID = getuid(); if (scanvec(argv, "-help")) { printf("recover: usage: recover [-d directory] [-syscrash]\n"); printf("Use \"jove -r\" after JOVE has died for some\n"); printf("unknown reason.\n\n"); printf("Use \"%s -syscrash\"\n", Recover); printf("when the system is in the process of rebooting."); printf("This is done automatically at reboot time\n"); printf("and so most of you don't have to worry about that.\n\n"); printf("Use \"recover -d directory\" when the tmp files are store\n"); printf("in DIRECTORY instead of the default one (/tmp).\n"); exit(0); } if (scanvec(argv, "-v")) Verbose = YES; if (scanvec(argv, "-syscrash")) { printf("Recovering jove files ... "); savetmps(); printf("Done.\n"); exit(0); } if ((argvp = scanvec(argv, "-uid")) != NULL) UserID = atoi(argvp[1]); if ((argvp = scanvec(argv, "-d")) != NULL) tmp_dir = argvp[1]; else tmp_dir = TmpFilePath; /* Check default directory */ nfound = lookup(tmp_dir); /* Check whether anything was saved when system died? */ if (strcmp(tmp_dir, REC_DIR) != 0) nfound += lookup(REC_DIR); if (nfound == 0) printf("There's nothing to recover.\n"); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -