1/*
2 * Copyright (c) 2000-2004,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// mdsclient - friendly interface to CDSA MDS API
21//
22#include <security_cdsa_client/mdsclient.h>
23
24
25namespace Security {
26namespace CssmClient {
27
28
29//
30// DLAccess gets a virtual destructor just in case
31//
32DLAccess::~DLAccess()
33{ }
34
35
36//
37// Basic Record objects (abstract)
38//
39Record::Record(const char * const * names)
40	: CssmAutoData(Allocator::standard(Allocator::sensitive))
41{
42	addAttributes(names);
43}
44
45void Record::addAttributes(const char * const * name)
46{
47	if (name)
48		while (*name)
49			mAttributes.add(CssmDbAttributeInfo(*name++));
50}
51
52Record::~Record()
53{ }
54
55
56//
57// Tables and their components (non-template common features)
58//
59TableBase::TableBase(DLAccess &source, CSSM_DB_RECORDTYPE type, bool getData /* = true */)
60	: database(source), mRecordType(type), mGetData(getData)
61{
62}
63
64TableBase::Handle::~Handle()
65{
66	if (query)
67		mAccess->dlAbortQuery(query);
68}
69
70TableBase::Uid::~Uid()
71{
72	if (uid)
73		mAccess->dlFreeUniqueId(uid);
74}
75
76TableBase::Iterator::Iterator(DLAccess *ac, CSSM_HANDLE query,
77		CSSM_DB_UNIQUE_RECORD *id, Record *record, bool getData)
78	: mAccess(ac), mQuery(new Handle(ac, query)),
79	  mUid(new Uid(ac, id)), mRecord(record), mGetData(getData)
80{ }
81
82
83void TableBase::Iterator::advance(Record *fill)
84{
85	RefPointer<Record> newRecord = fill;	// hold it safely
86	CSSM_DB_UNIQUE_RECORD *id;
87	CssmAutoData data(mAccess->allocator());
88	if (mAccess->dlGetNext(mQuery->query, newRecord->attributes(),
89		mGetData ? &data.get() : NULL, id)) {
90		if (mGetData)
91			newRecord->recordData() = data;
92		mUid = new Uid(mAccess, id);
93		mRecord = newRecord;
94	} else {
95		mQuery->query = CSSM_INVALID_HANDLE; // was automatically aborted
96		// release all iterator resources and make me == end()
97		mQuery = NULL;
98		mUid = NULL;
99		mRecord = NULL;
100	}
101}
102
103
104uint32 TableBase::erase(const CSSM_QUERY &query)
105{
106	CSSM_DB_UNIQUE_RECORD *id;
107	CssmDbRecordAttributeData noAttributes;
108	CSSM_HANDLE handle = database.dlGetFirst(query, noAttributes, NULL, id);
109	if (handle == CSSM_INVALID_HANDLE)
110		return 0;   // no match, nothing erased
111	uint32 count = 0;
112	do {
113		database.dlDeleteRecord(id);
114		count++;
115		database.dlFreeUniqueId(id);
116	} while (database.dlGetNext(handle, noAttributes, NULL, id));
117	return count;
118}
119
120uint32 TableBase::erase(const Query &query)
121{
122	return erase(query.cssmQuery());
123}
124
125
126} // end namespace CssmClient
127} // end namespace Security
128