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 struct select_user select
; /* select user */
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
=
59 static int create_pipe( struct object
*obj
[2] )
61 struct pipe
*newpipe
[2];
69 if (!(newpipe
[0] = mem_alloc( sizeof(struct pipe
) )))
75 if (!(newpipe
[1] = mem_alloc( sizeof(struct pipe
) )))
82 init_object( &newpipe
[0]->obj
, &pipe_ops
, NULL
);
83 init_object( &newpipe
[1]->obj
, &pipe_ops
, NULL
);
84 newpipe
[0]->select
.fd
= fd
[0];
85 newpipe
[0]->select
.func
= default_select_event
;
86 newpipe
[0]->select
.private = newpipe
[0];
87 newpipe
[0]->other
= newpipe
[1];
88 newpipe
[0]->side
= READ_SIDE
;
89 newpipe
[1]->select
.fd
= fd
[1];
90 newpipe
[1]->select
.func
= default_select_event
;
91 newpipe
[1]->select
.private = newpipe
[1];
92 newpipe
[1]->other
= newpipe
[0];
93 newpipe
[1]->side
= WRITE_SIDE
;
94 obj
[0] = &newpipe
[0]->obj
;
95 obj
[1] = &newpipe
[1]->obj
;
96 register_select_user( &newpipe
[0]->select
);
97 register_select_user( &newpipe
[1]->select
);
102 static void pipe_dump( struct object
*obj
, int verbose
)
104 struct pipe
*pipe
= (struct pipe
*)obj
;
105 assert( obj
->ops
== &pipe_ops
);
106 fprintf( stderr
, "Pipe %s-side fd=%d\n",
107 (pipe
->side
== READ_SIDE
) ? "read" : "write", pipe
->select
.fd
);
110 static int pipe_add_queue( struct object
*obj
, struct wait_queue_entry
*entry
)
112 struct pipe
*pipe
= (struct pipe
*)obj
;
113 assert( obj
->ops
== &pipe_ops
);
114 if (!obj
->head
) /* first on the queue */
115 set_select_events( &pipe
->select
,
116 (pipe
->side
== READ_SIDE
) ? READ_EVENT
: WRITE_EVENT
);
117 add_queue( obj
, entry
);
121 static void pipe_remove_queue( struct object
*obj
, struct wait_queue_entry
*entry
)
123 struct pipe
*pipe
= (struct pipe
*)grab_object(obj
);
124 assert( obj
->ops
== &pipe_ops
);
126 remove_queue( obj
, entry
);
127 if (!obj
->head
) /* last on the queue is gone */
128 set_select_events( &pipe
->select
, 0 );
129 release_object( obj
);
132 static int pipe_signaled( struct object
*obj
, struct thread
*thread
)
135 struct pipe
*pipe
= (struct pipe
*)obj
;
136 assert( obj
->ops
== &pipe_ops
);
138 event
= (pipe
->side
== READ_SIDE
) ? READ_EVENT
: WRITE_EVENT
;
139 if (check_select_events( &pipe
->select
, event
))
141 /* stop waiting on select() if we are signaled */
142 set_select_events( &pipe
->select
, 0 );
147 /* restart waiting on select() if we are no longer signaled */
148 if (obj
->head
) set_select_events( &pipe
->select
, event
);
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
->select
.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
->select
.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
;
202 unregister_select_user( &pipe
->select
);
203 close( pipe
->select
.fd
);
207 /* create an anonymous pipe */
208 DECL_HANDLER(create_pipe
)
210 struct create_pipe_reply reply
= { -1, -1 };
211 struct object
*obj
[2];
212 if (create_pipe( obj
))
214 reply
.handle_read
= alloc_handle( current
->process
, obj
[0],
215 STANDARD_RIGHTS_REQUIRED
|SYNCHRONIZE
|GENERIC_READ
,
217 if (reply
.handle_read
!= -1)
219 reply
.handle_write
= alloc_handle( current
->process
, obj
[1],
220 STANDARD_RIGHTS_REQUIRED
|SYNCHRONIZE
|GENERIC_WRITE
,
222 if (reply
.handle_write
== -1)
223 close_handle( current
->process
, reply
.handle_read
);
225 release_object( obj
[0] );
226 release_object( obj
[1] );
228 send_reply( current
, -1, 1, &reply
, sizeof(reply
) );