]> git.saurik.com Git - apple/security.git/blob - libsecurity_filedb/lib/ReadWriteSection.h
Security-55471.tar.gz
[apple/security.git] / libsecurity_filedb / lib / ReadWriteSection.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 // ReadWriteSection.h
21 //
22
23 #ifndef _H_APPLEDL_READWRITESECTION
24 #define _H_APPLEDL_READWRITESECTION
25
26 #include <security_utilities/alloc.h>
27 #include <security_filedb/AtomicFile.h>
28 #include <security_utilities/endian.h>
29 #include <security_cdsa_utilities/cssmerrors.h>
30 #include <Security/cssm.h>
31 #include "OverUnderflowCheck.h"
32
33 namespace Security
34 {
35
36 //
37 // Atom -- An Atom is a 32-bit unsigned integer value that is always internally
38 // represented using network byte order.
39 //
40 typedef Endian<uint32> Atom;
41
42 enum {
43 AtomSize = sizeof(uint32) // XXX Why not just use sizeof(Atom)?
44 };
45
46 //
47 // Class representing a range (or subrange of a buffer).
48 //
49 class Range
50 {
51 public:
52 Range(uint32 inOffset, uint32 inSize) : mOffset(inOffset), mSize(inSize) {}
53 uint32 mOffset;
54 uint32 mSize;
55 };
56
57 //
58 // Class representing a packed record. All the accessors on this class are const since the
59 // underlying data is read-only
60 //
61 // XXX Should be replaced by Atom::Vector
62 class ReadSection
63 {
64 protected:
65 ReadSection(uint8 *inAddress, size_t inLength) : mAddress(inAddress), mLength(inLength)
66 {
67 if (mAddress == NULL)
68 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
69 }
70 public:
71 ReadSection() : mAddress(NULL), mLength(0) {}
72 ReadSection(const uint8 *inAddress, size_t inLength) :
73 mAddress(const_cast<uint8 *>(inAddress)), mLength(inLength) {}
74
75 uint32 size() const { return (uint32)mLength; }
76
77 uint32 at(uint32 inOffset) const
78 {
79 if (inOffset > mLength)
80 {
81 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
82 }
83
84 return ntohl(*reinterpret_cast<const uint32 *>(mAddress + inOffset));
85 }
86
87 uint32 operator[](uint32 inOffset) const
88 {
89 return at(inOffset);
90 }
91
92 // Return a subsection from inOffset to end of section.
93 ReadSection subsection(uint32 inOffset) const
94 {
95 if (inOffset > mLength)
96 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
97 return ReadSection(mAddress + inOffset, mLength - inOffset);
98 }
99
100 // Return a subsection from inOffset of inLength bytes.
101 ReadSection subsection(uint32 inOffset, uint32 inLength) const
102 {
103 if (CheckUInt32Add(inOffset, inLength) > mLength)
104 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
105 return ReadSection(mAddress + inOffset, inLength);
106 }
107
108 ReadSection subsection(const Range &inRange) const
109 {
110 return subsection(inRange.mOffset, inRange.mSize);
111 }
112
113 const uint8 *range(const Range &inRange) const
114 {
115 if (CheckUInt32Add(inRange.mOffset, inRange.mSize) > mLength)
116 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
117 return mAddress + inRange.mOffset;
118 }
119
120 uint8 *allocCopyRange(const Range &inRange, Allocator &inAllocator) const
121 {
122 uint8 *aData;
123 if (inRange.mSize == 0)
124 aData = NULL;
125 else
126 {
127 if (CheckUInt32Add(inRange.mOffset, inRange.mSize) > mLength)
128 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
129
130 aData = reinterpret_cast<uint8 *>(inAllocator.malloc(inRange.mSize));
131 memcpy(aData, mAddress + inRange.mOffset, inRange.mSize);
132 }
133
134 return aData;
135 }
136
137 static uint32 align(uint32 offset) { return (CheckUInt32Subtract(CheckUInt32Add(offset, AtomSize), 1)) & ~(AtomSize - 1); }
138
139 protected:
140 uint8 *mAddress;
141 size_t mLength;
142 };
143
144 //
145 // Class representing a packed record (or buffer) used for writing.
146 //
147 class WriteSection : public ReadSection
148 {
149 public:
150 static const size_t DefaultCapacity = 64;
151
152 WriteSection(Allocator &inAllocator, size_t inCapacity) :
153 ReadSection(reinterpret_cast<uint8 *>(inAllocator.malloc(inCapacity)), 0),
154 mAllocator(inAllocator),
155 mCapacity(inCapacity)
156 {
157 if (mCapacity > 0)
158 memset(mAddress, 0, mCapacity);
159 }
160
161 WriteSection(Allocator &inAllocator = Allocator::standard()) :
162 ReadSection(reinterpret_cast<uint8 *>(inAllocator.malloc(DefaultCapacity)), 0),
163 mAllocator(inAllocator),
164 mCapacity(DefaultCapacity)
165 {
166 }
167
168 WriteSection(const WriteSection &ws, int length) :
169 ReadSection(reinterpret_cast<uint8 *>(ws.mAllocator.malloc(length)), length),
170 mAllocator(ws.mAllocator),
171 mCapacity(length)
172 {
173 memcpy(mAddress, ws.mAddress, length);
174 }
175
176 ~WriteSection() { mAllocator.free(mAddress); }
177
178 private:
179 void grow(size_t inNewCapacity);
180
181 public:
182 #if BUG_GCC
183 uint32 size() const { return ReadSection::size(); }
184 #else
185 // XXX This should work but egcs-2.95.2 doesn't like it.
186 using ReadSection::size;
187 #endif
188
189 void size(uint32 inLength) { mLength = inLength; }
190 uint32 put(uint32 inOffset, uint32 inValue);
191 uint32 put(uint32 inOffset, uint32 inLength, const uint8 *inData);
192
193 const uint8 *address() const { return mAddress; }
194 uint8 *release()
195 {
196 uint8 *anAddress = mAddress;
197 mAddress = NULL;
198 mCapacity = 0;
199 return anAddress;
200 }
201
202 private:
203 Allocator &mAllocator;
204 size_t mCapacity;
205 };
206
207 } // end namespace Security
208
209 #endif // _H_APPLEDL_READWRITESECTION