diff --git a/src/cats/protos.h b/src/cats/protos.h index c38f0b8bb21..1dbf80696c7 100644 --- a/src/cats/protos.h +++ b/src/cats/protos.h @@ -122,6 +122,7 @@ void db_list_pool_records(JCR *jcr, B_DB *db, POOL_DBR *pr, OUTPUT_FORMATTER *se void db_list_job_records(JCR *jcr, B_DB *db, JOB_DBR *jr, OUTPUT_FORMATTER *sendit, e_list_type type); void db_list_job_totals(JCR *jcr, B_DB *db, JOB_DBR *jr, OUTPUT_FORMATTER *sendit); void db_list_files_for_job(JCR *jcr, B_DB *db, uint32_t jobid, OUTPUT_FORMATTER *sendit); +void db_list_filesets(JCR *jcr, B_DB *mdb, JOB_DBR *jr, OUTPUT_FORMATTER *sendit, e_list_type type); void db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr, OUTPUT_FORMATTER *sendit, e_list_type type); void db_list_jobmedia_records(JCR *jcr, B_DB *mdb, JobId_t JobId, OUTPUT_FORMATTER *sendit, e_list_type type); void db_list_joblog_records(JCR *jcr, B_DB *mdb, JobId_t JobId, OUTPUT_FORMATTER *sendit, e_list_type type); diff --git a/src/cats/sql_list.c b/src/cats/sql_list.c index a3bc1626458..513e61bb4d6 100644 --- a/src/cats/sql_list.c +++ b/src/cats/sql_list.c @@ -534,4 +534,53 @@ void db_list_base_files_for_job(JCR *jcr, B_DB *mdb, JobId_t jobid, OUTPUT_FORMA db_unlock(mdb); } +/* + * List fileset + */ +void db_list_filesets(JCR *jcr, B_DB *mdb, JOB_DBR *jr, OUTPUT_FORMATTER *sendit, + e_list_type type) +{ + POOL_MEM str_limit(PM_MESSAGE); + char esc[MAX_ESCAPE_NAME_LENGTH]; + + db_lock(mdb); + if (jr->limit > 0) { + Mmsg(str_limit, " LIMIT %d", jr->limit); + } + + if (jr->Name[0] != 0) { + mdb->db_escape_string(jcr, esc, jr->Name, strlen(jr->Name)); + Mmsg(mdb->cmd, "SELECT DISTINCT FileSetId, FileSet, MD5, CreateTime " + "FROM Job, FileSet " + "WHERE Job.FileSetId = FileSet.FileSetId " + "AND Job.Name='%s'%s", esc, str_limit.c_str()); + } else if (jr->Job[0] != 0) { + mdb->db_escape_string(jcr, esc, jr->Job, strlen(jr->Job)); + Mmsg(mdb->cmd, "SELECT DISTINCT FileSetId, FileSet, MD5, CreateTime " + "FROM Job, FileSet " + "WHERE Job.FileSetId = FileSet.FileSetId " + "AND Job.Name='%s'%s", esc, str_limit.c_str()); + } else if (jr->JobId != 0) { + Mmsg(mdb->cmd, "SELECT DISTINCT FileSetId, FileSet, MD5, CreateTime " + "FROM Job, FileSet " + "WHERE Job.FileSetId = FileSet.FileSetId " + "AND Job.JobId='%s'%s", edit_int64(jr->JobId, esc), str_limit.c_str()); + } else { /* all records */ + Mmsg(mdb->cmd, "SELECT DISTINCT FileSetId, FileSet, MD5, CreateTime " + "FROM FileSet ORDER BY FileSetId ASC%s", str_limit.c_str()); + } + + if (!QUERY_DB(jcr, mdb, mdb->cmd)) { + goto bail_out; + } + sendit->object_start("filesets"); + list_result(jcr, mdb, sendit, type); + sendit->object_end("filesets"); + + sql_free_result(mdb); + +bail_out: + db_unlock(mdb); +} + #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL || HAVE_INGRES || HAVE_DBI */ diff --git a/src/dird/ua_cmds.c b/src/dird/ua_cmds.c index afe7a888428..aae345707c4 100644 --- a/src/dird/ua_cmds.c +++ b/src/dird/ua_cmds.c @@ -142,7 +142,8 @@ static struct cmdstruct commands[] = { NT_("jobs | jobid= | ujobid= | job= | jobmedia jobid= |\n" "\tjobmedia ujobid= | joblog jobid= | joblog ujobid= |\n" "\tbasefiles jobid= | basefiles ujobid= |\n" - "\tfiles jobid= | files ujobid= | pools | jobtotals |\n" + "\tfiles jobid= | files ujobid= |\n" + "\tfileset [ jobid= ] | fileset [ ujobid= ] | filesets | pools | jobtotals |\n" "\tvolumes [ jobid= ujobid= pool= ] |\n" "\tmedia [ jobid= ujobid= pool= ] | clients |\n" "\tnextvol job= | nextvolume ujobid= | copies jobid= [ limit= ]"), true, true }, @@ -150,7 +151,8 @@ static struct cmdstruct commands[] = { NT_("jobs | jobid= | ujobid= | job= | jobmedia jobid= |\n" "\tjobmedia ujobid= | joblog jobid= | joblog ujobid= |\n" "\tbasefiles jobid= | basefiles ujobid= |\n" - "\tfiles jobid= | files ujobid= | pools | jobtotals |\n" + "\tfiles jobid= | files ujobid= |\n" + "\tfileset [ jobid= ] | fileset [ ujobid= ] | filesets | pools | jobtotals |\n" "\tvolumes [ jobid= ujobid= pool= ] |\n" "\tmedia [ jobid= ujobid= pool= ] | clients |\n" "\tnextvol job= | nextvolume ujobid= | copies jobid="), true, true }, diff --git a/src/dird/ua_output.c b/src/dird/ua_output.c index de336175594..51c46f4c10c 100644 --- a/src/dird/ua_output.c +++ b/src/dird/ua_output.c @@ -385,24 +385,32 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) ua->error_msg(_("Hey! DB is NULL\n")); } - /* Apply any limit */ + /* + * Apply any limit + */ j = find_arg_with_value(ua, NT_("limit")); if (j >= 0) { jr.limit = atoi(ua->argv[j]); } - /* Scan arguments looking for things to do */ + /* + * Scan arguments looking for things to do + */ for (i = 1; i < ua->argc; i++) { - /* List JOBS */ if (bstrcasecmp(ua->argk[i], NT_("jobs"))) { + /* + * List JOBS + */ db_list_job_records(ua->jcr, ua->db, &jr, ua->send, llist); - - /* List JOBTOTALS */ } else if (bstrcasecmp(ua->argk[i], NT_("jobtotals"))) { + /* + * List JOBTOTALS + */ db_list_job_totals(ua->jcr, ua->db, &jr, ua->send); - - /* List JOBID=nn */ } else if (bstrcasecmp(ua->argk[i], NT_("jobid"))) { + /* + * List JOBID=nn + */ if (ua->argv[i]) { jobid = str_to_int64(ua->argv[i]); if (jobid > 0) { @@ -410,23 +418,26 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) db_list_job_records(ua->jcr, ua->db, &jr, ua->send, llist); } } - - /* List JOB=xxx */ } else if ((bstrcasecmp(ua->argk[i], NT_("job")) || bstrcasecmp(ua->argk[i], NT_("jobname"))) && ua->argv[i]) { + /* + * List JOB=xxx + */ bstrncpy(jr.Name, ua->argv[i], MAX_NAME_LENGTH); jr.JobId = 0; db_list_job_records(ua->jcr, ua->db, &jr, ua->send, llist); - - /* List UJOBID=xxx */ } else if (bstrcasecmp(ua->argk[i], NT_("ujobid")) && ua->argv[i]) { + /* + * List UJOBID=xxx + */ bstrncpy(jr.Job, ua->argv[i], MAX_NAME_LENGTH); jr.JobId = 0; db_list_job_records(ua->jcr, ua->db, &jr, ua->send, llist); - - /* List Base files */ } else if (bstrcasecmp(ua->argk[i], NT_("basefiles"))) { - for (j=i+1; jargc; j++) { + /* + * List Base files + */ + for (j = i + 1; j < ua->argc; j++) { if (bstrcasecmp(ua->argk[j], NT_("ujobid")) && ua->argv[j]) { bstrncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH); jr.JobId = 0; @@ -443,11 +454,11 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) db_list_base_files_for_job(ua->jcr, ua->db, jobid, ua->send); } } - - /* List FILES */ } else if (bstrcasecmp(ua->argk[i], NT_("files"))) { - - for (j=i+1; jargc; j++) { + /* + * List FILES + */ + for (j = i + 1; j < ua->argc; j++) { if (bstrcasecmp(ua->argk[j], NT_("ujobid")) && ua->argv[j]) { bstrncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH); jr.JobId = 0; @@ -464,11 +475,37 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) db_list_files_for_job(ua->jcr, ua->db, jobid, ua->send); } } + } else if (bstrcasecmp(ua->argk[i], NT_("fileset")) || + bstrcasecmp(ua->argk[i], NT_("filesets"))) { + /* + * List FILESETs + */ + for (j = i + 1; j < ua->argc; j++) { + if (bstrcasecmp(ua->argk[j], NT_("ujobid")) && ua->argv[j]) { + bstrncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH); + jr.JobId = 0; + if (!db_get_job_record(ua->jcr, ua->db, &jr)) { + continue; + } + } else if (bstrcasecmp(ua->argk[j], NT_("jobid")) && ua->argv[j]) { + jr.JobId = str_to_int64(ua->argv[j]); + } else { + continue; + } + } + db_list_filesets(ua->jcr, ua->db, &jr, ua->send, llist); - /* List JOBMEDIA */ + /* + * All arguments are evaluted, exit loop + */ + continue; } else if (bstrcasecmp(ua->argk[i], NT_("jobmedia"))) { bool done = false; - for (j=i+1; jargc; j++) { + + /* + * List JOBMEDIA + */ + for (j = i + 1; j < ua->argc; j++) { if (bstrcasecmp(ua->argk[j], NT_("ujobid")) && ua->argv[j]) { bstrncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH); jr.JobId = 0; @@ -485,14 +522,18 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) done = true; } if (!done) { - /* List for all jobs (jobid=0) */ + /* + * List for all jobs (jobid=0) + */ db_list_jobmedia_records(ua->jcr, ua->db, 0, ua->send, llist); } - - /* List JOBLOG */ } else if (bstrcasecmp(ua->argk[i], NT_("joblog"))) { bool done = false; - for (j=i+1; jargc; j++) { + + /* + * List JOBLOG + */ + for (j = i + 1; j < ua->argc; j++) { if (bstrcasecmp(ua->argk[j], NT_("ujobid")) && ua->argv[j]) { bstrncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH); jr.JobId = 0; @@ -509,30 +550,37 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) done = true; } if (!done) { - /* List for all jobs (jobid=0) */ + /* + * List for all jobs (jobid=0) + */ db_list_joblog_records(ua->jcr, ua->db, 0, ua->send, llist); } - - - /* List POOLS */ } else if (bstrcasecmp(ua->argk[i], NT_("pool")) || bstrcasecmp(ua->argk[i], NT_("pools"))) { POOL_DBR pr; + + /* + * List POOLS + */ memset(&pr, 0, sizeof(pr)); if (ua->argv[i]) { bstrncpy(pr.Name, ua->argv[i], sizeof(pr.Name)); } db_list_pool_records(ua->jcr, ua->db, &pr, ua->send, llist); - } else if (bstrcasecmp(ua->argk[i], NT_("clients"))) { + /* + * List CLIENTS + */ db_list_client_records(ua->jcr, ua->db, ua->send, llist); - - /* List MEDIA or VOLUMES */ } else if (bstrcasecmp(ua->argk[i], NT_("media")) || bstrcasecmp(ua->argk[i], NT_("volume")) || bstrcasecmp(ua->argk[i], NT_("volumes"))) { bool done = false; - for (j=i+1; jargc; j++) { + + /* + * List MEDIA or VOLUMES + */ + for (j = i + 1; j < ua->argc; j++) { if (bstrcasecmp(ua->argk[j], NT_("ujobid")) && ua->argv[j]) { bstrncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH); jr.JobId = 0; @@ -551,18 +599,27 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) free_pool_memory(VolumeName); done = true; } - /* if no job or jobid keyword found, then we list all media */ + + /* + * If no job or jobid keyword found, then we list all media + */ if (!done) { int num_pools; uint32_t *ids; - /* List a specific volume? */ + + /* + * List a specific volume? + */ if (ua->argv[i]) { bstrncpy(mr.VolumeName, ua->argv[i], sizeof(mr.VolumeName)); db_list_media_records(ua->jcr, ua->db, &mr, ua->send, llist); return 1; } - /* Is a specific pool wanted? */ - for (i=1; iargc; i++) { + + /* + * Is a specific pool wanted? + */ + for (i = 1; i < ua->argc; i++) { if (bstrcasecmp(ua->argk[i], NT_("pool"))) { if (!get_pool_dbr(ua, &pr)) { ua->error_msg(_("No Pool specified.\n")); @@ -574,7 +631,9 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) } } - /* List Volumes in all pools */ + /* + * List Volumes in all pools + */ if (!db_get_pool_ids(ua->jcr, ua->db, &num_pools, &ids)) { ua->error_msg(_("Error obtaining pool ids. ERR=%s\n"), db_strerror(ua->db)); @@ -583,7 +642,7 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) if (num_pools <= 0) { return 1; } - for (i=0; i < num_pools; i++) { + for (i = 0; i < num_pools; i++) { ua->send->object_start(); pr.PoolId = ids[i]; if (db_get_pool_record(ua->jcr, ua->db, &pr)) { @@ -596,9 +655,11 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) free(ids); return 1; } - /* List next volume */ } else if (bstrcasecmp(ua->argk[i], NT_("nextvol")) || bstrcasecmp(ua->argk[i], NT_("nextvolume"))) { + /* + * List next volume + */ n = 1; j = find_arg_with_value(ua, NT_("days")); if (j >= 0) { @@ -611,8 +672,12 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) list_nextvol(ua, n); } else if (bstrcasecmp(ua->argk[i], NT_("copies"))) { char *jobids = NULL; - uint32_t limit=0; - for (j=i+1; jargc; j++) { + uint32_t limit = 0; + + /* + * List copies + */ + for (j = i + 1; j < ua->argc; j++) { if (bstrcasecmp(ua->argk[j], NT_("jobid")) && ua->argv[j]) { if (is_a_number_list(ua->argv[j])) { jobids = ua->argv[j]; @@ -622,9 +687,11 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) } } db_list_copies_records(ua->jcr, ua->db, limit, jobids, ua->send, llist); - } else if (bstrcasecmp(ua->argk[i], NT_("limit")) - || bstrcasecmp(ua->argk[i], NT_("days"))) { - /* Ignore it */ + } else if (bstrcasecmp(ua->argk[i], NT_("limit")) || + bstrcasecmp(ua->argk[i], NT_("days"))) { + /* + * Ignore it + */ } else { ua->error_msg(_("Unknown list keyword: %s\n"), NPRT(ua->argk[i])); } @@ -1067,3 +1134,4 @@ void UAContext::info_msg(const char *fmt, ...) bmsg(this, fmt, arg_ptr); va_end(arg_ptr); } +