📄 amadmin.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. * * Author: James da Silva, Systems Design and Analysis Group * Computer Science Department * University of Maryland at College Park *//* * $Id: amadmin.c,v 1.124 2006/07/26 15:17:37 martinea Exp $ * * controlling process for the Amanda backup system */#include "amanda.h"#include "cmdline.h"#include "conffile.h"#include "diskfile.h"#include "tapefile.h"#include "infofile.h"#include "logfile.h"#include "version.h"#include "holding.h"#include "find.h"#include "util.h"#include "timestamp.h"disklist_t diskq;int main(int argc, char **argv);void usage(void);void force(int argc, char **argv);void force_one(disk_t *dp);void unforce(int argc, char **argv);void unforce_one(disk_t *dp);void force_bump(int argc, char **argv);void force_bump_one(disk_t *dp);void force_no_bump(int argc, char **argv);void force_no_bump_one(disk_t *dp);void unforce_bump(int argc, char **argv);void unforce_bump_one(disk_t *dp);void reuse(int argc, char **argv);void noreuse(int argc, char **argv);void info(int argc, char **argv);void info_one(disk_t *dp);void due(int argc, char **argv);void due_one(disk_t *dp);void find(int argc, char **argv);void holding(int argc, char **argv);void delete(int argc, char **argv);void delete_one(disk_t *dp);void balance(int argc, char **argv);void tape(int argc, char **argv);void bumpsize(int argc, char **argv);void diskloop(int argc, char **argv, char *cmdname, void (*func)(disk_t *dp));char *seqdatestr(int seq);static int next_level0(disk_t *dp, info_t *info);int bump_thresh(int level);void export_db(int argc, char **argv);void import_db(int argc, char **argv);void disklist(int argc, char **argv);void disklist_one(disk_t *dp);void show_version(int argc, char **argv);static void show_config(int argc, char **argv);static char *conf_tapelist = NULL;static char *displayunit;static long int unitdivisor;static const struct { const char *name; void (*fn)(int, char **); const char *usage;} cmdtab[] = { { "version", show_version, T_("\t\t\t\t\t# Show version info.") }, { "config", show_config, T_("\t\t\t\t\t# Show configuration.") }, { "force", force, T_(" [<hostname> [<disks>]* ]+\t\t# Force level 0 at next run.") }, { "unforce", unforce, T_(" [<hostname> [<disks>]* ]+\t# Clear force command.") }, { "force-bump", force_bump, T_(" [<hostname> [<disks>]* ]+\t# Force bump at next run.") }, { "force-no-bump", force_no_bump, T_(" [<hostname> [<disks>]* ]+\t# Force no-bump at next run.") }, { "unforce-bump", unforce_bump, T_(" [<hostname> [<disks>]* ]+\t# Clear bump command.") }, { "disklist", disklist, T_(" [<hostname> [<disks>]* ]*\t# Debug disklist entries.") }, { "reuse", reuse, T_(" <tapelabel> ...\t\t # re-use this tape.") }, { "no-reuse", noreuse, T_(" <tapelabel> ...\t # never re-use this tape.") }, { "find", find, T_(" [<hostname> [<disks>]* ]*\t # Show which tapes these dumps are on.") }, { "holding", holding, T_(" {list [ -l ] |delete} [ <hostname> [ <disk> [ <datestamp> [ .. ] ] ] ]+\t # Show or delete holding disk contents.") }, { "delete", delete, T_(" [<hostname> [<disks>]* ]+ # Delete from database.") }, { "info", info, T_(" [<hostname> [<disks>]* ]*\t # Show current info records.") }, { "due", due, T_(" [<hostname> [<disks>]* ]*\t # Show due date.") }, { "balance", balance, T_(" [-days <num>]\t\t # Show nightly dump size balance.") }, { "tape", tape, T_(" [-days <num>]\t\t # Show which tape is due next.") }, { "bumpsize", bumpsize, T_("\t\t\t # Show current bump thresholds.") }, { "export", export_db, T_(" [<hostname> [<disks>]* ]* # Export curinfo database to stdout.") }, { "import", import_db, T_("\t\t\t\t # Import curinfo database from stdin.") },};#define NCMDS (int)(sizeof(cmdtab) / sizeof(cmdtab[0]))intmain( int argc, char ** argv){ int i; char *conf_diskfile; char *conf_infofile; config_overwrites_t *cfg_ovr = NULL; /* * 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("amadmin"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); dbopen(DBG_SUBDIR_SERVER); erroutput_type = ERR_INTERACTIVE; cfg_ovr = extract_commandline_config_overwrites(&argc, &argv); if(argc < 3) usage(); if(strcmp(argv[2],"version") == 0) { show_version(argc, argv); goto done; } config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_FATAL, argv[1]); apply_config_overwrites(cfg_ovr); dbrename(config_name, DBG_SUBDIR_SERVER); check_running_as(RUNNING_AS_DUMPUSER); conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE)); if (read_diskfile(conf_diskfile, &diskq) < 0) { error(_("could not load disklist \"%s\""), conf_diskfile); /*NOTREACHED*/ } amfree(conf_diskfile); conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST)); if(read_tapelist(conf_tapelist)) { error(_("could not load tapelist \"%s\""), conf_tapelist); /*NOTREACHED*/ } /* conf_tapelist is not freed yet -- it may be used to write the * tapelist later. */ conf_infofile = config_dir_relative(getconf_str(CNF_INFOFILE)); if(open_infofile(conf_infofile)) { error(_("could not open info db \"%s\""), conf_infofile); /*NOTREACHED*/ } amfree(conf_infofile); displayunit = getconf_str(CNF_DISPLAYUNIT); unitdivisor = getconf_unit_divisor(); for (i = 0; i < NCMDS; i++) if (strcmp(argv[2], cmdtab[i].name) == 0) { (*cmdtab[i].fn)(argc, argv); break; } if (i == NCMDS) { g_fprintf(stderr, _("%s: unknown command \"%s\"\n"), argv[0], argv[2]); usage(); } close_infofile(); clear_tapelist(); amfree(conf_tapelist);done: free_disklist(&diskq); dbclose(); return 0;}voidusage(void){ int i; g_fprintf(stderr, _("\nUsage: %s%s <conf> <command> {<args>} [-o configoption]* ...\n"), get_pname(), versionsuffix()); g_fprintf(stderr, _(" Valid <command>s are:\n")); for (i = 0; i < NCMDS; i++) g_fprintf(stderr, "\t%s%s\n", cmdtab[i].name, _(cmdtab[i].usage)); exit(1);}/* ----------------------------------------------- */#define SECS_PER_DAY (24*60*60)time_t today;char *seqdatestr( int seq){ static char str[16]; static char *dow[7] = { T_("Sun"), T_("Mon"), T_("Tue"), T_("Wed"), T_("Thu"), T_("Fri"), T_("Sat") }; time_t t = today + seq*SECS_PER_DAY; struct tm *tm; tm = localtime(&t); if (tm) g_snprintf(str, SIZEOF(str), "%2d/%02d %3s", tm->tm_mon+1, tm->tm_mday, _(dow[tm->tm_wday])); else strcpy(str, _("BAD DATE")); return str;}#undef days_diff#define days_diff(a, b) (int)(((b) - (a) + SECS_PER_DAY) / SECS_PER_DAY)/* when is next level 0 due? 0 = tonight, 1 = tommorrow, etc*/static intnext_level0( disk_t * dp, info_t * info){ if(dp->strategy == DS_NOFULL) return 1; /* fake it */ if(info->inf[0].date < (time_t)0) return 0; /* new disk */ else return dp->dumpcycle - days_diff(info->inf[0].date, today);}/* ----------------------------------------------- */voiddiskloop( int argc, char ** argv, char * cmdname, void (*func)(disk_t *dp)){ disk_t *dp; int count = 0; char *errstr; if(argc < 4) { g_fprintf(stderr,_("%s: expecting \"%s [<hostname> [<disks>]* ]+\"\n"), get_pname(), cmdname); usage(); } errstr = match_disklist(&diskq, argc-3, argv+3); if (errstr) { g_printf("%s", errstr); amfree(errstr); } for(dp = diskq.head; dp != NULL; dp = dp->next) { if(dp->todo) { count++; func(dp); } } if(count==0) { g_fprintf(stderr,_("%s: no disk matched\n"),get_pname()); }}/* ----------------------------------------------- */voidforce_one( disk_t * dp){ char *hostname = dp->host->hostname; char *diskname = dp->name; info_t info; get_info(hostname, diskname, &info); SET(info.command, FORCE_FULL); if (ISSET(info.command, FORCE_BUMP)) { CLR(info.command, FORCE_BUMP); g_printf(_("%s: WARNING: %s:%s FORCE_BUMP command was cleared.\n"), get_pname(), hostname, diskname); } if(put_info(hostname, diskname, &info) == 0) { if (dp->strategy == DS_INCRONLY) { g_printf(_("%s: %s:%s, full dump done offline, next dump will be at level 1.\n"), get_pname(), hostname, diskname); } else { g_printf(_("%s: %s:%s is set to a forced level 0 at next run.\n"), get_pname(), hostname, diskname); } } else { g_fprintf(stderr, _("%s: %s:%s could not be forced.\n"), get_pname(), hostname, diskname); }}voidforce( int argc, char ** argv){ diskloop(argc, argv, "force", force_one);}/* ----------------------------------------------- */voidunforce_one( disk_t * dp){ char *hostname = dp->host->hostname; char *diskname = dp->name; info_t info; get_info(hostname, diskname, &info); if (ISSET(info.command, FORCE_FULL)) { CLR(info.command, FORCE_FULL); if(put_info(hostname, diskname, &info) == 0){ g_printf(_("%s: force command for %s:%s cleared.\n"), get_pname(), hostname, diskname); } else { g_fprintf(stderr, _("%s: force command for %s:%s could not be cleared.\n"), get_pname(), hostname, diskname); } } else { g_printf(_("%s: no force command outstanding for %s:%s, unchanged.\n"), get_pname(), hostname, diskname); }}voidunforce( int argc, char ** argv){ diskloop(argc, argv, "unforce", unforce_one);}/* ----------------------------------------------- */voidforce_bump_one( disk_t * dp){ char *hostname = dp->host->hostname; char *diskname = dp->name; info_t info; get_info(hostname, diskname, &info); SET(info.command, FORCE_BUMP); if (ISSET(info.command, FORCE_NO_BUMP)) { CLR(info.command, FORCE_NO_BUMP); g_printf(_("%s: WARNING: %s:%s FORCE_NO_BUMP command was cleared.\n"), get_pname(), hostname, diskname); } if (ISSET(info.command, FORCE_FULL)) { CLR(info.command, FORCE_FULL); g_printf(_("%s: WARNING: %s:%s FORCE_FULL command was cleared.\n"), get_pname(), hostname, diskname); } if(put_info(hostname, diskname, &info) == 0) { g_printf(_("%s: %s:%s is set to bump at next run.\n"), get_pname(), hostname, diskname); } else { g_fprintf(stderr, _("%s: %s:%s could not be forced to bump.\n"), get_pname(), hostname, diskname); }}voidforce_bump( int argc, char ** argv){ diskloop(argc, argv, "force-bump", force_bump_one);}/* ----------------------------------------------- */voidforce_no_bump_one( disk_t * dp){ char *hostname = dp->host->hostname; char *diskname = dp->name; info_t info; get_info(hostname, diskname, &info); SET(info.command, FORCE_NO_BUMP); if (ISSET(info.command, FORCE_BUMP)) { CLR(info.command, FORCE_BUMP); g_printf(_("%s: WARNING: %s:%s FORCE_BUMP command was cleared.\n"), get_pname(), hostname, diskname); } if(put_info(hostname, diskname, &info) == 0) { g_printf(_("%s: %s:%s is set to not bump at next run.\n"), get_pname(), hostname, diskname); } else { g_fprintf(stderr, _("%s: %s:%s could not be force to not bump.\n"), get_pname(), hostname, diskname); }}voidforce_no_bump( int argc, char ** argv){ diskloop(argc, argv, "force-no-bump", force_no_bump_one);}/* ----------------------------------------------- */voidunforce_bump_one( disk_t * dp){ char *hostname = dp->host->hostname; char *diskname = dp->name; info_t info; get_info(hostname, diskname, &info); if (ISSET(info.command, FORCE_BUMP|FORCE_NO_BUMP)) { CLR(info.command, FORCE_BUMP|FORCE_NO_BUMP); if(put_info(hostname, diskname, &info) == 0) { g_printf(_("%s: bump command for %s:%s cleared.\n"), get_pname(), hostname, diskname); } else { g_fprintf(stderr, _("%s: %s:%s bump command could not be cleared.\n"), get_pname(), hostname, diskname); } } else { g_printf(_("%s: no bump command outstanding for %s:%s, unchanged.\n"), get_pname(), hostname, diskname); }}voidunforce_bump( int argc, char ** argv){ diskloop(argc, argv, "unforce-bump", unforce_bump_one);}/* ----------------------------------------------- */voidreuse( int argc, char ** argv){ tape_t *tp; int count; if(argc < 4) { g_fprintf(stderr,_("%s: expecting \"reuse <tapelabel> ...\"\n"), get_pname()); usage(); } for(count=3; count< argc; count++) { tp = lookup_tapelabel(argv[count]); if ( tp == NULL) { g_fprintf(stderr, _("reuse: tape label %s not found in tapelist.\n"), argv[count]); continue; } if( tp->reuse == 0 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -