m3core/src/unix/Common/UnixC.c
/* Copyright (C) 1993, Digital Equipment Corporation */
/* All rights reserved. */
/* See the file COPYRIGHT for a full description. */
/*
On some platforms, such as 32bit Linux and 32bit Solaris,
various functions are defined to have 32bit limits by default.
unless #define _FILE_OFFSET_BITS 64, which only affects C source.
Usually they are also available with the name ending in "64" as well.
open => open64
stat => stat64
etc.
It might take a #define to expose those names to C.
(Just to help motivate why there are so many #defines.)
Therefore, saying, e.g.
<*EXTERNAL*> PROCEDURE ftruncate (fd: int; length: off_t): int;
is wrong, unless you constrain off_t to 32 bits, which is not good.
It would be correct to say:
<*EXTERNAL ftruncate64*> PROCEDURE ftruncate (fd: int; length: off_t): int;
However that is not portable.
So use these wrappers instead.
*/
#ifdef _MSC_VER
#undef _DLL
#ifndef _MT
#define _MT
#endif
#endif
#include "m3unix.h"
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
#endif
#ifdef __cplusplus
extern "C"
{
#endif
void Unix__Assertions(void)
{
/* make sure things are normal */
M3_STATIC_ASSERT(CHAR_BIT == 8);
M3_STATIC_ASSERT(sizeof(short) == 2);
M3_STATIC_ASSERT(sizeof(int) == 4);
M3_STATIC_ASSERT((sizeof(long) == 4) || (sizeof(long) == 8));
M3_STATIC_ASSERT((sizeof(void*) == 4) || (sizeof(void*) == 8));
M3_STATIC_ASSERT((sizeof(size_t) == 4) || (sizeof(size_t) == 8));
M3_STATIC_ASSERT(sizeof(ptrdiff_t) == sizeof(size_t));
M3_STATIC_ASSERT(sizeof(void*) == sizeof(size_t));
#ifndef _WIN64
M3_STATIC_ASSERT(sizeof(void*) == sizeof(long));
M3_STATIC_ASSERT(sizeof(size_t) == sizeof(long));
#endif
#ifdef _MSC_VER
M3_STATIC_ASSERT(sizeof(__int64) == 8);
#else
M3_STATIC_ASSERT(sizeof(long long) == 8);
#endif
#ifndef _WIN32
/* make sure all the Modula-3 types are large enough */
#define CHECK_M3_TYPE_SIZE(x) M3_STATIC_ASSERT(sizeof(m3_##x) >= sizeof(x))
#define IS_TYPE_SIGNED(x) (((x)-1) < (x)0)
CHECK_M3_TYPE_SIZE(dev_t);
CHECK_M3_TYPE_SIZE(gid_t);
CHECK_M3_TYPE_SIZE(ino_t);
CHECK_M3_TYPE_SIZE(mode_t);
CHECK_M3_TYPE_SIZE(nlink_t);
CHECK_M3_TYPE_SIZE(off_t);
CHECK_M3_TYPE_SIZE(pid_t);
CHECK_M3_TYPE_SIZE(pthread_t);
CHECK_M3_TYPE_SIZE(uid_t);
M3_STATIC_ASSERT(IS_TYPE_SIGNED(pid_t));
#endif
Utime__Assertions();
Usocket__Assertions();
}
/* open doesn't take any off_t parameter, but there is open64, that
#define _FILE_OFFSET_BITS 64 maps open to. */
int Unix__open(const char* path, int flags, m3_mode_t mode)
{
#ifdef _WIN32
return _open(path, flags, mode);
#else
return open(path, flags, mode);
#endif
}
/* wrapped in case passing mode_t vs. int varies */
int Unix__mkdir(const char* path, m3_mode_t mode)
{
#ifdef _WIN32
return _mkdir(path);
#else
return mkdir(path, mode);
#endif
}
#ifndef _WIN32
int Unix__truncate(const char* file, m3_off_t length)
{
return truncate(file, length);
}
int Unix__ftruncate(int file, m3_off_t length)
{
return ftruncate(file, length);
}
#endif
m3_off_t Unix__lseek(int fd, m3_off_t offset, int whence)
{
#ifdef _WIN32
return _lseeki64(fd, offset, whence);
#else
return lseek(fd, offset, whence);
#endif
}
#ifndef _WIN32
int Unix__fcntl(int fd, int request, int arg)
/* fcntl is actually fcntl(fd, request, ...).
Wrapper is needed on some systems to handle varargs.
See http://edoofus.blogspot.com/2008/08/interesting-bug-unbreaking-cvsupamd64.html.
*/
{
#ifdef __sun
/*
* This is to work around a bug in the Solaris-2 'libsocket' library
* which redefines 'fcntl' in such a way as to zero out 'errno' if the
* call is successful.
* See m3-libs/m3core/src/unix/solaris-2-x/Unix.m3.
*/
int e = errno;
int r = fcntl(fd, request, arg);
if (r == 0)
errno = e;
return r;
#else
return fcntl(fd, request, arg);
#endif
}
int Unix__ioctl(int fd, int request, void* argp)
/* ioctl is varargs. See fcntl. */
{
#ifdef __sun
/*
* This is to work around a bug in the Solaris-2 'libsocket' library
* which redefines 'ioctl' in such a way as to zero out 'errno' if the
* call is successful.
* See m3-libs/m3core/src/unix/solaris-2-x/Unix.m3.
*/
int e = errno;
int r = ioctl(fd, request, argp);
if (r == 0)
errno = e;
return r;
#else
return ioctl(fd, request, argp);
#endif
}
int Unix__mknod(const char* path, m3_mode_t mode, m3_dev_t dev)
/* no good reason to wrap this */
{
return mknod(path, mode, dev);
}
#endif
m3_mode_t Unix__umask(m3_mode_t newmask)
{
#ifdef _WIN32
return _umask(newmask);
#else
return umask(newmask);
#endif
}
int Unix__chmod(const char* path, m3_mode_t mode)
{
#ifdef _WIN32
return _chmod(path, mode);
#else
return chmod(path, mode);
#endif
}
#ifndef _WIN32
int Unix__fchmod(int fd, m3_mode_t mode)
{
return fchmod(fd, mode);
}
int Unix__chown(const char* path, m3_uid_t owner, m3_gid_t group)
{
return chown(path, owner, group);
}
int Unix__fchown(int fd, m3_uid_t owner, m3_gid_t group)
{
return fchown(fd, owner, group);
}
#endif
int Unix__creat(const char* path, m3_mode_t mode)
{
#ifdef _WIN32
return _creat(path, mode);
#else
return creat(path, mode);
#endif
}
int Unix__dup(int oldd)
{
#ifdef _WIN32
return _dup(oldd);
#else
return dup(oldd);
#endif
}
#ifndef _WIN32
m3_pid_t Unix__fork(void) { return fork(); }
#endif
int Unix__system(const char* s) { return system(s); }
int Unix__isatty(int file)
{
#ifdef _WIN32
return _isatty(file);
#else
return isatty(file);
#endif
}
int Unix__pipe(int files[2])
{
#ifdef _WIN32
return _pipe(files, 0, _O_BINARY);
#else
return pipe(files);
#endif
}
#ifndef _WIN32
INTEGER Unix__readlink(const char* path, char* buf, INTEGER bufsize) { return readlink(path, buf, bufsize); }
int Unix__symlink(const char* name1, const char* name2) { return symlink(name1, name2); }
#ifndef __INTERIX
int Unix__utimes(const char* file, const timeval_t* tvp) { return utimes(file, tvp); }
#endif
#endif
int Unix__rename(const char* from, const char* to) { return rename(from, to); }
int Unix__rmdir(const char* path)
{
#ifdef _WIN32
return _rmdir(path);
#else
return rmdir(path);
#endif
}
int Unix__unlink(const char* path)
{
#ifdef _WIN32
return _unlink(path);
#else
return unlink(path);
#endif
}
void Unix__underscore_exit(int exit_code)
{
_exit(exit_code);
}
int Unix__select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, timeval_t* timeout)
{
return select(nfds, readfds, writefds, exceptfds, timeout);
}
#ifndef _WIN32
int Unix__fsync(int file)
{
return fsync(file);
}
int Unix__getdtablesize()
{
return getdtablesize();
}
#endif
int Unix__gethostname(char* name, size_t namelen)
{
return gethostname(name, namelen);
}
#ifndef _WIN32
int Unix__getpagesize(void)
{
return getpagesize();
}
#endif
char* Unix__getcwd(char* pathname, size_t size)
{
#ifdef _WIN32
return _getcwd(pathname, size);
#else
return getcwd(pathname, size);
#endif
}
int Unix__access(const char* path, int mode)
{
#ifdef _WIN32
return _access(path, mode);
#else
return access(path, mode);
#endif
}
#ifndef _WIN32
void* Unix__sbrk(INTEGER inc)
{
return sbrk(inc);
}
#endif
int Unix__chdir(const char* path)
{
#ifdef _WIN32
return _chdir(path);
#else
return chdir(path);
#endif
}
int Unix__close(int d)
{
#ifdef _WIN32
return _close(d);
#else
return close(d);
#endif
}
int Unix__dup2(int oldd, int newd)
{
#ifdef _WIN32
return _dup2(oldd, newd);
#else
return dup2(oldd, newd);
#endif
}
#ifndef _WIN32
int Unix__execve(const char* name, char** argv, char** envp)
{
return execve(name, argv, envp);
}
M3WRAP1(unsigned, sleep, unsigned)
#endif
void Unix__exit(int i)
{
exit(i);
}
#ifdef __cplusplus
} /* extern C */
#endif