#include #include #include #include "dat.h" #include "fns.h" #include "linux.h" typedef struct Pipe Pipe; struct Pipe { Ufile; void *bufproc; ulong atime; ulong mtime; int ino; }; enum{ Maxatomic = 64*1024, }; int pipewrite(int fd, void *buf, int len) { uchar *p, *e; int err, n; p = buf; e = p + len; while(p < e){ n = e - p; if(n > Maxatomic) n = Maxatomic; if(notifyme(1)) err = -ERESTART; else { err = write(fd, p, n); notifyme(0); if(err < 0) err = mkerror(); } if(err < 0){ if(p == (uchar*)buf) return err; break; } p += err; } return p - (uchar*)buf; } static int closepipe(Ufile *file) { Pipe *pipe = (Pipe*)file; close(pipe->fd); freebufproc(pipe->bufproc); return 0; } static void* bufprocpipe(Pipe *pipe) { if(pipe->bufproc == nil) pipe->bufproc = newbufproc(pipe->fd); return pipe->bufproc; } static int pollpipe(Ufile *file, void *tab) { Pipe *pipe = (Pipe*)file; return pollbufproc(bufprocpipe(pipe), pipe, tab); } static int readpipe(Ufile *file, void *buf, int len, vlong) { Pipe *pipe = (Pipe*)file; int ret; if((pipe->mode & O_NONBLOCK) || (pipe->bufproc != nil)){ ret = readbufproc(bufprocpipe(pipe), buf, len, 0, (pipe->mode & O_NONBLOCK)); } else { if(notifyme(1)) return -ERESTART; ret = read(pipe->fd, buf, len); notifyme(0); if(ret < 0) ret = mkerror(); } if(ret > 0) pipe->atime = time(nil); return ret; } static int writepipe(Ufile *file, void *buf, int len, vlong) { Pipe *pipe = (Pipe*)file; int ret; ret = pipewrite(pipe->fd, buf, len); if(ret > 0) pipe->mtime = time(nil); return ret; } static int ioctlpipe(Ufile *file, int cmd, void *arg) { Pipe *pipe = (Pipe*)file; switch(cmd){ default: return -ENOTTY; case 0x541B: { int r; if(arg == nil) return -EINVAL; if((r = nreadablebufproc(bufprocpipe(pipe))) < 0){ *((int*)arg) = 0; return r; } *((int*)arg) = r; } return 0; } } int sys_pipe(int *fds) { Pipe *file; int p[2]; int i, fd; static int ino = 0x1234; trace("sys_pipe(%p)", fds); if(pipe(p) < 0) return mkerror(); for(i=0; i<2; i++){ file = kmallocz(sizeof(Pipe), 1); file->ref = 1; file->mode = O_RDWR; file->dev = PIPEDEV; file->fd = p[i]; file->ino = ino++; file->atime = file->mtime = time(nil); if((fd = newfd(file, 0)) < 0){ if(i > 0) sys_close(fds[0]); close(p[0]); close(p[1]); return fd; } fds[i] = fd; } return 0; } static void fillstat(Pipe *pipe, Ustat *s) { s->ino = pipe->ino; s->mode = 0666 | S_IFIFO; s->uid = current->uid; s->gid = current->gid; s->atime = pipe->atime; s->mtime = pipe->mtime; s->size = 0; } static int fstatpipe(Ufile *file, Ustat *s) { Pipe *pipe = (Pipe*)file; fillstat(pipe, s); return 0; }; static Udev pipedev = { .read = readpipe, .write = writepipe, .poll = pollpipe, .close = closepipe, .ioctl = ioctlpipe, .fstat = fstatpipe, }; void pipedevinit(void) { devtab[PIPEDEV] = &pipedev; }