blob: ddd200bbac4c22d086a4f2be314a6624f43bfffe [file] [log] [blame]
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +00001/*
2 * Server-side pipe management
3 *
4 * Copyright (C) 1998 Alexandre Julliard
5 */
6
Patrik Stridvall96336321999-10-24 22:13:47 +00007#include "config.h"
8
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +00009#include <assert.h>
10#include <fcntl.h>
Alexandre Julliard05625391999-01-03 11:55:56 +000011#include <string.h>
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000012#include <stdio.h>
13#include <stdlib.h>
Howard Abrams13277481999-07-10 13:16:29 +000014#ifdef HAVE_SYS_ERRNO_H
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000015#include <sys/errno.h>
Howard Abrams13277481999-07-10 13:16:29 +000016#endif
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000017#include <sys/time.h>
18#include <sys/types.h>
19#include <time.h>
20#include <unistd.h>
21
Michael Vekslerf935c591999-02-09 15:49:39 +000022#include "winbase.h"
Alexandre Julliard43c190e1999-05-15 10:48:19 +000023
24#include "handle.h"
25#include "thread.h"
Alexandre Julliard5bc78081999-06-22 17:26:53 +000026#include "request.h"
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000027
28enum side { READ_SIDE, WRITE_SIDE };
29
30struct pipe
31{
Alexandre Julliard57e11311999-05-16 16:59:38 +000032 struct object obj; /* object header */
33 struct pipe *other; /* the pipe other end */
Alexandre Julliard57e11311999-05-16 16:59:38 +000034 enum side side; /* which side of the pipe is this */
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000035};
36
37static void pipe_dump( struct object *obj, int verbose );
Alexandre Julliard1dca5e22000-01-01 00:56:27 +000038static int pipe_get_poll_events( struct object *obj );
Alexandre Julliard1ab243b2000-12-19 02:12:45 +000039static int pipe_get_fd( struct object *obj );
Alexandre Julliard9caa71e2001-11-30 18:46:42 +000040static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000041static void pipe_destroy( struct object *obj );
42
43static const struct object_ops pipe_ops =
44{
Alexandre Julliard1dca5e22000-01-01 00:56:27 +000045 sizeof(struct pipe), /* size */
46 pipe_dump, /* dump */
47 default_poll_add_queue, /* add_queue */
48 default_poll_remove_queue, /* remove_queue */
49 default_poll_signaled, /* signaled */
50 no_satisfied, /* satisfied */
51 pipe_get_poll_events, /* get_poll_events */
52 default_poll_event, /* poll_event */
Alexandre Julliard1ab243b2000-12-19 02:12:45 +000053 pipe_get_fd, /* get_fd */
Alexandre Julliard1dca5e22000-01-01 00:56:27 +000054 no_flush, /* flush */
55 pipe_get_info, /* get_file_info */
56 pipe_destroy /* destroy */
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000057};
58
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000059
Alexandre Julliard5bc78081999-06-22 17:26:53 +000060static struct pipe *create_pipe_side( int fd, int side )
61{
62 struct pipe *pipe;
63
Alexandre Julliard1dca5e22000-01-01 00:56:27 +000064 if ((pipe = alloc_object( &pipe_ops, fd )))
Alexandre Julliard5bc78081999-06-22 17:26:53 +000065 {
Alexandre Julliard247b8ae1999-12-13 00:16:44 +000066 pipe->other = NULL;
67 pipe->side = side;
Alexandre Julliard5bc78081999-06-22 17:26:53 +000068 }
69 return pipe;
70}
71
Alexandre Julliard43c190e1999-05-15 10:48:19 +000072static int create_pipe( struct object *obj[2] )
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000073{
Alexandre Julliard5bc78081999-06-22 17:26:53 +000074 struct pipe *read_pipe;
75 struct pipe *write_pipe;
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000076 int fd[2];
77
78 if (pipe( fd ) == -1)
79 {
80 file_set_error();
81 return 0;
82 }
Alexandre Julliard5bc78081999-06-22 17:26:53 +000083 if ((read_pipe = create_pipe_side( fd[0], READ_SIDE )))
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000084 {
Alexandre Julliard5bc78081999-06-22 17:26:53 +000085 if ((write_pipe = create_pipe_side( fd[1], WRITE_SIDE )))
86 {
87 write_pipe->other = read_pipe;
88 read_pipe->other = write_pipe;
89 obj[0] = &read_pipe->obj;
90 obj[1] = &write_pipe->obj;
91 return 1;
92 }
93 release_object( read_pipe );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000094 }
Alexandre Julliard1dca5e22000-01-01 00:56:27 +000095 else close( fd[1] );
Alexandre Julliard5bc78081999-06-22 17:26:53 +000096 return 0;
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000097}
98
99static void pipe_dump( struct object *obj, int verbose )
100{
101 struct pipe *pipe = (struct pipe *)obj;
102 assert( obj->ops == &pipe_ops );
Alexandre Julliard05625391999-01-03 11:55:56 +0000103 fprintf( stderr, "Pipe %s-side fd=%d\n",
Alexandre Julliard1dca5e22000-01-01 00:56:27 +0000104 (pipe->side == READ_SIDE) ? "read" : "write", pipe->obj.fd );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000105}
106
Alexandre Julliard1dca5e22000-01-01 00:56:27 +0000107static int pipe_get_poll_events( struct object *obj )
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000108{
109 struct pipe *pipe = (struct pipe *)obj;
110 assert( obj->ops == &pipe_ops );
Alexandre Julliard1dca5e22000-01-01 00:56:27 +0000111 return (pipe->side == READ_SIDE) ? POLLIN : POLLOUT;
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000112}
113
Alexandre Julliard1ab243b2000-12-19 02:12:45 +0000114static int pipe_get_fd( struct object *obj )
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000115{
116 struct pipe *pipe = (struct pipe *)obj;
117 assert( obj->ops == &pipe_ops );
118
119 if (!pipe->other)
120 {
Alexandre Julliardcb1fc732000-01-24 21:58:06 +0000121 set_error( STATUS_PIPE_BROKEN );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000122 return -1;
123 }
Alexandre Julliard63411db2000-12-22 21:12:36 +0000124 return pipe->obj.fd;
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000125}
126
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000127static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply )
Alexandre Julliard05625391999-01-03 11:55:56 +0000128{
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000129 if (reply)
Mike McCormackff58be52001-10-04 16:18:15 +0000130 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000131 reply->type = FILE_TYPE_PIPE;
132 reply->attr = 0;
133 reply->access_time = 0;
134 reply->write_time = 0;
135 reply->size_high = 0;
136 reply->size_low = 0;
137 reply->links = 0;
138 reply->index_high = 0;
139 reply->index_low = 0;
140 reply->serial = 0;
Mike McCormackff58be52001-10-04 16:18:15 +0000141 }
142 return FD_TYPE_DEFAULT;
Alexandre Julliard05625391999-01-03 11:55:56 +0000143}
144
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000145static void pipe_destroy( struct object *obj )
146{
147 struct pipe *pipe = (struct pipe *)obj;
148 assert( obj->ops == &pipe_ops );
149
150 if (pipe->other) pipe->other->other = NULL;
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000151}
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000152
153/* create an anonymous pipe */
154DECL_HANDLER(create_pipe)
155{
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000156 struct object *obj[2];
Alexandre Julliard8081e5a2001-01-05 04:08:07 +0000157 handle_t hread = 0, hwrite = 0;
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000158
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000159 if (create_pipe( obj ))
160 {
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000161 hread = alloc_handle( current->process, obj[0],
162 STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
163 req->inherit );
Alexandre Julliard8081e5a2001-01-05 04:08:07 +0000164 if (hread)
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000165 {
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000166 hwrite = alloc_handle( current->process, obj[1],
167 STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
168 req->inherit );
Alexandre Julliard8081e5a2001-01-05 04:08:07 +0000169 if (!hwrite) close_handle( current->process, hread, NULL );
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000170 }
171 release_object( obj[0] );
172 release_object( obj[1] );
173 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000174 reply->handle_read = hread;
175 reply->handle_write = hwrite;
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000176}