role_diff.c File Reference


Detailed Description

Implementation for computing semantic differences in roles.

Author:
Jeremy A. Mowery jmowery@tresys.com

Jason Tang jtang@tresys.com

Copyright (C) 2006-2007 Tresys Technology, LLC

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

Definition in file role_diff.c.

#include <config.h>
#include "poldiff_internal.h"
#include <apol/util.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>

Go to the source code of this file.


Classes

struct  poldiff_role_summary
struct  poldiff_role

Functions

void poldiff_role_get_stats (const poldiff_t *diff, size_t stats[5])
 Get an array of statistics for the number of differences of each form for roles.
char * poldiff_role_to_string (const poldiff_t *diff, const void *role)
 Obtain a newly allocated string representation of a difference in a role.
const apol_vector_tpoldiff_get_role_vector (const poldiff_t *diff)
 Get the vector of role differences from the role difference summary.
const char * poldiff_role_get_name (const poldiff_role_t *role)
 Get the name of the role from a role diff.
poldiff_form_e poldiff_role_get_form (const void *role)
 Get the form of difference from a role diff.
const apol_vector_tpoldiff_role_get_added_types (const poldiff_role_t *role)
 Get a vector of types added to the role.
const apol_vector_tpoldiff_role_get_removed_types (const poldiff_role_t *role)
 Get a vector of types removed from the role.
void role_free (void *elem)
poldiff_role_summary_trole_create (void)
 Allocate and return a new poldiff_role_summary_t object.
void role_destroy (poldiff_role_summary_t **rs)
 Deallocate all space associated with a poldiff_role_summary_t object, including the pointer itself.
int role_reset (poldiff_t *diff)
 Reset the state of all role differences.
int role_name_comp (const void *x, const void *y, void *arg)
 Comparison function for two roles from the same policy.
apol_vector_trole_get_items (poldiff_t *diff, const apol_policy_t *policy)
 Get a vector of all roles from the given policy, sorted by name.
int role_comp (const void *x, const void *y, const poldiff_t *diff)
 Compare two qpol_role_t objects, determining if they have the same name or not.
poldiff_role_tmake_diff (const poldiff_t *diff, poldiff_form_e form, const char *name)
 Allocate and return a new role difference object.
int role_new_diff (poldiff_t *diff, poldiff_form_e form, const void *item)
 Create, initialize, and insert a new semantic difference entry for a role.
apol_vector_trole_get_types (const poldiff_t *diff, const qpol_role_t *role, int which)
 Given a role, return an unsorted vector of its allowed types (in the form of uint32_t corresponding to pseudo-type values).
int role_deep_diff (poldiff_t *diff, const void *x, const void *y)
 Compute the semantic difference of two roles for which the compare callback returns 0.

Function Documentation

void poldiff_role_get_stats const poldiff_t diff,
size_t  stats[5]
 

Get an array of statistics for the number of differences of each form for roles.

Parameters:
diff The policy difference structure from which to get the stats.
stats Array into which to write the numbers (array must be pre-allocated). The order of the values written to the array is as follows: number of items of form POLDIFF_FORM_ADDED, number of POLDIFF_FORM_REMOVED, number of POLDIFF_FORM_MODIFIED, number of POLDIFF_FORM_ADD_TYPE, and number of POLDIFF_FORM_REMOVE_TYPE.

Definition at line 50 of file role_diff.c.

References diff, ERR, poldiff_role_summary::num_added, poldiff_role_summary::num_modified, poldiff_role_summary::num_removed, poldiff_t, and poldiff::role_diffs.

00051 {
00052         if (diff == NULL || stats == NULL) {
00053                 ERR(diff, "%s", strerror(EINVAL));
00054                 errno = EINVAL;
00055                 return;
00056         }
00057         stats[0] = diff->role_diffs->num_added;
00058         stats[1] = diff->role_diffs->num_removed;
00059         stats[2] = diff->role_diffs->num_modified;
00060         stats[3] = 0;
00061         stats[4] = 0;
00062 }

char* poldiff_role_to_string const poldiff_t diff,
const void *  role
 

Obtain a newly allocated string representation of a difference in a role.

Parameters:
diff The policy difference structure associated with the role.
role The role from which to generate the string.
Returns:
A string representation of role difference; the caller is responsible for free()ing this string. On error, return NULL and set errno.

Definition at line 64 of file role_diff.c.

References poldiff_role::added_types, apol_str_append(), apol_str_appendf(), apol_vector_get_element(), apol_vector_get_size(), diff, ERR, poldiff_role::form, poldiff_role::name, POLDIFF_FORM_ADDED, POLDIFF_FORM_MODIFIED, POLDIFF_FORM_REMOVED, poldiff_role_t, poldiff_t, and poldiff_role::removed_types.

00065 {
00066         const poldiff_role_t *r = role;
00067         size_t num_added, num_removed, len = 0, i;
00068         char *s = NULL, *type;
00069         if (diff == NULL || role == NULL) {
00070                 ERR(diff, "%s", strerror(EINVAL));
00071                 errno = EINVAL;
00072                 return NULL;
00073         }
00074         num_added = apol_vector_get_size(r->added_types);
00075         num_removed = apol_vector_get_size(r->removed_types);
00076         switch (r->form) {
00077         case POLDIFF_FORM_ADDED:
00078         {
00079                 if (apol_str_appendf(&s, &len, "+ %s", r->name) < 0) {
00080                         s = NULL;
00081                         break;
00082                 }
00083                 return s;
00084         }
00085         case POLDIFF_FORM_REMOVED:
00086         {
00087                 if (apol_str_appendf(&s, &len, "- %s", r->name) < 0) {
00088                         s = NULL;
00089                         break;
00090                 }
00091                 return s;
00092         }
00093         case POLDIFF_FORM_MODIFIED:
00094         {
00095                 if (apol_str_appendf(&s, &len, "* %s (", r->name) < 0) {
00096                         s = NULL;
00097                         break;
00098                 }
00099                 if (num_added > 0) {
00100                         if (apol_str_appendf(&s, &len, "%zd Added Type%s", num_added, (num_added == 1 ? "" : "s")) < 0) {
00101                                 break;
00102                         }
00103                 }
00104                 if (num_removed > 0) {
00105                         if (apol_str_appendf
00106                             (&s, &len, "%s%zd Removed Type%s", (num_added > 0 ? ", " : ""), num_removed,
00107                              (num_removed == 1 ? "" : "s")) < 0) {
00108                                 break;
00109                         }
00110                 }
00111                 if (apol_str_append(&s, &len, ")\n") < 0) {
00112                         break;
00113                 }
00114                 for (i = 0; i < apol_vector_get_size(r->added_types); i++) {
00115                         type = (char *)apol_vector_get_element(r->added_types, i);
00116                         if (apol_str_appendf(&s, &len, "\t+ %s\n", type) < 0) {
00117                                 goto err;
00118                         }
00119                 }
00120                 for (i = 0; i < apol_vector_get_size(r->removed_types); i++) {
00121                         type = (char *)apol_vector_get_element(r->removed_types, i);
00122                         if (apol_str_appendf(&s, &len, "\t- %s\n", type) < 0) {
00123                                 goto err;
00124                         }
00125                 }
00126                 return s;
00127         }
00128         default:
00129         {
00130                 ERR(diff, "%s", strerror(ENOTSUP));
00131                 errno = ENOTSUP;
00132                 return NULL;
00133         }
00134         }
00135       err:
00136         /* if this is reached then an error occurred */
00137         free(s);
00138         ERR(diff, "%s", strerror(ENOMEM));
00139         errno = ENOMEM;
00140         return NULL;
00141 }

const apol_vector_t* poldiff_get_role_vector const poldiff_t diff  ) 
 

Get the vector of role differences from the role difference summary.

Parameters:
diff The policy difference structure associated with the role difference summary.
Returns:
A vector of elements of type poldiff_role_t, or NULL on error. The caller should not destroy the vector returned. If the call fails, errno will be set.

Definition at line 143 of file role_diff.c.

References apol_vector_t, diff, poldiff_role_summary::diffs, poldiff_t, and poldiff::role_diffs.

Referenced by components_roles_tests().

00144 {
00145         if (diff == NULL) {
00146                 errno = EINVAL;
00147                 return NULL;
00148         }
00149         return diff->role_diffs->diffs;
00150 }

const char* poldiff_role_get_name const poldiff_role_t role  ) 
 

Get the name of the role from a role diff.

Parameters:
role The role from which to get the name.
Returns:
Name of the role on success and NULL on failure; if the call fails, errno will be set. The caller should not free the returned string.

Definition at line 152 of file role_diff.c.

References poldiff_role::name, and poldiff_role_t.

00153 {
00154         if (role == NULL) {
00155                 errno = EINVAL;
00156                 return NULL;
00157         }
00158         return role->name;
00159 }

poldiff_form_e poldiff_role_get_form const void *  role  ) 
 

Get the form of difference from a role diff.

Parameters:
role The role from which to get the difference form.
Returns:
The form of difference (one of POLDIFF_FORM_*) or POLDIFF_FORM_NONE on error. If the call fails, errno will be set.

Definition at line 161 of file role_diff.c.

References poldiff_role::form, poldiff_form_e, and poldiff_role_t.

Referenced by components_roles_tests().

00162 {
00163         if (role == NULL) {
00164                 errno = EINVAL;
00165                 return 0;
00166         }
00167         return ((const poldiff_role_t *)role)->form;
00168 }

const apol_vector_t* poldiff_role_get_added_types const poldiff_role_t role  ) 
 

Get a vector of types added to the role.

Parameters:
role The role diff from which to get the types vector.
Returns:
a vector of type names (type char *) that are allowed to the role in the modified policy. If no types were added the size of the returned vector will be 0. The caller must not destroy this vector. On error, errno will be set.

Definition at line 170 of file role_diff.c.

References poldiff_role::added_types, apol_vector_t, and poldiff_role_t.

00171 {
00172         if (role == NULL) {
00173                 errno = EINVAL;
00174                 return NULL;
00175         }
00176         return role->added_types;
00177 }

const apol_vector_t* poldiff_role_get_removed_types const poldiff_role_t role  ) 
 

Get a vector of types removed from the role.

Parameters:
role The role diff from which to get the types vector.
Returns:
A vector of type names (type char *) that are allowed to the role in the original policy. If no types were removed the size of the returned vector will be 0. The caller must not destroy this vector. On error, errno will be set.

Definition at line 179 of file role_diff.c.

References apol_vector_t, poldiff_role_t, and poldiff_role::removed_types.

00180 {
00181         if (role == NULL) {
00182                 errno = EINVAL;
00183                 return NULL;
00184         }
00185         return role->removed_types;
00186 }

void role_free void *  elem  )  [static]
 

Definition at line 190 of file role_diff.c.

References poldiff_role::added_types, apol_vector_destroy(), poldiff_role::name, poldiff_role_t, and poldiff_role::removed_types.

Referenced by make_diff(), role_create(), role_deep_diff(), and role_new_diff().

00191 {
00192         if (elem != NULL) {
00193                 poldiff_role_t *r = (poldiff_role_t *) elem;
00194                 free(r->name);
00195                 apol_vector_destroy(&r->added_types);
00196                 apol_vector_destroy(&r->removed_types);
00197                 free(r);
00198         }
00199 }

poldiff_role_summary_t* role_create void   ) 
 

Allocate and return a new poldiff_role_summary_t object.

Returns:
A new role summary. The caller must call role_destroy() afterwards. On error, return NULL and set errno.

Definition at line 201 of file role_diff.c.

References apol_vector_create(), poldiff_role_summary_t, role_destroy(), and role_free().

Referenced by poldiff_create(), and role_reset().

00202 {
00203         poldiff_role_summary_t *rs = calloc(1, sizeof(*rs));
00204         if (rs == NULL) {
00205                 return NULL;
00206         }
00207         if ((rs->diffs = apol_vector_create(role_free)) == NULL) {
00208                 role_destroy(&rs);
00209                 return NULL;
00210         }
00211         return rs;
00212 }

void role_destroy poldiff_role_summary_t **  us  ) 
 

Deallocate all space associated with a poldiff_role_summary_t object, including the pointer itself.

If the pointer is already NULL then do nothing.

Parameters:
us Reference to a role summary to destroy. The pointer will be set to NULL afterwards.

Definition at line 214 of file role_diff.c.

References apol_vector_destroy(), and poldiff_role_summary_t.

Referenced by poldiff_destroy(), role_create(), and role_reset().

00215 {
00216         if (rs != NULL && *rs != NULL) {
00217                 apol_vector_destroy(&(*rs)->diffs);
00218                 free(*rs);
00219                 *rs = NULL;
00220         }
00221 }

int role_reset poldiff_t diff  ) 
 

Reset the state of all role differences.

Parameters:
diff The policy difference structure containing the differences to reset.
Returns:
0 on success and < 0 on error; if the call fails, errno will be set and the user should call poldiff_destroy() on diff.

Definition at line 223 of file role_diff.c.

References diff, ERR, poldiff_t, role_create(), role_destroy(), and poldiff::role_diffs.

00224 {
00225         int error = 0;
00226 
00227         if (diff == NULL) {
00228                 ERR(diff, "%s", strerror(EINVAL));
00229                 errno = EINVAL;
00230                 return -1;
00231         }
00232 
00233         role_destroy(&diff->role_diffs);
00234         diff->role_diffs = role_create();
00235         if (diff->role_diffs == NULL) {
00236                 error = errno;
00237                 ERR(diff, "%s", strerror(error));
00238                 errno = error;
00239                 return -1;
00240         }
00241 
00242         return 0;
00243 }

int role_name_comp const void *  x,
const void *  y,
void *  arg
[static]
 

Comparison function for two roles from the same policy.

Definition at line 248 of file role_diff.c.

References apol_policy_get_qpol(), apol_policy_t, qpol_policy_t, qpol_role_get_name(), and qpol_role_t.

Referenced by role_get_items().

00249 {
00250         const qpol_role_t *r1 = x;
00251         const qpol_role_t *r2 = y;
00252         apol_policy_t *p = (apol_policy_t *) arg;
00253         qpol_policy_t *q = apol_policy_get_qpol(p);
00254         const char *name1, *name2;
00255         if (qpol_role_get_name(q, r1, &name1) < 0 || qpol_role_get_name(q, r2, &name2) < 0) {
00256                 return 0;
00257         }
00258         return strcmp(name1, name2);
00259 }

apol_vector_t* role_get_items poldiff_t diff,
const apol_policy_t policy
 

Get a vector of all roles from the given policy, sorted by name.

Parameters:
diff Policy diff error handler.
policy The policy from which to get the items.
Returns:
a newly allocated vector of all roles. The caller is responsible for calling apol_vector_destroy() afterwards. On error, return NULL and set errno.

Definition at line 261 of file role_diff.c.

References apol_policy_get_qpol(), apol_policy_t, apol_vector_create_from_iter(), apol_vector_sort(), apol_vector_t, diff, ERR, poldiff_t, qpol_iterator_destroy(), qpol_iterator_t, qpol_policy_get_role_iter(), qpol_policy_t, and role_name_comp().

00262 {
00263         qpol_iterator_t *iter = NULL;
00264         apol_vector_t *v = NULL;
00265         qpol_policy_t *q = apol_policy_get_qpol(policy);
00266         int error = 0;
00267         if (qpol_policy_get_role_iter(q, &iter) < 0) {
00268                 return NULL;
00269         }
00270         v = apol_vector_create_from_iter(iter, NULL);
00271         if (v == NULL) {
00272                 error = errno;
00273                 ERR(diff, "%s", strerror(error));
00274                 qpol_iterator_destroy(&iter);
00275                 errno = error;
00276                 return NULL;
00277         }
00278         qpol_iterator_destroy(&iter);
00279         apol_vector_sort(v, role_name_comp, (void *)policy);
00280         return v;
00281 }

int role_comp const void *  x,
const void *  y,
const poldiff_t diff
 

Compare two qpol_role_t objects, determining if they have the same name or not.

Parameters:
x The role from the original policy.
y The role from the modified policy.
diff The policy difference structure associated with both policies.
Returns:
< 0, 0, or > 0 if role x is respectively less than, equal to, or greater than role y.

Definition at line 283 of file role_diff.c.

References diff, poldiff::mod_qpol, poldiff::orig_qpol, poldiff_t, qpol_role_get_name(), and qpol_role_t.

00284 {
00285         const qpol_role_t *r1 = x;
00286         const qpol_role_t *r2 = y;
00287         const char *name1, *name2;
00288         if (qpol_role_get_name(diff->orig_qpol, r1, &name1) < 0 || qpol_role_get_name(diff->mod_qpol, r2, &name2) < 0) {
00289                 return 0;
00290         }
00291         return strcmp(name1, name2);
00292 }

poldiff_role_t* make_diff const poldiff_t diff,
poldiff_form_e  form,
const char *  name
[static]
 

Allocate and return a new role difference object.

Parameters:
diff Policy diff error handler.
form Form of the difference.
name Name of the role that is different.
Returns:
A newly allocated and initialized diff, or NULL upon error. The caller is responsible for calling role_free() upon the returned value.

Definition at line 305 of file role_diff.c.

References apol_vector_create_with_capacity(), diff, ERR, poldiff_user::form, poldiff_role_t, poldiff_t, and role_free().

00306 {
00307         poldiff_role_t *pr;
00308         int error;
00309         if ((pr = calloc(1, sizeof(*pr))) == NULL ||
00310             (pr->name = strdup(name)) == NULL ||
00311             (pr->added_types = apol_vector_create_with_capacity(1, free)) == NULL ||
00312             (pr->removed_types = apol_vector_create_with_capacity(1, free)) == NULL) {
00313                 error = errno;
00314                 role_free(pr);
00315                 ERR(diff, "%s", strerror(error));
00316                 errno = error;
00317                 return NULL;
00318         }
00319         pr->form = form;
00320         return pr;
00321 }

int role_new_diff poldiff_t diff,
poldiff_form_e  form,
const void *  item
 

Create, initialize, and insert a new semantic difference entry for a role.

Parameters:
diff The policy difference structure to which to add the entry.
form The form of the difference.
item Item for which the entry is being created.
Returns:
0 on success and < 0 on error; if the call fails, set errno and leave the policy difference structure unchanged.

Definition at line 323 of file role_diff.c.

References apol_vector_append(), diff, poldiff_role_summary::diffs, ERR, make_diff(), poldiff::mod_qpol, poldiff_role_summary::num_added, poldiff_role_summary::num_removed, poldiff::orig_qpol, POLDIFF_FORM_ADDED, POLDIFF_FORM_REMOVED, poldiff_role_t, poldiff_t, qpol_role_get_name(), qpol_role_t, poldiff::role_diffs, and role_free().

00324 {
00325         const qpol_role_t *r = item;
00326         const char *name = NULL;
00327         poldiff_role_t *pr;
00328         int error;
00329         if ((form == POLDIFF_FORM_ADDED &&
00330              qpol_role_get_name(diff->mod_qpol, r, &name) < 0) ||
00331             ((form == POLDIFF_FORM_REMOVED || form == POLDIFF_FORM_MODIFIED) && qpol_role_get_name(diff->orig_qpol, r, &name) < 0))
00332         {
00333                 return -1;
00334         }
00335         pr = make_diff(diff, form, name);
00336         if (pr == NULL) {
00337                 return -1;
00338         }
00339         if (apol_vector_append(diff->role_diffs->diffs, pr) < 0) {
00340                 error = errno;
00341                 ERR(diff, "%s", strerror(error));
00342                 role_free(pr);
00343                 errno = error;
00344                 return -1;
00345         }
00346         if (form == POLDIFF_FORM_ADDED) {
00347                 diff->role_diffs->num_added++;
00348         } else {
00349                 diff->role_diffs->num_removed++;
00350         }
00351         return 0;
00352 }

apol_vector_t* role_get_types const poldiff_t diff,
const qpol_role_t role,
int  which
[static]
 

Given a role, return an unsorted vector of its allowed types (in the form of uint32_t corresponding to pseudo-type values).

Parameters:
diff Policy diff error handler.
role Role whose roles to get.
which Which policy, one of POLDIFF_POLICY_ORIG or POLDIFF_POLICY_MOD.
Returns:
Vector of pseudo-type values. The caller is responsible for calling apol_vector_destroy(). On error, return NULL.

Definition at line 366 of file role_diff.c.

References apol_vector_append(), apol_vector_create(), apol_vector_destroy(), apol_vector_t, diff, ERR, poldiff::mod_qpol, poldiff::orig_qpol, poldiff_t, qpol_iterator_destroy(), qpol_iterator_end(), qpol_iterator_get_item(), qpol_iterator_next(), qpol_iterator_t, qpol_role_get_type_iter(), qpol_type_t, and type_map_lookup().

Referenced by role_deep_diff().

00367 {
00368         qpol_iterator_t *iter = NULL;
00369         const qpol_type_t *type;
00370         uint32_t new_val;
00371         apol_vector_t *v = NULL;
00372         int retval = -1, error = 0;
00373 
00374         if ((v = apol_vector_create(NULL)) == NULL) {
00375                 ERR(diff, "%s", strerror(errno));
00376                 goto cleanup;
00377         }
00378         if (which == POLDIFF_POLICY_ORIG) {
00379                 if (qpol_role_get_type_iter(diff->orig_qpol, role, &iter) < 0) {
00380                         goto cleanup;
00381                 }
00382         } else {
00383                 if (qpol_role_get_type_iter(diff->mod_qpol, role, &iter) < 0) {
00384                         goto cleanup;
00385                 }
00386         }
00387         for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
00388                 if (qpol_iterator_get_item(iter, (void **)&type) < 0 || (new_val = type_map_lookup(diff, type, which)) == 0) {
00389                         error = errno;
00390                         goto cleanup;
00391                 }
00392                 if (apol_vector_append(v, (void *)((size_t) new_val)) < 0) {
00393                         error = errno;
00394                         ERR(diff, "%s", strerror(error));
00395                         goto cleanup;
00396                 }
00397         }
00398 
00399         retval = 0;
00400       cleanup:
00401         qpol_iterator_destroy(&iter);
00402         if (retval < 0) {
00403                 apol_vector_destroy(&v);
00404                 errno = error;
00405                 return NULL;
00406         }
00407         return v;
00408 }

int role_deep_diff poldiff_t diff,
const void *  x,
const void *  y
 

Compute the semantic difference of two roles for which the compare callback returns 0.

If a difference is found then allocate, initialize, and insert a new semantic difference entry for that role.

Parameters:
diff The policy difference structure associated with both roles and to which to add an entry if needed.
x The role from the original policy.
y The role from the modified policy.
Returns:
0 on success and < 0 on error; if the call fails, set errno and leave the policy difference structure unchanged.

Definition at line 410 of file role_diff.c.

References added_types, poldiff_role::added_types, apol_str_strcmp(), apol_vector_append(), apol_vector_create(), apol_vector_destroy(), apol_vector_get_element(), apol_vector_get_size(), apol_vector_sort(), apol_vector_sort_uniquify(), apol_vector_t, diff, poldiff_role_summary::diffs, ERR, make_diff(), poldiff::mod_qpol, poldiff_role_summary::num_modified, poldiff::orig_qpol, POLDIFF_FORM_MODIFIED, POLDIFF_POLICY_MOD, POLDIFF_POLICY_ORIG, poldiff_role_t, poldiff_t, qpol_role_get_name(), qpol_role_t, qpol_type_get_name(), qpol_type_t, removed_types, poldiff_role::removed_types, poldiff::role_diffs, role_free(), role_get_types(), and type_map_lookup_reverse().

00411 {
00412         const qpol_role_t *r1 = x;
00413         const qpol_role_t *r2 = y;
00414         apol_vector_t *v1 = NULL, *v2 = NULL;
00415         apol_vector_t *added_types = NULL, *removed_types = NULL;
00416         const apol_vector_t *reverse_v;
00417         const char *name;
00418         char *new_name;
00419         uint32_t t1, t2;
00420         poldiff_role_t *r = NULL;
00421         qpol_type_t *t;
00422         size_t i, j;
00423         int retval = -1, error = 0;
00424 
00425         if (qpol_role_get_name(diff->orig_qpol, r1, &name) < 0 ||
00426             (v1 = role_get_types(diff, r1, POLDIFF_POLICY_ORIG)) == NULL ||
00427             (v2 = role_get_types(diff, r2, POLDIFF_POLICY_MOD)) == NULL) {
00428                 error = errno;
00429                 goto cleanup;
00430         }
00431         apol_vector_sort_uniquify(v1, NULL, NULL);
00432         apol_vector_sort_uniquify(v2, NULL, NULL);
00433         if ((added_types = apol_vector_create(NULL)) == NULL || (removed_types = apol_vector_create(NULL)) == NULL) {
00434                 error = errno;
00435                 ERR(diff, "%s", strerror(error));
00436                 goto cleanup;
00437         }
00438         for (i = j = 0; i < apol_vector_get_size(v1);) {
00439                 if (j >= apol_vector_get_size(v2))
00440                         break;
00441                 t1 = (uint32_t) ((size_t) apol_vector_get_element(v1, i));
00442                 t2 = (uint32_t) ((size_t) apol_vector_get_element(v2, j));
00443                 if (t2 > t1) {
00444                         if (apol_vector_append(removed_types, (void *)((size_t) t1)) < 0) {
00445                                 error = errno;
00446                                 ERR(diff, "%s", strerror(error));
00447                                 goto cleanup;
00448                         }
00449                         i++;
00450                 } else if (t1 > t2) {
00451                         if (apol_vector_append(added_types, (void *)((size_t) t2)) < 0) {
00452                                 error = errno;
00453                                 ERR(diff, "%s", strerror(error));
00454                                 goto cleanup;
00455                         }
00456                         j++;
00457                 } else {
00458                         i++;
00459                         j++;
00460                 }
00461         }
00462         for (; i < apol_vector_get_size(v1); i++) {
00463                 t1 = (uint32_t) ((size_t) apol_vector_get_element(v1, i));
00464                 if (apol_vector_append(removed_types, (void *)((size_t) t1)) < 0) {
00465                         error = errno;
00466                         ERR(diff, "%s", strerror(error));
00467                         goto cleanup;
00468                 }
00469         }
00470         for (; j < apol_vector_get_size(v2); j++) {
00471                 t2 = (uint32_t) ((size_t) apol_vector_get_element(v2, j));
00472                 if (apol_vector_append(added_types, (void *)((size_t) t2)) < 0) {
00473                         error = errno;
00474                         ERR(diff, "%s", strerror(error));
00475                         goto cleanup;
00476                 }
00477         }
00478         if (apol_vector_get_size(added_types) > 0 || apol_vector_get_size(removed_types) > 0) {
00479                 if ((r = make_diff(diff, POLDIFF_FORM_MODIFIED, name)) == NULL) {
00480                         error = errno;
00481                         goto cleanup;
00482                 }
00483                 for (i = 0; i < apol_vector_get_size(removed_types); i++) {
00484                         t1 = (uint32_t) ((size_t) apol_vector_get_element(removed_types, i));
00485                         if ((reverse_v = type_map_lookup_reverse(diff, t1, POLDIFF_POLICY_ORIG)) == NULL) {
00486                                 error = errno;
00487                                 goto cleanup;
00488                         }
00489                         for (j = 0; j < apol_vector_get_size(reverse_v); j++) {
00490                                 t = (qpol_type_t *) apol_vector_get_element(reverse_v, j);
00491                                 if (qpol_type_get_name(diff->orig_qpol, t, &name) < 0) {
00492                                         error = errno;
00493                                         goto cleanup;
00494                                 }
00495                                 if ((new_name = strdup(name)) == NULL || apol_vector_append(r->removed_types, new_name) < 0) {
00496                                         error = errno;
00497                                         free(new_name);
00498                                         ERR(diff, "%s", strerror(error));
00499                                         goto cleanup;
00500                                 }
00501                         }
00502                 }
00503                 for (i = 0; i < apol_vector_get_size(added_types); i++) {
00504                         t2 = (uint32_t) ((size_t) apol_vector_get_element(added_types, i));
00505                         if ((reverse_v = type_map_lookup_reverse(diff, t2, POLDIFF_POLICY_MOD)) == NULL) {
00506                                 error = errno;
00507                                 goto cleanup;
00508                         }
00509                         for (j = 0; j < apol_vector_get_size(reverse_v); j++) {
00510                                 t = (qpol_type_t *) apol_vector_get_element(reverse_v, j);
00511                                 if (qpol_type_get_name(diff->mod_qpol, t, &name) < 0) {
00512                                         error = errno;
00513                                         goto cleanup;
00514                                 }
00515                                 if ((new_name = strdup(name)) == NULL || apol_vector_append(r->added_types, new_name) < 0) {
00516                                         error = errno;
00517                                         free(new_name);
00518                                         ERR(diff, "%s", strerror(error));
00519                                         goto cleanup;
00520                                 }
00521                         }
00522                 }
00523                 apol_vector_sort(r->removed_types, apol_str_strcmp, NULL);
00524                 apol_vector_sort(r->added_types, apol_str_strcmp, NULL);
00525                 if (apol_vector_append(diff->role_diffs->diffs, r) < 0) {
00526                         error = errno;
00527                         ERR(diff, "%s", strerror(error));
00528                         goto cleanup;
00529                 }
00530                 diff->role_diffs->num_modified++;
00531         }
00532         retval = 0;
00533       cleanup:
00534         apol_vector_destroy(&v1);
00535         apol_vector_destroy(&v2);
00536         apol_vector_destroy(&added_types);
00537         apol_vector_destroy(&removed_types);
00538         if (retval != 0) {
00539                 role_free(r);
00540         }
00541         errno = error;
00542         return retval;
00543 }