]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/Database.cpp
Security-54.1.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / Database.cpp
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 #ifdef __MWERKS__
20 #define _CPP_DATABASE
21 #endif
22 #include <Security/Database.h>
23
24 #include <Security/cssmerr.h>
25 #include <Security/DbContext.h>
26 #include <memory>
27
28 DatabaseManager::DatabaseManager ()
29 {
30 }
31
32 DatabaseManager::~DatabaseManager ()
33 {
34 }
35
36 Database *
37 DatabaseManager::get (const DbName &inDbName)
38 {
39 StLock<Mutex> _(mDatabaseMapLock);
40 DatabaseMap::iterator anIterator = mDatabaseMap.find (inDbName);
41 if (anIterator == mDatabaseMap.end())
42 {
43 auto_ptr<Database> aDatabase(make(inDbName));
44 mDatabaseMap.insert(DatabaseMap::value_type(aDatabase->mDbName, aDatabase.get()));
45 return aDatabase.release();
46 }
47
48 return anIterator->second;
49 }
50
51 void
52 DatabaseManager::removeIfUnused(Database &inDatabase)
53 {
54 StLock<Mutex> _(mDatabaseMapLock);
55 if (!inDatabase.hasDbContexts()) {
56 mDatabaseMap.erase(inDatabase.mDbName);
57 delete &inDatabase;
58 }
59 }
60
61 DbContext &
62 DatabaseManager::dbOpen(DatabaseSession &inDatabaseSession,
63 const DbName &inDbName,
64 CSSM_DB_ACCESS_TYPE inAccessRequest,
65 const AccessCredentials *inAccessCred,
66 const void *inOpenParameters)
67 {
68 Database &aDatabase = *get(inDbName);
69 try
70 {
71 return aDatabase._dbOpen(inDatabaseSession, inAccessRequest, inAccessCred, inOpenParameters);
72 }
73 catch (...)
74 {
75 removeIfUnused(aDatabase);
76 throw;
77 }
78 }
79
80 DbContext &
81 DatabaseManager::dbCreate(DatabaseSession &inDatabaseSession,
82 const DbName &inDbName,
83 const CSSM_DBINFO &inDBInfo,
84 CSSM_DB_ACCESS_TYPE inAccessRequest,
85 const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry,
86 const void *inOpenParameters)
87 {
88 Database &aDatabase = *get(inDbName);
89 try
90 {
91 return aDatabase._dbCreate(inDatabaseSession, inDBInfo, inAccessRequest,
92 inCredAndAclEntry, inOpenParameters);
93 }
94 catch (...)
95 {
96 removeIfUnused(aDatabase);
97 throw;
98 }
99 }
100
101 // Delete a DbContext instance created by calling dbOpen or dbCreate.
102 void
103 DatabaseManager::dbClose(DbContext &inDbContext)
104 {
105 Database &aDatabase = inDbContext.mDatabase;
106 aDatabase._dbClose(inDbContext);
107 removeIfUnused(aDatabase);
108 }
109
110 // Delete a database.
111 void
112 DatabaseManager::dbDelete(DatabaseSession &inDatabaseSession,
113 const DbName &inDbName,
114 const AccessCredentials *inAccessCred)
115 {
116 Database &aDatabase = *get(inDbName);
117 try
118 {
119 aDatabase.dbDelete(inDatabaseSession, inAccessCred);
120 }
121 catch (...)
122 {
123 removeIfUnused(aDatabase);
124 throw;
125 }
126
127 removeIfUnused(aDatabase);
128 }
129
130 // List all available databases.
131 CSSM_NAME_LIST_PTR
132 DatabaseManager::getDbNames(DatabaseSession &inDatabaseSession)
133 {
134 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
135 }
136
137 void
138 DatabaseManager::freeNameList(DatabaseSession &inDatabaseSession,
139 CSSM_NAME_LIST &inNameList)
140 {
141 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
142 }
143
144 // Start of Database implementation.
145
146 Database::Database (const DbName &inDbName)
147 : mDbName(inDbName)
148 {
149 }
150
151 Database::~Database ()
152 {
153 }
154
155 bool
156 Database::hasDbContexts()
157 {
158 StLock<Mutex> _(mDbContextSetLock);
159 return !mDbContextSet.empty();
160 }
161
162 DbContext &
163 Database::_dbOpen(DatabaseSession &inDatabaseSession,
164 CSSM_DB_ACCESS_TYPE inAccessRequest,
165 const AccessCredentials *inAccessCred,
166 const void *inOpenParameters)
167 {
168 auto_ptr<DbContext>aDbContext(makeDbContext(inDatabaseSession,
169 inAccessRequest,
170 inAccessCred,
171 inOpenParameters));
172 {
173 StLock<Mutex> _(mDbContextSetLock);
174 mDbContextSet.insert(aDbContext.get());
175 // Release the mDbContextSetLock
176 }
177
178 try
179 {
180 dbOpen(*aDbContext);
181 }
182 catch (...)
183 {
184 StLock<Mutex> _(mDbContextSetLock);
185 mDbContextSet.erase(aDbContext.get());
186 throw;
187 }
188
189 return *aDbContext.release();
190 }
191
192 DbContext &
193 Database::_dbCreate(DatabaseSession &inDatabaseSession,
194 const CSSM_DBINFO &inDBInfo,
195 CSSM_DB_ACCESS_TYPE inAccessRequest,
196 const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry,
197 const void *inOpenParameters)
198 {
199 auto_ptr<DbContext>aDbContext(makeDbContext(inDatabaseSession,
200 inAccessRequest,
201 (inCredAndAclEntry
202 ? AccessCredentials::optional(inCredAndAclEntry->AccessCred)
203 : NULL),
204 inOpenParameters));
205 {
206 StLock<Mutex> _(mDbContextSetLock);
207 mDbContextSet.insert(aDbContext.get());
208 // Release the mDbContextSetLock
209 }
210
211 try
212 {
213 dbCreate(*aDbContext, inDBInfo,
214 inCredAndAclEntry ? &inCredAndAclEntry->InitialAclEntry : NULL);
215 }
216 catch (...)
217 {
218 StLock<Mutex> _(mDbContextSetLock);
219 mDbContextSet.erase(aDbContext.get());
220 throw;
221 }
222
223 return *aDbContext.release();
224 }
225
226 void
227 Database::_dbClose(DbContext &dbContext)
228 {
229 StLock<Mutex> _(mDbContextSetLock);
230 mDbContextSet.erase(&dbContext);
231 if (mDbContextSet.empty())
232 dbClose();
233 }