1/* 2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. 3 * 4 * The contents of this file constitute Original Code as defined in and are 5 * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 * You may not use this file except in compliance with the License. Please obtain 7 * a copy of the License at http://www.apple.com/publicsource and read it before 8 * using this file. 9 * 10 * This Original Code and all software distributed under the License are 11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 15 * specific language governing rights and limitations under the License. 16 */ 17 18 19// 20// MultiDLDb implementation. 21// 22 23#include <security_cdsa_client/multidldb.h> 24#include <security_cdsa_client/securestorage.h> 25 26 27 28namespace Security 29{ 30 31using namespace CssmClient; 32 33namespace CssmClient 34{ 35 36// 37// MultiDLDbDbCursorImpl declaration 38// 39class MultiDLDbDbCursorImpl : public DbCursorImpl 40{ 41public: 42 MultiDLDbDbCursorImpl(const MultiDLDb &parent, const CSSM_QUERY &query, Allocator &allocator); 43 MultiDLDbDbCursorImpl(const MultiDLDb &parent, uint32 capacity, Allocator &allocator); 44 virtual ~MultiDLDbDbCursorImpl(); 45 46 bool next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniqueRecord &uniqueId); 47private: 48 MultiDLDb multiDLDb() { return parent<MultiDLDb>(); } 49 void activate(); 50 void deactivate(); 51 52 MultiDLDbImpl::ListRef mListRef; 53 MultiDLDbImpl::List::const_iterator mNext; 54 MultiDLDbImpl::List::const_iterator mEnd; 55 DbCursor mCursor; 56}; 57 58} // end namespace CssmClient 59 60} // end namespace Security 61 62// 63// MultiDLDbImpl 64// 65MultiDLDbImpl::MultiDLDbImpl(const vector<DLDbIdentifier> &list, bool useSecureStorage, const Cssm &cssm) 66: ObjectImpl(cssm), mListRef(list), mUseSecureStorage(useSecureStorage) 67{ 68} 69 70MultiDLDbImpl::MultiDLDbImpl(const vector<DLDbIdentifier> &list, bool useSecureStorage) 71: ObjectImpl(Cssm::standard()), mListRef(list), mUseSecureStorage(useSecureStorage) 72{ 73} 74 75MultiDLDbImpl::~MultiDLDbImpl() 76{ 77 deactivate(); 78} 79 80Db 81MultiDLDbImpl::database(const DLDbIdentifier &dlDbIdentifier) 82{ 83 StLock<Mutex> _(mLock); 84 DbMap::const_iterator it = mDbMap.find(dlDbIdentifier); 85 if (it != mDbMap.end()) 86 return it->second; 87 88 Module module(dlDbIdentifier.ssuid().guid(), cssm()); 89 DL dl; 90 if (dlDbIdentifier.ssuid().subserviceType() & CSSM_SERVICE_CSP) 91 { 92 if (mUseSecureStorage) 93 dl = SSCSPDL(module); 94 else 95 dl = CSPDL(module); 96 } 97 else 98 dl = DL(module); 99 100 dl->subserviceId(dlDbIdentifier.ssuid().subserviceId()); 101 dl->version(dlDbIdentifier.ssuid().version()); 102 Db db(dl, dlDbIdentifier.dbName()); 103 if (find(mListRef->begin(), mListRef->end(), dlDbIdentifier) != mListRef->end()) 104 mDbMap.insert(DbMap::value_type(dlDbIdentifier, db)); 105 106 return db; 107} 108 109void 110MultiDLDbImpl::list(const vector<DLDbIdentifier> &list) 111{ 112 StLock<Mutex> _(mLock); 113 set<DLDbIdentifier> oldList(mListRef->begin(), mListRef->end()); 114 mListRef = ListRef(list); 115 set<DLDbIdentifier> newList(mListRef->begin(), mListRef->end()); 116 vector<DLDbIdentifier> obsolete; 117 back_insert_iterator<vector<DLDbIdentifier> > ii(obsolete); 118 // Remove all db's from the map that were in oldList but are not in mListRef. 119 set_difference(oldList.begin(), oldList.end(), newList.begin(), newList.end(), ii); 120 for (vector<DLDbIdentifier>::const_iterator it = obsolete.begin(); it != obsolete.end(); ++it) 121 mDbMap.erase(*it); 122} 123 124DbCursorImpl * 125MultiDLDbImpl::newDbCursor(const CSSM_QUERY &query, Allocator &allocator) 126{ 127 return new MultiDLDbDbCursorImpl(MultiDLDb(this), query, allocator); 128} 129 130DbCursorImpl * 131MultiDLDbImpl::newDbCursor(uint32 capacity, Allocator &allocator) 132{ 133 return new MultiDLDbDbCursorImpl(MultiDLDb(this), capacity, allocator); 134} 135 136void 137MultiDLDbImpl::activate() 138{ 139} 140 141void 142MultiDLDbImpl::deactivate() 143{ 144 StLock<Mutex> _(mLock); 145 mDbMap.erase(mDbMap.begin(), mDbMap.end()); 146} 147 148 149// 150// MultiDLDbDbCursorImpl 151// 152MultiDLDbDbCursorImpl::MultiDLDbDbCursorImpl(const MultiDLDb &parent, 153 const CSSM_QUERY &query, Allocator &allocator) 154: DbCursorImpl(parent, query, allocator) 155{ 156} 157 158MultiDLDbDbCursorImpl::MultiDLDbDbCursorImpl(const MultiDLDb &parent, 159 uint32 capacity, Allocator &allocator) 160: DbCursorImpl(parent, capacity, allocator) 161{ 162} 163 164MultiDLDbDbCursorImpl::~MultiDLDbDbCursorImpl() 165{ 166 try 167 { 168 deactivate(); 169 } 170 catch(...) {} 171} 172 173bool 174MultiDLDbDbCursorImpl::next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniqueRecord &uniqueId) 175{ 176 activate(); 177 for (;;) 178 { 179 if (!mCursor) 180 { 181 if (mNext == mEnd) 182 { 183 // This is how it ends. 184 deactivate(); 185 return false; 186 } 187 188 mCursor = DbCursor(multiDLDb()->database(*mNext++), *this); 189 } 190 191 try 192 { 193 if (mCursor->next(attributes, data, uniqueId)) 194 return true; 195 } 196 197 catch(const CommonError &err) 198 { 199 OSStatus status = err.osStatus(); 200 if(status != CSSMERR_DL_DATASTORE_DOESNOT_EXIST) 201 throw; 202 } 203 204 205 206 mCursor = DbCursor(); 207 } 208} 209 210void 211MultiDLDbDbCursorImpl::activate() 212{ 213 StLock<Mutex> _(mActivateMutex); 214 if (!mActive) 215 { 216 mListRef = multiDLDb()->listRef(); 217 mNext = mListRef->begin(); 218 mEnd = mListRef->end(); 219 mActive = true; 220 } 221} 222 223void 224MultiDLDbDbCursorImpl::deactivate() 225{ 226 StLock<Mutex> _(mActivateMutex); 227 if (mActive) 228 { 229 mActive = false; 230 mListRef = MultiDLDbImpl::ListRef(); 231 mNext = mEnd; 232 mCursor = DbCursor(); 233 } 234} 235 236