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