diff --git a/src/dird/protos.h b/src/dird/protos.h index 5dc45699e2d..bfb7de94def 100644 --- a/src/dird/protos.h +++ b/src/dird/protos.h @@ -349,7 +349,7 @@ void update_inchanger_for_export(UAContext *ua, STORERES *store, changer_vol_lis /* ua_output.c */ void bsendmsg(void *ua_ctx, const char *fmt, ...); -bool filterit(void *ctx, void *data, of_filter_tuple *tuple); +of_filter_state filterit(void *ctx, void *data, of_filter_tuple *tuple); bool printit(void *ctx, const char *msg); bool complete_jcr_for_job(JCR *jcr, JOBRES *job, POOLRES *pool); RUNRES *find_next_run(RUNRES *run, JOBRES *job, utime_t &runtime, int ndays); diff --git a/src/dird/ua_output.c b/src/dird/ua_output.c index 73528bd136c..536c3df0b60 100644 --- a/src/dird/ua_output.c +++ b/src/dird/ua_output.c @@ -1548,11 +1548,11 @@ bool messages_cmd(UAContext *ua, const char *cmd) /* * Callback routine for "filtering" database listing. */ -bool filterit(void *ctx, void *data, of_filter_tuple *tuple) +of_filter_state filterit(void *ctx, void *data, of_filter_tuple *tuple) { - bool retval = true; char **row = (char **)data; UAContext *ua = (UAContext *)ctx; + of_filter_state retval = OF_FILTER_STATE_SHOW; switch (tuple->type) { case OF_FILTER_LIMIT: @@ -1562,27 +1562,33 @@ bool filterit(void *ctx, void *data, of_filter_tuple *tuple) tuple->u.limit_filter.limit--; } else { Dmsg0(200, "filterit: limit filter reached don't display entry\n"); - retval = false; + retval = OF_FILTER_STATE_SUPPRESS; } goto bail_out; case OF_FILTER_ACL: - if (row[tuple->u.acl_filter.column] && - strlen(row[tuple->u.acl_filter.column]) && - !ua->acl_access_ok(tuple->u.acl_filter.acltype, - row[tuple->u.acl_filter.column], false)) { - Dmsg2(200, "filterit: Filter on acl_type %d value %s, suppress output\n", - tuple->u.acl_filter.acltype, row[tuple->u.acl_filter.column]); - retval = false; + if (!row[tuple->u.acl_filter.column] || + strlen(row[tuple->u.acl_filter.column]) == 0) { + retval = OF_FILTER_STATE_UNKNOWN; + } else { + if (!ua->acl_access_ok(tuple->u.acl_filter.acltype, + row[tuple->u.acl_filter.column], false)) { + Dmsg2(200, "filterit: Filter on acl_type %d value %s, suppress output\n", + tuple->u.acl_filter.acltype, row[tuple->u.acl_filter.column]); + retval = OF_FILTER_STATE_SUPPRESS; + } } goto bail_out; case OF_FILTER_RESOURCE: - if (row[tuple->u.res_filter.column] && - strlen(row[tuple->u.res_filter.column]) && - !GetResWithName(tuple->u.res_filter.restype, - row[tuple->u.res_filter.column], false)) { - Dmsg2(200, "filterit: Filter on resource_type %d value %s, suppress output\n", - tuple->u.res_filter.restype, row[tuple->u.res_filter.column]); - retval = false; + if (!row[tuple->u.res_filter.column] || + strlen(row[tuple->u.res_filter.column]) == 0) { + retval = OF_FILTER_STATE_UNKNOWN; + } else { + if (!GetResWithName(tuple->u.res_filter.restype, + row[tuple->u.res_filter.column], false)) { + Dmsg2(200, "filterit: Filter on resource_type %d value %s, suppress output\n", + tuple->u.res_filter.restype, row[tuple->u.res_filter.column]); + retval = OF_FILTER_STATE_SUPPRESS; + } } goto bail_out; case OF_FILTER_ENABLED: @@ -1591,6 +1597,7 @@ bool filterit(void *ctx, void *data, of_filter_tuple *tuple) if (!row[tuple->u.res_filter.column] || strlen(row[tuple->u.res_filter.column]) == 0) { + retval = OF_FILTER_STATE_UNKNOWN; goto bail_out; } @@ -1606,7 +1613,7 @@ bool filterit(void *ctx, void *data, of_filter_tuple *tuple) if (!client || client->enabled != enabled) { Dmsg2(200, "filterit: Filter on Client, %s is not %sabled\n", row[tuple->u.res_filter.column], (enabled) ? "En" : "Dis"); - retval = false; + retval = OF_FILTER_STATE_SUPPRESS; } goto bail_out; } @@ -1617,7 +1624,7 @@ bool filterit(void *ctx, void *data, of_filter_tuple *tuple) if (!job || job->enabled != enabled) { Dmsg2(200, "filterit: Filter on Job, %s is not %sabled\n", row[tuple->u.res_filter.column], (enabled) ? "En" : "Dis"); - retval = false; + retval = OF_FILTER_STATE_SUPPRESS; } goto bail_out; } @@ -1628,7 +1635,7 @@ bool filterit(void *ctx, void *data, of_filter_tuple *tuple) if (!store || store->enabled != enabled) { Dmsg2(200, "filterit: Filter on Storage, %s is not %sabled\n", row[tuple->u.res_filter.column], (enabled) ? "En" : "Dis"); - retval = false; + retval = OF_FILTER_STATE_SUPPRESS; } goto bail_out; } @@ -1639,7 +1646,7 @@ bool filterit(void *ctx, void *data, of_filter_tuple *tuple) if (!schedule || schedule->enabled != enabled) { Dmsg2(200, "filterit: Filter on Schedule, %s is not %sabled\n", row[tuple->u.res_filter.column], (enabled) ? "En" : "Dis"); - retval = false; + retval = OF_FILTER_STATE_SUPPRESS; } goto bail_out; } @@ -1649,7 +1656,7 @@ bool filterit(void *ctx, void *data, of_filter_tuple *tuple) break; } default: - retval = false; + retval = OF_FILTER_STATE_SUPPRESS; } bail_out: diff --git a/src/lib/output_formatter.c b/src/lib/output_formatter.c index be9064cb02b..87e3f24e53e 100644 --- a/src/lib/output_formatter.c +++ b/src/lib/output_formatter.c @@ -514,7 +514,10 @@ bool OUTPUT_FORMATTER::has_acl_filters() bool OUTPUT_FORMATTER::filter_data(void *data) { + of_filter_state state; of_filter_tuple *tuple; + int acl_filter_show = 0, + acl_filter_unknown = 0; /* * See if a filtering function is registered. @@ -522,12 +525,38 @@ bool OUTPUT_FORMATTER::filter_data(void *data) */ if (filter_func && filters && !filters->empty()) { foreach_alist(tuple, filters) { - if (!filter_func(filter_ctx, data, tuple)) { + state = filter_func(filter_ctx, data, tuple); + + Dmsg1(800, "filter_state %d\n", state); + switch (state) { + case OF_FILTER_STATE_SHOW: + if (tuple->type == OF_FILTER_ACL) { + acl_filter_show++; + } + break; + case OF_FILTER_STATE_SUPPRESS: return false; + case OF_FILTER_STATE_UNKNOWN: + if (tuple->type == OF_FILTER_ACL) { + acl_filter_unknown++; + } + break; } } } + /* + * If we have multiple ACL filters and none gave an + * explicit show state we suppress the entry just to + * be sure we do not show to much information if we + * are not sure if we should show the item. + */ + if (acl_filter_unknown > 0 && acl_filter_show == 0) { + Dmsg2(200, "tri-state filtering acl_filter_unknown %d, acl_filter_show %d\n", + acl_filter_unknown, acl_filter_show); + return false; + } + return true; } diff --git a/src/lib/output_formatter.h b/src/lib/output_formatter.h index 507aaacdbd8..5349fb229b0 100644 --- a/src/lib/output_formatter.h +++ b/src/lib/output_formatter.h @@ -50,6 +50,15 @@ typedef struct json_t json_t; #endif #endif +/* + * Filtering states. + */ +typedef enum of_filter_state { + OF_FILTER_STATE_SHOW, + OF_FILTER_STATE_SUPPRESS, + OF_FILTER_STATE_UNKNOWN +} of_filter_state; + /* * Filtering types. */ @@ -93,7 +102,7 @@ class OUTPUT_FORMATTER : public SMARTALLOC { * Typedefs. */ typedef bool (SEND_HANDLER)(void *ctx, const char *msg); - typedef bool (FILTER_HANDLER)(void *ctx, void *data, of_filter_tuple *tuple); + typedef of_filter_state (FILTER_HANDLER)(void *ctx, void *data, of_filter_tuple *tuple); private: /*