X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/OSX/libsecurity_cdsa_client/lib/multidldb.cpp diff --git a/OSX/libsecurity_cdsa_client/lib/multidldb.cpp b/OSX/libsecurity_cdsa_client/lib/multidldb.cpp new file mode 100644 index 00000000..596d01c7 --- /dev/null +++ b/OSX/libsecurity_cdsa_client/lib/multidldb.cpp @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS + * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT + * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the + * specific language governing rights and limitations under the License. + */ + + +// +// MultiDLDb implementation. +// + +#include +#include + + + +namespace Security +{ + +using namespace CssmClient; + +namespace CssmClient +{ + +// +// MultiDLDbDbCursorImpl declaration +// +class MultiDLDbDbCursorImpl : public DbCursorImpl +{ +public: + MultiDLDbDbCursorImpl(const MultiDLDb &parent, const CSSM_QUERY &query, Allocator &allocator); + MultiDLDbDbCursorImpl(const MultiDLDb &parent, uint32 capacity, Allocator &allocator); + virtual ~MultiDLDbDbCursorImpl(); + + bool next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniqueRecord &uniqueId); +private: + MultiDLDb multiDLDb() { return parent(); } + void activate(); + void deactivate(); + + MultiDLDbImpl::ListRef mListRef; + MultiDLDbImpl::List::const_iterator mNext; + MultiDLDbImpl::List::const_iterator mEnd; + DbCursor mCursor; +}; + +} // end namespace CssmClient + +} // end namespace Security + +// +// MultiDLDbImpl +// +MultiDLDbImpl::MultiDLDbImpl(const vector &list, bool useSecureStorage, const Cssm &cssm) +: ObjectImpl(cssm), mListRef(list), mUseSecureStorage(useSecureStorage) +{ +} + +MultiDLDbImpl::MultiDLDbImpl(const vector &list, bool useSecureStorage) +: ObjectImpl(Cssm::standard()), mListRef(list), mUseSecureStorage(useSecureStorage) +{ +} + +MultiDLDbImpl::~MultiDLDbImpl() +{ + deactivate(); +} + +Db +MultiDLDbImpl::database(const DLDbIdentifier &dlDbIdentifier) +{ + StLock _(mLock); + DbMap::const_iterator it = mDbMap.find(dlDbIdentifier); + if (it != mDbMap.end()) + return it->second; + + Module module(dlDbIdentifier.ssuid().guid(), cssm()); + DL dl; + if (dlDbIdentifier.ssuid().subserviceType() & CSSM_SERVICE_CSP) + { + if (mUseSecureStorage) + dl = SSCSPDL(module); + else + dl = CSPDL(module); + } + else + dl = DL(module); + + dl->subserviceId(dlDbIdentifier.ssuid().subserviceId()); + dl->version(dlDbIdentifier.ssuid().version()); + Db db(dl, dlDbIdentifier.dbName()); + if (find(mListRef->begin(), mListRef->end(), dlDbIdentifier) != mListRef->end()) + mDbMap.insert(DbMap::value_type(dlDbIdentifier, db)); + + return db; +} + +void +MultiDLDbImpl::list(const vector &list) +{ + StLock _(mLock); + set oldList(mListRef->begin(), mListRef->end()); + mListRef = ListRef(list); + set newList(mListRef->begin(), mListRef->end()); + vector obsolete; + back_insert_iterator > ii(obsolete); + // Remove all db's from the map that were in oldList but are not in mListRef. + set_difference(oldList.begin(), oldList.end(), newList.begin(), newList.end(), ii); + for (vector::const_iterator it = obsolete.begin(); it != obsolete.end(); ++it) + mDbMap.erase(*it); +} + +DbCursorImpl * +MultiDLDbImpl::newDbCursor(const CSSM_QUERY &query, Allocator &allocator) +{ + return new MultiDLDbDbCursorImpl(MultiDLDb(this), query, allocator); +} + +DbCursorImpl * +MultiDLDbImpl::newDbCursor(uint32 capacity, Allocator &allocator) +{ + return new MultiDLDbDbCursorImpl(MultiDLDb(this), capacity, allocator); +} + +void +MultiDLDbImpl::activate() +{ +} + +void +MultiDLDbImpl::deactivate() +{ + StLock _(mLock); + mDbMap.erase(mDbMap.begin(), mDbMap.end()); +} + + +// +// MultiDLDbDbCursorImpl +// +MultiDLDbDbCursorImpl::MultiDLDbDbCursorImpl(const MultiDLDb &parent, + const CSSM_QUERY &query, Allocator &allocator) +: DbCursorImpl(parent, query, allocator) +{ +} + +MultiDLDbDbCursorImpl::MultiDLDbDbCursorImpl(const MultiDLDb &parent, + uint32 capacity, Allocator &allocator) +: DbCursorImpl(parent, capacity, allocator) +{ +} + +MultiDLDbDbCursorImpl::~MultiDLDbDbCursorImpl() +{ + try + { + deactivate(); + } + catch(...) {} +} + +bool +MultiDLDbDbCursorImpl::next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniqueRecord &uniqueId) +{ + activate(); + for (;;) + { + if (!mCursor) + { + if (mNext == mEnd) + { + // This is how it ends. + deactivate(); + return false; + } + + mCursor = DbCursor(multiDLDb()->database(*mNext++), *this); + } + + try + { + if (mCursor->next(attributes, data, uniqueId)) + return true; + } + + catch(const CommonError &err) + { + OSStatus status = err.osStatus(); + if(status != CSSMERR_DL_DATASTORE_DOESNOT_EXIST) + throw; + } + + + + mCursor = DbCursor(); + } +} + +void +MultiDLDbDbCursorImpl::activate() +{ + StLock _(mActivateMutex); + if (!mActive) + { + mListRef = multiDLDb()->listRef(); + mNext = mListRef->begin(); + mEnd = mListRef->end(); + mActive = true; + } +} + +void +MultiDLDbDbCursorImpl::deactivate() +{ + StLock _(mActivateMutex); + if (mActive) + { + mActive = false; + mListRef = MultiDLDbImpl::ListRef(); + mNext = mEnd; + mCursor = DbCursor(); + } +} +