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