int __darwin_execvpe(const char *file, char *const argv[], char *const envp[]) { TRACE1(file); const char* path = findInPath(file); if (!path) { errno = DARWIN_ENOENT; return -1; } if (!MachO::isMachO(path)) { int rv = execv(path, argv); errnoOut(); return rv; } else { argv = prependLoaderPath(argv, path); int rv = execvpe(g_loader_path, argv, envp); errnoOut(); delete [] argv; return rv; } }
template<typename RetVal, typename Func, typename... Params> RetVal AutoFileErrno(Func f, __darwin_FILE* file, Params... params) { RetVal rv = f(params..., file->linux_fp); if (!retvalOK(rv)) errnoOut(); return rv; }
int __darwin_stat64(const char* path, struct __darwin_stat64* mac) { TRACE2(path, mac); struct stat64 linux_buf; if (Darling::MachOMgr::instance()->hasSysRoot()) { const char* prefixed; std::string lpath = Darling::MachOMgr::instance()->sysRoot(); lpath += '/'; lpath += path; prefixed = translatePathCI(lpath.c_str()); if (::access(prefixed, F_OK) == 0) path = prefixed; else path = translatePathCI(path); } else path = translatePathCI(path); int ret = stat64(translatePathCI(path), &linux_buf); if (ret == -1) errnoOut(); convertStat64(&linux_buf, mac); return ret; }
int __darwin_pthread_mutexattr_setpshared(pthread_mutexattr_t* attr, int pshared) { pshared = TranslatePshared(pshared); int rv = pthread_mutexattr_setpshared(attr, pshared); if (rv == -1) errnoOut(); return rv; }
int __darwin_sigsuspend(const __darwin_sigset_t *mask) { sigset_t set = sigsetDarwinToLinux(mask); int rv = sigsuspend(&set); if (rv == -1) errnoOut(); return rv; }
int __darwin_pclose(__darwin_FILE* stream) { int r = pclose(stream->linux_fp); delete stream; if (r == -1) errnoOut(); return r; }
int __darwin_sigwait(const __darwin_sigset_t *set, int *sig) { sigset_t nset = sigsetDarwinToLinux(set); int rv = sigwait(&nset, sig); if (rv == -1) errnoOut(); *sig = g_sigLinuxToDarwin[*sig]; return rv; }
int __darwin_fclose(__darwin_FILE* fp) { int r = fclose(fp->linux_fp); delete fp; if (r == -1) errnoOut(); return r; }
int __darwin_stat(const char* path, struct __darwin_stat* mac) { TRACE2(path, mac); struct stat64 linux_buf; int ret = stat64(translatePathCI(path), &linux_buf); if (ret == -1) errnoOut(); convertStat(&linux_buf, mac); return ret; }
int __darwin_sigpending(__darwin_sigset_t *set) { sigset_t nset; int rv = sigpending(&nset); if (rv == -1) errnoOut(); else *set = sigsetLinuxToDarwin(&nset); return rv; }
int __darwin_fstat64(int fd, struct __darwin_stat64* mac) { TRACE2(fd, mac); struct stat64 linux_buf; int ret = fstat64(fd, &linux_buf); if (ret == -1) errnoOut(); convertStat64(&linux_buf, mac); return ret; }
int fchflags(int fd, unsigned int flags) { int rv; flags = Darling::flagsDarwinToNative(g_fflags, sizeof(g_fflags)/sizeof(g_fflags[0]), flags); rv = ioctl(fd, FS_IOC_SETFLAGS, &flags); if (rv) errnoOut(); return rv; }
int __darwin_fclose(__darwin_FILE* fp) { int r = fclose(fp->linux_fp); if (fp != __stdinp && fp != __stdoutp && fp != __stderrp) delete fp; if (r == -1) errnoOut(); return r; }
int __darwin_feof(__darwin_FILE *stream) { if (!stream) { errno = DARWIN_EINVAL; return -1; } else { int rv = feof(stream->linux_fp); if (rv == -1) errnoOut(); return rv; } }
int chflags(const char *path, unsigned int flags) { int rv; int fd = ::open(path, O_RDWR); if (fd == -1) { errnoOut(); return -1; } rv = fchflags(fd, flags); ::close(fd); return rv; }
template<typename T> int __darwin_statfsGen(const char* path, T* buf) { struct statvfs st; int rv; ::memset(buf, 0, sizeof(*buf)); rv = statvfs(path, &st); if (rv == -1) errnoOut(); else StatfsLinuxToDarwinGen(path, &st, buf); return rv; }
int __darwin_execv(const char *path, char *const argv[]) { TRACE1(path); path = translatePathCI(path); if (!MachO::isMachO(path)) { int rv = execv(path, argv); errnoOut(); return rv; } else { argv = prependLoaderPath(argv, path); int rv = execvp(g_loader_path, argv); std::cout << "Executing with loader at " << g_loader_path << std::endl; errnoOut(); delete [] argv; return rv; } }
template <typename T> int __darwin_fstatfsGen(int fd, T* out) { char buf[PATH_MAX], buf2[PATH_MAX]; sprintf(buf, "/proc/%d/fd/%d", getpid(), fd); memset(out, 0, sizeof(*out)); if (::readlink(buf, buf2, sizeof buf2) == -1) { errnoOut(); return -1; } return __darwin_statfsGen(buf2, out); }
int __darwin_fsetpos(__darwin_FILE *stream, fpos_t *pos) { if (!stream) { errno = DARWIN_EINVAL; return -1; } else { int rv = fsetpos(stream->linux_fp, pos); if (rv == -1) errnoOut(); return rv; } }
int __darwin_execv(const char *path, char *const argv[]) { TRACE1(path); path = translatePathCI(path); if (!MachO::isMachO(path)) { int rv = execv(path, argv); errnoOut(); return rv; } else { argv = Darling::prependLoaderPath(argv, path); int rv = execvp(g_dyld_path, argv); // TODO: change to execv? LOG << "Executing with loader at " << g_dyld_path << std::endl; errnoOut(); delete [] argv; return rv; } }
// TODO: check siginfo compatibility // TODO: map signal numbers for int __darwin_sigaction(int signum, const struct __darwin_sigaction* act, struct __darwin_sigaction* oldact) { std::unique_ptr<struct sigaction> nact; std::unique_ptr<struct sigaction> noldact; HandlerType oldhdl = 0; signum = g_sigDarwinToLinux[signum]; if (oldact) noldact.reset(new struct sigaction); if (act) { nact.reset(new struct sigaction); nact->sa_flags = Darling::flagsDarwinToNative(g_sigactionFlags, sizeof(g_sigactionFlags)/sizeof(g_sigactionFlags[0]), act->sa_flags); nact->sa_handler = act->xsa_handler; nact->sa_sigaction = act->xsa_sigaction; nact->sa_mask = sigsetDarwinToLinux(&act->sa_mask); oldhdl = g_darwinHandlers[signum]; // defer a user-supplied function to a wrapper that will translate the signal number if (act->xsa_handler != 0 && act->xsa_handler != SIG_IGN && act->xsa_handler != SIG_DFL) { //std::cout << "Setting GenericHandler for " << signum << std::endl; nact->sa_sigaction = GenericHandler; } g_darwinHandlers[signum] = act->xsa_sigaction; } int rv = sigaction(signum, nact.get(), noldact.get()); if (rv != -1 && noldact) { oldact->sa_flags = Darling::flagsNativeToDarwin(g_sigactionFlags, sizeof(g_sigactionFlags)/sizeof(g_sigactionFlags[0]), noldact->sa_flags); if (noldact->sa_flags & SA_SIGINFO) oldact->xsa_sigaction = noldact->sa_sigaction; else oldact->xsa_handler = noldact->sa_handler; oldact->xsa_sigaction = oldhdl; oldact->sa_mask = sigsetLinuxToDarwin(&noldact->sa_mask); } if (rv == -1) errnoOut(); return rv; }
int __darwin_pthread_mutexattr_settype(pthread_mutexattr_t* attr, int kind) { switch (kind) { case __DARWIN_PTHREAD_MUTEX_NORMAL: kind = PTHREAD_MUTEX_FAST_NP; break; case __DARWIN_PTHREAD_MUTEX_ERRORCHECK: kind = PTHREAD_MUTEX_ERRORCHECK_NP; break; case __DARWIN_PTHREAD_MUTEX_RECURSIVE: kind = PTHREAD_MUTEX_RECURSIVE_NP; break; default: fprintf(stderr, "Unknown pthread_mutexattr_settype kind: %d\n", kind); } int rv = pthread_mutexattr_settype(attr, kind); if (rv == -1) errnoOut(); return rv; }
int __darwin_sigprocmask(int how, const __darwin_sigset_t *set, __darwin_sigset_t *oldset) { std::unique_ptr<sigset_t> nset; std::unique_ptr<sigset_t> noldset; if (set) { nset.reset(new sigset_t); *nset = sigsetDarwinToLinux(set); } if (oldset) noldset.reset(new sigset_t); // -1 -> conversion from Darwin to Linux int rv = sigprocmask(how - 1, nset.get(), noldset.get()); if (rv == -1) errnoOut(); else if (oldset) *oldset = sigsetLinuxToDarwin(noldset.get()); return rv; }
int __darwin_fcntl(int fd, int cmd, void* arg) { switch (cmd) { case DARWIN_F_DUPFD: cmd = F_DUPFD; break; case DARWIN_F_DUPFD_CLOEXEC: cmd = F_DUPFD_CLOEXEC; break; case DARWIN_F_GETFD: // CLOEXEC is compatible cmd = F_GETFD; break; case DARWIN_F_SETFD: cmd = F_SETFD; break; case DARWIN_F_GETFL: { int value = fcntl(fd, F_GETFL); if (value == -1) { errnoOut(); return -1; } else { return Darling::openflagsNativeToDarwin(value); } break; } case DARWIN_F_SETFL: { int value = (int)(uintptr_t) arg; value = Darling::openflagsDarwinToNative(value); cmd = F_SETFL; arg = (void*) value; break; } case DARWIN_F_GETOWN: cmd = F_GETOWN; break; case DARWIN_F_SETOWN: cmd = F_SETOWN; break; case DARWIN_F_GETPATH: { REQUIRE_ARG_PTR(arg); char procpath[255]; int rv; sprintf(procpath, "/proc/%d/fd/%d", getpid(), fd); rv = readlink(procpath, (char*) arg, DARWIN_MAXPATHLEN); if (rv == -1) { errnoOut(); return -1; } ((char*) arg)[rv] = 0; return 0; } case DARWIN_F_PREALLOCATE: { REQUIRE_ARG_PTR(arg); __darwin_fallocate* fa = static_cast<__darwin_fallocate*>(arg); fa->allocated = 0; // We disregard fa->flags, it's not supported on Linux if (fa->mode == DARWIN_F_PEOFPOSMODE) // like SEEK_END { struct stat st; if (fstat(fd, &st) == -1) { errnoOut(); return -1; } fa->offset += st.st_size; } else if (fa->mode == DARWIN_F_VOLPOSMODE) // like SEEK_CUR { fa->offset += lseek(fd, 0, SEEK_CUR); } else { errno = DARWIN_EINVAL; return -1; } int err = posix_fallocate(fd, fa->offset, fa->length); if (err) // doesn't use errno! { errno = errnoLinuxToDarwin(err); return -1; } else { fa->allocated = fa->length; return 0; } } case DARWIN_F_SETSIZE: { uint64_t size = uint64_t(arg); // Not identical to what F_SETSIZE is supposed to do // but it's the best we can do. if (ftruncate(fd, size) == -1) { errnoOut(); return -1; } return 0; } case DARWIN_F_RDADVISE: { REQUIRE_ARG_PTR(arg); const __darwin_rdadvise* adv = static_cast<__darwin_rdadvise*>(arg); int err = posix_fadvise(fd, adv->offset, adv->count, POSIX_FADV_WILLNEED); if (err) // doesn't use errno! { errno = errnoLinuxToDarwin(err); return -1; } else return 0; } case DARWIN_F_RDAHEAD: { REQUIRE_ARG_PTR(arg); int advice = (arg) ? POSIX_FADV_NORMAL : POSIX_FADV_RANDOM; int err = posix_fadvise(fd, 0, 1, advice); // on Linux, the offset and length doesn't matter for these advices if (err) // doesn't use errno! { errno = errnoLinuxToDarwin(err); return -1; } else return 0; } case DARWIN_F_NOCACHE: { struct stat st; if (fstat(fd, &st) == -1) { errnoOut(); return -1; } // This is as close as we can get... int advice = (arg) ? POSIX_FADV_NORMAL : POSIX_FADV_DONTNEED; int err = posix_fadvise(fd, 0, 1, advice); if (err) // doesn't use errno! { errno = errnoLinuxToDarwin(err); return -1; } else return 0; } case DARWIN_F_FULLFSYNC: { if (fsync(fd) == -1) { errnoOut(); return -1; } // This is as close as we can get... // Linux 2.6.39+ if (syncfs(fd) == -1) { errnoOut(); return -1; } return 0; } case DARWIN_F_GETLK: { REQUIRE_ARG_PTR(arg); __darwin_flock* lock = static_cast<__darwin_flock*>(arg); struct flock native; memset(lock, 0, sizeof(*lock)); if (fcntl(fd, F_GETLK, &native) == -1) { errnoOut(); return -1; } lock->l_start = native.l_start; lock->l_len = native.l_len; lock->l_pid = native.l_pid; lock->l_type = native.l_type; lock->l_whence = native.l_whence; return 0; } case DARWIN_F_SETLK: case DARWIN_F_SETLKW: { REQUIRE_ARG_PTR(arg); int ncmd = (cmd == DARWIN_F_SETLK) ? F_SETLK : F_SETLKW; const __darwin_flock* lock = static_cast<__darwin_flock*>(arg); struct flock native; native.l_start = lock->l_start; native.l_len = lock->l_len; native.l_pid = lock->l_pid; native.l_type = lock->l_type; native.l_whence = lock->l_whence; return AutoErrno<int>(fcntl, fd, ncmd, &native); } case DARWIN_F_SETNOSIGPIPE: case DARWIN_F_GETNOSIGPIPE: case DARWIN_F_READBOOTSTRAP: case DARWIN_F_WRITEBOOTSTRAP: case DARWIN_F_LOG2PHYS: case DARWIN_F_LOG2PHYS_EXT: { errno = DARWIN_ENOSYS; return -1; } default: errno = DARWIN_EINVAL; return -1; } return AutoErrno<int>(fcntl, fd, cmd, arg); }