Goto sanos source index
//
// sysapi.h
//
// Operating System API
//
// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the project nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#include <os.h>
#include <string.h>
#include <os/syscall.h>
#include <os/cpu.h>
int sprintf(char *buf, const char *fmt, ...);
__declspec(naked) int syscall(int syscallno, void *params) {
__asm {
push ebp
mov ebp, esp
mov eax, 8[ebp]
mov edx, 12[ebp]
mov ecx, offset sys_return
sysenter
sys_return:
pop ebp
ret
}
}
__declspec(naked) int syscall_int48(int syscallno, void *params) {
__asm {
push ebp
mov ebp, esp
mov eax, 8[ebp]
mov edx, 12[ebp]
int 48
leave
ret
}
}
void init_syscall() {
// If the processor does not support sysenter patch the
// syscall routine with a jump to syscall_int48
if (!getpeb()->fast_syscalls_supported) {
// Inject a 'JMP syscall_int48' at the entry of syscall
char *sc = (char *) syscall;
char *sc48 = (char *) syscall_int48;
sc[0] = 0xEB;
sc[1] = (sc48 - sc - 2);
}
}
int mkfs(const char *devname, const char *type, const char *opts) {
return syscall(SYSCALL_MKFS, (void *) &devname);
}
/*static*/ int _mount(const char *type, const char *mntto, const char *mntfrom, const char *opts) {
return syscall(SYSCALL_MOUNT, (void *) &type);
}
int mount(const char *type, const char *mntto, const char *mntfrom, const char *opts) {
if (type && strcmp(type, "smbfs") == 0) {
char addr[256];
char *p, *q;
char *newopts;
struct hostent *hp;
struct in_addr ipaddr;
int rc;
if (mntfrom[0] != '/' && mntfrom[1] != '/') {
errno = EINVAL;
return -1;
}
p = (char *) mntfrom + 2;
q = strchr(p, '/');
if (!q) {
errno = EINVAL;
return -1;
}
if (q - p > sizeof(addr) - 1) {
errno = EINVAL;
return -1;
}
memcpy(addr, p, q - p);
addr[q - p] = 0;
hp = gethostbyname(addr);
if (!hp) return -1;
memcpy(&ipaddr, hp->h_addr_list[0], hp->h_length);
newopts = malloc((opts ? strlen(opts) : 0) + 32);
if (!newopts) return -1;
if (opts) {
sprintf(newopts, "%s,addr=0x%08X", opts, ipaddr.s_addr);
} else {
sprintf(newopts, "addr=0x%08X", ipaddr.s_addr);
}
rc = _mount(type, mntto, mntfrom, newopts);
free(newopts);
return rc;
} else {
return _mount(type, mntto, mntfrom, opts);
}
}
int umount(const char *path) {
return syscall(SYSCALL_UMOUNT, (void *) &path);
}
int getfsstat(struct statfs *buf, size_t size) {
return syscall(SYSCALL_GETFSSTAT, (void *) &buf);
}
int fstatfs(handle_t f, struct statfs *buf) {
return syscall(SYSCALL_FSTATFS, (void *) &f);
}
int statfs(const char *name, struct statfs *buf) {
return syscall(SYSCALL_STATFS, (void *) &name);
}
handle_t open(const char *name, int flags, ...) {
return syscall(SYSCALL_OPEN, (void *) &name);
}
int close(handle_t h) {
return syscall(SYSCALL_CLOSE, &h);
}
int fsync(handle_t f) {
return syscall(SYSCALL_FSYNC, &f);
}
int read(handle_t f, void *data, size_t size) {
return syscall(SYSCALL_READ, &f);
}
int write(handle_t f, const void *data, size_t size) {
return syscall(SYSCALL_WRITE, &f);
}
int pread(handle_t f, void *data, size_t size, off64_t offset) {
return syscall(SYSCALL_PREAD, &f);
}
int pwrite(handle_t f, const void *data, size_t size, off64_t offset) {
return syscall(SYSCALL_PWRITE, &f);
}
int ioctl(handle_t f, int cmd, const void *data, size_t size) {
return syscall(SYSCALL_IOCTL, &f);
}
int readv(handle_t f, const struct iovec *iov, int count) {
return syscall(SYSCALL_READV, &f);
}
int writev(handle_t f, const struct iovec *iov, int count) {
return syscall(SYSCALL_WRITEV, &f);
}
/*static*/ loff_t _tell(handle_t f, off64_t *retval) {
return syscall(SYSCALL_TELL, &f);
}
loff_t tell(handle_t f) {
return _tell(f, NULL);
}
off64_t tell64(handle_t f) {
off64_t rc;
_tell(f, &rc);
return rc;
}
/*static*/ int _lseek(handle_t f, off64_t offset, int origin, off64_t *retval) {
return syscall(SYSCALL_LSEEK, &f);
}
off64_t lseek64(handle_t f, off64_t offset, int origin) {
off64_t rc;
_lseek(f, offset, origin, &rc);
return rc;
}
loff_t lseek(handle_t f, loff_t offset, int origin) {
return _lseek(f, offset, origin, NULL);
}
int ftruncate64(handle_t f, off64_t size) {
return syscall(SYSCALL_FTRUNCATE, &f);
}
int ftruncate(handle_t f, loff_t size) {
return ftruncate64(f, size);
}
int futime(handle_t f, struct utimbuf *times) {
return syscall(SYSCALL_FUTIME, &f);
}
int utime(const char *name, struct utimbuf *times) {
return syscall(SYSCALL_UTIME, (void *) &name);
}
int fstat64(handle_t f, struct stat64 *buffer) {
return syscall(SYSCALL_FSTAT, &f);
}
int fstat(handle_t f, struct stat *buffer) {
if (buffer) {
struct stat64 buf64;
int rc;
rc = fstat64(f, &buf64);
if (rc < 0) return rc;
buffer->st_dev = buf64.st_dev;
buffer->st_ino = buf64.st_ino;
buffer->st_mode = buf64.st_mode;
buffer->st_nlink = buf64.st_nlink;
buffer->st_uid = buf64.st_uid;
buffer->st_gid = buf64.st_gid;
buffer->st_rdev = buf64.st_rdev;
buffer->st_size = buf64.st_size > 0x7FFFFFFF ? 0x7FFFFFFF : (loff_t) buf64.st_size;
buffer->st_atime = buf64.st_atime;
buffer->st_mtime = buf64.st_mtime;
buffer->st_ctime = buf64.st_ctime;
return rc;
} else {
return fstat64(f, NULL);
}
}
int stat64(const char *name, struct stat64 *buffer) {
return syscall(SYSCALL_STAT, (void *) &name);
}
int stat(const char *name, struct stat *buffer) {
if (buffer) {
struct stat64 buf64;
int rc;
rc = stat64(name, &buf64);
if (rc < 0) return rc;
buffer->st_dev = buf64.st_dev;
buffer->st_ino = buf64.st_ino;
buffer->st_mode = buf64.st_mode;
buffer->st_nlink = buf64.st_nlink;
buffer->st_uid = buf64.st_uid;
buffer->st_gid = buf64.st_gid;
buffer->st_rdev = buf64.st_rdev;
buffer->st_size = buf64.st_size > 0x7FFFFFFF ? 0x7FFFFFFF : (loff_t) buf64.st_size;
buffer->st_atime = buf64.st_atime;
buffer->st_mtime = buf64.st_mtime;
buffer->st_ctime = buf64.st_ctime;
return rc;
} else {
return stat64(name, NULL);
}
}
int lstat(const char *name, struct stat *buffer) {
return stat(name, buffer);
}
int lstat64(const char *name, struct stat64 *buffer) {
return stat64(name, buffer);
}
int chmod(const char *name, int mode) {
return syscall(SYSCALL_CHMOD, (void *) &name);
}
int fchmod(handle_t f, int mode) {
return syscall(SYSCALL_FCHMOD, (void *) &f);
}
int mkdir(const char *name, int mode) {
return syscall(SYSCALL_MKDIR, (void *) &name);
}
int rmdir(const char *name) {
return syscall(SYSCALL_RMDIR, (void *) &name);
}
int rename(const char *oldname, const char *newname) {
return syscall(SYSCALL_RENAME, (void *) &oldname);
}
int link(const char *oldname, const char *newname) {
return syscall(SYSCALL_LINK, (void *) &oldname);
}
int unlink(const char *name) {
return syscall(SYSCALL_UNLINK, (void *) &name);
}
handle_t _opendir(const char *name) {
return syscall(SYSCALL_OPENDIR, (void *) &name);
}
int _readdir(handle_t f, struct direntry *dirp, int count) {
return syscall(SYSCALL_READDIR, &f);
}
void *vmalloc(void *addr, unsigned long size, int type, int protect, unsigned long tag) {
return (void *) syscall(SYSCALL_VMALLOC, &addr);
}
int vmfree(void *addr, unsigned long size, int type) {
return syscall(SYSCALL_VMFREE, &addr);
}
void *vmrealloc(void *addr, unsigned long oldsize, unsigned long newsize, int type, int protect, unsigned long tag) {
return (void *) syscall(SYSCALL_VMREALLOC, &addr);
}
int vmprotect(void *addr, unsigned long size, int protect) {
return syscall(SYSCALL_VMPROTECT, &addr);
}
int vmlock(void *addr, unsigned long size) {
return syscall(SYSCALL_VMLOCK, &addr);
}
int vmunlock(void *addr, unsigned long size) {
return syscall(SYSCALL_VMUNLOCK, &addr);
}
void *vmmap(void *addr, unsigned long size, int protect, handle_t h, off64_t offset) {
return (void *) syscall(SYSCALL_VMMAP, &addr);
}
int vmsync(void *addr, unsigned long size) {
return syscall(SYSCALL_VMSYNC, &addr);
}
int waitone(handle_t h, int timeout) {
return syscall(SYSCALL_WAITONE, &h);
}
int waitall(handle_t *h, int count, int timeout) {
return syscall(SYSCALL_WAITALL, &h);
}
int waitany(handle_t *h, int count, int timeout) {
return syscall(SYSCALL_WAITANY, &h);
}
handle_t mkevent(int manual_reset, int initial_state) {
return syscall(SYSCALL_MKEVENT, &manual_reset);
}
int epulse(handle_t h) {
return syscall(SYSCALL_EPULSE, &h);
}
int eset(handle_t h) {
return syscall(SYSCALL_ESET, &h);
}
int ereset(handle_t h) {
return syscall(SYSCALL_ERESET, &h);
}
void exitos(int mode) {
syscall(SYSCALL_EXITOS, &mode);
}
handle_t dup(handle_t h) {
return syscall(SYSCALL_DUP, &h);
}
time_t time(time_t *timeptr) {
return syscall(SYSCALL_TIME, &timeptr);
}
int gettimeofday(struct timeval *tv, void *tzp) {
return syscall(SYSCALL_GETTIMEOFDAY, &tv);
}
int settimeofday(struct timeval *tv) {
return syscall(SYSCALL_SETTIMEOFDAY, &tv);
}
clock_t clock() {
return syscall(SYSCALL_CLOCK, NULL);
}
handle_t mksem(int initial_count) {
return syscall(SYSCALL_MKSEM, &initial_count);
}
int semrel(handle_t h, int count) {
return syscall(SYSCALL_SEMREL, &h);
}
int accept(int s, struct sockaddr *addr, int *addrlen) {
return syscall(SYSCALL_ACCEPT, &s);
}
int bind(int s, const struct sockaddr *name, int namelen) {
return syscall(SYSCALL_BIND, &s);
}
int connect(int s, const struct sockaddr *name, int namelen) {
return syscall(SYSCALL_CONNECT, &s);
}
int getpeername(int s, struct sockaddr *name, int *namelen) {
return syscall(SYSCALL_GETPEERNAME, &s);
}
int getsockname(int s, struct sockaddr *name, int *namelen) {
return syscall(SYSCALL_GETSOCKNAME, &s);
}
int getsockopt(int s, int level, int optname, void *optval, int *optlen) {
return syscall(SYSCALL_GETSOCKOPT, &s);
}
int listen(int s, int backlog) {
return syscall(SYSCALL_LISTEN, &s);
}
int recv(int s, void *data, int size, unsigned int flags) {
return syscall(SYSCALL_RECV, &s);
}
int recvfrom(int s, void *data, int size, unsigned int flags, struct sockaddr *from, int *fromlen) {
return syscall(SYSCALL_RECVFROM, &s);
}
int send(int s, const void *data, int size, unsigned int flags) {
return syscall(SYSCALL_SEND, &s);
}
int sendto(int s, const void *data, int size, unsigned int flags, const struct sockaddr *to, int tolen) {
return syscall(SYSCALL_SENDTO, &s);
}
int setsockopt(int s, int level, int optname, const void *optval, int optlen) {
return syscall(SYSCALL_SETSOCKOPT, &s);
}
int shutdown(int s, int how) {
return syscall(SYSCALL_SHUTDOWN, &s);
}
int socket(int domain, int type, int protocol) {
return syscall(SYSCALL_SOCKET, &domain);
}
int chdir(const char *name) {
return syscall(SYSCALL_CHDIR, (void *) &name);
}
handle_t mkiomux(int flags) {
return syscall(SYSCALL_MKIOMUX, (void *) &flags);
}
int dispatch(handle_t iomux, handle_t h, int events, int context) {
return syscall(SYSCALL_DISPATCH, (void *) &iomux);
}
int recvmsg(int s, struct msghdr *hdr, unsigned int flags) {
return syscall(SYSCALL_RECVMSG, (void *) &s);
}
int sendmsg(int s, struct msghdr *hdr, unsigned int flags) {
return syscall(SYSCALL_SENDMSG, (void *) &s);
}
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout) {
return syscall(SYSCALL_SELECT, (void *) &nfds);
}
int pipe(handle_t fildes[2]) {
return syscall(SYSCALL_PIPE, (void *) &fildes);
}
handle_t dup2(handle_t h1, handle_t h2) {
return syscall(SYSCALL_DUP2, (void *) &h1);
}
int setmode(handle_t f, int mode) {
return syscall(SYSCALL_SETMODE, (void *) &f);
}
int sysinfo(int cmd, void *data, size_t size) {
return syscall(SYSCALL_SYSINFO, (void *) &cmd);
}
handle_t mkmutex(int owned) {
return syscall(SYSCALL_MKMUTEX, (void *) &owned);
}
int mutexrel(handle_t h) {
return syscall(SYSCALL_MUTEXREL, (void *) &h);
}
int getuid() {
return syscall(SYSCALL_GETUID, NULL);
}
int setuid(uid_t uid) {
return syscall(SYSCALL_SETUID, (void *) &uid);
}
int getgid() {
return syscall(SYSCALL_GETGID, NULL);
}
int setgid(gid_t gid) {
return syscall(SYSCALL_SETGID, (void *) &gid);
}
int geteuid() {
return syscall(SYSCALL_GETEUID, NULL);
}
int seteuid(uid_t uid) {
return syscall(SYSCALL_SETEUID, (void *) &uid);
}
int getegid() {
return syscall(SYSCALL_GETEGID, NULL);
}
int setegid(gid_t gid) {
return syscall(SYSCALL_SETEGID, (void *) &gid);
}
int getgroups(int size, gid_t list[]) {
return syscall(SYSCALL_GETGROUPS, (void *) &size);
}
int setgroups(int size, const gid_t list[]) {
return syscall(SYSCALL_SETGROUPS, (void *) &size);
}
int chown(const char *name, int owner, int group) {
return syscall(SYSCALL_CHOWN, (void *) &name);
}
int fchown(handle_t f, int owner, int group) {
return syscall(SYSCALL_FCHOWN, (void *) &f);
}
int access(const char *name, int mode) {
return syscall(SYSCALL_ACCESS, (void *) &name);
}
int poll(struct pollfd fds[], unsigned int nfds, int timeout) {
return syscall(SYSCALL_POLL, (void *) &fds);
}
int _getcwd(char *buf, size_t size) {
return syscall(SYSCALL_GETCWD, (void *) &buf);
}
char *getcwd(char *buf, size_t size) {
if (buf) {
if (_getcwd(buf, size) < 0) {
return NULL;
} else {
return buf;
}
} else {
char curdir[MAXPATH];
size_t len;
if (_getcwd(curdir, MAXPATH) < 0) return NULL;
len = strlen(curdir);
if (size == 0) {
size = len + 1;
} else if (len >= size) {
errno = ERANGE;
return NULL;
}
buf = malloc(size);
if (!buf) {
errno = ENOMEM;
return NULL;
}
memcpy(buf, curdir, len + 1);
return buf;
}
}