2 * Server-side pipe management
4 * Copyright (C) 1998 Alexandre Julliard
12 #include <sys/errno.h>
15 #include <sys/types.h>
25 enum side
{ READ_SIDE
, WRITE_SIDE
};
29 struct object obj
; /* object header */
30 struct pipe
*other
; /* the pipe other end */
31 int fd
; /* Unix file descriptor */
32 enum side side
; /* which side of the pipe is this */
35 static void pipe_dump( struct object
*obj
, int verbose
);
36 static int pipe_add_queue( struct object
*obj
, struct wait_queue_entry
*entry
);
37 static void pipe_remove_queue( struct object
*obj
, struct wait_queue_entry
*entry
);
38 static int pipe_signaled( struct object
*obj
, struct thread
*thread
);
39 static int pipe_get_read_fd( struct object
*obj
);
40 static int pipe_get_write_fd( struct object
*obj
);
41 static int pipe_get_info( struct object
*obj
, struct get_file_info_reply
*reply
);
42 static void pipe_destroy( struct object
*obj
);
44 static const struct object_ops pipe_ops
=
58 static const struct select_ops select_ops
=
61 NULL
/* we never set a timeout on a pipe */
64 static int create_pipe( struct object
*obj
[2] )
66 struct pipe
*newpipe
[2];
74 if (!(newpipe
[0] = mem_alloc( sizeof(struct pipe
) )))
80 if (!(newpipe
[1] = mem_alloc( sizeof(struct pipe
) )))
87 init_object( &newpipe
[0]->obj
, &pipe_ops
, NULL
);
88 init_object( &newpipe
[1]->obj
, &pipe_ops
, NULL
);
89 newpipe
[0]->fd
= fd
[0];
90 newpipe
[0]->other
= newpipe
[1];
91 newpipe
[0]->side
= READ_SIDE
;
92 newpipe
[1]->fd
= fd
[1];
93 newpipe
[1]->other
= newpipe
[0];
94 newpipe
[1]->side
= WRITE_SIDE
;
95 obj
[0] = &newpipe
[0]->obj
;
96 obj
[1] = &newpipe
[1]->obj
;
101 static void pipe_dump( struct object
*obj
, int verbose
)
103 struct pipe
*pipe
= (struct pipe
*)obj
;
104 assert( obj
->ops
== &pipe_ops
);
105 fprintf( stderr
, "Pipe %s-side fd=%d\n",
106 (pipe
->side
== READ_SIDE
) ? "read" : "write", pipe
->fd
);
109 static int pipe_add_queue( struct object
*obj
, struct wait_queue_entry
*entry
)
111 struct pipe
*pipe
= (struct pipe
*)obj
;
112 assert( obj
->ops
== &pipe_ops
);
113 if (!obj
->head
) /* first on the queue */
115 if (!add_select_user( pipe
->fd
,
116 (pipe
->side
== READ_SIDE
) ? READ_EVENT
: WRITE_EVENT
,
119 SET_ERROR( ERROR_OUTOFMEMORY
);
123 add_queue( obj
, entry
);
127 static void pipe_remove_queue( struct object
*obj
, struct wait_queue_entry
*entry
)
129 struct pipe
*pipe
= (struct pipe
*)grab_object(obj
);
130 assert( obj
->ops
== &pipe_ops
);
132 remove_queue( obj
, entry
);
133 if (!obj
->head
) /* last on the queue is gone */
134 remove_select_user( pipe
->fd
);
135 release_object( obj
);
138 static int pipe_signaled( struct object
*obj
, struct thread
*thread
)
140 struct pipe
*pipe
= (struct pipe
*)obj
;
141 struct timeval tv
= { 0, 0 };
144 assert( obj
->ops
== &pipe_ops
);
146 FD_SET( pipe
->fd
, &fds
);
147 if (pipe
->side
== READ_SIDE
)
148 return select( pipe
->fd
+ 1, &fds
, NULL
, NULL
, &tv
) > 0;
150 return select( pipe
->fd
+ 1, NULL
, &fds
, NULL
, &tv
) > 0;
153 static int pipe_get_read_fd( struct object
*obj
)
155 struct pipe
*pipe
= (struct pipe
*)obj
;
156 assert( obj
->ops
== &pipe_ops
);
160 SET_ERROR( ERROR_BROKEN_PIPE
);
163 if (pipe
->side
!= READ_SIDE
) /* FIXME: should not be necessary */
165 SET_ERROR( ERROR_ACCESS_DENIED
);
168 return dup( pipe
->fd
);
171 static int pipe_get_write_fd( struct object
*obj
)
173 struct pipe
*pipe
= (struct pipe
*)obj
;
174 assert( obj
->ops
== &pipe_ops
);
178 SET_ERROR( ERROR_BROKEN_PIPE
);
181 if (pipe
->side
!= WRITE_SIDE
) /* FIXME: should not be necessary */
183 SET_ERROR( ERROR_ACCESS_DENIED
);
186 return dup( pipe
->fd
);
189 static int pipe_get_info( struct object
*obj
, struct get_file_info_reply
*reply
)
191 memset( reply
, 0, sizeof(*reply
) );
192 reply
->type
= FILE_TYPE_PIPE
;
196 static void pipe_destroy( struct object
*obj
)
198 struct pipe
*pipe
= (struct pipe
*)obj
;
199 assert( obj
->ops
== &pipe_ops
);
201 if (pipe
->other
) pipe
->other
->other
= NULL
;
206 /* create an anonymous pipe */
207 DECL_HANDLER(create_pipe
)
209 struct create_pipe_reply reply
= { -1, -1 };
210 struct object
*obj
[2];
211 if (create_pipe( obj
))
213 reply
.handle_read
= alloc_handle( current
->process
, obj
[0],
214 STANDARD_RIGHTS_REQUIRED
|SYNCHRONIZE
|GENERIC_READ
,
216 if (reply
.handle_read
!= -1)
218 reply
.handle_write
= alloc_handle( current
->process
, obj
[1],
219 STANDARD_RIGHTS_REQUIRED
|SYNCHRONIZE
|GENERIC_WRITE
,
221 if (reply
.handle_write
== -1)
222 close_handle( current
->process
, reply
.handle_read
);
224 release_object( obj
[0] );
225 release_object( obj
[1] );
227 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );