blob: d135a2250a78f72ac2e44755630069c002e2e067 [file] [log] [blame]
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +00001/*
2 * Server-side pipe management
3 *
4 * Copyright (C) 1998 Alexandre Julliard
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00005 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library 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 GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000019 */
20
Patrik Stridvall96336321999-10-24 22:13:47 +000021#include "config.h"
22
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000023#include <assert.h>
24#include <fcntl.h>
Alexandre Julliard05625391999-01-03 11:55:56 +000025#include <string.h>
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000026#include <stdio.h>
27#include <stdlib.h>
Howard Abrams13277481999-07-10 13:16:29 +000028#ifdef HAVE_SYS_ERRNO_H
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000029#include <sys/errno.h>
Howard Abrams13277481999-07-10 13:16:29 +000030#endif
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000031#include <sys/time.h>
32#include <sys/types.h>
33#include <time.h>
34#include <unistd.h>
35
Michael Vekslerf935c591999-02-09 15:49:39 +000036#include "winbase.h"
Alexandre Julliard43c190e1999-05-15 10:48:19 +000037
38#include "handle.h"
39#include "thread.h"
Alexandre Julliard5bc78081999-06-22 17:26:53 +000040#include "request.h"
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000041
42enum side { READ_SIDE, WRITE_SIDE };
43
44struct pipe
45{
Alexandre Julliard57e11311999-05-16 16:59:38 +000046 struct object obj; /* object header */
47 struct pipe *other; /* the pipe other end */
Alexandre Julliard57e11311999-05-16 16:59:38 +000048 enum side side; /* which side of the pipe is this */
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000049};
50
51static void pipe_dump( struct object *obj, int verbose );
Alexandre Julliard1dca5e22000-01-01 00:56:27 +000052static int pipe_get_poll_events( struct object *obj );
Alexandre Julliard1ab243b2000-12-19 02:12:45 +000053static int pipe_get_fd( struct object *obj );
Martin Wilck88cd32b2002-01-09 20:30:51 +000054static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000055static void pipe_destroy( struct object *obj );
56
57static const struct object_ops pipe_ops =
58{
Alexandre Julliard1dca5e22000-01-01 00:56:27 +000059 sizeof(struct pipe), /* size */
60 pipe_dump, /* dump */
61 default_poll_add_queue, /* add_queue */
62 default_poll_remove_queue, /* remove_queue */
63 default_poll_signaled, /* signaled */
64 no_satisfied, /* satisfied */
65 pipe_get_poll_events, /* get_poll_events */
66 default_poll_event, /* poll_event */
Alexandre Julliard1ab243b2000-12-19 02:12:45 +000067 pipe_get_fd, /* get_fd */
Alexandre Julliard1dca5e22000-01-01 00:56:27 +000068 no_flush, /* flush */
69 pipe_get_info, /* get_file_info */
Mike McCormack6f011c02001-12-20 00:07:05 +000070 NULL, /* queue_async */
Alexandre Julliard1dca5e22000-01-01 00:56:27 +000071 pipe_destroy /* destroy */
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000072};
73
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000074
Alexandre Julliard5bc78081999-06-22 17:26:53 +000075static struct pipe *create_pipe_side( int fd, int side )
76{
77 struct pipe *pipe;
78
Alexandre Julliard1dca5e22000-01-01 00:56:27 +000079 if ((pipe = alloc_object( &pipe_ops, fd )))
Alexandre Julliard5bc78081999-06-22 17:26:53 +000080 {
Alexandre Julliard247b8ae1999-12-13 00:16:44 +000081 pipe->other = NULL;
82 pipe->side = side;
Alexandre Julliard5bc78081999-06-22 17:26:53 +000083 }
84 return pipe;
85}
86
Alexandre Julliard43c190e1999-05-15 10:48:19 +000087static int create_pipe( struct object *obj[2] )
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000088{
Alexandre Julliard5bc78081999-06-22 17:26:53 +000089 struct pipe *read_pipe;
90 struct pipe *write_pipe;
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000091 int fd[2];
92
93 if (pipe( fd ) == -1)
94 {
95 file_set_error();
96 return 0;
97 }
Alexandre Julliard5bc78081999-06-22 17:26:53 +000098 if ((read_pipe = create_pipe_side( fd[0], READ_SIDE )))
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000099 {
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000100 if ((write_pipe = create_pipe_side( fd[1], WRITE_SIDE )))
101 {
102 write_pipe->other = read_pipe;
103 read_pipe->other = write_pipe;
104 obj[0] = &read_pipe->obj;
105 obj[1] = &write_pipe->obj;
106 return 1;
107 }
108 release_object( read_pipe );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000109 }
Alexandre Julliard1dca5e22000-01-01 00:56:27 +0000110 else close( fd[1] );
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000111 return 0;
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000112}
113
114static void pipe_dump( struct object *obj, int verbose )
115{
116 struct pipe *pipe = (struct pipe *)obj;
117 assert( obj->ops == &pipe_ops );
Alexandre Julliard05625391999-01-03 11:55:56 +0000118 fprintf( stderr, "Pipe %s-side fd=%d\n",
Alexandre Julliard1dca5e22000-01-01 00:56:27 +0000119 (pipe->side == READ_SIDE) ? "read" : "write", pipe->obj.fd );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000120}
121
Alexandre Julliard1dca5e22000-01-01 00:56:27 +0000122static int pipe_get_poll_events( struct object *obj )
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000123{
124 struct pipe *pipe = (struct pipe *)obj;
125 assert( obj->ops == &pipe_ops );
Alexandre Julliard1dca5e22000-01-01 00:56:27 +0000126 return (pipe->side == READ_SIDE) ? POLLIN : POLLOUT;
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000127}
128
Alexandre Julliard1ab243b2000-12-19 02:12:45 +0000129static int pipe_get_fd( struct object *obj )
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000130{
131 struct pipe *pipe = (struct pipe *)obj;
132 assert( obj->ops == &pipe_ops );
133
134 if (!pipe->other)
135 {
Alexandre Julliardcb1fc732000-01-24 21:58:06 +0000136 set_error( STATUS_PIPE_BROKEN );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000137 return -1;
138 }
Alexandre Julliard63411db2000-12-22 21:12:36 +0000139 return pipe->obj.fd;
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000140}
141
Martin Wilck88cd32b2002-01-09 20:30:51 +0000142static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags )
Alexandre Julliard05625391999-01-03 11:55:56 +0000143{
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000144 if (reply)
Mike McCormackff58be52001-10-04 16:18:15 +0000145 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000146 reply->type = FILE_TYPE_PIPE;
147 reply->attr = 0;
148 reply->access_time = 0;
149 reply->write_time = 0;
150 reply->size_high = 0;
151 reply->size_low = 0;
152 reply->links = 0;
153 reply->index_high = 0;
154 reply->index_low = 0;
155 reply->serial = 0;
Mike McCormackff58be52001-10-04 16:18:15 +0000156 }
Martin Wilck88cd32b2002-01-09 20:30:51 +0000157 *flags = 0;
Mike McCormackff58be52001-10-04 16:18:15 +0000158 return FD_TYPE_DEFAULT;
Alexandre Julliard05625391999-01-03 11:55:56 +0000159}
160
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000161static void pipe_destroy( struct object *obj )
162{
163 struct pipe *pipe = (struct pipe *)obj;
164 assert( obj->ops == &pipe_ops );
165
166 if (pipe->other) pipe->other->other = NULL;
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000167}
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000168
169/* create an anonymous pipe */
170DECL_HANDLER(create_pipe)
171{
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000172 struct object *obj[2];
Alexandre Julliard51885742002-05-30 20:12:58 +0000173 obj_handle_t hread = 0, hwrite = 0;
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000174
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000175 if (create_pipe( obj ))
176 {
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000177 hread = alloc_handle( current->process, obj[0],
178 STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
179 req->inherit );
Alexandre Julliard8081e5a2001-01-05 04:08:07 +0000180 if (hread)
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000181 {
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000182 hwrite = alloc_handle( current->process, obj[1],
183 STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
184 req->inherit );
Alexandre Julliard8081e5a2001-01-05 04:08:07 +0000185 if (!hwrite) close_handle( current->process, hread, NULL );
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000186 }
187 release_object( obj[0] );
188 release_object( obj[1] );
189 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000190 reply->handle_read = hread;
191 reply->handle_write = hwrite;
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000192}