This document describes the file format of the protection database file.

The actual prdb.DB0 file on disk begins with a ubik header, which is not
exposed to the callers of ubik_ RPCs.  64 octets are reserved for this header,
though only 16 are used.  The first 16 octets contain the representation
of a struct ubik_hdr, with all fields in network byte order:

       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                           ubik_magic                          |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |            padding            |          header_size          |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                             epoch                             |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                            counter                            |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                            [unused]                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                            [unused]                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                            [unused]                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                            [unused]                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                            [unused]                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                            [unused]                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                            [unused]                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                            [unused]                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                            [unused]                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                            [unused]                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                            [unused]                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                            [unused]                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
       0                   1                   2                   3

ubik_magic is a global constant, 0x00354545.

padding is an unused field and should always be zeros.

header_size is the length of the reserved space for the ubik header,
and will always be 0x64.

epoch is the ubik epoch.

counter is the ubik counter for transactions and updates.

The unused space should always be zeros.

The ubik header is not exposed through the PR_ RPC package, and as such
is not considered to be part of the logical prdb database.  Subsequent
discussion will refer to addresses and offsets; these addresses are logical
addresses within the prdb, and do not include the size of the ubik header.
When using logical addresses to index into the file on disk, the size of
the ubik header must be added to the offset used.


Immediately following the ubik header on disk (so, at the beginning of the
logical prdb) is the prdb header, which consumes 65600 octets.
The majority of this space is for two hash tables, enabling
quick lookups of prdb entries by name and by id.  All fields with integer
values are stored in network byte order.

The prdb header structure is:

        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
octets +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     0 |                            version                            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          headerSize                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                            freePtr                            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                            eofPtr                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           maxGroup                            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                             maxID                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           maxForeign                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                            maxInst                            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    32 |                            orphan                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           usercount                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          groupcount                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                         foreigncount                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           instcount                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          [reserved]                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          [reserved]                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          [reserved]                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    64 |                          [reserved]                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          [reserved]                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    72 |                           nameHash                            |
       |                                                               |
       ~                              ...                              ~
 32832 |                                                               |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 32836 |                            idHash                             |
       |                                                               |
       ~                              ...                              ~
 65596 |                                                               |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        0                   1                   2                   3

version is the PR database version number.  Only version number 0 is
presently in use.

headerSize is the size in octets of the prdb header (currently 0x10040).

freePtr is the logical index (in octets) of the first unused prentry in the
prdb (that is, the first logical hole in the database file).  If the database
file is densely packed, this field is zero.  This index is not the actual
index into the prdb.DB0 file on disk, because logical indices within the
prdb do not account for the 64-octet space reserved for the ubik header.

eofPtr is the index (in octets) of the end of the database file.  When a new
entry is created that extends the database file, it will be created at this
logical index.  (Again, this logical index excludes the 64-octet ubik header.)

maxGroup is the most negative group ID allocated, stored as a 32-bit
twos-complement signed integer.

maxId is the largest user ID allocated to a local-realm user.

maxForeign is the largest user ID allocated to a foreign-realm user.

maxInst is reserved for a feature which is not yet implemented.

orphan is the pointer to the head of the list of "orphaned" prdb entries.
Entries are orphaned when their owner gets deleted; at that time, they are
added to the head of the orphan list.

usercount is the number of user entries in the prdb.

groupcount is the number of group entries in the prdb, including mandatory
groups such as system:backup, system:administrators, system:ptsviewers,
system:authuser, and system:anyuser.

foreigncount is the number of foreign users that have registered with the
prdb.

instcount is reserved for a feature which is not yet implemented.

Five 32-bit fields are reserved for future expansion.

The nameHash and idHash fields each contain 8191 entries; each entry is 32 bits,
so the space consumed by each hash table is 32764 octets.

The NameHash hash function is targetted for ASCII text.  Each octet is
treated as an unsigned integer from which 31 (decimal) is subtracted
(corresponding to the 7-bit control characters), and the resulting stream
of integers is used as the coefficients of a power series with base 31 (also
decimal), with the least significant coefficient appearing first.
For example, if a name string was the (highly unlikely and nigh-unusable)
stream of octets (in hex):
21 22 23 24
Then the power series used in the hash function calculation would be
(all numbers in decimal):
2 + 3 * 31 + 4 * 31**2 + 5 * 31**3
The value of this power series is stored in an unsigned 32-bit integer,
and as such is implicitly computed modulo 2**32.  The remainder modulo
8191 (the size of the hash table) of this 32-bit value is used as the
index into the hash table for this name entry.
(This hash function can be easily implemented iteratively.)

The IdHash hash function is very simple; it is just the remainder modulo
8191 (the size of the hash table) of the absolute value of the user or
group id.  Note that a group id of INT_MIN would cause undefined behavior
in the evaluation of this hash function, and is given the name PRBADID
and used as a sentinel.

Hash collisions are treated in the standard way of having a linked list
of entries with the same hash.  The hash table itself holds the id of the
entry which is the head of the list, and the nextName and nextID fields
of each entry chain the lists for the respective hash tables.


prdb entries follow immediately after the prdb header.  Each entry is
192 octets in size, and may represent either a user or a group or (if
enabled) a supergroup entry, or a continuation entry.

User and group entries use the same format for the data structure (user
ids are positive and group ids are negative, and their structures parallel
each other), and continuation entries are used when a user belongs to more
than PRSIZE (10) groups or a group has more than PRSIZE users in it.
supergroup entries share many fields with the user/group entries, but
the binary format is slightly different.  In all cases, integer fields
are represented in network byte order.

All entries have a flags field in the second 16 bits which is used to indicate
what type the entry is -- PRFREE, PRGRP, PRCONT, PRCELL, PRFOREIGN, or PRINST
(not used).  The other fields which are invariant in the block structure
(i.e., present in all types of entry) are id, cellid, and next.  At present
there is also a reserved field in all entry types at a fixed offset; this
field can be used for future extensions.  Another invariant is that each
block (outside the header) is pointed to from some other location.  Continuation
blocks are pointed to from the 'next' field of the previous block, and
user/group entries are locatable from the name and id hash tables, either
directly from the header or through a nextName/nextID pointer.  The head
of the free list is in the prdb header directly.

The layout of the invariant fields is:

        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
octets +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     0 |       [entry-specific]        |          type_flags           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                              id                               |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                            cellid                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                             next                              |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    16 |                       [entry-specific]                        |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                       [entry-specific]                        |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                       [entry-specific]                        |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                       [entry-specific]                        |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    32 |                           reserved                            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

type_flags specifies the type of this prdb entry:
0x1	PRFREE    -- the entry is on the free list
0x2	PRGRP     -- the entry is a group entry
0x4	PRCONT    -- the entry is a continuation block
0x8	PRCELL    -- the entry is a cell entry
0x10	PRFOREIGN -- the entry is for a foreign user
0x20	PRINST    -- the entry is a sub/super instance
0x3f    PRTYPE    -- bitmask for "type" bits
Other bits are allocated for status flags on the entry:
0x40	PRACCESS  -- access checking is enabled
0x80	PRQUOTA   -- group creation quota checking is enabled
Note that this document specifies the on-disk data format, which is in
network byte order. Because the fundamental quantum of ubik accesses is
a 32-bit word, byte swaps between host and network byte order are done
on 32-bit words, so the in-memory representation may place the bits
holding type_flags in the other half of the word.

id is the ID number of the user or group, or the user/group to which
an continuation or other extension entry belongs.  User entries are positive
and group entries are negative.

cellid is only used for foreign user entries (not foreign groups).
Group entries are allocated for system:authuser@remotecell with
a (negative 32-bit) group id of a particular substructure.  Foreign
user entries have their cellid field set to the id of the
system:authuser@remotecell group corresponding to the remotecell of the
foreign user.  (Additionally, foreign user entries are allocated pts ids
with a particular substructure.)
There is no particularly good reason for the cellid field to remain an
invariant in future extensions.

next is a pointer to the next entry in a chain of related data for this
entry, e.g. a continuation block.  For type PRFREE entries, it is a pointer
to the next block on the free list.


The layout of a user or group entry (struct prentry) is:

        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
octets +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     0 |           prp_flags           |          type_flags           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                              id                               |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                            cellid                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                             next                              |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    16 |                          createTime                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                            addTime                            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          removeTime                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          changeTime                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    32 |                           reserved0                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           entries[0]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           entries[1]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           entries[2]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    48 |                           entries[3]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           entries[4]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           entries[5]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           entries[6]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    64 |                           entries[7]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           entries[8]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           entries[9]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                             nextID                            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    80 |                            nextName                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                             owner                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                            creator                            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                            ngroups                            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    96 |                             nusers                            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                             count                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                            instance                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                             owned                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   112 |                           nextOwned                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                            parent                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                            sibling                            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                             child                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   128 |                             name                              |
       +                                                               +
       |                                                               |
       +                                                               +
       |                                                               |
       +                                                               +
       |                                                               |
       +                                                               +
   144 |                                                               |
       +                                                               +
       |                                                               |
       +                                                               +
       |                                                               |
       +                                                               +
       |                                                               |
       +                                                               +
   160 |                                                               |
       +                                                               +
       |                                                               |
       +                                                               +
       |                                                               |
       +                                                               +
       |                                                               |
       +                                                               +
   176 |                                                               |
       +                                                               +
       |                                                               |
       +                                                               +
       |                                                               |
       +                                                               +
   188 |                                                               |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        0                   1                   2                   3

prp_flags and type_flags are consolidated into a single "flags" field for
API purposes.
prp_flags hold the access bits for entries, e.g., PRP_STATUS_ANY
and PRP_ADD_MEM.
Because prp_flags and type_flags are consolidated
into a single 'flags' field for the API, the in-memory layout will have
prp_flags and type_flags swapped on little-endian machines.

[id and cellid are per the entry-invariant fields]

next is a pointer to the next continuation block for this entry, or (for
type PRFREE entries) a pointer to the next block on the free list.

createTime holds the time at which this entry was created, in seconds from
the Unix epoch.

addTime is the most recent time at which an entry was added to this
usr/group's membership list, in seconds since the Unix epoch.

removeTime is the most recent time at which an entry was removed from this
user/group's membership list, in seconds since the Unix epoch.

changeTime is the most recent time at which the entry was changed with
a PR_ChangeEntry RPC (that is, renamed or renumbered or had owner
or name change).  Changing the access flags does not update this time.

reserved[0] is reserved for future use.

entries[0-9] hold the first ten elements of this entry's membership list
(the users in this group, or the groups of which this user is a member).
They are populated in increasing order; when fewer than ten elements are
present, the unused fields are zero or PRBADID.  Additional elements of the
membership list are stored in continuation block(s).

nextID is a pointer for the hash table chain in the header's idHash hash
table.  All prdb entries whose id hashes to the same value are stored in
a singly-linked list; this field effects the linkage of that list.

nextName is similar to nextID, but for the nameHash hash table instead of
the idHash hash table.

owner is the id of the the prdb entry which owns this entry.

creator is the id of the prdb entry which created this entry.

ngroups is the number of groups this entry is still allowed to create
(it is the quota minus the number of groups which have been created).
For regular group entries, this field is always zero.
For foreign group entries, this is the number of (foreign) users who are
members of that group.

nusers is nominally the foreign user registration quota for a user entry,
that is, the number of foreign user entries this user is still allowed to
create.  However, this quota value is never actually used -- the presence of
nusers for user entries was intended to support a feature which has not been
implemented.
For regular group entries, it is always zero.
For foreign group entries (i.e., system:authuser@remotecell), nusers is the
number of foreign user entries which are members of the group.
(It is used when allocating user ids for new foreign users from that cell.)

count is the cardinality of this entry's membership list.  That is, for user
entries, the number of groups of which this user is a member; for group entries,
the number of users in the group.

instances is reserved for a feature which is not yet implemented.

owned is the head of the linked list of entries owned by this entry.
Both users and groups may own group entries (user entries always display
as being owned by system:administrators though the numerical value of this
field is zero).  The nextOwned field of the group entries chains this list.

nextOwned is the pointer to the next entry in the list of groups owned
by a the owner of this group.
For user entries, this field is always zero.

parent is reserved for a feature which is not yet implemented.

sibling is reserved for a feature which is not yet implemented.

child is reserved for a feature which is not yet implemented.

name holds the name of this entry.  For users, it is the krb4 name;
for groups, is is an ASCII string.  The name is NUL-terminated, making the
maximum permissible length of a name 63 characters.  Unused portions of this
field should be zeroed.


Supergroup entries are quite similar to regular user/group entries, differing
only at the 'instance', 'parent', 'sibling', and 'child' fields,
which are replace by 'countsg', 'nextsg', 'supergroup[0]', and
'supergroup[1]', respectively.  Putting the byte offsets in, those fields
are:

        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
octets +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   104 |                            countsg                            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                             owned                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   112 |                           nextOwned                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                            nextsg                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                         supergroup[0]                         |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                         supergroup[1]                         |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   128 |                             name                              |
       ~                                                               ~
   188 |                                                               |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        0                   1                   2                   3

countsg is the number of groups of which this group is a member, akin to
the 'count' field of a user entry.

nextsg is a pointer to a chain of continuation blocks holding additional
supergroup entries for this group.  That is, the 'entries' elements of the
continuation blocks will be groups of which this group is a member, akin
to supergroup[0-1].  This chain is extended using the 'next' pointer of
the contentry structure, if necessary.

supergroup[0-1] are the first two groups of which this group is a member.
These supergroup elements are used in increasing order, and unused elements
should be zero (but PRBADID is also okay).


Continuation entries have a simpler structure, retaining a few key fields
that are shared amongst all types of entry but leaving a large contiguous
block of space to be used as an array of ids.  Again, all integer
fields are stored in network byte order.  The format is:

        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
octets +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     0 |             unused            |          type_flags           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                              id                               |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                            cellid                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                             next                              |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    16 |                          reserved[0]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          reserved[1]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          reserved[2]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          reserved[3]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    32 |                          reserved[4]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           entries[0]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           entries[1]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           entries[2]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    48 |                           entries[3]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       ~                              ...                              ~
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   188 |                          entries[38]                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        0                   1                   2                   3

the type_flags field is again exposed via the API as a 32-bit 'flags' field,
but only the low 16 bits are used for flags by continuation entries.

id and cellid are retained as a consistency check for the entry -- these
fields should be identical amongst the main entry and all continuation
blocks chained to it.

The four Time fields present in the user/group entries are not needed for
continuation entries, but are left as reserved so as to make the space
used for holding ids a contiguous array.

Each continuation block can hold up to 39 additional prdb ids associated
with the original user or group entry, extending the original 10 entries
available in the main entry block (for user/group membership) or the
original 2 entries available in the main group block (for supergroup
membership).
