#include <getopt.h> #include "attribute.h" void attribute_usage() { fprintf(stderr, "\tattribute [-l|--list] [-r|--reverse] <name>\n"); } static void retrieve_mapping(policydb_t *policydb, struct type_datum *dat, char *name, int reverse) { struct ebitmap_node *n; unsigned int bit; if (reverse) { ebitmap_for_each_bit(&policydb->type_attr_map[dat->s.value - 1], n, bit) { if (!ebitmap_node_get_bit(n, bit)) continue; if (!strcmp(policydb->p_type_val_to_name[bit], name)) continue; printf("%s\n", policydb->p_type_val_to_name[bit]); } } else { ebitmap_for_each_bit(&policydb->attr_type_map[dat->s.value - 1], n, bit) { if (!ebitmap_node_get_bit(n, bit)) continue; printf("%s\n", policydb->p_type_val_to_name[bit]); } } } static int list_attribute(policydb_t *policydb, char *name, int reverse) { struct type_datum *dat; dat = hashtab_search(policydb->p_types.table, name); if (!dat) { fprintf(stderr, "%s is not defined in this policy.\n", name); return -1; } if (reverse) { if (dat->flavor != TYPE_TYPE) { fprintf(stderr, "%s is an attribute not a type in this policy.\n", name); return -1; } } else { if (dat->flavor != TYPE_ATTRIB) { fprintf(stderr, "%s is a type not an attribute in this policy.\n", name); return -1; } } retrieve_mapping(policydb, dat, name, reverse); return 0; } static int print_attr(__attribute__ ((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { struct type_datum *dat = (struct type_datum *)d; policydb_t *pdb = (policydb_t *)args; if (!dat) { fprintf(stderr, "type encountered without datum!\n"); return -1; } if (dat->flavor == TYPE_ATTRIB) { printf("%s\n", pdb->p_type_val_to_name[dat->s.value - 1]); } return 0; } static int list_all_attributes(policydb_t *policydb) { return hashtab_map(policydb->p_types.table, print_attr, policydb); } int attribute_func (int argc, char **argv, policydb_t *policydb) { int rc = -1; int list = 0; int reverse = 0; char ch; struct option attribute_options[] = { {"list", no_argument, NULL, 'l'}, {"reverse", no_argument, NULL, 'r'}, {NULL, 0, NULL, 0} }; while ((ch = getopt_long(argc, argv, "lr", attribute_options, NULL)) != -1) { switch (ch) { case 'l': list = 1; break; case 'r': reverse = 1; break; default: USAGE_ERROR = true; goto out; } } if ((argc != 2 && !(reverse && argc == 3)) || (list && reverse)) { USAGE_ERROR = true; goto out; } if (list) rc = list_all_attributes(policydb); else rc = list_attribute(policydb, argv[optind], reverse); out: return rc; }