📄 pgprngpub.c
字号:
/* Okay, allocated - fill it in */
iter->set.pool = pool;
iter->set.next = pool->sets;
iter->set.type = RINGSET_ITERATOR;
pool->sets = &iter->set;
iter->set.mask = set->mask;
iter->level = 0; /* Rewind to beginning */
return iter;
}
void
ringIterDestroy(RingIterator *iter)
{
RingPool *pool;
RingSet **setp;
if (iter) {
pool = iter->set.pool;
pgpAssert(iter->set.type == RINGSET_ITERATOR);
iter->set.type = RINGSET_FREE;
/* Remove it from the list of allocated sets */
setp = &pool->sets;
while (*setp != &iter->set) {
pgpAssert(*setp);
setp = &(*setp)->next;
}
*setp = iter->set.next;
/* Add to the list of free iterators. */
iter->set.next = (RingSet *)pool->freeiter;
pool->freeiter = iter;
}
}
static RingSet *
ringSetAlloc(RingPool *pool)
{
RingSet *set;
/* Allocate the structure */
set = pool->freesets;
if (set) {
pool->freesets = set->next;
} else {
set = (RingSet *)memPoolNew(&pool->structs,
RingSet);
if (!set) {
ringAllocErr(pool);
return NULL;
}
}
/* Okay, allocated - fill it in */
set->pool = pool;
set->next = pool->sets;
pool->sets = set;
pgpVirtMaskInit (pool, &set->mask);
/* set->type uninitialized */
return set;
}
RingSet *
ringSetCreate(RingPool *pool)
{
PGPVirtMask mask;
RingSet *set;
unsigned bit;
PGPError err;
if (!pool)
return NULL;
/* Allocate a new bit */
err = ringBitAlloc(pool, &bit);
if (IsPGPError(err)) {
ringSimpleErr(pool, err);
return NULL;
}
pgpVirtMaskInit (pool, &mask);
pgpVirtMaskSetBit (pool, &mask, bit);
/* Allocate the structure */
set = ringSetAlloc(pool);
if (set) {
pgpVirtMaskCopy (pool, &mask, &set->mask);
set->type = RINGSET_MUTABLE;
pgpVirtMaskOR (pool, &mask, &pool->allocmask);
}
pgpVirtMaskCleanup (pool, &mask);
return set;
}
/* Create a "universal" set which represents all keys in the pool */
RingSet *
ringSetCreateUniversal(RingPool *pool)
{
RingSet *set;
if (!pool)
return NULL;
/* Allocate the structure */
set = ringSetAlloc(pool);
if (set) {
pgpVirtMaskCopy (pool, &pool->allocmask, &set->mask);
set->type = RINGSET_IMMUTABLE;
}
return set;
}
void
ringSetDestroy(RingSet *set)
{
RingPool *pool;
RingSet **setp;
if (set) {
pool = set->pool;
pgpAssert(set->type < RINGSET_FREE);
set->type = RINGSET_FREE;
/* Remove it from the list of allocated sets */
setp = &pool->sets;
while (*setp != set) {
pgpAssert(*setp);
setp = &(*setp)->next;
}
*setp = set->next;
pgpVirtMaskCleanup (pool, &set->mask);
/* Add to the list of free sets. */
set->next = pool->freesets;
pool->freesets = set;
}
}
/*
* Freeze a RingSet so that you can start doing set operations
* on it, copying it, etc.
*/
PGPError
ringSetFreeze(RingSet *set)
{
if (set) {
if (set->type == RINGSET_MUTABLE)
set->type = RINGSET_IMMUTABLE;
pgpAssert(set->type == RINGSET_IMMUTABLE);
}
return kPGPError_NoErr;
}
RingSet *
ringSetCopy(RingSet const *s)
{
RingSet *set;
if (!s)
return NULL;
pgpAssert(!RINGSETISMUTABLE(s));
set = ringSetAlloc(s->pool);
if (set) {
pgpVirtMaskCopy (s->pool, &s->mask, &set->mask);
set->type = RINGSET_IMMUTABLE;
}
return set;
}
/* This accepts NULL as an alias for "no such set" */
RingSet *
ringSetUnion(RingSet const *s1, RingSet const *s2)
{
RingSet *set;
if (!s1)
return ringSetCopy(s2);
set = ringSetCopy(s1);
if (set && s2) {
pgpAssert(s1->pool == s2->pool);
pgpAssert(!RINGSETISMUTABLE(s2));
pgpVirtMaskOR (s1->pool, &s2->mask, &set->mask);
}
return set;
}
/** The following operations only apply to mutable RingSets **/
/*
* Add an object to a mutable RingSet. That includes the all of the
* object's parents in order to main the proper RingSet invariants.
*/
int
ringSetAddObject(RingSet *set, union RingObject *obj)
{
pgpAssert(RINGSETISMUTABLE(set));
if (IsntNull(obj) && !pgpIsRingSetMember(set, obj)) {
pgpVirtMaskOR (set->pool, &set->mask, &obj->g.mask);
/* Ensure all parents are added, too. */
while (!OBJISTOP(obj)) {
obj = obj->g.up;
if (pgpIsRingSetMember(set, obj))
break;
pgpVirtMaskOR (set->pool, &set->mask, &obj->g.mask);
}
}
return 0;
}
/*
* Add an object and its children to a mutable RingSet. Also will do
* the object's parents. src RingSet controls which children are added.
*/
int
ringSetAddObjectChildren(RingSet *dest, RingSet const *src,
union RingObject *obj)
{
RingSet const *srcx;
RingIterator *iter;
int level, initlevel;
int nobjs;
int err;
/* Need to iterate over src, make a copy if necessary */
srcx = src;
if (RINGSETISMUTABLE(src)) {
RingSet *src1 = ringSetCreate (ringSetPool (src));
if (!src1)
return ringSetError(src)->error;
ringSetAddSet (src1, src);
ringSetFreeze (src1);
src = (RingSet const *)src1;
}
/* First add the object */
if ((err= (PGPError)ringSetAddObject(dest, obj)) < 0)
return err;
iter = ringIterCreate(src);
if (!iter)
return ringSetError(src)->error;
nobjs = 1;
initlevel=ringIterSeekTo(iter, obj);
if (initlevel < 0)
return initlevel;
level = initlevel + 1;
while (level > initlevel) {
union RingObject *child;
err = (PGPError)ringIterNextObject(iter, level);
if (err < 0) {
ringIterDestroy(iter);
return err;
}
if (err > 0) {
child = ringIterCurrentObject(iter, level);
if (!child)
return ringSetError(src)->error;
if ((err=ringSetAddObject(dest, child)) < 0)
return err;
++nobjs;
++level;
} else {
--level;
}
}
ringIterDestroy(iter);
/* Destroy set copy if we made one */
if (src != srcx)
ringSetDestroy ((RingSet *)src);
return nobjs;
}
/*
* Remove an object from a mutable RingSet. That includes the all of the
* object's children in order to main the proper RingSet invariants.
* (Done recursively.)
*/
int
ringSetRemObject(RingSet *set, union RingObject *obj)
{
pgpAssert(RINGSETISMUTABLE(set));
/*
* Remove this object and all its children.
* As an optimization, omit scanning children if the
* object is not already in the set.
*/
if (IsntNull(obj) && pgpIsRingSetMember (set, obj)) {
if (!OBJISBOT(obj)) {
union RingObject *obj2 = obj;
for (obj2 = obj2->g.down; obj2; obj2 = obj2->g.next)
ringSetRemObject(set, obj2);
}
pgpVirtMaskANDNOT (set->pool, &set->mask, &obj->g.mask);
ringGarbageCollectObject(set->pool, obj);
}
return 0;
}
/* Helper function for ringSetAddSet */
static void
ringSetAddList(union RingObject *obj, RingSet *dest, RingSet const *src)
{
while (obj) {
if (pgpIsRingSetMember(src, obj)) {
pgpVirtMaskOR (dest->pool, &dest->mask, &obj->g.mask);
if (!OBJISBOT(obj))
ringSetAddList(obj->g.down, dest, src);
}
obj = obj->g.next;
}
}
int
ringSetAddSet(RingSet *set, RingSet const *set2)
{
pgpAssert(RINGSETISMUTABLE(set));
if (set2) {
pgpAssert(set->pool == set2->pool);
ringSetAddList(set->pool->keys, set, set2);
}
return 0;
}
/*
* Subtracting sets is simplified by the proper-set requirement.
* If I remove a key (because it's in set2), I have to remove all
* children of the key, so I just use ringClearMask to do
* the job. If I don't (because it's not in set2), then it's
* guaranteed that none of its children are in set2 either,
* so there's no need to examine any children.
*/
int
ringSetSubtractSet(RingSet *set, RingSet const *set2)
{
union RingObject *obj;
PGPVirtMask tmask;
pgpAssert(RINGSETISMUTABLE(set));
pgpVirtMaskInit (set->pool, &tmask);
if (IsntNull(set2) && !pgpVirtMaskIsEmpty(&set2->mask)) {
pgpAssert(set->pool == set2->pool);
for (obj = set->pool->keys; obj; obj = obj->g.next) {
if (pgpIsRingSetMember (set, obj)
&& pgpIsRingSetMember (set2, obj)) {
pgpVirtMaskANDNOT (set->pool, &set->mask, &obj->g.mask);
if (!OBJISBOT(obj)) {
ringClearMask(set->pool, &obj->g.down, NULL,
&set->mask, &tmask);
}
}
}
}
pgpVirtMaskCleanup (set->pool, &tmask);
return 0;
}
static int
ringSetIntersectList(union RingObject *obj, RingSet const *s1,
RingSet const *s2, RingSet const *dest)
{
int flag = 0;
while (obj) {
if (pgpIsRingSetMember(s1,obj) &&
pgpIsRingSetMember(s2,obj)) {
flag = 1;
pgpVirtMaskOR (s1->pool, &dest->mask, &obj->g.mask);
if (!OBJISBOT(obj))
ringSetIntersectList(obj->g.down, s1, s2, dest);
}
obj = obj->g.next;
}
return flag;
}
RingSet *
ringSetIntersection(RingSet const *s1, RingSet const *s2)
{
RingSet *set;
PGPVirtMask mask;
if (!s1 || !s2)
return (RingSet *)NULL;
pgpVirtMaskInit (s1->pool, &mask);
pgpAssert(s1->pool == s2->pool);
pgpAssert(!RINGSETISMUTABLE(s1));
pgpAssert(!RINGSETISMUTABLE(s2));
/* Do a few trivial cases without allocating bits. */
pgpVirtMaskCopy (s1->pool, &s1->mask, &mask);
pgpVirtMaskANDNOT (s1->pool, &s2->mask, &mask);
if (!pgpVirtMaskIsEmpty(&mask)) { /* s1 is a subset of s2 - copy s1 */
pgpVirtMaskCleanup (s1->pool, &mask);
return ringSetCopy(s1);
}
pgpVirtMaskCopy (s1->pool, &s2->mask, &mask);
pgpVirtMaskANDNOT (s1->pool, &s1->mask, &mask);
if (!pgpVirtMaskIsEmpty(&mask)) { /* s2 is a subset of s1 - copy s2 */
pgpVirtMaskCleanup (s1->pool, &mask);
return ringSetCopy(s2);
}
set = ringSetCreate(s1->pool);
if (set) {
if (!ringSetIntersectList(s1->pool->keys, s1, s2, set))
{
/* Empty set - free bit */
pgpVirtMaskANDNOT (s1->pool, &set->mask, &s1->pool->allocmask);
pgpVirtMaskCleanup (s1->pool, &set->mask);
}
set->type = RINGSET_IMMUTABLE;
}
pgpVirtMaskCleanup (s1->pool, &mask);
return set;
}
static void
ringSetDiffList(union RingObject *obj, RingSet const *s1, RingSet const *s2,
RingSet const *dest)
{
while (obj) {
if (pgpIsRingSetMember(s1, obj) &&
!pgpIsRingSetMember(s2, obj)) {
pgpVirtMaskOR (s1->pool, &dest->mask, &obj->g.mask);
if (!OBJISBOT(obj))
ringSetDiffList(obj->g.down, s1, s2, dest);
}
obj = obj->g.next;
}
}
/* Return s1-s2. */
RingSet *
ringSetDifference(RingSet const *s1, RingSet const *s2)
{
RingSet *set;
PGPVirtMask mask;
if (IsNull(s1))
return NULL;
if (IsNull(s2) || pgpVirtMaskIsEmpty(&s2->mask))
return ringSetCopy(s1);
pgpAssert(s1->pool == s2->pool);
pgpAssert(!RINGSETISMUTABLE(s1));
pgpAssert(!RINGSETISMUTABLE(s2));
pgpVirtMaskInit (s1->pool, &mask);
pgpVirtMaskCopy (s1->pool, &s1->mask, &mask);
pgpVirtMaskANDNOT (s1->pool, &s2->mask, &mask);
if (pgpVirtMaskIsEmpty(&mask)) {
/* s1->mask is a subset of s2->mask, so result is empty */
set = ringSetAlloc(s1->pool);
if (set) {
pgpVirtMaskCleanup (s1->pool, &set->mask);
set->type = RINGSET_IMMUTABLE;
}
} else {
set = ringSetCreate(s1->pool);
if (set) {
ringSetDiffList(s1->pool->keys, s1, s2, set);
set->type = RINGSET_IMMUTABLE;
}
}
pgpVirtMaskCleanup (s1->pool, &mask);
return set;
}
int
ringFileIsDirty(RingFile const *file)
{
return file ? file->flags & RINGFILEF_DIRTY : 0;
}
int
ringFileIsTrustChanged(RingFile const *file)
{
return file ? file->flags & RINGFILEF_TRUSTCHANGED : 0;
}
RingPool *
ringPoolCreate(PGPEnv const *env)
{
RingPool *pool;
PGPContextRef context = pgpenvGetContext( env );
pool = (RingPool *)pgpContextMemAlloc( context,
sizeof(*pool), kPGPMemoryMgrFlags_Clear );
if (pool)
ringPoolInit( context, pool, env);
return pool;
}
void
ringPoolDestroy(RingPool *pool)
{
if (pool) {
PGPContextRef cdkContext = pool->context;
ringPoolFini(pool);
pgpContextMemFree( cdkContext, pool);
}
}
PGPContextRef
ringPoolContext(RingPool *pool)
{
pgpAssert( pool );
return pool->context;
}
union RingObject *
ringKeyById8(
RingSet const * set,
PGPByte pkalg,
PGPByte const * keyID)
{
RingKey *key;
if ((pkalg|1) == 3) /* viacrypt */
pkalg = 1;
for (key = set->pool->hashtable[keyID[0]]; key; key = key->util) {
if ((((key->pkalg|1) == 3) ? 1 : key->pkalg) == pkalg &&
memcmp(keyID, key->keyID, 8) == 0) {
if (!pgpIsRingSetMember(set, (union RingObject *)key))
break;
ringObjectHold((union RingObject *)key);
return (union RingObject *)key;
}
}
/* Failed */
return NULL;
}
#if 0
union RingObject *
ringKeyById4(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -