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