pipe.c 5.32 KB
Newer Older
1 2 3 4
/*
 * Server-side pipe management
 *
 * Copyright (C) 1998 Alexandre Julliard
5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 20
 */

21 22
#include "config.h"

23 24
#include <assert.h>
#include <fcntl.h>
25
#include <string.h>
26 27
#include <stdio.h>
#include <stdlib.h>
28
#ifdef HAVE_SYS_ERRNO_H
29
#include <sys/errno.h>
30
#endif
31 32 33 34 35
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

36
#include "winbase.h"
37 38 39

#include "handle.h"
#include "thread.h"
40
#include "request.h"
41 42 43 44 45

enum side { READ_SIDE, WRITE_SIDE };

struct pipe
{
46 47 48
    struct object       obj;         /* object header */
    struct pipe        *other;       /* the pipe other end */
    enum side           side;        /* which side of the pipe is this */
49 50 51
};

static void pipe_dump( struct object *obj, int verbose );
52
static int pipe_get_poll_events( struct object *obj );
53
static int pipe_get_fd( struct object *obj );
54
static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
55 56 57 58
static void pipe_destroy( struct object *obj );

static const struct object_ops pipe_ops =
{
59 60 61 62 63 64 65 66
    sizeof(struct pipe),          /* size */
    pipe_dump,                    /* dump */
    default_poll_add_queue,       /* add_queue */
    default_poll_remove_queue,    /* remove_queue */
    default_poll_signaled,        /* signaled */
    no_satisfied,                 /* satisfied */
    pipe_get_poll_events,         /* get_poll_events */
    default_poll_event,           /* poll_event */
67
    pipe_get_fd,                  /* get_fd */
68 69
    no_flush,                     /* flush */
    pipe_get_info,                /* get_file_info */
70
    NULL,                         /* queue_async */
71
    pipe_destroy                  /* destroy */
72 73 74
};


75 76 77 78
static struct pipe *create_pipe_side( int fd, int side )
{
    struct pipe *pipe;

79
    if ((pipe = alloc_object( &pipe_ops, fd )))
80
    {
81 82
        pipe->other  = NULL;
        pipe->side   = side;
83 84 85 86
    }
    return pipe;
}

87
static int create_pipe( struct object *obj[2] )
88
{
89 90
    struct pipe *read_pipe;
    struct pipe *write_pipe;
91 92 93 94 95 96 97
    int fd[2];

    if (pipe( fd ) == -1)
    {
        file_set_error();
        return 0;
    }
98
    if ((read_pipe = create_pipe_side( fd[0], READ_SIDE )))
99
    {
100 101 102 103 104 105 106 107 108
        if ((write_pipe = create_pipe_side( fd[1], WRITE_SIDE )))
        {
            write_pipe->other = read_pipe;
            read_pipe->other  = write_pipe;
            obj[0] = &read_pipe->obj;
            obj[1] = &write_pipe->obj;
            return 1;
        }
        release_object( read_pipe );
109
    }
110
    else close( fd[1] );
111
    return 0;
112 113 114 115 116 117
}

static void pipe_dump( struct object *obj, int verbose )
{
    struct pipe *pipe = (struct pipe *)obj;
    assert( obj->ops == &pipe_ops );
118
    fprintf( stderr, "Pipe %s-side fd=%d\n",
119
             (pipe->side == READ_SIDE) ? "read" : "write", pipe->obj.fd );
120 121
}

122
static int pipe_get_poll_events( struct object *obj )
123 124 125
{
    struct pipe *pipe = (struct pipe *)obj;
    assert( obj->ops == &pipe_ops );
126
    return (pipe->side == READ_SIDE) ? POLLIN : POLLOUT;
127 128
}

129
static int pipe_get_fd( struct object *obj )
130 131 132 133 134 135
{
    struct pipe *pipe = (struct pipe *)obj;
    assert( obj->ops == &pipe_ops );

    if (!pipe->other)
    {
136
        set_error( STATUS_PIPE_BROKEN );
137 138
        return -1;
    }
139
    return pipe->obj.fd;
140 141
}

142
static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags )
143
{
144
    if (reply)
145
    {
146 147 148 149 150 151 152 153 154 155
        reply->type        = FILE_TYPE_PIPE;
        reply->attr        = 0;
        reply->access_time = 0;
        reply->write_time  = 0;
        reply->size_high   = 0;
        reply->size_low    = 0;
        reply->links       = 0;
        reply->index_high  = 0;
        reply->index_low   = 0;
        reply->serial      = 0;
156
    }
157
    *flags = 0;
158
    return FD_TYPE_DEFAULT;
159 160
}

161 162 163 164 165 166 167
static void pipe_destroy( struct object *obj )
{
    struct pipe *pipe = (struct pipe *)obj;
    assert( obj->ops == &pipe_ops );

    if (pipe->other) pipe->other->other = NULL;
}
168 169 170 171 172

/* create an anonymous pipe */
DECL_HANDLER(create_pipe)
{
    struct object *obj[2];
173
    handle_t hread = 0, hwrite = 0;
174

175 176
    if (create_pipe( obj ))
    {
177 178 179
        hread = alloc_handle( current->process, obj[0],
                              STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
                              req->inherit );
180
        if (hread)
181
        {
182 183 184
            hwrite = alloc_handle( current->process, obj[1],
                                   STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
                                   req->inherit );
185
            if (!hwrite) close_handle( current->process, hread, NULL );
186 187 188 189
        }
        release_object( obj[0] );
        release_object( obj[1] );
    }
190 191
    reply->handle_read  = hread;
    reply->handle_write = hwrite;
192
}