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