Examining structures exposed in the API

Ken Raeburn raeburn at MIT.EDU
Thu Mar 13 22:37:09 EST 2003

"Theodore Ts'o" <tytso at MIT.EDU> writes:
> On Sat, Mar 08, 2003 at 11:09:22PM -0500, Sam Hartman wrote:
>> In such cases you need to be prepared to support old versions of your
>> structure to maintain ABI compatibility.  I.E. having a
>> krb5_search_creds structure would have been fine, but using this same
>> structure as the krb5_credentials structure elsewhere in the code is
>> not fine at all.

Right.  The credentials returned have keys with specific enctypes; the
get_credentials call ought to be able to supply a list.  Similarly
with other fields.

> For this case one solution is to add some spare entries to the data
> structures:
> 	struct foo {
> 		...
> 		int	spare_int[8];
> 		void	*spare_ptr[8];
> 	};

As long as the initialization function can report a failure for memory
allocation errors, and you add a finalization function too, yes, this
should work.  The pointers give you the hooks you need in case the
structure turns out not to be big enough.  (Or you could go all the
way in the other direction, and only give the application a single
pointer, letting the library completely control the data pointed to,
like krb5_auth_context in MIT krb5.)

> Then define a function which initializes the data structure, and you
> can now add new elements to the structure to define new ways to search
> for krb5 credentials, for example, while maintaining both ABI and API
> compatibility.  There are some gotchas of course; you need to be
> careful about situations where off_t might be different types on
> different archiectures or operating systems, for example, but on the
> whole this trick can be quite useful.

Yes, this can be a problem, if you add spare "int" fields and need to
store a size_t.  (Alignment may also become an issue.)  Perhaps the
spare field should be more like:

union { unsigned char c[4]; long l; size_t sz; off_t off; void *ptr; }

That'll waste space when you need a 32-bit field on a 64-bit machine,
but it's probably better than trying to figure out how many int fields
you need to consume for a size_t.  (That's debatable, of course; for
an embedded system, writing the hairy macros and letting the compiler
do the crunching may be better than wasting the space.)


More information about the krbdev mailing list