#include #include #include #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); }