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