add linux_emul base, reorganize docs
[openbsd_emul.git] / linux_emul_base / pipedev.c
CommitLineData
cae36a52 1#include <u.h>
2#include <libc.h>
3#include <ureg.h>
4#include "dat.h"
5#include "fns.h"
6#include "linux.h"
7
8typedef struct Pipe Pipe;
9
10struct Pipe
11{
12 Ufile;
13 void *bufproc;
14 ulong atime;
15 ulong mtime;
16 int ino;
17};
18
19enum{
20 Maxatomic = 64*1024,
21};
22
23int
24pipewrite(int fd, void *buf, int len)
25{
26 uchar *p, *e;
27 int err, n;
28
29 p = buf;
30 e = p + len;
31 while(p < e){
32 n = e - p;
33 if(n > Maxatomic)
34 n = Maxatomic;
35 if(notifyme(1))
36 err = -ERESTART;
37 else {
38 err = write(fd, p, n);
39 notifyme(0);
40 if(err < 0)
41 err = mkerror();
42 }
43 if(err < 0){
44 if(p == (uchar*)buf)
45 return err;
46 break;
47 }
48 p += err;
49 }
50 return p - (uchar*)buf;
51}
52
53static int
54closepipe(Ufile *file)
55{
56 Pipe *pipe = (Pipe*)file;
57
58 close(pipe->fd);
59 freebufproc(pipe->bufproc);
60
61 return 0;
62}
63
64static void*
65bufprocpipe(Pipe *pipe)
66{
67 if(pipe->bufproc == nil)
68 pipe->bufproc = newbufproc(pipe->fd);
69 return pipe->bufproc;
70}
71
72static int
73pollpipe(Ufile *file, void *tab)
74{
75 Pipe *pipe = (Pipe*)file;
76
77 return pollbufproc(bufprocpipe(pipe), pipe, tab);
78}
79
80static int
81readpipe(Ufile *file, void *buf, int len, vlong)
82{
83 Pipe *pipe = (Pipe*)file;
84 int ret;
85
86 if((pipe->mode & O_NONBLOCK) || (pipe->bufproc != nil)){
87 ret = readbufproc(bufprocpipe(pipe), buf, len, 0, (pipe->mode & O_NONBLOCK));
88 } else {
89 if(notifyme(1))
90 return -ERESTART;
91 ret = read(pipe->fd, buf, len);
92 notifyme(0);
93 if(ret < 0)
94 ret = mkerror();
95 }
96 if(ret > 0)
97 pipe->atime = time(nil);
98 return ret;
99}
100
101static int
102writepipe(Ufile *file, void *buf, int len, vlong)
103{
104 Pipe *pipe = (Pipe*)file;
105 int ret;
106
107 ret = pipewrite(pipe->fd, buf, len);
108 if(ret > 0)
109 pipe->mtime = time(nil);
110 return ret;
111}
112
113static int
114ioctlpipe(Ufile *file, int cmd, void *arg)
115{
116 Pipe *pipe = (Pipe*)file;
117
118 switch(cmd){
119 default:
120 return -ENOTTY;
121 case 0x541B:
122 {
123 int r;
124
125 if(arg == nil)
126 return -EINVAL;
127 if((r = nreadablebufproc(bufprocpipe(pipe))) < 0){
128 *((int*)arg) = 0;
129 return r;
130 }
131 *((int*)arg) = r;
132 }
133 return 0;
134 }
135}
136
137int sys_pipe(int *fds)
138{
139 Pipe *file;
140 int p[2];
141 int i, fd;
142 static int ino = 0x1234;
143
144 trace("sys_pipe(%p)", fds);
145
146 if(pipe(p) < 0)
147 return mkerror();
148
149 for(i=0; i<2; i++){
150 file = kmallocz(sizeof(Pipe), 1);
151 file->ref = 1;
152 file->mode = O_RDWR;
153 file->dev = PIPEDEV;
154 file->fd = p[i];
155 file->ino = ino++;
156 file->atime = file->mtime = time(nil);
157 if((fd = newfd(file, 0)) < 0){
158 if(i > 0)
159 sys_close(fds[0]);
160 close(p[0]);
161 close(p[1]);
162 return fd;
163 }
164 fds[i] = fd;
165 }
166 return 0;
167}
168
169static void
170fillstat(Pipe *pipe, Ustat *s)
171{
172 s->ino = pipe->ino;
173 s->mode = 0666 | S_IFIFO;
174 s->uid = current->uid;
175 s->gid = current->gid;
176 s->atime = pipe->atime;
177 s->mtime = pipe->mtime;
178 s->size = 0;
179}
180
181static int
182fstatpipe(Ufile *file, Ustat *s)
183{
184 Pipe *pipe = (Pipe*)file;
185 fillstat(pipe, s);
186 return 0;
187};
188
189static Udev pipedev =
190{
191 .read = readpipe,
192 .write = writepipe,
193 .poll = pollpipe,
194 .close = closepipe,
195 .ioctl = ioctlpipe,
196 .fstat = fstatpipe,
197};
198
199void pipedevinit(void)
200{
201 devtab[PIPEDEV] = &pipedev;
202}