]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/AppleDatabase.h
Security-54.1.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / AppleDatabase.h
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 // AppleDatabase.h - Description t.b.d.
21 //
22 #ifndef _H_APPLEDATABASE
23 #define _H_APPLEDATABASE
24
25 #include "MetaRecord.h"
26 #include "SelectionPredicate.h"
27 #include "DbIndex.h"
28
29 #include <Security/AtomicFile.h>
30 #include <Security/Database.h>
31 #include <Security/DbContext.h>
32 #include <Security/handleobject.h>
33 #include <Security/refcount.h>
34 #include <memory>
35 #include <vector>
36
37 namespace Security
38 {
39
40 // Abstract database Cursor class.
41 class Cursor;
42 class DbVersion;
43 class CssmAutoQuery;
44
45 struct AppleDatabaseTableName
46 {
47 uint32 mTableId;
48 const char *mTableName;
49
50 // indices of meta-table entries in an array of table names
51
52 enum {
53 kSchemaInfo = 0,
54 kSchemaAttributes,
55 kSchemaIndexes,
56 kSchemaParsingModule,
57 kNumRequiredTableNames
58 };
59 };
60
61 //
62 // This is what the CDSA standard refers to as a Relation. We use
63 // the more conventional term Table.
64 //
65 class Table
66 {
67 NOCOPY(Table)
68 public:
69 // Type used to refer to a table.
70 typedef CSSM_DB_RECORDTYPE Id;
71
72 Table(const ReadSection &inTableSection);
73 ~Table();
74 #if 0
75 Table(const CSSM_DB_RECORD_ATTRIBUTE_INFO &inInfo) :
76 mMetaRecord (inInfo) {}
77 Table(Id inTableId, const string &inTableName,
78 uint32 inNumberOfAttributes,
79 const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *inAttributeInfo,
80 uint32 inNumberOfIndexes,
81 const CSSM_DB_SCHEMA_INDEX_INFO *inIndexInfo) :
82 mMetaRecord(inTableId, inTableName,
83 inNumberOfAttributes, inAttributeInfo)
84 { /* XXX Use inIndexInfo */ }
85 #endif
86
87 // Return a newly created cursor satisfying inQuery on the receiving table
88 // The returned Cursor may or may not use indexes depending on their availability.
89 Cursor *createCursor(const CSSM_QUERY *inQuery, const DbVersion &inDbVersion) const;
90
91 const ReadSection getRecordSection(uint32 inRecordNumber) const;
92
93 const RecordId getRecord(const RecordId &inRecordId,
94 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes,
95 CssmData *inoutData,
96 CssmAllocator &inAllocator) const;
97
98 // Return the number of recordNumbers in use by this table including empty slots.
99 uint32 recordNumberCount() const { return mRecordNumbersCount; }
100 uint32 freeListHead() const { return mFreeListHead; }
101
102 // Return the record number corresponding to aFreeListHead and update
103 // aFreeListHead to point to the next availble recordNumber slot.
104 uint32 popFreeList(uint32 &aFreeListHead) const;
105
106 MetaRecord &getMetaRecord() { return mMetaRecord; }
107 const MetaRecord &getMetaRecord() const { return mMetaRecord; }
108
109 uint32 getRecordsCount() const { return mRecordsCount; }
110 const ReadSection getRecordsSection() const;
111
112 const ReadSection &getTableSection() const { return mTableSection; }
113
114 bool matchesTableId(Id inTableId) const;
115
116 void readIndexSection();
117
118 enum
119 {
120 OffsetSize = AtomSize * 0,
121 OffsetId = AtomSize * 1,
122 OffsetRecordsCount = AtomSize * 2,
123 OffsetRecords = AtomSize * 3,
124 OffsetIndexesOffset = AtomSize * 4,
125 OffsetFreeListHead = AtomSize * 5,
126 OffsetRecordNumbersCount = AtomSize * 6,
127 OffsetRecordNumbers = AtomSize * 7
128 };
129 protected:
130 friend class ModifiedTable;
131
132 MetaRecord mMetaRecord;
133 const ReadSection mTableSection;
134
135 uint32 mRecordsCount;
136 uint32 mFreeListHead;
137 // Number of record numbers (including freelist slots) in this table.
138 uint32 mRecordNumbersCount;
139
140 // all the table's indexes, mapped by index id
141 typedef map<uint32, DbConstIndex *> ConstIndexMap;
142 ConstIndexMap mIndexMap;
143 };
144
145 class ModifiedTable
146 {
147 NOCOPY(ModifiedTable)
148 public:
149 ModifiedTable(const Table *inTable);
150 ModifiedTable(MetaRecord *inMetaRecord); // Take over ownership of inMetaRecord
151 ~ModifiedTable();
152
153 // Mark the record with inRecordId as deleted.
154 void deleteRecord(const RecordId &inRecordId);
155 const RecordId insertRecord(AtomicFile::VersionId inVersionId,
156 const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes,
157 const CssmData *inData);
158 const RecordId updateRecord(const RecordId &inRecordId,
159 const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes,
160 const CssmData *inData,
161 CSSM_DB_MODIFY_MODE inModifyMode);
162
163 // Return the MetaRecord this table should use for writes.
164 const MetaRecord &getMetaRecord() const;
165
166 // find, and create if needed, an index with the given id
167 DbMutableIndex &findIndex(uint32 indexId, const MetaRecord &metaRecord, bool isUniqueIndex);
168
169 // Write this table to inOutputFile at inSectionOffset and return the new offset.
170 uint32 writeTable(AtomicFile &inOutputFile, uint32 inSectionOffset);
171
172 private:
173 // Return the next available record number for this table.
174 uint32 nextRecordNumber();
175
176 // Return the number of recordNumbers in use by this table including empty slots.
177 uint32 recordNumberCount() const;
178
179 void modifyTable();
180 void createMutableIndexes();
181 uint32 writeIndexSection(WriteSection &tableSection, uint32 offset);
182
183 // Optional, this is merly a reference, we do not own this object.
184 const Table *mTable;
185
186 // Optional, New MetaRecord. This is only present if it is different from the
187 // MetaRecord of mTable or mTable is nil.
188 const MetaRecord *mNewMetaRecord;
189
190 // Set of Records that have been deleted or modified.
191 typedef set<uint32> DeletedSet;
192 DeletedSet mDeletedSet;
193
194 // Set of Records that have been inserted or modified.
195 typedef map<uint32, WriteSection *> InsertedMap;
196 InsertedMap mInsertedMap;
197
198 // Next lowest available RecordNumber
199 uint32 mRecordNumberCount;
200 // Head of the free list (if there is one) or 0 if either we have no
201 // mTable of the free list has been exhausted.
202 uint32 mFreeListHead;
203
204 // has this table actually been modified?
205 bool mIsModified;
206
207 typedef map<uint32, DbMutableIndex *> MutableIndexMap;
208 MutableIndexMap mIndexMap;
209 };
210
211 //
212 // Read only snapshot of a database.
213 //
214 class Metadata
215 {
216 NOCOPY(Metadata)
217 protected:
218 Metadata() {}
219 enum
220 {
221 HeaderOffset = 0, // Absolute offset of header.
222 OffsetMagic = AtomSize * 0,
223 OffsetVersion = AtomSize * 1,
224 OffsetAuthOffset = AtomSize * 2,
225 OffsetSchemaOffset = AtomSize * 3,
226 HeaderSize = AtomSize * 4,
227
228 HeaderMagic = FOUR_CHAR_CODE('kych'),
229 HeaderVersion = 0x00010000
230 };
231
232 enum
233 {
234 OffsetSchemaSize = AtomSize * 0,
235 OffsetTablesCount = AtomSize * 1,
236 OffsetTables = AtomSize * 2
237 };
238 };
239
240 //
241 // Read only representation of a database
242 //
243 class DbVersion : public Metadata, public RefCount
244 {
245 NOCOPY(DbVersion)
246 public:
247 DbVersion(AtomicFile &inDatabaseFile, const class AppleDatabase &db);
248 ~DbVersion();
249
250 // Return true if the file on which this DbVersion is based
251 // has been modified.
252 bool isDirty() const;
253
254 AtomicFile::VersionId getVersionId() const { return mVersionId; }
255 const RecordId getRecord(Table::Id inTableId, const RecordId &inRecordId,
256 CSSM_DB_RECORD_ATTRIBUTE_DATA *inoutAttributes,
257 CssmData *inoutData, CssmAllocator &inAllocator) const;
258 Cursor *createCursor(const CSSM_QUERY *inQuery) const;
259 protected:
260 const Table &findTable(Table::Id inTableId) const;
261 Table &findTable(Table::Id inTableId);
262
263 private:
264 void open(); // Part of constructor contract.
265
266 ReadSection mDatabase;
267 AtomicFile *mDatabaseFile;
268 AtomicFile::VersionId mVersionId;
269
270 friend class DbModifier; // XXX Fixme
271 typedef map<Table::Id, Table *> TableMap;
272 TableMap mTableMap;
273 const class AppleDatabase &mDb;
274
275 public:
276 typedef Table value_type;
277 typedef const Table &const_reference;
278 typedef const Table *const_pointer;
279
280 // A const forward iterator.
281 class const_iterator
282 {
283 public:
284 const_iterator(const TableMap::const_iterator &it) : mIterator(it) {}
285
286 // Use default copy consturctor and assignment operator.
287 //const_iterator(const const_iterator &it) : mIterator(it.mIterator) {}
288 //const_iterator &operator=(const const_iterator &it) { mIterator = it.mIterator; return *this; }
289 const_reference operator*() const { return *mIterator->second; }
290 const_iterator &operator++() { mIterator.operator++(); return *this; }
291 const_iterator operator++(int i) { return const_iterator(mIterator.operator++(i)); }
292 bool operator!=(const const_iterator &other) const { return mIterator != other.mIterator; }
293 bool operator==(const const_iterator &other) const { return mIterator == other.mIterator; }
294
295 const_pointer operator->() const { return mIterator->second; } // Not really needed.
296
297 private:
298 TableMap::const_iterator mIterator;
299 };
300
301 const_iterator begin() const { return const_iterator(mTableMap.begin()); }
302 const_iterator end() const { return const_iterator(mTableMap.end()); }
303 };
304
305 //
306 // Cursor
307 //
308 class Cursor : public HandleObject
309 {
310 public:
311 virtual ~Cursor();
312 virtual bool next(Table::Id &outTableId,
313 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR outAttributes,
314 CssmData *outData,
315 CssmAllocator &inAllocator,
316 RecordId &recordId) = 0;
317 };
318
319 //
320 // LinearCursor
321 //
322 class LinearCursor : public Cursor
323 {
324 NOCOPY(LinearCursor)
325 public:
326 LinearCursor(const CSSM_QUERY *inQuery, const DbVersion &inDbVersion,
327 const Table &inTable);
328 virtual ~LinearCursor();
329 virtual bool next(Table::Id &outTableId,
330 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR outAttributes,
331 CssmData *outData,
332 CssmAllocator &inAllocator,
333 RecordId &recordId);
334
335 private:
336 const RefPointer<const DbVersion> mDbVersion;
337 uint32 mRecordsCount;
338 uint32 mRecord;
339 const ReadSection mRecordsSection;
340 uint32 mReadOffset;
341 const MetaRecord &mMetaRecord;
342
343 CSSM_DB_CONJUNCTIVE mConjunctive;
344 CSSM_QUERY_FLAGS mQueryFlags; // If CSSM_QUERY_RETURN_DATA is set return the raw key bits;
345 typedef vector<SelectionPredicate *> PredicateVector;
346
347 PredicateVector mPredicates;
348 };
349
350 //
351 // A cursor that uses an index.
352 //
353
354 class IndexCursor : public Cursor
355 {
356 NOCOPY(IndexCursor)
357 public:
358 IndexCursor(DbQueryKey *queryKey, const DbVersion &inDbVersion,
359 const Table &table, const DbConstIndex *index);
360 virtual ~IndexCursor();
361
362 virtual bool next(Table::Id &outTableId,
363 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR outAttributes,
364 CssmData *outData,
365 CssmAllocator &inAllocator,
366 RecordId &recordId);
367
368 private:
369 auto_ptr<DbQueryKey> mQueryKey;
370 const DbVersion &mDbVersion;
371 const Table &mTable;
372 const DbConstIndex *mIndex;
373
374 DbIndexIterator mBegin, mEnd;
375 };
376
377 //
378 // MultiCursor
379 //
380 class MultiCursor : public Cursor
381 {
382 NOCOPY(MultiCursor)
383 public:
384 MultiCursor(const CSSM_QUERY *inQuery, const DbVersion &inDbVersion);
385 virtual ~MultiCursor();
386 virtual bool next(Table::Id &outTableId,
387 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR outAttributes,
388 CssmData *outData,
389 CssmAllocator &inAllocator,
390 RecordId &recordId);
391 private:
392 const RefPointer<const DbVersion> mDbVersion;
393 auto_ptr<CssmAutoQuery> mQuery;
394
395 DbVersion::const_iterator mTableIterator;
396 auto_ptr<Cursor> mCursor;
397 };
398
399 //
400 // A DbModifier contains all pending changes to be made to a DB.
401 // It also contains a DbVersion representing the state of the Database before any such changes
402 // No read-style operations are supported by DbModifier. If a DbModifier exists for a
403 // particular Database and a client wishes to perform a query commit() must be called and
404 // the client should perform the new query on the current database version after the commit.
405 // Otherwise a client will not see changes made since the DbModifier was instanciated.
406 //
407 class DbModifier : public Metadata
408 {
409 NOCOPY(DbModifier)
410 public:
411 DbModifier(AtomicFile &inAtomicFile, const class AppleDatabase &db);
412 ~DbModifier();
413
414 // Whole database affecting members.
415 void createDatabase(const CSSM_DBINFO &inDbInfo,
416 const CSSM_ACL_ENTRY_INPUT *inInitialAclEntry);
417 void openDatabase(); // This is optional right now.
418 void closeDatabase();
419 void deleteDatabase();
420
421 void commit();
422 void rollback();
423
424 // Record changing members
425 void deleteRecord(Table::Id inTableId, const RecordId &inRecordId);
426 const RecordId insertRecord(Table::Id inTableId,
427 const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes,
428 const CssmData *inData);
429 const RecordId updateRecord(Table::Id inTableId, const RecordId &inRecordId,
430 const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes,
431 const CssmData *inData,
432 CSSM_DB_MODIFY_MODE inModifyMode);
433
434 // Schema changing members
435 void insertTable(Table::Id inTableId, const string &inTableName,
436 uint32 inNumberOfAttributes,
437 const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *inAttributeInfo,
438 uint32 inNumberOfIndexes,
439 const CSSM_DB_SCHEMA_INDEX_INFO *inIndexInfo);
440 void deleteTable(Table::Id inTableId);
441
442 // Record reading members
443 const RecordId getRecord(Table::Id inTableId, const RecordId &inRecordId,
444 CSSM_DB_RECORD_ATTRIBUTE_DATA *inoutAttributes,
445 CssmData *inoutData, CssmAllocator &inAllocator);
446 Cursor *createCursor(const CSSM_QUERY *inQuery);
447 protected:
448 void modifyDatabase();
449 const RefPointer<const DbVersion> getDbVersion();
450
451 ModifiedTable *createTable(MetaRecord *inMetaRecord); // Takes over ownership of inMetaRecord
452
453 void insertTableSchema(const CssmDbRecordAttributeInfo &inInfo,
454 const CSSM_DB_RECORD_INDEX_INFO *inIndexInfo = NULL);
455
456 void insertTable(const CssmDbRecordAttributeInfo &inInfo,
457 const CSSM_DB_RECORD_INDEX_INFO * inIndexInfo = NULL,
458 const CSSM_DB_PARSING_MODULE_INFO * inParsingModule = NULL);
459
460 ModifiedTable &findTable(Table::Id inTableId);
461
462 uint32 writeAuthSection(uint32 inSectionOffset);
463 uint32 writeSchemaSection(uint32 inSectionOffset);
464
465 private:
466
467 // Current DbVersion of this database before any changes we are going to make.
468 RefPointer<const DbVersion> mDbVersion;
469 Mutex mDbVersionLock;
470
471 AtomicFile &mAtomicFile;
472 AtomicFile::VersionId mVersionId;
473 AtomicFile::FileRef mFileRef;
474 bool mWriting;
475
476 typedef map<Table::Id, ModifiedTable *> ModifiedTableMap;
477 ModifiedTableMap mModifiedTableMap;
478
479 const class AppleDatabase &mDb;
480 };
481
482 //
483 // AppleDatabaseManager
484 //
485 class AppleDatabaseManager : public DatabaseManager
486 {
487 public:
488 AppleDatabaseManager(const AppleDatabaseTableName *tableNames);
489 Database *make(const DbName &inDbName);
490
491 protected:
492 const AppleDatabaseTableName *mTableNames;
493 };
494
495 //
496 // AppleDbContext
497 //
498 class AppleDbContext : public DbContext
499 {
500 public:
501 AppleDbContext(Database &inDatabase,
502 DatabaseSession &inDatabaseSession,
503 CSSM_DB_ACCESS_TYPE inAccessRequest,
504 const AccessCredentials *inAccessCred,
505 const void *inOpenParameters);
506 virtual ~AppleDbContext();
507 bool autoCommit() const { return mAutoCommit; }
508 void autoCommit(bool on) { mAutoCommit = on; }
509
510 private:
511 bool mAutoCommit;
512 };
513
514 //
515 // AppleDatabase
516 //
517 class AppleDatabase : public Database
518 {
519 public:
520 AppleDatabase(const DbName &inDbName, const AppleDatabaseTableName *tableNames);
521 virtual ~AppleDatabase();
522
523 virtual void
524 dbCreate(DbContext &inDbContext, const CSSM_DBINFO &inDBInfo,
525 const CSSM_ACL_ENTRY_INPUT *inInitialAclEntry);
526
527 virtual void
528 dbOpen(DbContext &inDbContext);
529
530 virtual void
531 dbClose();
532
533 virtual void
534 dbDelete(DatabaseSession &inDatabaseSession,
535 const AccessCredentials *inAccessCred);
536
537 virtual void
538 createRelation(DbContext &inDbContext,
539 CSSM_DB_RECORDTYPE inRelationID,
540 const char *inRelationName,
541 uint32 inNumberOfAttributes,
542 const CSSM_DB_SCHEMA_ATTRIBUTE_INFO &inAttributeInfo,
543 uint32 inNumberOfIndexes,
544 const CSSM_DB_SCHEMA_INDEX_INFO &inIndexInfo);
545
546 virtual void
547 destroyRelation(DbContext &inDbContext,
548 CSSM_DB_RECORDTYPE inRelationID);
549
550 virtual void
551 authenticate(DbContext &inDbContext,
552 CSSM_DB_ACCESS_TYPE inAccessRequest,
553 const AccessCredentials &inAccessCred);
554
555 virtual void
556 getDbAcl(DbContext &inDbContext,
557 const CSSM_STRING *inSelectionTag,
558 uint32 &outNumberOfAclInfos,
559 CSSM_ACL_ENTRY_INFO_PTR &outAclInfos);
560
561 virtual void
562 changeDbAcl(DbContext &inDbContext,
563 const AccessCredentials &inAccessCred,
564 const CSSM_ACL_EDIT &inAclEdit);
565
566 virtual void
567 getDbOwner(DbContext &inDbContext, CSSM_ACL_OWNER_PROTOTYPE &outOwner);
568
569 virtual void
570 changeDbOwner(DbContext &inDbContext,
571 const AccessCredentials &inAccessCred,
572 const CSSM_ACL_OWNER_PROTOTYPE &inNewOwner);
573
574 virtual char *
575 getDbNameFromHandle(const DbContext &inDbContext) const;
576
577 virtual CSSM_DB_UNIQUE_RECORD_PTR
578 dataInsert(DbContext &inDbContext,
579 CSSM_DB_RECORDTYPE RecordType,
580 const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes,
581 const CssmData *inData);
582
583 virtual void
584 dataDelete(DbContext &inDbContext,
585 const CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier);
586
587 virtual void
588 dataModify(DbContext &inDbContext,
589 CSSM_DB_RECORDTYPE inRecordType,
590 CSSM_DB_UNIQUE_RECORD &inoutUniqueRecordIdentifier,
591 const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributesToBeModified,
592 const CssmData *inDataToBeModified,
593 CSSM_DB_MODIFY_MODE inModifyMode);
594
595 virtual CSSM_HANDLE
596 dataGetFirst(DbContext &inDbContext,
597 const DLQuery *inQuery,
598 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes,
599 CssmData *inoutData,
600 CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord);
601
602 virtual bool
603 dataGetNext(DbContext &inDbContext,
604 CSSM_HANDLE inResultsHandle,
605 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes,
606 CssmData *inoutData,
607 CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord);
608
609 virtual void
610 dataAbortQuery(DbContext &inDbContext,
611 CSSM_HANDLE inResultsHandle);
612
613 virtual void
614 dataGetFromUniqueRecordId(DbContext &inDbContext,
615 const CSSM_DB_UNIQUE_RECORD &inUniqueRecord,
616 CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes,
617 CssmData *inoutData);
618
619 virtual void
620 freeUniqueRecord(DbContext &inDbContext,
621 CSSM_DB_UNIQUE_RECORD &inUniqueRecord);
622
623 virtual void passThrough(DbContext &dbContext,
624 uint32 passThroughId,
625 const void *inputParams,
626 void **outputParams);
627
628 // Subclasses must implement this method.
629 virtual DbContext *makeDbContext(DatabaseSession &inDatabaseSession,
630 CSSM_DB_ACCESS_TYPE inAccessRequest,
631 const AccessCredentials *inAccessCred,
632 const void *inOpenParameters);
633
634 const CssmDbRecordAttributeInfo schemaRelations;
635 const CssmDbRecordAttributeInfo schemaAttributes;
636 const CssmDbRecordAttributeInfo schemaIndexes;
637 const CssmDbRecordAttributeInfo schemaParsingModule;
638
639 const char *recordName(CSSM_DB_RECORDTYPE inRecordType) const;
640
641 private:
642 static void
643 AppleDatabase::updateUniqueRecord(DbContext &inDbContext,
644 CSSM_DB_RECORDTYPE inTableId,
645 const RecordId &inRecordId,
646 CSSM_DB_UNIQUE_RECORD &inoutUniqueRecord);
647
648 CSSM_DB_UNIQUE_RECORD_PTR
649 createUniqueRecord(DbContext &inDbContext, CSSM_DB_RECORDTYPE inTableId,
650 const RecordId &inRecordId);
651 const RecordId parseUniqueRecord(const CSSM_DB_UNIQUE_RECORD &inUniqueRecord,
652 CSSM_DB_RECORDTYPE &outTableId);
653
654 Mutex mWriteLock;
655 AtomicFile mAtomicFile;
656 DbModifier mDbModifier;
657 const AppleDatabaseTableName *mTableNames;
658 };
659
660 } // end namespace Security
661
662 #endif //_H_APPLEDATABASE