📄 sendbackup.c
字号:
error(_("error [opening mesg pipe: %s]"), s); } program->start_backup(g_options->hostname, disk, amdevice, level, dumpdate, datafd, mesgpipe[1], indexfd); dbprintf(_("Started backup\n")); parse_backup_messages(mesgpipe[0]); dbprintf(_("Parsed backup messages\n")); } amfree(prog); amfree(disk); amfree(qdisk); amfree(amdevice); amfree(qamdevice); amfree(dumpdate); amfree(stroptions); amfree(our_feature_string); am_release_feature_set(our_features); our_features = NULL; free_g_options(g_options); dbclose(); return 0; err: g_printf(_("FORMAT ERROR IN REQUEST PACKET\n")); dbprintf(_("REQ packet is bogus%s%s\n"), err_extra ? ": " : "", err_extra ? err_extra : ""); dbclose(); return 1;}/* * Returns a string for a child process. Checks the saved dump and * compress pids to see which it is. */char *childstr( pid_t pid){ if(pid == dumppid) return program->backup_name; if(pid == comppid) return "compress"; if(pid == encpid) return "encrypt"; if(pid == indexpid) return "index"; return "unknown";}/* * Determine if the child return status really indicates an error. * If so, add the error message to the error string; more than one * child can have an error. */intcheck_status( pid_t pid, amwait_t w){ char *thiserr = NULL; char *str, *strX; int ret, sig, rc; str = childstr(pid); if(WIFSIGNALED(w)) { ret = 0; rc = sig = WTERMSIG(w); } else { sig = 0; rc = ret = WEXITSTATUS(w); } if(pid == indexpid) { /* * Treat an index failure (other than signal) as a "STRANGE" * rather than an error so the dump goes ahead and gets processed * but the failure is noted. */ if(ret != 0) { g_fprintf(stderr, _("? index %s returned %d\n"), str, ret); rc = 0; } indexpid = -1; strX = "index "; } else if(pid == comppid) { /* * compress returns 2 sometimes, but it is ok. */#ifndef HAVE_GZIP if(ret == 2) { rc = 0; }#endif comppid = -1; strX = "compress "; } else if(pid == dumppid && tarpid == -1) { /* * Ultrix dump returns 1 sometimes, but it is ok. */#ifdef DUMP_RETURNS_1 if(ret == 1) { rc = 0; }#endif dumppid = -1; strX = "dump "; } else if(pid == tarpid) { if (ret == 1) { rc = 0; } /* * tar bitches about active filesystems, but we do not care. */#ifdef IGNORE_TAR_ERRORS if(ret == 2) { rc = 0; }#endif dumppid = tarpid = -1; strX = "dump "; } else { strX = "unknown "; } if(rc == 0) { return 0; /* normal exit */ } if(ret == 0) { thiserr = vstrallocf(_("%s (%d) %s got signal %d"), strX, (int)pid, str, sig); } else { thiserr = vstrallocf(_("%s (%d) %s returned %d"), strX, (int)pid, str, ret); } if(errorstr) { errorstr = newvstrallocf(errorstr, "%s, %s", errorstr, thiserr); amfree(thiserr); } else { errorstr = thiserr; thiserr = NULL; } return 1;}/* *Send header info to the message file. */voidinfo_tapeheader(void){ g_fprintf(stderr, "%s: info BACKUP=%s\n", get_pname(), program->backup_name); g_fprintf(stderr, "%s: info RECOVER_CMD=", get_pname()); if (options->compress == COMP_FAST || options->compress == COMP_BEST) g_fprintf(stderr, "%s %s |", UNCOMPRESS_PATH,#ifdef UNCOMPRESS_OPT UNCOMPRESS_OPT#else ""#endif ); g_fprintf(stderr, "%s -xpGf - ...\n", program->restore_name); if (options->compress == COMP_FAST || options->compress == COMP_BEST) g_fprintf(stderr, "%s: info COMPRESS_SUFFIX=%s\n", get_pname(), COMPRESS_SUFFIX); g_fprintf(stderr, "%s: info end\n", get_pname());}voidbackup_api_info_tapeheader( int mesgfd, char *prog, option_t *options){ char line[1024]; g_snprintf(line, 1024, "%s: info BACKUP=DUMPER\n", get_pname()); if (fullwrite(mesgfd, line, strlen(line)) != (ssize_t)strlen(line)) { dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno)); return; } g_snprintf(line, 1024, "%s: info DUMPER=%s\n", get_pname(), prog); if (fullwrite(mesgfd, line, strlen(line)) != (ssize_t)strlen(line)) { dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno)); return; } g_snprintf(line, 1024, "%s: info RECOVER_CMD=", get_pname()); if (fullwrite(mesgfd, line, strlen(line)) != (ssize_t)strlen(line)) { dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno)); return; } if (options->compress) { g_snprintf(line, 1024, "%s %s |", UNCOMPRESS_PATH,#ifdef UNCOMPRESS_OPT UNCOMPRESS_OPT#else ""#endif ); if (fullwrite(mesgfd, line, strlen(line)) != (ssize_t)strlen(line)) { dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno)); return; } } g_snprintf(line, 1024, "%s -f... -\n", prog); if (fullwrite(mesgfd, line, strlen(line)) != (ssize_t)strlen(line)) { dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno)); return; } if (options->compress) { g_snprintf(line, 1024, "%s: info COMPRESS_SUFFIX=%s\n", get_pname(), COMPRESS_SUFFIX); if (fullwrite(mesgfd, line, strlen(line)) != (ssize_t)strlen(line)) { dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno)); return; } } g_snprintf(line, 1024, "%s: info end\n", get_pname()); if (fullwrite(mesgfd, line, strlen(line)) != (ssize_t)strlen(line)) { dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno)); return; }}pid_tpipefork( void (*func)(void), char * fname, int * stdinfd, int stdoutfd, int stderrfd){ int inpipe[2]; pid_t pid; dbprintf(_("Forking function %s in pipeline\n"), fname); if(pipe(inpipe) == -1) { error(_("error [open pipe to %s: %s]"), fname, strerror(errno)); /*NOTREACHED*/ } switch(pid = fork()) { case -1: error(_("error [fork %s: %s]"), fname, strerror(errno)); /*NOTREACHED*/ default: /* parent process */ aclose(inpipe[0]); /* close input side of pipe */ *stdinfd = inpipe[1]; break; case 0: /* child process */ aclose(inpipe[1]); /* close output side of pipe */ if(dup2(inpipe[0], 0) == -1) { error(_("error [fork %s: dup2(%d, in): %s]"), fname, inpipe[0], strerror(errno)); /*NOTRACHED*/ } if(dup2(stdoutfd, 1) == -1) { error(_("error [fork %s: dup2(%d, out): %s]"), fname, stdoutfd, strerror(errno)); /*NOTRACHED*/ } if(dup2(stderrfd, 2) == -1) { error(_("error [fork %s: dup2(%d, err): %s]"), fname, stderrfd, strerror(errno)); /*NOTRACHED*/ } func(); exit(0); /*NOTREACHED*/ } return pid;}voidparse_backup_messages( int mesgin){ int goterror; pid_t wpid; amwait_t retstat; char *line; goterror = 0; amfree(errorstr); for(; (line = areads(mesgin)) != NULL; free(line)) { process_dumpline(line); } if(errno) { error(_("error [read mesg pipe: %s]"), strerror(errno)); /*NOTREACHED*/ } while((wpid = waitpid((pid_t)-1, &retstat, WNOHANG)) > 0) { if(check_status(wpid, retstat)) goterror = 1; } if (dumppid != -1) { sleep(5); while((wpid = waitpid((pid_t)-1, &retstat, WNOHANG)) > 0) { if(check_status(wpid, retstat)) goterror = 1; } } if (dumppid != -1) { dbprintf(_("Sending SIGHUP to dump process %d\n"), (int)dumppid); if(dumppid != -1) { if(kill(dumppid, SIGHUP) == -1) { dbprintf(_("Can't send SIGHUP to %d: %s\n"), (int)dumppid, strerror(errno)); } } sleep(5); while((wpid = waitpid((pid_t)-1, &retstat, WNOHANG)) > 0) { if(check_status(wpid, retstat)) goterror = 1; } } if (dumppid != -1) { dbprintf(_("Sending SIGKILL to dump process %d\n"), (int)dumppid); if(dumppid != -1) { if(kill(dumppid, SIGKILL) == -1) { dbprintf(_("Can't send SIGKILL to %d: %s\n"), (int)dumppid, strerror(errno)); } } sleep(5); while((wpid = waitpid((pid_t)-1, &retstat, WNOHANG)) > 0) { if(check_status(wpid, retstat)) goterror = 1; } } if(errorstr) { error(_("error [%s]"), errorstr); /*NOTREACHED*/ } else if(dump_size == -1) { error(_("error [no backup size line]")); /*NOTREACHED*/ } program->end_backup(goterror); g_fprintf(stderr, _("%s: size %ld\n"), get_pname(), dump_size); g_fprintf(stderr, _("%s: end\n"), get_pname());}/* * Returns the value of the first integer in a string. */doublethe_num( char * str, int pos){ char *num; int ch; double d; do { ch = *str++; while(ch && !isdigit(ch)) ch = *str++; if (pos == 1) break; pos--; while(ch && (isdigit(ch) || ch == '.')) ch = *str++; } while (ch); num = str - 1; while(isdigit(ch) || ch == '.') ch = *str++; str[-1] = '\0'; d = atof(num); str[-1] = (char)ch; return d;}static voidprocess_dumpline( char * str){ amregex_t *rp; char *type; char startchr; for(rp = program->re_table; rp->regex != NULL; rp++) { if(match(rp->regex, str)) { break; } } if(rp->typ == DMP_SIZE) { dump_size = (long)((the_num(str, rp->field)* rp->scale+1023.0)/1024.0); } switch(rp->typ) { case DMP_NORMAL: type = "normal"; startchr = '|'; break; case DMP_STRANGE: type = "strange"; startchr = '?'; break; case DMP_SIZE: type = "size"; startchr = '|'; break; case DMP_ERROR: type = "error"; startchr = '?'; break; default: /* * Should never get here. */ type = "unknown"; startchr = '!'; break; } dbprintf("%3d: %7s(%c): %s\n", rp->srcline, type, startchr, str); g_fprintf(stderr, "%c %s\n", startchr, str);}/* * start_index. Creates an index file from the output of dump/tar. * It arranges that input is the fd to be written by the dump process. * If createindex is not enabled, it does nothing. If it is not, a * new process will be created that tees input both to a pipe whose * read fd is dup2'ed input and to a program that outputs an index * file to `index'. * * make sure that the chat from restore doesn't go to stderr cause * this goes back to amanda which doesn't expect to see it * (2>/dev/null should do it) * * Originally by Alan M. McIvor, 13 April 1996 * * Adapted by Alexandre Oliva, 1 May 1997 * * This program owes a lot to tee.c from GNU sh-utils and dumptee.c * from the DeeJay backup package. */static voidsave_fd( int * fd, int min){ int origfd = *fd; while (*fd >= 0 && *fd < min) { int newfd = dup(*fd); if (newfd == -1) dbprintf(_("Unable to save file descriptor [%s]\n"), strerror(errno)); *fd = newfd; } if (origfd != *fd) dbprintf(_("Dupped file descriptor %i to %i\n"), origfd, *fd);}voidstart_index( int createindex, int input, int mesg, int index, char * cmd){ int pipefd[2]; FILE *pipe_fp; int exitcode; if (!createindex) return; if (pipe(pipefd) != 0) { error(_("creating index pipe: %s"), strerror(errno)); /*NOTREACHED*/ } switch(indexpid = fork()) { case -1: error(_("forking index tee process: %s"), strerror(errno)); /*NOTREACHED*/ default: aclose(pipefd[0]); if (dup2(pipefd[1], input) == -1) { error(_("dup'ping index tee output: %s"), strerror(errno)); /*NOTREACHED*/ } aclose(pipefd[1]); return; case 0: break; } /* now in a child process */ save_fd(&pipefd[0], 4); save_fd(&index, 4); save_fd(&mesg, 4); save_fd(&input, 4); dup2(pipefd[0], 0); dup2(index, 1); dup2(mesg, 2); dup2(input, 3); for(index = 4; index < (int)FD_SETSIZE; index++) { if (index != dbfd()) { close(index); } } if ((pipe_fp = popen(cmd, "w")) == NULL) { error(_("couldn't start index creator [%s]"), strerror(errno)); /*NOTREACHED*/ } dbprintf(_("Started index creator: \"%s\"\n"), cmd); while(1) { char buffer[BUFSIZ], *ptr; ssize_t bytes_read; size_t bytes_written; ssize_t just_written; do { bytes_read = read(0, buffer, SIZEOF(buffer)); } while ((bytes_read < 0) && ((errno == EINTR) || (errno == EAGAIN))); if (bytes_read < 0) { error(_("index tee cannot read [%s]"), strerror(errno)); /*NOTREACHED*/ } if (bytes_read == 0) break; /* finished */ /* write the stuff to the subprocess */ ptr = buffer; bytes_written = 0; just_written = fullwrite(fileno(pipe_fp), ptr, (size_t)bytes_read); if (just_written < 0) { /* * just as we waited for write() to complete. */ if (errno != EPIPE) { dbprintf(_("Index tee cannot write to index creator [%s]\n"), strerror(errno)); } } else { bytes_written += just_written; ptr += just_written; } /* write the stuff to stdout, ensuring none lost when interrupt occurs */ ptr = buffer; bytes_written = 0; just_written = fullwrite(3, ptr, (size_t)bytes_read); if (just_written < 0) { error(_("index tee cannot write [%s]"), strerror(errno)); /*NOTREACHED*/ } else { bytes_written += just_written; ptr += just_written; } } aclose(pipefd[1]); /* finished */ /* check the exit code of the pipe and moan if not 0 */ if ((exitcode = pclose(pipe_fp)) != 0) { char *exitstr = str_exit_status("Index pipe", exitcode); dbprintf("%s\n", exitstr); amfree(exitstr); } else { dbprintf(_("Index created successfully\n")); } pipe_fp = NULL; exit(exitcode);}extern backup_program_t dump_program, gnutar_program;backup_program_t *programs[] = { &dump_program, &gnutar_program, NULL};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -