From: Michal Rakowski Date: Wed, 14 Apr 2021 17:01:08 +0000 (+0200) Subject: Fix #7448 About extending 'list jobs' with hours and days parameters X-Git-Tag: Release-11.3.2~571 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a827528899dc365670c600999d7831401734c201;p=thirdparty%2Fbacula.git Fix #7448 About extending 'list jobs' with hours and days parameters --- diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index e9998c73d..fa26e47d5 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -168,6 +168,8 @@ struct JOB_DBR { faddr_t rec_addr; int32_t FileIndex; /* added during Verify */ + char FromDate[MAX_TIME_LENGTH]; /* Used for filtering job records ('days' and 'hours' in list cmd) */ + int CorrNbJob; /* used by dbd_get_job_statistics() */ int CorrJobBytes; /* used by dbd_get_job_statistics() */ int CorrJobFiles; /* used by dbd_get_job_statistics() */ diff --git a/bacula/src/cats/sql_list.c b/bacula/src/cats/sql_list.c index 37172d2c5..878c516d0 100644 --- a/bacula/src/cats/sql_list.c +++ b/bacula/src/cats/sql_list.c @@ -760,6 +760,12 @@ alist *BDB::bdb_list_job_records(JCR *jcr, JOB_DBR *jr, DB_LIST_HANDLER *sendit, append_filter(&where, tmp); } + if (jr->FromDate[0]) { + bdb_escape_string(jcr, esc, jr->FromDate, strlen(jr->FromDate)); + Mmsg(tmp, " Job.StartTime >= '%s' ", esc); + append_filter(&where, tmp); + } + where_tmp = get_acls(DB_ACL_BIT(DB_ACL_CLIENT) | DB_ACL_BIT(DB_ACL_JOB) | DB_ACL_BIT(DB_ACL_FILESET), diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 083ec405a..bd1523988 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -131,7 +131,7 @@ static struct cmdstruct commands[] = { /* C { NT_("label"), label_cmd, _("Label a tape"), NT_("storage= volume= pool= slot= drive= barcodes [yes]"), false}, { NT_("list"), list_cmd, _("List objects from catalog"), - NT_("jobs [client=] [jobid=] [ujobid=] [job=] [tag=] [joberrors] [jobstatus=] [level=] [jobtype=] [limit=] [order=]|\n" + NT_("jobs [client=] [jobid=] [ujobid=] [job=] [tag=] [joberrors] [jobstatus=] [level=] [jobtype=] [days=] [hours=] [limit=] [order=]|\n" "\tjobtotals | pools | volume | media | files [type=] jobid= | copies jobid= |\n" "\tjoblog jobid= | pluginrestoreconf jobid= restoreobjectid= | snapshot | \n" "\tfilemedia jobid= fileindex= | clients\n" diff --git a/bacula/src/dird/ua_output.c b/bacula/src/dird/ua_output.c index 8305687a0..2a918d954 100644 --- a/bacula/src/dird/ua_output.c +++ b/bacula/src/dird/ua_output.c @@ -355,6 +355,27 @@ int list_cmd(UAContext *ua, const char *cmd) } } +/* Simple helper to setup date used for filtering records. + * Value can be passed as a days or hours count */ +static bool setup_start_date(const char *val, bool days, char *dest, uint32_t dest_len) +{ + time_t stime; + struct tm tm; + int hours_count; + + if (!is_an_integer(val)) { + return false; + } + + /* Do we have hours or days count */ + hours_count = days ? 24 : 1; + stime = time(NULL) - atoi(val) * hours_count * 60*60; + (void)localtime_r(&stime, &tm); + strftime(dest, dest_len, "%Y-%m-%d %H:%M:%S", &tm); + + return true; +} + static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) { POOLMEM *VolumeName; @@ -422,6 +443,16 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) jr.ClientId = cr.ClientId; } } + } else if (strcasecmp(ua->argk[j], NT_("days")) == 0 && ua->argv[j]) { + if (!setup_start_date(ua->argv[j], true, jr.FromDate, sizeof(jr.FromDate))) { + ua->error_msg(_("Expected integer passed as a days count, got: %s\n"), ua->argv[j]); + return 1; + } + } else if (strcasecmp(ua->argk[j], NT_("hours")) == 0 && ua->argv[j]) { + if (!setup_start_date(ua->argv[j], false, jr.FromDate, sizeof(jr.FromDate))) { + ua->error_msg(_("Expected integer passed as a hours count, got: %s\n"), ua->argv[j]); + return 1; + } } } @@ -818,8 +849,6 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) } else if (strcasecmp(ua->argk[i], NT_("events")) == 0) { EVENTS_DBR event; - time_t stime; - struct tm tm; for (j=i+1; jargc; j++) { if (strcasecmp(ua->argk[j], NT_("type")) == 0 && ua->argv[j]) { @@ -833,10 +862,15 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) event.order = bstrcasecmp(ua->argv[j], "DESC") == 0; } else if (strcasecmp(ua->argk[j], NT_("days")) == 0 && ua->argv[j]) { - stime = time(NULL) - atoi(ua->argv[j]) * 24*60*60; - (void)localtime_r(&stime, &tm); - strftime(event.start, sizeof(event.start), "%Y-%m-%d %H:%M:%S", &tm); - + if (!setup_start_date(ua->argv[j], true, event.start, sizeof(event.start))) { + ua->error_msg(_("Expected integer passed as a days count, got: %s\n"), ua->argv[j]); + return 1; + } + } else if (strcasecmp(ua->argk[j], NT_("hours")) == 0 && ua->argv[j]) { + if (!setup_start_date(ua->argv[j], false, event.start, sizeof(event.start))) { + ua->error_msg(_("Expected integer passed as a hours count, got: %s\n"), ua->argv[j]); + return 1; + } } else if (strcasecmp(ua->argk[j], NT_("start")) == 0 && ua->argv[j]) { bstrncpy(event.start, ua->argv[j], sizeof(event.start)); /* TODO: check format */ @@ -860,6 +894,7 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) } else if (strcasecmp(ua->argk[i], NT_("limit")) == 0 || strcasecmp(ua->argk[i], NT_("days")) == 0 + || strcasecmp(ua->argk[i], NT_("hours")) == 0 || strcasecmp(ua->argk[i], NT_("joberrors")) == 0 || strcasecmp(ua->argk[i], NT_("order")) == 0 || strcasecmp(ua->argk[i], NT_("jobstatus")) == 0