Traverse the role grant graph and invoke callbacks at the specified points. @param user user or role to start traversal from @param context opaque parameter to pass to callbacks @param offset offset to ACL_ROLE::parent_grantee or to ACL_USER_BASE::role_grants. Depending on this value, traversal will go from roles to
| 6566 | this error code |
| 6567 | */ |
| 6568 | static int traverse_role_graph_impl(ACL_USER_BASE *user, void *context, |
| 6569 | off_t offset, |
| 6570 | int (*on_node) (ACL_USER_BASE *role, void *context), |
| 6571 | int (*on_edge) (ACL_USER_BASE *current, ACL_ROLE *neighbour, void *context)) |
| 6572 | { |
| 6573 | DBUG_ENTER("traverse_role_graph_impl"); |
| 6574 | DBUG_ASSERT(user); |
| 6575 | DBUG_PRINT("enter",("role: '%s'", user->user.str)); |
| 6576 | /* |
| 6577 | The search operation should always leave the ROLE_ON_STACK and |
| 6578 | ROLE_EXPLORED flags clean for all nodes involved in the search |
| 6579 | */ |
| 6580 | DBUG_ASSERT(!(user->flags & ROLE_ON_STACK)); |
| 6581 | DBUG_ASSERT(!(user->flags & ROLE_EXPLORED)); |
| 6582 | mysql_mutex_assert_owner(&acl_cache->lock); |
| 6583 | |
| 6584 | /* |
| 6585 | Stack used to simulate the recursive calls of DFS. |
| 6586 | It uses a Dynamic_array to reduce the number of |
| 6587 | malloc calls to a minimum |
| 6588 | */ |
| 6589 | Dynamic_array<NODE_STATE> stack(PSI_INSTRUMENT_MEM, 20,50); |
| 6590 | Dynamic_array<ACL_USER_BASE *> to_clear(PSI_INSTRUMENT_MEM, 20, 50); |
| 6591 | NODE_STATE state; /* variable used to insert elements in the stack */ |
| 6592 | int result= 0; |
| 6593 | |
| 6594 | state.neigh_idx= 0; |
| 6595 | state.node_data= user; |
| 6596 | user->flags|= ROLE_ON_STACK; |
| 6597 | |
| 6598 | stack.push(state); |
| 6599 | to_clear.push(user); |
| 6600 | |
| 6601 | user->flags|= ROLE_OPENED; |
| 6602 | if (on_node && ((result= on_node(user, context)) < 0)) |
| 6603 | goto end; |
| 6604 | |
| 6605 | while (stack.elements()) |
| 6606 | { |
| 6607 | NODE_STATE *curr_state= stack.back(); |
| 6608 | |
| 6609 | DBUG_ASSERT(curr_state->node_data->flags & ROLE_ON_STACK); |
| 6610 | |
| 6611 | ACL_USER_BASE *current= curr_state->node_data; |
| 6612 | ACL_USER_BASE *neighbour= NULL; |
| 6613 | DBUG_PRINT("info", ("Examining role %s", current->user.str)); |
| 6614 | /* |
| 6615 | Iterate through the neighbours until a first valid jump-to |
| 6616 | neighbour is found |
| 6617 | */ |
| 6618 | bool found= FALSE; |
| 6619 | uint i; |
| 6620 | DYNAMIC_ARRAY *array= (DYNAMIC_ARRAY *)(((char*)current) + offset); |
| 6621 | |
| 6622 | DBUG_ASSERT(array == ¤t->role_grants || current->flags & IS_ROLE); |
| 6623 | for (i= curr_state->neigh_idx; i < array->elements; i++) |
| 6624 | { |
| 6625 | neighbour= *(dynamic_element(array, i, ACL_ROLE**)); |
no test coverage detected