]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/AtomicFile.h
Security-54.1.3.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / AtomicFile.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 // AtomicFile.h - Description t.b.d.
21 //
22 #ifndef _H_ATOMICFILE
23 #define _H_ATOMICFILE
24
25 #include <Security/threading.h>
26
27 #include <map>
28 #include <string>
29
30 #if _USE_IO == _USE_IO_POSIX
31 #include <sys/types.h>
32 #include <machine/endian.h>
33 #elif _USE_IO == _USE_IO_MACOS
34 #define htonl(X) (X)
35 #define ntohl(X) (X)
36 #endif
37
38 #ifdef _CPP_ATOMICFILE
39 #pragma export on
40 #endif
41
42 namespace Security
43 {
44
45 class DbName;
46
47 class AtomicFile
48 {
49 public:
50 typedef int FileRef;
51 typedef int VersionId;
52
53 AtomicFile(const DbName &inDbName);
54 ~AtomicFile();
55
56 // Close the currently open AtomicFile. (If there are transactions outstanding this call
57 // has no effect until after they have completed.
58 void close();
59
60 // Start a read operation. Returns a mmaped region with the file in it. Return the size of the
61 // file in length. Each call to enterRead() *must* be paired with a call to exitRead.
62 VersionId enterRead(const uint8 *&outFileAddress, size_t &outLength);
63
64 // End a read operation.
65 void exitRead(VersionId inVersionId);
66
67 // Return true if inVersionId is not the most recent version of this file.
68 bool isDirty(VersionId inVersionId);
69
70 // Aquire the write lock and remove the file.
71 void performDelete();
72
73 // Create and lock the database file for writing, and set outWriteRef to a newly created
74 // file open for writing.
75 // Return the new VersionId this file will have after a succesful commit.
76 VersionId enterCreate(FileRef &outWriteRef);
77
78 // Lock the database file for writing, map the database file for reading and
79 // set outWriteRef to a newly created file open for writing.
80 // Return the VersionId or the file being modified.
81 VersionId enterWrite(const uint8 *&outFileAddress, size_t &outLength, FileRef &outWriteRef);
82
83 // Commit the current create or write and close the write file. Return the VersionId of the new file.
84 VersionId commit();
85
86 // Rollback the current create or write.
87 void rollback();
88
89 enum OffsetType {
90 None,
91 FromStart,
92 FromCurrent
93 };
94
95 void write(OffsetType inOffsetType, uint32 inOffset, const uint32 *inData, uint32 inCount);
96 void write(OffsetType inOffsetType, uint32 inOffset, const uint8 *inData, uint32 inLength);
97 void write(OffsetType inOffsetType, uint32 inOffset, const uint32 inData);
98 const string filename() const { return mReadFilename; }
99 private:
100 void endWrite();
101 void rename(const string &inSrcFilename, const string &inDestFilename);
102 void unlink(const string &inFilename);
103
104 class OpenFile
105 {
106 public:
107 OpenFile(const std::string &inFilename, bool write, bool lock, VersionId inVersionId, mode_t mode);
108 ~OpenFile();
109
110 void close();
111 VersionId versionId() const { return mVersionId; }
112 FileRef fileRef() const { return mFileRef; }
113 const uint8 *address() const { return mAddress; }
114 size_t length() const { return mLength; }
115
116 // Check if the file has its dirty bit set.
117 bool isDirty();
118 // Set the files dirty bit (requires the file to be writeable and locked).
119 void setDirty();
120
121 void lock();
122 void unlock();
123
124 // Return the mode bits of the file
125 mode_t mode();
126
127 int mUseCount;
128 FileRef mFileRef;
129 private:
130 VersionId readVersionId();
131 void writeVersionId(VersionId inVersionId);
132 static void mkpath(const std::string &inFilename);
133
134 VersionId mVersionId;
135 const uint8 *mAddress;
136 size_t mLength;
137 bool mFcntlLock;
138 enum
139 {
140 Closed,
141 Read,
142 Write,
143 ReadWrite,
144 Create
145 } mState;
146 };
147
148 Mutex mReadLock;
149 OpenFile *mReadFile;
150 string mReadFilename;
151
152 Mutex mWriteLock;
153 OpenFile *mWriteFile;
154 string mWriteFilename;
155
156 typedef std::map<VersionId, OpenFile *> OpenFileMap;
157 OpenFileMap mOpenFileMap;
158
159 bool mCreating;
160 };
161
162
163 class AtomicFileRef
164 {
165 public:
166 virtual ~AtomicFileRef();
167
168 uint32 at(uint32 inOffset)
169 {
170 return ntohl(*reinterpret_cast<const uint32 *>(mAddress + inOffset));
171 }
172
173 uint32 operator[](uint32 inOffset)
174 {
175 if (inOffset + sizeof(uint32) > mLength)
176 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
177 return at(inOffset);
178 }
179
180 const uint8 *range(uint32 inOffset, uint32 inLength)
181 {
182 if (inOffset + inLength > mLength)
183 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
184 return mAddress + inOffset;
185 }
186
187 const AtomicFile::VersionId mVersionId;
188 protected:
189 struct InitArg;
190 AtomicFileRef(AtomicFile &inAtomicFile, const InitArg &inInitArg);
191
192 AtomicFile &mAtomicFile;
193 const uint8 *mAddress;
194 const size_t mLength;
195 };
196
197 // Use this class to open an AtomicFile for reading.
198 class AtomicFileReadRef : public AtomicFileRef
199 {
200 public:
201 AtomicFileReadRef(AtomicFile &inAtomicFile);
202 virtual ~AtomicFileReadRef();
203 private:
204 static InitArg enterRead(AtomicFile &inAtomicFile);
205 };
206
207 // Use this class to open an AtomicFile for writing.
208 class AtomicFileWriteRef : public AtomicFileRef
209 {
210 public:
211 AtomicFileWriteRef(AtomicFile &inAtomicFile);
212 virtual ~AtomicFileWriteRef();
213 AtomicFile::VersionId commit() { mOpen = false; return mAtomicFile.commit(); }
214
215 private:
216 static InitArg enterWrite(AtomicFile &inAtomicFile, AtomicFile::FileRef &outWriteFileRef);
217 AtomicFile::FileRef mFileRef;
218 bool mOpen;
219 };
220
221 } // end namespace Security
222
223 #ifdef _CPP_ATOMICFILE
224 #pragma export off
225 #endif
226
227 #endif //_H_ATOMICFILE