Fixed ZDE build - missing header file
[ZeXOS.git] / kernel / lib / unistd / pipe.c
blobeb5e659552025289fc713b23f12aa7c6ec20c0f6
1 /*
2 * ZeX/OS
3 * Copyright (C) 2009 Martin 'povik' Poviser (martin.povik@gmail.com)
4 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
20 #include <system.h>
21 #include <string.h>
22 #include <fd.h>
23 #include <pipe.h>
24 #include <errno.h>
26 pipe_t *pipe_list_start;
27 pipe_t *pipe_list_end;
29 int pipe (int fds[2])
31 pipe_t *p = (pipe_t *) kmalloc (sizeof (pipe_t));
33 fd_t *fd = fd_create (FD_PIPE);
34 fds[0] = fd->id;
36 fd = fd_create (FD_PIPE);
37 fds[1] = fd->id;
39 if (!pipe_list_start) {
40 pipe_list_end = p;
41 pipe_list_start = p;
42 p->prev = NULL;
43 p->next = NULL;
44 } else {
45 pipe_list_end->next = p;
46 p->prev = pipe_list_end;
47 pipe_list_end = p;
48 p->next = NULL;
51 p->fd_a = fds[0];
52 p->fd_b = fds[1];
54 p->buffer_list_start = (pipe_buffer_t *) kmalloc (sizeof(pipe_buffer_t));
55 p->buffer_list_end = p->buffer_list_start;
56 p->buffer_list_start->next = NULL;
57 p->buffer_list_start->prev = NULL;
58 p->buffer_end_len = 0;
59 p->buffer_start_pos = 0;
61 return 0;
64 pipe_t *pipe_get (int fd)
66 pipe_t *p = pipe_list_start;
68 if (!p)
69 return NULL;
71 while (true) {
72 if (p->fd_a == fd
73 || p->fd_b == fd)
74 return p;
76 if (!p->next)
77 break;
78 else
79 p = p->next;
82 return NULL;
85 int pipe_write (pipe_t *p, BYTE *buffer, unsigned int buffer_len)
87 if ((!p) || (!buffer) || (!buffer_len) || (!p->buffer_list_start)) {
88 errno_set (EINVAL);
89 return -1;
92 { // hardcore code :)
93 unsigned int block_size = 0;
94 unsigned int buffer_pos = 0;
95 pipe_buffer_t *ptr;
96 while (buffer_pos < buffer_len) {
97 if ((buffer_len - buffer_pos) >= (PIPE_BUFFER_PART_SIZE - p->buffer_end_len)) {
98 ptr = p->buffer_list_end;
99 block_size = PIPE_BUFFER_PART_SIZE - p->buffer_end_len;
100 memcpy (((ptr->buffer) + p->buffer_end_len), ((buffer) + buffer_pos), block_size);
101 buffer_pos += block_size;
103 p->buffer_list_end = ((pipe_buffer_t*) kmalloc(sizeof (pipe_buffer_t)));
104 p->buffer_end_len = 0;
105 ptr->next = p->buffer_list_end;
106 p->buffer_list_end->prev = ptr;
107 } else {
108 ptr = p->buffer_list_end;
109 block_size = buffer_len - buffer_pos;
110 memcpy (((ptr->buffer) + p->buffer_end_len), ((buffer) + buffer_pos), block_size);
111 p->buffer_end_len += block_size;
112 buffer_pos += block_size;
116 return buffer_pos;
120 int pipe_read (pipe_t *p, BYTE *buffer, unsigned int buffer_len)
122 unsigned int buffer_pos = 0;
124 if ((!p) || (!buffer) || (!buffer_len) || (!p->buffer_list_start)) {
125 errno_set (EINVAL);
126 return -1;
129 while (true) { // hardcore code :)
130 while (buffer_pos < buffer_len) {
131 pipe_buffer_t *ptr;
132 unsigned int block_size = 0;
133 unsigned int buffer_space = buffer_len - buffer_pos;
135 if (p->buffer_list_start == p->buffer_list_end) {
136 unsigned int pipe_buffer_len = p->buffer_end_len - p->buffer_start_pos;
137 block_size = (pipe_buffer_len < buffer_space) ? (pipe_buffer_len) : (buffer_space);
139 if (p->buffer_start_pos == p->buffer_end_len)
140 break;
141 ptr = p->buffer_list_start;
142 memcpy (((buffer) + buffer_pos), ((ptr->buffer) + p->buffer_start_pos), block_size);
143 p->buffer_start_pos += block_size;
144 buffer_pos += block_size;
145 } else if (buffer_space >= PIPE_BUFFER_PART_SIZE - p->buffer_start_pos) {
146 ptr = p->buffer_list_start;
148 block_size = PIPE_BUFFER_PART_SIZE - p->buffer_start_pos;
149 memcpy (((buffer) + buffer_pos), ((ptr->buffer) + p->buffer_start_pos), block_size);
150 buffer_pos += block_size;
152 p->buffer_start_pos = 0;
153 p->buffer_list_start = ptr->next;
154 p->buffer_list_start->prev = NULL;
155 kfree(ptr);
156 } else {
157 ptr = p->buffer_list_start;
158 memcpy (((buffer) + buffer_pos), ((ptr->buffer) + p->buffer_start_pos), buffer_space);
159 p->buffer_start_pos += buffer_space;
163 if (buffer_pos == buffer_len)
164 return buffer_pos;
165 else
166 schedule();
170 void pipe_remove (pipe_t *pipe)
172 if (pipe->next)
173 pipe->next->prev = pipe->prev;
174 else {
175 if (pipe->prev)
176 pipe_list_end = pipe->prev;
177 else
178 pipe_list_end = NULL;
181 if (pipe->prev)
182 pipe->prev->next = pipe->next;
183 else {
184 if (pipe->next)
185 pipe_list_start = pipe->next;
186 else
187 pipe_list_start = NULL;
191 pipe_buffer_t *tmp;
192 pipe_buffer_t *p = pipe->buffer_list_start;
194 while (p) {
195 tmp = p;
196 p = p->next;
197 kfree (tmp);
201 kfree (pipe);
204 void pipe_close (int fd)
206 pipe_t *p = pipe_list_start;
208 if (!p)
209 return;
211 while (true) {
212 if (p->fd_a == fd) {
213 fd_delete (fd_get (fd));
214 p->fd_a = -1;
215 if (0 > p->fd_b)
216 pipe_remove(p);
217 return;
219 if (p->fd_b == fd) {
220 fd_delete (fd_get (fd));
221 p->fd_b = -1;
222 if (0 > p->fd_a)
223 pipe_remove(p);
224 return;
227 if (!p->next)
228 break;
229 else
230 p = p->next;
233 return;