4f79b71c7d7f9132ca3d0aa929e912f895c6e815
[p5sagit/p5-mst-13.2.git] / perlio.c
1 /*
2  * perlio.c Copyright (c) 1996-2001, Nick Ing-Simmons You may distribute
3  * under the terms of either the GNU General Public License or the
4  * Artistic License, as specified in the README file.
5  */
6
7 /*
8  * If we have ActivePerl-like PERL_IMPLICIT_SYS then we need a dTHX to get
9  * at the dispatch tables, even when we do not need it for other reasons.
10  * Invent a dSYS macro to abstract this out
11  */
12 #ifdef PERL_IMPLICIT_SYS
13 #define dSYS dTHX
14 #else
15 #define dSYS dNOOP
16 #endif
17
18 #define VOIDUSED 1
19 #ifdef PERL_MICRO
20 #   include "uconfig.h"
21 #else
22 #   include "config.h"
23 #endif
24
25 #define PERLIO_NOT_STDIO 0
26 #if !defined(PERLIO_IS_STDIO) && !defined(USE_SFIO)
27 /*
28  * #define PerlIO FILE
29  */
30 #endif
31 /*
32  * This file provides those parts of PerlIO abstraction
33  * which are not #defined in perlio.h.
34  * Which these are depends on various Configure #ifdef's
35  */
36
37 #include "EXTERN.h"
38 #define PERL_IN_PERLIO_C
39 #include "perl.h"
40
41 #include "XSUB.h"
42
43 #undef PerlMemShared_calloc
44 #define PerlMemShared_calloc(x,y) calloc(x,y)
45 #undef PerlMemShared_free
46 #define PerlMemShared_free(x) free(x)
47
48 int
49 perlsio_binmode(FILE *fp, int iotype, int mode)
50 {
51     /*
52      * This used to be contents of do_binmode in doio.c
53      */
54 #ifdef DOSISH
55 #  if defined(atarist) || defined(__MINT__)
56     if (!fflush(fp)) {
57         if (mode & O_BINARY)
58             ((FILE *) fp)->_flag |= _IOBIN;
59         else
60             ((FILE *) fp)->_flag &= ~_IOBIN;
61         return 1;
62     }
63     return 0;
64 #  else
65     dTHX;
66 #ifdef NETWARE
67     if (PerlLIO_setmode(fp, mode) != -1) {
68 #else
69     if (PerlLIO_setmode(fileno(fp), mode) != -1) {
70 #endif
71 #    if defined(WIN32) && defined(__BORLANDC__)
72         /*
73          * The translation mode of the stream is maintained independent of
74          * the translation mode of the fd in the Borland RTL (heavy
75          * digging through their runtime sources reveal).  User has to set
76          * the mode explicitly for the stream (though they don't document
77          * this anywhere). GSAR 97-5-24
78          */
79         fseek(fp, 0L, 0);
80         if (mode & O_BINARY)
81             fp->flags |= _F_BIN;
82         else
83             fp->flags &= ~_F_BIN;
84 #    endif
85         return 1;
86     }
87     else
88         return 0;
89 #  endif
90 #else
91 #  if defined(USEMYBINMODE)
92     if (my_binmode(fp, iotype, mode) != FALSE)
93         return 1;
94     else
95         return 0;
96 #  else
97     return 1;
98 #  endif
99 #endif
100 }
101
102 #ifndef PERLIO_LAYERS
103 int
104 PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names)
105 {
106     if (!names || !*names || strEQ(names, ":crlf") || strEQ(names, ":raw")) {
107         return 0;
108     }
109     Perl_croak(aTHX_ "Cannot apply \"%s\" in non-PerlIO perl", names);
110     /*
111      * NOTREACHED
112      */
113     return -1;
114 }
115
116 void
117 PerlIO_destruct(pTHX)
118 {
119 }
120
121 int
122 PerlIO_binmode(pTHX_ PerlIO *fp, int iotype, int mode, const char *names)
123 {
124 #ifdef USE_SFIO
125     return 1;
126 #else
127     return perlsio_binmode(fp, iotype, mode);
128 #endif
129 }
130
131 /*
132  * De-mux PerlIO_openn() into fdopen, freopen and fopen type entries
133  */
134
135 PerlIO *
136 PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd,
137              int imode, int perm, PerlIO *old, int narg, SV **args)
138 {
139     if (narg == 1) {
140         if (*args == &PL_sv_undef)
141             return PerlIO_tmpfile();
142         else {
143             char *name = SvPV_nolen(*args);
144             if (*mode == '#') {
145                 fd = PerlLIO_open3(name, imode, perm);
146                 if (fd >= 0)
147                     return PerlIO_fdopen(fd, (char *) mode + 1);
148             }
149             else if (old) {
150                 return PerlIO_reopen(name, mode, old);
151             }
152             else {
153                 return PerlIO_open(name, mode);
154             }
155         }
156     }
157     else {
158         return PerlIO_fdopen(fd, (char *) mode);
159     }
160     return NULL;
161 }
162
163 XS(XS_PerlIO__Layer__find)
164 {
165     dXSARGS;
166     if (items < 2)
167         Perl_croak(aTHX_ "Usage class->find(name[,load])");
168     else {
169         char *name = SvPV_nolen(ST(1));
170         ST(0) = (strEQ(name, "crlf")
171                  || strEQ(name, "raw")) ? &PL_sv_yes : &PL_sv_undef;
172         XSRETURN(1);
173     }
174 }
175
176
177 void
178 Perl_boot_core_PerlIO(pTHX)
179 {
180     newXS("PerlIO::Layer::find", XS_PerlIO__Layer__find, __FILE__);
181 }
182
183 #endif
184
185
186 #ifdef PERLIO_IS_STDIO
187
188 void
189 PerlIO_init(void)
190 {
191     /*
192      * Does nothing (yet) except force this file to be included in perl
193      * binary. That allows this file to force inclusion of other functions
194      * that may be required by loadable extensions e.g. for
195      * FileHandle::tmpfile
196      */
197 }
198
199 #undef PerlIO_tmpfile
200 PerlIO *
201 PerlIO_tmpfile(void)
202 {
203     return tmpfile();
204 }
205
206 #else                           /* PERLIO_IS_STDIO */
207
208 #ifdef USE_SFIO
209
210 #undef HAS_FSETPOS
211 #undef HAS_FGETPOS
212
213 /*
214  * This section is just to make sure these functions get pulled in from
215  * libsfio.a
216  */
217
218 #undef PerlIO_tmpfile
219 PerlIO *
220 PerlIO_tmpfile(void)
221 {
222     return sftmp(0);
223 }
224
225 void
226 PerlIO_init(void)
227 {
228     /*
229      * Force this file to be included in perl binary. Which allows this
230      * file to force inclusion of other functions that may be required by
231      * loadable extensions e.g. for FileHandle::tmpfile
232      */
233
234     /*
235      * Hack sfio does its own 'autoflush' on stdout in common cases. Flush
236      * results in a lot of lseek()s to regular files and lot of small
237      * writes to pipes.
238      */
239     sfset(sfstdout, SF_SHARE, 0);
240 }
241
242 PerlIO *
243 PerlIO_importFILE(FILE *stdio, int fl)
244 {
245     int fd = fileno(stdio);
246     PerlIO *r = PerlIO_fdopen(fd, "r+");
247     return r;
248 }
249
250 FILE *
251 PerlIO_findFILE(PerlIO *pio)
252 {
253     int fd = PerlIO_fileno(pio);
254     FILE *f = fdopen(fd, "r+");
255     PerlIO_flush(pio);
256     if (!f && errno == EINVAL)
257         f = fdopen(fd, "w");
258     if (!f && errno == EINVAL)
259         f = fdopen(fd, "r");
260     return f;
261 }
262
263
264 #else                           /* USE_SFIO */
265 /*======================================================================================*/
266 /*
267  * Implement all the PerlIO interface ourselves.
268  */
269
270 #include "perliol.h"
271
272 /*
273  * We _MUST_ have <unistd.h> if we are using lseek() and may have large
274  * files
275  */
276 #ifdef I_UNISTD
277 #include <unistd.h>
278 #endif
279 #ifdef HAS_MMAP
280 #include <sys/mman.h>
281 #endif
282
283
284 void PerlIO_debug(const char *fmt, ...)
285     __attribute__ ((format(__printf__, 1, 2)));
286
287 void
288 PerlIO_debug(const char *fmt, ...)
289 {
290     static int dbg = 0;
291     va_list ap;
292     dSYS;
293     va_start(ap, fmt);
294     if (!dbg) {
295         char *s = PerlEnv_getenv("PERLIO_DEBUG");
296         if (s && *s)
297             dbg = PerlLIO_open3(s, O_WRONLY | O_CREAT | O_APPEND, 0666);
298         else
299             dbg = -1;
300     }
301     if (dbg > 0) {
302         dTHX;
303 #ifdef USE_ITHREADS
304         /* Use fixed buffer as sv_catpvf etc. needs SVs */
305         char buffer[1024];
306         char *s;
307         STRLEN len;
308         s = CopFILE(PL_curcop);
309         if (!s)
310             s = "(none)";
311         sprintf(buffer, "%s:%" IVdf " ", s, (IV) CopLINE(PL_curcop));
312         len = strlen(buffer);
313         vsprintf(buffer+len, fmt, ap);
314         PerlLIO_write(dbg, buffer, strlen(buffer));
315 #else
316         SV *sv = newSVpvn("", 0);
317         char *s;
318         STRLEN len;
319         s = CopFILE(PL_curcop);
320         if (!s)
321             s = "(none)";
322         Perl_sv_catpvf(aTHX_ sv, "%s:%" IVdf " ", s,
323                        (IV) CopLINE(PL_curcop));
324         Perl_sv_vcatpvf(aTHX_ sv, fmt, &ap);
325
326         s = SvPV(sv, len);
327         PerlLIO_write(dbg, s, len);
328         SvREFCNT_dec(sv);
329 #endif
330     }
331     va_end(ap);
332 }
333
334 /*--------------------------------------------------------------------------------------*/
335
336 /*
337  * Inner level routines
338  */
339
340 /*
341  * Table of pointers to the PerlIO structs (malloc'ed)
342  */
343 PerlIO *_perlio = NULL;
344 #define PERLIO_TABLE_SIZE 64
345
346
347
348 PerlIO *
349 PerlIO_allocate(pTHX)
350 {
351     /*
352      * Find a free slot in the table, allocating new table as necessary
353      */
354     PerlIO **last;
355     PerlIO *f;
356     last = &_perlio;
357     while ((f = *last)) {
358         int i;
359         last = (PerlIO **) (f);
360         for (i = 1; i < PERLIO_TABLE_SIZE; i++) {
361             if (!*++f) {
362                 return f;
363             }
364         }
365     }
366     f = PerlMemShared_calloc(PERLIO_TABLE_SIZE, sizeof(PerlIO));
367     if (!f) {
368         return NULL;
369     }
370     *last = f;
371     return f + 1;
372 }
373
374 void
375 PerlIO_cleantable(pTHX_ PerlIO **tablep)
376 {
377     PerlIO *table = *tablep;
378     if (table) {
379         int i;
380         PerlIO_cleantable(aTHX_(PerlIO **) & (table[0]));
381         for (i = PERLIO_TABLE_SIZE - 1; i > 0; i--) {
382             PerlIO *f = table + i;
383             if (*f) {
384                 PerlIO_close(f);
385             }
386         }
387         PerlMemShared_free(table);
388         *tablep = NULL;
389     }
390 }
391
392 PerlIO_list_t *PerlIO_known_layers;
393 PerlIO_list_t *PerlIO_def_layerlist;
394
395 PerlIO_list_t *
396 PerlIO_list_alloc(void)
397 {
398     PerlIO_list_t *list;
399     Newz('L', list, 1, PerlIO_list_t);
400     list->refcnt = 1;
401     return list;
402 }
403
404 void
405 PerlIO_list_free(PerlIO_list_t *list)
406 {
407     if (list) {
408         if (--list->refcnt == 0) {
409             if (list->array) {
410                 dTHX;
411                 IV i;
412                 for (i = 0; i < list->cur; i++) {
413                     if (list->array[i].arg)
414                         SvREFCNT_dec(list->array[i].arg);
415                 }
416                 Safefree(list->array);
417             }
418             Safefree(list);
419         }
420     }
421 }
422
423 void
424 PerlIO_list_push(PerlIO_list_t *list, PerlIO_funcs *funcs, SV *arg)
425 {
426     dTHX;
427     PerlIO_pair_t *p;
428     if (list->cur >= list->len) {
429         list->len += 8;
430         if (list->array)
431             Renew(list->array, list->len, PerlIO_pair_t);
432         else
433             New('l', list->array, list->len, PerlIO_pair_t);
434     }
435     p = &(list->array[list->cur++]);
436     p->funcs = funcs;
437     if ((p->arg = arg)) {
438         SvREFCNT_inc(arg);
439     }
440 }
441
442
443 void
444 PerlIO_cleanup_layers(pTHX_ void *data)
445 {
446 #if 0
447     PerlIO_known_layers = Nullhv;
448     PerlIO_def_layerlist = Nullav;
449 #endif
450 }
451
452 void
453 PerlIO_cleanup()
454 {
455     dTHX;
456     PerlIO_cleantable(aTHX_ & _perlio);
457 }
458
459 void
460 PerlIO_destruct(pTHX)
461 {
462     PerlIO **table = &_perlio;
463     PerlIO *f;
464     while ((f = *table)) {
465         int i;
466         table = (PerlIO **) (f++);
467         for (i = 1; i < PERLIO_TABLE_SIZE; i++) {
468             PerlIO *x = f;
469             PerlIOl *l;
470             while ((l = *x)) {
471                 if (l->tab->kind & PERLIO_K_DESTRUCT) {
472                     PerlIO_debug("Destruct popping %s\n", l->tab->name);
473                     PerlIO_flush(x);
474                     PerlIO_pop(aTHX_ x);
475                 }
476                 else {
477                     x = PerlIONext(x);
478                 }
479             }
480             f++;
481         }
482     }
483 }
484
485 void
486 PerlIO_pop(pTHX_ PerlIO *f)
487 {
488     PerlIOl *l = *f;
489     if (l) {
490         PerlIO_debug("PerlIO_pop f=%p %s\n", f, l->tab->name);
491         if (l->tab->Popped) {
492             /*
493              * If popped returns non-zero do not free its layer structure
494              * it has either done so itself, or it is shared and still in
495              * use
496              */
497             if ((*l->tab->Popped) (f) != 0)
498                 return;
499         }
500         *f = l->next;;
501         PerlMemShared_free(l);
502     }
503 }
504
505 /*--------------------------------------------------------------------------------------*/
506 /*
507  * XS Interface for perl code
508  */
509
510 PerlIO_funcs *
511 PerlIO_find_layer(pTHX_ const char *name, STRLEN len, int load)
512 {
513     IV i;
514     if ((SSize_t) len <= 0)
515         len = strlen(name);
516     for (i = 0; i < PerlIO_known_layers->cur; i++) {
517         PerlIO_funcs *f = PerlIO_known_layers->array[i].funcs;
518         if (memEQ(f->name, name, len)) {
519             PerlIO_debug("%.*s => %p\n", (int) len, name, f);
520             return f;
521         }
522     }
523     if (load && PL_subname && PerlIO_def_layerlist
524         && PerlIO_def_layerlist->cur >= 2) {
525         SV *pkgsv = newSVpvn("PerlIO", 6);
526         SV *layer = newSVpvn(name, len);
527         ENTER;
528         /*
529          * The two SVs are magically freed by load_module
530          */
531         Perl_load_module(aTHX_ 0, pkgsv, Nullsv, layer, Nullsv);
532         LEAVE;
533         return PerlIO_find_layer(aTHX_ name, len, 0);
534     }
535     PerlIO_debug("Cannot find %.*s\n", (int) len, name);
536     return NULL;
537 }
538
539 #ifdef USE_ATTRIBUTES_FOR_PERLIO
540
541 static int
542 perlio_mg_set(pTHX_ SV *sv, MAGIC *mg)
543 {
544     if (SvROK(sv)) {
545         IO *io = GvIOn((GV *) SvRV(sv));
546         PerlIO *ifp = IoIFP(io);
547         PerlIO *ofp = IoOFP(io);
548         Perl_warn(aTHX_ "set %" SVf " %p %p %p", sv, io, ifp, ofp);
549     }
550     return 0;
551 }
552
553 static int
554 perlio_mg_get(pTHX_ SV *sv, MAGIC *mg)
555 {
556     if (SvROK(sv)) {
557         IO *io = GvIOn((GV *) SvRV(sv));
558         PerlIO *ifp = IoIFP(io);
559         PerlIO *ofp = IoOFP(io);
560         Perl_warn(aTHX_ "get %" SVf " %p %p %p", sv, io, ifp, ofp);
561     }
562     return 0;
563 }
564
565 static int
566 perlio_mg_clear(pTHX_ SV *sv, MAGIC *mg)
567 {
568     Perl_warn(aTHX_ "clear %" SVf, sv);
569     return 0;
570 }
571
572 static int
573 perlio_mg_free(pTHX_ SV *sv, MAGIC *mg)
574 {
575     Perl_warn(aTHX_ "free %" SVf, sv);
576     return 0;
577 }
578
579 MGVTBL perlio_vtab = {
580     perlio_mg_get,
581     perlio_mg_set,
582     NULL,                       /* len */
583     perlio_mg_clear,
584     perlio_mg_free
585 };
586
587 XS(XS_io_MODIFY_SCALAR_ATTRIBUTES)
588 {
589     dXSARGS;
590     SV *sv = SvRV(ST(1));
591     AV *av = newAV();
592     MAGIC *mg;
593     int count = 0;
594     int i;
595     sv_magic(sv, (SV *) av, PERL_MAGIC_ext, NULL, 0);
596     SvRMAGICAL_off(sv);
597     mg = mg_find(sv, PERL_MAGIC_ext);
598     mg->mg_virtual = &perlio_vtab;
599     mg_magical(sv);
600     Perl_warn(aTHX_ "attrib %" SVf, sv);
601     for (i = 2; i < items; i++) {
602         STRLEN len;
603         const char *name = SvPV(ST(i), len);
604         SV *layer = PerlIO_find_layer(aTHX_ name, len, 1);
605         if (layer) {
606             av_push(av, SvREFCNT_inc(layer));
607         }
608         else {
609             ST(count) = ST(i);
610             count++;
611         }
612     }
613     SvREFCNT_dec(av);
614     XSRETURN(count);
615 }
616
617 #endif                          /* USE_ATTIBUTES_FOR_PERLIO */
618
619 SV *
620 PerlIO_tab_sv(pTHX_ PerlIO_funcs *tab)
621 {
622     HV *stash = gv_stashpv("PerlIO::Layer", TRUE);
623     SV *sv = sv_bless(newRV_noinc(newSViv(PTR2IV(tab))), stash);
624     return sv;
625 }
626
627 XS(XS_PerlIO__Layer__find)
628 {
629     dXSARGS;
630     if (items < 2)
631         Perl_croak(aTHX_ "Usage class->find(name[,load])");
632     else {
633         STRLEN len = 0;
634         char *name = SvPV(ST(1), len);
635         bool load = (items > 2) ? SvTRUE(ST(2)) : 0;
636         PerlIO_funcs *layer = PerlIO_find_layer(aTHX_ name, len, load);
637         ST(0) =
638             (layer) ? sv_2mortal(PerlIO_tab_sv(aTHX_ layer)) :
639             &PL_sv_undef;
640         XSRETURN(1);
641     }
642 }
643
644 void
645 PerlIO_define_layer(pTHX_ PerlIO_funcs *tab)
646 {
647     if (!PerlIO_known_layers)
648         PerlIO_known_layers = PerlIO_list_alloc();
649     PerlIO_list_push(PerlIO_known_layers, tab, Nullsv);
650     PerlIO_debug("define %s %p\n", tab->name, tab);
651 }
652
653 int
654 PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names)
655 {
656     if (names) {
657         const char *s = names;
658         while (*s) {
659             while (isSPACE(*s) || *s == ':')
660                 s++;
661             if (*s) {
662                 STRLEN llen = 0;
663                 const char *e = s;
664                 const char *as = Nullch;
665                 STRLEN alen = 0;
666                 if (!isIDFIRST(*s)) {
667                     /*
668                      * Message is consistent with how attribute lists are
669                      * passed. Even though this means "foo : : bar" is
670                      * seen as an invalid separator character.
671                      */
672                     char q = ((*s == '\'') ? '"' : '\'');
673                     Perl_warn(aTHX_
674                               "perlio: invalid separator character %c%c%c in layer specification list",
675                               q, *s, q);
676                     return -1;
677                 }
678                 do {
679                     e++;
680                 } while (isALNUM(*e));
681                 llen = e - s;
682                 if (*e == '(') {
683                     int nesting = 1;
684                     as = ++e;
685                     while (nesting) {
686                         switch (*e++) {
687                         case ')':
688                             if (--nesting == 0)
689                                 alen = (e - 1) - as;
690                             break;
691                         case '(':
692                             ++nesting;
693                             break;
694                         case '\\':
695                             /*
696                              * It's a nul terminated string, not allowed
697                              * to \ the terminating null. Anything other
698                              * character is passed over.
699                              */
700                             if (*e++) {
701                                 break;
702                             }
703                             /*
704                              * Drop through
705                              */
706                         case '\0':
707                             e--;
708                             Perl_warn(aTHX_
709                                       "perlio: argument list not closed for layer \"%.*s\"",
710                                       (int) (e - s), s);
711                             return -1;
712                         default:
713                             /*
714                              * boring.
715                              */
716                             break;
717                         }
718                     }
719                 }
720                 if (e > s) {
721                     PerlIO_funcs *layer =
722                         PerlIO_find_layer(aTHX_ s, llen, 1);
723                     if (layer) {
724                         PerlIO_list_push(av, layer,
725                                          (as) ? newSVpvn(as,
726                                                          alen) :
727                                          &PL_sv_undef);
728                     }
729                     else {
730                         Perl_warn(aTHX_ "perlio: unknown layer \"%.*s\"",
731                                   (int) llen, s);
732                         return -1;
733                     }
734                 }
735                 s = e;
736             }
737         }
738     }
739     return 0;
740 }
741
742 void
743 PerlIO_default_buffer(pTHX_ PerlIO_list_t *av)
744 {
745     PerlIO_funcs *tab = &PerlIO_perlio;
746     if (O_BINARY != O_TEXT) {
747         tab = &PerlIO_crlf;
748     }
749     else {
750         if (PerlIO_stdio.Set_ptrcnt) {
751             tab = &PerlIO_stdio;
752         }
753     }
754     PerlIO_debug("Pushing %s\n", tab->name);
755     PerlIO_list_push(av, PerlIO_find_layer(aTHX_ tab->name, 0, 0),
756                      &PL_sv_undef);
757 }
758
759 SV *
760 PerlIO_arg_fetch(PerlIO_list_t *av, IV n)
761 {
762     return av->array[n].arg;
763 }
764
765 PerlIO_funcs *
766 PerlIO_layer_fetch(pTHX_ PerlIO_list_t *av, IV n, PerlIO_funcs *def)
767 {
768     if (n >= 0 && n < av->cur) {
769         PerlIO_debug("Layer %" IVdf " is %s\n", n,
770                      av->array[n].funcs->name);
771         return av->array[n].funcs;
772     }
773     if (!def)
774         Perl_croak(aTHX_ "panic: PerlIO layer array corrupt");
775     return def;
776 }
777
778 PerlIO_list_t *
779 PerlIO_default_layers(pTHX)
780 {
781     if (!PerlIO_def_layerlist) {
782         const char *s = (PL_tainting) ? Nullch : PerlEnv_getenv("PERLIO");
783         PerlIO_funcs *osLayer = &PerlIO_unix;
784         PerlIO_def_layerlist = PerlIO_list_alloc();
785         PerlIO_define_layer(aTHX_ & PerlIO_unix);
786 #if defined(WIN32) && !defined(UNDER_CE)
787         PerlIO_define_layer(aTHX_ & PerlIO_win32);
788 #if 0
789         osLayer = &PerlIO_win32;
790 #endif
791 #endif
792         PerlIO_define_layer(aTHX_ & PerlIO_raw);
793         PerlIO_define_layer(aTHX_ & PerlIO_perlio);
794         PerlIO_define_layer(aTHX_ & PerlIO_stdio);
795         PerlIO_define_layer(aTHX_ & PerlIO_crlf);
796 #ifdef HAS_MMAP
797         PerlIO_define_layer(aTHX_ & PerlIO_mmap);
798 #endif
799         PerlIO_define_layer(aTHX_ & PerlIO_utf8);
800         PerlIO_define_layer(aTHX_ & PerlIO_byte);
801         PerlIO_list_push(PerlIO_def_layerlist,
802                          PerlIO_find_layer(aTHX_ osLayer->name, 0, 0),
803                          &PL_sv_undef);
804         if (s) {
805             PerlIO_parse_layers(aTHX_ PerlIO_def_layerlist, s);
806         }
807         else {
808             PerlIO_default_buffer(aTHX_ PerlIO_def_layerlist);
809         }
810     }
811     if (PerlIO_def_layerlist->cur < 2) {
812         PerlIO_default_buffer(aTHX_ PerlIO_def_layerlist);
813     }
814     return PerlIO_def_layerlist;
815 }
816
817 void
818 Perl_boot_core_PerlIO(pTHX)
819 {
820 #ifdef USE_ATTRIBUTES_FOR_PERLIO
821     newXS("io::MODIFY_SCALAR_ATTRIBUTES", XS_io_MODIFY_SCALAR_ATTRIBUTES,
822           __FILE__);
823 #endif
824     newXS("PerlIO::Layer::find", XS_PerlIO__Layer__find, __FILE__);
825 }
826
827 PerlIO_funcs *
828 PerlIO_default_layer(pTHX_ I32 n)
829 {
830     PerlIO_list_t *av = PerlIO_default_layers(aTHX);
831     if (n < 0)
832         n += av->cur;
833     return PerlIO_layer_fetch(aTHX_ av, n, &PerlIO_stdio);
834 }
835
836 #define PerlIO_default_top() PerlIO_default_layer(aTHX_ -1)
837 #define PerlIO_default_btm() PerlIO_default_layer(aTHX_ 0)
838
839 void
840 PerlIO_stdstreams(pTHX)
841 {
842     if (!_perlio) {
843         PerlIO_allocate(aTHX);
844         PerlIO_fdopen(0, "Ir" PERLIO_STDTEXT);
845         PerlIO_fdopen(1, "Iw" PERLIO_STDTEXT);
846         PerlIO_fdopen(2, "Iw" PERLIO_STDTEXT);
847     }
848 }
849
850 PerlIO *
851 PerlIO_push(pTHX_ PerlIO *f, PerlIO_funcs *tab, const char *mode, SV *arg)
852 {
853     PerlIOl *l = NULL;
854     l = PerlMemShared_calloc(tab->size, sizeof(char));
855     if (l) {
856         Zero(l, tab->size, char);
857         l->next = *f;
858         l->tab = tab;
859         *f = l;
860         PerlIO_debug("PerlIO_push f=%p %s %s %p\n", f, tab->name,
861                      (mode) ? mode : "(Null)", arg);
862         if ((*l->tab->Pushed) (f, mode, arg) != 0) {
863             PerlIO_pop(aTHX_ f);
864             return NULL;
865         }
866     }
867     return f;
868 }
869
870 IV
871 PerlIOPop_pushed(PerlIO *f, const char *mode, SV *arg)
872 {
873     dTHX;
874     PerlIO_pop(aTHX_ f);
875     if (*f) {
876         PerlIO_flush(f);
877         PerlIO_pop(aTHX_ f);
878         return 0;
879     }
880     return -1;
881 }
882
883 IV
884 PerlIORaw_pushed(PerlIO *f, const char *mode, SV *arg)
885 {
886     /*
887      * Remove the dummy layer
888      */
889     dTHX;
890     PerlIO_pop(aTHX_ f);
891     /*
892      * Pop back to bottom layer
893      */
894     if (f && *f) {
895         PerlIO_flush(f);
896         while (!(PerlIOBase(f)->tab->kind & PERLIO_K_RAW)) {
897             if (*PerlIONext(f)) {
898                 PerlIO_pop(aTHX_ f);
899             }
900             else {
901                 /*
902                  * Nothing bellow - push unix on top then remove it
903                  */
904                 if (PerlIO_push(aTHX_ f, PerlIO_default_btm(), mode, arg)) {
905                     PerlIO_pop(aTHX_ PerlIONext(f));
906                 }
907                 break;
908             }
909         }
910         PerlIO_debug(":raw f=%p :%s\n", f, PerlIOBase(f)->tab->name);
911         return 0;
912     }
913     return -1;
914 }
915
916 int
917 PerlIO_apply_layera(pTHX_ PerlIO *f, const char *mode,
918                     PerlIO_list_t *layers, IV n)
919 {
920     IV max = layers->cur;
921     int code = 0;
922     while (n < max) {
923         PerlIO_funcs *tab = PerlIO_layer_fetch(aTHX_ layers, n, NULL);
924         if (tab) {
925             if (!PerlIO_push(aTHX_ f, tab, mode, PerlIOArg)) {
926                 code = -1;
927                 break;
928             }
929         }
930         n++;
931     }
932     return code;
933 }
934
935 int
936 PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names)
937 {
938     int code = 0;
939     if (names) {
940         PerlIO_list_t *layers = PerlIO_list_alloc();
941         code = PerlIO_parse_layers(aTHX_ layers, names);
942         if (code == 0) {
943             code = PerlIO_apply_layera(aTHX_ f, mode, layers, 0);
944         }
945         PerlIO_list_free(layers);
946     }
947     return code;
948 }
949
950
951 /*--------------------------------------------------------------------------------------*/
952 /*
953  * Given the abstraction above the public API functions
954  */
955
956 int
957 PerlIO_binmode(pTHX_ PerlIO *f, int iotype, int mode, const char *names)
958 {
959     PerlIO_debug("PerlIO_binmode f=%p %s %c %x %s\n",
960                  f, PerlIOBase(f)->tab->name, iotype, mode,
961                  (names) ? names : "(Null)");
962     PerlIO_flush(f);
963     if (!names && (O_TEXT != O_BINARY && (mode & O_BINARY))) {
964         PerlIO *top = f;
965         while (*top) {
966             if (PerlIOBase(top)->tab == &PerlIO_crlf) {
967                 PerlIOBase(top)->flags &= ~PERLIO_F_CRLF;
968                 break;
969             }
970             top = PerlIONext(top);
971             PerlIO_flush(top);
972         }
973     }
974     return PerlIO_apply_layers(aTHX_ f, NULL, names) == 0 ? TRUE : FALSE;
975 }
976
977 #undef PerlIO__close
978 int
979 PerlIO__close(PerlIO *f)
980 {
981     if (f && *f)
982         return (*PerlIOBase(f)->tab->Close) (f);
983     else {
984         SETERRNO(EBADF, SS$_IVCHAN);
985         return -1;
986     }
987 }
988
989 #undef PerlIO_fdupopen
990 PerlIO *
991 PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param)
992 {
993     if (f && *f) {
994         PerlIO_funcs *tab = PerlIOBase(f)->tab;
995         PerlIO *new;
996         PerlIO_debug("fdupopen f=%p param=%p\n",f,param);
997         new = (*tab->Dup)(aTHX_ PerlIO_allocate(aTHX),f,param);
998         return new;
999     }
1000     else {
1001         SETERRNO(EBADF, SS$_IVCHAN);
1002         return NULL;
1003     }
1004 }
1005
1006 #undef PerlIO_close
1007 int
1008 PerlIO_close(PerlIO *f)
1009 {
1010     dTHX;
1011     int code = -1;
1012     if (f && *f) {
1013         code = (*PerlIOBase(f)->tab->Close) (f);
1014         while (*f) {
1015             PerlIO_pop(aTHX_ f);
1016         }
1017     }
1018     return code;
1019 }
1020
1021 #undef PerlIO_fileno
1022 int
1023 PerlIO_fileno(PerlIO *f)
1024 {
1025     if (f && *f)
1026         return (*PerlIOBase(f)->tab->Fileno) (f);
1027     else {
1028         SETERRNO(EBADF, SS$_IVCHAN);
1029         return -1;
1030     }
1031 }
1032
1033 static const char *
1034 PerlIO_context_layers(pTHX_ const char *mode)
1035 {
1036     const char *type = NULL;
1037     /*
1038      * Need to supply default layer info from open.pm
1039      */
1040     if (PL_curcop) {
1041         SV *layers = PL_curcop->cop_io;
1042         if (layers) {
1043             STRLEN len;
1044             type = SvPV(layers, len);
1045             if (type && mode[0] != 'r') {
1046                 /*
1047                  * Skip to write part
1048                  */
1049                 const char *s = strchr(type, 0);
1050                 if (s && (s - type) < len) {
1051                     type = s + 1;
1052                 }
1053             }
1054         }
1055     }
1056     return type;
1057 }
1058
1059 static PerlIO_funcs *
1060 PerlIO_layer_from_ref(pTHX_ SV *sv)
1061 {
1062     /*
1063      * For any scalar type load the handler which is bundled with perl
1064      */
1065     if (SvTYPE(sv) < SVt_PVAV)
1066         return PerlIO_find_layer(aTHX_ "Scalar", 6, 1);
1067
1068     /*
1069      * For other types allow if layer is known but don't try and load it
1070      */
1071     switch (SvTYPE(sv)) {
1072     case SVt_PVAV:
1073         return PerlIO_find_layer(aTHX_ "Array", 5, 0);
1074     case SVt_PVHV:
1075         return PerlIO_find_layer(aTHX_ "Hash", 4, 0);
1076     case SVt_PVCV:
1077         return PerlIO_find_layer(aTHX_ "Code", 4, 0);
1078     case SVt_PVGV:
1079         return PerlIO_find_layer(aTHX_ "Glob", 4, 0);
1080     }
1081     return NULL;
1082 }
1083
1084 PerlIO_list_t *
1085 PerlIO_resolve_layers(pTHX_ const char *layers,
1086                       const char *mode, int narg, SV **args)
1087 {
1088     PerlIO_list_t *def = PerlIO_default_layers(aTHX);
1089     int incdef = 1;
1090     if (!_perlio)
1091         PerlIO_stdstreams(aTHX);
1092     if (narg) {
1093         SV *arg = *args;
1094         /*
1095          * If it is a reference but not an object see if we have a handler
1096          * for it
1097          */
1098         if (SvROK(arg) && !sv_isobject(arg)) {
1099             PerlIO_funcs *handler = PerlIO_layer_from_ref(aTHX_ SvRV(arg));
1100             if (handler) {
1101                 def = PerlIO_list_alloc();
1102                 PerlIO_list_push(def, handler, &PL_sv_undef);
1103                 incdef = 0;
1104             }
1105             /*
1106              * Don't fail if handler cannot be found :Via(...) etc. may do
1107              * something sensible else we will just stringfy and open
1108              * resulting string.
1109              */
1110         }
1111     }
1112     if (!layers)
1113         layers = PerlIO_context_layers(aTHX_ mode);
1114     if (layers && *layers) {
1115         PerlIO_list_t *av;
1116         if (incdef) {
1117             IV i = def->cur;
1118             av = PerlIO_list_alloc();
1119             for (i = 0; i < def->cur; i++) {
1120                 PerlIO_list_push(av, def->array[i].funcs,
1121                                  def->array[i].arg);
1122             }
1123         }
1124         else {
1125             av = def;
1126         }
1127         PerlIO_parse_layers(aTHX_ av, layers);
1128         return av;
1129     }
1130     else {
1131         if (incdef)
1132             def->refcnt++;
1133         return def;
1134     }
1135 }
1136
1137 PerlIO *
1138 PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd,
1139              int imode, int perm, PerlIO *f, int narg, SV **args)
1140 {
1141     if (!f && narg == 1 && *args == &PL_sv_undef) {
1142         if ((f = PerlIO_tmpfile())) {
1143             if (!layers)
1144                 layers = PerlIO_context_layers(aTHX_ mode);
1145             if (layers && *layers)
1146                 PerlIO_apply_layers(aTHX_ f, mode, layers);
1147         }
1148     }
1149     else {
1150         PerlIO_list_t *layera = NULL;
1151         IV n;
1152         PerlIO_funcs *tab = NULL;
1153         if (f && *f) {
1154             /*
1155              * This is "reopen" - it is not tested as perl does not use it
1156              * yet
1157              */
1158             PerlIOl *l = *f;
1159             layera = PerlIO_list_alloc();
1160             while (l) {
1161                 SV *arg =
1162                     (l->tab->Getarg) ? (*l->tab->
1163                                         Getarg) (&l) : &PL_sv_undef;
1164                 PerlIO_list_push(layera, l->tab, arg);
1165                 l = *PerlIONext(&l);
1166             }
1167         }
1168         else {
1169             layera = PerlIO_resolve_layers(aTHX_ layers, mode, narg, args);
1170         }
1171         /*
1172          * Start at "top" of layer stack
1173          */
1174         n = layera->cur - 1;
1175         while (n >= 0) {
1176             PerlIO_funcs *t = PerlIO_layer_fetch(aTHX_ layera, n, NULL);
1177             if (t && t->Open) {
1178                 tab = t;
1179                 break;
1180             }
1181             n--;
1182         }
1183         if (tab) {
1184             /*
1185              * Found that layer 'n' can do opens - call it
1186              */
1187             PerlIO_debug("openn(%s,'%s','%s',%d,%x,%o,%p,%d,%p)\n",
1188                          tab->name, layers, mode, fd, imode, perm, f, narg,
1189                          args);
1190             f = (*tab->Open) (aTHX_ tab, layera, n, mode, fd, imode, perm,
1191                               f, narg, args);
1192             if (f) {
1193                 if (n + 1 < layera->cur) {
1194                     /*
1195                      * More layers above the one that we used to open -
1196                      * apply them now
1197                      */
1198                     if (PerlIO_apply_layera(aTHX_ f, mode, layera, n + 1)
1199                         != 0) {
1200                         f = NULL;
1201                     }
1202                 }
1203             }
1204         }
1205         PerlIO_list_free(layera);
1206     }
1207     return f;
1208 }
1209
1210
1211 #undef PerlIO_fdopen
1212 PerlIO *
1213 PerlIO_fdopen(int fd, const char *mode)
1214 {
1215     dTHX;
1216     return PerlIO_openn(aTHX_ Nullch, mode, fd, 0, 0, NULL, 0, NULL);
1217 }
1218
1219 #undef PerlIO_open
1220 PerlIO *
1221 PerlIO_open(const char *path, const char *mode)
1222 {
1223     dTHX;
1224     SV *name = sv_2mortal(newSVpvn(path, strlen(path)));
1225     return PerlIO_openn(aTHX_ Nullch, mode, -1, 0, 0, NULL, 1, &name);
1226 }
1227
1228 #undef PerlIO_reopen
1229 PerlIO *
1230 PerlIO_reopen(const char *path, const char *mode, PerlIO *f)
1231 {
1232     dTHX;
1233     SV *name = sv_2mortal(newSVpvn(path, strlen(path)));
1234     return PerlIO_openn(aTHX_ Nullch, mode, -1, 0, 0, f, 1, &name);
1235 }
1236
1237 #undef PerlIO_read
1238 SSize_t
1239 PerlIO_read(PerlIO *f, void *vbuf, Size_t count)
1240 {
1241     if (f && *f)
1242         return (*PerlIOBase(f)->tab->Read) (f, vbuf, count);
1243     else {
1244         SETERRNO(EBADF, SS$_IVCHAN);
1245         return -1;
1246     }
1247 }
1248
1249 #undef PerlIO_unread
1250 SSize_t
1251 PerlIO_unread(PerlIO *f, const void *vbuf, Size_t count)
1252 {
1253     if (f && *f)
1254         return (*PerlIOBase(f)->tab->Unread) (f, vbuf, count);
1255     else {
1256         SETERRNO(EBADF, SS$_IVCHAN);
1257         return -1;
1258     }
1259 }
1260
1261 #undef PerlIO_write
1262 SSize_t
1263 PerlIO_write(PerlIO *f, const void *vbuf, Size_t count)
1264 {
1265     if (f && *f)
1266         return (*PerlIOBase(f)->tab->Write) (f, vbuf, count);
1267     else {
1268         SETERRNO(EBADF, SS$_IVCHAN);
1269         return -1;
1270     }
1271 }
1272
1273 #undef PerlIO_seek
1274 int
1275 PerlIO_seek(PerlIO *f, Off_t offset, int whence)
1276 {
1277     if (f && *f)
1278         return (*PerlIOBase(f)->tab->Seek) (f, offset, whence);
1279     else {
1280         SETERRNO(EBADF, SS$_IVCHAN);
1281         return -1;
1282     }
1283 }
1284
1285 #undef PerlIO_tell
1286 Off_t
1287 PerlIO_tell(PerlIO *f)
1288 {
1289     if (f && *f)
1290         return (*PerlIOBase(f)->tab->Tell) (f);
1291     else {
1292         SETERRNO(EBADF, SS$_IVCHAN);
1293         return -1;
1294     }
1295 }
1296
1297 #undef PerlIO_flush
1298 int
1299 PerlIO_flush(PerlIO *f)
1300 {
1301     if (f) {
1302         if (*f) {
1303             PerlIO_funcs *tab = PerlIOBase(f)->tab;
1304             if (tab && tab->Flush) {
1305                 return (*tab->Flush) (f);
1306             }
1307             else {
1308                 PerlIO_debug("Cannot flush f=%p :%s\n", f, tab->name);
1309                 SETERRNO(EBADF, SS$_IVCHAN);
1310                 return -1;
1311             }
1312         }
1313         else {
1314             PerlIO_debug("Cannot flush f=%p\n", f);
1315             SETERRNO(EBADF, SS$_IVCHAN);
1316             return -1;
1317         }
1318     }
1319     else {
1320         /*
1321          * Is it good API design to do flush-all on NULL, a potentially
1322          * errorneous input? Maybe some magical value (PerlIO*
1323          * PERLIO_FLUSH_ALL = (PerlIO*)-1;)? Yes, stdio does similar
1324          * things on fflush(NULL), but should we be bound by their design
1325          * decisions? --jhi
1326          */
1327         PerlIO **table = &_perlio;
1328         int code = 0;
1329         while ((f = *table)) {
1330             int i;
1331             table = (PerlIO **) (f++);
1332             for (i = 1; i < PERLIO_TABLE_SIZE; i++) {
1333                 if (*f && PerlIO_flush(f) != 0)
1334                     code = -1;
1335                 f++;
1336             }
1337         }
1338         return code;
1339     }
1340 }
1341
1342 void
1343 PerlIOBase_flush_linebuf()
1344 {
1345     PerlIO **table = &_perlio;
1346     PerlIO *f;
1347     while ((f = *table)) {
1348         int i;
1349         table = (PerlIO **) (f++);
1350         for (i = 1; i < PERLIO_TABLE_SIZE; i++) {
1351             if (*f
1352                 && (PerlIOBase(f)->
1353                     flags & (PERLIO_F_LINEBUF | PERLIO_F_CANWRITE))
1354                 == (PERLIO_F_LINEBUF | PERLIO_F_CANWRITE))
1355                 PerlIO_flush(f);
1356             f++;
1357         }
1358     }
1359 }
1360
1361 #undef PerlIO_fill
1362 int
1363 PerlIO_fill(PerlIO *f)
1364 {
1365     if (f && *f)
1366         return (*PerlIOBase(f)->tab->Fill) (f);
1367     else {
1368         SETERRNO(EBADF, SS$_IVCHAN);
1369         return -1;
1370     }
1371 }
1372
1373 #undef PerlIO_isutf8
1374 int
1375 PerlIO_isutf8(PerlIO *f)
1376 {
1377     if (f && *f)
1378         return (PerlIOBase(f)->flags & PERLIO_F_UTF8) != 0;
1379     else {
1380         SETERRNO(EBADF, SS$_IVCHAN);
1381         return -1;
1382     }
1383 }
1384
1385 #undef PerlIO_eof
1386 int
1387 PerlIO_eof(PerlIO *f)
1388 {
1389     if (f && *f)
1390         return (*PerlIOBase(f)->tab->Eof) (f);
1391     else {
1392         SETERRNO(EBADF, SS$_IVCHAN);
1393         return -1;
1394     }
1395 }
1396
1397 #undef PerlIO_error
1398 int
1399 PerlIO_error(PerlIO *f)
1400 {
1401     if (f && *f)
1402         return (*PerlIOBase(f)->tab->Error) (f);
1403     else {
1404         SETERRNO(EBADF, SS$_IVCHAN);
1405         return -1;
1406     }
1407 }
1408
1409 #undef PerlIO_clearerr
1410 void
1411 PerlIO_clearerr(PerlIO *f)
1412 {
1413     if (f && *f)
1414         (*PerlIOBase(f)->tab->Clearerr) (f);
1415     else
1416         SETERRNO(EBADF, SS$_IVCHAN);
1417 }
1418
1419 #undef PerlIO_setlinebuf
1420 void
1421 PerlIO_setlinebuf(PerlIO *f)
1422 {
1423     if (f && *f)
1424         (*PerlIOBase(f)->tab->Setlinebuf) (f);
1425     else
1426         SETERRNO(EBADF, SS$_IVCHAN);
1427 }
1428
1429 #undef PerlIO_has_base
1430 int
1431 PerlIO_has_base(PerlIO *f)
1432 {
1433     if (f && *f) {
1434         return (PerlIOBase(f)->tab->Get_base != NULL);
1435     }
1436     return 0;
1437 }
1438
1439 #undef PerlIO_fast_gets
1440 int
1441 PerlIO_fast_gets(PerlIO *f)
1442 {
1443     if (f && *f && (PerlIOBase(f)->flags & PERLIO_F_FASTGETS)) {
1444         PerlIO_funcs *tab = PerlIOBase(f)->tab;
1445         return (tab->Set_ptrcnt != NULL);
1446     }
1447     return 0;
1448 }
1449
1450 #undef PerlIO_has_cntptr
1451 int
1452 PerlIO_has_cntptr(PerlIO *f)
1453 {
1454     if (f && *f) {
1455         PerlIO_funcs *tab = PerlIOBase(f)->tab;
1456         return (tab->Get_ptr != NULL && tab->Get_cnt != NULL);
1457     }
1458     return 0;
1459 }
1460
1461 #undef PerlIO_canset_cnt
1462 int
1463 PerlIO_canset_cnt(PerlIO *f)
1464 {
1465     if (f && *f) {
1466         PerlIOl *l = PerlIOBase(f);
1467         return (l->tab->Set_ptrcnt != NULL);
1468     }
1469     return 0;
1470 }
1471
1472 #undef PerlIO_get_base
1473 STDCHAR *
1474 PerlIO_get_base(PerlIO *f)
1475 {
1476     if (f && *f)
1477         return (*PerlIOBase(f)->tab->Get_base) (f);
1478     return NULL;
1479 }
1480
1481 #undef PerlIO_get_bufsiz
1482 int
1483 PerlIO_get_bufsiz(PerlIO *f)
1484 {
1485     if (f && *f)
1486         return (*PerlIOBase(f)->tab->Get_bufsiz) (f);
1487     return 0;
1488 }
1489
1490 #undef PerlIO_get_ptr
1491 STDCHAR *
1492 PerlIO_get_ptr(PerlIO *f)
1493 {
1494     PerlIO_funcs *tab = PerlIOBase(f)->tab;
1495     if (tab->Get_ptr == NULL)
1496         return NULL;
1497     return (*tab->Get_ptr) (f);
1498 }
1499
1500 #undef PerlIO_get_cnt
1501 int
1502 PerlIO_get_cnt(PerlIO *f)
1503 {
1504     PerlIO_funcs *tab = PerlIOBase(f)->tab;
1505     if (tab->Get_cnt == NULL)
1506         return 0;
1507     return (*tab->Get_cnt) (f);
1508 }
1509
1510 #undef PerlIO_set_cnt
1511 void
1512 PerlIO_set_cnt(PerlIO *f, int cnt)
1513 {
1514     (*PerlIOBase(f)->tab->Set_ptrcnt) (f, NULL, cnt);
1515 }
1516
1517 #undef PerlIO_set_ptrcnt
1518 void
1519 PerlIO_set_ptrcnt(PerlIO *f, STDCHAR * ptr, int cnt)
1520 {
1521     PerlIO_funcs *tab = PerlIOBase(f)->tab;
1522     if (tab->Set_ptrcnt == NULL) {
1523         dTHX;
1524         Perl_croak(aTHX_ "PerlIO buffer snooping abuse");
1525     }
1526     (*PerlIOBase(f)->tab->Set_ptrcnt) (f, ptr, cnt);
1527 }
1528
1529 /*--------------------------------------------------------------------------------------*/
1530 /*
1531  * utf8 and raw dummy layers
1532  */
1533
1534 IV
1535 PerlIOUtf8_pushed(PerlIO *f, const char *mode, SV *arg)
1536 {
1537     if (PerlIONext(f)) {
1538         dTHX;
1539         PerlIO_funcs *tab = PerlIOBase(f)->tab;
1540         PerlIO_pop(aTHX_ f);
1541         if (tab->kind & PERLIO_K_UTF8)
1542             PerlIOBase(f)->flags |= PERLIO_F_UTF8;
1543         else
1544             PerlIOBase(f)->flags &= ~PERLIO_F_UTF8;
1545         return 0;
1546     }
1547     return -1;
1548 }
1549
1550 PerlIO_funcs PerlIO_utf8 = {
1551     "utf8",
1552     sizeof(PerlIOl),
1553     PERLIO_K_DUMMY | PERLIO_F_UTF8,
1554     PerlIOUtf8_pushed,
1555     NULL,
1556     NULL,
1557     NULL,
1558     NULL,
1559     NULL,
1560     NULL,
1561     NULL,
1562     NULL,
1563     NULL,
1564     NULL,
1565     NULL,                       /* flush */
1566     NULL,                       /* fill */
1567     NULL,
1568     NULL,
1569     NULL,
1570     NULL,
1571     NULL,                       /* get_base */
1572     NULL,                       /* get_bufsiz */
1573     NULL,                       /* get_ptr */
1574     NULL,                       /* get_cnt */
1575     NULL,                       /* set_ptrcnt */
1576 };
1577
1578 PerlIO_funcs PerlIO_byte = {
1579     "bytes",
1580     sizeof(PerlIOl),
1581     PERLIO_K_DUMMY,
1582     PerlIOUtf8_pushed,
1583     NULL,
1584     NULL,
1585     NULL,
1586     NULL,
1587     NULL,
1588     NULL,
1589     NULL,
1590     NULL,
1591     NULL,
1592     NULL,
1593     NULL,                       /* flush */
1594     NULL,                       /* fill */
1595     NULL,
1596     NULL,
1597     NULL,
1598     NULL,
1599     NULL,                       /* get_base */
1600     NULL,                       /* get_bufsiz */
1601     NULL,                       /* get_ptr */
1602     NULL,                       /* get_cnt */
1603     NULL,                       /* set_ptrcnt */
1604 };
1605
1606 PerlIO *
1607 PerlIORaw_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
1608                IV n, const char *mode, int fd, int imode, int perm,
1609                PerlIO *old, int narg, SV **args)
1610 {
1611     PerlIO_funcs *tab = PerlIO_default_btm();
1612     return (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm,
1613                          old, narg, args);
1614 }
1615
1616 PerlIO_funcs PerlIO_raw = {
1617     "raw",
1618     sizeof(PerlIOl),
1619     PERLIO_K_DUMMY,
1620     PerlIORaw_pushed,
1621     PerlIOBase_popped,
1622     PerlIORaw_open,
1623     NULL,
1624     NULL,
1625     NULL,
1626     NULL,
1627     NULL,
1628     NULL,
1629     NULL,
1630     NULL,
1631     NULL,                       /* flush */
1632     NULL,                       /* fill */
1633     NULL,
1634     NULL,
1635     NULL,
1636     NULL,
1637     NULL,                       /* get_base */
1638     NULL,                       /* get_bufsiz */
1639     NULL,                       /* get_ptr */
1640     NULL,                       /* get_cnt */
1641     NULL,                       /* set_ptrcnt */
1642 };
1643 /*--------------------------------------------------------------------------------------*/
1644 /*--------------------------------------------------------------------------------------*/
1645 /*
1646  * "Methods" of the "base class"
1647  */
1648
1649 IV
1650 PerlIOBase_fileno(PerlIO *f)
1651 {
1652     return PerlIO_fileno(PerlIONext(f));
1653 }
1654
1655 char *
1656 PerlIO_modestr(PerlIO *f, char *buf)
1657 {
1658     char *s = buf;
1659     IV flags = PerlIOBase(f)->flags;
1660     if (flags & PERLIO_F_APPEND) {
1661         *s++ = 'a';
1662         if (flags & PERLIO_F_CANREAD) {
1663             *s++ = '+';
1664         }
1665     }
1666     else if (flags & PERLIO_F_CANREAD) {
1667         *s++ = 'r';
1668         if (flags & PERLIO_F_CANWRITE)
1669             *s++ = '+';
1670     }
1671     else if (flags & PERLIO_F_CANWRITE) {
1672         *s++ = 'w';
1673         if (flags & PERLIO_F_CANREAD) {
1674             *s++ = '+';
1675         }
1676     }
1677 #if O_TEXT != O_BINARY
1678     if (!(flags & PERLIO_F_CRLF))
1679         *s++ = 'b';
1680 #endif
1681     *s = '\0';
1682     return buf;
1683 }
1684
1685 IV
1686 PerlIOBase_pushed(PerlIO *f, const char *mode, SV *arg)
1687 {
1688     PerlIOl *l = PerlIOBase(f);
1689 #if 0
1690     const char *omode = mode;
1691     char temp[8];
1692 #endif
1693     PerlIO_funcs *tab = PerlIOBase(f)->tab;
1694     l->flags &= ~(PERLIO_F_CANREAD | PERLIO_F_CANWRITE |
1695                   PERLIO_F_TRUNCATE | PERLIO_F_APPEND);
1696     if (tab->Set_ptrcnt != NULL)
1697         l->flags |= PERLIO_F_FASTGETS;
1698     if (mode) {
1699         if (*mode == '#' || *mode == 'I')
1700             mode++;
1701         switch (*mode++) {
1702         case 'r':
1703             l->flags |= PERLIO_F_CANREAD;
1704             break;
1705         case 'a':
1706             l->flags |= PERLIO_F_APPEND | PERLIO_F_CANWRITE;
1707             break;
1708         case 'w':
1709             l->flags |= PERLIO_F_TRUNCATE | PERLIO_F_CANWRITE;
1710             break;
1711         default:
1712             SETERRNO(EINVAL, LIB$_INVARG);
1713             return -1;
1714         }
1715         while (*mode) {
1716             switch (*mode++) {
1717             case '+':
1718                 l->flags |= PERLIO_F_CANREAD | PERLIO_F_CANWRITE;
1719                 break;
1720             case 'b':
1721                 l->flags &= ~PERLIO_F_CRLF;
1722                 break;
1723             case 't':
1724                 l->flags |= PERLIO_F_CRLF;
1725                 break;
1726             default:
1727                 SETERRNO(EINVAL, LIB$_INVARG);
1728                 return -1;
1729             }
1730         }
1731     }
1732     else {
1733         if (l->next) {
1734             l->flags |= l->next->flags &
1735                 (PERLIO_F_CANREAD | PERLIO_F_CANWRITE | PERLIO_F_TRUNCATE |
1736                  PERLIO_F_APPEND);
1737         }
1738     }
1739 #if 0
1740     PerlIO_debug("PerlIOBase_pushed f=%p %s %s fl=%08" UVxf " (%s)\n",
1741                  f, PerlIOBase(f)->tab->name, (omode) ? omode : "(Null)",
1742                  l->flags, PerlIO_modestr(f, temp));
1743 #endif
1744     return 0;
1745 }
1746
1747 IV
1748 PerlIOBase_popped(PerlIO *f)
1749 {
1750     return 0;
1751 }
1752
1753 SSize_t
1754 PerlIOBase_unread(PerlIO *f, const void *vbuf, Size_t count)
1755 {
1756     dTHX;
1757     /*
1758      * Save the position as current head considers it
1759      */
1760     Off_t old = PerlIO_tell(f);
1761     SSize_t done;
1762     PerlIO_push(aTHX_ f, &PerlIO_pending, "r", Nullsv);
1763     PerlIOSelf(f, PerlIOBuf)->posn = old;
1764     done = PerlIOBuf_unread(f, vbuf, count);
1765     return done;
1766 }
1767
1768 SSize_t
1769 PerlIOBase_read(PerlIO *f, void *vbuf, Size_t count)
1770 {
1771     STDCHAR *buf = (STDCHAR *) vbuf;
1772     if (f) {
1773         if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD))
1774             return 0;
1775         while (count > 0) {
1776             SSize_t avail = PerlIO_get_cnt(f);
1777             SSize_t take = 0;
1778             if (avail > 0)
1779                 take = (count < avail) ? count : avail;
1780             if (take > 0) {
1781                 STDCHAR *ptr = PerlIO_get_ptr(f);
1782                 Copy(ptr, buf, take, STDCHAR);
1783                 PerlIO_set_ptrcnt(f, ptr + take, (avail -= take));
1784                 count -= take;
1785                 buf += take;
1786             }
1787             if (count > 0 && avail <= 0) {
1788                 if (PerlIO_fill(f) != 0)
1789                     break;
1790             }
1791         }
1792         return (buf - (STDCHAR *) vbuf);
1793     }
1794     return 0;
1795 }
1796
1797 IV
1798 PerlIOBase_noop_ok(PerlIO *f)
1799 {
1800     return 0;
1801 }
1802
1803 IV
1804 PerlIOBase_noop_fail(PerlIO *f)
1805 {
1806     return -1;
1807 }
1808
1809 IV
1810 PerlIOBase_close(PerlIO *f)
1811 {
1812     IV code = 0;
1813     PerlIO *n = PerlIONext(f);
1814     if (PerlIO_flush(f) != 0)
1815         code = -1;
1816     if (n && *n && (*PerlIOBase(n)->tab->Close) (n) != 0)
1817         code = -1;
1818     PerlIOBase(f)->flags &=
1819         ~(PERLIO_F_CANREAD | PERLIO_F_CANWRITE | PERLIO_F_OPEN);
1820     return code;
1821 }
1822
1823 IV
1824 PerlIOBase_eof(PerlIO *f)
1825 {
1826     if (f && *f) {
1827         return (PerlIOBase(f)->flags & PERLIO_F_EOF) != 0;
1828     }
1829     return 1;
1830 }
1831
1832 IV
1833 PerlIOBase_error(PerlIO *f)
1834 {
1835     if (f && *f) {
1836         return (PerlIOBase(f)->flags & PERLIO_F_ERROR) != 0;
1837     }
1838     return 1;
1839 }
1840
1841 void
1842 PerlIOBase_clearerr(PerlIO *f)
1843 {
1844     if (f && *f) {
1845         PerlIO *n = PerlIONext(f);
1846         PerlIOBase(f)->flags &= ~(PERLIO_F_ERROR | PERLIO_F_EOF);
1847         if (n)
1848             PerlIO_clearerr(n);
1849     }
1850 }
1851
1852 void
1853 PerlIOBase_setlinebuf(PerlIO *f)
1854 {
1855     if (f) {
1856         PerlIOBase(f)->flags |= PERLIO_F_LINEBUF;
1857     }
1858 }
1859
1860 /*--------------------------------------------------------------------------------------*/
1861 /*
1862  * Bottom-most level for UNIX-like case
1863  */
1864
1865 typedef struct {
1866     struct _PerlIO base;        /* The generic part */
1867     int fd;                     /* UNIX like file descriptor */
1868     int oflags;                 /* open/fcntl flags */
1869 } PerlIOUnix;
1870
1871 int
1872 PerlIOUnix_oflags(const char *mode)
1873 {
1874     int oflags = -1;
1875     if (*mode == 'I' || *mode == '#')
1876         mode++;
1877     switch (*mode) {
1878     case 'r':
1879         oflags = O_RDONLY;
1880         if (*++mode == '+') {
1881             oflags = O_RDWR;
1882             mode++;
1883         }
1884         break;
1885
1886     case 'w':
1887         oflags = O_CREAT | O_TRUNC;
1888         if (*++mode == '+') {
1889             oflags |= O_RDWR;
1890             mode++;
1891         }
1892         else
1893             oflags |= O_WRONLY;
1894         break;
1895
1896     case 'a':
1897         oflags = O_CREAT | O_APPEND;
1898         if (*++mode == '+') {
1899             oflags |= O_RDWR;
1900             mode++;
1901         }
1902         else
1903             oflags |= O_WRONLY;
1904         break;
1905     }
1906     if (*mode == 'b') {
1907         oflags |= O_BINARY;
1908         oflags &= ~O_TEXT;
1909         mode++;
1910     }
1911     else if (*mode == 't') {
1912         oflags |= O_TEXT;
1913         oflags &= ~O_BINARY;
1914         mode++;
1915     }
1916     /*
1917      * Always open in binary mode
1918      */
1919     oflags |= O_BINARY;
1920     if (*mode || oflags == -1) {
1921         SETERRNO(EINVAL, LIB$_INVARG);
1922         oflags = -1;
1923     }
1924     return oflags;
1925 }
1926
1927 IV
1928 PerlIOUnix_fileno(PerlIO *f)
1929 {
1930     return PerlIOSelf(f, PerlIOUnix)->fd;
1931 }
1932
1933 IV
1934 PerlIOUnix_pushed(PerlIO *f, const char *mode, SV *arg)
1935 {
1936     IV code = PerlIOBase_pushed(f, mode, arg);
1937     if (*PerlIONext(f)) {
1938         PerlIOUnix *s = PerlIOSelf(f, PerlIOUnix);
1939         s->fd = PerlIO_fileno(PerlIONext(f));
1940         /*
1941          * XXX could (or should) we retrieve the oflags from the open file
1942          * handle rather than believing the "mode" we are passed in? XXX
1943          * Should the value on NULL mode be 0 or -1?
1944          */
1945         s->oflags = mode ? PerlIOUnix_oflags(mode) : -1;
1946     }
1947     PerlIOBase(f)->flags |= PERLIO_F_OPEN;
1948     return code;
1949 }
1950
1951 PerlIO *
1952 PerlIOUnix_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
1953                 IV n, const char *mode, int fd, int imode,
1954                 int perm, PerlIO *f, int narg, SV **args)
1955 {
1956     if (f) {
1957         if (PerlIOBase(f)->flags & PERLIO_F_OPEN)
1958             (*PerlIOBase(f)->tab->Close) (f);
1959     }
1960     if (narg > 0) {
1961         char *path = SvPV_nolen(*args);
1962         if (*mode == '#')
1963             mode++;
1964         else {
1965             imode = PerlIOUnix_oflags(mode);
1966             perm = 0666;
1967         }
1968         if (imode != -1) {
1969             fd = PerlLIO_open3(path, imode, perm);
1970         }
1971     }
1972     if (fd >= 0) {
1973         PerlIOUnix *s;
1974         if (*mode == 'I')
1975             mode++;
1976         if (!f) {
1977             f = PerlIO_allocate(aTHX);
1978             s = PerlIOSelf(PerlIO_push(aTHX_ f, self, mode, PerlIOArg),
1979                            PerlIOUnix);
1980         }
1981         else
1982             s = PerlIOSelf(f, PerlIOUnix);
1983         s->fd = fd;
1984         s->oflags = imode;
1985         PerlIOBase(f)->flags |= PERLIO_F_OPEN;
1986         return f;
1987     }
1988     else {
1989         if (f) {
1990             /*
1991              * FIXME: pop layers ???
1992              */
1993         }
1994         return NULL;
1995     }
1996 }
1997
1998 SV *
1999 PerlIO_sv_dup(pTHX_ SV *arg, CLONE_PARAMS *param)
2000 {
2001     if (!arg)
2002         return Nullsv;
2003 #ifdef sv_dup
2004     if (param) {
2005         return sv_dup(arg, param);
2006     }
2007     else {
2008         return newSVsv(arg);
2009     }
2010 #else
2011     return newSVsv(arg);
2012 #endif
2013 }
2014
2015 PerlIO *
2016 PerlIOBase_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param)
2017 {
2018     PerlIO *nexto = PerlIONext(o);
2019     PerlIO_debug("PerlIOBase_dup f=%p o=%p param=%p\n",f,o,param);
2020     if (*nexto) {
2021         PerlIO_funcs *tab = PerlIOBase(nexto)->tab;
2022         f = (*tab->Dup)(aTHX_ f, nexto, param);
2023     }
2024     if (f) {
2025         PerlIO_funcs *self = PerlIOBase(o)->tab;
2026         SV *arg = Nullsv;
2027         char buf[8];
2028         if (self->Getarg) {
2029             arg = (*self->Getarg)(o);
2030             if (arg) {
2031                 arg = PerlIO_sv_dup(aTHX_ arg, param);
2032             }
2033         }
2034         f = PerlIO_push(aTHX_ f, self, PerlIO_modestr(o,buf), arg);
2035         if (!f && arg) {
2036             SvREFCNT_dec(arg);
2037         }
2038     }
2039     return f;
2040 }
2041
2042 PerlIO *
2043 PerlIOUnix_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param)
2044 {
2045     PerlIOUnix *os = PerlIOSelf(o, PerlIOUnix);
2046     int fd = PerlLIO_dup(os->fd);
2047     if (fd >= 0) {
2048         f = PerlIOBase_dup(aTHX_ f, o, param);
2049         if (f) {
2050             /* If all went well overwrite fd in dup'ed lay with the dup()'ed fd */
2051             PerlIOUnix *s = PerlIOSelf(f, PerlIOUnix);
2052             s->fd = fd;
2053             return f;
2054         }
2055         else {
2056             PerlLIO_close(fd);
2057         }
2058     }
2059     return NULL;
2060 }
2061
2062
2063 SSize_t
2064 PerlIOUnix_read(PerlIO *f, void *vbuf, Size_t count)
2065 {
2066     dTHX;
2067     int fd = PerlIOSelf(f, PerlIOUnix)->fd;
2068     if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD))
2069         return 0;
2070     while (1) {
2071         SSize_t len = PerlLIO_read(fd, vbuf, count);
2072         if (len >= 0 || errno != EINTR) {
2073             if (len < 0)
2074                 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
2075             else if (len == 0 && count != 0)
2076                 PerlIOBase(f)->flags |= PERLIO_F_EOF;
2077             return len;
2078         }
2079         PERL_ASYNC_CHECK();
2080     }
2081 }
2082
2083 SSize_t
2084 PerlIOUnix_write(PerlIO *f, const void *vbuf, Size_t count)
2085 {
2086     dTHX;
2087     int fd = PerlIOSelf(f, PerlIOUnix)->fd;
2088     while (1) {
2089         SSize_t len = PerlLIO_write(fd, vbuf, count);
2090         if (len >= 0 || errno != EINTR) {
2091             if (len < 0)
2092                 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
2093             return len;
2094         }
2095         PERL_ASYNC_CHECK();
2096     }
2097 }
2098
2099 IV
2100 PerlIOUnix_seek(PerlIO *f, Off_t offset, int whence)
2101 {
2102     dSYS;
2103     Off_t new =
2104         PerlLIO_lseek(PerlIOSelf(f, PerlIOUnix)->fd, offset, whence);
2105     PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
2106     return (new == (Off_t) - 1) ? -1 : 0;
2107 }
2108
2109 Off_t
2110 PerlIOUnix_tell(PerlIO *f)
2111 {
2112     dSYS;
2113     return PerlLIO_lseek(PerlIOSelf(f, PerlIOUnix)->fd, 0, SEEK_CUR);
2114 }
2115
2116
2117 IV
2118 PerlIOUnix_close(PerlIO *f)
2119 {
2120     dTHX;
2121     int fd = PerlIOSelf(f, PerlIOUnix)->fd;
2122     int code = 0;
2123     while (PerlLIO_close(fd) != 0) {
2124         if (errno != EINTR) {
2125             code = -1;
2126             break;
2127         }
2128         PERL_ASYNC_CHECK();
2129     }
2130     if (code == 0) {
2131         PerlIOBase(f)->flags &= ~PERLIO_F_OPEN;
2132     }
2133     return code;
2134 }
2135
2136 PerlIO_funcs PerlIO_unix = {
2137     "unix",
2138     sizeof(PerlIOUnix),
2139     PERLIO_K_RAW,
2140     PerlIOUnix_pushed,
2141     PerlIOBase_noop_ok,
2142     PerlIOUnix_open,
2143     NULL,
2144     PerlIOUnix_fileno,
2145     PerlIOUnix_dup,
2146     PerlIOUnix_read,
2147     PerlIOBase_unread,
2148     PerlIOUnix_write,
2149     PerlIOUnix_seek,
2150     PerlIOUnix_tell,
2151     PerlIOUnix_close,
2152     PerlIOBase_noop_ok,         /* flush */
2153     PerlIOBase_noop_fail,       /* fill */
2154     PerlIOBase_eof,
2155     PerlIOBase_error,
2156     PerlIOBase_clearerr,
2157     PerlIOBase_setlinebuf,
2158     NULL,                       /* get_base */
2159     NULL,                       /* get_bufsiz */
2160     NULL,                       /* get_ptr */
2161     NULL,                       /* get_cnt */
2162     NULL,                       /* set_ptrcnt */
2163 };
2164
2165 /*--------------------------------------------------------------------------------------*/
2166 /*
2167  * stdio as a layer
2168  */
2169
2170 typedef struct {
2171     struct _PerlIO base;
2172     FILE *stdio;                /* The stream */
2173 } PerlIOStdio;
2174
2175 IV
2176 PerlIOStdio_fileno(PerlIO *f)
2177 {
2178     dSYS;
2179     return PerlSIO_fileno(PerlIOSelf(f, PerlIOStdio)->stdio);
2180 }
2181
2182 char *
2183 PerlIOStdio_mode(const char *mode, char *tmode)
2184 {
2185     char *ret = tmode;
2186     while (*mode) {
2187         *tmode++ = *mode++;
2188     }
2189     if (O_BINARY != O_TEXT) {
2190         *tmode++ = 'b';
2191     }
2192     *tmode = '\0';
2193     return ret;
2194 }
2195
2196 /*
2197  * This isn't used yet ...
2198  */
2199 IV
2200 PerlIOStdio_pushed(PerlIO *f, const char *mode, SV *arg)
2201 {
2202     if (*PerlIONext(f)) {
2203         dSYS;
2204         PerlIOStdio *s = PerlIOSelf(f, PerlIOStdio);
2205         char tmode[8];
2206         FILE *stdio =
2207             PerlSIO_fdopen(PerlIO_fileno(PerlIONext(f)), mode =
2208                            PerlIOStdio_mode(mode, tmode));
2209         if (stdio)
2210             s->stdio = stdio;
2211         else
2212             return -1;
2213     }
2214     return PerlIOBase_pushed(f, mode, arg);
2215 }
2216
2217 #undef PerlIO_importFILE
2218 PerlIO *
2219 PerlIO_importFILE(FILE *stdio, int fl)
2220 {
2221     dTHX;
2222     PerlIO *f = NULL;
2223     if (stdio) {
2224         PerlIOStdio *s =
2225             PerlIOSelf(PerlIO_push
2226                        (aTHX_(f = PerlIO_allocate(aTHX)), &PerlIO_stdio,
2227                         "r+", Nullsv), PerlIOStdio);
2228         s->stdio = stdio;
2229     }
2230     return f;
2231 }
2232
2233 PerlIO *
2234 PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
2235                  IV n, const char *mode, int fd, int imode,
2236                  int perm, PerlIO *f, int narg, SV **args)
2237 {
2238     char tmode[8];
2239     if (f) {
2240         char *path = SvPV_nolen(*args);
2241         PerlIOStdio *s = PerlIOSelf(f, PerlIOStdio);
2242         FILE *stdio =
2243             PerlSIO_freopen(path, (mode = PerlIOStdio_mode(mode, tmode)),
2244                             s->stdio);
2245         if (!s->stdio)
2246             return NULL;
2247         s->stdio = stdio;
2248         return f;
2249     }
2250     else {
2251         if (narg > 0) {
2252             char *path = SvPV_nolen(*args);
2253             if (*mode == '#') {
2254                 mode++;
2255                 fd = PerlLIO_open3(path, imode, perm);
2256             }
2257             else {
2258                 FILE *stdio = PerlSIO_fopen(path, mode);
2259                 if (stdio) {
2260                     PerlIOStdio *s =
2261                         PerlIOSelf(PerlIO_push
2262                                    (aTHX_(f = PerlIO_allocate(aTHX)), self,
2263                                     (mode = PerlIOStdio_mode(mode, tmode)),
2264                                     PerlIOArg),
2265                                    PerlIOStdio);
2266                     s->stdio = stdio;
2267                 }
2268                 return f;
2269             }
2270         }
2271         if (fd >= 0) {
2272             FILE *stdio = NULL;
2273             int init = 0;
2274             if (*mode == 'I') {
2275                 init = 1;
2276                 mode++;
2277             }
2278             if (init) {
2279                 switch (fd) {
2280                 case 0:
2281                     stdio = PerlSIO_stdin;
2282                     break;
2283                 case 1:
2284                     stdio = PerlSIO_stdout;
2285                     break;
2286                 case 2:
2287                     stdio = PerlSIO_stderr;
2288                     break;
2289                 }
2290             }
2291             else {
2292                 stdio = PerlSIO_fdopen(fd, mode =
2293                                        PerlIOStdio_mode(mode, tmode));
2294             }
2295             if (stdio) {
2296                 PerlIOStdio *s =
2297                     PerlIOSelf(PerlIO_push
2298                                (aTHX_(f = PerlIO_allocate(aTHX)), self,
2299                                 mode, PerlIOArg), PerlIOStdio);
2300                 s->stdio = stdio;
2301                 return f;
2302             }
2303         }
2304     }
2305     return NULL;
2306 }
2307
2308 SSize_t
2309 PerlIOStdio_read(PerlIO *f, void *vbuf, Size_t count)
2310 {
2311     dSYS;
2312     FILE *s = PerlIOSelf(f, PerlIOStdio)->stdio;
2313     SSize_t got = 0;
2314     if (count == 1) {
2315         STDCHAR *buf = (STDCHAR *) vbuf;
2316         /*
2317          * Perl is expecting PerlIO_getc() to fill the buffer Linux's
2318          * stdio does not do that for fread()
2319          */
2320         int ch = PerlSIO_fgetc(s);
2321         if (ch != EOF) {
2322             *buf = ch;
2323             got = 1;
2324         }
2325     }
2326     else
2327         got = PerlSIO_fread(vbuf, 1, count, s);
2328     return got;
2329 }
2330
2331 SSize_t
2332 PerlIOStdio_unread(PerlIO *f, const void *vbuf, Size_t count)
2333 {
2334     dSYS;
2335     FILE *s = PerlIOSelf(f, PerlIOStdio)->stdio;
2336     STDCHAR *buf = ((STDCHAR *) vbuf) + count - 1;
2337     SSize_t unread = 0;
2338     while (count > 0) {
2339         int ch = *buf-- & 0xff;
2340         if (PerlSIO_ungetc(ch, s) != ch)
2341             break;
2342         unread++;
2343         count--;
2344     }
2345     return unread;
2346 }
2347
2348 SSize_t
2349 PerlIOStdio_write(PerlIO *f, const void *vbuf, Size_t count)
2350 {
2351     dSYS;
2352     return PerlSIO_fwrite(vbuf, 1, count,
2353                           PerlIOSelf(f, PerlIOStdio)->stdio);
2354 }
2355
2356 IV
2357 PerlIOStdio_seek(PerlIO *f, Off_t offset, int whence)
2358 {
2359     dSYS;
2360     FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2361     return PerlSIO_fseek(stdio, offset, whence);
2362 }
2363
2364 Off_t
2365 PerlIOStdio_tell(PerlIO *f)
2366 {
2367     dSYS;
2368     FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2369     return PerlSIO_ftell(stdio);
2370 }
2371
2372 IV
2373 PerlIOStdio_close(PerlIO *f)
2374 {
2375     dSYS;
2376 #ifdef SOCKS5_VERSION_NAME
2377     int optval;
2378     Sock_size_t optlen = sizeof(int);
2379 #endif
2380     FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2381     return (
2382 #ifdef SOCKS5_VERSION_NAME
2383                (getsockopt
2384                 (PerlIO_fileno(f), SOL_SOCKET, SO_TYPE, (void *) &optval,
2385                  &optlen) <
2386                 0) ? PerlSIO_fclose(stdio) : close(PerlIO_fileno(f))
2387 #else
2388                PerlSIO_fclose(stdio)
2389 #endif
2390         );
2391
2392 }
2393
2394 IV
2395 PerlIOStdio_flush(PerlIO *f)
2396 {
2397     dSYS;
2398     FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2399     if (PerlIOBase(f)->flags & PERLIO_F_CANWRITE) {
2400         return PerlSIO_fflush(stdio);
2401     }
2402     else {
2403 #if 0
2404         /*
2405          * FIXME: This discards ungetc() and pre-read stuff which is not
2406          * right if this is just a "sync" from a layer above Suspect right
2407          * design is to do _this_ but not have layer above flush this
2408          * layer read-to-read
2409          */
2410         /*
2411          * Not writeable - sync by attempting a seek
2412          */
2413         int err = errno;
2414         if (PerlSIO_fseek(stdio, (Off_t) 0, SEEK_CUR) != 0)
2415             errno = err;
2416 #endif
2417     }
2418     return 0;
2419 }
2420
2421 IV
2422 PerlIOStdio_fill(PerlIO *f)
2423 {
2424     dSYS;
2425     FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2426     int c;
2427     /*
2428      * fflush()ing read-only streams can cause trouble on some stdio-s
2429      */
2430     if ((PerlIOBase(f)->flags & PERLIO_F_CANWRITE)) {
2431         if (PerlSIO_fflush(stdio) != 0)
2432             return EOF;
2433     }
2434     c = PerlSIO_fgetc(stdio);
2435     if (c == EOF || PerlSIO_ungetc(c, stdio) != c)
2436         return EOF;
2437     return 0;
2438 }
2439
2440 IV
2441 PerlIOStdio_eof(PerlIO *f)
2442 {
2443     dSYS;
2444     return PerlSIO_feof(PerlIOSelf(f, PerlIOStdio)->stdio);
2445 }
2446
2447 IV
2448 PerlIOStdio_error(PerlIO *f)
2449 {
2450     dSYS;
2451     return PerlSIO_ferror(PerlIOSelf(f, PerlIOStdio)->stdio);
2452 }
2453
2454 void
2455 PerlIOStdio_clearerr(PerlIO *f)
2456 {
2457     dSYS;
2458     PerlSIO_clearerr(PerlIOSelf(f, PerlIOStdio)->stdio);
2459 }
2460
2461 void
2462 PerlIOStdio_setlinebuf(PerlIO *f)
2463 {
2464     dSYS;
2465 #ifdef HAS_SETLINEBUF
2466     PerlSIO_setlinebuf(PerlIOSelf(f, PerlIOStdio)->stdio);
2467 #else
2468     PerlSIO_setvbuf(PerlIOSelf(f, PerlIOStdio)->stdio, Nullch, _IOLBF, 0);
2469 #endif
2470 }
2471
2472 #ifdef FILE_base
2473 STDCHAR *
2474 PerlIOStdio_get_base(PerlIO *f)
2475 {
2476     dSYS;
2477     FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2478     return PerlSIO_get_base(stdio);
2479 }
2480
2481 Size_t
2482 PerlIOStdio_get_bufsiz(PerlIO *f)
2483 {
2484     dSYS;
2485     FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2486     return PerlSIO_get_bufsiz(stdio);
2487 }
2488 #endif
2489
2490 #ifdef USE_STDIO_PTR
2491 STDCHAR *
2492 PerlIOStdio_get_ptr(PerlIO *f)
2493 {
2494     dSYS;
2495     FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2496     return PerlSIO_get_ptr(stdio);
2497 }
2498
2499 SSize_t
2500 PerlIOStdio_get_cnt(PerlIO *f)
2501 {
2502     dSYS;
2503     FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2504     return PerlSIO_get_cnt(stdio);
2505 }
2506
2507 void
2508 PerlIOStdio_set_ptrcnt(PerlIO *f, STDCHAR * ptr, SSize_t cnt)
2509 {
2510     FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
2511     dSYS;
2512     if (ptr != NULL) {
2513 #ifdef STDIO_PTR_LVALUE
2514         PerlSIO_set_ptr(stdio, ptr);
2515 #ifdef STDIO_PTR_LVAL_SETS_CNT
2516         if (PerlSIO_get_cnt(stdio) != (cnt)) {
2517             dTHX;
2518             assert(PerlSIO_get_cnt(stdio) == (cnt));
2519         }
2520 #endif
2521 #if (!defined(STDIO_PTR_LVAL_NOCHANGE_CNT))
2522         /*
2523          * Setting ptr _does_ change cnt - we are done
2524          */
2525         return;
2526 #endif
2527 #else                           /* STDIO_PTR_LVALUE */
2528         PerlProc_abort();
2529 #endif                          /* STDIO_PTR_LVALUE */
2530     }
2531     /*
2532      * Now (or only) set cnt
2533      */
2534 #ifdef STDIO_CNT_LVALUE
2535     PerlSIO_set_cnt(stdio, cnt);
2536 #else                           /* STDIO_CNT_LVALUE */
2537 #if (defined(STDIO_PTR_LVALUE) && defined(STDIO_PTR_LVAL_SETS_CNT))
2538     PerlSIO_set_ptr(stdio,
2539                     PerlSIO_get_ptr(stdio) + (PerlSIO_get_cnt(stdio) -
2540                                               cnt));
2541 #else                           /* STDIO_PTR_LVAL_SETS_CNT */
2542     PerlProc_abort();
2543 #endif                          /* STDIO_PTR_LVAL_SETS_CNT */
2544 #endif                          /* STDIO_CNT_LVALUE */
2545 }
2546
2547 #endif
2548
2549 PerlIO *
2550 PerlIOStdio_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param)
2551 {
2552  return PerlIOBase_dup(aTHX_ f, o, param);
2553 }
2554
2555 PerlIO_funcs PerlIO_stdio = {
2556     "stdio",
2557     sizeof(PerlIOStdio),
2558     PERLIO_K_BUFFERED,
2559     PerlIOBase_pushed,
2560     PerlIOBase_noop_ok,
2561     PerlIOStdio_open,
2562     NULL,
2563     PerlIOStdio_fileno,
2564     PerlIOStdio_dup,
2565     PerlIOStdio_read,
2566     PerlIOStdio_unread,
2567     PerlIOStdio_write,
2568     PerlIOStdio_seek,
2569     PerlIOStdio_tell,
2570     PerlIOStdio_close,
2571     PerlIOStdio_flush,
2572     PerlIOStdio_fill,
2573     PerlIOStdio_eof,
2574     PerlIOStdio_error,
2575     PerlIOStdio_clearerr,
2576     PerlIOStdio_setlinebuf,
2577 #ifdef FILE_base
2578     PerlIOStdio_get_base,
2579     PerlIOStdio_get_bufsiz,
2580 #else
2581     NULL,
2582     NULL,
2583 #endif
2584 #ifdef USE_STDIO_PTR
2585     PerlIOStdio_get_ptr,
2586     PerlIOStdio_get_cnt,
2587 #if (defined(STDIO_PTR_LVALUE) && (defined(STDIO_CNT_LVALUE) || defined(STDIO_PTR_LVAL_SETS_CNT)))
2588     PerlIOStdio_set_ptrcnt
2589 #else                           /* STDIO_PTR_LVALUE */
2590     NULL
2591 #endif                          /* STDIO_PTR_LVALUE */
2592 #else                           /* USE_STDIO_PTR */
2593     NULL,
2594     NULL,
2595     NULL
2596 #endif                          /* USE_STDIO_PTR */
2597 };
2598
2599 #undef PerlIO_exportFILE
2600 FILE *
2601 PerlIO_exportFILE(PerlIO *f, int fl)
2602 {
2603     FILE *stdio;
2604     PerlIO_flush(f);
2605     stdio = fdopen(PerlIO_fileno(f), "r+");
2606     if (stdio) {
2607         dTHX;
2608         PerlIOStdio *s =
2609             PerlIOSelf(PerlIO_push(aTHX_ f, &PerlIO_stdio, "r+", Nullsv),
2610                        PerlIOStdio);
2611         s->stdio = stdio;
2612     }
2613     return stdio;
2614 }
2615
2616 #undef PerlIO_findFILE
2617 FILE *
2618 PerlIO_findFILE(PerlIO *f)
2619 {
2620     PerlIOl *l = *f;
2621     while (l) {
2622         if (l->tab == &PerlIO_stdio) {
2623             PerlIOStdio *s = PerlIOSelf(&l, PerlIOStdio);
2624             return s->stdio;
2625         }
2626         l = *PerlIONext(&l);
2627     }
2628     return PerlIO_exportFILE(f, 0);
2629 }
2630
2631 #undef PerlIO_releaseFILE
2632 void
2633 PerlIO_releaseFILE(PerlIO *p, FILE *f)
2634 {
2635 }
2636
2637 /*--------------------------------------------------------------------------------------*/
2638 /*
2639  * perlio buffer layer
2640  */
2641
2642 IV
2643 PerlIOBuf_pushed(PerlIO *f, const char *mode, SV *arg)
2644 {
2645     dSYS;
2646     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
2647     int fd = PerlIO_fileno(f);
2648     Off_t posn;
2649     if (fd >= 0 && PerlLIO_isatty(fd)) {
2650         PerlIOBase(f)->flags |= PERLIO_F_LINEBUF | PERLIO_F_TTY;
2651     }
2652     posn = PerlIO_tell(PerlIONext(f));
2653     if (posn != (Off_t) - 1) {
2654         b->posn = posn;
2655     }
2656     return PerlIOBase_pushed(f, mode, arg);
2657 }
2658
2659 PerlIO *
2660 PerlIOBuf_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
2661                IV n, const char *mode, int fd, int imode, int perm,
2662                PerlIO *f, int narg, SV **args)
2663 {
2664     if (f) {
2665         PerlIO *next = PerlIONext(f);
2666         PerlIO_funcs *tab =
2667             PerlIO_layer_fetch(aTHX_ layers, n - 1, PerlIOBase(next)->tab);
2668         next =
2669             (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm,
2670                           next, narg, args);
2671         if (!next
2672             || (*PerlIOBase(f)->tab->Pushed) (f, mode, PerlIOArg) != 0) {
2673             return NULL;
2674         }
2675     }
2676     else {
2677         PerlIO_funcs *tab =
2678             PerlIO_layer_fetch(aTHX_ layers, n - 1, PerlIO_default_btm());
2679         int init = 0;
2680         if (*mode == 'I') {
2681             init = 1;
2682             /*
2683              * mode++;
2684              */
2685         }
2686         f = (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm,
2687                           NULL, narg, args);
2688         if (f) {
2689             PerlIO_push(aTHX_ f, self, mode, PerlIOArg);
2690             fd = PerlIO_fileno(f);
2691 #if O_BINARY != O_TEXT
2692             /*
2693              * do something about failing setmode()? --jhi
2694              */
2695             PerlLIO_setmode(fd, O_BINARY);
2696 #endif
2697             if (init && fd == 2) {
2698                 /*
2699                  * Initial stderr is unbuffered
2700                  */
2701                 PerlIOBase(f)->flags |= PERLIO_F_UNBUF;
2702             }
2703         }
2704     }
2705     return f;
2706 }
2707
2708 /*
2709  * This "flush" is akin to sfio's sync in that it handles files in either
2710  * read or write state
2711  */
2712 IV
2713 PerlIOBuf_flush(PerlIO *f)
2714 {
2715     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
2716     int code = 0;
2717     if (PerlIOBase(f)->flags & PERLIO_F_WRBUF) {
2718         /*
2719          * write() the buffer
2720          */
2721         STDCHAR *buf = b->buf;
2722         STDCHAR *p = buf;
2723         PerlIO *n = PerlIONext(f);
2724         while (p < b->ptr) {
2725             SSize_t count = PerlIO_write(n, p, b->ptr - p);
2726             if (count > 0) {
2727                 p += count;
2728             }
2729             else if (count < 0 || PerlIO_error(n)) {
2730                 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
2731                 code = -1;
2732                 break;
2733             }
2734         }
2735         b->posn += (p - buf);
2736     }
2737     else if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
2738         STDCHAR *buf = PerlIO_get_base(f);
2739         /*
2740          * Note position change
2741          */
2742         b->posn += (b->ptr - buf);
2743         if (b->ptr < b->end) {
2744             /*
2745              * We did not consume all of it
2746              */
2747             if (PerlIO_seek(PerlIONext(f), b->posn, SEEK_SET) == 0) {
2748                 b->posn = PerlIO_tell(PerlIONext(f));
2749             }
2750         }
2751     }
2752     b->ptr = b->end = b->buf;
2753     PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
2754     /*
2755      * FIXME: Is this right for read case ?
2756      */
2757     if (PerlIO_flush(PerlIONext(f)) != 0)
2758         code = -1;
2759     return code;
2760 }
2761
2762 IV
2763 PerlIOBuf_fill(PerlIO *f)
2764 {
2765     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
2766     PerlIO *n = PerlIONext(f);
2767     SSize_t avail;
2768     /*
2769      * FIXME: doing the down-stream flush is a bad idea if it causes
2770      * pre-read data in stdio buffer to be discarded but this is too
2771      * simplistic - as it skips _our_ hosekeeping and breaks tell tests.
2772      * if (!(PerlIOBase(f)->flags & PERLIO_F_RDBUF)) { }
2773      */
2774     if (PerlIO_flush(f) != 0)
2775         return -1;
2776     if (PerlIOBase(f)->flags & PERLIO_F_TTY)
2777         PerlIOBase_flush_linebuf();
2778
2779     if (!b->buf)
2780         PerlIO_get_base(f);     /* allocate via vtable */
2781
2782     b->ptr = b->end = b->buf;
2783     if (PerlIO_fast_gets(n)) {
2784         /*
2785          * Layer below is also buffered We do _NOT_ want to call its
2786          * ->Read() because that will loop till it gets what we asked for
2787          * which may hang on a pipe etc. Instead take anything it has to
2788          * hand, or ask it to fill _once_.
2789          */
2790         avail = PerlIO_get_cnt(n);
2791         if (avail <= 0) {
2792             avail = PerlIO_fill(n);
2793             if (avail == 0)
2794                 avail = PerlIO_get_cnt(n);
2795             else {
2796                 if (!PerlIO_error(n) && PerlIO_eof(n))
2797                     avail = 0;
2798             }
2799         }
2800         if (avail > 0) {
2801             STDCHAR *ptr = PerlIO_get_ptr(n);
2802             SSize_t cnt = avail;
2803             if (avail > b->bufsiz)
2804                 avail = b->bufsiz;
2805             Copy(ptr, b->buf, avail, STDCHAR);
2806             PerlIO_set_ptrcnt(n, ptr + avail, cnt - avail);
2807         }
2808     }
2809     else {
2810         avail = PerlIO_read(n, b->ptr, b->bufsiz);
2811     }
2812     if (avail <= 0) {
2813         if (avail == 0)
2814             PerlIOBase(f)->flags |= PERLIO_F_EOF;
2815         else
2816             PerlIOBase(f)->flags |= PERLIO_F_ERROR;
2817         return -1;
2818     }
2819     b->end = b->buf + avail;
2820     PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
2821     return 0;
2822 }
2823
2824 SSize_t
2825 PerlIOBuf_read(PerlIO *f, void *vbuf, Size_t count)
2826 {
2827     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
2828     if (f) {
2829         if (!b->ptr)
2830             PerlIO_get_base(f);
2831         return PerlIOBase_read(f, vbuf, count);
2832     }
2833     return 0;
2834 }
2835
2836 SSize_t
2837 PerlIOBuf_unread(PerlIO *f, const void *vbuf, Size_t count)
2838 {
2839     const STDCHAR *buf = (const STDCHAR *) vbuf + count;
2840     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
2841     SSize_t unread = 0;
2842     SSize_t avail;
2843     if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
2844         PerlIO_flush(f);
2845     if (!b->buf)
2846         PerlIO_get_base(f);
2847     if (b->buf) {
2848         if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
2849             /*
2850              * Buffer is already a read buffer, we can overwrite any chars
2851              * which have been read back to buffer start
2852              */
2853             avail = (b->ptr - b->buf);
2854         }
2855         else {
2856             /*
2857              * Buffer is idle, set it up so whole buffer is available for
2858              * unread
2859              */
2860             avail = b->bufsiz;
2861             b->end = b->buf + avail;
2862             b->ptr = b->end;
2863             PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
2864             /*
2865              * Buffer extends _back_ from where we are now
2866              */
2867             b->posn -= b->bufsiz;
2868         }
2869         if (avail > (SSize_t) count) {
2870             /*
2871              * If we have space for more than count, just move count
2872              */
2873             avail = count;
2874         }
2875         if (avail > 0) {
2876             b->ptr -= avail;
2877             buf -= avail;
2878             /*
2879              * In simple stdio-like ungetc() case chars will be already
2880              * there
2881              */
2882             if (buf != b->ptr) {
2883                 Copy(buf, b->ptr, avail, STDCHAR);
2884             }
2885             count -= avail;
2886             unread += avail;
2887             PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
2888         }
2889     }
2890     return unread;
2891 }
2892
2893 SSize_t
2894 PerlIOBuf_write(PerlIO *f, const void *vbuf, Size_t count)
2895 {
2896     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
2897     const STDCHAR *buf = (const STDCHAR *) vbuf;
2898     Size_t written = 0;
2899     if (!b->buf)
2900         PerlIO_get_base(f);
2901     if (!(PerlIOBase(f)->flags & PERLIO_F_CANWRITE))
2902         return 0;
2903     while (count > 0) {
2904         SSize_t avail = b->bufsiz - (b->ptr - b->buf);
2905         if ((SSize_t) count < avail)
2906             avail = count;
2907         PerlIOBase(f)->flags |= PERLIO_F_WRBUF;
2908         if (PerlIOBase(f)->flags & PERLIO_F_LINEBUF) {
2909             while (avail > 0) {
2910                 int ch = *buf++;
2911                 *(b->ptr)++ = ch;
2912                 count--;
2913                 avail--;
2914                 written++;
2915                 if (ch == '\n') {
2916                     PerlIO_flush(f);
2917                     break;
2918                 }
2919             }
2920         }
2921         else {
2922             if (avail) {
2923                 Copy(buf, b->ptr, avail, STDCHAR);
2924                 count -= avail;
2925                 buf += avail;
2926                 written += avail;
2927                 b->ptr += avail;
2928             }
2929         }
2930         if (b->ptr >= (b->buf + b->bufsiz))
2931             PerlIO_flush(f);
2932     }
2933     if (PerlIOBase(f)->flags & PERLIO_F_UNBUF)
2934         PerlIO_flush(f);
2935     return written;
2936 }
2937
2938 IV
2939 PerlIOBuf_seek(PerlIO *f, Off_t offset, int whence)
2940 {
2941     IV code;
2942     if ((code = PerlIO_flush(f)) == 0) {
2943         PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
2944         PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
2945         code = PerlIO_seek(PerlIONext(f), offset, whence);
2946         if (code == 0) {
2947             b->posn = PerlIO_tell(PerlIONext(f));
2948         }
2949     }
2950     return code;
2951 }
2952
2953 Off_t
2954 PerlIOBuf_tell(PerlIO *f)
2955 {
2956     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
2957     /*
2958      * b->posn is file position where b->buf was read, or will be written
2959      */
2960     Off_t posn = b->posn;
2961     if (b->buf) {
2962         /*
2963          * If buffer is valid adjust position by amount in buffer
2964          */
2965         posn += (b->ptr - b->buf);
2966     }
2967     return posn;
2968 }
2969
2970 IV
2971 PerlIOBuf_close(PerlIO *f)
2972 {
2973     IV code = PerlIOBase_close(f);
2974     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
2975     if (b->buf && b->buf != (STDCHAR *) & b->oneword) {
2976         PerlMemShared_free(b->buf);
2977     }
2978     b->buf = NULL;
2979     b->ptr = b->end = b->buf;
2980     PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
2981     return code;
2982 }
2983
2984 STDCHAR *
2985 PerlIOBuf_get_ptr(PerlIO *f)
2986 {
2987     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
2988     if (!b->buf)
2989         PerlIO_get_base(f);
2990     return b->ptr;
2991 }
2992
2993 SSize_t
2994 PerlIOBuf_get_cnt(PerlIO *f)
2995 {
2996     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
2997     if (!b->buf)
2998         PerlIO_get_base(f);
2999     if (PerlIOBase(f)->flags & PERLIO_F_RDBUF)
3000         return (b->end - b->ptr);
3001     return 0;
3002 }
3003
3004 STDCHAR *
3005 PerlIOBuf_get_base(PerlIO *f)
3006 {
3007     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3008     if (!b->buf) {
3009         if (!b->bufsiz)
3010             b->bufsiz = 4096;
3011         b->buf = PerlMemShared_calloc(b->bufsiz, sizeof(STDCHAR));
3012         if (!b->buf) {
3013             b->buf = (STDCHAR *) & b->oneword;
3014             b->bufsiz = sizeof(b->oneword);
3015         }
3016         b->ptr = b->buf;
3017         b->end = b->ptr;
3018     }
3019     return b->buf;
3020 }
3021
3022 Size_t
3023 PerlIOBuf_bufsiz(PerlIO *f)
3024 {
3025     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3026     if (!b->buf)
3027         PerlIO_get_base(f);
3028     return (b->end - b->buf);
3029 }
3030
3031 void
3032 PerlIOBuf_set_ptrcnt(PerlIO *f, STDCHAR * ptr, SSize_t cnt)
3033 {
3034     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3035     if (!b->buf)
3036         PerlIO_get_base(f);
3037     b->ptr = ptr;
3038     if (PerlIO_get_cnt(f) != cnt || b->ptr < b->buf) {
3039         dTHX;
3040         assert(PerlIO_get_cnt(f) == cnt);
3041         assert(b->ptr >= b->buf);
3042     }
3043     PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
3044 }
3045
3046 PerlIO *
3047 PerlIOBuf_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param)
3048 {
3049  return PerlIOBase_dup(aTHX_ f, o, param);
3050 }
3051
3052
3053
3054 PerlIO_funcs PerlIO_perlio = {
3055     "perlio",
3056     sizeof(PerlIOBuf),
3057     PERLIO_K_BUFFERED,
3058     PerlIOBuf_pushed,
3059     PerlIOBase_noop_ok,
3060     PerlIOBuf_open,
3061     NULL,
3062     PerlIOBase_fileno,
3063     PerlIOBuf_dup,
3064     PerlIOBuf_read,
3065     PerlIOBuf_unread,
3066     PerlIOBuf_write,
3067     PerlIOBuf_seek,
3068     PerlIOBuf_tell,
3069     PerlIOBuf_close,
3070     PerlIOBuf_flush,
3071     PerlIOBuf_fill,
3072     PerlIOBase_eof,
3073     PerlIOBase_error,
3074     PerlIOBase_clearerr,
3075     PerlIOBase_setlinebuf,
3076     PerlIOBuf_get_base,
3077     PerlIOBuf_bufsiz,
3078     PerlIOBuf_get_ptr,
3079     PerlIOBuf_get_cnt,
3080     PerlIOBuf_set_ptrcnt,
3081 };
3082
3083 /*--------------------------------------------------------------------------------------*/
3084 /*
3085  * Temp layer to hold unread chars when cannot do it any other way
3086  */
3087
3088 IV
3089 PerlIOPending_fill(PerlIO *f)
3090 {
3091     /*
3092      * Should never happen
3093      */
3094     PerlIO_flush(f);
3095     return 0;
3096 }
3097
3098 IV
3099 PerlIOPending_close(PerlIO *f)
3100 {
3101     /*
3102      * A tad tricky - flush pops us, then we close new top
3103      */
3104     PerlIO_flush(f);
3105     return PerlIO_close(f);
3106 }
3107
3108 IV
3109 PerlIOPending_seek(PerlIO *f, Off_t offset, int whence)
3110 {
3111     /*
3112      * A tad tricky - flush pops us, then we seek new top
3113      */
3114     PerlIO_flush(f);
3115     return PerlIO_seek(f, offset, whence);
3116 }
3117
3118
3119 IV
3120 PerlIOPending_flush(PerlIO *f)
3121 {
3122     dTHX;
3123     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3124     if (b->buf && b->buf != (STDCHAR *) & b->oneword) {
3125         PerlMemShared_free(b->buf);
3126         b->buf = NULL;
3127     }
3128     PerlIO_pop(aTHX_ f);
3129     return 0;
3130 }
3131
3132 void
3133 PerlIOPending_set_ptrcnt(PerlIO *f, STDCHAR * ptr, SSize_t cnt)
3134 {
3135     if (cnt <= 0) {
3136         PerlIO_flush(f);
3137     }
3138     else {
3139         PerlIOBuf_set_ptrcnt(f, ptr, cnt);
3140     }
3141 }
3142
3143 IV
3144 PerlIOPending_pushed(PerlIO *f, const char *mode, SV *arg)
3145 {
3146     IV code = PerlIOBase_pushed(f, mode, arg);
3147     PerlIOl *l = PerlIOBase(f);
3148     /*
3149      * Our PerlIO_fast_gets must match what we are pushed on, or sv_gets()
3150      * etc. get muddled when it changes mid-string when we auto-pop.
3151      */
3152     l->flags = (l->flags & ~(PERLIO_F_FASTGETS | PERLIO_F_UTF8)) |
3153         (PerlIOBase(PerlIONext(f))->
3154          flags & (PERLIO_F_FASTGETS | PERLIO_F_UTF8));
3155     return code;
3156 }
3157
3158 SSize_t
3159 PerlIOPending_read(PerlIO *f, void *vbuf, Size_t count)
3160 {
3161     SSize_t avail = PerlIO_get_cnt(f);
3162     SSize_t got = 0;
3163     if (count < avail)
3164         avail = count;
3165     if (avail > 0)
3166         got = PerlIOBuf_read(f, vbuf, avail);
3167     if (got >= 0 && got < count) {
3168         SSize_t more =
3169             PerlIO_read(f, ((STDCHAR *) vbuf) + got, count - got);
3170         if (more >= 0 || got == 0)
3171             got += more;
3172     }
3173     return got;
3174 }
3175
3176 PerlIO_funcs PerlIO_pending = {
3177     "pending",
3178     sizeof(PerlIOBuf),
3179     PERLIO_K_BUFFERED,
3180     PerlIOPending_pushed,
3181     PerlIOBase_noop_ok,
3182     NULL,
3183     NULL,
3184     PerlIOBase_fileno,
3185     PerlIOBuf_dup,
3186     PerlIOPending_read,
3187     PerlIOBuf_unread,
3188     PerlIOBuf_write,
3189     PerlIOPending_seek,
3190     PerlIOBuf_tell,
3191     PerlIOPending_close,
3192     PerlIOPending_flush,
3193     PerlIOPending_fill,
3194     PerlIOBase_eof,
3195     PerlIOBase_error,
3196     PerlIOBase_clearerr,
3197     PerlIOBase_setlinebuf,
3198     PerlIOBuf_get_base,
3199     PerlIOBuf_bufsiz,
3200     PerlIOBuf_get_ptr,
3201     PerlIOBuf_get_cnt,
3202     PerlIOPending_set_ptrcnt,
3203 };
3204
3205
3206
3207 /*--------------------------------------------------------------------------------------*/
3208 /*
3209  * crlf - translation On read translate CR,LF to "\n" we do this by
3210  * overriding ptr/cnt entries to hand back a line at a time and keeping a
3211  * record of which nl we "lied" about. On write translate "\n" to CR,LF
3212  */
3213
3214 typedef struct {
3215     PerlIOBuf base;             /* PerlIOBuf stuff */
3216     STDCHAR *nl;                /* Position of crlf we "lied" about in the
3217                                  * buffer */
3218 } PerlIOCrlf;
3219
3220 IV
3221 PerlIOCrlf_pushed(PerlIO *f, const char *mode, SV *arg)
3222 {
3223     IV code;
3224     PerlIOBase(f)->flags |= PERLIO_F_CRLF;
3225     code = PerlIOBuf_pushed(f, mode, arg);
3226 #if 0
3227     PerlIO_debug("PerlIOCrlf_pushed f=%p %s %s fl=%08" UVxf "\n",
3228                  f, PerlIOBase(f)->tab->name, (mode) ? mode : "(Null)",
3229                  PerlIOBase(f)->flags);
3230 #endif
3231     return code;
3232 }
3233
3234
3235 SSize_t
3236 PerlIOCrlf_unread(PerlIO *f, const void *vbuf, Size_t count)
3237 {
3238     PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf);
3239     if (c->nl) {
3240         *(c->nl) = 0xd;
3241         c->nl = NULL;
3242     }
3243     if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF))
3244         return PerlIOBuf_unread(f, vbuf, count);
3245     else {
3246         const STDCHAR *buf = (const STDCHAR *) vbuf + count;
3247         PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3248         SSize_t unread = 0;
3249         if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
3250             PerlIO_flush(f);
3251         if (!b->buf)
3252             PerlIO_get_base(f);
3253         if (b->buf) {
3254             if (!(PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
3255                 b->end = b->ptr = b->buf + b->bufsiz;
3256                 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
3257                 b->posn -= b->bufsiz;
3258             }
3259             while (count > 0 && b->ptr > b->buf) {
3260                 int ch = *--buf;
3261                 if (ch == '\n') {
3262                     if (b->ptr - 2 >= b->buf) {
3263                         *--(b->ptr) = 0xa;
3264                         *--(b->ptr) = 0xd;
3265                         unread++;
3266                         count--;
3267                     }
3268                     else {
3269                         buf++;
3270                         break;
3271                     }
3272                 }
3273                 else {
3274                     *--(b->ptr) = ch;
3275                     unread++;
3276                     count--;
3277                 }
3278             }
3279         }
3280         return unread;
3281     }
3282 }
3283
3284 SSize_t
3285 PerlIOCrlf_get_cnt(PerlIO *f)
3286 {
3287     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3288     if (!b->buf)
3289         PerlIO_get_base(f);
3290     if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
3291         PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf);
3292         if ((PerlIOBase(f)->flags & PERLIO_F_CRLF) && !c->nl) {
3293             STDCHAR *nl = b->ptr;
3294           scan:
3295             while (nl < b->end && *nl != 0xd)
3296                 nl++;
3297             if (nl < b->end && *nl == 0xd) {
3298               test:
3299                 if (nl + 1 < b->end) {
3300                     if (nl[1] == 0xa) {
3301                         *nl = '\n';
3302                         c->nl = nl;
3303                     }
3304                     else {
3305                         /*
3306                          * Not CR,LF but just CR
3307                          */
3308                         nl++;
3309                         goto scan;
3310                     }
3311                 }
3312                 else {
3313                     /*
3314                      * Blast - found CR as last char in buffer
3315                      */
3316                     if (b->ptr < nl) {
3317                         /*
3318                          * They may not care, defer work as long as
3319                          * possible
3320                          */
3321                         return (nl - b->ptr);
3322                     }
3323                     else {
3324                         int code;
3325                         b->ptr++;       /* say we have read it as far as
3326                                          * flush() is concerned */
3327                         b->buf++;       /* Leave space an front of buffer */
3328                         b->bufsiz--;    /* Buffer is thus smaller */
3329                         code = PerlIO_fill(f);  /* Fetch some more */
3330                         b->bufsiz++;    /* Restore size for next time */
3331                         b->buf--;       /* Point at space */
3332                         b->ptr = nl = b->buf;   /* Which is what we hand
3333                                                  * off */
3334                         b->posn--;      /* Buffer starts here */
3335                         *nl = 0xd;      /* Fill in the CR */
3336                         if (code == 0)
3337                             goto test;  /* fill() call worked */
3338                         /*
3339                          * CR at EOF - just fall through
3340                          */
3341                     }
3342                 }
3343             }
3344         }
3345         return (((c->nl) ? (c->nl + 1) : b->end) - b->ptr);
3346     }
3347     return 0;
3348 }
3349
3350 void
3351 PerlIOCrlf_set_ptrcnt(PerlIO *f, STDCHAR * ptr, SSize_t cnt)
3352 {
3353     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3354     PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf);
3355     IV flags = PerlIOBase(f)->flags;
3356     if (!b->buf)
3357         PerlIO_get_base(f);
3358     if (!ptr) {
3359         if (c->nl)
3360             ptr = c->nl + 1;
3361         else {
3362             ptr = b->end;
3363             if ((flags & PERLIO_F_CRLF) && ptr > b->buf && ptr[-1] == 0xd)
3364                 ptr--;
3365         }
3366         ptr -= cnt;
3367     }
3368     else {
3369         /*
3370          * Test code - delete when it works ...
3371          */
3372         STDCHAR *chk;
3373         if (c->nl)
3374             chk = c->nl + 1;
3375         else {
3376             chk = b->end;
3377             if ((flags & PERLIO_F_CRLF) && chk > b->buf && chk[-1] == 0xd)
3378                 chk--;
3379         }
3380         chk -= cnt;
3381
3382         if (ptr != chk) {
3383             dTHX;
3384             Perl_croak(aTHX_ "ptr wrong %p != %p fl=%08" UVxf
3385                        " nl=%p e=%p for %d", ptr, chk, flags, c->nl,
3386                        b->end, cnt);
3387         }
3388     }
3389     if (c->nl) {
3390         if (ptr > c->nl) {
3391             /*
3392              * They have taken what we lied about
3393              */
3394             *(c->nl) = 0xd;
3395             c->nl = NULL;
3396             ptr++;
3397         }
3398     }
3399     b->ptr = ptr;
3400     PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
3401 }
3402
3403 SSize_t
3404 PerlIOCrlf_write(PerlIO *f, const void *vbuf, Size_t count)
3405 {
3406     if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF))
3407         return PerlIOBuf_write(f, vbuf, count);
3408     else {
3409         PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3410         const STDCHAR *buf = (const STDCHAR *) vbuf;
3411         const STDCHAR *ebuf = buf + count;
3412         if (!b->buf)
3413             PerlIO_get_base(f);
3414         if (!(PerlIOBase(f)->flags & PERLIO_F_CANWRITE))
3415             return 0;
3416         while (buf < ebuf) {
3417             STDCHAR *eptr = b->buf + b->bufsiz;
3418             PerlIOBase(f)->flags |= PERLIO_F_WRBUF;
3419             while (buf < ebuf && b->ptr < eptr) {
3420                 if (*buf == '\n') {
3421                     if ((b->ptr + 2) > eptr) {
3422                         /*
3423                          * Not room for both
3424                          */
3425                         PerlIO_flush(f);
3426                         break;
3427                     }
3428                     else {
3429                         *(b->ptr)++ = 0xd;      /* CR */
3430                         *(b->ptr)++ = 0xa;      /* LF */
3431                         buf++;
3432                         if (PerlIOBase(f)->flags & PERLIO_F_LINEBUF) {
3433                             PerlIO_flush(f);
3434                             break;
3435                         }
3436                     }
3437                 }
3438                 else {
3439                     int ch = *buf++;
3440                     *(b->ptr)++ = ch;
3441                 }
3442                 if (b->ptr >= eptr) {
3443                     PerlIO_flush(f);
3444                     break;
3445                 }
3446             }
3447         }
3448         if (PerlIOBase(f)->flags & PERLIO_F_UNBUF)
3449             PerlIO_flush(f);
3450         return (buf - (STDCHAR *) vbuf);
3451     }
3452 }
3453
3454 IV
3455 PerlIOCrlf_flush(PerlIO *f)
3456 {
3457     PerlIOCrlf *c = PerlIOSelf(f, PerlIOCrlf);
3458     if (c->nl) {
3459         *(c->nl) = 0xd;
3460         c->nl = NULL;
3461     }
3462     return PerlIOBuf_flush(f);
3463 }
3464
3465 PerlIO_funcs PerlIO_crlf = {
3466     "crlf",
3467     sizeof(PerlIOCrlf),
3468     PERLIO_K_BUFFERED | PERLIO_K_CANCRLF,
3469     PerlIOCrlf_pushed,
3470     PerlIOBase_noop_ok,         /* popped */
3471     PerlIOBuf_open,
3472     NULL,
3473     PerlIOBase_fileno,
3474     PerlIOBuf_dup,
3475     PerlIOBuf_read,             /* generic read works with ptr/cnt lies
3476                                  * ... */
3477     PerlIOCrlf_unread,          /* Put CR,LF in buffer for each '\n' */
3478     PerlIOCrlf_write,           /* Put CR,LF in buffer for each '\n' */
3479     PerlIOBuf_seek,
3480     PerlIOBuf_tell,
3481     PerlIOBuf_close,
3482     PerlIOCrlf_flush,
3483     PerlIOBuf_fill,
3484     PerlIOBase_eof,
3485     PerlIOBase_error,
3486     PerlIOBase_clearerr,
3487     PerlIOBase_setlinebuf,
3488     PerlIOBuf_get_base,
3489     PerlIOBuf_bufsiz,
3490     PerlIOBuf_get_ptr,
3491     PerlIOCrlf_get_cnt,
3492     PerlIOCrlf_set_ptrcnt,
3493 };
3494
3495 #ifdef HAS_MMAP
3496 /*--------------------------------------------------------------------------------------*/
3497 /*
3498  * mmap as "buffer" layer
3499  */
3500
3501 typedef struct {
3502     PerlIOBuf base;             /* PerlIOBuf stuff */
3503     Mmap_t mptr;                /* Mapped address */
3504     Size_t len;                 /* mapped length */
3505     STDCHAR *bbuf;              /* malloced buffer if map fails */
3506 } PerlIOMmap;
3507
3508 static size_t page_size = 0;
3509
3510 IV
3511 PerlIOMmap_map(PerlIO *f)
3512 {
3513     dTHX;
3514     PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
3515     IV flags = PerlIOBase(f)->flags;
3516     IV code = 0;
3517     if (m->len)
3518         abort();
3519     if (flags & PERLIO_F_CANREAD) {
3520         PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3521         int fd = PerlIO_fileno(f);
3522         struct stat st;
3523         code = fstat(fd, &st);
3524         if (code == 0 && S_ISREG(st.st_mode)) {
3525             SSize_t len = st.st_size - b->posn;
3526             if (len > 0) {
3527                 Off_t posn;
3528                 if (!page_size) {
3529 #if defined(HAS_SYSCONF) && (defined(_SC_PAGESIZE) || defined(_SC_PAGE_SIZE))
3530                     {
3531                         SETERRNO(0, SS$_NORMAL);
3532 #   ifdef _SC_PAGESIZE
3533                         page_size = sysconf(_SC_PAGESIZE);
3534 #   else
3535                         page_size = sysconf(_SC_PAGE_SIZE);
3536 #   endif
3537                         if ((long) page_size < 0) {
3538                             if (errno) {
3539                                 SV *error = ERRSV;
3540                                 char *msg;
3541                                 STRLEN n_a;
3542                                 (void) SvUPGRADE(error, SVt_PV);
3543                                 msg = SvPVx(error, n_a);
3544                                 Perl_croak(aTHX_ "panic: sysconf: %s",
3545                                            msg);
3546                             }
3547                             else
3548                                 Perl_croak(aTHX_
3549                                            "panic: sysconf: pagesize unknown");
3550                         }
3551                     }
3552 #else
3553 #   ifdef HAS_GETPAGESIZE
3554                     page_size = getpagesize();
3555 #   else
3556 #       if defined(I_SYS_PARAM) && defined(PAGESIZE)
3557                     page_size = PAGESIZE;       /* compiletime, bad */
3558 #       endif
3559 #   endif
3560 #endif
3561                     if ((IV) page_size <= 0)
3562                         Perl_croak(aTHX_ "panic: bad pagesize %" IVdf,
3563                                    (IV) page_size);
3564                 }
3565                 if (b->posn < 0) {
3566                     /*
3567                      * This is a hack - should never happen - open should
3568                      * have set it !
3569                      */
3570                     b->posn = PerlIO_tell(PerlIONext(f));
3571                 }
3572                 posn = (b->posn / page_size) * page_size;
3573                 len = st.st_size - posn;
3574                 m->mptr = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, posn);
3575                 if (m->mptr && m->mptr != (Mmap_t) - 1) {
3576 #if 0 && defined(HAS_MADVISE) && defined(MADV_SEQUENTIAL)
3577                     madvise(m->mptr, len, MADV_SEQUENTIAL);
3578 #endif
3579 #if 0 && defined(HAS_MADVISE) && defined(MADV_WILLNEED)
3580                     madvise(m->mptr, len, MADV_WILLNEED);
3581 #endif
3582                     PerlIOBase(f)->flags =
3583                         (flags & ~PERLIO_F_EOF) | PERLIO_F_RDBUF;
3584                     b->end = ((STDCHAR *) m->mptr) + len;
3585                     b->buf = ((STDCHAR *) m->mptr) + (b->posn - posn);
3586                     b->ptr = b->buf;
3587                     m->len = len;
3588                 }
3589                 else {
3590                     b->buf = NULL;
3591                 }
3592             }
3593             else {
3594                 PerlIOBase(f)->flags =
3595                     flags | PERLIO_F_EOF | PERLIO_F_RDBUF;
3596                 b->buf = NULL;
3597                 b->ptr = b->end = b->ptr;
3598                 code = -1;
3599             }
3600         }
3601     }
3602     return code;
3603 }
3604
3605 IV
3606 PerlIOMmap_unmap(PerlIO *f)
3607 {
3608     PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
3609     PerlIOBuf *b = &m->base;
3610     IV code = 0;
3611     if (m->len) {
3612         if (b->buf) {
3613             code = munmap(m->mptr, m->len);
3614             b->buf = NULL;
3615             m->len = 0;
3616             m->mptr = NULL;
3617             if (PerlIO_seek(PerlIONext(f), b->posn, SEEK_SET) != 0)
3618                 code = -1;
3619         }
3620         b->ptr = b->end = b->buf;
3621         PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
3622     }
3623     return code;
3624 }
3625
3626 STDCHAR *
3627 PerlIOMmap_get_base(PerlIO *f)
3628 {
3629     PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
3630     PerlIOBuf *b = &m->base;
3631     if (b->buf && (PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
3632         /*
3633          * Already have a readbuffer in progress
3634          */
3635         return b->buf;
3636     }
3637     if (b->buf) {
3638         /*
3639          * We have a write buffer or flushed PerlIOBuf read buffer
3640          */
3641         m->bbuf = b->buf;       /* save it in case we need it again */
3642         b->buf = NULL;          /* Clear to trigger below */
3643     }
3644     if (!b->buf) {
3645         PerlIOMmap_map(f);      /* Try and map it */
3646         if (!b->buf) {
3647             /*
3648              * Map did not work - recover PerlIOBuf buffer if we have one
3649              */
3650             b->buf = m->bbuf;
3651         }
3652     }
3653     b->ptr = b->end = b->buf;
3654     if (b->buf)
3655         return b->buf;
3656     return PerlIOBuf_get_base(f);
3657 }
3658
3659 SSize_t
3660 PerlIOMmap_unread(PerlIO *f, const void *vbuf, Size_t count)
3661 {
3662     PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
3663     PerlIOBuf *b = &m->base;
3664     if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
3665         PerlIO_flush(f);
3666     if (b->ptr && (b->ptr - count) >= b->buf
3667         && memEQ(b->ptr - count, vbuf, count)) {
3668         b->ptr -= count;
3669         PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
3670         return count;
3671     }
3672     if (m->len) {
3673         /*
3674          * Loose the unwritable mapped buffer
3675          */
3676         PerlIO_flush(f);
3677         /*
3678          * If flush took the "buffer" see if we have one from before
3679          */
3680         if (!b->buf && m->bbuf)
3681             b->buf = m->bbuf;
3682         if (!b->buf) {
3683             PerlIOBuf_get_base(f);
3684             m->bbuf = b->buf;
3685         }
3686     }
3687     return PerlIOBuf_unread(f, vbuf, count);
3688 }
3689
3690 SSize_t
3691 PerlIOMmap_write(PerlIO *f, const void *vbuf, Size_t count)
3692 {
3693     PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
3694     PerlIOBuf *b = &m->base;
3695     if (!b->buf || !(PerlIOBase(f)->flags & PERLIO_F_WRBUF)) {
3696         /*
3697          * No, or wrong sort of, buffer
3698          */
3699         if (m->len) {
3700             if (PerlIOMmap_unmap(f) != 0)
3701                 return 0;
3702         }
3703         /*
3704          * If unmap took the "buffer" see if we have one from before
3705          */
3706         if (!b->buf && m->bbuf)
3707             b->buf = m->bbuf;
3708         if (!b->buf) {
3709             PerlIOBuf_get_base(f);
3710             m->bbuf = b->buf;
3711         }
3712     }
3713     return PerlIOBuf_write(f, vbuf, count);
3714 }
3715
3716 IV
3717 PerlIOMmap_flush(PerlIO *f)
3718 {
3719     PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
3720     PerlIOBuf *b = &m->base;
3721     IV code = PerlIOBuf_flush(f);
3722     /*
3723      * Now we are "synced" at PerlIOBuf level
3724      */
3725     if (b->buf) {
3726         if (m->len) {
3727             /*
3728              * Unmap the buffer
3729              */
3730             if (PerlIOMmap_unmap(f) != 0)
3731                 code = -1;
3732         }
3733         else {
3734             /*
3735              * We seem to have a PerlIOBuf buffer which was not mapped
3736              * remember it in case we need one later
3737              */
3738             m->bbuf = b->buf;
3739         }
3740     }
3741     return code;
3742 }
3743
3744 IV
3745 PerlIOMmap_fill(PerlIO *f)
3746 {
3747     PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
3748     IV code = PerlIO_flush(f);
3749     if (code == 0 && !b->buf) {
3750         code = PerlIOMmap_map(f);
3751     }
3752     if (code == 0 && !(PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
3753         code = PerlIOBuf_fill(f);
3754     }
3755     return code;
3756 }
3757
3758 IV
3759 PerlIOMmap_close(PerlIO *f)
3760 {
3761     PerlIOMmap *m = PerlIOSelf(f, PerlIOMmap);
3762     PerlIOBuf *b = &m->base;
3763     IV code = PerlIO_flush(f);
3764     if (m->bbuf) {
3765         b->buf = m->bbuf;
3766         m->bbuf = NULL;
3767         b->ptr = b->end = b->buf;
3768     }
3769     if (PerlIOBuf_close(f) != 0)
3770         code = -1;
3771     return code;
3772 }
3773
3774 PerlIO *
3775 PerlIOMmap_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param)
3776 {
3777  return PerlIOBase_dup(aTHX_ f, o, param);
3778 }
3779
3780
3781 PerlIO_funcs PerlIO_mmap = {
3782     "mmap",
3783     sizeof(PerlIOMmap),
3784     PERLIO_K_BUFFERED,
3785     PerlIOBuf_pushed,
3786     PerlIOBase_noop_ok,
3787     PerlIOBuf_open,
3788     NULL,
3789     PerlIOBase_fileno,
3790     PerlIOMmap_dup,
3791     PerlIOBuf_read,
3792     PerlIOMmap_unread,
3793     PerlIOMmap_write,
3794     PerlIOBuf_seek,
3795     PerlIOBuf_tell,
3796     PerlIOBuf_close,
3797     PerlIOMmap_flush,
3798     PerlIOMmap_fill,
3799     PerlIOBase_eof,
3800     PerlIOBase_error,
3801     PerlIOBase_clearerr,
3802     PerlIOBase_setlinebuf,
3803     PerlIOMmap_get_base,
3804     PerlIOBuf_bufsiz,
3805     PerlIOBuf_get_ptr,
3806     PerlIOBuf_get_cnt,
3807     PerlIOBuf_set_ptrcnt,
3808 };
3809
3810 #endif                          /* HAS_MMAP */
3811
3812 void
3813 PerlIO_init(void)
3814 {
3815     dTHX;
3816 #ifndef WIN32
3817     call_atexit(PerlIO_cleanup_layers, NULL);
3818 #endif
3819     if (!_perlio) {
3820 #ifndef WIN32
3821         atexit(&PerlIO_cleanup);
3822 #endif
3823     }
3824 }
3825
3826 #undef PerlIO_stdin
3827 PerlIO *
3828 PerlIO_stdin(void)
3829 {
3830     if (!_perlio) {
3831         dTHX;
3832         PerlIO_stdstreams(aTHX);
3833     }
3834     return &_perlio[1];
3835 }
3836
3837 #undef PerlIO_stdout
3838 PerlIO *
3839 PerlIO_stdout(void)
3840 {
3841     if (!_perlio) {
3842         dTHX;
3843         PerlIO_stdstreams(aTHX);
3844     }
3845     return &_perlio[2];
3846 }
3847
3848 #undef PerlIO_stderr
3849 PerlIO *
3850 PerlIO_stderr(void)
3851 {
3852     if (!_perlio) {
3853         dTHX;
3854         PerlIO_stdstreams(aTHX);
3855     }
3856     return &_perlio[3];
3857 }
3858
3859 /*--------------------------------------------------------------------------------------*/
3860
3861 #undef PerlIO_getname
3862 char *
3863 PerlIO_getname(PerlIO *f, char *buf)
3864 {
3865     dTHX;
3866     char *name = NULL;
3867 #ifdef VMS
3868     FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
3869     if (stdio)
3870         name = fgetname(stdio, buf);
3871 #else
3872     Perl_croak(aTHX_ "Don't know how to get file name");
3873 #endif
3874     return name;
3875 }
3876
3877
3878 /*--------------------------------------------------------------------------------------*/
3879 /*
3880  * Functions which can be called on any kind of PerlIO implemented in
3881  * terms of above
3882  */
3883
3884 #undef PerlIO_getc
3885 int
3886 PerlIO_getc(PerlIO *f)
3887 {
3888     STDCHAR buf[1];
3889     SSize_t count = PerlIO_read(f, buf, 1);
3890     if (count == 1) {
3891         return (unsigned char) buf[0];
3892     }
3893     return EOF;
3894 }
3895
3896 #undef PerlIO_ungetc
3897 int
3898 PerlIO_ungetc(PerlIO *f, int ch)
3899 {
3900     if (ch != EOF) {
3901         STDCHAR buf = ch;
3902         if (PerlIO_unread(f, &buf, 1) == 1)
3903             return ch;
3904     }
3905     return EOF;
3906 }
3907
3908 #undef PerlIO_putc
3909 int
3910 PerlIO_putc(PerlIO *f, int ch)
3911 {
3912     STDCHAR buf = ch;
3913     return PerlIO_write(f, &buf, 1);
3914 }
3915
3916 #undef PerlIO_puts
3917 int
3918 PerlIO_puts(PerlIO *f, const char *s)
3919 {
3920     STRLEN len = strlen(s);
3921     return PerlIO_write(f, s, len);
3922 }
3923
3924 #undef PerlIO_rewind
3925 void
3926 PerlIO_rewind(PerlIO *f)
3927 {
3928     PerlIO_seek(f, (Off_t) 0, SEEK_SET);
3929     PerlIO_clearerr(f);
3930 }
3931
3932 #undef PerlIO_vprintf
3933 int
3934 PerlIO_vprintf(PerlIO *f, const char *fmt, va_list ap)
3935 {
3936     dTHX;
3937     SV *sv = newSVpvn("", 0);
3938     char *s;
3939     STRLEN len;
3940     SSize_t wrote;
3941 #ifdef NEED_VA_COPY
3942     va_list apc;
3943     Perl_va_copy(ap, apc);
3944     sv_vcatpvf(sv, fmt, &apc);
3945 #else
3946     sv_vcatpvf(sv, fmt, &ap);
3947 #endif
3948     s = SvPV(sv, len);
3949     wrote = PerlIO_write(f, s, len);
3950     SvREFCNT_dec(sv);
3951     return wrote;
3952 }
3953
3954 #undef PerlIO_printf
3955 int
3956 PerlIO_printf(PerlIO *f, const char *fmt, ...)
3957 {
3958     va_list ap;
3959     int result;
3960     va_start(ap, fmt);
3961     result = PerlIO_vprintf(f, fmt, ap);
3962     va_end(ap);
3963     return result;
3964 }
3965
3966 #undef PerlIO_stdoutf
3967 int
3968 PerlIO_stdoutf(const char *fmt, ...)
3969 {
3970     va_list ap;
3971     int result;
3972     va_start(ap, fmt);
3973     result = PerlIO_vprintf(PerlIO_stdout(), fmt, ap);
3974     va_end(ap);
3975     return result;
3976 }
3977
3978 #undef PerlIO_tmpfile
3979 PerlIO *
3980 PerlIO_tmpfile(void)
3981 {
3982     /*
3983      * I have no idea how portable mkstemp() is ...
3984      */
3985 #if defined(WIN32) || !defined(HAVE_MKSTEMP)
3986     dTHX;
3987     PerlIO *f = NULL;
3988     FILE *stdio = PerlSIO_tmpfile();
3989     if (stdio) {
3990         PerlIOStdio *s =
3991             PerlIOSelf(PerlIO_push
3992                        (aTHX_(f = PerlIO_allocate(aTHX)), &PerlIO_stdio,
3993                         "w+", Nullsv), PerlIOStdio);
3994         s->stdio = stdio;
3995     }
3996     return f;
3997 #else
3998     dTHX;
3999     SV *sv = newSVpv("/tmp/PerlIO_XXXXXX", 0);
4000     int fd = mkstemp(SvPVX(sv));
4001     PerlIO *f = NULL;
4002     if (fd >= 0) {
4003         f = PerlIO_fdopen(fd, "w+");
4004         if (f) {
4005             PerlIOBase(f)->flags |= PERLIO_F_TEMP;
4006         }
4007         PerlLIO_unlink(SvPVX(sv));
4008         SvREFCNT_dec(sv);
4009     }
4010     return f;
4011 #endif
4012 }
4013
4014 #undef HAS_FSETPOS
4015 #undef HAS_FGETPOS
4016
4017 #endif                          /* USE_SFIO */
4018 #endif                          /* PERLIO_IS_STDIO */
4019
4020 /*======================================================================================*/
4021 /*
4022  * Now some functions in terms of above which may be needed even if we are
4023  * not in true PerlIO mode
4024  */
4025
4026 #ifndef HAS_FSETPOS
4027 #undef PerlIO_setpos
4028 int
4029 PerlIO_setpos(PerlIO *f, SV *pos)
4030 {
4031     dTHX;
4032     if (SvOK(pos)) {
4033         STRLEN len;
4034         Off_t *posn = (Off_t *) SvPV(pos, len);
4035         if (f && len == sizeof(Off_t))
4036             return PerlIO_seek(f, *posn, SEEK_SET);
4037     }
4038     SETERRNO(EINVAL, SS$_IVCHAN);
4039     return -1;
4040 }
4041 #else
4042 #undef PerlIO_setpos
4043 int
4044 PerlIO_setpos(PerlIO *f, SV *pos)
4045 {
4046     dTHX;
4047     if (SvOK(pos)) {
4048         STRLEN len;
4049         Fpos_t *fpos = (Fpos_t *) SvPV(pos, len);
4050         if (f && len == sizeof(Fpos_t)) {
4051 #if defined(USE_64_BIT_STDIO) && defined(USE_FSETPOS64)
4052             return fsetpos64(f, fpos);
4053 #else
4054             return fsetpos(f, fpos);
4055 #endif
4056         }
4057     }
4058     SETERRNO(EINVAL, SS$_IVCHAN);
4059     return -1;
4060 }
4061 #endif
4062
4063 #ifndef HAS_FGETPOS
4064 #undef PerlIO_getpos
4065 int
4066 PerlIO_getpos(PerlIO *f, SV *pos)
4067 {
4068     dTHX;
4069     Off_t posn = PerlIO_tell(f);
4070     sv_setpvn(pos, (char *) &posn, sizeof(posn));
4071     return (posn == (Off_t) - 1) ? -1 : 0;
4072 }
4073 #else
4074 #undef PerlIO_getpos
4075 int
4076 PerlIO_getpos(PerlIO *f, SV *pos)
4077 {
4078     dTHX;
4079     Fpos_t fpos;
4080     int code;
4081 #if defined(USE_64_BIT_STDIO) && defined(USE_FSETPOS64)
4082     code = fgetpos64(f, &fpos);
4083 #else
4084     code = fgetpos(f, &fpos);
4085 #endif
4086     sv_setpvn(pos, (char *) &fpos, sizeof(fpos));
4087     return code;
4088 }
4089 #endif
4090
4091 #if (defined(PERLIO_IS_STDIO) || !defined(USE_SFIO)) && !defined(HAS_VPRINTF)
4092
4093 int
4094 vprintf(char *pat, char *args)
4095 {
4096     _doprnt(pat, args, stdout);
4097     return 0;                   /* wrong, but perl doesn't use the return
4098                                  * value */
4099 }
4100
4101 int
4102 vfprintf(FILE *fd, char *pat, char *args)
4103 {
4104     _doprnt(pat, args, fd);
4105     return 0;                   /* wrong, but perl doesn't use the return
4106                                  * value */
4107 }
4108
4109 #endif
4110
4111 #ifndef PerlIO_vsprintf
4112 int
4113 PerlIO_vsprintf(char *s, int n, const char *fmt, va_list ap)
4114 {
4115     int val = vsprintf(s, fmt, ap);
4116     if (n >= 0) {
4117         if (strlen(s) >= (STRLEN) n) {
4118             dTHX;
4119             (void) PerlIO_puts(Perl_error_log,
4120                                "panic: sprintf overflow - memory corrupted!\n");
4121             my_exit(1);
4122         }
4123     }
4124     return val;
4125 }
4126 #endif
4127
4128 #ifndef PerlIO_sprintf
4129 int
4130 PerlIO_sprintf(char *s, int n, const char *fmt, ...)
4131 {
4132     va_list ap;
4133     int result;
4134     va_start(ap, fmt);
4135     result = PerlIO_vsprintf(s, n, fmt, ap);
4136     va_end(ap);
4137     return result;
4138 }
4139 #endif