#include <u.h>
#include <libc.h>
#include <ureg.h>
#include "linuxsys.h"
#include "linux.h"
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
located on an ext2 file system */
#define O_ACCMODE 0003
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
#define O_CREAT 0100 /* not fcntl */
#define O_EXCL 0200 /* not fcntl */
#define O_NOCTTY 0400 /* not fcntl */
#define O_TRUNC 01000 /* not fcntl */
#define O_APPEND 02000
#define O_NONBLOCK 04000
#define O_NDELAY O_NONBLOCK
#define O_SYNC 010000
#define FASYNC 020000 /* fcntl, for BSD compatibility */
/*
* BUG: can't support O_EXCL (not in plan9 semantics)
* O_NOTTY doesn't make sense for plan9.
* BUG: supporting O_APPEND will be hard.
* BUG: O_NONBLOCK will be hard.
* O_SYNC doesn't make sense for plan9.
*
* To support O_APPEND and O_NONBLOCK,
* we really need to keep our own fd table.
* I'm not willing to do that quite yet. --rsc
*/
SYSCALL(sys_open)
{
char *path = (char*)ARG1;
int mode = ARG2;
int perm = ARG3;
int mode9, perm9, fd;
DPRINT("open(%s, %#o, %#o)...", path, mode, (mode&O_CREAT)?perm:0);
mode9 = mode & 3;
if(mode & O_TRUNC)
mode9 |= OTRUNC;
if(mode & O_CREAT) {
perm9 = perm & 0777;
fd = create(path, mode9, perm9);
} else
fd = open(path, mode9);
if(fd >= 0)
RETURN(fd);
RETURN(mkerror());
}
SYSCALL(sys_creat)
{
char *path = (char*)ARG1;
int perm = ARG2;
DPRINT("creat(%s, 0%o)...", path, perm);
/*
* open(2) says ``creat is equivalent to open with flags equal to
* O_CREAT|O_WRONLY|O_TRUNC''.
*/
ARG3 = ARG2;
ARG2 = O_CREAT|O_WRONLY|O_TRUNC;
sys_open(ureg);
}
SYSCALL(sys_close)
{
int fd = ARG1;
if(close(fd) < 0)
RETURN(-EBADFD);
RETURN(0);
}
SYSCALL(sys_read)
{
int fd = ARG1;
void *v = (void*) ARG2;
ulong n = ARG3;
int r;
DPRINT("read(%d, %p, %lud)...", fd, v, n);
r = read(fd, v, n);
if(r >= 0)
RETURN(r);
RETURN(mkerror());
}
SYSCALL(sys_write)
{
int r;
int fd = ARG1;
void *v = (void*) ARG2;
ulong n = ARG3;
DPRINT("write(%d, %p, %lud)...", fd, v, n);
r = write(fd, v, n);
if(r >= 0)
RETURN(r);
RETURN(mkerror());
}
SYSCALL(sys_link)
{
/*
* link(2) says EPERM means the file system
* doesn't support links.
*/
DPRINT("link(%s, %s)...", (char*)ARG1, (char*)ARG2);
RETURN(-EPERM);
}
SYSCALL(sys_unlink)
{
char *file = (char*) ARG1;
DPRINT("unlink(%s)...", file);
if(remove(file) == 0)
RETURN(0);
RETURN(mkerror());
}
SYSCALL(sys_chdir)
{
char *file = (char*) ARG1;
DPRINT("chdir(%s)...", file);
if(chdir(file) == 0)
RETURN(0);
RETURN(mkerror());
}
SYSCALL(sys_mknod)
{
/*
* mknod(2) says EPERM means the file system
* doesn't support the requested node type,
* which is pretty true.
*/
DPRINT("mknod(%s, %#luo, %lud)...", (char*)ARG1, ARG2, ARG3);
RETURN(-EPERM);
}
SYSCALL(sys_chmod)
{
char *file = (char*) ARG1;
int mode = ARG2;
Dir *d, nd;
DPRINT("chmod(%s, %#o)...", file, mode);
mode &= 0777;
if((d = dirstat(file)) == nil)
RETURN(mkerror());
nulldir(&nd);
nd.mode = d->mode & ~0777;
free(d);
nd.mode |= mode;
if(dirwstat(file, &nd) < 0)
RETURN(mkerror());
RETURN(0);
}
SYSCALL(sys_lseek)
{
int fd = ARG1;
int offset = ARG2;
int whence = ARG3;
DPRINT("lseek(%d, %d, %d)...", fd, offset, whence);
if(seek(fd, offset, whence) < 0)
RETURN(mkerror());
RETURN(0);
}
/*
* sync() always returns zero, even
* though we don't support it.
*/
SYSCALL(sys_sync)
{
DPRINT("sync()...");
RETURN(0);
}
SYSCALL(sys_rmdir)
{
char *file = (char*) ARG1;
DPRINT("rmdir(%s)...", file);
if(remove(file) < 0)
RETURN(mkerror());
RETURN(0);
}
|