From 9a421324844731a953f596a7063c49cd7aa23bb8 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Thu, 18 Jul 2002 17:40:22 +0000 Subject: [PATCH] Add RunBeforeJob and RunAfterJob -- kes18Jul02 git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@64 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/dird/dird_conf.c | 14 +++ bacula/src/dird/dird_conf.h | 2 + bacula/src/dird/job.c | 98 ++++++++++++++++++ bacula/src/lib/message.c | 130 ++++-------------------- bacula/src/lib/protos.h | 181 +++++++++++++++++---------------- bacula/src/lib/util.c | 196 ++++++++++++++++++++++++++++-------- bacula/src/stored/dev.c | 5 +- bacula/src/stored/device.c | 2 +- 8 files changed, 384 insertions(+), 244 deletions(-) diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index 1cc6195c4a..a16f3aa335 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -177,6 +177,8 @@ static struct res_items job_items[] = { {"prunejobs", store_yesno, ITEM(res_job.PruneJobs), 1, ITEM_DEFAULT, 0}, {"prunefiles", store_yesno, ITEM(res_job.PruneFiles), 1, ITEM_DEFAULT, 0}, {"prunevolumes", store_yesno, ITEM(res_job.PruneVolumes), 1, ITEM_DEFAULT, 0}, + {"runbeforejob", store_str, ITEM(res_job.RunBeforeJob), 0, 0, 0}, + {"runafterjob", store_str, ITEM(res_job.RunAfterJob), 0, 0, 0}, {NULL, NULL, NULL, 0, 0, 0} }; @@ -476,6 +478,12 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ... if (res->res_job.RestoreBootstrap) { sendit(sock, " --> Bootstrap=%s\n", NPRT(res->res_job.RestoreBootstrap)); } + if (res->res_job.RunBeforeJob) { + sendit(sock, " --> RunBefore=%s\n", NPRT(res->res_job.RunBeforeJob)); + } + if (res->res_job.RunAfterJob) { + sendit(sock, " --> RunAfter=%s\n", NPRT(res->res_job.RunAfterJob)); + } if (res->res_job.storage) { sendit(sock, " --> "); dump_resource(-R_STORAGE, (RES *)res->res_job.storage, sendit, sock); @@ -703,6 +711,12 @@ void free_resource(int type) if (res->res_job.RestoreBootstrap) { free(res->res_job.RestoreBootstrap); } + if (res->res_job.RunBeforeJob) { + free(res->res_job.RunBeforeJob); + } + if (res->res_job.RunAfterJob) { + free(res->res_job.RunAfterJob); + } break; case R_MSGS: if (res->res_msgs.mail_cmd) diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index 603ca943aa..079b80835a 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -156,6 +156,8 @@ struct s_res_job { 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 */ diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index 0900b33d96..e72bd5e60f 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -31,6 +31,7 @@ /* Forward referenced subroutines */ static void job_thread(void *arg); +static char *edit_run_codes(JCR *jcr, char *omsg, char *imsg); /* Exported subroutines */ void run_job(JCR *jcr); @@ -151,6 +152,14 @@ static void job_thread(void *arg) /* Run Job */ jcr->JobStatus = JS_Running; + if (jcr->job->RunBeforeJob) { + POOLMEM *before = get_pool_memory(PM_FNAME); + int status; + + before = edit_run_codes(jcr, before, jcr->job->RunBeforeJob); + status = run_program(before, 0, NULL); + free_pool_memory(before); + } switch (jcr->JobType) { case JT_BACKUP: do_backup(jcr); @@ -179,6 +188,14 @@ static void job_thread(void *arg) break; } } + if (jcr->job->RunAfterJob) { + POOLMEM *after = get_pool_memory(PM_FNAME); + int status; + + after = edit_run_codes(jcr, after, jcr->job->RunAfterJob); + status = run_program(after, 0, NULL); + free_pool_memory(after); + } Dmsg0(50, "Before free jcr\n"); free_jcr(jcr); Dmsg0(50, "======== End Job ==========\n"); @@ -360,3 +377,84 @@ void set_jcr_defaults(JCR *jcr, JOB *job) } } } + +/* + * Edit codes into Run command + * %% = % + * %c = Client's name + * %d = Director's name + * %i = JobId + * %e = Job Exit + * %j = Job + * %l = Job Level + * %n = Job name + * %t = Job type + * + * omsg = edited output message + * imsg = input string containing edit codes (%x) + * + */ +static char *edit_run_codes(JCR *jcr, char *omsg, char *imsg) +{ + char *p, *o; + const char *str; + char add[20]; + + Dmsg1(200, "edit_run_codes: %s\n", imsg); + add[2] = 0; + o = omsg; + for (p=imsg; *p; p++) { + if (*p == '%') { + switch (*++p) { + case '%': + add[0] = '%'; + add[1] = 0; + str = add; + break; + case 'c': + str = jcr->client_name; + if (!str) { + str = ""; + } + break; + case 'd': + str = my_name; + break; + case 'e': + str = job_status_to_str(jcr->JobStatus); + break; + case 'i': + sprintf(add, "%d", jcr->JobId); + str = add; + break; + case 'j': /* Job */ + str = jcr->Job; + break; + case 'l': + str = job_level_to_str(jcr->JobLevel); + break; + case 'n': + str = jcr->job->hdr.name; + break; + case 't': + str = job_type_to_str(jcr->JobType); + break; + default: + add[0] = '%'; + add[1] = *p; + str = add; + break; + } + } else { + add[0] = *p; + add[1] = 0; + str = add; + } + Dmsg1(200, "add_str %s\n", str); + add_str_to_pool_mem(&omsg, &o, (char *)str); + *o = 0; + Dmsg1(200, "omsg=%s\n", omsg); + } + *o = 0; + return omsg; +} diff --git a/bacula/src/lib/message.c b/bacula/src/lib/message.c index 1408e31b47..6639f0e3b8 100755 --- a/bacula/src/lib/message.c +++ b/bacula/src/lib/message.c @@ -279,103 +279,6 @@ void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where) } -/* - * Convert Job Termination Status into a string - */ -static char *job_status_to_str(int stat) -{ - char *str; - - switch (stat) { - case JS_Terminated: - str = "OK"; - break; - case JS_ErrorTerminated: - case JS_Error: - str = "Error"; - break; - case JS_FatalError: - str = "Fatal Error"; - break; - case JS_Cancelled: - str = "Cancelled"; - break; - case JS_Differences: - str = "Differences"; - break; - default: - str = "Unknown term code"; - break; - } - return str; -} - - -/* - * Convert Job Type into a string - */ -static char *job_type_to_str(int type) -{ - char *str; - - switch (type) { - case JT_BACKUP: - str = "Backup"; - break; - case JT_VERIFY: - str = "Verify"; - break; - case JT_RESTORE: - str = "Restore"; - break; - default: - str = "Unknown Job Type"; - break; - } - return str; -} - -/* - * Convert Job Level into a string - */ -static char *job_level_to_str(int level) -{ - char *str; - - switch (level) { - case L_FULL: - str = "full"; - break; - case L_INCREMENTAL: - str = "incremental"; - break; - case L_DIFFERENTIAL: - str = "differential"; - break; - case L_LEVEL: - str = "level"; - break; - case L_SINCE: - str = "since"; - break; - case L_VERIFY_CATALOG: - str = "verify catalog"; - break; - case L_VERIFY_INIT: - str = "verify init"; - break; - case L_VERIFY_VOLUME_TO_CATALOG: - str = "verify volume to catalog"; - break; - case L_VERIFY_DATA: - str = "verify data"; - break; - default: - str = "Unknown Job level"; - break; - } - return str; -} /* @@ -384,6 +287,7 @@ static char *job_level_to_str(int level) * %j = Job name * %t = Job type (Backup, ...) * %e = Job Exit code + * %i = JobId * %l = job level * %c = Client's name * %r = Recipients @@ -397,7 +301,7 @@ static char *job_level_to_str(int level) static char *edit_job_codes(JCR *jcr, char *omsg, char *imsg, char *to) { char *p, *o, *str; - char add[3]; + char add[20]; Dmsg1(200, "edit_job_codes: %s\n", imsg); add[2] = 0; @@ -410,29 +314,33 @@ static char *edit_job_codes(JCR *jcr, char *omsg, char *imsg, char *to) add[1] = 0; str = add; break; - case 'j': /* Job name */ - str = jcr->Job; + case 'c': + str = jcr->client_name; + if (!str) { + str = ""; + } + break; + case 'd': + str = my_name; /* Director's name */ break; case 'e': str = job_status_to_str(jcr->JobStatus); break; - case 't': - str = job_type_to_str(jcr->JobType); + case 'i': + sprintf(add, "%d", jcr->JobId); + str = add; break; - case 'r': - str = to; + case 'j': /* Job name */ + str = jcr->Job; break; case 'l': str = job_level_to_str(jcr->JobLevel); break; - case 'c': - str = jcr->client_name; - if (!str) { - str = ""; - } + case 'r': + str = to; break; - case 'd': - str = my_name; /* Director's name */ + case 't': + str = job_type_to_str(jcr->JobType); break; default: add[0] = '%'; diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index c461784ce1..2f54983fc0 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -24,138 +24,141 @@ */ /* base64.c */ -void base64_init (void); -int to_base64 (intmax_t value, char *where); -int from_base64 (intmax_t *value, char *where); -void encode_stat (char *buf, struct stat *statp); -void decode_stat (char *buf, struct stat *statp); -int bin_to_base64 (char *buf, char *bin, int len); +void base64_init (void); +int to_base64 (intmax_t value, char *where); +int from_base64 (intmax_t *value, char *where); +void encode_stat (char *buf, struct stat *statp); +void decode_stat (char *buf, struct stat *statp); +int bin_to_base64 (char *buf, char *bin, int len); /* bmisc.c */ -void *b_malloc (char *file, int line, size_t size); +void *b_malloc (char *file, int line, size_t size); #ifndef DEBUG -void *bmalloc (size_t size); +void *bmalloc (size_t size); #endif -void *brealloc (void *buf, size_t size); -void *bcalloc (size_t size1, size_t size2); -int bsnprintf (char *str, size_t size, const char *format, ...); -int bvsnprintf (char *str, size_t size, const char *format, va_list ap); -int pool_sprintf (char *pool_buf, char *fmt, ...); -void create_pid_file (char *dir, char *progname, int port); -int delete_pid_file (char *dir, char *progname, int port); +void *brealloc (void *buf, size_t size); +void *bcalloc (size_t size1, size_t size2); +int bsnprintf (char *str, size_t size, const char *format, ...); +int bvsnprintf (char *str, size_t size, const char *format, va_list ap); +int pool_sprintf (char *pool_buf, char *fmt, ...); +void create_pid_file (char *dir, char *progname, int port); +int delete_pid_file (char *dir, char *progname, int port); #ifndef HAVE_STRERROR_R -int strerror_r (int errnum, char *buf, size_t bufsiz); +int strerror_r (int errnum, char *buf, size_t bufsiz); #endif /* bnet.c */ -int32_t bnet_recv (BSOCK *bsock); -int bnet_send (BSOCK *bsock); -int bnet_fsend (BSOCK *bs, char *fmt, ...); -int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw); -int bnet_sig (BSOCK *bs, int sig); -BSOCK * bnet_connect (void *jcr, int retry_interval, - int max_retry_time, char *name, char *host, char *service, - int port, int verbose); -int bnet_wait_data (BSOCK *bsock, int sec); -void bnet_close (BSOCK *bsock); -BSOCK * init_bsock (int sockfd, char *who, char *ip, int port); -BSOCK * dup_bsock (BSOCK *bsock); -void term_bsock (BSOCK *bsock); -char * bnet_strerror (BSOCK *bsock); -char * bnet_sig_to_ascii (BSOCK *bsock); -int bnet_wait_data (BSOCK *bsock, int sec); +int32_t bnet_recv (BSOCK *bsock); +int bnet_send (BSOCK *bsock); +int bnet_fsend (BSOCK *bs, char *fmt, ...); +int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw); +int bnet_sig (BSOCK *bs, int sig); +BSOCK * bnet_connect (void *jcr, int retry_interval, + int max_retry_time, char *name, char *host, char *service, + int port, int verbose); +int bnet_wait_data (BSOCK *bsock, int sec); +void bnet_close (BSOCK *bsock); +BSOCK * init_bsock (int sockfd, char *who, char *ip, int port); +BSOCK * dup_bsock (BSOCK *bsock); +void term_bsock (BSOCK *bsock); +char * bnet_strerror (BSOCK *bsock); +char * bnet_sig_to_ascii (BSOCK *bsock); +int bnet_wait_data (BSOCK *bsock, int sec); /* cram-md5.c */ int cram_md5_get_auth(BSOCK *bs, char *password); int cram_md5_auth(BSOCK *bs, char *password); void hmac_md5(uint8_t* text, int text_len, uint8_t* key, - int key_len, uint8_t *hmac); + int key_len, uint8_t *hmac); /* create_file.c */ int create_file(void *jcr, char *fname, char *ofile, char *lname, - int type, struct stat *statp, int *ofd); + int type, struct stat *statp, int *ofd); int set_statp(void *jcr, char *fname, char *ofile, char *lname, int type, - struct stat *statp); + struct stat *statp); /* crc32.c */ uint32_t bcrc32(uint8_t *buf, int len); /* daemon.c */ -void daemon_start (); +void daemon_start (); /* lex.c */ -LEX * lex_close_file (LEX *lf); -LEX * lex_open_file (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error); -int lex_get_char (LEX *lf); -void lex_unget_char (LEX *lf); -char * lex_tok_to_str (int token); -int lex_get_token (LEX *lf, int expect); +LEX * lex_close_file (LEX *lf); +LEX * lex_open_file (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error); +int lex_get_char (LEX *lf); +void lex_unget_char (LEX *lf); +char * lex_tok_to_str (int token); +int lex_get_token (LEX *lf, int expect); /* makepath.c */ int make_path( - void *jcr, - const char *argpath, - int mode, - int parent_mode, - uid_t owner, - gid_t group, - int preserve_existing, - char *verbose_fmt_string); + void *jcr, + const char *argpath, + int mode, + int parent_mode, + uid_t owner, + gid_t group, + int preserve_existing, + char *verbose_fmt_string); /* message.c */ -void my_name_is (int argc, char *argv[], char *name); -void init_msg (void *jcr, MSGS *msg); -void term_msg (void); -void close_msg (void *jcr); -void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code); -void rem_msg_dest (MSGS *msg, int dest, int type, char *where); -void Jmsg (void *jcr, int type, int level, char *fmt, ...); -void dispatch_message (void *jcr, int type, int level, char *buf); -void init_console_msg (char *wd); -void free_msgs_res (MSGS *msgs); +void my_name_is (int argc, char *argv[], char *name); +void init_msg (void *jcr, MSGS *msg); +void term_msg (void); +void close_msg (void *jcr); +void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code); +void rem_msg_dest (MSGS *msg, int dest, int type, char *where); +void Jmsg (void *jcr, int type, int level, char *fmt, ...); +void dispatch_message (void *jcr, int type, int level, char *buf); +void init_console_msg (char *wd); +void free_msgs_res (MSGS *msgs); /* bnet_server.c */ -void bnet_thread_server(int port, int max_clients, workq_t *client_wq, - void handle_client_request(void *bsock)); -void bnet_server (int port, void handle_client_request(BSOCK *bsock)); -int net_connect (int port); -BSOCK * bnet_bind (int port); -BSOCK * bnet_accept (BSOCK *bsock, char *who); +void bnet_thread_server(int port, int max_clients, workq_t *client_wq, + void handle_client_request(void *bsock)); +void bnet_server (int port, void handle_client_request(BSOCK *bsock)); +int net_connect (int port); +BSOCK * bnet_bind (int port); +BSOCK * bnet_accept (BSOCK *bsock, char *who); /* signal.c */ -void init_signals (void terminate(int sig)); -void init_stack_dump (void); +void init_signals (void terminate(int sig)); +void init_stack_dump (void); /* util.c */ -void lcase (char *str); -void bash_spaces (char *str); -void unbash_spaces (char *str); -void strip_trailing_junk (char *str); -void strip_trailing_slashes (char *dir); -int skip_spaces (char **msg); -int skip_nonspaces (char **msg); -int fstrsch (char *a, char *b); -char * encode_time (time_t time, char *buf); -char * encode_mode (mode_t mode, char *buf); -char * edit_uint64_with_commas (uint64_t val, char *buf); -char * add_commas (char *val, char *buf); -char * edit_uint64 (uint64_t val, char *buf); -int do_shell_expansion (char *name); -int is_a_number (const char *num); -int string_to_btime (char *str, btime_t *value); -char *edit_btime (btime_t val, char *buf); -void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen); -void add_str_to_pool_mem (POOLMEM **base, char **msg, char *str); -int run_program (char *prog, int wait, POOLMEM *results); +void lcase (char *str); +void bash_spaces (char *str); +void unbash_spaces (char *str); +void strip_trailing_junk (char *str); +void strip_trailing_slashes (char *dir); +int skip_spaces (char **msg); +int skip_nonspaces (char **msg); +int fstrsch (char *a, char *b); +char * encode_time (time_t time, char *buf); +char * encode_mode (mode_t mode, char *buf); +char * edit_uint64_with_commas (uint64_t val, char *buf); +char * add_commas (char *val, char *buf); +char * edit_uint64 (uint64_t val, char *buf); +int do_shell_expansion (char *name); +int is_a_number (const char *num); +int string_to_btime (char *str, btime_t *value); +char *edit_btime (btime_t val, char *buf); +void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen); +void add_str_to_pool_mem (POOLMEM **base, char **msg, char *str); +int run_program (char *prog, int wait, POOLMEM *results); +char * job_type_to_str (int type); +char * job_status_to_str (int stat); +char * job_level_to_str (int level); /* - *void print_ls_output (char *fname, char *lname, int type, struct stat *statp); + *void print_ls_output (char *fname, char *lname, int type, struct stat *statp); */ /* watchdog.c */ diff --git a/bacula/src/lib/util.c b/bacula/src/lib/util.c index 290563355e..5bf396db94 100644 --- a/bacula/src/lib/util.c +++ b/bacula/src/lib/util.c @@ -376,6 +376,105 @@ void jobstatus_to_ascii(int JobStatus, char *msg, int maxlen) msg[maxlen-1] = 0; } +/* + * Convert Job Termination Status into a string + */ +char *job_status_to_str(int stat) +{ + char *str; + + switch (stat) { + case JS_Terminated: + str = "OK"; + break; + case JS_ErrorTerminated: + case JS_Error: + str = "Error"; + break; + case JS_FatalError: + str = "Fatal Error"; + break; + case JS_Cancelled: + str = "Cancelled"; + break; + case JS_Differences: + str = "Differences"; + break; + default: + str = "Unknown term code"; + break; + } + return str; +} + + +/* + * Convert Job Type into a string + */ +char *job_type_to_str(int type) +{ + char *str; + + switch (type) { + case JT_BACKUP: + str = "Backup"; + break; + case JT_VERIFY: + str = "Verify"; + break; + case JT_RESTORE: + str = "Restore"; + break; + default: + str = "Unknown Job Type"; + break; + } + return str; +} + +/* + * Convert Job Level into a string + */ +char *job_level_to_str(int level) +{ + char *str; + + switch (level) { + case L_FULL: + str = "full"; + break; + case L_INCREMENTAL: + str = "incremental"; + break; + case L_DIFFERENTIAL: + str = "differential"; + break; + case L_LEVEL: + str = "level"; + break; + case L_SINCE: + str = "since"; + break; + case L_VERIFY_CATALOG: + str = "verify catalog"; + break; + case L_VERIFY_INIT: + str = "verify init"; + break; + case L_VERIFY_VOLUME_TO_CATALOG: + str = "verify volume to catalog"; + break; + case L_VERIFY_DATA: + str = "verify data"; + break; + default: + str = "Unknown Job level"; + break; + } + return str; +} + + /*********************************************************************** * Encode the mode bits into a 10 character string like LS does ***********************************************************************/ @@ -549,20 +648,25 @@ int do_shell_expansion(char *name) } #define MAX_ARGV 100 -static char *bargv[MAX_ARGV]; -static int bargc; -static void build_argc_argv(char *cmd); +static void build_argc_argv(char *cmd, int *bargc, char *bargv[], int max_arg); +/* + * Run an external program. Optionally wait a specified number + * of seconds. Program killed if wait exceeded. Optionally + * return the output from the program (normally a single line). + */ int run_program(char *prog, int wait, POOLMEM *results) { int stat = ETIME; int chldstatus = 0; pid_t pid1, pid2; int pfd[2]; + char *bargv[MAX_ARGV]; + int bargc; - build_argc_argv(prog); -#ifdef xxxxxxxxxxx + build_argc_argv(prog, &bargc, bargv, MAX_ARGV); +#ifdef xxxxxxxxxx printf("argc=%d\n", bargc); int i; for (i=0; i 0) { + switch (pid2=fork()) { + case -1: + break; + case 0: /* child 2 */ + /* Time the worker process */ + sleep(wait); + if (kill(pid1, SIGTERM) == 0) { /* time expired kill it */ + exit(0); + } + sleep(3); + kill(pid1, SIGKILL); exit(0); + default: /* parent */ + break; } - sleep(3); - kill(pid1, SIGKILL); - exit(0); - default: /* parent */ - int i; - if (results) { - i = read(pfd[0], results, sizeof_pool_memory(results) - 1); - if (--i < 0) { - i = 0; - } - results[i] = 0; /* set end of string */ + } + + /* Parent continues here */ + int i; + if (results) { + i = read(pfd[0], results, sizeof_pool_memory(results) - 1); + if (--i < 0) { + i = 0; } - /* wait for worker child to exit */ - for ( ;; ) { - pid_t wpid; - wpid = waitpid(pid1, &chldstatus, 0); - if (wpid == pid1 || (errno != EINTR)) { - break; - } + results[i] = 0; /* set end of string */ + } + /* wait for worker child to exit */ + for ( ;; ) { + pid_t wpid; + wpid = waitpid(pid1, &chldstatus, 0); + if (wpid == pid1 || (errno != EINTR)) { + break; } - if (WIFEXITED(chldstatus)) - stat = WEXITSTATUS(chldstatus); + } + if (WIFEXITED(chldstatus)) + stat = WEXITSTATUS(chldstatus); + if (wait > 0) { kill(pid2, SIGKILL); /* kill off timer process */ waitpid(pid2, &chldstatus, 0); /* reap timer process */ - if (results) { - close(pfd[0]); /* close pipe */ - close(pfd[1]); - } - break; + } + if (results) { + close(pfd[0]); /* close pipe */ + close(pfd[1]); } break; } @@ -637,13 +747,14 @@ int run_program(char *prog, int wait, POOLMEM *results) /* * Build argc and argv from a string */ -static void build_argc_argv(char *cmd) +static void build_argc_argv(char *cmd, int *bargc, char *bargv[], int max_argv) { int i, quote; char *p, *q; + int argc = 0; - bargc = 0; - for (i=0; imode = O_RDONLY | O_BINARY; } timeout = dev->max_open_wait; + errno = 0; while ((dev->fd = open(dev->dev_name, dev->mode, MODE_RW)) < 0) { if (errno == EBUSY && timeout-- > 0) { + Dmsg2(100, "Device %s busy. ERR=%s\n", dev->dev_name, strerror(errno)); sleep(1); continue; } @@ -219,8 +221,9 @@ open_dev(DEVICE *dev, char *VolName, int mode) Mmsg2(&dev->errmsg, _("stored: unable to open device %s: ERR=%s\n"), dev->dev_name, strerror(dev->dev_errno)); Emsg0(M_FATAL, 0, dev->errmsg); + break; } - if (dev->fd < 0) { + if (dev->fd >= 0) { dev->dev_errno = 0; dev->state |= ST_OPENED; dev->use_count++; diff --git a/bacula/src/stored/device.c b/bacula/src/stored/device.c index ef9163425c..9ff3b759f4 100644 --- a/bacula/src/stored/device.c +++ b/bacula/src/stored/device.c @@ -833,7 +833,7 @@ static char *edit_device_codes(JCR *jcr, char *omsg, char *imsg, char *cmd) const char *str; char add[20]; - Dmsg1(200, "edit_job_codes: %s\n", imsg); + Dmsg1(200, "edit_device_codes: %s\n", imsg); add[2] = 0; o = omsg; for (p=imsg; *p; p++) { -- 2.39.2