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 | |
8 | typedef struct Pipe Pipe; |
9 | |
10 | struct Pipe |
11 | { |
12 | Ufile; |
13 | void *bufproc; |
14 | ulong atime; |
15 | ulong mtime; |
16 | int ino; |
17 | }; |
18 | |
19 | enum{ |
20 | Maxatomic = 64*1024, |
21 | }; |
22 | |
23 | int |
24 | pipewrite(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 | |
53 | static int |
54 | closepipe(Ufile *file) |
55 | { |
56 | Pipe *pipe = (Pipe*)file; |
57 | |
58 | close(pipe->fd); |
59 | freebufproc(pipe->bufproc); |
60 | |
61 | return 0; |
62 | } |
63 | |
64 | static void* |
65 | bufprocpipe(Pipe *pipe) |
66 | { |
67 | if(pipe->bufproc == nil) |
68 | pipe->bufproc = newbufproc(pipe->fd); |
69 | return pipe->bufproc; |
70 | } |
71 | |
72 | static int |
73 | pollpipe(Ufile *file, void *tab) |
74 | { |
75 | Pipe *pipe = (Pipe*)file; |
76 | |
77 | return pollbufproc(bufprocpipe(pipe), pipe, tab); |
78 | } |
79 | |
80 | static int |
81 | readpipe(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 | |
101 | static int |
102 | writepipe(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 | |
113 | static int |
114 | ioctlpipe(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 | |
137 | int 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 | |
169 | static void |
170 | fillstat(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 | |
181 | static int |
182 | fstatpipe(Ufile *file, Ustat *s) |
183 | { |
184 | Pipe *pipe = (Pipe*)file; |
185 | fillstat(pipe, s); |
186 | return 0; |
187 | }; |
188 | |
189 | static Udev pipedev = |
190 | { |
191 | .read = readpipe, |
192 | .write = writepipe, |
193 | .poll = pollpipe, |
194 | .close = closepipe, |
195 | .ioctl = ioctlpipe, |
196 | .fstat = fstatpipe, |
197 | }; |
198 | |
199 | void pipedevinit(void) |
200 | { |
201 | devtab[PIPEDEV] = &pipedev; |
202 | } |