📄 recover.c
字号:
SCR *sp; EXF *ep;{ if (ep->db->sync(ep->db, R_RECNOSYNC)) { F_CLR(ep, F_RCV_ON); msgq(sp, M_ERR, "Automatic file backup failed: %s: %s", ep->rcv_path, strerror(errno)); return (1); } return (0);}/* * rcv_hup -- * Recovery SIGHUP interrupt handler. (Modem line dropped, or * xterm window closed.) */voidrcv_hup(){ SCR *sp; /* * Walk the lists of screens, sync'ing the files; only sync * each file once. Send email to the user for each file saved. */ for (sp = __global_list->dq.cqh_first; sp != (void *)&__global_list->dq; sp = sp->q.cqe_next) rcv_syncit(sp, 1); for (sp = __global_list->hq.cqh_first; sp != (void *)&__global_list->hq; sp = sp->q.cqe_next) rcv_syncit(sp, 1); /* * Die with the proper exit status. Don't bother using * sigaction(2) 'cause we want the default behavior. */ (void)signal(SIGHUP, SIG_DFL); (void)kill(0, SIGHUP); /* NOTREACHED */ exit (1);}/* * rcv_term -- * Recovery SIGTERM interrupt handler. (Reboot or halt is running.) */voidrcv_term(){ SCR *sp; /* * Walk the lists of screens, sync'ing the files; only sync * each file once. */ for (sp = __global_list->dq.cqh_first; sp != (void *)&__global_list->dq; sp = sp->q.cqe_next) rcv_syncit(sp, 0); for (sp = __global_list->hq.cqh_first; sp != (void *)&__global_list->hq; sp = sp->q.cqe_next) rcv_syncit(sp, 0); /* * Die with the proper exit status. Don't bother using * sigaction(2) 'cause we want the default behavior. */ (void)signal(SIGTERM, SIG_DFL); (void)kill(0, SIGTERM); /* NOTREACHED */ exit (1);}/* * rcv_syncit -- * Sync the file, optionally send mail. */static voidrcv_syncit(sp, email) SCR *sp; int email;{ EXF *ep; char comm[1024]; if ((ep = sp->ep) == NULL || !F_ISSET(ep, F_MODIFIED) || !F_ISSET(ep, F_RCV_ON)) return; (void)ep->db->sync(ep->db, R_RECNOSYNC); F_SET(ep, F_RCV_NORM); /* * !!! * If you need to port this to a system that doesn't have sendmail, * the -t flag being used causes sendmail to read the message for * the recipients instead of us specifying them some other way. */ if (email) { (void)snprintf(comm, sizeof(comm), "%s -t < %s", _PATH_SENDMAIL, ep->rcv_mpath); (void)system(comm); } (void)file_end(sp, ep, 1);}/* * people making love * never exactly the same * just like a snowflake * * rcv_list -- * List the files that can be recovered by this user. */intrcv_list(sp) SCR *sp;{ struct dirent *dp; struct stat sb; DIR *dirp; FILE *fp; int found; char *p, file[1024]; if (chdir(O_STR(sp, O_RECDIR)) || (dirp = opendir(".")) == NULL) { (void)fprintf(stderr, "vi: %s: %s\n", O_STR(sp, O_RECDIR), strerror(errno)); return (1); } for (found = 0; (dp = readdir(dirp)) != NULL;) { if (strncmp(dp->d_name, "recover.", 8)) continue; /* If it's readable, it's recoverable. */ if ((fp = fopen(dp->d_name, "r")) == NULL) continue; /* If it's locked, it's live. */ if (flock(fileno(fp), LOCK_EX | LOCK_NB)) { (void)fclose(fp); continue; } /* Check the header, get the file name. */ if (fgets(file, sizeof(file), fp) == NULL || strncmp(file, VI_FHEADER, sizeof(VI_FHEADER) - 1) || (p = strchr(file, '\n')) == NULL) { (void)fprintf(stderr, "vi: %s: malformed recovery file.\n", dp->d_name); goto next; } *p = '\0'; /* Get the last modification time. */ if (fstat(fileno(fp), &sb)) { (void)fprintf(stderr, "vi: %s: %s\n", dp->d_name, strerror(errno)); goto next; } /* Display. */ (void)printf("%s: %s", file + sizeof(VI_FHEADER) - 1, ctime(&sb.st_mtime)); found = 1;next: (void)fclose(fp); } if (found == 0) (void)printf("vi: no files to recover.\n"); (void)closedir(dirp); return (0);}/* * rcv_read -- * Start a recovered file as the file to edit. */intrcv_read(sp, name) SCR *sp; char *name;{ struct dirent *dp; struct stat sb; DIR *dirp; FREF *frp; FILE *fp, *sv_fp; time_t rec_mtime; int found, requested; char *p, *t, *recp, *pathp; char recpath[MAXPATHLEN], file[MAXPATHLEN], path[MAXPATHLEN]; if ((dirp = opendir(O_STR(sp, O_RECDIR))) == NULL) { msgq(sp, M_ERR, "%s: %s", O_STR(sp, O_RECDIR), strerror(errno)); return (1); } sv_fp = NULL; rec_mtime = 0; recp = pathp = NULL; for (found = requested = 0; (dp = readdir(dirp)) != NULL;) { if (strncmp(dp->d_name, "recover.", 8)) continue; /* If it's readable, it's recoverable. */ (void)snprintf(recpath, sizeof(recpath), "%s/%s", O_STR(sp, O_RECDIR), dp->d_name); if ((fp = fopen(recpath, "r")) == NULL) continue; /* If it's locked, it's live. */ if (flock(fileno(fp), LOCK_EX | LOCK_NB)) { (void)fclose(fp); continue; } /* Check the headers. */ if (fgets(file, sizeof(file), fp) == NULL || strncmp(file, VI_FHEADER, sizeof(VI_FHEADER) - 1) || (p = strchr(file, '\n')) == NULL || fgets(path, sizeof(path), fp) == NULL || strncmp(path, VI_PHEADER, sizeof(VI_PHEADER) - 1) || (t = strchr(path, '\n')) == NULL) { msgq(sp, M_ERR, "%s: malformed recovery file.", recpath); goto next; } ++found; *t = *p = '\0'; /* Get the last modification time. */ if (fstat(fileno(fp), &sb)) { msgq(sp, M_ERR, "vi: %s: %s", dp->d_name, strerror(errno)); goto next; } /* Check the file name. */ if (strcmp(file + sizeof(VI_FHEADER) - 1, name)) goto next; ++requested; /* If we've found more than one, take the most recent. */ if (recp == NULL || rec_mtime < sb.st_mtime) { p = recp; t = pathp; if ((recp = strdup(recpath)) == NULL) { msgq(sp, M_ERR, "vi: Error: %s.\n", strerror(errno)); recp = p; goto next; } if ((pathp = strdup(path)) == NULL) { msgq(sp, M_ERR, "vi: Error: %s.\n", strerror(errno)); FREE(recp, strlen(recp) + 1); recp = p; pathp = t; goto next; } if (p != NULL) { FREE(p, strlen(p) + 1); FREE(t, strlen(t) + 1); } rec_mtime = sb.st_mtime; if (sv_fp != NULL) (void)fclose(sv_fp); sv_fp = fp; } elsenext: (void)fclose(fp); } (void)closedir(dirp); if (recp == NULL) { msgq(sp, M_INFO, "No files named %s, owned by you, to edit.", name); return (1); } if (found) { if (requested > 1) msgq(sp, M_INFO, "There are older versions of this file for you to recover."); if (found > requested) msgq(sp, M_INFO, "There are other files for you to recover."); } /* Create the FREF structure, start the btree file. */ if ((frp = file_add(sp, NULL, name, 0)) == NULL || file_init(sp, frp, pathp + sizeof(VI_PHEADER) - 1, 0)) { FREE(recp, strlen(recp) + 1); FREE(pathp, strlen(pathp) + 1); (void)fclose(sv_fp); return (1); } /* * We keep an open lock on the file so that the recover option can * distinguish between files that are live and those that need to * be recovered. The lock is already acquired, so just get a copy. */ if ((sp->ep->rcv_fd = dup(fileno(sv_fp))) != -1) (void)fclose(sv_fp); sp->ep->rcv_mpath = recp; /* We believe the file is recoverable. */ F_SET(sp->ep, F_RCV_ON); return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -