#include #include #include #include "dat.h" #include "fns.h" #include "linux.h" int ufstat(int fd, Ustat *ps) { Ufile *f; int err; err = -EBADF; if((f = fdgetfile(fd)) == nil) goto out; err = -EPERM; if(devtab[f->dev]->fstat == nil) goto out; memset(ps, 0, sizeof(Ustat)); err = devtab[f->dev]->fstat(f, ps); out: putfile(f); return err; } struct linux_stat { ushort st_dev; ushort __pad1; ulong st_ino; ushort st_mode; ushort st_nlink; ushort st_uid; ushort st_gid; ushort st_rdev; ushort __pad2; ulong st_size; ulong st_blksize; ulong st_blocks; ulong st_atime; ulong __unused1; ulong st_mtime; ulong __unused2; ulong st_ctime; ulong __unused3; ulong __unused4; ulong __unused5; }; static void ustat2linuxstat(Ustat *x, struct linux_stat *s) { memset(s, 0, sizeof(*s)); s->st_dev = x->dev; s->st_ino = x->ino; s->st_mode = x->mode; s->st_nlink = 1; s->st_uid = x->uid; s->st_gid = x->gid; s->st_size = x->size; s->st_rdev = x->rdev; s->st_blksize = 4096; s->st_blocks = (x->size+s->st_blksize-1) / s->st_blksize; s->st_atime = x->atime; s->st_mtime = x->mtime; s->st_ctime = x->ctime; } struct linux_stat64 { uvlong lst_dev; uint __pad1; uint __lst_ino; uint lst_mode; uint lst_nlink; uint lst_uid; uint lst_gid; uvlong lst_rdev; uint __pad2; vlong lst_size; uint lst_blksize; uvlong lst_blocks; uint lst_atime; uint lst_atime_nsec; uint lst_mtime; uint lst_mtime_nsec; uint lst_ctime; uint lst_ctime_nsec; uvlong lst_ino; }; static void ustat2linuxstat64(Ustat *x, struct linux_stat64 *s) { memset(s, 0, sizeof(*s)); s->lst_dev = x->dev; s->lst_ino = x->ino; s->__lst_ino = x->ino & 0xFFFFFFFF; s->lst_mode = x->mode; s->lst_nlink = 1; s->lst_uid = x->uid; s->lst_gid = x->gid; s->lst_size = x->size; s->lst_rdev = x->rdev; s->lst_blksize = 4096; // good as any s->lst_blocks = (x->size+s->lst_blksize-1) / s->lst_blksize; s->lst_atime = x->atime; s->lst_mtime = x->mtime; s->lst_ctime = x->ctime; } int sys_linux_stat(char *path, void *st) { int err; Ustat x; trace("sys_linux_stat(%s, %p)", path, st); err = fsstat(path, 0, &x); if(err < 0) return err; ustat2linuxstat(&x, (struct linux_stat*)st); return err; } int sys_linux_lstat(char *path, void *st) { int err; Ustat x; trace("sys_linux_lstat(%s, %p)", path, st); if((path = fsfullpath(path)) == nil) return -EFAULT; err = fsstat(path, 1, &x); free(path); if(err < 0) return err; ustat2linuxstat(&x, (struct linux_stat*)st); return err; } int sys_linux_stat64(char *path, void *st) { int err; Ustat x; trace("sys_linux_stat64(%s, %p)", path, st); if((path = fsfullpath(path)) == nil) return -EFAULT; err = fsstat(path, 0, &x); free(path); if(err < 0) return err; ustat2linuxstat64(&x, (struct linux_stat64*)st); return err; } int sys_linux_lstat64(char *path, void *st) { int err; Ustat x; trace("sys_linux_lstat64(%s, %p)", path, st); if((path = fsfullpath(path)) == nil) return -EFAULT; err = fsstat(path, 1, &x); free(path); if(err < 0) return err; ustat2linuxstat64(&x, (struct linux_stat64*)st); return err; } int sys_linux_fstat(int fd, void *st) { int err; Ustat x; trace("sys_linux_fstat(%d, %p)", fd, st); err = ufstat(fd, &x); if(err < 0) return err; ustat2linuxstat(&x, (struct linux_stat*)st); return err; } int sys_linux_fstat64(int fd, void *st) { int err; Ustat x; trace("sys_linux_fstat64(%d, %p)", fd, st); err = ufstat(fd, &x); if(err < 0) return err; ustat2linuxstat64(&x, (struct linux_stat64*)st); return err; } static int getdents(int fd, void *buf, int len, int (*fconv)(Udirent *, void *, int, int)) { Ufile *f; Udirent *t, *x; uchar *p, *e; int o, r, err; if((f = fdgetfile(fd)) == nil) return -EBADF; o = 0; p = buf; e = p + len; t = f->rdaux; if(t == nil || f->off == 0){ f->rdaux = nil; while(x = t){ t = t->next; free(x); } if((err = devtab[f->dev]->readdir(f, &t)) <= 0){ putfile(f); return err; } f->rdaux = t; } for(; t; t=t->next){ /* just calculate size */ r = fconv(t, nil, 0, e - p); if(r <= 0) break; if(o >= f->off){ /* convert */ f->off = o + r; r = fconv(t, p, t->next ? f->off : 0, e - p); p += r; } o += r; } putfile(f); return p - (uchar*)buf; } Udirent* newdirent(char *path, char *name, int mode) { Udirent *d; int nlen; char *s; nlen = strlen(name); d = kmallocz(sizeof(*d) + nlen + 1, 1); d->mode = mode; strcpy(d->name, name); s = allocpath(path, nil, d->name); d->ino = hashpath(s); free(s); return d; } struct linux_dirent { long d_ino; long d_off; ushort d_reclen; char d_name[]; }; static int udirent2linux(Udirent *u, void *d, int off, int left) { int n; struct linux_dirent *e = d; n = sizeof(*e) + strlen(u->name) + 1; if(n > left) return 0; if(e){ e->d_ino = u->ino & 0xFFFFFFFF; e->d_off = off; e->d_reclen = n; strcpy(e->d_name, u->name); } return n; } struct linux_dirent64 { uvlong d_ino; vlong d_off; ushort d_reclen; uchar d_type; char d_name[]; }; static int udirent2linux64(Udirent *u, void *d, int off, int left) { int n; struct linux_dirent64 *e = d; n = sizeof(*e) + strlen(u->name) + 1; if(n > left) return 0; if(e){ e->d_ino = u->ino; e->d_off = off; e->d_reclen = n; e->d_type = (u->mode>>12)&15; strcpy(e->d_name, u->name); } return n; } int sys_linux_getdents(int fd, void *buf, int nbuf) { trace("sys_linux_getdents(%d, %p, %x)", fd, buf, nbuf); return getdents(fd, buf, nbuf, udirent2linux); } int sys_linux_getdents64(int fd, void *buf, int nbuf) { trace("sys_linux_getdents64(%d, %p, %x)", fd, buf, nbuf); return getdents(fd, buf, nbuf, udirent2linux64); } struct linux_statfs { long f_type; long f_bsize; long f_blocks; long f_bfree; long f_bavail; long f_files; long f_ffree; long f_fsid[2]; long f_namelen; long f_frsize; long f_spare[5]; }; int sys_statfs(char *name, void *pstatfs) { struct linux_statfs *s = pstatfs; trace("sys_statfs(%s, %p)", name, s); if((s == nil) || (name == nil)) return -EINVAL; memset(s, 0, sizeof(*s)); s->f_namelen = 256; s->f_bsize = 4096; s->f_blocks = 0x80000000; s->f_bavail = s->f_bfree = 0x80000000; s->f_files = s->f_ffree = 0x40000000; if(strncmp(name, "/dev/pts", 8) == 0){ s->f_type = 0x1cd1; return 0; } memmove(&s->f_type, "PLN9", 4); memmove(s->f_fsid, "PLAN9_FS", 8); return 0; } int sys_getxattr(char *path, char *name, void *value, int size) { trace("sys_getxattr(%s, %s, %p, %x)", path, name, value, size); return -EOPNOTSUPP; } int sys_lgetxattr(char *path, char *name, void *value, int size) { trace("sys_lgetxattr(%s, %s, %p, %x)", path, name, value, size); return -EOPNOTSUPP; } int sys_fgetxattr(int fd, char *name, void *value, int size) { Ufile *f; int err; trace("sys_fgetxattr(%d, %s, %p, %x)", fd, name, value, size); if((f = fdgetfile(fd)) == nil) return -EBADF; err = -EOPNOTSUPP; putfile(f); return err; } int sys_setxattr(char *path, char *name, void *value, int flags, int size) { trace("sys_setxattr(%s, %s, %p, %x, %x)", path, name, value, flags, size); return -EOPNOTSUPP; } int sys_lsetxattr(char *path, char *name, void *value, int flags, int size) { trace("sys_lsetxattr(%s, %s, %p, %x, %x)", path, name, value, flags, size); return -EOPNOTSUPP; } int sys_fsetxattr(int fd, char *name, void *value, int size, int flags) { Ufile *f; int err; trace("sys_fsetxattr(%d, %s, %p, %x, %x)", fd, name, value, flags, size); if((f = fdgetfile(fd)) == nil) return -EBADF; err = -EOPNOTSUPP; putfile(f); return err; }