]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/AtomicFile.h
Security-164.1.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / AtomicFile.h
1 /*
2 * Copyright (c) 2000-2001, 2003 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 _SECURITY_ATOMICFILE_H_
23 #define _SECURITY_ATOMICFILE_H_ 1
24
25 #include <Security/refcount.h>
26 #include <string>
27 #include <sys/stat.h>
28
29 namespace Security
30 {
31
32 class AtomicBufferedFile;
33 class AtomicLockedFile;
34 class AtomicTempFile;
35
36 class AtomicFile
37 {
38 public:
39 AtomicFile(const std::string &inPath);
40 ~AtomicFile();
41
42 // Aquire the write lock and remove the file.
43 void performDelete();
44
45 // Aquire the write lock and rename the file.
46 void rename(const std::string &inNewPath);
47
48 // Lock the file for writing and return a newly created AtomicTempFile.
49 RefPointer<AtomicTempFile> create(mode_t mode);
50
51 // Lock the file for writing and return a newly created AtomicTempFile.
52 RefPointer<AtomicTempFile> write();
53
54 // Return a bufferedFile containing current version of the file for reading.
55 RefPointer<AtomicBufferedFile> read();
56
57 string path() const { return mPath; }
58 string dir() const { return mDir; }
59 string file() const { return mFile; }
60
61 mode_t mode() const;
62
63 enum OffsetType
64 {
65 FromStart,
66 FromEnd // only works with offset of 0
67 };
68
69 static void pathSplit(const std::string &inFull, std::string &outDir, std::string &outFile);
70 static void mkpath(const std::string &inDir, mode_t mode = 0777);
71 static int ropen(const char *const name, int flags, mode_t mode);
72 static int rclose(int fd);
73
74 private:
75 string mPath;
76 string mDir;
77 string mFile;
78 };
79
80
81 //
82 // AtomicBufferedFile - This represents an instance of a file opened for reading.
83 // The file is read into memory and closed after this is done.
84 // The memory is released when this object is destroyed.
85 //
86 class AtomicBufferedFile : public RefCount
87 {
88 public:
89 AtomicBufferedFile(const std::string &inPath);
90 ~AtomicBufferedFile();
91
92 // Open the file and return it's size.
93 off_t open();
94
95 // Read inLength bytes starting at inOffset.
96 const uint8 *read(off_t inOffset, off_t inLength, off_t &outLength);
97
98 // Return the current mode bits of the file
99 mode_t mode();
100
101 // Close the file (this doesn't release the buffer).
102 void close();
103
104 // Return the length of the file.
105 off_t length() const { return mLength; }
106
107 private:
108 // Complete path to the file
109 string mPath;
110
111 // File descriptor to the file or -1 if it's not currently open.
112 int mFileRef;
113
114 // This is where the data from the file is read in to.
115 uint8 *mBuffer;
116
117 // Length of file in bytes.
118 off_t mLength;
119 };
120
121
122 //
123 // AtomicTempFile - A temporary file to write changes to.
124 //
125 class AtomicTempFile : public RefCount
126 {
127 public:
128 // Start a write for a new file.
129 AtomicTempFile(AtomicFile &inFile, const RefPointer<AtomicLockedFile> &inLockedFile, mode_t mode);
130
131 // Start a write of an existing file.
132 AtomicTempFile(AtomicFile &inFile, const RefPointer<AtomicLockedFile> &inLockedFile);
133
134 ~AtomicTempFile();
135
136 // Commit the current create or write and close the write file.
137 void commit();
138
139 void write(AtomicFile::OffsetType inOffsetType, off_t inOffset, const uint32 *inData, uint32 inCount);
140 void write(AtomicFile::OffsetType inOffsetType, off_t inOffset, const uint8 *inData, uint32 inLength);
141 void write(AtomicFile::OffsetType inOffsetType, off_t inOffset, const uint32 inData);
142
143 private:
144 // Called by both constructors.
145 void create(mode_t mode);
146
147 // Fsync the file
148 void fsync();
149
150 // Close the file
151 void close();
152
153 // Rollback the current create or write (happens automatically if commit() isn't called before the destructor is).
154 void rollback() throw();
155
156 private:
157 // Our AtomicFile object.
158 AtomicFile &mFile;
159
160 RefPointer<AtomicLockedFile> mLockedFile;
161
162 // Complete path to the file
163 string mPath;
164
165 // File descriptor to the file or -1 if it's not currently open.
166 int mFileRef;
167
168 // If this is true we unlink both mPath and mFile.path() when we rollback.
169 bool mCreating;
170 };
171
172
173 // The current lock being held.
174 class AtomicLockedFile : public RefCount
175 {
176 public:
177 // Create a write lock for inFile.
178 AtomicLockedFile(AtomicFile &inFile);
179
180 ~AtomicLockedFile();
181
182 private:
183 void lock(mode_t mode = (S_IRUSR|S_IRGRP|S_IROTH) /* === 0444 */);
184 void unlock() throw();
185
186 private:
187 std::string unique(mode_t mode);
188 int rlink(const char *const old, const char *const newn, struct stat &sto);
189 int myrename(const char *const old, const char *const newn);
190 int xcreat(const char *const name, mode_t mode, time_t &tim);
191
192 // The directory in which we create the lock
193 string mDir;
194
195 // Complete path to the file
196 string mPath;
197 };
198
199
200 } // end namespace Security
201
202
203 #endif // _SECURITY_ATOMICFILE_H_