Jason Tang jtang@tresys.com
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_t * | poldiff_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_t * | poldiff_role_get_added_types (const poldiff_role_t *role) |
| Get a vector of types added to the role. | |
| const apol_vector_t * | poldiff_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_t * | role_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_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. | |
| 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_t * | make_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_t * | role_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. | |
|
||||||||||||
|
Get an array of statistics for the number of differences of each form for roles.
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 }
|
|
||||||||||||
|
Obtain a newly allocated string representation of a difference in a role.
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 }
|
|
|
Get the vector of role differences from the role difference summary.
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 }
|
|
|
Get the name of the role from a role diff.
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 }
|
|
|
Get the form of difference from a role diff.
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 }
|
|
|
Get a vector of types added to the role.
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 }
|
|
|
Get a vector of types removed from the role.
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 }
|
|
|
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 }
|
|
|
Allocate and return a new poldiff_role_summary_t object.
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 }
|
|
|
Deallocate all space associated with a poldiff_role_summary_t object, including the pointer itself. If the pointer is already NULL then do nothing.
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 }
|
|
|
Reset the state of all role differences.
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||
|
Get a vector of all roles from the given policy, sorted by name.
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 }
|
|
||||||||||||||||
|
Compare two qpol_role_t objects, determining if they have the same name or not.
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 }
|
|
||||||||||||||||
|
Allocate and return a new role difference object.
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 }
|
|
||||||||||||||||
|
Create, initialize, and insert a new semantic difference entry for a role.
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 }
|
|
||||||||||||||||
|
Given a role, return an unsorted vector of its allowed types (in the form of uint32_t corresponding to pseudo-type values).
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 }
|
|
||||||||||||||||
|
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.
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 }
|