📄 dumper.c
字号:
{ (void)unused; /* Quiet unused parameter warning */ assert(unused == NULL); errstr = newstralloc(errstr, _("data timeout")); dump_result = 2; stop_dump();}/* * This is called when everything needs to shut down so event_loop() * will exit. */static voidstop_dump(void){ int i; for (i = 0; i < NSTREAMS; i++) { if (streams[i].fd != NULL) { security_stream_close(streams[i].fd); streams[i].fd = NULL; } } timeout(0);}/* * Runs compress with the first arg as its stdout. Returns * 0 on success or negative if error, and it's pid via the second * argument. The outfd arg is dup2'd to the pipe to the compress * process. */static intruncompress( int outfd, pid_t * pid, comp_t comptype){ int outpipe[2], rval; assert(outfd >= 0); assert(pid != NULL); /* outpipe[0] is pipe's stdin, outpipe[1] is stdout. */ if (pipe(outpipe) < 0) { errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno)); return (-1); } switch (*pid = fork()) { case -1: errstr = newvstrallocf(errstr, _("couldn't fork: %s"), strerror(errno)); aclose(outpipe[0]); aclose(outpipe[1]); return (-1); default: rval = dup2(outpipe[1], outfd); if (rval < 0) errstr = newvstrallocf(errstr, _("couldn't dup2: %s"), strerror(errno)); aclose(outpipe[1]); aclose(outpipe[0]); return (rval); case 0: if (dup2(outpipe[0], 0) < 0) { error(_("err dup2 in: %s"), strerror(errno)); /*NOTREACHED*/ } if (dup2(outfd, 1) == -1) { error(_("err dup2 out: %s"), strerror(errno)); /*NOTREACHED*/ } safe_fd(-1, 0); if (comptype != COMP_SERVER_CUST) { execlp(COMPRESS_PATH, COMPRESS_PATH, ( comptype == COMP_BEST ? COMPRESS_BEST_OPT : COMPRESS_FAST_OPT), (char *)NULL); error(_("error: couldn't exec %s: %s"), COMPRESS_PATH, strerror(errno)); /*NOTREACHED*/ } else if (*srvcompprog) { execlp(srvcompprog, srvcompprog, (char *)0); error(_("error: couldn't exec server custom filter%s.\n"), srvcompprog); /*NOTREACHED*/ } } /*NOTREACHED*/ return (-1);}/* * Runs encrypt with the first arg as its stdout. Returns * 0 on success or negative if error, and it's pid via the second * argument. The outfd arg is dup2'd to the pipe to the encrypt * process. */static intrunencrypt( int outfd, pid_t * pid, encrypt_t encrypttype){ int outpipe[2], rval; assert(outfd >= 0); assert(pid != NULL); /* outpipe[0] is pipe's stdin, outpipe[1] is stdout. */ if (pipe(outpipe) < 0) { errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno)); return (-1); } switch (*pid = fork()) { case -1: errstr = newvstrallocf(errstr, _("couldn't fork: %s"), strerror(errno)); aclose(outpipe[0]); aclose(outpipe[1]); return (-1); default: rval = dup2(outpipe[1], outfd); if (rval < 0) errstr = newvstrallocf(errstr, _("couldn't dup2: %s"), strerror(errno)); aclose(outpipe[1]); aclose(outpipe[0]); return (rval); case 0: if (dup2(outpipe[0], 0) < 0) { error(_("err dup2 in: %s"), strerror(errno)); /*NOTREACHED*/ } if (dup2(outfd, 1) < 0 ) { error(_("err dup2 out: %s"), strerror(errno)); /*NOTREACHED*/ } safe_fd(-1, 0); if ((encrypttype == ENCRYPT_SERV_CUST) && *srv_encrypt) { execlp(srv_encrypt, srv_encrypt, (char *)0); error(_("error: couldn't exec server encryption%s.\n"), srv_encrypt); /*NOTREACHED*/ } } /*NOTREACHED*/ return (-1);}/* -------------------- */static voidsendbackup_response( void * datap, pkt_t * pkt, security_handle_t * sech){ int ports[NSTREAMS], *response_error = datap, i; char *p; char *tok; char *extra; assert(response_error != NULL); assert(sech != NULL); if (pkt == NULL) { errstr = newvstrallocf(errstr, _("[request failed: %s]"), security_geterror(sech)); *response_error = 1; return; } security_close_connection(sech, hostname); extra = NULL; memset(ports, 0, SIZEOF(ports)); if (pkt->type == P_NAK) {#if defined(PACKET_DEBUG) g_fprintf(stderr, _("got nak response:\n----\n%s\n----\n\n"), pkt->body);#endif tok = strtok(pkt->body, " "); if (tok == NULL || strcmp(tok, "ERROR") != 0) goto bad_nak; tok = strtok(NULL, "\n"); if (tok != NULL) { errstr = newvstrallocf(errstr, "NAK: %s", tok); *response_error = 1; } else {bad_nak: errstr = newvstrallocf(errstr, "request NAK"); *response_error = 2; } return; } if (pkt->type != P_REP) { errstr = newvstrallocf(errstr, _("received strange packet type %s: %s"), pkt_type2str(pkt->type), pkt->body); *response_error = 1; return; } dbprintf(_("got response:\n----\n%s\n----\n\n"), pkt->body); for(i = 0; i < NSTREAMS; i++) { ports[i] = -1; streams[i].fd = NULL; } p = pkt->body; while((tok = strtok(p, " \n")) != NULL) { p = NULL; /* * Error response packets have "ERROR" followed by the error message * followed by a newline. */ if (strcmp(tok, "ERROR") == 0) { tok = strtok(NULL, "\n"); if (tok == NULL) tok = _("[bogus error packet]"); errstr = newvstrallocf(errstr, "%s", tok); *response_error = 2; return; } /* * Regular packets have CONNECT followed by three streams */ if (strcmp(tok, "CONNECT") == 0) { /* * Parse the three stream specifiers out of the packet. */ for (i = 0; i < NSTREAMS; i++) { tok = strtok(NULL, " "); if (tok == NULL || strcmp(tok, streams[i].name) != 0) { extra = vstrallocf( _("CONNECT token is \"%s\": expected \"%s\""), tok ? tok : "(null)", streams[i].name); goto parse_error; } tok = strtok(NULL, " \n"); if (tok == NULL || sscanf(tok, "%d", &ports[i]) != 1) { extra = vstrallocf( _("CONNECT %s token is \"%s\": expected a port number"), streams[i].name, tok ? tok : "(null)"); goto parse_error; } } continue; } /* * OPTIONS [options string] '\n' */ if (strcmp(tok, "OPTIONS") == 0) { tok = strtok(NULL, "\n"); if (tok == NULL) { extra = vstrallocf(_("OPTIONS token is missing")); goto parse_error; } while((p = strchr(tok, ';')) != NULL) { char ch; *p++ = '\0'; if(strncmp_const_skip(tok, "features=", tok, ch) == 0) { am_release_feature_set(their_features); if((their_features = am_string_to_feature(tok)) == NULL) { errstr = newvstrallocf(errstr, _("OPTIONS: bad features value: %s"), tok); goto parse_error; } } tok = p; } continue; } extra = vstrallocf(_("next token is \"%s\": expected \"CONNECT\", \"ERROR\" or \"OPTIONS\""), tok ? tok : "(null)"); goto parse_error; } if (dumper_kencrypt == KENCRYPT_WILL_DO) dumper_kencrypt = KENCRYPT_YES; /* * Connect the streams to their remote ports */ for (i = 0; i < NSTREAMS; i++) { if (ports[i] == -1) continue; streams[i].fd = security_stream_client(sech, ports[i]); if (streams[i].fd == NULL) { errstr = newvstrallocf(errstr, _("[could not connect %s stream: %s]"), streams[i].name, security_geterror(sech)); goto connect_error; } } /* * Authenticate the streams */ for (i = 0; i < NSTREAMS; i++) { if (streams[i].fd == NULL) continue;#ifdef KRB4_SECURITY /* * XXX krb4 historically never authenticated the index stream! * We need to reproduce this lossage here to preserve compatibility * with old clients. * It is wrong to delve into sech, but we have no choice here. */ if (strcasecmp(sech->driver->name, "krb4") == 0 && i == INDEXFD) continue;#endif if (security_stream_auth(streams[i].fd) < 0) { errstr = newvstrallocf(errstr, _("[could not authenticate %s stream: %s]"), streams[i].name, security_stream_geterror(streams[i].fd)); goto connect_error; } } /* * The MESGFD and DATAFD streams are mandatory. If we didn't get * them, complain. */ if (streams[MESGFD].fd == NULL || streams[DATAFD].fd == NULL) { errstr = newvstrallocf(errstr, _("[couldn't open MESG or INDEX streams]")); goto connect_error; } /* everything worked */ *response_error = 0; return;parse_error: errstr = newvstrallocf(errstr, _("[parse of reply message failed: %s]"), extra ? extra : _("(no additional information)")); amfree(extra); *response_error = 2; return;connect_error: stop_dump(); *response_error = 1;}static char *dumper_get_security_conf( char * string, void * arg){ (void)arg; /* Quiet unused parameter warning */ if(!string || !*string) return(NULL); if(strcmp(string, "krb5principal")==0) { return(getconf_str(CNF_KRB5PRINCIPAL)); } else if(strcmp(string, "krb5keytab")==0) { return(getconf_str(CNF_KRB5KEYTAB)); } else if(strcmp(string, "amandad_path")==0) { return (amandad_path); } else if(strcmp(string, "client_username")==0) { return (client_username); } else if(strcmp(string, "ssh_keys")==0) { return (ssh_keys); } else if(strcmp(string, "kencrypt")==0) { if (dumper_kencrypt == KENCRYPT_YES) return ("yes"); else return (NULL); } return(NULL);}static intstartup_dump( const char *hostname, const char *disk, const char *device, int level, const char *dumpdate, const char *progname, const char *amandad_path, const char *client_username, const char *ssh_keys, const char *options){ char level_string[NUM_STR_SIZE]; char *req = NULL; char *authopt, *endauthopt, authoptbuf[80]; int response_error; const security_driver_t *secdrv; char *backup_api; int has_features; int has_hostname; int has_device; int has_config; (void)disk; /* Quiet unused parameter warning */ (void)amandad_path; /* Quiet unused parameter warning */ (void)client_username; /* Quiet unused parameter warning */ (void)ssh_keys; /* Quiet unused parameter warning */ has_features = am_has_feature(their_features, fe_req_options_features); has_hostname = am_has_feature(their_features, fe_req_options_hostname); has_config = am_has_feature(their_features, fe_req_options_config); has_device = am_has_feature(their_features, fe_sendbackup_req_device); /* * Default to bsd authentication if none specified. This is gross. * * Options really need to be pre-parsed into some sort of structure * much earlier, and then flattened out again before transmission. */ authopt = strstr(options, "auth="); if (authopt == NULL) { authopt = "BSD"; } else { endauthopt = strchr(authopt, ';'); if ((endauthopt == NULL) || ((sizeof(authoptbuf) - 1) < (size_t)(endauthopt - authopt))) { authopt = "BSD"; } else { authopt += strlen("auth="); strncpy(authoptbuf, authopt, (size_t)(endauthopt - authopt)); authoptbuf[endauthopt - authopt] = '\0'; authopt = authoptbuf; } } g_snprintf(level_string, SIZEOF(level_string), "%d", level); if(strcmp(progname, "DUMP") == 0 || strcmp(progname, "GNUTAR") == 0) { backup_api = ""; } else { backup_api = "BACKUP "; } req = vstralloc("SERVICE sendbackup\n", "OPTIONS ", has_features ? "features=" : "", has_features ? our_feature_string : "", has_features ? ";" : "", has_hostname ? "hostname=" : "", has_hostname ? hostname : "", has_hostname ? ";" : "", has_config ? "config=" : "", has_config ? config_name : "", has_config ? ";" : "", "\n", backup_api, progname, " ", qdiskname, " ", device && has_device ? device : "", " ", level_string, " ", dumpdate, " OPTIONS ", options, /* compat: if auth=krb4, send krb4-auth */ (strcasecmp(authopt, "krb4") ? "" : "krb4-auth"), "\n", NULL); dbprintf(_("send request:\n----\n%s\n----\n\n"), req); secdrv = security_getdriver(authopt); if (secdrv == NULL) { errstr = newvstrallocf(errstr, _("[could not find security driver '%s']"), authopt); amfree(req); return 2; } protocol_sendreq(hostname, secdrv, dumper_get_security_conf, req, STARTUP_TIMEOUT, sendbackup_response, &response_error); amfree(req); protocol_run(); return (response_error);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -