📄 full_backup.c
字号:
TypeUCharPTR }, { &identity, NULL, (UChar *) "^[ \t]*\\([Cc]lient[-_ \t]*\\)?[Ii]denti\\(ty\\|fier\\):?", TypeUCharPTR }, { &chksum, NULL, (UChar *) "^[ \t]*\\([Ww]rite\\)?[Cc]heck[-_ \t]*[Ss]um\\(s\\|ming\\)?:?", TypeFlag }, { &chk_perms, NULL, (UChar *) "^[ \t]*[Cc]heck[-_ \t]*[Rr]estore[-_ \t]*[Aa]ccess[-_ \t]*[Pp]ermi?s?s?i?o?n?s?:?", TypeFlag }, { &use_ctime, NULL, (UChar *) "^[ \t]*[Uu]se[-_ \t]*[Cc][-_ \t]*[Tt]ime:?", TypeFlag }, { &msgs_config_str, NULL, (UChar *) "^[ \t]*[Pp]rint[-_ \t]*[Ss]e?r?ve?r?[-_ \t]*[Mm]e?ss?a?ge?s?:?", TypeUCharPTR },};#define EM__(nmem) { nomemerrexit(nmem); }#define EEM__(nmem) { if(nmem) nomemerrexit(NULL); }#define ENM__ nomemerrexit(NULL)#define ER__(cmd, lerrfl) { if( (lerrfl = cmd) ) return(lerrfl); }#define repl_dirs(string) repl_substrings((string), dir_pat_repl, \ sizeof(dir_pat_repl) / sizeof(dir_pat_repl[0]))#define one_more_for_restore (restore_EM > 1 || restore_em > 1)static void verifybu(int, char **);static void restore(int, char **);static void restoreall(int, char **);static void restoreem(int, char **);static void copy_tape(int, char **);static Int32 get_args(int, char **);static Int32 get_restore_args(int, char **);static Int32 get_verify_args(int, char **);static Int32 get_copytape_args(int, char **);static Int32 get_update_indexes_args(int, char **);static Int32 get_backup_args(int, char **);static int get_arg_num(int, char **, Int32 *, Int8);static Int32 write_to_restore(UChar **, UChar **, Int32 *);static UChar *repl_substring_safe(UChar *, UChar *, UChar *);static Int32 get_tapepos(Int32 *, Int32 *, Int32 *, Int8, UChar *, Int32, UChar *);static Int32 get_streamerstate(StreamerStat *, UChar *, Int32, Flag);static Int32 read_header_line(UChar *, Int32 *, time_t *, Int32 *, UChar *, UChar *);static Int32 eval_index_line(UChar *, UChar **, Int32 *, Int32 *, Int32 *, int *, time_t *);static void compose_clntcmd(UChar *, UChar *, UChar *, UChar *, Int32, Int32, UChar *, Int32, Int32, time_t, time_t, Int32, UChar *);static Int32 add_server_id_entries(UChar *, ServerIdTab *, Int32);static ServerIdTab *get_server_id_entries(UChar *, Int32 *);static Int32 serverid_from_netaddr(ServerIdTab *, UChar *, Int32, UChar *);static Uns32Range *get_needed_tapes(UChar *, UChar *);static Int32 remove_needed_tapes(UChar *, UChar *, Uns32Range *);static Int32 remove_tapes_from_idxes(StreamerStat *, Int32, UChar *, Int32, Int32);static UChar *repl_fmts(UChar *, ReplSpec *, Int32, UChar *, time_t);static int open_idxfile_read(Int32, int *, UChar **, Flag);static voiddo_exit(int s){ int fd, i; if(locked == BU_GOT_LOCK){#if 0 /* unnecessary: close removes any lock */ lockb.l_type = F_UNLCK; fcntl(lockfd, F_SETLK, &lockb);#endif unlink(lockfile); close(lockfd); } if(interrupted) s = 128 + interrupted; if(exitprog && (mode == MODE_FULL_BACKUP || mode == MODE_INCR_BACKUP)){ sprintf(tmpbuf, "%d", s); if(reportfile) exitprog = repl_substring_safe(exitprog, "%r", reportfile); exitprog = repl_substring_safe(exitprog, "%e", tmpbuf); exitprog = repl_substring_safe(exitprog, "%i", minrestoreinfo ? minrestoreinfo : (UChar *) ""); exitprog = repl_substring_safe(exitprog, "%l", filelist ? (!access(filelist, R_OK) ? filelist : (UChar *) T_("<filename-logfile_not_yet_created>")) : (UChar *) T_("<filename-logfile_not_yet_determined>")); if(reportfile) if((fd = open(reportfile, O_WRONLY | O_APPEND | O_CREAT, 0644)) >= 0) close(fd); system(exitprog); } if(reportfile) if(reportfile[0]) unlink(reportfile); for(i = 0; i < 10; i++){ if(tmpfiles[i]){ unlink(tmpfiles[i]); free(tmpfiles[i]); } } exit(s);}static voidnomemerrexit(void * ptr){ if(!ptr){ fprintf(stderr, "Error: No memory.\n"); do_exit(3); }}static voiderrmsg(UChar * msg, ...){ FILE *lfp = NULL; va_list args; va_start(args, msg); if(logfile) if(strcmp(logfile, "-")) lfp = fopen(logfile, "a"); if(lfp){ fprintf(lfp, "%s, ", actimestr()); vfprintf(lfp, msg, args); fclose(lfp); } vfprintf(stderr, msg, args); va_end(args);}static voidlogmsg(UChar * msg, ...){ FILE *lfp = NULL; Flag si = NO; va_list args; va_start(args, msg); if(logfile){ if(!strcmp(logfile, "-")){ lfp = stdout; si = YES; } else lfp = fopen(logfile, "a"); } if(lfp){ fprintf(lfp, "%s, ", actimestr()); vfprintf(lfp, msg, args); if(!si) fclose(lfp); } if(verbose){ vfprintf(stdout, msg, args); } va_end(args);}UChar *repl_substring_safe(UChar * org, UChar * to_subst, UChar * subst_by){ UChar *newstr; EM__(newstr = repl_substring(org, to_subst, subst_by)); return(newstr);}Int32replace_if_pipe(UChar ** str, Int32 mode, Int32 level, Int32 part){ FILE *fp; UChar *newstr = NULL, *line = NULL, *sep, *newcmd = NULL; UChar typestr[30], *cptr; Int32 r = 0; if(strncmp(*str, "| ", 2)) return(0); typestr[0] = (mode == MODE_FULL_BACKUP ? 'F' : (level > 0 ? 'L' : 'I')); typestr[1] = '\0'; if(mode == MODE_INCR_BACKUP && level > 0) sprintf(typestr + 1, "%d", (int) level); if(mode == MODE_FULL_BACKUP && part > 0) sprintf(typestr + 1, "%d", (int) part); newcmd = repl_substring_safe(*str + 2, "%T", typestr); fp = popen(newcmd, "r"); if(!fp){ errmsg(T_("Cannot run command `%s'.\n"), *str + 2); CLEANUPR(-1); } sep = ""; EM__(newstr = strdup("")); while(!feof(fp)){ ZFREE(line); line = fget_alloc_str(fp); if(!line) continue; while(chop(line)); cptr = newstr; EM__(newstr = strchain(newstr, sep, line, NULL)); free(cptr); sep = " "; } ZFREE(*str); *str = newstr; newstr = NULL; cleanup: if(fp) pclose(fp); ZFREE(newcmd); ZFREE(newstr); ZFREE(line); return(r);}static voidusage(UChar * pname){ pname = FN_BASENAME(pname); switch(mode){ case MODE_RESTORE: if(curuid) fprintf(stderr, T_("Usage: %s [ -nltvmi ] [ -<past-backup-no> ] [ -C <root-directory> ] \\\n" " [ -h <backuphosts> ] [ -P <backup-ports> ] \\\n" " [ -A \"<after-date>\" ] [ -B \"<before-date>\" ] \\\n" " [ -k <encryption-key-file> ] [ -T <tapes> ] \\\n" " [ -z <process-cmd> <unprocess-cmd> ] \\\n" " [ -Z <built-in-compress-level> ] [ -F <format> ] \\\n" " [ { -N <num-indexfiles> | -O <indexfile-age-days> } ] \\\n" " [ -M <server-message-config> ] \\\n" " [ -p ] <path-pattern> [ [ -p ] <path-patterns> [ ... ] ]\n"), pname); else fprintf(stderr, T_("Usage: %s [ -nltvmi ] [ -<past-backup-no> ] [ -C <root-directory> ] \\\n" " [ -h <backuphosts> ] [ -P <backup-ports> ] \\\n" " [ -c <configuration-file> ] [ -W <identity> ] \\\n" " [ -I <indexfile-part> ] [ -V <var-directory> ] \\\n" " [ -A \"<after-date>\" ] [ -B \"<before-date>\" ] \\\n" " [ -k <encryption-key-file> ] [ -T <tapes> ] \\\n" " [ -z <process-cmd> <unprocess-cmd> ] \\\n" " [ -Z <built-in-compress-level> ] [ -F <format> ] \\\n" " [ -N <num-indexfiles> | -O <indexfile-age-days> ] \\\n" " [ -M <server-message-config> ] \\\n" " [ -p ] <path-pattern> [ [ -p ] <path-patterns> [ ... ] ]\n" " %s -a [ -nlvm ] [ -<past-backup-no> ] [ -C <root-directory> ] \\\n" " [ -h <backuphosts> ] [ -P <backup-ports> ] \\\n" " [ -c <configuration-file> ] [ -W <identity> ] \\\n" " [ -I <indexfile-part> ] [ -V <var-directory> ] \\\n" " [ -k <encryption-key-file> ] \\\n" " [ -z <process-cmd> <unprocess-cmd> ] \\\n" " [ -Z <built-in-compress-level> ] [ -F <format> ] \\\n" " [ -M <server-message-config> ]\n" " %s -{ef} [ -evm ] [ -C <root-directory> ] [ -h <backuphosts> ] \\\n" " [ -P <backup-ports> ] [ -V <var-directory> ] \\\n" " [ -z <process-cmd> <unprocess-cmd> ] \\\n" " [ -Z <built-in-compress-level> ] \\\n" " [ -k <encryption-key-file> ] [ -W <identity> ] \\\n" " [ -M <server-message-config> ] \\\n" " [ -c <configuration-file> ] < <startup-info-file>\n" " %s -E [ -Enlvm ] [ -C <root-directory> ] [ -h <backuphosts> ] \\\n" " [ -P <backup-ports> ] [ -V <var-directory> ] \\\n" " [ -z <process-cmd> <unprocess-cmd> ] \\\n" " [ -Z <built-in-compress-level> ] \\\n" " [ -k <encryption-key-file> ] [ -W <identity> ] \\\n" " [ -M <server-message-config> ] \\\n" " [ -c <configuration-file> ] \\\n" " [ <cartridge-number> | <cartridge-range> ] ... ]\n"), pname, pname, pname, pname); break; case MODE_UPDATE_INDEXES: if(curuid) fprintf(stderr, "%s: %s\n", T_("Usage"), pname); else fprintf(stderr, T_("Usage: %s [ -v ] [ -c <configuration-file> ] \\\n" " [ -h <backuphosts> ] [ -P <backup-ports> ] \\\n" " [ -I <indexfile-part> ] [ -V <var-directory> ] \\\n" " [ -k <encryption-key-file> ] [ -W <identity> ] \\\n" " [ -z <process-cmd> <unprocess-cmd> ] \\\n" " [ -Z <built-in-compress-level> ] \\\n"), pname); break; case MODE_VERIFYBU: fprintf(stderr, T_("Usage: %s [ -lav ] [ -c <configuration-file> ] \\\n" " [ -<past-run-no>[.<past-backup-no>] ] \\\n" " [ -h <backuphosts> ] [ -P <backup-ports> ] \\\n" " [ -C <root-directory> ] [ -S <cartridge-set> ] \\\n" " [ -I <indexfile-part> ] [ -V <var-directory> ] \\\n" " [ -k <encryption-key-file> ] [ -W <identity> ] \\\n" " [ -z <process-cmd> <unprocess-cmd> ] \\\n" " [ -Z <built-in-compress-level> ] \\\n" " [ -M <server-message-config> ]\n"), pname); break; case MODE_COPY_TAPE: fprintf(stderr, T_("Usage: %s [ -v ] [ -c <configuration-file> ] \\\n" " [ -l <logfile> ] [ -T <tmpdir> ] \\\n" " [ -M <server-message-config> ] \\\n" " [ -h <source-server> ] [ -P <source-serverport> ] \\\n" " [ -C <source-cartridge> ] [ -F <tape-filenumber> ] \\\n" " [ -k <source-encryption-key-file> ] \\\n" " [ -D [ -h <target-server> ] [ -P <target-serverport> ] \\\n" " [ -C <target-cartridge> ] [ -k <target-encryption-key-file> ] ]\n"), pname); break; default: fprintf(stderr, T_("Usage: %s [ -daG%s ] [ {+-}LBx ] [ <files> <directories> ... ] \\\n" " [ -C <root-directory> ] [ -F \"<files-to-skip>\" ] \\\n" " [ -D \"<directories-to-skip>\" ] \\\n" " [ -c <configuration-file> ] [ -W <identity> ] \\\n" " [ -h <backuphosts> ] [ -P <backup-ports> ] \\\n" " [ -I <indexfile-part> ] [ -Q <backup-level> ] \\\n" " [ { -N <num-indexes-to-store> ] | \\\n" " -O <max-age-of-indexes-to-store-in-days> } ] \\\n" " [ -z <process-cmd> <unprocess-cmd> ] \\\n" " [ -Z <built-in-compress-level> ] \\\n" " [ -s \"<dont-process-patterns>\" ] \\\n" " [ -X <exclude-list-file> ] [ -l <logfile> ] \\\n" " [ -i <startup-info-program> ] \\\n" " [ -b <init-program> ] [ -e <exit-program> ] \\\n" " [ -k <encryption-key-file> ] \\\n" " [ -f <filesystem-types> ] \\\n" " [ -V <var-directory> ] [ -S <cartridge-sets> ] \\\n" " [ -M <server-message-config> ]\n"), pname, mode == MODE_INCR_BACKUP ? "EH" : ""); } do_exit(1);}static voidsig_handler(int s){/* Ladies and Gentelmen, let me present you the superduper cracy heuristics * to find out, what should really be done on what signal. This is a little * like reading an operator's mind. Anyway let's have a try. */ static int num_int = 0; static time_t first_int = (time_t) 0; Flag hard_interrupt = NO, ttyinput; ttyinput = isatty(0); if(interrupted){ if(s == SIGINT && (mode == MODE_INCR_BACKUP || mode == MODE_FULL_BACKUP)){ /* Maybe stdio should be avoided within a signal handler, but the user * should be informed about what is going on. If it is not done here, * it can probably never be done from now on. This comment bases on * a hint from Davin Reade. I (AF) basically disagree on a 'must' * concerning avoiding stdio within signal handlers. If stdio must be * avoided, to be policital correct, any system call must be avoided */ if(num_int <= 0) first_int = time(NULL); num_int++; if(time(NULL) - first_int < 2){ if(num_int > 2){ fprintf(stderr, T_("Forced interruption, program will terminate as soon as possible.\n")); hard_interrupt = YES; } } else{ num_int = 0; } if(!hard_interrupt){ fprintf(stderr, T_( "Repeated interruption, please stand by during cleanup.\n" "To force termination press Ctrl-C 3 times within 2 seconds " "or Ctrl-\\ once.\n" )); } } else{ fprintf(stderr, T_("Repeated interruption, please stand by during cleanup.\n")); } if(!hard_interrupt) return; } if(mode != MODE_INCR_BACKUP && mode != MODE_FULL_BACKUP){ /* * At this point we are now using the default action for this particular * signal, due to the semantics of signal(2). */ kill(getpid(), s); do_exit(2); } if(s == SIGTERM || s == SIGABRT || s == SIGQUIT || (s == SIGINT && !ttyinput)) hard_interrupt = YES; if(hard_interrupt && clientpid > 0) kill(clientpid, SIGKILL); if(s != SIGPIPE){ signal(s, sig_handler); if(interrupted) return; fprintf(stderr, T_("Interrupted. Cleanup in progress, please stand by.\n")); } else{ if(!interrupted) errmsg(T_("Connection to client process lost, exiting.\n")); logf_lost = YES; } interrupted = s;}static voidexitcleanup(){ if(!keep_timestamp){ switch(mode){ case MODE_FULL_BACKUP: if(!access(orgoldmarkfile, R_OK)){ unlink(oldmarkfile); rename(orgoldmarkfile, oldmarkfile); } break; case MODE_INCR_BACKUP: unlink(newmarkfile); default: break; } }}static voidintrpt_exit(){ exitcleanup(); if(logfile){ switch(mode){ case MODE_FULL_BACKUP: if(numparts > 1) logmsg(T_("Full backup part %d interrupted.\n"), part); else logmsg(T_("Full backup interrupted.\n")); break; case MODE_INCR_BACKUP: logmsg(T_("Incremental backup interrupted.\n")); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -