📄 pgpkeyset.c
字号:
{
pgpContextMemFree( context, db );
return NULL;
}
db->numKeyDBDependencies = 0;
memPoolInit( context, &db->keyPool);
db->numKeys = 0;
db->firstKeyInDB = NULL;
db->firstFreeKey = NULL;
db->firstFreeUserID = NULL;
db->firstFreeCert = NULL;
db->keysByKeyID = NULL;
return db;
}
/* Does any additional initialization necessary after DB is fully created */
void
pgpKeyDBInitInternal(PGPKeyDB *db)
{
/* Nothing for now */
(void)db;
}
/* Does the final destruction of a key database structure */
void
pgpKeyDBDestroyInternal(PGPKeyDB *db)
{
PGPContextRef context = db->context;
pgpAssert( pgpContextIsValid( context ) );
pgpKeyDBReleaseDependencies( db );
pgpContextMemFree( context, db->keyDBDependencies );
memPoolEmpty( &db->keyPool );
pgpClearMemory( db, sizeof(*db) );
pgpContextMemFree ( context, db );
}
static PGPKey *
allocKey(PGPKeyDB *db)
{
PGPKey * key;
pgpa(pgpaPGPKeyDBValid(db));
if (db->firstFreeKey != NULL)
{
key = db->firstFreeKey;
db->firstFreeKey = key->nextKeyInDB;
}
else
key = (PGPKey *)memPoolNew(&db->keyPool, PGPKey);
if ( IsntNull( key ) )
{
pgpClearMemory(key, sizeof(*key));
#if PGP_OPTIONAL_MAGICS
key->magic = kPGPKeyMagic;
#endif
}
return key;
}
static void
deallocKey(PGPKeyDB *db, PGPKey *key)
{
pgpa((
pgpaPGPKeyDBValid(db),
pgpaAssert(db == key->keyDB)));
#if PGP_OPTIONAL_MAGICS
key->magic = ~key->magic;
#endif
key->nextKeyInDB = db->firstFreeKey;
db->firstFreeKey = key;
}
static PGPError
addKeyToList(PGPKeyList *list, PGPKey *key)
{
long i;
long newKeyCount;
PGPKey ** newKeys;
PGPContextRef context = PGPGetKeyListContext( list );
pgpa(pgpaPGPKeyListValid(list));
i = binarySearchKeyList(list, key);
newKeyCount = list->keyCount + 1;
newKeys = (PGPKey **)pgpContextMemAlloc( context,
newKeyCount * sizeof(PGPKey *), kPGPMemoryMgrFlags_Clear );
if (!newKeys)
return kPGPError_OutOfMemory;
pgpCopyMemory(list->keys, newKeys, i * sizeof(PGPKey *));
pgpCopyMemory(list->keys + i, newKeys + i + 1,
(list->keyCount - i) * sizeof(PGPKey *));
pgpContextMemFree( context, list->keys);
list->keys = newKeys;
list->keyCount = newKeyCount;
newKeys[i] = key;
pgpKeyIterAddKey(list, i);
return kPGPError_NoErr;
}
static PGPError
addKeyToLists(PGPKeyDB *db, PGPKey *key)
{
PGPKeySet * set;
PGPKeyList * list;
PGPError result;
pgpa(pgpaPGPKeyDBValid(db));
for (set = db->firstSetInDB; set; set = set->nextSetInDB)
{
pgpa(pgpaPGPKeySetValid(set));
if (PGPKeySetIsMember( key, set))
for (list = set->firstListInSet; list; list = list->nextListInSet)
if ((result = addKeyToList(list, key)) != kPGPError_NoErr)
return result;
}
return kPGPError_NoErr;
}
static PGPError
removeKeyFromList(PGPKeyList *list, PGPKey *key)
{
long i;
PGPContextRef cdkContext = PGPGetKeyListContext( list );
pgpa(pgpaPGPKeyListValid(list));
for (i = 0; i < list->keyCount; i++)
if (list->keys[i] == key)
break;
if (i < list->keyCount)
{
pgpCopyMemory(list->keys + i + 1, list->keys + i,
(list->keyCount - i - 1) * sizeof(PGPKey *));
list->keyCount--;
/*
* Reducing the size of a block cannot fail, and
* if it did fail we don't care anyway. Therefore,
* we can ignore errors from the following realloc.
*/
pgpContextMemRealloc(cdkContext, (void **)&list->keys,
list->keyCount * sizeof(PGPKey *), 0);
pgpKeyIterRemoveKey(list, i);
}
return kPGPError_NoErr;
}
static PGPError
removeKeyFromSets(PGPKeyDB *db, PGPKey *key)
{
PGPKeySet * set;
PGPKeyList * list;
PGPError result;
pgpa(pgpaPGPKeyDBValid(db));
for (set = db->firstSetInDB; set; set = set->nextSetInDB)
{
pgpa(pgpaPGPKeySetValid(set));
set->removeKey(set, key);
for (list = set->firstListInSet; list; list = list->nextListInSet)
if ((result = removeKeyFromList(list, key)) != kPGPError_NoErr)
return result;
}
return kPGPError_NoErr;
}
PGPError
pgpReSortKeys(PGPKeyDB *db, RingSet *changed)
{
PGPKeySet * set;
PGPKeyList * list;
PGPKey * key;
PGPKey ** movedKeys = NULL;
long numMovedKeys;
long movedKeysAlloc;
long i;
int (*compare)(void const *, void const *);
PGPError result = kPGPError_NoErr;
PGPContextRef context = pgpGetKeyDBContext( db );
pgpa(pgpaPGPKeyDBValid(db));
movedKeysAlloc = 8;
movedKeys = (PGPKey **)pgpContextMemAlloc( context,
movedKeysAlloc * sizeof(PGPKey *), kPGPMemoryMgrFlags_Clear );
if (!movedKeys)
{
result = kPGPError_OutOfMemory;
goto done;
}
for (set = db->firstSetInDB; set; set = set->nextSetInDB)
{
pgpa(pgpaPGPKeySetValid(set));
for (list = set->firstListInSet; list; list = list->nextListInSet)
{
pgpa((
pgpaPGPKeyListValid(list),
pgpaAssert(list->order > 0 && list->order < sNumCompareFuncs)));
if (list->order != kPGPAnyOrdering)
{
compare = compareFunc[list->order];
numMovedKeys = 0;
for (i = 0; i < list->keyCount; i++)
if (ringSetIsMember(changed, list->keys[i]->key))
{
if (numMovedKeys >= movedKeysAlloc)
{
void *vmovedKeys;
movedKeysAlloc *= 2;
vmovedKeys = movedKeys;
result = pgpContextMemRealloc(
context, &vmovedKeys,
movedKeysAlloc * sizeof(PGPKey *),
0 );
movedKeys = (PGPKeyRef *)vmovedKeys;
if ( IsPGPError( result ) )
goto done;
}
key = movedKeys[numMovedKeys++] = list->keys[i];
result = removeKeyFromList(list, key);
if ( IsPGPError( result ) )
goto done;
i--;
}
for (i = 0; i < numMovedKeys; i++)
{
result = addKeyToList(list, movedKeys[i]);
if (result)
goto done;
}
}
}
}
done:
if (movedKeys != NULL)
pgpContextMemFree( context, movedKeys);
return result;
}
/*
* buildKeyPool can be used to either add keys or remove keys, but not both.
* If you are removing keys, pass TRUE for <deleteFlag>, but if so there
* better not be any new keys or else it'll do the wrong thing. Likewise,
* if you pass FALSE for <deleteFlag>, there better not be any keys missing.
*/
PGPError
pgpBuildKeyPool(PGPKeyDB *db, PGPBoolean deleteFlag)
{
RingIterator * iter;
RingObject * obj;
PGPKey * key;
PGPKey ** prevPtr;
PGPError result = kPGPError_NoErr;
iter = ringIterCreate(pgpKeyDBRingSet(db));
if (iter == NULL)
return kPGPError_OutOfMemory;
prevPtr = &db->firstKeyInDB;
while (ringIterNextObject(iter, 1) > 0)
{
obj = ringIterCurrentObject(iter, 1);
pgpAssertAddrValid(obj, VoidAlign); /* XXX use better align check */
key = *prevPtr;
if (deleteFlag && key)
while (key->key != obj)
{
pgpa(pgpaPGPKeyValid(key));
removeKeyFromSets(db, key);
*prevPtr = key->nextKeyInDB;
pgpFreeKey(key);
key = *prevPtr;
pgpAssert(db->numKeys > 0);
db->numKeys--;
}
if ((!key || key->key != obj) && !deleteFlag)
{
key = allocKey(db);
if (key == NULL)
{
result = kPGPError_OutOfMemory;
break;
}
key->refCount = 0;
key->keyDB = db;
key->key = obj;
key->userVal = 0;
key->subKeys.next = &key->subKeys;
key->subKeys.prev = key->subKeys.next;
key->userIDs.next = &key->userIDs;
key->userIDs.prev = key->userIDs.next;
key->nextKeyInDB = *prevPtr;
pgpIncKeyRefCount (key);
*prevPtr = key;
db->numKeys++;
addKeyToLists(db, key);
}
prevPtr = &key->nextKeyInDB;
}
/* Reached end of RingSet. If we're in delete mode, there
may still be trailing PGPKey objects that need to be
freed. */
if (deleteFlag) {
key = *prevPtr;
while (key != NULL) {
pgpa(pgpaPGPKeyValid(key));
removeKeyFromSets(db, key);
*prevPtr = key->nextKeyInDB;
pgpFreeKey(key);
key = *prevPtr;
pgpAssert(db->numKeys > 0);
db->numKeys--;
}
}
*prevPtr = NULL;
ringIterDestroy(iter);
return result;
}
void
pgpIncKeyDBRefCount(PGPKeyDB *db)
{
pgpa(pgpaPGPKeyDBValid(db));
db->refCount++;
}
void
pgpFreeKeyDB(PGPKeyDB *db)
{
pgpa(pgpaPGPKeyDBValid(db));
db->refCount--;
if (db->refCount <= 0)
{
if (db->keysByKeyID != NULL)
{
/*
* Move the refCount up by 2 while we destroy the keyList,
* so when pgpFreeKeyDB is called from PGPFreeKeySet from
* PGPFreeKeyList below, it does nothing but decrement the
* refCount. Unfortunately this is more of a hack than I'd
* like. refCounts don't work all that well with cycles.
*/
db->refCount += 2;
PGPFreeKeyList(db->keysByKeyID);
db->refCount--;
}
(*db->destroy)(db);
pgpKeyDBDestroyInternal (db);
}
}
PGPBoolean
PGPKeySetIsMember(PGPKey *key, PGPKeySet *set)
{
pgpa((
pgpaPGPKeySetValid(set),
pgpaPGPKeyValid(key)));
if ( ! ( pgpKeySetIsValid( set ) && pgpKeyIsValid( key ) ) )
{
return( FALSE );
}
return set->isMember(set, key);
}
PGPError
PGPUnionKeySets(PGPKeySetRef set1, PGPKeySetRef set2, PGPKeySetRef *newSet)
{
PGPError err = kPGPError_NoErr;
PGPValidatePtr( newSet );
*newSet = NULL;
PGPValidateKeySet( set1 );
PGPValidateKeySet( set2 );
if (set1->keyDB != set2->keyDB)
return kPGPError_KeyDBMismatch;
if (set1->makeUnion == set2->makeUnion && IsntNull(set1->makeUnion))
err = set1->makeUnion(set1, set2, newSet);
else
err = pgpGenericUnionOfKeySets(set1, set2, newSet);
return err;
}
static void
defaultRemoveKeyFromKeySet(
PGPKeySetRef set,
PGPKeyRef key)
{
/* Do nothing */
(void)set; /* Avoid warnings */
(void)key;
}
PGPError
pgpNewKeySetInternal(
PGPKeyDBRef db,
PGPKeySetRef * newSet)
{
PGPKeySet * set;
PGPContextRef context = pgpGetKeyDBContext(db);
pgpa(pgpaPGPKeyDBValid(db));
*newSet = NULL; /* In case there's an error */
set = (PGPKeySet *)pgpContextMemAlloc(context,
sizeof(PGPKeySet), kPGPMemoryMgrFlags_Clear);
if (IsNull(set))
return kPGPError_OutOfMemory;
pgpIncKeyDBRefCount(db);
set->priv = NULL;
set->refCount = 1;
set->keyDB = db;
set->firstListInSet = NULL;
set->magic = kPGPKeySetMagic;
set->prevSetInDB = NULL;
set->nextSetInDB = db->firstSetInDB;
if (set->nextSetInDB)
set->nextSetInDB->prevSetInDB = set;
db->firstSetInDB = set;
set->removeKey = defaultRemoveKeyFromKeySet;
*newSet = set;
return kPGPError_NoErr;
}
static PGPBoolean
rootSetIsMember(PGPKeySet *set, PGPKeyRef key)
{
pgpa((
pgpaPGPKeySetValid(set),
pgpaAddrValid(key, VoidAlign))); /* XXX use better align check */
return ringSetIsMember(pgpKeyDBRingSet(set->keyDB), key->key);
}
static PGPError
rootSetMakeUnion(PGPKeySetRef set1, PGPKeySetRef set2, PGPKeySetRef *newSet)
{
(void)set2; /* Avoid warning */
PGPIncKeySetRefCount(set1);
*newSet = set1;
return kPGPError_NoErr;
}
static void
rootSetDestroy(PGPKeySet *set)
{
(void)set; /* Avoid warning */
}
PGPKeySet *
pgpKeyDBRootSet(
PGPKeyDB * db)
{
PGPKeySet * set;
pgpNewKeySetInternal(db, &set);
if (IsntNull(set))
{
set->isMember = rootSetIsMember;
set->makeUnion = rootSetMakeUnion;
set->destroy = rootSetDestroy;
}
return set;
}
RingSet const *
pgpKeyDBRingSet(PGPKeyDB *db)
{
pgpa(pgpaPGPKeyDBValid(db));
return (*db->getRingSet)(db);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -