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