Added an inode object to keep track of all file descriptors open for a
[wine] / server / pipe.c
1 /*
2  * Server-side pipe management
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  *
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
19  */
20
21 #include "config.h"
22
23 #include <assert.h>
24 #include <fcntl.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <sys/time.h>
29 #include <sys/types.h>
30 #include <time.h>
31 #include <unistd.h>
32
33 #include "winbase.h"
34
35 #include "file.h"
36 #include "handle.h"
37 #include "thread.h"
38 #include "request.h"
39
40 enum side { READ_SIDE, WRITE_SIDE };
41
42 struct pipe
43 {
44     struct object       obj;         /* object header */
45     struct fd          *fd;          /* pipe file descriptor */
46     struct pipe        *other;       /* the pipe other end */
47     enum side           side;        /* which side of the pipe is this */
48 };
49
50 static void pipe_dump( struct object *obj, int verbose );
51 static struct fd *pipe_get_fd( struct object *obj );
52 static void pipe_destroy( struct object *obj );
53
54 static int pipe_get_poll_events( struct fd *fd );
55 static int pipe_get_info( struct fd *fd, struct get_file_info_reply *reply, int *flags );
56
57 static const struct object_ops pipe_ops =
58 {
59     sizeof(struct pipe),          /* size */
60     pipe_dump,                    /* dump */
61     default_fd_add_queue,         /* add_queue */
62     default_fd_remove_queue,      /* remove_queue */
63     default_fd_signaled,          /* signaled */
64     no_satisfied,                 /* satisfied */
65     pipe_get_fd,                  /* get_fd */
66     pipe_destroy                  /* destroy */
67 };
68
69 static const struct fd_ops pipe_fd_ops =
70 {
71     pipe_get_poll_events,         /* get_poll_events */
72     default_poll_event,           /* poll_event */
73     no_flush,                     /* flush */
74     pipe_get_info,                /* get_file_info */
75     no_queue_async                /* queue_async */
76 };
77
78
79 static struct pipe *create_pipe_side( int fd, int side )
80 {
81     struct pipe *pipe;
82
83     if ((pipe = alloc_object( &pipe_ops )))
84     {
85         pipe->other  = NULL;
86         pipe->side   = side;
87     }
88     if (!(pipe->fd = create_anonymous_fd( &pipe_fd_ops, fd, &pipe->obj )))
89     {
90         release_object( pipe );
91         return NULL;
92     }
93     return pipe;
94 }
95
96 static int create_pipe( struct object *obj[2] )
97 {
98     struct pipe *read_pipe;
99     struct pipe *write_pipe;
100     int fd[2];
101
102     if (pipe( fd ) == -1)
103     {
104         file_set_error();
105         return 0;
106     }
107     if ((read_pipe = create_pipe_side( fd[0], READ_SIDE )))
108     {
109         if ((write_pipe = create_pipe_side( fd[1], WRITE_SIDE )))
110         {
111             write_pipe->other = read_pipe;
112             read_pipe->other  = write_pipe;
113             obj[0] = &read_pipe->obj;
114             obj[1] = &write_pipe->obj;
115             return 1;
116         }
117         release_object( read_pipe );
118     }
119     else close( fd[1] );
120     return 0;
121 }
122
123 static void pipe_dump( struct object *obj, int verbose )
124 {
125     struct pipe *pipe = (struct pipe *)obj;
126     assert( obj->ops == &pipe_ops );
127     fprintf( stderr, "Pipe %s-side fd=%p\n",
128              (pipe->side == READ_SIDE) ? "read" : "write", pipe->fd );
129 }
130
131 static int pipe_get_poll_events( struct fd *fd )
132 {
133     struct pipe *pipe = get_fd_user( fd );
134     assert( pipe->obj.ops == &pipe_ops );
135     return (pipe->side == READ_SIDE) ? POLLIN : POLLOUT;
136 }
137
138 static struct fd *pipe_get_fd( struct object *obj )
139 {
140     struct pipe *pipe = (struct pipe *)obj;
141     assert( obj->ops == &pipe_ops );
142
143     if (!pipe->other)
144     {
145         set_error( STATUS_PIPE_BROKEN );
146         return NULL;
147     }
148     return (struct fd *)grab_object( pipe->fd );
149 }
150
151 static int pipe_get_info( struct fd *fd, struct get_file_info_reply *reply, int *flags )
152 {
153     if (reply)
154     {
155         reply->type        = FILE_TYPE_PIPE;
156         reply->attr        = 0;
157         reply->access_time = 0;
158         reply->write_time  = 0;
159         reply->size_high   = 0;
160         reply->size_low    = 0;
161         reply->links       = 0;
162         reply->index_high  = 0;
163         reply->index_low   = 0;
164         reply->serial      = 0;
165     }
166     *flags = 0;
167     return FD_TYPE_DEFAULT;
168 }
169
170 static void pipe_destroy( struct object *obj )
171 {
172     struct pipe *pipe = (struct pipe *)obj;
173     assert( obj->ops == &pipe_ops );
174
175     if (pipe->other) pipe->other->other = NULL;
176     if (pipe->fd) release_object( pipe->fd );
177 }
178
179 /* create an anonymous pipe */
180 DECL_HANDLER(create_pipe)
181 {
182     struct object *obj[2];
183     obj_handle_t hread = 0, hwrite = 0;
184
185     if (create_pipe( obj ))
186     {
187         hread = alloc_handle( current->process, obj[0],
188                               STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
189                               req->inherit );
190         if (hread)
191         {
192             hwrite = alloc_handle( current->process, obj[1],
193                                    STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
194                                    req->inherit );
195             if (!hwrite) close_handle( current->process, hread, NULL );
196         }
197         release_object( obj[0] );
198         release_object( obj[1] );
199     }
200     reply->handle_read  = hread;
201     reply->handle_write = hwrite;
202 }