CernVM-FS  2.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
platform_osx.h
Go to the documentation of this file.
1 
7 #ifndef CVMFS_UTIL_PLATFORM_OSX_H_
8 #define CVMFS_UTIL_PLATFORM_OSX_H_
9 
10 #include <alloca.h>
11 #include <dirent.h>
12 #include <fcntl.h>
13 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \
14  && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
15 #include <os/lock.h> // NOLINT
16 #else
17 #include <libkern/OSAtomic.h>
18 #endif // defined(__MAC_OS_X_VERSION_MIN_REQUIRED) &&
19  // __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
20 #include <mach-o/dyld.h>
21 #include <mach/mach.h> // NOLINT
22 #include <mach/mach_time.h>
23 #include <signal.h>
24 #include <sys/mount.h>
25 #include <sys/param.h>
26 #include <sys/stat.h>
27 #include <sys/sysctl.h>
28 #include <sys/types.h>
29 #include <sys/ucred.h>
30 // clang-format off
31 #include <sys/xattr.h>
32 // clang-format on
33 
34 #include <cassert>
35 #include <cstdio>
36 #include <cstdlib>
37 #include <cstring>
38 #include <string>
39 #include <vector>
40 
41 #include "util/smalloc.h"
42 
43 #ifdef CVMFS_NAMESPACE_GUARD
44 namespace CVMFS_NAMESPACE_GUARD {
45 #endif
46 
53 #ifndef MSG_NOSIGNAL
54 #define MSG_NOSIGNAL SO_NOSIGPIPE
55 #endif
56 
60 #define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
61 
62 #define platform_sighandler_t sig_t
63 
64 inline std::vector<std::string> platform_mountlist() {
65  std::vector<std::string> result;
66  struct statfs *mntbufp;
67  int num_elems = getmntinfo(&mntbufp, MNT_NOWAIT); // modifies static memory
68  for (int i = 0; i < num_elems; ++i) {
69  result.push_back(mntbufp[i].f_mntonname);
70  }
71  return result;
72 }
73 
74 inline bool platform_umount(const char *mountpoint, const bool lazy) {
75  const int flags = lazy ? MNT_FORCE : 0;
76  int retval = unmount(mountpoint, flags);
77  return retval == 0;
78 }
79 
80 
81 inline int platform_umount_lazy(const char *mountpoint) {
82  int retval = unmount(mountpoint, MNT_FORCE);
83  return retval == 0;
84 }
85 
89 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \
90  && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
91 typedef os_unfair_lock platform_spinlock;
92 
93 inline int platform_spinlock_init(platform_spinlock *lock, int /*pshared*/) {
94  *lock = OS_UNFAIR_LOCK_INIT;
95  return 0;
96 }
97 
98 inline int platform_spinlock_destroy(platform_spinlock * /*lock*/) { return 0; }
99 
101  return os_unfair_lock_trylock(lock) ? 0 : -1;
102 }
103 
104 inline void platform_spinlock_unlock(platform_spinlock *lock) {
105  os_unfair_lock_unlock(lock);
106 }
107 
108 #else
109 typedef OSSpinLock platform_spinlock;
110 
111 inline int platform_spinlock_init(platform_spinlock *lock, int /*pshared*/) {
112  *lock = 0;
113  return 0;
114 }
115 
116 inline int platform_spinlock_destroy(platform_spinlock * /*lock*/) { return 0; }
117 
119  return OSSpinLockTry(lock) ? 0 : -1;
120 }
121 
123  OSSpinLockUnlock(lock);
124 }
125 
126 #endif
127 
131 inline thread_port_t platform_gettid() { return mach_thread_self(); }
132 
133 inline int platform_sigwait(const int signum) {
134  sigset_t sigset;
135  int retval = sigemptyset(&sigset);
136  assert(retval == 0);
137  retval = sigaddset(&sigset, signum);
138  assert(retval == 0);
139  int result;
140  retval = sigwait(&sigset, &result);
141  assert(retval == 0);
142  return result;
143 }
144 
148 inline bool platform_allow_ptrace(const pid_t pid) {
149  // No-op on Mac OS X
150  return true;
151 }
152 
156 typedef struct dirent platform_dirent64;
157 
158 inline platform_dirent64 *platform_readdir(DIR *dirp) { return readdir(dirp); }
159 
160 typedef struct stat platform_stat64;
161 
162 inline int platform_stat(const char *path, platform_stat64 *buf) {
163  return stat(path, buf);
164 }
165 
166 inline int platform_lstat(const char *path, platform_stat64 *buf) {
167  return lstat(path, buf);
168 }
169 
170 inline int platform_fstat(int filedes, platform_stat64 *buf) {
171  return fstat(filedes, buf);
172 }
173 
174 inline bool platform_getxattr(const std::string &path, const std::string &name,
175  std::string *value) {
176  int size = 0;
177  void *buffer = NULL;
178  int retval;
179  retval = getxattr(path.c_str(), name.c_str(), buffer, size, 0, 0);
180  if (retval >= 1) {
181  size = retval;
182  buffer = smalloc(size);
183  retval = getxattr(path.c_str(), name.c_str(), buffer, size, 0, 0);
184  }
185  if ((retval < 0) || (retval > size)) {
186  free(buffer);
187  return false;
188  }
189  if (retval > 0) {
190  value->assign(static_cast<const char *>(buffer), size);
191  free(buffer);
192  } else {
193  value->assign("");
194  }
195  return true;
196 }
197 
198 inline bool platform_setxattr(const std::string &path, const std::string &name,
199  const std::string &value) {
200  int retval = setxattr(path.c_str(), name.c_str(), value.c_str(), value.size(),
201  0, 0);
202  return retval == 0;
203 }
204 
205 inline bool platform_lsetxattr(const std::string &path, const std::string &name,
206  const std::string &value) {
207  int retval = setxattr(path.c_str(),
208  name.c_str(),
209  value.c_str(),
210  value.size(),
211  0,
212  XATTR_NOFOLLOW);
213  return retval == 0;
214 }
215 
216 inline ssize_t platform_lgetxattr(const char *path, const char *name,
217  void *value, size_t size) {
218  return getxattr(path, name, value, size, 0 /* position */, XATTR_NOFOLLOW);
219 }
220 
221 inline ssize_t platform_llistxattr(const char *path, char *list, size_t size) {
222  return listxattr(path, list, size, XATTR_NOFOLLOW);
223 }
224 
225 inline void platform_disable_kcache(int filedes) {
226  fcntl(filedes, F_RDAHEAD, 0);
227  fcntl(filedes, F_NOCACHE, 1);
228 }
229 
230 inline void platform_invalidate_kcache(const int fd, const off_t offset,
231  const off_t length) {
232  // NOOP
233  // TODO(rmeusel): implement
234 }
235 
236 inline ssize_t platform_readahead(int filedes) {
237  // TODO(jblomer): is there a readahead equivalent?
238  return 0;
239 }
240 
241 inline bool read_line(FILE *f, std::string *line) {
242  char *buffer_line = NULL;
243  size_t buffer_size = 0;
244  const int res = getline(&buffer_line, &buffer_size, f);
245  if (res < 0) {
246  free(buffer_line);
247  return false;
248  }
249 
250  line->clear();
251  line->assign(buffer_line);
252  free(buffer_line);
253  return true;
254 }
255 
256 inline uint64_t platform_monotonic_time() {
257  uint64_t val_abs = mach_absolute_time();
258  // Doing the conversion every time is slow but thread-safe
259  mach_timebase_info_data_t info;
260  mach_timebase_info(&info);
261  uint64_t val_ns = val_abs * (info.numer / info.denom);
262  return val_ns * 1e-9;
263 }
264 
265 inline uint64_t platform_monotonic_time_ns() {
266  uint64_t val_abs = mach_absolute_time();
267  // Doing the conversion every time is slow but thread-safe
268  mach_timebase_info_data_t info;
269  mach_timebase_info(&info);
270  uint64_t val_ns = val_abs * (info.numer / info.denom);
271  return val_ns;
272 }
273 
274 inline uint64_t platform_realtime_ns() {
275  struct timeval tv;
276  int ret = gettimeofday(&tv, NULL);
277  assert(ret == 0);
278  uint64_t time = tv.tv_sec * 1e6 + tv.tv_usec * 1e3;
279  return time;
280 }
281 
285 #define strdupa(s) \
286  strcpy(/* NOLINT(runtime/printf) */ \
287  reinterpret_cast<char *>(alloca(strlen((s)) + 1)), (s))
288 
289 inline std::string platform_libname(const std::string &base_name) {
290  return "lib" + base_name + ".dylib";
291 }
292 
293 inline std::string platform_getexepath() {
294  return std::string(_dyld_get_image_name(0));
295 }
296 
300 inline uint64_t platform_memsize() {
301  int mib[] = {CTL_HW, HW_MEMSIZE};
302  int64_t ramsize;
303  int rc;
304  size_t len;
305 
306  len = sizeof(ramsize);
307  rc = sysctl(mib, 2, &ramsize, &len, NULL, 0);
308  assert(rc == 0);
309  return ramsize;
310 }
311 
312 #ifdef CVMFS_NAMESPACE_GUARD
313 } // namespace CVMFS_NAMESPACE_GUARD
314 #endif
315 
316 inline int prctl(int, uint64_t, uint64_t, uint64_t, uint64_t) { return 0; }
317 #define PR_SET_DUMPABLE 0
318 
319 #endif // CVMFS_UTIL_PLATFORM_OSX_H_
struct stat64 platform_stat64
pthread_t platform_gettid()
int platform_spinlock_init(platform_spinlock *lock, int pshared)
assert((mem||(size==0))&&"Out Of Memory")
uint64_t platform_monotonic_time_ns()
bool platform_umount_lazy(const char *mountpoint)
bool platform_umount(const char *mountpoint, const bool lazy)
int platform_stat(const char *path, platform_stat64 *buf)
std::string platform_getexepath()
ssize_t platform_llistxattr(const char *path, char *list, size_t size)
bool platform_allow_ptrace(const pid_t pid)
int prctl(int, uint64_t, uint64_t, uint64_t, uint64_t)
Definition: platform_osx.h:316
uint64_t platform_memsize()
pthread_spinlock_t platform_spinlock
int platform_spinlock_trylock(platform_spinlock *lock)
int platform_invalidate_kcache(const int fd, const off_t offset, const off_t length)
bool platform_getxattr(const std::string &path, const std::string &name, std::string *value)
bool platform_setxattr(const std::string &path, const std::string &name, const std::string &value)
ssize_t platform_readahead(int filedes)
uint64_t platform_realtime_ns()
int platform_sigwait(const int signum)
ssize_t platform_lgetxattr(const char *path, const char *name, void *value, size_t size)
std::vector< std::string > platform_mountlist()
int platform_lstat(const char *path, platform_stat64 *buf)
uint64_t platform_monotonic_time()
std::string platform_libname(const std::string &base_name)
void platform_disable_kcache(int filedes)
void platform_spinlock_unlock(platform_spinlock *lock)
platform_dirent64 * platform_readdir(DIR *dirp)
int platform_spinlock_destroy(platform_spinlock *lock)
int platform_fstat(int filedes, platform_stat64 *buf)
static void size_t size
Definition: smalloc.h:54
bool platform_lsetxattr(const std::string &path, const std::string &name, const std::string &value)
bool read_line(FILE *f, std::string *line)
Definition: platform_osx.h:241
struct dirent64 platform_dirent64