/* Copyright 2017-present Renesas Electronics Corporation and other contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "./posix4_target.h"

inline const char* safe_str(const char* in) { return in ? in : "<null>"; }

char* P4(getcwd)(char* buf, P4(size_t) size)
{
	TRACE(ENTER "getcwd(buf=%p, size=%u)", buf, size);
	char* rc = posix::getcwd( buf, size );
	TRACE(LEAVE "getcwd(buf=%p, size=%u) = %s(errno:%d)", buf, size, safe_str(rc), errno);
	return rc;
}

int P4(chdir)(const char* path)
{
	TRACE(ENTER "chdir(path=%s)", safe_str(path));
	int rc = posix::chdir( path );
	TRACE(LEAVE "chdir(path=%s) = %d(errno:%d)", safe_str(path), rc, errno);
	return rc;
}

int P4(fdatasync)(int fd)
{
	TRACE(ENTER "fdatasync(fd=%d)", fd);
	int rc = posix::fdatasync( fd );
	TRACE(LEAVE "fdatasync(fd=%d) = %d(errno:%d)", fd, rc, errno);
	return rc;
}

int P4(fsync)(int fd)
{
	TRACE(ENTER "fsync(fd=%d)", fd);
	int rc = posix::fsync( fd );
	TRACE(LEAVE "fsync(fd=%d) = %d(errno:%d)", fd, rc, errno);
	return rc;
}

int P4(ftruncate)(int fd, P4(off_t) length)
{
	TRACE(ENTER "ftruncate(fd=%d, length=%ld)", fd, length);
	int rc = posix::ftruncate( fd, length );
	TRACE(LEAVE "ftruncate(fd=%d, length=%ld) = %d(errno:%d)", fd, length, rc, errno);
	return rc;
}

int P4(scandir)(const char* dirp, struct P4(dirent)*** namelist, int (*filter)(const struct P4(dirent)*), int (*compar)(const struct P4(dirent)**, const struct P4(dirent)**))
{
	TRACE(ENTER "scandir(dirp=%s, namelist=%p, filter=%p, compar=%p)", safe_str(dirp), namelist, filter, compar);
	int rc = posix::scandir( dirp, namelist, filter, compar );
	TRACE(LEAVE "scandir(dirp=%s, namelist=%p, filter=%p, compar=%p) = %d(errno:%d)", safe_str(dirp), namelist, filter, compar, rc, errno);
	return rc;
}

int P4(utime)(const char* filename, const struct P4(utimbuf)* times)
{
	TRACE(ENTER "utime(filename=%s, times=%p)", safe_str(filename), times);
	int rc = posix::utime( filename, times );
	TRACE(LEAVE "utime(filename=%s, times=%p) = %d(errno:%d)", safe_str(filename), times, rc, errno);
	return rc;
}

int P4(utimes)(const char* filename, const struct P4(timeval) times[2])
{
	TRACE(ENTER "utimes(filename=%s, times[2]=maybe_later)", safe_str(filename));
	int rc = posix::utimes( filename, times );
	TRACE(LEAVE "utimes(filename=%s, times[2]=maybe_later) = %d(errno:%d)", safe_str(filename), rc, errno);
	return rc;
}

P4(ssize_t) P4(pread)(int fd, void* buf, P4(size_t) count, P4(off_t) offset)
{
	TRACE(ENTER "pread(fd=%d, buf=%p, count=%d, offset=%ld)", fd, buf, count, offset);
	P4(ssize_t) rc = posix::pread( fd, buf, count, offset );
	TRACE(LEAVE "pread(fd=%d, buf=%p, count=%d, offset=%ld) = %d(errno:%d)", fd, buf, count, offset, rc, errno);
	return rc;
}

P4(ssize_t) P4(pwrite)(int fd, const void* buf, P4(size_t) count, P4(off_t) offset)
{
	TRACE(ENTER "pwrite(fd=%d, buf=%p, count=%d, offset=%ld)", fd, buf, count, offset);
	P4(ssize_t) rc = posix::pwrite( fd, buf, count, offset );
	TRACE(LEAVE "pwrite(fd=%d, buf=%p, count=%d, offset=%ld) = %d(errno:%d)", fd, buf, count, offset, rc, errno);
	return rc;
}

P4(ssize_t) P4(readv)(int fd, const struct P4(iovec)* iov, int iovcnt)
{
	TRACE(ENTER "readv(fd=%d, iov=%p, iovcnt=%d)", fd, iov, iovcnt);
	P4(ssize_t) rc = posix::readv( fd, iov, iovcnt );
	TRACE(LEAVE "readv(fd=%d, iov=%p, iovcnt=%d) = %d(errno:%d)", fd, iov, iovcnt, rc, errno);
	return rc;
}

P4(ssize_t) P4(writev)(int fd, const struct P4(iovec)* iov, int iovcnt)
{
	TRACE(ENTER "writev(fd=%d, iov=%p, iovcnt=%d)", fd, iov, iovcnt);
	P4(ssize_t) rc = posix::writev( fd, iov, iovcnt );
	TRACE(LEAVE "writev(fd=%d, iov=%p, iovcnt=%d) = %d(errno:%d)", fd, iov, iovcnt, rc, errno);
	return rc;
}

int P4(utimensat)(int dirfd, const char* pathname, const struct P4(timespec) times[2], int flags)
{
	TRACE(ENTER "utimensat(dirfd=%d, pathname=%s, times=%p, flags=%d)", dirfd, safe_str(pathname), times, flags);
	int rc = posix::utimensat( dirfd, pathname, times, flags );
	TRACE(LEAVE "utimensat(dirfd=%d, pathname=%s, times=%p, flags=%d) = %d(errno:%d)", dirfd, safe_str(pathname), times, flags, rc, errno);
	return rc;
}

int P4(clock_getres)(P4(clockid_t) clk_id, struct P4(timespec)* res)
{
	TRACE(ENTER "clock_getres(clk_id=%lu, res=%p)", clk_id, res);
	int rc = posix::clock::getres( clk_id, res );
	TRACE(LEAVE "clock_getres(clk_id=%lu, res={%ld.%09ld}) = %d(errno:%d)", clk_id, res->tv_sec, res->tv_nsec, rc, errno);
	return rc;
}

int P4(clock_gettime)(P4(clockid_t) clk_id, struct P4(timespec)* tp)
{
	TRACE(ENTER "clock_gettime(clk_id=%lu, tp=%p)", clk_id, tp);
	int rc = posix::clock::gettime( clk_id, tp );
	TRACE(LEAVE "clock_gettime(clk_id=%lu, tp={%ld.%09ld}) = %d(errno:%d)", clk_id, tp->tv_sec, tp->tv_nsec, rc, errno);
	return rc;
}

int P4(pthread_create)(P4(pthread_t)* thread, P4(pthread_attr_t)* attr, void* (*start_routine)(void*), void* arg)
{
	TRACE(ENTER "pthread_create(thread=%p, attr=%p, start_routine=%p, arg=%p)", thread, attr, start_routine, arg);
	int rc = posix::pthread::create( thread, attr, start_routine, arg );
	TRACE(LEAVE "pthread_create(thread={%p}, attr=%p, start_routine=%p, arg=%p) = %d", *thread, attr, start_routine, arg, rc);
	return rc;
}

int P4(pthread_join)(P4(pthread_t) thread, void** retval)
{
	TRACE(ENTER "pthread_join(thread=%p, retval=%p)", thread, retval);
	int rc = posix::pthread::join( thread, retval );
	TRACE(LEAVE "pthread_join(thread=%p, retval=%p) = %d", thread, retval, rc);
	return rc;
}

int P4(pthread_once)(P4(pthread_once_t)* once_control, void (*init_routine)(void))
{
	TRACE(ENTER "pthread_once(once_control={0x%08X}, init_routine=%p)", *once_control, init_routine);
	int rc = posix::pthread::once( once_control, init_routine );
	TRACE(LEAVE "pthread_once(once_control={0x%08X}, init_routine=%p) = %d", *once_control, init_routine, rc);
	return rc;
}

int P4(pthread_sigmask)(int how, const P4(sigset_t)* set, P4(sigset_t)* oldset)
{
	TRACE(ENTER "pthread_sigmask(how=%d, set=%p, oldset=%p)", how, set, oldset);
	int rc = posix::pthread::sigmask( how, set, oldset );
	TRACE(LEAVE "pthread_sigmask(how=%d, set=%p, oldset=%p) = %d", how, set, oldset, rc);
	return rc;
}

int P4(pthread_attr_destroy)(P4(pthread_attr_t)* attr)
{
	TRACE(ENTER "pthread_attr_destroy(attr=%p)", attr);
	int rc = posix::pthread::attr::destroy( attr );
	TRACE(LEAVE "pthread_attr_destroy(attr=%p) = %d", attr, rc);
	return rc;
}

int P4(pthread_cond_destroy)(P4(pthread_cond_t)* cond)
{
	TRACE(ENTER "pthread_cond_destroy(cond=%p)", cond);
	int rc = posix::pthread::cond::destroy( cond );
	TRACE(LEAVE "pthread_cond_destroy(cond=%p) = %d", cond, rc);
	return rc;
}

int P4(pthread_cond_init)(P4(pthread_cond_t)* cond, P4(pthread_condattr_t)* cond_attr)
{
	TRACE(ENTER "pthread_cond_init(cond=%p, cond_attr=%p)", cond, cond_attr);
	int rc = posix::pthread::cond::init( cond, cond_attr );
	TRACE(LEAVE "pthread_cond_init(cond=%p, cond_attr=%p) = %d", cond, cond_attr, rc);
	return rc;
}

int P4(pthread_cond_signal)(P4(pthread_cond_t)* cond)
{
	TRACE(ENTER "pthread_cond_signal(cond=%p)", cond);
	int rc = posix::pthread::cond::signal( cond );
	TRACE(LEAVE "pthread_cond_signal(cond=%p) = %d", cond, rc);
	return rc;
}

int P4(pthread_cond_wait)(P4(pthread_cond_t)* cond, P4(pthread_mutex_t)* mutex)
{
	TRACE(ENTER "pthread_cond_wait(cond=%p, mutex=%p)", cond, mutex);
	int rc = posix::pthread::cond::wait( cond, mutex );
	TRACE(LEAVE "pthread_cond_wait(cond=%p, mutex=%p) = %d", cond, mutex, rc);
	return rc;
}

int P4(pthread_condattr_destroy)(P4(pthread_condattr_t)* attr)
{
	TRACE(ENTER "pthread_condattr_destroy(attr=%p)", attr);
	int rc = posix::pthread::condattr::destroy( attr );
	TRACE(LEAVE "pthread_condattr_destroy(attr=%p) = %d", attr, rc);
	return rc;
}

int P4(pthread_condattr_init)(P4(pthread_condattr_t)* attr)
{
	TRACE(ENTER "pthread_condattr_init(attr=%p)", attr);
	int rc = posix::pthread::condattr::init( attr );
	TRACE(LEAVE "pthread_condattr_init(attr=%p) = %d", attr, rc);
	return rc;
}

int P4(pthread_condattr_setclock)(P4(pthread_condattr_t)* attr, P4(clockid_t) clock_id)
{
	TRACE(ENTER "pthread_condattr_setclock(attr=%p, clock_id=%lu)", attr, clock_id);
	int rc = posix::pthread::condattr::setclock( attr, clock_id );
	TRACE(LEAVE "pthread_condattr_setclock(attr=%p, clock_id=%lu) = %d", attr, clock_id, rc);
	return rc;
}

int P4(pthread_mutex_destroy)(P4(pthread_mutex_t)* mutex)
{
	TRACE(ENTER "pthread_mutex_destroy(mutex=%p)", mutex);
	int rc = posix::pthread::mutex::destroy( mutex );
	TRACE(LEAVE "pthread_mutex_destroy(mutex=%p) = %d", mutex, rc);
	return rc;
}

int P4(pthread_mutex_init)(P4(pthread_mutex_t)* mutex, const P4(pthread_mutexattr_t)* mutexattr)
{
	TRACE(ENTER "pthread_mutex_init(mutex=%p, mutexattr=%p)", mutex, mutexattr);
	int rc = posix::pthread::mutex::init( mutex, mutexattr );
	TRACE(LEAVE "pthread_mutex_init(mutex=%p, mutexattr=%p) = %d", mutex, mutexattr, rc);
	return rc;
}

int P4(pthread_mutex_lock)(P4(pthread_mutex_t)* mutex)
{
	TRACE(ENTER "pthread_mutex_lock(mutex=%p)", mutex);
	int rc = posix::pthread::mutex::lock( mutex );
	TRACE(LEAVE "pthread_mutex_lock(mutex=%p) = %d", mutex, rc);
	return rc;
}

int P4(pthread_mutex_unlock)(P4(pthread_mutex_t)* mutex)
{
	TRACE(ENTER "pthread_mutex_unlock(mutex=%p)", mutex);
	int rc = posix::pthread::mutex::unlock( mutex );
	TRACE(LEAVE "pthread_mutex_unlock(mutex=%p) = %d", mutex, rc);
	return rc;
}

int P4(pthread_rwlock_destroy)(P4(pthread_rwlock_t)* rwlock)
{
	TRACE(ENTER "pthread_rwlock_destroy(rwlock=%p)", rwlock);
	int rc = posix::pthread::rwlock::destroy( rwlock );
	TRACE(LEAVE "pthread_rwlock_destroy(rwlock=%p) = %d", rwlock, rc);
	return rc;
}

int P4(pthread_rwlock_init)(P4(pthread_rwlock_t)* rwlock, const P4(pthread_rwlockattr_t)* attr)
{
	TRACE(ENTER "pthread_rwlock_init(rwlock=%p, attr=%p)", rwlock, attr);
	int rc = posix::pthread::rwlock::init( rwlock, attr );
	TRACE(LEAVE "pthread_rwlock_init(rwlock=%p, attr=%p) = %d", rwlock, attr, rc);
	return rc;
}

int P4(pthread_rwlock_rdlock)(P4(pthread_rwlock_t)* rwlock)
{
	TRACE(ENTER "pthread_rwlock_rdlock(rwlock=%p)", rwlock);
	int rc = posix::pthread::rwlock::rdlock( rwlock );
	TRACE(LEAVE "pthread_rwlock_rdlock(rwlock=%p) = %d", rwlock, rc);
	return rc;
}

int P4(pthread_rwlock_unlock)(P4(pthread_rwlock_t)* rwlock)
{
	TRACE(ENTER "pthread_rwlock_unlock(rwlock=%p)", rwlock);
	int rc = posix::pthread::rwlock::unlock( rwlock );
	TRACE(LEAVE "pthread_rwlock_unlock(rwlock=%p) = %d", rwlock, rc);
	return rc;
}

struct P4(cmsghdr)* P4(cmsg_nxthdr)(struct P4(msghdr)* mhdr, struct P4(cmsghdr)* cmsg)
{
#define OFFSET(addr, bytes)	((void*)((char*)addr + bytes))
	if((P4(size_t))cmsg->cmsg_len < sizeof( struct P4(cmsghdr) )) {
		return 0;
	}
	cmsg = (struct P4(cmsghdr)*)OFFSET( cmsg, CMSG_ALIGN( cmsg->cmsg_len ) );
	if( cmsg + 1 > OFFSET( mhdr->msg_control, mhdr->msg_controllen ) ) {
		return 0;
	}
	if( OFFSET( cmsg, CMSG_ALIGN( cmsg->cmsg_len ) ) > OFFSET( mhdr->msg_control, mhdr->msg_controllen ) ) {
		return 0;
	}
#undef OFFSET
	return cmsg;
}

int P4(accept)(int sockfd, struct P4(sockaddr)* addr, P4(socklen_t)* addrlen)
{
	TRACE(ENTER "accept(sockfd=%d, addr=%p, addrlen=%p)", sockfd, addr, addrlen);
	int rc = posix::sock::accept( sockfd, addr, addrlen );
	TRACE(LEAVE "accept(sockfd=%d, addr=%p, addrlen=%p) = %d(errno:%d)", sockfd, addr, addrlen, rc, errno);
	return rc;
}

int P4(bind)(int sockfd, const struct P4(sockaddr)* addr, P4(socklen_t) addrlen)
{
	TRACE(ENTER "bind(sockfd=%d, addr=%p, addrlen=%lu)", sockfd, addr, addrlen);
	int rc = posix::sock::bind( sockfd, addr, addrlen );
	TRACE(LEAVE "bind(sockfd=%d, addr=%p, addrlen=%lu) = %d(errno:%d)", sockfd, addr, addrlen, rc, errno);
	return rc;
}

int P4(connect)(int sockfd, const struct P4(sockaddr)* addr, P4(socklen_t) addrlen)
{
	TRACE(ENTER "connect(sockfd=%d, addr=%p, addrlen=%lu)", sockfd, addr, addrlen);
	int rc = posix::sock::connect( sockfd, addr, addrlen );
	TRACE(LEAVE "connect(sockfd=%d, addr=%p, addrlen=%lu) = %d(errno:%d)", sockfd, addr, addrlen, rc, errno);
	return rc;
}

void P4(freeaddrinfo)(struct P4(addrinfo)* res)
{
	TRACE(ENTER "freeaddrinfo(res=%p)", res);
	posix::sock::freeaddrinfo( res );
	TRACE(LEAVE "freeaddrinfo(res=%p)", res);
}

int P4(getaddrinfo)(const char* node, const char* service, const struct P4(addrinfo)* hints, struct P4(addrinfo)** res)
{
	TRACE(ENTER "getaddrinfo(node={%s}, service={%s}, hints=%p, res=%p)", safe_str(node), safe_str(service), hints, res);
	int rc = posix::sock::getaddrinfo( node, service, hints, res );
	TRACE(LEAVE "getaddrinfo(node={%s}, service={%s}, hints=%p, res=%p) = %d", safe_str(node), safe_str(service), hints, res, rc);
	return rc;
}

int P4(getsockname)(int sockfd, struct P4(sockaddr)* addr, P4(socklen_t)* addrlen)
{
	TRACE(ENTER "getsockname(sockfd=%d, addr=%p, addrlen={%ld})", sockfd, addr, *addrlen);
	int rc = posix::sock::getsockname( sockfd, addr, addrlen );
	TRACE(LEAVE "getsockname(sockfd=%d, addr=%p, addrlen={%ld}) = %d(errno:%d)", sockfd, addr, *addrlen, rc, errno);
	return rc;
}

int P4(getsockopt)(int sockfd, int level, int optname, void* optval, P4(socklen_t)* optlen)
{
	TRACE(ENTER "getsockopt(sockfd=%d, level=%d, optname=%d, optval=%p, optlen=%p)", sockfd, level, optname, optval, optlen);
	uint32_t rc = posix::sock::getsockopt( sockfd, level, optname, optval, optlen );
	TRACE(LEAVE "getsockopt(sockfd=%d, level=%d, optname=%d, optval=%p, optlen=%p) = %lu(errno:%d)", sockfd, level, optname, optval, optlen, rc, errno);
	return rc;
}

uint32_t P4(htonl)(uint32_t hostlong)
{
	TRACE(ENTER "htonl(hostlong=0x%08lX)", hostlong);
	uint32_t rc = posix::sock::htonl( hostlong );
	TRACE(LEAVE "htonl(hostlong=0x%08lX) = 0x%08lX", hostlong, rc);
	return rc;
}

uint16_t P4(htons)(uint16_t hostshort)
{
	TRACE(ENTER "htons(hostshort=0x%04X)", hostshort);
	uint16_t rc = posix::sock::htons( hostshort );
	TRACE(LEAVE "htons(hostshort=0x%04X) = 0x%04X", hostshort, rc);
	return rc;
}

unsigned int P4(if_nametoindex)(const char* ifname)
{
	TRACE(ENTER "if_nametoindex(ifname={%s})", safe_str(ifname));
	unsigned int rc = posix::sock::if_nametoindex( ifname );
	TRACE(LEAVE "if_nametoindex(ifname={%s}) = %u(errno:%d)", safe_str(ifname), rc, errno);
	return rc;
}

int P4(listen)(int sockfd, int backlog)
{
	TRACE(ENTER "listen(sockfd=%d, backlog=%d)", sockfd, backlog);
	int rc = posix::sock::listen( sockfd, backlog );
	TRACE(LEAVE "listen(sockfd=%d, backlog=%d) = %d(errno:%d)", sockfd, backlog, rc, errno);
	return rc;
}

uint16_t P4(ntohs)(uint16_t netshort)
{
	TRACE(ENTER "ntohs(netshort=0x%04X)", netshort);
	uint16_t rc = posix::sock::ntohs( netshort );
	TRACE(LEAVE "ntohs(netshort=0x%04X) = 0x%04X", netshort, rc);
	return rc;
}

P4(ssize_t) P4(recvmsg)(int sockfd, struct P4(msghdr)* msg, int flags)
{
	TRACE(ENTER "recvmsg(sockfd=%d, msg=%p, flags=%d)", sockfd, msg, flags);
	P4(ssize_t) rc = posix::sock::recvmsg( sockfd, msg, flags );
	TRACE(LEAVE "recvmsg(sockfd=%d, msg=%p, flags=%d) = %d(errno:%d)", sockfd, msg, flags, rc, errno);
	return rc;
}

P4(ssize_t) P4(sendmsg)(int sockfd, const struct P4(msghdr)* msg, int flags)
{
	TRACE(ENTER "sendmsg(sockfd=%d, msg=%p, flags=%d)", sockfd, msg, flags);
	P4(ssize_t) rc = posix::sock::sendmsg( sockfd, msg, flags );
	TRACE(LEAVE "sendmsg(sockfd=%d, msg=%p, flags=%d) = %d(errno:%d)", sockfd, msg, flags, rc, errno);
	return rc;
}

int P4(setsockopt)(int sockfd, int level, int optname, const void* optval, P4(socklen_t) optlen)
{
	TRACE(ENTER "setsockopt(sockfd=%d, level=%d, optname=%d, optval=%p, optlen=%lu)", sockfd, level, optname, optval, optlen);
	int rc = posix::sock::setsockopt( sockfd, level, optname, optval, optlen );
	TRACE(LEAVE "setsockopt(sockfd=%d, level=%d, optname=%d, optval=%p, optlen=%lu) = %d(errno:%d)", sockfd, level, optname, optval, optlen, rc, errno);
	return rc;
}

int P4(shutdown)(int sockfd, int how)
{
	TRACE(ENTER "shutdown(sockfd=%d, how=%d)", sockfd, how);
	int rc = posix::sock::shutdown( sockfd, how );
	TRACE(LEAVE "shutdown(sockfd=%d, how=%d) = %d(errno:%d)", sockfd, how, rc, errno);
	return rc;
}

int P4(socket)(int domain, int type, int protocol)
{
	TRACE(ENTER "socket(domain=%d, type=%d, protocol=%d)", domain, type, protocol);
	int rc = posix::sock::socket( domain, type, protocol );
	TRACE(LEAVE "socket(domain=%d, type=%d, protocol=%d) = %d(errno:%d)", domain, type, protocol, rc, errno);
	return rc;
}

int P4(nanosleep)(const struct P4(timespec)* req, struct P4(timespec)* rem)
{
	return posix::sys::nanosleep( req, rem );
}

int P4(pipe)(int pipefd[2])
{
	TRACE(ENTER "pipe(pipefd[2]=[%d,%d])", pipefd[0], pipefd[1]);
	int rc = posix::sys::pipe( pipefd );
	TRACE(LEAVE "pipe(pipefd[2]=[%d,%d]) = %d(errno:%d)", pipefd[0], pipefd[1], rc, errno);
	return rc;
}

long P4(sysconf)(int name)
{
	TRACE(ENTER "sysconf(name=%d)", name);
	long rc = posix::sys::sysconf( name );
	TRACE(LEAVE "sysconf(name=%d) = %ld(errno:%d)", name, rc, errno);
	return rc;
}


P4(ssize_t) P4(preadv)(int fd, const struct P4(iovec)* iov, int iovcnt, P4(off_t) offset)
{
	TRACE(ENTER "preadv(fd=%d, iov=%p, iovcnt=%d, offset=%ld)", fd, iov, iovcnt, offset);
	P4(ssize_t) rc = linux::preadv( fd, iov, iovcnt, offset );
	TRACE(LEAVE "preadv(fd=%d, iov=%p, iovcnt=%d, offset=%ld) = %d(errno:%d)", fd, iov, iovcnt, offset, rc, errno);
	return rc;
}

P4(ssize_t) P4(pwritev)(int fd, const struct P4(iovec)* iov, int iovcnt, P4(off_t) offset)
{
	TRACE(ENTER "pwritev(fd=%d, iov=%p, iovcnt=%d, offset=%ld)", fd, iov, iovcnt, offset);
	P4(ssize_t) rc = linux::pwritev( fd, iov, iovcnt, offset );
	TRACE(LEAVE "pwritev(fd=%d, iov=%p, iovcnt=%d, offset=%ld) = %d(errno:%d)", fd, iov, iovcnt, offset, rc, errno);
	return rc;
}

int P4(epoll_create)(int size)
{
	TRACE(ENTER "epoll_create(size=%d)", size);
	int rc = linux::epoll::create( size );
	TRACE(LEAVE "epoll_create(size=%d) = %d(errno:%d)", size, rc, errno);
	return rc;
}

int P4(epoll_create1)(int flags)
{
	TRACE(ENTER "epoll_create1(flags=0x%08X)", flags);
	int rc = linux::epoll::create1( flags );
	TRACE(LEAVE "epoll_create1(flags=0x%08X) = %d(errno:%d)", flags, rc, errno);
	return rc;
}

int P4(epoll_ctl)(int epfd, int op, int fd, struct P4(poll_event)* event)
{
	TRACE(ENTER "epoll_ctl(epfd=%d, op=%d, fd=%d, event=%p{0x%08lX})", epfd, op, fd, event, event->events);
	int rc = linux::epoll::ctl( epfd, op, fd, event );
	TRACE(LEAVE "epoll_ctl(epfd=%d, op=%d, fd=%d, event=%p) = %d(errno:%d)", epfd, op, fd, event, rc, errno);
	return rc;
}

int P4(epoll_pwait)(int epfd, struct P4(poll_event)* events, int maxevents, int timeout, const P4(sigset_t)* sigmask)
{
	TRACE(ENTER "epoll_pwait(epfd=%d, events=%p, maxevents=%d, timeout=%d, sigmask=%p)", epfd, events, maxevents, timeout, sigmask);
	int rc = linux::epoll::pwait( epfd, events, maxevents, timeout, sigmask );
	TRACE(LEAVE "epoll_pwait(epfd=%d, events=%p, maxevents=%d, timeout=%d, sigmask=%p) = %d(errno:%d)", epfd, events, maxevents, timeout, sigmask, rc, errno);
	return rc;
}

int P4(epoll_wait)(int epfd, struct P4(poll_event)* events, int maxevents, int timeout)
{
	TRACE(ENTER "epoll_wait(epfd=%d, events=%p, maxevents=%d, timeout=%d)", epfd, events, maxevents, timeout);
	int rc = linux::epoll::wait( epfd, events, maxevents, timeout );
	TRACE(LEAVE "epoll_wait(epfd=%d, events=%p, maxevents=%d, timeout=%d) = %d(errno:%d)", epfd, events, maxevents, timeout, rc, errno);
	return rc;
}

int P4(eventfd)(unsigned int initval, int flags)
{
	TRACE(ENTER "eventfd(initval=%u, flags=%d)", initval, flags);
	int rc = linux::epoll::eventfd( initval, flags );
	TRACE(LEAVE "eventfd(initval=%u, flags=%d) = %d(errno:%d)", initval, flags, rc, errno);
	return rc;
}

int P4(eventfd2)(unsigned int initval, int flags)
{
	TRACE(ENTER "eventfd2(initval=%u, flags=0x%08X)", initval, flags);
	int rc = linux::epoll::eventfd2( initval, flags );
	TRACE(LEAVE "eventfd2(initval=%u, flags=0x%08X) = %d(errno:%d)", initval, flags, rc, errno);
	return rc;
}

int P4(accept4)(int fd, struct P4(sockaddr)* addr, P4(socklen_t)* addr_len, int flags)
{
	TRACE(ENTER "accept4(fd=%d, addr=%p, addr_len=%p, flags=%d)", fd, addr, addr_len, flags);
	int rc = linux::sock::accept4( fd, addr, addr_len, flags );
	TRACE(LEAVE "accept4(fd=%d, addr=%p, addr_len=%p, flags=%d) = %d(errno:%d)", fd, addr, addr_len, flags, rc, errno);
	return rc;
}

int P4(socketcall)(int call, unsigned long* args)
{
	TRACE(ENTER "socketcall(call=%d, args=%p)", call, args);
	int rc = linux::sock::socketcall( call, args );
	TRACE(LEAVE "socketcall(call=%d, args=%p) = %d(errno:%d)", call, args, rc, errno);
	return rc;
}

int P4(ioctl)(int fd, unsigned long request, ...)
{
	TRACE(ENTER "ioctl(fd=%d, request=0x%08lX, ...)", fd, request);
	va_list args;
	va_start( args, request );
	int rc = linux::sys::ioctl( fd, request, args );
	va_end( args );
	TRACE(LEAVE "ioctl(fd=%d, request=0x%08lX, ...) = %d(errno:%d)", fd, request, rc, errno);
	return rc;
}

long P4(syscall)(long number, ...)
{
	TRACE(ENTER "syscall(number=%ld, ...)", number);
	va_list args;
	va_start( args, number );
	long rc = linux::sys::syscall( number, args );
	va_end( args );
	TRACE(LEAVE "syscall(number=%ld, ...) = %ld(errno:%d)", number, rc, errno);
	return rc;
}

int P4(pipe2)(int pipefd[2], int flags)
{
	TRACE(ENTER "pipe2(pipefd[]=[%d, %d], flags=%d)", pipefd[0], pipefd[1], flags);
	int rc = linux::sys::pipe2( pipefd, flags );
	TRACE(LEAVE "pipe2(pipefd[]=[%d, %d], flags=%d) = %d(errno:%d)", pipefd[0], pipefd[1], flags, rc, errno);
	return rc;
}

void* P4(dlopen)(const char* filename, int flag)
{
	TRACE(ENTER "dlopen(filename=%s, flag=%d)", safe_str(filename), flag);
	void* rc = linux::sys::dlopen( filename, flag );
	TRACE(ENTER "dlopen(filename=%s, flag=%d) = %p", safe_str(filename), flag, rc);
	return rc;
}

void* P4(dlsym)(void* handle, char* symbol)
{
	TRACE(ENTER "dlsym(handle=%p, symbol=%s)", handle, safe_str(symbol));
	void* rc = linux::sys::dlsym( handle, symbol );
	TRACE(ENTER "dlsym(handle=%p, symbol=%s) = %p", handle, safe_str(symbol), rc);
	return rc;
}

int P4(dlclose)(void* handle)
{
	TRACE(ENTER "dlclose(handle=%p)", handle);
	int rc = linux::sys::dlclose( handle );
	TRACE(ENTER "dlclose(handle=%p) = %d", handle, rc);
	return rc;
}

char** P4(backtrace_symbols)(void*const* buffer, int size)
{
	TRACE(ENTER "backtrace_symbols(buffer=%p, size=%d)", buffer, size);
	char** rc = linux::debug::backtrace_symbols( buffer, size );
	TRACE(LEAVE "backtrace_symbols(buffer=%p, size=%d) = %p", buffer, size, rc);
	return rc;
}

int P4(backtrace)(void** buffer, int size)
{
	TRACE(ENTER "backtrace(buffer=%p, size=%d)", buffer, size);
	int rc = linux::debug::backtrace( buffer, size );
	TRACE(LEAVE "backtrace(buffer=%p, size=%d) = %d", buffer, size, rc);
	return rc;
}


void P4(abort)(void)
{
	TRACE(INFO "abort called from [%p]", CALLED_FROM);
	overridden::abort();
}

int P4(gettimeofday)(struct P4(timeval)* tv, void* tz)
{
	TRACE(ENTER "overridden_gettimeofday(tv=%d, tz=%p)", tv, tz);
	int rc = overridden::gettimeofday( tv, tz );
	TRACE(LEAVE "overridden_gettimeofday(tv=%d, tz=%p) = %d(errno:%d)", tv, tz, rc, errno);
	return rc;
}

P4(ssize_t) P4(read)(int fd, void* buf, P4(size_t) count)
{
	TRACE(ENTER "overridden_read(fd=%d, buf=%p, count=%u)", fd, buf, count);
	P4(ssize_t) rc = overridden::read( fd, buf, count );
	TRACE(LEAVE "overridden_read(fd=%d, buf=%p, count=%u) = %d(errno:%d)", fd, buf, count, rc, errno);
	return rc;
}

P4(ssize_t) P4(write)(int fd, const void* buf, P4(size_t) count)
{
	TRACE(ENTER "overridden_write(fd=%d, buf=%p, count=%u)", fd, buf, count);
	P4(ssize_t) rc = overridden::write( fd, buf, count );
	TRACE(LEAVE "overridden_write(fd=%d, buf=%p, count=%u) = %d(errno:%d)", fd, buf, count, rc, errno);
	return rc;
}

int P4(open)(const char* pathname, ...)
{
	TRACE(ENTER "overridden_open(pathname=%s, ...)", safe_str(pathname));
	va_list args;
	va_start( args, pathname );
	int rc = overridden::open( pathname, args );
	va_end( args );
	TRACE(LEAVE "overridden_open(pathname=%s, ...) = %d(errno:%d)", safe_str(pathname), rc, errno);
	return rc;
}

int P4(close)(int fd)
{
	TRACE(ENTER "overridden_close(fd=%d)", fd);
	int rc = overridden::close( fd );
	TRACE(LEAVE "overridden_close(fd=%d) = %d(errno:%d)", fd, rc, errno);
	return rc;
}

int P4(unlink)(const char* pathname)
{
	TRACE(ENTER "overridden_unlink(pathname=%s)", safe_str(pathname));
	int rc = overridden::unlink( pathname );
	TRACE(LEAVE "overridden_unlink(pathname=%s) = %d(errno:%d)", safe_str(pathname), rc, errno);
	return rc;
}

int P4(mkdir)(const char* pathname, P4(mode_t) mode)
{
	TRACE(ENTER "overridden_mkdir(pathname=%s, mode=0x%04X)", safe_str(pathname), mode);
	int rc = overridden::mkdir( pathname, mode );
	TRACE(LEAVE "overridden_mkdir(pathname=%s, mode=0x%04X) = %d(errno:%d)", safe_str(pathname), mode, rc, errno);
	return rc;
}

int P4(rmdir)(const char* pathname)
{
	TRACE(ENTER "overridden_rmdir(pathname=%s)", safe_str(pathname));
	int rc = overridden::rmdir( pathname );
	TRACE(LEAVE "overridden_rmdir(pathname=%s) = %d(errno:%d)", safe_str(pathname), rc, errno);
	return rc;
}

int P4(stat)(const char* pathname, P4(stat_t)* buf)
{
	TRACE(ENTER "overridden_stat(pathname=%s, buf=%p)", safe_str(pathname), buf);
	int rc = overridden::stat( pathname, buf );
	TRACE(LEAVE "overridden_stat(pathname=%s, buf=%p) = %d(errno:%d)", safe_str(pathname), buf, rc, errno);
	return rc;
}

int P4(fstat)(int fd, P4(stat_t)* buf)
{
	TRACE(ENTER "overridden_fstat(fd=%d, buf=%p)", fd, buf);
	int rc = overridden::fstat( fd, buf );
	TRACE(LEAVE "overridden_fstat(fd=%d, buf=%p) = %d(errno:%d)", fd, buf, rc, errno);
	return rc;
}


char* P4(nic_enumerate)(void)
{
	TRACE(ENTER "nic_enumerate()");
	char* rc = nic::enumerate();
	TRACE(LEAVE "nic_enumerate() = {%s}", safe_str(rc));
	return rc;
}

int P4(nic_ifup)(const char* nic, const char* params)
{
	TRACE(ENTER "nic_ifup(nic={%s}, params={%s})", safe_str(nic), safe_str(params));
	int rc = nic::ifup( nic, params );
	TRACE(LEAVE "nic_ifup(nic={%s}, params={%s}) = %d", safe_str(nic), safe_str(params), rc);
	return rc;
}

int P4(nic_ifdown)(const char* nic)
{
	TRACE(ENTER "nic_ifdown(nic={%s})", safe_str(nic));
	int rc = nic::ifdown( nic );
	TRACE(LEAVE "nic_ifdown(nic={%s}) = %d", safe_str(nic), rc);
	return rc;
}

char* P4(nic_ifconfig)(const char* nic)
{
	TRACE(ENTER "nic_ifconfig(nic={%s})", safe_str(nic));
	char* rc = nic::ifconfig( nic );
	TRACE(LEAVE "nic_ifconfig(nic={%s}) = {%s}", safe_str(nic), safe_str(rc));
	return rc;
}

int P4(nic_ntpdate)(const char* nic, const char* server, int port, int timeout)
{
	TRACE(ENTER "nic_ntpdate(nic={%s}, server={%s}, port=%d, timeout=%d)", safe_str(nic), safe_str(server), port, timeout);
	int rc = nic::ntpdate( nic, server, port, timeout );
	TRACE(LEAVE "nic_ntpdate(nic={%s}, server={%s}, port=%d, timeout=%d) = %d", safe_str(nic), safe_str(server), port, timeout, rc);
	return rc;
}

