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 <signal.h> 40#include <fcntl.h> 41#include <semaphore.h> 42#include <cstdio> 43#include <cstdarg> 44#include <map> 45 46 47namespace Security { 48namespace UnixPlusPlus { 49 50 51// 52// Check system call return and throw on error 53// 54template <class Result> 55inline Result checkError(Result result) 56{ 57 if (result == Result(-1)) 58 UnixError::throwMe(); 59 return result; 60} 61 62 63// 64// A UNIX standard 'struct iovec' wrapped 65// 66class IOVec : public iovec { 67public: 68 IOVec() { } 69 IOVec(const void *data, size_t length) { set(data, length); } 70 IOVec(void *data, size_t length) { set(data, length); } 71 72 void set(const void *data, size_t length) 73 { iov_base = reinterpret_cast<char *>(const_cast<void *>(data)); iov_len = length; } 74 75 // data-oid methods 76 void *data() const { return iov_base; } 77 size_t length() const { return iov_len; } 78}; 79 80 81// 82// Generic file descriptors 83// 84class FileDesc { 85protected: 86 static const int invalidFd = -1; 87 88 void setFd(int fd) { mFd = fd; mAtEnd = false; } 89 void checkSetFd(int fd) { checkError(fd); mFd = fd; mAtEnd = false; } 90 91 FileDesc(int fd, bool atEnd) : mFd(fd), mAtEnd(atEnd) { } 92 93public: 94 FileDesc() : mFd(invalidFd), mAtEnd(false) { } 95 FileDesc(int fd) : mFd(fd), mAtEnd(false) { } 96 97 static const mode_t modeMissingOk = S_IFIFO; // in mode means "do not throw on ENOENT" 98 99 // implicit file system open() construction 100 explicit FileDesc(const char *path, int flag = O_RDONLY, mode_t mode = 0666) 101 : mFd(invalidFd) { this->open(path, flag, mode); } 102 explicit FileDesc(const std::string &path, int flag = O_RDONLY, mode_t mode = 0666) 103 : mFd(invalidFd) { this->open(path.c_str(), flag, mode); } 104 105 // assignment 106 FileDesc &operator = (int fd) { mFd = fd; mAtEnd = false; return *this; } 107 FileDesc &operator = (const FileDesc &fd) { mFd = fd.mFd; mAtEnd = fd.mAtEnd; return *this; } 108 109 bool isOpen() const { return mFd != invalidFd; } 110 operator bool() const { return isOpen(); } 111 int fd() const { return mFd; } 112 operator int() const { return fd(); } 113 114 void clear() { mFd = invalidFd; } 115 void close(); // close and clear 116 117 void open(const char *path, int flag = O_RDONLY, mode_t mode = 0666); 118 void open(const std::string &path, int flag = O_RDONLY, mode_t mode = 0666) 119 { this->open(path.c_str(), flag, mode); } 120 121 // basic I/O: this defines the "Filedescoid" pseudo-type 122 size_t read(void *addr, size_t length); 123 size_t write(const void *addr, size_t length); 124 bool atEnd() const { return mAtEnd; } // valid after zero-length read only 125 126 // basic I/O with positioning 127 size_t read(void *addr, size_t length, size_t position); 128 size_t write(const void *addr, size_t length, size_t position); 129 130 // read/write all of a buffer, in pieces of necessary 131 size_t readAll(void *addr, size_t length); 132 size_t readAll(std::string &content); 133 void writeAll(const void *addr, size_t length); 134 void writeAll(char *s) { writeAll(s, strlen(s)); } 135 void writeAll(const char *s) { writeAll(s, strlen(s)); } 136 template <class Data> 137 void writeAll(const Data &ds) { writeAll(ds.data(), ds.length()); } 138 139 // more convenient I/O 140 template <class T> size_t read(T &obj) { return read(&obj, sizeof(obj)); } 141 template <class T> size_t write(const T &obj) { return write(&obj, sizeof(obj)); } 142 143 // seeking 144 size_t seek(size_t position, int whence = SEEK_SET); 145 size_t position() const; 146 147 // mapping support 148 void *mmap(int prot = PROT_READ, size_t length = 0, 149 int flags = MAP_FILE | MAP_PRIVATE, size_t offset = 0, void *addr = NULL); 150 151 // fcntl support 152 int fcntl(int cmd, void *arg = NULL) const; 153 template <class T> int fcntl(int cmd, T arg) const 154 { return fcntl(cmd, reinterpret_cast<void *>(arg)); } 155 int flags() const { return fcntl(F_GETFL); } 156 void flags(int flags) const { fcntl(F_SETFL, flags); } 157 void setFlag(int flag, bool on = true) const; 158 void clearFlag(int flag) const { setFlag(flag, false); } 159 160 int openMode() const { return flags() & O_ACCMODE; } 161 bool isWritable() const { return openMode() != O_RDONLY; } 162 bool isReadable() const { return openMode() != O_WRONLY; } 163 164 FileDesc dup() const; 165 FileDesc dup(int newFd) const; 166 167 // lock support (fcntl style) 168 struct Pos { 169 Pos(size_t s = 0, int wh = SEEK_SET, size_t siz = 0) 170 : start(s), size(siz), whence(wh) { } 171 172 size_t start; 173 size_t size; 174 int whence; 175 }; 176 static Pos lockAll() { return Pos(0, SEEK_SET, 0); } 177 178 void lock(struct flock &args); // raw form (fill in yourself) 179 180 void lock(int type = F_WRLCK, const Pos &pos = lockAll()); 181 bool tryLock(int type = F_WRLCK, const Pos &pos = lockAll()); 182 void unlock(const Pos &pos = lockAll()) { lock(F_UNLCK, pos); } 183 184 // ioctl support 185 int ioctl(int cmd, void *arg) const; 186 template <class Arg> Arg iocget(int cmd) const 187 { Arg arg; ioctl(cmd, &arg); return arg; } 188 template <class Arg> void iocget(int cmd, Arg &arg) const 189 { ioctl(cmd, &arg); } 190 template <class Arg> void iocset(int cmd, const Arg &arg) 191 { ioctl(cmd, const_cast<Arg *>(&arg)); } 192 193 // xattr support 194 void setAttr(const char *name, const void *value, size_t length, 195 u_int32_t position = 0, int options = 0); 196 void setAttr(const std::string &name, const void *value, size_t length, 197 u_int32_t position = 0, int options = 0) 198 { return setAttr(name.c_str(), value, length, position, options); } 199 ssize_t getAttr(const char *name, void *value, size_t length, 200 u_int32_t position = 0, int options = 0); 201 ssize_t getAttr(const std::string &name, void *value, size_t length, 202 u_int32_t position = 0, int options = 0) 203 { return getAttr(name.c_str(), value, length, position, options); } 204 ssize_t getAttrLength(const char *name); 205 ssize_t getAttrLength(const std::string &name) { return getAttrLength(name.c_str()); } 206 // removeAttr ignore missing attributes. Pass XATTR_REPLACE to fail in that case 207 void removeAttr(const char *name, int options = 0); 208 void removeAttr(const std::string &name, int options = 0) 209 { return removeAttr(name.c_str(), options); } 210 size_t listAttr(char *value, size_t length, int options = 0); 211 size_t listAttr(const std::string &name, size_t length, int options = 0) 212 { return listAttr(name.c_str(), length, options); } 213 214 // xattrs with string values (not including trailing null bytes) 215 void setAttr(const std::string &name, const std::string &value, int options = 0); 216 std::string getAttr(const std::string &name, int options = 0); 217 218 // stat-related utilities. @@@ should cache?? 219 typedef struct stat UnixStat; 220 void fstat(UnixStat &st) const; 221 size_t fileSize() const; 222 bool isA(int type) const; 223 224 // change various permissions-related features on the open file 225 void chown(uid_t uid); 226 void chown(uid_t uid, gid_t gid); 227 void chgrp(gid_t gid); 228 void chmod(mode_t mode); 229 void chflags(u_int flags); 230 231 // stdio interactions 232 FILE *fdopen(const char *mode = NULL); // fdopen(3) 233 234 // Is this a regular file? (not a symlink, fifo, etc.) 235 bool isPlainFile(const std::string &path); 236 237private: 238 int mFd; // UNIX file descriptor 239 240private: 241 struct LockArgs : public flock { 242 LockArgs(int type, const Pos &pos) 243 { l_start = pos.start; l_len = pos.size; l_type = type; l_whence = pos.whence; } 244 IFDEBUG(void debug(int fd, const char *what)); 245 }; 246 247protected: 248 bool mAtEnd; // end-of-data indicator (after zero read) 249}; 250 251 252// 253// A (plain) FileDesc that auto-closes 254// 255class AutoFileDesc : public FileDesc { 256public: 257 AutoFileDesc() { } 258 AutoFileDesc(int fd) : FileDesc(fd) { } 259 260 AutoFileDesc(const char *path, int flag = O_RDONLY, mode_t mode = 0666) 261 : FileDesc(path, flag, mode) { } 262 AutoFileDesc(const std::string &path, int flag = O_RDONLY, mode_t mode = 0666) 263 : FileDesc(path, flag, mode) { } 264 265 ~AutoFileDesc() { close(); } 266}; 267 268 269// 270// Signal sets 271// 272class SigSet { 273public: 274 SigSet() { sigemptyset(&mValue); } 275 SigSet(const sigset_t &s) : mValue(s) { } 276 277 SigSet &operator += (int sig) 278 { sigaddset(&mValue, sig); return *this; } 279 SigSet &operator -= (int sig) 280 { sigdelset(&mValue, sig); return *this; } 281 282 bool contains(int sig) 283 { return sigismember(&mValue, sig); } 284 285 sigset_t &value() { return mValue; } 286 operator sigset_t () const { return mValue; } 287 288private: 289 sigset_t mValue; 290}; 291 292SigSet sigMask(SigSet set, int how = SIG_SETMASK); 293 294 295// 296// A ForkMonitor determines whether the current thread is a (fork) child of 297// the thread that last checked it. Essentially, it checks for pid changes. 298// 299class StaticForkMonitor { 300public: 301 bool operator () () const 302 { 303 if (mLastPid == 0) { 304 mLastPid = getpid(); 305 return false; 306 } else if (getpid() != mLastPid) { 307 mLastPid = getpid(); 308 return true; 309 } 310 return false; 311 } 312 313protected: 314 mutable pid_t mLastPid; 315}; 316 317class ForkMonitor : public StaticForkMonitor { 318public: 319 ForkMonitor() { mLastPid = getpid(); } 320}; 321 322 323// 324// Miscellaneous functions to aid the intrepid UNIX hacker 325// 326void makedir(const char *path, int flags, mode_t mode = 0777); 327 328int ffprintf(const char *path, int flags, mode_t mode, const char *format, ...); 329int ffscanf(const char *path, const char *format, ...); 330 331 332} // end namespace UnixPlusPlus 333} // end namespace Security 334 335 336#endif //_H_UNIXPLUSPLUS 337