From ccfcd927365b09e5bb9a61703018151082e04805 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sun, 11 Aug 2002 11:12:19 +0000 Subject: [PATCH] Make restore Job work -- kes11Aug02 git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@86 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/autoconf/configure.in | 2 + bacula/configure | 4 + bacula/kernstodo | 50 ++++----- bacula/src/dird/dird.c | 2 +- bacula/src/dird/dird_conf.c | 12 +- bacula/src/dird/dird_conf.h | 204 +++++++++++++++++----------------- bacula/src/dird/job.c | 2 +- bacula/src/dird/ua.h | 2 +- bacula/src/dird/ua_restore.c | 12 +- bacula/src/dird/ua_run.c | 67 +++++++++-- bacula/src/dird/ua_select.c | 2 +- bacula/src/jcr.h | 2 +- bacula/src/lib/lex.h | 1 + bacula/src/stored/bextract.c | 2 +- bacula/src/stored/fd_cmds.c | 5 +- bacula/src/stored/job.c | 1 + bacula/src/stored/parse_bsr.c | 27 +++-- bacula/src/stored/protos.h | 152 ++++++++++++------------- 18 files changed, 305 insertions(+), 244 deletions(-) diff --git a/bacula/autoconf/configure.in b/bacula/autoconf/configure.in index ef1b148ad8..c4e72f5b0f 100644 --- a/bacula/autoconf/configure.in +++ b/bacula/autoconf/configure.in @@ -1178,6 +1178,8 @@ AC_OUTPUT([autoconf/Make.common \ btraceback \ startit \ stopit \ + console \ + gconsole \ bacula \ fd \ doc/Makefile \ diff --git a/bacula/configure b/bacula/configure index 823b49513d..d20174bfc7 100755 --- a/bacula/configure +++ b/bacula/configure @@ -9152,6 +9152,8 @@ trap 'rm -fr `echo "autoconf/Make.common \ btraceback \ startit \ stopit \ + console \ + gconsole \ bacula \ fd \ doc/Makefile \ @@ -9396,6 +9398,8 @@ CONFIG_FILES=\${CONFIG_FILES-"autoconf/Make.common \ btraceback \ startit \ stopit \ + console \ + gconsole \ bacula \ fd \ doc/Makefile \ diff --git a/bacula/kernstodo b/bacula/kernstodo index f01f44b978..87be51e37d 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 9 August 2002 + 11 August 2002 Irix conversion notes: - no uuencode @@ -17,25 +17,18 @@ To do: From Chuck: --bindir is wrong and does not reflect prefix= in the *_sqlite_* scripts -(src/cats) - + (src/cats) --top level configure options are not passed to the depkgs, particularly -prefix= - -Also, it might be better to split the depkgs location from the --with-sqlite -location. - + prefix= +--Also, it might be better to split the depkgs location from the --with-sqlite + location. --should be able to specify e.g. --with-sqlite=/opt/local and have it find -lib, bin, sbin for itself - -I tried this and it didn't find sqlite.h - ---the console script is broken as installed and has to be hand-massaged with -paths, config files etc. - + lib, bin, sbin for itself + I tried this and it didn't find sqlite.h --sd.conf password does not match dir.conf storage password - ======= + +- Make Restore report an error if FD or SD term codes are not OK. - Convert all %x substitution variables, which are hard to remember and read to %(variable-name)s. Idea from TMDA. - Report volume write rate. @@ -46,14 +39,8 @@ paths, config files etc. using MySQL. - Pass "Catalog Files = no" to storage daemon to eliminate network traffic. -- Implement alter_sqlite_tables -- Fix scheduler -- see "Hourly cycle". It doesn't do both each - hour, rather it alternates between 0:05 and 0:35. -- Create Counter DB records. - Make Pool resource handle Counter resources. - Remove NextId for SQLite. Optimize. -- Termination status in FD for Verify = C -- incorrect. -- Fix strerror() to use strerror_r() - Fix gethostbyname() to use gethostbyname_r() - Cleanup path/filename separation in sql_get.c and sql_create.c - Implement ./configure --with-client-only @@ -89,22 +76,22 @@ Minor details: Major Project: - Improve the Restore capabilities of Bacula - * Restore to most recent system state (i.e. + - Restore to most recent system state (i.e. figure out what tapes need to be mounted and in what order). - * Restore to a particular time (perhaps several + - Restore to a particular time (perhaps several variations -- e.g. before date, after date). - * Interactive Restore where you get to select + - Interactive Restore where you get to select what files are to be restored (much like the Unix "restore" program permits). Now that we have a catalog of all files saved, it would be nice to be able to use it. - * Restore options (overwrite, overwrite if older, + - Restore options (overwrite, overwrite if older, overwrite if newer, never overwrite, ...) - * Improve the standalone programs (bls and bextract) + - Improve the standalone programs (bls and bextract) to have pattern matching capabilities (e.g. restore by FileSet, Job, JobType, JobLevel, ...). - * Ideally after each Job, Bacula could write out a + - Ideally after each Job, Bacula could write out a set of commands to a file that if later feed to bextract would restore your system to the current state (at least for the saved FileSet). This would @@ -459,3 +446,10 @@ Longer term to do: Done: (see kernsdone for more) +--the console script is broken as installed and has to be hand-massaged with + paths, config files etc. +- Termination status in FD for Verify = C -- incorrect. +- Implement alter_sqlite_tables +- Fix scheduler -- see "Hourly cycle". It doesn't do both each + hour, rather it alternates between 0:05 and 0:35. +- Create Counter DB records. diff --git a/bacula/src/dird/dird.c b/bacula/src/dird/dird.c index 83541d8202..edf2297847 100644 --- a/bacula/src/dird/dird.c +++ b/bacula/src/dird/dird.c @@ -331,7 +331,7 @@ Without that I don't know who I am :-(\n"), configfile); Emsg1(M_FATAL, 0, _("No Client record defined for job %s\n"), job->hdr.name); OK = FALSE; } - if (!job->fs) { + if (!job->fileset) { Emsg1(M_FATAL, 0, _("No FileSet record defined for job %s\n"), job->hdr.name); OK = FALSE; } diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index f7c947fcdb..d479797d9f 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -169,7 +169,7 @@ static struct res_items job_items[] = { {"storage", store_res, ITEM(res_job.storage), R_STORAGE, 0, 0}, {"pool", store_res, ITEM(res_job.pool), R_POOL, 0, 0}, {"client", store_res, ITEM(res_job.client), R_CLIENT, 0, 0}, - {"fileset", store_res, ITEM(res_job.fs), R_FILESET, 0, 0}, + {"fileset", store_res, ITEM(res_job.fileset), R_FILESET, 0, 0}, {"where", store_dir, ITEM(res_job.RestoreWhere), 0, 0, 0}, {"bootstrap",store_dir, ITEM(res_job.RestoreBootstrap), 0, 0, 0}, {"maxruntime", store_time, ITEM(res_job.MaxRunTime), 0, 0, 0}, @@ -464,9 +464,9 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ... sendit(sock, " --> "); dump_resource(-R_CLIENT, (RES *)res->res_job.client, sendit, sock); } - if (res->res_job.fs) { + if (res->res_job.fileset) { sendit(sock, " --> "); - dump_resource(-R_FILESET, (RES *)res->res_job.fs, sendit, sock); + dump_resource(-R_FILESET, (RES *)res->res_job.fileset, sendit, sock); } if (res->res_job.schedule) { sendit(sock, " --> "); @@ -800,7 +800,7 @@ void save_resource(int type, struct res_items *items, int pass) res->res_job.messages = res_all.res_job.messages; res->res_job.schedule = res_all.res_job.schedule; res->res_job.client = res_all.res_job.client; - res->res_job.fs = res_all.res_job.fs; + res->res_job.fileset = res_all.res_job.fileset; res->res_job.storage = res_all.res_job.storage; res->res_job.pool = res_all.res_job.pool; if (res->res_job.JobType == 0) { @@ -1017,7 +1017,7 @@ static void store_backup(LEX *lc, struct res_items *item, int index, int pass) scan_err1(lc, "Could not find specified FileSet Resource: %s\n", lc->str); } - res_all.res_job.fs = (FILESET *)res; + res_all.res_job.fileset = (FILESET *)res; } break; case 'L': @@ -1108,7 +1108,7 @@ static void store_restore(LEX *lc, struct res_items *item, int index, int pass) scan_err1(lc, "Could not find specified FileSet Resource: %s\n", lc->str); } - res_all.res_job.fs = (FILESET *)res; + res_all.res_job.fileset = (FILESET *)res; } break; case 'J': diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index 079b80835a..7c3e6d0284 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -30,43 +30,43 @@ /* * Resource codes -- they must be sequential for indexing */ -#define R_FIRST 1001 - -#define R_DIRECTOR 1001 -#define R_CLIENT 1002 -#define R_JOB 1003 -#define R_STORAGE 1004 -#define R_CATALOG 1005 -#define R_SCHEDULE 1006 -#define R_FILESET 1007 -#define R_GROUP 1008 -#define R_POOL 1009 -#define R_MSGS 1010 -#define R_COUNTER 1011 - -#define R_LAST R_COUNTER +#define R_FIRST 1001 + +#define R_DIRECTOR 1001 +#define R_CLIENT 1002 +#define R_JOB 1003 +#define R_STORAGE 1004 +#define R_CATALOG 1005 +#define R_SCHEDULE 1006 +#define R_FILESET 1007 +#define R_GROUP 1008 +#define R_POOL 1009 +#define R_MSGS 1010 +#define R_COUNTER 1011 + +#define R_LAST R_COUNTER /* * Some resource attributes */ -#define R_NAME 1020 -#define R_ADDRESS 1021 -#define R_PASSWORD 1022 -#define R_TYPE 1023 -#define R_BACKUP 1024 +#define R_NAME 1020 +#define R_ADDRESS 1021 +#define R_PASSWORD 1022 +#define R_TYPE 1023 +#define R_BACKUP 1024 /* Used for certain KeyWord tables */ -struct s_kw { +struct s_kw { char *name; - int token; + int token; }; /* Job Level keyword structure */ struct s_jl { - char *level_name; /* level keyword */ - int level; /* level */ - int job_type; /* JobType permitting this level */ + char *level_name; /* level keyword */ + int level; /* level */ + int job_type; /* JobType permitting this level */ }; /* Job Type keyword structure */ @@ -78,21 +78,21 @@ struct s_jt { /* Definition of the contents of each Resource */ /* - * Director Resource + * Director Resource * */ struct s_res_dir { - RES hdr; - int DIRport; /* where we listen -- UA port server port */ - char *password; /* Password for UA access */ - char *query_file; /* SQL query file */ - char *working_directory; /* WorkingDirectory */ - char *pid_directory; /* PidDirectory */ - char *subsys_directory; /* SubsysDirectory */ + RES hdr; + int DIRport; /* where we listen -- UA port server port */ + char *password; /* Password for UA access */ + char *query_file; /* SQL query file */ + char *working_directory; /* WorkingDirectory */ + char *pid_directory; /* PidDirectory */ + char *subsys_directory; /* SubsysDirectory */ struct s_res_msgs *messages; /* Daemon message handler */ - int MaxConcurrentJobs; - btime_t FDConnectTimeout; /* timeout for connect in seconds */ - btime_t SDConnectTimeout; /* timeout in seconds */ + int MaxConcurrentJobs; + btime_t FDConnectTimeout; /* timeout for connect in seconds */ + btime_t SDConnectTimeout; /* timeout in seconds */ }; typedef struct s_res_dir DIRRES; @@ -101,12 +101,12 @@ typedef struct s_res_dir DIRRES; * */ struct s_res_client { - RES hdr; + RES hdr; - int FDport; /* Where File daemon listens */ - int AutoPrune; /* Do automatic pruning? */ - btime_t FileRetention; /* file retention period in seconds */ - btime_t JobRetention; /* job retention period in seconds */ + int FDport; /* Where File daemon listens */ + int AutoPrune; /* Do automatic pruning? */ + btime_t FileRetention; /* file retention period in seconds */ + btime_t JobRetention; /* job retention period in seconds */ char *address; char *password; struct s_res_cat *catalog; /* Catalog resource */ @@ -118,10 +118,10 @@ typedef struct s_res_client CLIENT; * */ struct s_res_store { - RES hdr; + RES hdr; - int SDport; /* port where Directors connect */ - int SDDport; /* data port for File daemon */ + int SDport; /* port where Directors connect */ + int SDDport; /* data port for File daemon */ char *address; char *password; char *media_type; @@ -134,9 +134,9 @@ typedef struct s_res_store STORE; * */ struct s_res_cat { - RES hdr; + RES hdr; - int DBport; /* Port -- not yet implemented */ + int DBport; /* Port -- not yet implemented */ char *address; char *db_password; char *db_user; @@ -149,28 +149,28 @@ typedef struct s_res_cat CAT; * */ struct s_res_job { - RES hdr; - - int JobType; /* job type (backup, verify, restore */ - int level; /* default backup/verify level */ - int RestoreJobId; /* What -- JobId to restore */ - char *RestoreWhere; /* Where on disk to restore -- directory */ - char *RestoreBootstrap; /* Bootstrap file */ - char *RunBeforeJob; /* Run program before Job */ - char *RunAfterJob; /* Run program after Job */ - int RestoreOptions; /* How (overwrite, ..) */ - btime_t MaxRunTime; /* max run time in seconds */ - btime_t MaxStartDelay; /* max start delay in seconds */ - int PruneJobs; /* Force pruning of Jobs */ - int PruneFiles; /* Force pruning of Files */ - int PruneVolumes; /* Force pruning of Volumes */ + RES hdr; + + int JobType; /* job type (backup, verify, restore */ + int level; /* default backup/verify level */ + int RestoreJobId; /* What -- JobId to restore */ + char *RestoreWhere; /* Where on disk to restore -- directory */ + char *RestoreBootstrap; /* Bootstrap file */ + char *RunBeforeJob; /* Run program before Job */ + char *RunAfterJob; /* Run program after Job */ + int RestoreOptions; /* How (overwrite, ..) */ + btime_t MaxRunTime; /* max run time in seconds */ + btime_t MaxStartDelay; /* max start delay in seconds */ + int PruneJobs; /* Force pruning of Jobs */ + int PruneFiles; /* Force pruning of Files */ + int PruneVolumes; /* Force pruning of Volumes */ struct s_res_msgs *messages; /* How and where to send messages */ struct s_res_sch *schedule; /* When -- Automatic schedule */ struct s_res_client *client; /* Who to backup */ - struct s_res_fs *fs; /* What to backup -- Fileset */ + struct s_res_fs *fileset; /* What to backup -- Fileset */ struct s_res_store *storage; /* Where is device -- Storage daemon */ - struct s_res_pool *pool; /* Where is media -- Media Pool */ + struct s_res_pool *pool; /* Where is media -- Media Pool */ }; typedef struct s_res_job JOB; @@ -179,7 +179,7 @@ typedef struct s_res_job JOB; * */ struct s_res_fs { - RES hdr; + RES hdr; char **include_array; int num_includes; @@ -187,8 +187,8 @@ struct s_res_fs { char **exclude_array; int num_excludes; int exclude_size; - int have_MD5; /* set if MD5 initialized */ - struct MD5Context md5c; /* MD5 of include/exclude */ + int have_MD5; /* set if MD5 initialized */ + struct MD5Context md5c; /* MD5 of include/exclude */ }; typedef struct s_res_fs FILESET; @@ -198,7 +198,7 @@ typedef struct s_res_fs FILESET; * */ struct s_res_sch { - RES hdr; + RES hdr; struct s_run *run; }; @@ -209,7 +209,7 @@ typedef struct s_res_sch SCHED; * */ struct s_res_group { - RES hdr; + RES hdr; }; typedef struct s_res_group GROUP; @@ -217,12 +217,12 @@ typedef struct s_res_group GROUP; * Counter Resource */ struct s_res_counter { - RES hdr; + RES hdr; - int32_t MinValue; /* Minimum value */ - int32_t MaxValue; /* Maximum value */ - int Global; /* global/local */ - char *WrapCounter; /* Wrap counter name */ + int32_t MinValue; /* Minimum value */ + int32_t MaxValue; /* Maximum value */ + int Global; /* global/local */ + char *WrapCounter; /* Wrap counter name */ }; typedef struct s_res_counter COUNTER; @@ -231,19 +231,19 @@ typedef struct s_res_counter COUNTER; * */ struct s_res_pool { - RES hdr; + RES hdr; struct s_res_counter counter; /* Counter resources */ - char *pool_type; /* Pool type */ - char *label_format; /* Label format string */ - int use_catalog; /* maintain catalog for media */ - int catalog_files; /* maintain file entries in catalog */ - int use_volume_once; /* write on volume only once */ - int accept_any_volume; /* accept any volume */ - int max_volumes; /* max number of volumes */ - btime_t VolRetention; /* volume retention period in seconds */ - int AutoPrune; /* default for pool auto prune */ - int Recycle; /* default for media recycle yes/no */ + char *pool_type; /* Pool type */ + char *label_format; /* Label format string */ + int use_catalog; /* maintain catalog for media */ + int catalog_files; /* maintain file entries in catalog */ + int use_volume_once; /* write on volume only once */ + int accept_any_volume; /* accept any volume */ + int max_volumes; /* max number of volumes */ + btime_t VolRetention; /* volume retention period in seconds */ + int AutoPrune; /* default for pool auto prune */ + int Recycle; /* default for media recycle yes/no */ }; typedef struct s_res_pool POOL; @@ -252,16 +252,16 @@ typedef struct s_res_pool POOL; * resource structure definitions. */ union u_res { - struct s_res_dir res_dir; - struct s_res_client res_client; - struct s_res_store res_store; - struct s_res_cat res_cat; - struct s_res_job res_job; - struct s_res_fs res_fs; - struct s_res_sch res_sch; - struct s_res_group res_group; - struct s_res_pool res_pool; - struct s_res_msgs res_msgs; + struct s_res_dir res_dir; + struct s_res_client res_client; + struct s_res_store res_store; + struct s_res_cat res_cat; + struct s_res_job res_job; + struct s_res_fs res_fs; + struct s_res_sch res_sch; + struct s_res_group res_group; + struct s_res_pool res_pool; + struct s_res_msgs res_msgs; struct s_res_counter res_counter; RES hdr; }; @@ -271,17 +271,17 @@ typedef union u_res URES; /* Run structure contained in Schedule Resource */ struct s_run { - struct s_run *next; /* points to next run record */ - int level; /* level override */ + struct s_run *next; /* points to next run record */ + int level; /* level override */ int job_type; - POOL *pool; /* Pool override */ - STORE *storage; /* Storage override */ - MSGS *msgs; /* Messages override */ + POOL *pool; /* Pool override */ + STORE *storage; /* Storage override */ + MSGS *msgs; /* Messages override */ char *since; int level_no; - int minute; /* minute to run job */ - time_t last_run; /* last time run */ - time_t next_run; /* next time to run */ + int minute; /* minute to run job */ + time_t last_run; /* last time run */ + time_t next_run; /* next time to run */ char hour[nbytes_for_bits(24)]; /* bit set for each hour */ char mday[nbytes_for_bits(31)]; /* bit set for each day of month */ char month[nbytes_for_bits(12)]; /* bit set for each month */ diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index 7c9678f60e..75ffdcff86 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -356,7 +356,7 @@ void set_jcr_defaults(JCR *jcr, JOB *job) strcpy(jcr->client_name, jcr->client->hdr.name); jcr->pool = job->pool; jcr->catalog = job->client->catalog; - jcr->fileset = job->fs; + jcr->fileset = job->fileset; jcr->msgs = job->messages; if (jcr->RestoreBootstrap) { free(jcr->RestoreBootstrap); diff --git a/bacula/src/dird/ua.h b/bacula/src/dird/ua.h index b5e28774e0..66f4d9d5ea 100644 --- a/bacula/src/dird/ua.h +++ b/bacula/src/dird/ua.h @@ -71,7 +71,7 @@ STORE *select_storage_resource(UAContext *ua); JOB *select_job_resource(UAContext *ua); JOB *select_restore_job_resource(UAContext *ua); CLIENT *select_client_resource(UAContext *ua); -FILESET *select_fs_resource(UAContext *ua); +FILESET *select_fileset_resource(UAContext *ua); int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr); int select_pool_dbr(UAContext *ua, POOL_DBR *pr); diff --git a/bacula/src/dird/ua_restore.c b/bacula/src/dird/ua_restore.c index 2403a8bd0c..37cf7443a4 100644 --- a/bacula/src/dird/ua_restore.c +++ b/bacula/src/dird/ua_restore.c @@ -222,7 +222,7 @@ int restorecmd(UAContext *ua, char *cmd) job->hdr.name, working_directory); } - Dmsg1(400, "Submitting: %s\n", ua->cmd); + Dmsg1(000, "Submitting: %s\n", ua->cmd); parse_command_args(ua); runcmd(ua, ua->cmd); @@ -440,8 +440,8 @@ static int quitcmd(UAContext *ua, TREE_CTX *tree); struct cmdstruct { char *key; int (*func)(UAContext *ua, TREE_CTX *tree); char *help; }; static struct cmdstruct commands[] = { - { N_("mark"), markcmd, _("mark file for extraction")}, - { N_("unmark"), unmarkcmd, _("unmark file for extraction")}, + { N_("mark"), markcmd, _("mark file for restoration")}, + { N_("unmark"), unmarkcmd, _("unmark file for restoration")}, { N_("cd"), cdcmd, _("change current directory")}, { N_("pwd"), pwdcmd, _("print current working directory")}, { N_("ls"), lscmd, _("list current directory")}, @@ -625,7 +625,7 @@ static void write_bsr(UAContext *ua, RBSR *bsr, FILE *fd) { if (bsr) { if (bsr->VolumeName) { - fprintf(fd, "VolumeName=%s\n", bsr->VolumeName); + fprintf(fd, "Volume=%s\n", bsr->VolumeName); } fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId); fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime); @@ -638,7 +638,7 @@ static void print_bsr(UAContext *ua, RBSR *bsr) { if (bsr) { if (bsr->VolumeName) { - bsendmsg(ua, "VolumeName=%s\n", bsr->VolumeName); + bsendmsg(ua, "Volume=%s\n", bsr->VolumeName); } bsendmsg(ua, "VolSessionId=%u\n", bsr->VolSessionId); bsendmsg(ua, "VolSessionTime=%u\n", bsr->VolSessionTime); @@ -832,7 +832,7 @@ static int countcmd(UAContext *ua, TREE_CTX *tree) } } } - bsendmsg(ua, "%d total files. %d marked for extraction.\n", total, extract); + bsendmsg(ua, "%d total files. %d marked for restoration.\n", total, extract); return 1; } diff --git a/bacula/src/dird/ua_run.c b/bacula/src/dird/ua_run.c index be26ed7d70..fac2652a4c 100644 --- a/bacula/src/dird/ua_run.c +++ b/bacula/src/dird/ua_run.c @@ -47,14 +47,14 @@ extern struct s_jl joblevels[]; */ int runcmd(UAContext *ua, char *cmd) { - JOB *job; JCR *jcr; char *job_name, *level_name, *jid, *store_name; char *where, *fileset_name, *client_name, *bootstrap; int i, j, found; - STORE *store; - CLIENT *client; - FILESET *fileset; + JOB *job = NULL; + STORE *store = NULL; + CLIENT *client = NULL; + FILESET *fileset = NULL; static char *kw[] = { N_("job"), N_("jobid"), @@ -79,7 +79,7 @@ int runcmd(UAContext *ua, char *cmd) fileset_name = NULL; bootstrap = NULL; - Dmsg1(20, "run: %s\n", ua->UA_sock->msg); + Dmsg1(000, "run: %s\n", ua->UA_sock->msg); for (i=1; iargc; i++) { found = False; @@ -177,7 +177,10 @@ int runcmd(UAContext *ua, char *cmd) } } /* end argc loop */ - Dmsg0(20, "Done scan.\n"); + Dmsg0(200, "Done scan.\n"); + + + if (job_name) { /* Find Job */ job = (JOB *)GetResWithName(R_JOB, job_name); @@ -185,7 +188,7 @@ int runcmd(UAContext *ua, char *cmd) bsendmsg(ua, _("Job %s: not found\n"), job_name); job = select_job_resource(ua); } else { - Dmsg1(20, "Found job=%s\n", job_name); + Dmsg1(200, "Found job=%s\n", job_name); } } else { bsendmsg(ua, _("A job name must be specified.\n")); @@ -208,10 +211,56 @@ int runcmd(UAContext *ua, char *cmd) return 1; } + if (client_name) { + client = (CLIENT *)GetResWithName(R_CLIENT, client_name); + if (!client) { + bsendmsg(ua, _("Client %s not found.\n"), client_name); + client = select_client_resource(ua); + } + } else { + client = job->client; /* use default */ + } + if (!client) { + return 1; + } + + if (fileset_name) { + fileset = (FILESET *)GetResWithName(R_FILESET, fileset_name); + if (!fileset) { + bsendmsg(ua, _("FileSet %s not found.\n"), fileset_name); + fileset = select_fileset_resource(ua); + } + } else { + fileset = job->fileset; /* use default */ + } + if (!fileset) { + return 1; + } + + + /* Create JCR to run job */ jcr = new_jcr(sizeof(JCR), dird_free_jcr); set_jcr_defaults(jcr, job); init_msg(jcr, jcr->msgs); /* start message handler */ - jcr->store = store; /* set possible new Storage */ + + jcr->store = store; + jcr->client = client; + jcr->fileset = fileset; + if (where) { + if (jcr->RestoreWhere) { + free(jcr->RestoreWhere); + } + jcr->RestoreWhere = bstrdup(where); + } + if (bootstrap) { + if (jcr->RestoreBootstrap) { + free(jcr->RestoreBootstrap); + } + jcr->RestoreBootstrap = bstrdup(bootstrap); + } + + + try_again: Dmsg1(20, "JobType=%c\n", jcr->JobType); @@ -393,7 +442,7 @@ JobId: %s\n"), break; case 3: /* FileSet */ - fileset = select_fs_resource(ua); + fileset = select_fileset_resource(ua); if (fileset) { jcr->fileset = fileset; goto try_again; diff --git a/bacula/src/dird/ua_select.c b/bacula/src/dird/ua_select.c index ce5fb94d46..3b4a6bb67b 100644 --- a/bacula/src/dird/ua_select.c +++ b/bacula/src/dird/ua_select.c @@ -132,7 +132,7 @@ STORE *select_storage_resource(UAContext *ua) /* * Select a FileSet resource from prompt list */ -FILESET *select_fs_resource(UAContext *ua) +FILESET *select_fileset_resource(UAContext *ua) { char name[MAX_NAME_LENGTH]; FILESET *fs = NULL; diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index 2648256acb..f746ce66e2 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -105,7 +105,7 @@ struct s_jcr { time_t end_time; /* job end time */ POOLMEM *VolumeName; /* Volume name desired -- pool_memory */ POOLMEM *client_name; /* client name */ - POOLMEM *RestoreBootstrap; /* Bootstrap file to restore */ + char *RestoreBootstrap; /* Bootstrap file to restore */ char *sd_auth_key; /* SD auth key */ MSGS *msgs; /* Message resource */ diff --git a/bacula/src/lib/lex.h b/bacula/src/lib/lex.h index d52542ac3c..f73beed615 100644 --- a/bacula/src/lib/lex.h +++ b/bacula/src/lib/lex.h @@ -99,6 +99,7 @@ typedef struct s_lex_context { int32_t int32_val; int64_t int64_val; void (*scan_error)(char *file, int line, struct s_lex_context *lc, char *msg, ...); + void *caller_ctx; /* caller private data */ } LEX; typedef void (LEX_ERROR_HANDLER)(char *file, int line, LEX *lc, char *msg, ...); diff --git a/bacula/src/stored/bextract.c b/bacula/src/stored/bextract.c index c7e8206ab7..903de5ddae 100644 --- a/bacula/src/stored/bextract.c +++ b/bacula/src/stored/bextract.c @@ -79,7 +79,7 @@ int main (int argc, char *argv[]) while ((ch = getopt(argc, argv, "b:d:e:i:?")) != -1) { switch (ch) { case 'b': /* bootstrap file */ - bsr = parse_bsr(optarg); + bsr = parse_bsr(NULL, optarg); dump_bsr(bsr); break; diff --git a/bacula/src/stored/fd_cmds.c b/bacula/src/stored/fd_cmds.c index 90cec7925c..5424b89a6f 100644 --- a/bacula/src/stored/fd_cmds.c +++ b/bacula/src/stored/fd_cmds.c @@ -329,12 +329,13 @@ static int bootstrap_cmd(JCR *jcr) goto bail_out; } while (bnet_recv(fd) > 0) { - Dmsg1(200, "storedmsg); + Dmsg1(000, "storedmsg); fputs(fd->msg, bs); } fclose(bs); - jcr->bsr = parse_bsr(jcr->RestoreBootstrap); + jcr->bsr = parse_bsr(jcr, jcr->RestoreBootstrap); if (!jcr->bsr) { + Jmsg(jcr, M_FATAL, 0, _("Error parsing bootstrap file.\n")); goto bail_out; } if (debug_level > 20) { diff --git a/bacula/src/stored/job.c b/bacula/src/stored/job.c index cd6e49693c..4c873d3a01 100644 --- a/bacula/src/stored/job.c +++ b/bacula/src/stored/job.c @@ -329,6 +329,7 @@ void stored_free_jcr(JCR *jcr) } if (jcr->bsr) { free_bsr(jcr->bsr); + jcr->bsr = NULL; } if (jcr->RestoreBootstrap) { unlink(jcr->RestoreBootstrap); diff --git a/bacula/src/stored/parse_bsr.c b/bacula/src/stored/parse_bsr.c index 1d5ba45a25..4cd7cba3d7 100755 --- a/bacula/src/stored/parse_bsr.c +++ b/bacula/src/stored/parse_bsr.c @@ -82,6 +82,7 @@ static BSR *new_bsr() */ static void s_err(char *file, int line, LEX *lc, char *msg, ...) { + JCR *jcr = (JCR *)(lc->caller_ctx); va_list arg_ptr; char buf[MAXSTRING]; @@ -89,9 +90,15 @@ static void s_err(char *file, int line, LEX *lc, char *msg, ...) bvsnprintf(buf, sizeof(buf), msg, arg_ptr); va_end(arg_ptr); - e_msg(file, line, M_FATAL, 0, "Config error: %s\n\ - : Line %d, col %d of file %s\n%s\n", - buf, lc->line_no, lc->col_no, lc->fname, lc->line); + if (jcr) { + Jmsg(jcr, M_FATAL, 0, _("Bootstrap file error: %s\n\ + : Line %d, col %d of file %s\n%s\n"), + buf, lc->line_no, lc->col_no, lc->fname, lc->line); + } else { + e_msg(file, line, M_FATAL, 0, _("Bootstrap file error: %s\n\ + : Line %d, col %d of file %s\n%s\n"), + buf, lc->line_no, lc->col_no, lc->fname, lc->line); + } } @@ -100,30 +107,31 @@ static void s_err(char *file, int line, LEX *lc, char *msg, ...) * Parse Bootstrap file * */ -BSR *parse_bsr(char *cf) +BSR *parse_bsr(JCR *jcr, char *cf) { LEX *lc = NULL; int token, i; BSR *root_bsr = new_bsr(); BSR *bsr = root_bsr; - Dmsg0(200, "Enter parse_bsf()\n"); + Dmsg1(200, "Enter parse_bsf %s\n", cf); lc = lex_open_file(lc, cf, s_err); + lc->caller_ctx = (void *)jcr; while ((token=lex_get_token(lc, T_ALL)) != T_EOF) { - Dmsg1(150, "parse got token=%s\n", lex_tok_to_str(token)); + Dmsg1(200, "parse got token=%s\n", lex_tok_to_str(token)); if (token == T_EOL) { continue; } for (i=0; items[i].name; i++) { if (strcasecmp(items[i].name, lc->str) == 0) { token = lex_get_token(lc, T_ALL); - Dmsg1 (150, "in T_IDENT got token=%s\n", lex_tok_to_str(token)); + Dmsg1 (200, "in T_IDENT got token=%s\n", lex_tok_to_str(token)); if (token != T_EQUALS) { scan_err1(lc, "expected an equals, got: %s", lc->str); bsr = NULL; break; } - Dmsg1(100, "calling handler for %s\n", items[i].name); + Dmsg1(200, "calling handler for %s\n", items[i].name); /* Call item handler */ bsr = items[i].handler(lc, bsr); i = -1; @@ -131,8 +139,9 @@ BSR *parse_bsr(char *cf) } } if (i >= 0) { - Dmsg1(150, "Keyword = %s\n", lc->str); + Dmsg1(200, "Keyword = %s\n", lc->str); scan_err1(lc, "Keyword %s not found", lc->str); + bsr = NULL; break; } if (!bsr) { diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 2ec6d357e5..95eb7e6b33 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -28,107 +28,107 @@ uint32_t new_VolSessionId(); /* From askdir.c */ -int dir_get_volume_info(JCR *jcr); -int dir_find_next_appendable_volume(JCR *jcr); -int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel); -int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev); -int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev); -int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec); -int dir_send_job_status(JCR *jcr); -int dir_create_job_media_record(JCR *jcr); +int dir_get_volume_info(JCR *jcr); +int dir_find_next_appendable_volume(JCR *jcr); +int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel); +int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev); +int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev); +int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec); +int dir_send_job_status(JCR *jcr); +int dir_create_job_media_record(JCR *jcr); /* authenticate.c */ -int authenticate_director(JCR *jcr); -int authenticate_filed(JCR *jcr); +int authenticate_director(JCR *jcr); +int authenticate_filed(JCR *jcr); /* From block.c */ -void dump_block(DEV_BLOCK *b, char *msg); +void dump_block(DEV_BLOCK *b, char *msg); DEV_BLOCK *new_block(DEVICE *dev); -void init_block_write(DEV_BLOCK *block); -void empty_block(DEV_BLOCK *block); -void free_block(DEV_BLOCK *block); -int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block); -int read_block_from_device(DEVICE *dev, DEV_BLOCK *block); -int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block); +void init_block_write(DEV_BLOCK *block); +void empty_block(DEV_BLOCK *block); +void free_block(DEV_BLOCK *block); +int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block); +int read_block_from_device(DEVICE *dev, DEV_BLOCK *block); +int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block); /* From dev.c */ -DEVICE *init_dev(DEVICE *dev, char *device); -int open_dev(DEVICE *dev, char *VolName, int mode); -void close_dev(DEVICE *dev); -void force_close_dev(DEVICE *dev); -int truncate_dev(DEVICE *dev); -void term_dev(DEVICE *dev); -char * strerror_dev(DEVICE *dev); -void clrerror_dev(DEVICE *dev, int func); -int update_pos_dev(DEVICE *dev); -int rewind_dev(DEVICE *dev); -int load_dev(DEVICE *dev); -int offline_dev(DEVICE *dev); -int flush_dev(DEVICE *dev); -int weof_dev(DEVICE *dev, int num); -int write_block(DEVICE *dev); -int write_dev(DEVICE *dev, char *buf, size_t len); -int read_dev(DEVICE *dev, char *buf, size_t len); -int status_dev(DEVICE *dev, uint32_t *status); -int eod_dev(DEVICE *dev); -int fsf_dev(DEVICE *dev, int num); -int fsr_dev(DEVICE *dev, int num); -int bsf_dev(DEVICE *dev, int num); -int bsr_dev(DEVICE *dev, int num); +DEVICE *init_dev(DEVICE *dev, char *device); +int open_dev(DEVICE *dev, char *VolName, int mode); +void close_dev(DEVICE *dev); +void force_close_dev(DEVICE *dev); +int truncate_dev(DEVICE *dev); +void term_dev(DEVICE *dev); +char * strerror_dev(DEVICE *dev); +void clrerror_dev(DEVICE *dev, int func); +int update_pos_dev(DEVICE *dev); +int rewind_dev(DEVICE *dev); +int load_dev(DEVICE *dev); +int offline_dev(DEVICE *dev); +int flush_dev(DEVICE *dev); +int weof_dev(DEVICE *dev, int num); +int write_block(DEVICE *dev); +int write_dev(DEVICE *dev, char *buf, size_t len); +int read_dev(DEVICE *dev, char *buf, size_t len); +int status_dev(DEVICE *dev, uint32_t *status); +int eod_dev(DEVICE *dev); +int fsf_dev(DEVICE *dev, int num); +int fsr_dev(DEVICE *dev, int num); +int bsf_dev(DEVICE *dev, int num); +int bsr_dev(DEVICE *dev, int num); /* Get info about device */ -char * dev_name(DEVICE *dev); -char * dev_vol_name(DEVICE *dev); +char * dev_name(DEVICE *dev); +char * dev_vol_name(DEVICE *dev); uint32_t dev_block(DEVICE *dev); uint32_t dev_file(DEVICE *dev); -int dev_is_tape(DEVICE *dev); +int dev_is_tape(DEVICE *dev); /* From device.c */ -int open_device(DEVICE *dev); -int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -int ready_dev_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -int release_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void block_device(DEVICE *dev, int state); -void unblock_device(DEVICE *dev); -void lock_device(DEVICE *dev); -void unlock_device(DEVICE *dev); -int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int open_device(DEVICE *dev); +int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int ready_dev_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +int release_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void block_device(DEVICE *dev, int state); +void unblock_device(DEVICE *dev); +void lock_device(DEVICE *dev); +void unlock_device(DEVICE *dev); +int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); /* From dircmd.c */ -void connection_request(void *arg); +void connection_request(void *arg); /* From fd_cmds.c */ -void run_job(JCR *jcr); +void run_job(JCR *jcr); /* From fdmsg.c */ -int bget_msg(BSOCK *sock); +int bget_msg(BSOCK *sock); /* From job.c */ -void stored_free_jcr(JCR *jcr); -void connection_from_filed(void *arg); -void handle_filed_connection(BSOCK *fd, char *job_name); +void stored_free_jcr(JCR *jcr); +void connection_from_filed(void *arg); +void handle_filed_connection(BSOCK *fd, char *job_name); /* From label.c */ -int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void create_session_label(JCR *jcr, DEV_RECORD *rec, int label); -int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName); -int write_session_label(JCR *jcr, DEV_BLOCK *block, int label); -int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void dump_volume_label(DEVICE *dev); -void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose); -int unser_volume_label(DEVICE *dev, DEV_RECORD *rec); -int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec); +int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void create_session_label(JCR *jcr, DEV_RECORD *rec, int label); +int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName); +int write_session_label(JCR *jcr, DEV_BLOCK *block, int label); +int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +void dump_volume_label(DEVICE *dev); +void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose); +int unser_volume_label(DEVICE *dev, DEV_RECORD *rec); +int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec); /* From match_bsr.c */ int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, - SESSION_LABEL *sesrec); + SESSION_LABEL *sesrec); /* From parse_bsr.c */ -extern BSR *parse_bsr(char *lf); +extern BSR *parse_bsr(JCR *jcr, char *lf); extern void dump_bsr(BSR *bsr); extern void free_bsr(BSR *bsr); extern VOL_LIST *new_vol(); @@ -139,9 +139,9 @@ extern void create_vol_list(JCR *jcr); /* From record.c */ char *FI_to_ascii(int fi); char *stream_to_ascii(int stream); -int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); -int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); +int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); +int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); DEV_RECORD *new_record(); -void free_record(DEV_RECORD *rec); -int read_record(DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record); -int write_record_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record); +void free_record(DEV_RECORD *rec); +int read_record(DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record); +int write_record_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record); -- 2.39.5