📄 sendsize.c
字号:
/* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 1991-1998 University of Maryland at College Park * All Rights Reserved. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of U.M. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. U.M. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Authors: the Amanda Development Team. Its members are listed in a * file named AUTHORS, in the root directory of this distribution. *//* * $Id: sendsize.c,v 1.171 2006/08/24 01:57:15 paddy_s Exp $ * * send estimated backup sizes using dump */#include "amanda.h"#include "pipespawn.h"#include "amfeatures.h"#include "amandates.h"#include "clock.h"#include "util.h"#include "getfsent.h"#include "version.h"#include "client_util.h"#include "conffile.h"#include "amandad.h"#ifdef SAMBA_CLIENT#include "findpass.h"#endif#define sendsize_debug(i, ...) do { \ if ((i) <= debug_sebdsize) { \ dbprintf(__VA_ARGS__); \ } \} while (0)#ifdef HAVE_SETPGID# define SETPGRP setpgid(getpid(), getpid())# define SETPGRP_FAILED() do { \ dbprintf(_("setpgid(%ld,%ld) failed: %s\n"), \ (long)getpid(), (long)getpid(), strerror(errno)); \} while(0)#else /* () line 0 */#if defined(SETPGRP_VOID)# define SETPGRP setpgrp()# define SETPGRP_FAILED() do { \ dbprintf(_("setpgrp() failed: %s\n"), strerror(errno)); \} while(0)#else# define SETPGRP setpgrp(0, getpid())# define SETPGRP_FAILED() do { \ dbprintf(_("setpgrp(0,%ld) failed: %s\n"), \ (long)getpid(), strerror(errno)); \} while(0)#endif#endiftypedef struct level_estimates_s { time_t dumpsince; int estsize; int needestimate;} level_estimate_t;typedef struct disk_estimates_s { struct disk_estimates_s *next; char *amname; char *qamname; char *amdevice; char *qamdevice; char *dirname; char *qdirname; char *program; char *calcprog; int program_is_backup_api; int spindle; pid_t child; int done; option_t *options; level_estimate_t est[DUMP_LEVELS];} disk_estimates_t;disk_estimates_t *est_list;static am_feature_t *our_features = NULL;static char *our_feature_string = NULL;static g_option_t *g_options = NULL;/* local functions */int main(int argc, char **argv);void add_diskest(char *disk, char *amdevice, int level, int spindle, int program_is_backup_api, char *prog, char *calcprog, option_t *options);void calc_estimates(disk_estimates_t *est);void free_estimates(disk_estimates_t *est);void dump_calc_estimates(disk_estimates_t *);void star_calc_estimates(disk_estimates_t *);void smbtar_calc_estimates(disk_estimates_t *);void gnutar_calc_estimates(disk_estimates_t *);void backup_api_calc_estimate(disk_estimates_t *);void generic_calc_estimates(disk_estimates_t *);intmain( int argc, char ** argv){ int level, spindle; char *prog, *calcprog, *dumpdate; option_t *options = NULL; int program_is_backup_api; disk_estimates_t *est; disk_estimates_t *est1; disk_estimates_t *est_prev; char *line = NULL; char *s, *fp; int ch; char *err_extra = NULL; int done; int need_wait; int dumpsrunning; char *disk = NULL; char *qdisk = NULL; char *qlist = NULL; char *amdevice = NULL; char *qamdevice = NULL; char *amandates_file; int amandates_read = 0; (void)argc; /* Quiet unused parameter warning */ (void)argv; /* Quiet unused parameter warning */ /* initialize */ /* * Configure program for internationalization: * 1) Only set the message locale for now. * 2) Set textdomain for all amanda related programs to "amanda" * We don't want to be forced to support dozens of message catalogs. */ setlocale(LC_MESSAGES, "C"); textdomain("amanda"); safe_fd(-1, 0); safe_cd(); set_pname("sendsize"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG); dbopen(DBG_SUBDIR_CLIENT); startclock(); dbprintf(_("version %s\n"), version()); our_features = am_init_feature_set(); our_feature_string = am_feature_to_string(our_features); config_init(CONFIG_INIT_CLIENT, NULL); check_running_as(RUNNING_AS_CLIENT_LOGIN); /* handle all service requests */ for(; (line = agets(stdin)) != NULL; free(line)) { if (line[0] == '\0') continue; if(strncmp_const(line, "OPTIONS ") == 0) { g_options = parse_g_options(line+8, 1); if(!g_options->hostname) { g_options->hostname = alloc(MAX_HOSTNAME_LENGTH+1); gethostname(g_options->hostname, MAX_HOSTNAME_LENGTH); g_options->hostname[MAX_HOSTNAME_LENGTH] = '\0'; } g_printf("OPTIONS "); if(am_has_feature(g_options->features, fe_rep_options_features)) { g_printf("features=%s;", our_feature_string); } if(am_has_feature(g_options->features, fe_rep_options_maxdumps)) { g_printf("maxdumps=%d;", g_options->maxdumps); } if(am_has_feature(g_options->features, fe_rep_options_hostname)) { g_printf("hostname=%s;", g_options->hostname); } g_printf("\n"); fflush(stdout); if (g_options->config) { /* overlay this configuration on the existing (nameless) configuration */ config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY, g_options->config); dbrename(config_name, DBG_SUBDIR_CLIENT); } continue; } if (amandates_read == 0) { amandates_file = getconf_str(CNF_AMANDATES); if(!start_amandates(amandates_file, 0)) error("error [opening %s: %s]", amandates_file, strerror(errno)); amandates_read = 1; } s = line; ch = *s++; skip_whitespace(s, ch); /* find the program name */ if(ch == '\0') { err_extra = stralloc(_("no program name")); goto err; /* no program name */ } prog = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; program_is_backup_api=0; if(strncmp_const(prog, "CALCSIZE") == 0) { skip_whitespace(s, ch); /* find the program name */ if(ch == '\0') { err_extra = stralloc(_("no program name")); goto err; } calcprog = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; if (strcmp(calcprog,"BACKUP") == 0) { program_is_backup_api=1; skip_whitespace(s, ch); /* find dumper name */ if (ch == '\0') { goto err; /* no program */ } calcprog = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; } } else { calcprog = NULL; if (strcmp(prog,"BACKUP") == 0) { program_is_backup_api=1; skip_whitespace(s, ch); /* find dumper name */ if (ch == '\0') { goto err; /* no program */ } prog = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; } } skip_whitespace(s, ch); /* find the disk name */ if(ch == '\0') { err_extra = stralloc(_("no disk name")); goto err; /* no disk name */ } if (qdisk != NULL) amfree(qdisk); if (disk != NULL) amfree(disk); fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; /* terminate the disk name */ qdisk = stralloc(fp); disk = unquote_string(qdisk); skip_whitespace(s, ch); /* find the device or level */ if (ch == '\0') { err_extra = stralloc(_("bad level")); goto err; } if(!isdigit((int)s[-1])) { fp = s - 1; skip_quoted_string(s, ch); s[-1] = '\0'; qamdevice = stralloc(fp); amdevice = unquote_string(qamdevice); skip_whitespace(s, ch); /* find level number */ } else { amdevice = stralloc(disk); qamdevice = stralloc(qdisk); } /* find the level number */ if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) { err_extra = stralloc(_("bad level")); goto err; /* bad level */ } if (level < 0 || level >= DUMP_LEVELS) { err_extra = stralloc(_("bad level")); goto err; } skip_integer(s, ch); skip_whitespace(s, ch); /* find the dump date */ if(ch == '\0') { err_extra = stralloc(_("no dumpdate")); goto err; /* no dumpdate */ } dumpdate = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; (void)dumpdate; /* XXX: Set but not used */ spindle = 0; /* default spindle */ skip_whitespace(s, ch); /* find the spindle */ if(ch != '\0') { if(sscanf(s - 1, "%d", &spindle) != 1) { err_extra = stralloc(_("bad spindle")); goto err; /* bad spindle */ } skip_integer(s, ch); skip_whitespace(s, ch); /* find the parameters */ if(ch != '\0') { if(strncmp_const(s-1, "OPTIONS |;") == 0) { options = parse_options(s + 8, disk, amdevice, g_options->features, 0); } else { options = alloc(SIZEOF(option_t)); init_options(options); while (ch != '\0') { if(strncmp_const(s-1, "exclude-file=") == 0) { qlist = unquote_string(s+12); options->exclude_file = append_sl(options->exclude_file, qlist); amfree(qlist); } else if(strncmp_const(s-1, "exclude-list=") == 0) { qlist = unquote_string(s+12); options->exclude_list = append_sl(options->exclude_list, qlist); amfree(qlist); } else if(strncmp_const(s-1, "include-file=") == 0) { qlist = unquote_string(s+12); options->include_file = append_sl(options->include_file, qlist); amfree(qlist); } else if(strncmp_const(s-1, "include-list=") == 0) { qlist = unquote_string(s+12); options->include_list = append_sl(options->include_list, qlist); amfree(qlist); } else { err_extra = vstrallocf(_("Invalid parameter (%s)"), s-1); goto err; /* should have gotten to end */ } skip_quoted_string(s, ch); skip_whitespace(s, ch); /* find the inclusion list */ amfree(qlist); } } } else { options = alloc(SIZEOF(option_t)); init_options(options); } } else { options = alloc(SIZEOF(option_t)); init_options(options); } /*@ignore@*/ add_diskest(disk, amdevice, level, spindle, program_is_backup_api, prog, calcprog, options); /*@end@*/ amfree(disk); amfree(qdisk); amfree(amdevice); amfree(qamdevice); } if (g_options == NULL) { printf(_("ERROR [Missing OPTIONS line in sendsize input]\n")); error(_("Missing OPTIONS line in sendsize input\n")); /*NOTREACHED*/ } amfree(line); finish_amandates(); free_amandates(); dumpsrunning = 0; need_wait = 0; done = 0; while(! done) { done = 1; /* * See if we need to wait for a child before we can do anything * else in this pass. */ if(need_wait) { pid_t child_pid; amwait_t child_status; need_wait = 0; dbprintf(_("waiting for any estimate child: %d running\n"), dumpsrunning); child_pid = wait(&child_status); if(child_pid == -1) { error(_("wait failed: %s"), strerror(errno)); /*NOTREACHED*/ } if (!WIFEXITED(child_status) || WEXITSTATUS(child_status) != 0) { char *child_name = vstrallocf(_("child %ld"), (long)child_pid); char *child_status_str = str_exit_status(child_name, child_status); dbprintf("%s\n", child_status_str); amfree(child_status_str); amfree(child_name); } /* * Find the child and mark it done. */ for(est = est_list; est != NULL; est = est->next) { if(est->child == child_pid) { break; } } if(est == NULL) { dbprintf(_("unexpected child %ld\n"), (long)child_pid); } else { est->done = 1; est->child = 0; dumpsrunning--; } } /* * If we are already running the maximum number of children * go back and wait until one of them finishes. */ if(dumpsrunning >= g_options->maxdumps) { done = 0; need_wait = 1; continue; /* have to wait first */ } /* * Find a new child to start. */ for(est = est_list; est != NULL; est = est->next) { if(est->done == 0) { done = 0; /* more to do */ } if(est->child != 0 || est->done) { continue; /* child is running or done */ } /* * Make sure there is no spindle conflict. */ if(est->spindle != -1) { for(est1 = est_list; est1 != NULL; est1 = est1->next) { if(est1->child == 0 || est == est1 || est1->done) { /* * Ignore anything not yet started, ourself, * and anything completed. */ continue; } if(est1->spindle == est->spindle) { break; /* oops -- they match */ } } if(est1 != NULL) { continue; /* spindle conflict */ } } break; /* start this estimate */ } if(est == NULL) { if(dumpsrunning > 0) { need_wait = 1; /* nothing to do but wait */ } } else { done = 0; if((est->child = fork()) == 0) { calc_estimates(est); /* child does the estimate */ exit(0); } else if(est->child == -1) { error(_("calc_estimates fork failed: %s"), strerror(errno)); /*NOTREACHED*/ } dumpsrunning++; /* parent */ } } est_prev = NULL; for(est = est_list; est != NULL; est = est->next) { free_estimates(est); amfree(est_prev); est_prev = est; } amfree(est_prev); 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")); if (err_extra) { dbprintf(_("REQ packet is bogus: %s\n"), err_extra); amfree(err_extra); } else { dbprintf(_("REQ packet is bogus\n")); } dbclose(); return 1;}voidadd_diskest( char * disk, char * amdevice, int level, int spindle, int program_is_backup_api, char * prog, char * calcprog, option_t * options){ disk_estimates_t *newp, *curp; amandates_t *amdp; int dumplev, estlev; time_t dumpdate; if (level < 0) level = 0; if (level >= DUMP_LEVELS) level = DUMP_LEVELS - 1; for(curp = est_list; curp != NULL; curp = curp->next) { if(strcmp(curp->amname, disk) == 0) { /* already have disk info, just note the level request */ curp->est[level].needestimate = 1; if(options) { free_sl(options->exclude_file); free_sl(options->exclude_list); free_sl(options->include_file); free_sl(options->include_list); amfree(options->auth); amfree(options->str); amfree(options); } return; } } newp = (disk_estimates_t *) alloc(SIZEOF(disk_estimates_t)); memset(newp, 0, SIZEOF(*newp)); newp->next = est_list; est_list = newp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -