1 /*
2 Copyright (C) 2001-2015, Parrot Foundation.
3 
4 =head1 NAME
5 
6 src/io/pipe.c - IO_VTABLE and helpers for Pipes
7 
8 =head1 DESCRIPTION
9 
10 This file implements the IO_VTABLE for pipes and helper functions.
11 
12 =head2 IO_VTABLE Functions
13 
14 =over 4
15 
16 =cut
17 
18 */
19 
20 #include "parrot/parrot.h"
21 #include "io_private.h"
22 #include "pmc/pmc_filehandle.h"
23 
24 /* HEADERIZER HFILE: src/io/io_private.h */
25 
26 /* HEADERIZER BEGIN: static */
27 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
28 
29 static void io_pipe_adv_position(PARROT_INTERP,
30     ARGMOD_NULLOK(PMC *handle),
31     const size_t offset)
32         FUNC_MODIFIES(*handle);
33 
34 static INTVAL io_pipe_close(PARROT_INTERP, ARGMOD(PMC *handle))
35         __attribute__nonnull__(1)
36         __attribute__nonnull__(2)
37         FUNC_MODIFIES(*handle);
38 
39 static INTVAL io_pipe_flush(PARROT_INTERP, ARGMOD(PMC *handle))
40         __attribute__nonnull__(1)
41         __attribute__nonnull__(2)
42         FUNC_MODIFIES(*handle);
43 
44 PARROT_CAN_RETURN_NULL
45 PARROT_WARN_UNUSED_RESULT
46 static const STR_VTABLE * io_pipe_get_encoding(PARROT_INTERP,
47     ARGIN(const PMC *handle))
48         __attribute__nonnull__(1)
49         __attribute__nonnull__(2);
50 
51 static INTVAL io_pipe_get_flags(PARROT_INTERP, ARGIN(const PMC *handle))
52         __attribute__nonnull__(2);
53 
54 static PIOHANDLE io_pipe_get_piohandle(PARROT_INTERP,
55     ARGIN(const PMC *handle))
56         __attribute__nonnull__(1)
57         __attribute__nonnull__(2);
58 
59 static PIOOFF_T io_pipe_get_position(PARROT_INTERP,
60     ARGIN_NULLOK(const PMC *handle));
61 
62 static INTVAL io_pipe_is_eof(PARROT_INTERP, ARGIN(const PMC *handle))
63         __attribute__nonnull__(1)
64         __attribute__nonnull__(2);
65 
66 static INTVAL io_pipe_is_open(PARROT_INTERP, ARGIN(const PMC *handle))
67         __attribute__nonnull__(1)
68         __attribute__nonnull__(2);
69 
70 static INTVAL io_pipe_open(PARROT_INTERP,
71     ARGMOD(PMC *handle),
72     ARGIN(const STRING *path),
73     const INTVAL flags,
74     ARGIN(const STRING *mode))
75         __attribute__nonnull__(1)
76         __attribute__nonnull__(2)
77         __attribute__nonnull__(3)
78         __attribute__nonnull__(5)
79         FUNC_MODIFIES(*handle);
80 
81 static INTVAL io_pipe_read_b(PARROT_INTERP,
82     ARGMOD(PMC *handle),
83     ARGOUT(char *buffer),
84     const size_t byte_length)
85         __attribute__nonnull__(1)
86         __attribute__nonnull__(2)
87         __attribute__nonnull__(3)
88         FUNC_MODIFIES(*handle)
89         FUNC_MODIFIES(*buffer);
90 
91 static PIOOFF_T io_pipe_seek(PARROT_INTERP,
92     ARGMOD(PMC *handle),
93     const PIOOFF_T offset,
94     const INTVAL whence)
95         __attribute__nonnull__(1)
96         __attribute__nonnull__(2)
97         FUNC_MODIFIES(*handle);
98 
99 static void io_pipe_set_eof(PARROT_INTERP,
100     ARGMOD(PMC *handle),
101     const INTVAL is_set)
102         __attribute__nonnull__(2)
103         FUNC_MODIFIES(*handle);
104 
105 static void io_pipe_set_flags(PARROT_INTERP,
106     ARGMOD(PMC *handle),
107     const INTVAL flags)
108         __attribute__nonnull__(2)
109         FUNC_MODIFIES(*handle);
110 
111 static void io_pipe_set_position(PARROT_INTERP,
112     ARGMOD_NULLOK(PMC *handle),
113     const PIOOFF_T pos)
114         FUNC_MODIFIES(*handle);
115 
116 static PIOOFF_T io_pipe_tell(PARROT_INTERP, ARGIN(const PMC *handle))
117         __attribute__nonnull__(1)
118         __attribute__nonnull__(2);
119 
120 static size_t io_pipe_total_size(PARROT_INTERP,
121     ARGIN_NULLOK(const PMC *handle));
122 
123 static INTVAL io_pipe_write_b(PARROT_INTERP,
124     ARGMOD(PMC *handle),
125     ARGIN(const char *buffer),
126     const size_t byte_length)
127         __attribute__nonnull__(1)
128         __attribute__nonnull__(2)
129         __attribute__nonnull__(3)
130         FUNC_MODIFIES(*handle);
131 
132 #define ASSERT_ARGS_io_pipe_adv_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
133 #define ASSERT_ARGS_io_pipe_close __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
134        PARROT_ASSERT_ARG(interp) \
135     , PARROT_ASSERT_ARG(handle))
136 #define ASSERT_ARGS_io_pipe_flush __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
137        PARROT_ASSERT_ARG(interp) \
138     , PARROT_ASSERT_ARG(handle))
139 #define ASSERT_ARGS_io_pipe_get_encoding __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
140        PARROT_ASSERT_ARG(interp) \
141     , PARROT_ASSERT_ARG(handle))
142 #define ASSERT_ARGS_io_pipe_get_flags __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
143        PARROT_ASSERT_ARG(handle))
144 #define ASSERT_ARGS_io_pipe_get_piohandle __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
145        PARROT_ASSERT_ARG(interp) \
146     , PARROT_ASSERT_ARG(handle))
147 #define ASSERT_ARGS_io_pipe_get_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
148 #define ASSERT_ARGS_io_pipe_is_eof __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
149        PARROT_ASSERT_ARG(interp) \
150     , PARROT_ASSERT_ARG(handle))
151 #define ASSERT_ARGS_io_pipe_is_open __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
152        PARROT_ASSERT_ARG(interp) \
153     , PARROT_ASSERT_ARG(handle))
154 #define ASSERT_ARGS_io_pipe_open __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
155        PARROT_ASSERT_ARG(interp) \
156     , PARROT_ASSERT_ARG(handle) \
157     , PARROT_ASSERT_ARG(path) \
158     , PARROT_ASSERT_ARG(mode))
159 #define ASSERT_ARGS_io_pipe_read_b __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
160        PARROT_ASSERT_ARG(interp) \
161     , PARROT_ASSERT_ARG(handle) \
162     , PARROT_ASSERT_ARG(buffer))
163 #define ASSERT_ARGS_io_pipe_seek __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
164        PARROT_ASSERT_ARG(interp) \
165     , PARROT_ASSERT_ARG(handle))
166 #define ASSERT_ARGS_io_pipe_set_eof __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
167        PARROT_ASSERT_ARG(handle))
168 #define ASSERT_ARGS_io_pipe_set_flags __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
169        PARROT_ASSERT_ARG(handle))
170 #define ASSERT_ARGS_io_pipe_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
171 #define ASSERT_ARGS_io_pipe_tell __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
172        PARROT_ASSERT_ARG(interp) \
173     , PARROT_ASSERT_ARG(handle))
174 #define ASSERT_ARGS_io_pipe_total_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
175 #define ASSERT_ARGS_io_pipe_write_b __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
176        PARROT_ASSERT_ARG(interp) \
177     , PARROT_ASSERT_ARG(handle) \
178     , PARROT_ASSERT_ARG(buffer))
179 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
180 /* HEADERIZER END: static */
181 
182 /*
183 
184 =item C<void io_pipe_setup_vtable(PARROT_INTERP, IO_VTABLE *vtable, const INTVAL
185 idx)>
186 
187 Set up the Pipe IO_VTABLE.
188 
189 =cut
190 
191 */
192 
193 void
io_pipe_setup_vtable(PARROT_INTERP,ARGMOD_NULLOK (IO_VTABLE * vtable),const INTVAL idx)194 io_pipe_setup_vtable(PARROT_INTERP, ARGMOD_NULLOK(IO_VTABLE *vtable), const INTVAL idx)
195 {
196     ASSERT_ARGS(io_pipe_setup_vtable)
197     if (vtable == NULL)
198         vtable = IO_EDITABLE_IO_VTABLE(interp, idx);
199     vtable->number = idx;
200     vtable->flags = PIO_VF_DEFAULT_READ_BUF     /* Use read buffers by default */
201                   | PIO_VF_MULTI_READABLE       /* Can read multiple times without hanging */
202                   | PIO_VF_FLUSH_ON_CLOSE;      /* Flush handle on close */
203     vtable->name = "Pipe";
204     vtable->read_b = io_pipe_read_b;
205     vtable->write_b = io_pipe_write_b;
206     vtable->flush = io_pipe_flush;
207     vtable->is_eof = io_pipe_is_eof;
208     vtable->set_eof = io_pipe_set_eof;
209     vtable->tell = io_pipe_tell;
210     vtable->seek = io_pipe_seek;
211     vtable->adv_position = io_pipe_adv_position;
212     vtable->set_position = io_pipe_set_position;
213     vtable->get_position = io_pipe_get_position;
214     vtable->open = io_pipe_open;
215     vtable->is_open = io_pipe_is_open;
216     vtable->close = io_pipe_close;
217     vtable->get_encoding = io_pipe_get_encoding;
218     vtable->set_flags = io_pipe_set_flags;
219     vtable->get_flags = io_pipe_get_flags;
220     vtable->total_size = io_pipe_total_size;
221     vtable->get_piohandle = io_pipe_get_piohandle;
222 }
223 
224 /*
225 
226 =item C<static INTVAL io_pipe_read_b(PARROT_INTERP, PMC *handle, char *buffer,
227 const size_t byte_length)>
228 
229 Read up to C<byte_length> bytes from the pipe.
230 
231 =cut
232 
233 */
234 
235 static INTVAL
io_pipe_read_b(PARROT_INTERP,ARGMOD (PMC * handle),ARGOUT (char * buffer),const size_t byte_length)236 io_pipe_read_b(PARROT_INTERP, ARGMOD(PMC *handle), ARGOUT(char *buffer),
237                const size_t byte_length)
238 {
239     ASSERT_ARGS(io_pipe_read_b)
240     const PIOHANDLE os_handle = io_filehandle_get_os_handle(interp, handle);
241     const size_t bytes_read = Parrot_io_internal_read(interp, os_handle, buffer, byte_length);
242     if (bytes_read == 0) {
243         INTVAL flags;
244         GETATTR_FileHandle_flags(interp, handle, flags);
245         flags |= PIO_F_EOF;
246         SETATTR_FileHandle_flags(interp, handle, flags);
247     }
248     return bytes_read;
249 }
250 
251 /*
252 
253 =item C<static INTVAL io_pipe_write_b(PARROT_INTERP, PMC *handle, const char
254 *buffer, const size_t byte_length)>
255 
256 Write bytes to the pipe.
257 
258 =cut
259 
260 */
261 
262 static INTVAL
io_pipe_write_b(PARROT_INTERP,ARGMOD (PMC * handle),ARGIN (const char * buffer),const size_t byte_length)263 io_pipe_write_b(PARROT_INTERP, ARGMOD(PMC *handle), ARGIN(const char *buffer),
264                 const size_t byte_length)
265 {
266     ASSERT_ARGS(io_pipe_write_b)
267     const PIOHANDLE os_handle = io_filehandle_get_os_handle(interp, handle);
268     return Parrot_io_internal_write(interp, os_handle, buffer, byte_length);
269 }
270 
271 /*
272 
273 =item C<static INTVAL io_pipe_flush(PARROT_INTERP, PMC *handle)>
274 
275 Flush the pipe.
276 
277 =cut
278 
279 */
280 
281 static INTVAL
io_pipe_flush(PARROT_INTERP,ARGMOD (PMC * handle))282 io_pipe_flush(PARROT_INTERP, ARGMOD(PMC *handle))
283 {
284     ASSERT_ARGS(io_pipe_flush)
285     /* TODO: In read mode, don't do what this does. */
286     PIOHANDLE os_handle = io_filehandle_get_os_handle(interp, handle);
287     return Parrot_io_internal_flush(interp, os_handle);
288 }
289 
290 /*
291 
292 =item C<static INTVAL io_pipe_is_eof(PARROT_INTERP, const PMC *handle)>
293 
294 Determine if the pipe thinks it's at the end of input.
295 
296 =item C<static void io_pipe_set_eof(PARROT_INTERP, PMC *handle, const INTVAL
297 is_set)>
298 
299 Do nothing.
300 
301 =cut
302 
303 */
304 
305 static INTVAL
io_pipe_is_eof(PARROT_INTERP,ARGIN (const PMC * handle))306 io_pipe_is_eof(PARROT_INTERP, ARGIN(const PMC *handle))
307 {
308     ASSERT_ARGS(io_pipe_is_eof)
309     INTVAL flags;
310     GETATTR_FileHandle_flags(interp, (PMC*)handle, flags);
311     if (flags & PIO_F_EOF)
312         return 1;
313     return 0;
314 }
315 
316 static void
io_pipe_set_eof(SHIM_INTERP,ARGMOD (PMC * handle),const INTVAL is_set)317 io_pipe_set_eof(SHIM_INTERP, ARGMOD(PMC *handle), const INTVAL is_set)
318 {
319     ASSERT_ARGS(io_pipe_set_eof)
320     if (is_set)
321         PARROT_FILEHANDLE(handle)->flags |= PIO_F_EOF;
322     else
323         PARROT_FILEHANDLE(handle)->flags &= ~PIO_F_EOF;
324 }
325 
326 /*
327 
328 =item C<static PIOOFF_T io_pipe_tell(PARROT_INTERP, const PMC *handle)>
329 
330 Pipes don't keep track of position. Throw an exception.
331 
332 =cut
333 
334 */
335 
336 static PIOOFF_T
io_pipe_tell(PARROT_INTERP,ARGIN (const PMC * handle))337 io_pipe_tell(PARROT_INTERP, ARGIN(const PMC *handle))
338 {
339     ASSERT_ARGS(io_pipe_tell)
340     const IO_VTABLE * const vtable = IO_GET_VTABLE(interp, (PMC*)handle);
341     IO_VTABLE_UNIMPLEMENTED(interp, vtable, "tell");
342     return (PIOOFF_T)0;
343 }
344 
345 /*
346 
347 =item C<static PIOOFF_T io_pipe_seek(PARROT_INTERP, PMC *handle, const PIOOFF_T
348 offset, const INTVAL whence)>
349 
350 Pipes don't seek. Throw an exception.
351 
352 =cut
353 
354 */
355 
356 static PIOOFF_T
io_pipe_seek(PARROT_INTERP,ARGMOD (PMC * handle),SHIM (const PIOOFF_T offset),SHIM (const INTVAL whence))357 io_pipe_seek(PARROT_INTERP, ARGMOD(PMC *handle), SHIM(const PIOOFF_T offset),
358              SHIM(const INTVAL whence))
359 {
360     ASSERT_ARGS(io_pipe_seek)
361     const IO_VTABLE * const vtable = IO_GET_VTABLE(interp, handle);
362     IO_VTABLE_UNIMPLEMENTED(interp, vtable, "seek");
363     return 0;
364 }
365 
366 /*
367 
368 =item C<static void io_pipe_adv_position(PARROT_INTERP, PMC *handle, const
369 size_t offset)>
370 
371 Pipes don't keep track of position. Ignore.
372 
373 =cut
374 
375 */
376 
377 static void
io_pipe_adv_position(SHIM_INTERP,ARGMOD_NULLOK (PMC * handle),SHIM (const size_t offset))378 io_pipe_adv_position(SHIM_INTERP, ARGMOD_NULLOK(PMC *handle), SHIM(const size_t offset))
379 {
380     ASSERT_ARGS(io_pipe_adv_position)
381     UNUSED(handle);
382     /* Pipes don't keep track of file position internally. Ignore this. */
383 }
384 
385 /*
386 
387 =item C<static void io_pipe_set_position(PARROT_INTERP, PMC *handle, const
388 PIOOFF_T pos)>
389 
390 Pipes don't keep track of position. Ignore.
391 
392 =cut
393 
394 */
395 
396 static void
io_pipe_set_position(SHIM_INTERP,ARGMOD_NULLOK (PMC * handle),SHIM (const PIOOFF_T pos))397 io_pipe_set_position(SHIM_INTERP, ARGMOD_NULLOK(PMC *handle), SHIM(const PIOOFF_T pos))
398 {
399     ASSERT_ARGS(io_pipe_set_position)
400     UNUSED(handle);
401     /* Pipes don't keep track of file position internally. Ignore. */
402 }
403 
404 /*
405 
406 =item C<static PIOOFF_T io_pipe_get_position(PARROT_INTERP, const PMC *handle)>
407 
408 Pipes don't keep track of position. Return 0.
409 
410 =cut
411 
412 */
413 
414 static PIOOFF_T
io_pipe_get_position(SHIM_INTERP,ARGIN_NULLOK (const PMC * handle))415 io_pipe_get_position(SHIM_INTERP, ARGIN_NULLOK(const PMC *handle))
416 {
417     ASSERT_ARGS(io_pipe_get_position)
418     UNUSED(handle);
419     /* Pipes don't keep track of file position internally. Return 0 */
420     return (PIOOFF_T)0;
421 }
422 
423 /*
424 
425 =item C<static INTVAL io_pipe_open(PARROT_INTERP, PMC *handle, const STRING
426 *path, const INTVAL flags, const STRING *mode)>
427 
428 Open the pipe with the command in C<path>.
429 
430 =cut
431 
432 */
433 
434 static INTVAL
io_pipe_open(PARROT_INTERP,ARGMOD (PMC * handle),ARGIN (const STRING * path),const INTVAL flags,ARGIN (const STRING * mode))435 io_pipe_open(PARROT_INTERP, ARGMOD(PMC *handle), ARGIN(const STRING *path),
436              const INTVAL flags, ARGIN(const STRING *mode))
437 {
438     ASSERT_ARGS(io_pipe_open)
439 
440     const int f_read  = (flags & PIO_F_READ) != 0;
441     const int f_write = (flags & PIO_F_WRITE) != 0;
442     INTVAL    pid;
443     PIOHANDLE os_handle;
444 
445     /* Hack! If we're opening in file mode, turn this FileHandle into a file
446        and use that vtable instead. */
447     if ((flags & PIO_F_PIPE) == 0) {
448         const IO_VTABLE * vtable = Parrot_io_get_vtable(interp, IO_VTABLE_FILEHANDLE, NULL);
449         VTABLE_set_pointer_keyed_int(interp, handle, IO_PTR_IDX_VTABLE, (void *)PTR2INTVAL(vtable));
450         return vtable->open(interp, handle, path, flags, mode);
451     }
452 
453     if (f_read == f_write)
454         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR,
455             "Invalid pipe mode: %X", flags);
456 
457     os_handle = Parrot_io_internal_open_pipe(interp, path, flags, &pid);
458 
459     /* Save the pid of the child, we'll wait for it when closing */
460     VTABLE_set_integer_keyed_int(interp, handle, 0, pid);
461 
462     if (flags & PIO_F_BINARY)
463         SETATTR_FileHandle_encoding(interp, handle, Parrot_str_new(interp, "binary", 0));
464 
465     SETATTR_FileHandle_os_handle(interp, handle, os_handle);
466     SETATTR_FileHandle_flags(interp, handle, flags);
467     SETATTR_FileHandle_filename(interp, handle, (STRING*)path);
468     SETATTR_FileHandle_mode(interp, handle, (STRING*)mode);
469     SETATTR_FileHandle_file_pos(interp, handle, 0);
470 
471     return 1;
472 }
473 
474 /*
475 
476 =item C<static INTVAL io_pipe_is_open(PARROT_INTERP, const PMC *handle)>
477 
478 Determine if the pipe is currently open.
479 
480 =cut
481 
482 */
483 
484 static INTVAL
io_pipe_is_open(PARROT_INTERP,ARGIN (const PMC * handle))485 io_pipe_is_open(PARROT_INTERP, ARGIN(const PMC *handle))
486 {
487     ASSERT_ARGS(io_pipe_is_open)
488     const PIOHANDLE os_handle = io_filehandle_get_os_handle(interp, handle);
489     return os_handle != PIO_INVALID_HANDLE;
490 }
491 
492 /*
493 
494 =item C<static INTVAL io_pipe_close(PARROT_INTERP, PMC *handle)>
495 
496 Close the pipe.
497 
498 =cut
499 
500 */
501 
502 static INTVAL
io_pipe_close(PARROT_INTERP,ARGMOD (PMC * handle))503 io_pipe_close(PARROT_INTERP, ARGMOD(PMC *handle))
504 {
505     ASSERT_ARGS(io_pipe_close)
506     const PIOHANDLE os_handle = io_filehandle_get_os_handle(interp, handle);
507 
508     if (os_handle == PIO_INVALID_HANDLE)
509         return -1;
510 
511     else {
512         INTVAL pid;
513         INTVAL status;
514         INTVAL result = Parrot_io_internal_close(interp, os_handle);
515         io_filehandle_set_os_handle(interp, handle, PIO_INVALID_HANDLE);
516         GETATTR_FileHandle_process_id(interp, handle, pid);
517         status = Parrot_proc_waitpid(interp, pid);
518         SETATTR_FileHandle_exit_status(interp, handle, status);
519         io_pipe_set_flags(interp, handle, 0);
520         return result;
521     }
522 }
523 
524 /*
525 
526 =item C<static const STR_VTABLE * io_pipe_get_encoding(PARROT_INTERP, const PMC
527 *handle)>
528 
529 Get the encoding used by the pipe.
530 
531 =cut
532 
533 */
534 
535 PARROT_CAN_RETURN_NULL
536 PARROT_WARN_UNUSED_RESULT
537 static const STR_VTABLE *
io_pipe_get_encoding(PARROT_INTERP,ARGIN (const PMC * handle))538 io_pipe_get_encoding(PARROT_INTERP, ARGIN(const PMC *handle))
539 {
540     ASSERT_ARGS(io_pipe_get_encoding)
541     STRING           *encoding_str;
542 
543     GETATTR_FileHandle_encoding(interp, (PMC*)handle, encoding_str);
544     if (!STRING_IS_NULL(encoding_str))
545         return Parrot_find_encoding_by_string(interp, encoding_str);
546     return NULL;
547 }
548 
549 /*
550 
551 =item C<static void io_pipe_set_flags(PARROT_INTERP, PMC *handle, const INTVAL
552 flags)>
553 
554 Set flags on the Pipe.
555 
556 =cut
557 
558 */
559 
560 static void
io_pipe_set_flags(SHIM_INTERP,ARGMOD (PMC * handle),const INTVAL flags)561 io_pipe_set_flags(SHIM_INTERP, ARGMOD(PMC *handle), const INTVAL flags)
562 {
563     ASSERT_ARGS(io_pipe_set_flags)
564     PARROT_FILEHANDLE(handle)->flags = flags;
565 }
566 
567 /*
568 
569 =item C<static INTVAL io_pipe_get_flags(PARROT_INTERP, const PMC *handle)>
570 
571 Get the flags from the pipe.
572 
573 =cut
574 
575 */
576 
577 static INTVAL
io_pipe_get_flags(SHIM_INTERP,ARGIN (const PMC * handle))578 io_pipe_get_flags(SHIM_INTERP, ARGIN(const PMC *handle))
579 {
580     ASSERT_ARGS(io_pipe_get_flags)
581     return PARROT_FILEHANDLE(handle)->flags;
582 }
583 
584 /*
585 
586 =item C<static size_t io_pipe_total_size(PARROT_INTERP, const PMC *handle)>
587 
588 Pipes have an unknown total size.
589 
590 =cut
591 
592 */
593 
594 static size_t
io_pipe_total_size(SHIM_INTERP,ARGIN_NULLOK (const PMC * handle))595 io_pipe_total_size(SHIM_INTERP, ARGIN_NULLOK(const PMC *handle))
596 {
597     ASSERT_ARGS(io_pipe_total_size)
598     UNUSED(handle);
599     return PIO_UNKNOWN_SIZE;
600 }
601 
602 /*
603 
604 =item C<static PIOHANDLE io_pipe_get_piohandle(PARROT_INTERP, const PMC
605 *handle)>
606 
607 Get the stream descriptor for the pipe.
608 
609 =cut
610 
611 */
612 
613 static PIOHANDLE
io_pipe_get_piohandle(PARROT_INTERP,ARGIN (const PMC * handle))614 io_pipe_get_piohandle(PARROT_INTERP, ARGIN(const PMC *handle))
615 {
616     ASSERT_ARGS(io_pipe_get_piohandle)
617     return io_filehandle_get_os_handle(interp, handle);
618 }
619 
620 /*
621 
622 =back
623 
624 =cut
625 
626 */
627 
628 /*
629  * Local variables:
630  *   c-file-style: "parrot"
631  * End:
632  * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
633  */
634