Factor out ulog serial number status check

Add a new function ulog_get_sno_status, which checks a serial number
and timestamp against the ulog for currency.  Use it in kdb5_util
dump's current_dump_sno_in_ulog and (except for locking) in
ulog_get_entries.  Adjust parse_iprop_header's contract in dump.c to
better match the ulog_get_sno_status contract.

Relative to ulog_get_entries, we now explicitly check for an empty
ulog (by checking if kdb_num == 0).  This change helps prepare for
hierarchical iprop support, because an intermediate slave can have an
empty ulog file with a non-zero kdb_last_sno value.  Also, the old
code was setting lastentry.last_sno in one of the cases where it
returned UPDATE_FULL_RESYNC_NEEDED, but this value wasn't used and
couldn't possibly be relied on since it wasn't set in other cases
where UPDATE_FULL_RESYNC_NEEDED was returned.

Relative to current_dump_sno_in_ulog, we now return true with an empty
ulog as long as the dump's last serial number and timestamp match the
ulog last serial number and timestamp exactly.  This change also helps
prepare for hierarchical iprop support, because unlike a master KDC,
an intermediate slave will have an empty ulog each time it receives a
dump from upstream.  Also, we now check the timestamp of the dump's
last serial number against the actual ulog entry (as we always have in
ulog_get_entries) instead of checking against the ulog's
kdb_first_time field.  This way is more robust against non-monotonic
clocks.  Finally, we now lock the ulog around the check.

ticket: 7855
Lock around more ulog operations

We are lax about locking for ulog operations which primarily happen on
slaves, which is harmless right now because slaves are effectively
single-threaded for the most part.  But hierarchical iprop will allow
for a kadmind to be running alongside the slave operations, so we need
to be more disciplined about locking.  Therefore:

* Make ulog_init_header acquire an exclusive lock.  Correspondingly,
  simplify the libkdb5 policy operations to just call ulog_init_header
  after the DB module operation succeeds.

* Add interfaces to get and set the last serial number and timestamp
  in the ulog header with a lock held, and use them in dump.c and
  kpropd.c.

* Add comments stating that ulog_add_update and ulog_finish_update
  should be called with the ulog locked.

ulog_replay also needs to lock, but it needs to change in other ways
for hierarchical iprop, so it will be addressed later.
ulog_sync_header no longer needs to be used outside of kdb_log.c, so
turn it back into a static helper.

ticket: 7855
Simplify ulog_map

Get rid of the caller parameter.  The kproplog semantics (without -R)
for mapping the ulog are simple and almost completely different from
other users of the ulog, so implement them as a static helper in
kproplog.  With hierarchical iprop, kpropd will need the same
semantics as FKCOMMAND and FKADMIND, which were already identical.

Remove an inoperative lseek() call when creating a new ulog file.
Rename ulog_filesize to filesize and compute it from scratch each time
we use it, for easier analysis.  If kdb_hmagic is zero, init the ulog
header but don't skip the rest of the function; it's possible that we
need to expand the ulog file.  Remove an unneeded conditional before
calling extend_file_to for an existing ulog.

ticket: 7855
Maintain complete ulog on iprop slaves

Factor out most of ulog_add_update into a helper function named
store_update, and make ulog_add_update just responsible for assigning
a serial number and timestamp to the update before storing it.  In
ulog_replay, use store_update and ulog_finish_update to add each
update to the ulog in addition to replaying it to the database.  Don't
use incr_ret->lastentry to set kdb_last_sno/kdb_last_time, since it
will have been set properly by adding the individual updates; instead,
just reinitialize the ulog on error.

Slave ulogs use serial numbers provided from upstream, and thus do not
always begin at serial number 1 after a header reset.  As a result, we
must (1) in store_update, detect the first update (for which we must
assign kdb_first_sno/kdb_first_time) by comparing kdb_num to 0,
instead of by comparing the serial number to 1, (2) in store_update,
detect that we are overwriting the first update by comparing kdb_num
to ulogentries, instead of comparing the serial number to ulogentries,
and (3) in ulog_map, detect that ulogentries changed by verifying the
first and last serial number and timestamp against the corresponding
entries, rather than comparing kdb_last_sno to kdb_num.

Based on code submitted by Richard Basch.

ticket: 7855
Implement kadmind -proponly

The -proponly option causes kadmind to only service the iprop service,
not the kpasswd or kadmin services.  An intermediate slave in a
hierarchical iprop setup runs kadmind -proponly in order to provide
incremental updates to downstream slaves.

Based on code submitted by Richard Basch.

ticket: 7855
Implement kpropd -A

The -A option causes kpropd to contact a specified admin server
(normally an intermediate slave running kadmind -proponly) instead of
the master admin server.

Based on code submitted by Richard Basch.

ticket: 7855
Test iprop slave ulog management

Check the ulog more thoroughly after each operation, including the
principal names we expect in each update entry.  Verify that the slave
ulog contains actual update entries received from master.  Add a
second slave which receives updates from the first.  Test a wider
variety of principal operations.  Add two additional operations after
the full resync to test that incremental updates resume after a full
resync (albeit with some lag).

ticket: 7855