📄 dumper.c
字号:
amfree(q); } else { do_dump(&db); /* try to clean up any defunct processes, since Amanda doesn't wait() for them explicitly */ while(waitpid(-1, NULL, WNOHANG)> 0); } amfree(amandad_path); amfree(client_username); break; default: if(cmdargs.argc >= 1) { q = squote(cmdargs.argv[1]); } else if(cmdargs.argc >= 0) { q = squote(cmdargs.argv[0]); } else { q = stralloc(_("(no input?)")); } putresult(BAD_COMMAND, "%s\n", q); amfree(q); break; } if (outfd != -1) aclose(outfd); } while(cmd != QUIT); am_release_feature_set(our_features); amfree(our_feature_string); amfree(errstr); amfree(dumper_timestamp); amfree(handle); amfree(hostname); amfree(qdiskname); amfree(diskname); amfree(device); amfree(dumpdate); amfree(progname); amfree(srvcompprog); amfree(clntcompprog); amfree(srv_encrypt); amfree(clnt_encrypt); amfree(srv_decrypt_opt); amfree(clnt_decrypt_opt); amfree(options); dbclose(); return (0); /* exit */}/* * Initialize a databuf. Takes a writeable file descriptor. */static voiddatabuf_init( struct databuf * db, int fd){ db->fd = fd; db->datain = db->dataout = db->datalimit = NULL; db->compresspid = -1; db->encryptpid = -1;}/* * Updates the buffer pointer for the input data buffer. The buffer is * written regardless of how much data is present, since we know we * are writing to a socket (to chunker) and there is no need to maintain * any boundaries. */static intdatabuf_write( struct databuf * db, const void * buf, size_t size){ db->buf = (char *)buf; db->datain = db->datalimit = db->buf + size; db->dataout = db->buf; return databuf_flush(db);}/* * Write out the buffer to chunker. */static intdatabuf_flush( struct databuf * db){ ssize_t written; /* * If there's no data, do nothing. */ if (db->dataout >= db->datain) { return 0; } /* * Write out the buffer */ written = fullwrite(db->fd, db->dataout, (size_t)(db->datain - db->dataout)); if (written > 0) { db->dataout += written; dumpbytes += (off_t)written; } if (dumpbytes >= (off_t)1024) { dumpsize += (dumpbytes / (off_t)1024); dumpbytes %= (off_t)1024; } if (written < 0) { errstr = squotef(_("data write: %s"), strerror(errno)); return -1; } db->datain = db->dataout = db->buf; return 0;}static int dump_result;static int status;#define GOT_INFO_ENDLINE (1 << 0)#define GOT_SIZELINE (1 << 1)#define GOT_ENDLINE (1 << 2)#define HEADER_DONE (1 << 3)static voidprocess_dumpeof(void){ /* process any partial line in msgbuf? !!! */ add_msg_data(NULL, 0); if(!ISSET(status, GOT_SIZELINE) && dump_result < 2) { /* make a note if there isn't already a failure */ g_fprintf(errf, _("? %s: strange [missing size line from sendbackup]\n"), get_pname()); if(errstr == NULL) { errstr = stralloc(_("missing size line from sendbackup")); } dump_result = max(dump_result, 2); } if(!ISSET(status, GOT_ENDLINE) && dump_result < 2) { g_fprintf(errf, _("? %s: strange [missing end line from sendbackup]\n"), get_pname()); if(errstr == NULL) { errstr = stralloc(_("missing end line from sendbackup")); } dump_result = max(dump_result, 2); }}/* * Parse an information line from the client. * We ignore unknown parameters and only remember the last * of any duplicates. */static voidparse_info_line( char *str){ static const struct { const char *name; char *value; size_t len; } fields[] = { { "BACKUP", file.program, SIZEOF(file.program) }, { "DUMPER", file.dumper, SIZEOF(file.dumper) }, { "RECOVER_CMD", file.recover_cmd, SIZEOF(file.recover_cmd) }, { "COMPRESS_SUFFIX", file.comp_suffix, SIZEOF(file.comp_suffix) }, { "SERVER_CUSTOM_COMPRESS", file.srvcompprog, SIZEOF(file.srvcompprog) }, { "CLIENT_CUSTOM_COMPRESS", file.clntcompprog, SIZEOF(file.clntcompprog) }, { "SERVER_ENCRYPT", file.srv_encrypt, SIZEOF(file.srv_encrypt) }, { "CLIENT_ENCRYPT", file.clnt_encrypt, SIZEOF(file.clnt_encrypt) }, { "SERVER_DECRYPT_OPTION", file.srv_decrypt_opt, SIZEOF(file.srv_decrypt_opt) }, { "CLIENT_DECRYPT_OPTION", file.clnt_decrypt_opt, SIZEOF(file.clnt_decrypt_opt) } }; char *name, *value; size_t i; if (strcmp(str, "end") == 0) { SET(status, GOT_INFO_ENDLINE); return; } name = strtok(str, "="); if (name == NULL) return; value = strtok(NULL, ""); if (value == NULL) return; for (i = 0; i < SIZEOF(fields) / SIZEOF(fields[0]); i++) { if (strcmp(name, fields[i].name) == 0) { strncpy(fields[i].value, value, fields[i].len - 1); fields[i].value[fields[i].len - 1] = '\0'; break; } }}static voidprocess_dumpline( const char * str){ char *buf, *tok; buf = stralloc(str); switch (*buf) { case '|': /* normal backup output line */ break; case '?': /* sendbackup detected something strange */ dump_result = max(dump_result, 1); break; case 's': /* a sendbackup line, just check them all since there are only 5 */ tok = strtok(buf, " "); if (tok == NULL || strcmp(tok, "sendbackup:") != 0) goto bad_line; tok = strtok(NULL, " "); if (tok == NULL) goto bad_line; if (strcmp(tok, "start") == 0) { break; } if (strcmp(tok, "size") == 0) { tok = strtok(NULL, ""); if (tok != NULL) { origsize = OFF_T_ATOI(tok); SET(status, GOT_SIZELINE); } break; } if (strcmp(tok, "end") == 0) { SET(status, GOT_ENDLINE); break; } if (strcmp(tok, "warning") == 0) { dump_result = max(dump_result, 1); break; } if (strcmp(tok, "error") == 0) { SET(status, GOT_ENDLINE); dump_result = max(dump_result, 2); tok = strtok(NULL, ""); if (tok == NULL || *tok != '[') { errstr = newvstrallocf(errstr, _("bad remote error: %s"), str); } else { char *enderr; tok++; /* skip over '[' */ if ((enderr = strchr(tok, ']')) != NULL) *enderr = '\0'; errstr = newstralloc(errstr, tok); } break; } if (strcmp(tok, "info") == 0) { tok = strtok(NULL, ""); if (tok != NULL) parse_info_line(tok); break; } /* else we fall through to bad line */ default:bad_line: /* prefix with ?? */ g_fprintf(errf, "??"); dump_result = max(dump_result, 1); break; } g_fprintf(errf, "%s\n", str); amfree(buf);}static voidadd_msg_data( const char * str, size_t len){ static struct { char *buf; /* buffer holding msg data */ size_t size; /* size of alloced buffer */ } msg = { NULL, 0 }; char *line, *ch; size_t buflen; if (msg.buf != NULL) buflen = strlen(msg.buf); else buflen = 0; /* * If our argument is NULL, then we need to flush out any remaining * bits and return. */ if (str == NULL) { if (buflen == 0) return; g_fprintf(errf,_("? %s: error [partial line in msgbuf: %zu bytes]\n"), get_pname(), buflen); g_fprintf(errf,_("? %s: error [partial line in msgbuf: \"%s\"]\n"), get_pname(), msg.buf); msg.buf[0] = '\0'; return; } /* * Expand the buffer if it can't hold the new contents. */ if ((buflen + len + 1) > msg.size) { char *newbuf; size_t newsize;/* round up to next y, where y is a power of 2 */#define ROUND(x, y) (((x) + (y) - 1) & ~((y) - 1)) newsize = ROUND(buflen + (ssize_t)len + 1, 256); newbuf = alloc(newsize); if (msg.buf != NULL) { strncpy(newbuf, msg.buf, newsize); amfree(msg.buf); } else newbuf[0] = '\0'; msg.buf = newbuf; msg.size = newsize; } /* * If there was a partial line from the last call, then * append the new data to the end. */ strncat(msg.buf, str, len); /* * Process all lines in the buffer * scanning line for unqouted newline. */ for (ch = line = msg.buf; *ch != '\0'; ch++) { if (*ch == '\n') { /* * Found a newline. Terminate and process line. */ *ch = '\0'; process_dumpline(line); line = ch + 1; } } /* * If we did not process all of the data, move it to the front * of the buffer so it is there next time. */ if (*line != '\0') { buflen = strlen(line); memmove(msg.buf, line, (size_t)buflen + 1); } else { msg.buf[0] = '\0'; }}static voidlog_msgout( logtype_t typ){ char *line; fflush(errf); if (fseek(errf, 0L, SEEK_SET) < 0) { dbprintf(_("log_msgout: warning - seek failed: %s\n"), strerror(errno)); } while ((line = agets(errf)) != NULL) { if (line[0] != '\0') { log_add(typ, "%s", line); } amfree(line); } afclose(errf);}/* ------------- *//* * Fill in the rest of the tape header */static voidfinish_tapeheader( dumpfile_t *file){ assert(ISSET(status, HEADER_DONE)); file->type = F_DUMPFILE; strncpy(file->datestamp, dumper_timestamp, sizeof(file->datestamp) - 1); strncpy(file->name, hostname, SIZEOF(file->name) - 1); strncpy(file->disk, diskname, SIZEOF(file->disk) - 1); file->dumplevel = level; /* * If we're doing the compression here, we need to override what * sendbackup told us the compression was. */ if (srvcompress != COMP_NONE) { file->compressed = 1;#ifndef UNCOMPRESS_OPT#define UNCOMPRESS_OPT ""#endif if (srvcompress == COMP_SERVER_CUST) { g_snprintf(file->uncompress_cmd, SIZEOF(file->uncompress_cmd), " %s %s |", srvcompprog, "-d"); strncpy(file->comp_suffix, "cust", SIZEOF(file->comp_suffix) - 1); file->comp_suffix[SIZEOF(file->comp_suffix) - 1] = '\0'; strncpy(file->srvcompprog, srvcompprog, SIZEOF(file->srvcompprog) - 1); file->srvcompprog[SIZEOF(file->srvcompprog) - 1] = '\0'; } else if ( srvcompress == COMP_CUST ) { g_snprintf(file->uncompress_cmd, SIZEOF(file->uncompress_cmd), " %s %s |", clntcompprog, "-d"); strncpy(file->comp_suffix, "cust", SIZEOF(file->comp_suffix) - 1); file->comp_suffix[SIZEOF(file->comp_suffix) - 1] = '\0'; strncpy(file->clntcompprog, clntcompprog, SIZEOF(file->clntcompprog)); file->clntcompprog[SIZEOF(file->clntcompprog) - 1] = '\0'; } else { g_snprintf(file->uncompress_cmd, SIZEOF(file->uncompress_cmd), " %s %s |", UNCOMPRESS_PATH, UNCOMPRESS_OPT); strncpy(file->comp_suffix, COMPRESS_SUFFIX,SIZEOF(file->comp_suffix) - 1); file->comp_suffix[SIZEOF(file->comp_suffix) - 1] = '\0'; } } else { if (file->comp_suffix[0] == '\0') { file->compressed = 0; assert(SIZEOF(file->comp_suffix) >= 2); strncpy(file->comp_suffix, "N", SIZEOF(file->comp_suffix) - 1); file->comp_suffix[SIZEOF(file->comp_suffix) - 1] = '\0'; } else { file->compressed = 1; } } /* take care of the encryption header here */ if (srvencrypt != ENCRYPT_NONE) { file->encrypted= 1; if (srvencrypt == ENCRYPT_SERV_CUST) { g_snprintf(file->decrypt_cmd, SIZEOF(file->decrypt_cmd), " %s %s |", srv_encrypt, srv_decrypt_opt); strncpy(file->encrypt_suffix, "enc", SIZEOF(file->encrypt_suffix) - 1); file->encrypt_suffix[SIZEOF(file->encrypt_suffix) - 1] = '\0'; strncpy(file->srv_encrypt, srv_encrypt, SIZEOF(file->srv_encrypt) - 1); file->srv_encrypt[SIZEOF(file->srv_encrypt) - 1] = '\0'; strncpy(file->srv_decrypt_opt, srv_decrypt_opt, SIZEOF(file->srv_decrypt_opt) - 1); file->srv_decrypt_opt[SIZEOF(file->srv_decrypt_opt) - 1] = '\0'; } else if ( srvencrypt == ENCRYPT_CUST ) { g_snprintf(file->decrypt_cmd, SIZEOF(file->decrypt_cmd), " %s %s |", clnt_encrypt, clnt_decrypt_opt); strncpy(file->encrypt_suffix, "enc", SIZEOF(file->encrypt_suffix) - 1); file->encrypt_suffix[SIZEOF(file->encrypt_suffix) - 1] = '\0'; strncpy(file->clnt_encrypt, clnt_encrypt, SIZEOF(file->clnt_encrypt) - 1); file->clnt_encrypt[SIZEOF(file->clnt_encrypt) - 1] = '\0'; strncpy(file->clnt_decrypt_opt, clnt_decrypt_opt, SIZEOF(file->clnt_decrypt_opt)); file->clnt_decrypt_opt[SIZEOF(file->clnt_decrypt_opt) - 1] = '\0'; } } else { if (file->encrypt_suffix[0] == '\0') { file->encrypted = 0; assert(SIZEOF(file->encrypt_suffix) >= 2); strncpy(file->encrypt_suffix, "N", SIZEOF(file->encrypt_suffix) - 1); file->encrypt_suffix[SIZEOF(file->encrypt_suffix) - 1] = '\0'; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -