📄 pgpfiledb.c
字号:
if (rdb->rsfrozen) {
ringSetDestroy (rdb->rsfrozen);
rdb->rsfrozen = 0;
}
rdb->rsimmut = 0;
ringSetDestroy (rdb->rsmut);
rdb->rsmut = 0;
ringFileClose (rdb->rfile);
rdb->rfile = 0;
pgpFileClose (rdb->pfile);
rdb->pfile = 0;
if (rdb->bfreebuf && rdb->membuf){
pgpMemFree (rdb->membuf);
}
return PGPERR_OK;
}
/******************** Virtual Functions ************************/
static Boolean
rdbIsMutable (PGPKeyDB *kdb) {
RingDB *rdb = (RingDB *)kdb->private;
return rdb->bwriteable;
}
static Boolean
rdbObjIsMutable (PGPKeyDB *kdb, RingObject *testObj)
{
RingDB *rdb = (RingDB *)kdb->private;
return rdb->bwriteable && ringSetIsMember (rdb->rsmut, testObj);
}
static Boolean
rdbIsDirty (PGPKeyDB *kdb) {
RingDB *rdb = (RingDB *)kdb->private;
return rdb->bdirty;
}
/* Mark as dirty */
static void
rdbDirty (RingDB *rdb)
{
rdb->bdirty = TRUE;
if (rdb->rsfrozen) {
ringSetDestroy (rdb->rsfrozen);
rdb->rsfrozen = 0;
}
}
static RingSet *
rdbGetRingSet (PGPKeyDB *kdb) {
RingDB *rdb = (RingDB *)kdb->private;
RingSet *rset;
if (!(rset = rdb->rsfrozen)) {
rset = ringSetCreate (ringSetPool (rdb->rsmut));
ringSetAddSet (rset, rdb->rsmut);
ringSetFreeze (rset);
rdb->rsfrozen = rset;
}
return rset;
}
static PGPError
rdbAdd (PGPKeyDB *kdb, RingSet *toAdd) {
RingDB *rdb = (RingDB *)kdb->private;
RingIterator *riAdd; /* Iterator over toAdd set */
RingObject *robj; /* Object we are adding */
int level; /* Level of iterator in hierarchy */
int type; /* Type of robj */
int added; /* Number of objects added */
int skipped; /* Number of objects skipped */
int skipparts; /* True if skipping, obj not for us */
if (!rdb->bwriteable)
return PGPERR_KEYDB_KEYDBREADONLY;
riAdd = ringIterCreate (toAdd);
if (!riAdd) {
return PGPERR_NOMEM;
}
added = 0;
skipped = 0;
skipparts = 0;
while ((level = ringIterNextObjectAnywhere(riAdd)) > 0) {
robj = ringIterCurrentObject (riAdd, level);
type = ringObjectType (robj);
if (type==RINGTYPE_KEY) {
/*
* If key lacks secret object, put it only on the public
* ring, and if key comes only from a source where it is a
* secret key, put it only on the secret ring
*/
if (rdb->bprivate) {
skipparts = !ringKeyIsSec (toAdd, robj);
} else {
skipparts = ringKeyIsSecOnly (toAdd, robj);
}
}
/* Signatures only go to public keyrings, secrets to private */
if (skipparts ||
((type==RINGTYPE_SIG)&&rdb->bprivate) ||
((type==RINGTYPE_SEC)&&!rdb->bprivate)) {
skipped += 1;
} else {
ringSetAddObject (rdb->rsmut, robj);
added += 1;
}
}
ringIterDestroy (riAdd);
rdbDirty (rdb);
return PGPERR_OK;
}
static PGPError
rdbRemove (PGPKeyDB *kdb, RingObject *toRemove)
{
RingDB *rdb = (RingDB *)kdb->private;
if (!rdb->bwriteable)
return PGPERR_KEYDB_KEYDBREADONLY;
if (ringSetIsMember (rdb->rsmut, toRemove))
rdbDirty (rdb);
return ringSetRemObject (rdb->rsmut, toRemove);
}
/*
* Note that unions don't pass this call down, they take care of it
* themselves
*/
static PGPError
rdbChanged (PGPKeyDB *kdb, RingSet *changedkeys)
{
RingDB *rdb = (RingDB *)kdb->private;
if (!rdb->bwriteable)
return PGPERR_KEYDB_KEYDBREADONLY;
rdbDirty (rdb);
return pgpReSortKeys (kdb, changedkeys);
}
static PGPError
rdbCommit (PGPKeyDB *kdb) {
RingDB *rdb = (RingDB *)kdb->private;
RingPool *ringpool = ringSetPool (rdb->rsmut);
PGPError error;
if (!rdb->bwriteable)
return PGPERR_OK;
/* Don't check for trust changed if untrusted file */
if (!rdb->bdirty && (!rdb->btrusted ||
(rdb->btrusted && !ringFileIsTrustChanged(rdb->rfile))))
return PGPERR_OK;
/* Must use frozen set for writing */
ringSetFreeze (rdb->rsmut);
if (rdb->rsfrozen) {
ringSetDestroy (rdb->rsfrozen);
rdb->rsfrozen = 0;
}
error = do_write (rdb);
if (error) {
/*
* Sometimes on error we have fixed rdb->rsmut, but possibly it may
* still be frozen as above. To be safe we will always make a copy
* here so it is writeable in the future.
*/
RingSet *rset = ringSetCreate (ringpool);
pgpAssert (rset);
pgpAssert (rdb->rsmut);
ringSetAddSet (rset, rdb->rsmut);
ringSetDestroy (rdb->rsmut);
rdb->rsmut = rset;
return error;
}
rdb->rsimmut = ringFileSet (rdb->rfile);
rdb->rsmut = ringSetCreate (ringpool);
ringSetAddSet (rdb->rsmut, rdb->rsimmut);
rdb->bdirty = 0;
return PGPERR_OK;
}
static PGPError
rdbRevert (PGPKeyDB *kdb) {
RingDB *rdb = (RingDB *)kdb->private;
if (!rdb->bdirty)
return PGPERR_OK;
rdb->bdirty = 0;
if (rdb->rsmut) {
ringSetDestroy (rdb->rsmut);
rdb->rsmut = ringSetCreate (ringSetPool(rdb->rsimmut));
if (!rdb->rsmut) {
return PGPERR_NOMEM;
}
ringSetAddSet (rdb->rsmut, rdb->rsimmut);
}
if (rdb->rsfrozen) {
ringSetDestroy (rdb->rsfrozen);
rdb->rsfrozen = 0;
}
return PGPERR_OK;
}
static PGPError
rdbReload (PGPKeyDB *kdb) {
RingDB *rdb = (RingDB *)kdb->private;
PGPFileRef *fileRef;
PGPError err;
if (rdb->membuf)
return PGPERR_OK;
if ((fileRef = pgpCopyFileRef(rdb->fileRef)) == NULL)
return PGPERR_NOMEM;
err = do_close (rdb);
if (err) {
pgpFreeFileRef(fileRef);
return err;
}
err = do_open (fileRef, rdb->btrusted, rdb->bprivate,
rdb->bwriteable, ringSetPool (rdb->rsimmut), rdb);
rdb->bdirty = 0;
if (rdb->rsfrozen) {
ringSetDestroy (rdb->rsfrozen);
rdb->rsfrozen = 0;
}
pgpFreeFileRef(fileRef);
return err;
}
static void
rdbDestroy (PGPKeyDB *kdb)
{
RingDB *rdb = (RingDB *)kdb->private;
do_close (rdb);
pgpFreeFileRef (rdb->fileRef);
pgpMemFree (rdb);
}
/**************************** Constructor **************************/
PGPKeyDB *
pgpCreateFileKeyDB (PGPFileRef const *fileRef, int trusted, int private,
int writeable, RingPool *ringpool, PGPError *error)
{
PGPKeyDB *kdb;
RingDB *rdb;
*error = 0;
kdb = pgpKeyDBCreateInternal ();
if (!kdb) {
*error = PGPERR_NOMEM;
return NULL;
}
rdb = (RingDB *) pgpMemAlloc (sizeof (RingDB));
if (!rdb) {
*error = PGPERR_NOMEM;
pgpKeyDBDestroyInternal (kdb);
return NULL;
}
memset (rdb, 0, sizeof (*rdb));
*error = do_open (fileRef, trusted, private, writeable, ringpool, rdb);
if (*error) {
pgpMemFree (rdb);
pgpKeyDBDestroyInternal (kdb);
return NULL;
}
kdb->private = rdb;
kdb->magic = PGPKDBFILEMAGIC;
kdb->isMutable = rdbIsMutable;
kdb->objIsMutable = rdbObjIsMutable;
kdb->isDirty = rdbIsDirty;
kdb->getRingSet = rdbGetRingSet;
kdb->add = rdbAdd;
kdb->remove = rdbRemove;
kdb->changed = rdbChanged;
kdb->commit = rdbCommit;
kdb->revert = rdbRevert;
kdb->reload = rdbReload;
kdb->destroy = rdbDestroy;
pgpKeyDBInitInternal(kdb);
return kdb;
}
/*
* Create a File type KeyDB from a memory buffer. This will be an
* immutable KeyDB since we can't save our changes anywhere.
*/
PGPKeyDB *
pgpCreateMemFileKeyDB (byte *buf, size_t length, RingPool *ringpool,
PGPError *error)
{
PGPKeyDB *kdb;
RingDB *rdb;
*error = 0;
kdb = pgpKeyDBCreateInternal ();
if (!kdb) {
*error = PGPERR_NOMEM;
return NULL;
}
rdb = (RingDB *) pgpMemAlloc (sizeof (RingDB));
if (!rdb) {
*error = PGPERR_NOMEM;
pgpKeyDBDestroyInternal (kdb);
return NULL;
}
memset (rdb, 0, sizeof (*rdb));
rdb->rsmut = ringSetCreate (ringpool);
if (!rdb->rsmut) {
pgpMemFree (rdb);
pgpKeyDBDestroyInternal (kdb);
*error = PGPERR_NOMEM;
return NULL;
}
rdb->pfile = pgpFileMemReadOpen (buf, length);
if (!rdb->pfile) {
ringSetDestroy (rdb->rsmut);
pgpMemFree (rdb);
pgpKeyDBDestroyInternal (kdb);
*error = PGPERR_NOMEM;
return NULL;
}
rdb->rfile = ringFileOpen (ringpool, rdb->pfile, 0, error);
if (!rdb->rfile) {
pgpFileClose (rdb->pfile);
ringSetDestroy (rdb->rsmut);
pgpMemFree (rdb);
pgpKeyDBDestroyInternal (kdb);
return NULL;
}
rdb->rsimmut = ringFileSet (rdb->rfile);
ringSetAddSet (rdb->rsmut, rdb->rsimmut);
rdb->membuf = buf;
rdb->bfreebuf = 1;
rdb->fileRef = pgpNewFileRefFromFullPath("");
kdb->private = rdb;
kdb->magic = PGPKDBFILEMAGIC;
kdb->isMutable = rdbIsMutable;
kdb->objIsMutable = rdbObjIsMutable;
kdb->isDirty = rdbIsDirty;
kdb->getRingSet = rdbGetRingSet;
kdb->add = rdbAdd;
kdb->remove = rdbRemove;
kdb->changed = rdbChanged;
kdb->commit = rdbCommit;
kdb->revert = rdbRevert;
kdb->reload = rdbReload;
kdb->destroy = rdbDestroy;
pgpKeyDBInitInternal(kdb);
return kdb;
}
/*
* Local Variables:
* tab-width: 4
* End:
* vi: ts=4 sw=4
* vim: si
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -