]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/unix++.h
Security-59754.41.1.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / unix++.h
1 /*
2 * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 //
26 // unix++ - C++ layer for basic UNIX facilities
27 //
28 #ifndef _H_UNIXPLUSPLUS
29 #define _H_UNIXPLUSPLUS
30
31 #include <security_utilities/utilities.h>
32 #include <security_utilities/errors.h>
33 #include <security_utilities/timeflow.h>
34 #include <sys/types.h>
35 #include <sys/ioctl.h>
36 #include <sys/uio.h>
37 #include <sys/stat.h>
38 #include <sys/mman.h>
39 #include <sys/xattr.h>
40 #include <signal.h>
41 #include <fcntl.h>
42 #include <semaphore.h>
43 #include <cstdio>
44 #include <cstdarg>
45 #include <map>
46
47
48 namespace Security {
49 namespace UnixPlusPlus {
50
51
52 //
53 // Check system call return and throw on error
54 //
55 template <class Result>
56 inline Result checkError(Result result)
57 {
58 if (result == Result(-1))
59 UnixError::throwMe();
60 return result;
61 }
62
63
64 //
65 // A UNIX standard 'struct iovec' wrapped
66 //
67 class IOVec : public iovec {
68 public:
69 IOVec() { }
70 IOVec(const void *data, size_t length) { set(data, length); }
71 IOVec(void *data, size_t length) { set(data, length); }
72
73 void set(const void *data, size_t length)
74 { iov_base = reinterpret_cast<char *>(const_cast<void *>(data)); iov_len = length; }
75
76 // data-oid methods
77 void *data() const { return iov_base; }
78 size_t length() const { return iov_len; }
79 };
80
81
82 //
83 // Generic file descriptors
84 //
85 class FileDesc {
86 protected:
87 static const int invalidFd = -1;
88
89 void setFd(int fd) { mFd = fd; mAtEnd = false; }
90 void checkSetFd(int fd) { checkError(fd); mFd = fd; mAtEnd = false; }
91
92 FileDesc(int fd, bool atEnd) : mFd(fd), mAtEnd(atEnd) { }
93 void closeAndLog(); // close and clear without throwing
94
95 public:
96 FileDesc() : mFd(invalidFd), mAtEnd(false) { }
97 FileDesc(int fd) : mFd(fd), mAtEnd(false) { }
98
99 FileDesc(const FileDesc& fd) : mFd(fd.mFd), mAtEnd(fd.mAtEnd) { }
100
101 static const mode_t modeMissingOk = S_IFIFO; // in mode means "do not throw on ENOENT"
102
103 // implicit file system open() construction
104 explicit FileDesc(const char *path, int flag = O_RDONLY, mode_t mode = 0666)
105 : mFd(invalidFd) { this->open(path, flag, mode); }
106 explicit FileDesc(const std::string &path, int flag = O_RDONLY, mode_t mode = 0666)
107 : mFd(invalidFd) { this->open(path.c_str(), flag, mode); }
108
109 // assignment
110 FileDesc &operator = (int fd) { mFd = fd; mAtEnd = false; return *this; }
111 FileDesc &operator = (const FileDesc &fd) { mFd = fd.mFd; mAtEnd = fd.mAtEnd; return *this; }
112
113 bool isOpen() const { return mFd != invalidFd; }
114 operator bool() const { return isOpen(); }
115 int fd() const { return mFd; }
116 operator int() const { return fd(); }
117
118 void clear() { mFd = invalidFd; }
119 void close(); // close and clear
120
121 void open(const char *path, int flag = O_RDONLY, mode_t mode = 0666);
122 void open(const std::string &path, int flag = O_RDONLY, mode_t mode = 0666)
123 { this->open(path.c_str(), flag, mode); }
124
125 // basic I/O: this defines the "Filedescoid" pseudo-type
126 size_t read(void *addr, size_t length);
127 size_t write(const void *addr, size_t length);
128 bool atEnd() const { return mAtEnd; } // valid after zero-length read only
129
130 // basic I/O with positioning
131 size_t read(void *addr, size_t length, size_t position);
132 size_t write(const void *addr, size_t length, size_t position);
133
134 // read/write all of a buffer, in pieces of necessary
135 size_t readAll(void *addr, size_t length);
136 size_t readAll(std::string &content);
137 void writeAll(const void *addr, size_t length);
138 void writeAll(char *s) { writeAll(s, strlen(s)); }
139 void writeAll(const char *s) { writeAll(s, strlen(s)); }
140 template <class Data>
141 void writeAll(const Data &ds) { writeAll(ds.data(), ds.length()); }
142
143 void truncate(size_t offset);
144
145 // more convenient I/O
146 template <class T> size_t read(T &obj) { return read(&obj, sizeof(obj)); }
147 template <class T> size_t write(const T &obj) { return write(&obj, sizeof(obj)); }
148
149 // seeking
150 size_t seek(size_t position, int whence = SEEK_SET);
151 size_t position() const;
152
153 // mapping support
154 void *mmap(int prot = PROT_READ, size_t length = 0,
155 int flags = MAP_FILE | MAP_PRIVATE, size_t offset = 0, void *addr = NULL);
156
157 // fcntl support
158 int fcntl(int cmd, void *arg = NULL) const;
159 template <class T> int fcntl(int cmd, T arg) const
160 { return fcntl(cmd, reinterpret_cast<void *>(arg)); }
161 int flags() const { return fcntl(F_GETFL); }
162 void flags(int flags) const { fcntl(F_SETFL, flags); }
163 void setFlag(int flag, bool on = true) const;
164 void clearFlag(int flag) const { setFlag(flag, false); }
165
166 int openMode() const { return flags() & O_ACCMODE; }
167 bool isWritable() const { return openMode() != O_RDONLY; }
168 bool isReadable() const { return openMode() != O_WRONLY; }
169
170 FileDesc dup() const;
171 FileDesc dup(int newFd) const;
172
173 // lock support (fcntl style)
174 struct Pos {
175 Pos(size_t s = 0, int wh = SEEK_SET, size_t siz = 0)
176 : start(s), size(siz), whence(wh) { }
177
178 size_t start;
179 size_t size;
180 int whence;
181 };
182 static Pos lockAll() { return Pos(0, SEEK_SET, 0); }
183
184 void lock(struct flock &args); // raw form (fill in yourself)
185
186 void lock(int type = F_WRLCK, const Pos &pos = lockAll());
187 bool tryLock(int type = F_WRLCK, const Pos &pos = lockAll());
188 void unlock(const Pos &pos = lockAll()) { lock(F_UNLCK, pos); }
189
190 // ioctl support
191 int ioctl(int cmd, void *arg) const;
192 template <class Arg> Arg iocget(int cmd) const
193 { Arg arg; ioctl(cmd, &arg); return arg; }
194 template <class Arg> void iocget(int cmd, Arg &arg) const
195 { ioctl(cmd, &arg); }
196 template <class Arg> void iocset(int cmd, const Arg &arg)
197 { ioctl(cmd, const_cast<Arg *>(&arg)); }
198
199 // xattr support
200 void setAttr(const char *name, const void *value, size_t length,
201 u_int32_t position = 0, int options = 0);
202 void setAttr(const std::string &name, const void *value, size_t length,
203 u_int32_t position = 0, int options = 0)
204 { return setAttr(name.c_str(), value, length, position, options); }
205 ssize_t getAttr(const char *name, void *value, size_t length,
206 u_int32_t position = 0, int options = 0);
207 ssize_t getAttr(const std::string &name, void *value, size_t length,
208 u_int32_t position = 0, int options = 0)
209 { return getAttr(name.c_str(), value, length, position, options); }
210 ssize_t getAttrLength(const char *name, int options = 0);
211 ssize_t getAttrLength(const std::string &name, int options = 0) { return getAttrLength(name.c_str(), options); }
212 // removeAttr ignore missing attributes. Pass XATTR_REPLACE to fail in that case
213 void removeAttr(const char *name, int options = 0);
214 void removeAttr(const std::string &name, int options = 0)
215 { return removeAttr(name.c_str(), options); }
216 size_t listAttr(char *value, size_t length, int options = 0);
217
218 bool hasExtendedAttribute(const char *forkname) const;
219
220 // xattrs with string values (not including trailing null bytes)
221 void setAttr(const std::string &name, const std::string &value, int options = 0);
222 std::string getAttr(const std::string &name, int options = 0);
223
224 // stat-related utilities. @@@ should cache??
225 typedef struct stat UnixStat;
226 void fstat(UnixStat &st) const;
227 size_t fileSize() const;
228 bool isA(int type) const;
229
230 // change various permissions-related features on the open file
231 void chown(uid_t uid);
232 void chown(uid_t uid, gid_t gid);
233 void chgrp(gid_t gid);
234 void chmod(mode_t mode);
235 void chflags(u_int flags);
236
237 // stdio interactions
238 FILE *fdopen(const char *mode = NULL); // fdopen(3)
239
240 // Is this a regular file? (not a symlink, fifo, etc.)
241 bool isPlainFile(const std::string &path);
242
243 // device characteristics
244 std::string mediumType();
245
246 private:
247 int mFd; // UNIX file descriptor
248
249 private:
250 struct LockArgs : public flock {
251 LockArgs(int type, const Pos &pos)
252 { l_start = pos.start; l_len = pos.size; l_type = type; l_whence = pos.whence; }
253 IFDEBUG(void debug(int fd, const char *what));
254 };
255
256 protected:
257 bool mAtEnd; // end-of-data indicator (after zero read)
258 };
259
260
261 bool filehasExtendedAttribute(const char *path, const char *forkname);
262 inline bool filehasExtendedAttribute(const std::string& path, const char *forkname) { return filehasExtendedAttribute(path.c_str(), forkname); }
263
264
265 //
266 // A (plain) FileDesc that auto-closes
267 //
268 class AutoFileDesc : public FileDesc {
269 public:
270 AutoFileDesc() { }
271 AutoFileDesc(int fd) : FileDesc(fd) { }
272
273 AutoFileDesc(const char *path, int flag = O_RDONLY, mode_t mode = 0666)
274 : FileDesc(path, flag, mode) { }
275 AutoFileDesc(const std::string &path, int flag = O_RDONLY, mode_t mode = 0666)
276 : FileDesc(path, flag, mode) { }
277 AutoFileDesc(const AutoFileDesc& rhs);
278 ~AutoFileDesc() { closeAndLog(); }
279 };
280
281
282 //
283 // Signal sets
284 //
285 class SigSet {
286 public:
287 SigSet() { sigemptyset(&mValue); }
288 SigSet(const sigset_t &s) : mValue(s) { }
289
290 SigSet &operator += (int sig)
291 { sigaddset(&mValue, sig); return *this; }
292 SigSet &operator -= (int sig)
293 { sigdelset(&mValue, sig); return *this; }
294
295 bool contains(int sig)
296 { return sigismember(&mValue, sig); }
297
298 sigset_t &value() { return mValue; }
299 operator sigset_t () const { return mValue; }
300
301 private:
302 sigset_t mValue;
303 };
304
305 SigSet sigMask(SigSet set, int how = SIG_SETMASK);
306
307
308 //
309 // A ForkMonitor determines whether the current thread is a (fork) child of
310 // the thread that last checked it. Essentially, it checks for pid changes.
311 //
312 class StaticForkMonitor {
313 public:
314 bool operator () () const
315 {
316 if (mLastPid == 0) {
317 mLastPid = getpid();
318 return false;
319 } else if (getpid() != mLastPid) {
320 mLastPid = getpid();
321 return true;
322 }
323 return false;
324 }
325
326 protected:
327 mutable pid_t mLastPid;
328 };
329
330 class ForkMonitor : public StaticForkMonitor {
331 public:
332 ForkMonitor() { mLastPid = getpid(); }
333 };
334
335
336 //
337 // Miscellaneous functions to aid the intrepid UNIX hacker
338 //
339 void makedir(const char *path, int flags, mode_t mode = 0777);
340
341 int ffprintf(const char *path, int flags, mode_t mode, const char *format, ...) __attribute__((format(printf, 4, 5)));
342 int ffscanf(const char *path, const char *format, ...) __attribute__((format(scanf, 2, 3)));
343
344
345 } // end namespace UnixPlusPlus
346 } // end namespace Security
347
348
349 #endif //_H_UNIXPLUSPLUS