This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Test for a subtle pre-5.10 bug. Before 5.10 the overloading flag was
[perl5.git] / perlio.c
CommitLineData
14a5cf38 1/*
5cb43542
RGS
2 * perlio.c
3 * Copyright (c) 1996-2006, Nick Ing-Simmons
c1d0198f 4 * Copyright (c) 2006, 2007, Larry Wall and others
5cb43542
RGS
5 *
6 * You may distribute under the terms of either the GNU General Public License
7 * or the Artistic License, as specified in the README file.
760ac839
LW
8 */
9
14a5cf38 10/*
d31a8517
AT
11 * Hour after hour for nearly three weary days he had jogged up and down,
12 * over passes, and through long dales, and across many streams.
13 */
14
166f8a29
DM
15/* This file contains the functions needed to implement PerlIO, which
16 * is Perl's private replacement for the C stdio library. This is used
17 * by default unless you compile with -Uuseperlio or run with
18 * PERLIO=:stdio (but don't do this unless you know what you're doing)
19 */
20
d31a8517 21/*
71200d45 22 * If we have ActivePerl-like PERL_IMPLICIT_SYS then we need a dTHX to get
14a5cf38 23 * at the dispatch tables, even when we do not need it for other reasons.
71200d45 24 * Invent a dSYS macro to abstract this out
14a5cf38 25 */
7bcba3d4
NIS
26#ifdef PERL_IMPLICIT_SYS
27#define dSYS dTHX
28#else
29#define dSYS dNOOP
30#endif
31
760ac839 32#define VOIDUSED 1
12ae5dfc
JH
33#ifdef PERL_MICRO
34# include "uconfig.h"
35#else
b0f06652
VK
36# ifndef USE_CROSS_COMPILE
37# include "config.h"
38# else
39# include "xconfig.h"
40# endif
12ae5dfc 41#endif
760ac839 42
6f9d8c32 43#define PERLIO_NOT_STDIO 0
760ac839 44#if !defined(PERLIO_IS_STDIO) && !defined(USE_SFIO)
14a5cf38 45/*
71200d45 46 * #define PerlIO FILE
14a5cf38 47 */
760ac839
LW
48#endif
49/*
6f9d8c32 50 * This file provides those parts of PerlIO abstraction
88b61e10 51 * which are not #defined in perlio.h.
6f9d8c32 52 * Which these are depends on various Configure #ifdef's
760ac839
LW
53 */
54
55#include "EXTERN.h"
864dbfa3 56#define PERL_IN_PERLIO_C
760ac839
LW
57#include "perl.h"
58
32af7c23
CL
59#ifdef PERL_IMPLICIT_CONTEXT
60#undef dSYS
61#define dSYS dTHX
62#endif
63
0c4f7ff0
NIS
64#include "XSUB.h"
65
9cffb111
OS
66#ifdef __Lynx__
67/* Missing proto on LynxOS */
68int mkstemp(char*);
69#endif
70
1b7a0411 71/* Call the callback or PerlIOBase, and return failure. */
b32dd47e 72#define Perl_PerlIO_or_Base(f, callback, base, failure, args) \
1b7a0411 73 if (PerlIOValid(f)) { \
46c461b5 74 const PerlIO_funcs * const tab = PerlIOBase(f)->tab;\
1b7a0411
JH
75 if (tab && tab->callback) \
76 return (*tab->callback) args; \
77 else \
78 return PerlIOBase_ ## base args; \
79 } \
80 else \
81 SETERRNO(EBADF, SS_IVCHAN); \
82 return failure
83
84/* Call the callback or fail, and return failure. */
b32dd47e 85#define Perl_PerlIO_or_fail(f, callback, failure, args) \
1b7a0411 86 if (PerlIOValid(f)) { \
46c461b5 87 const PerlIO_funcs * const tab = PerlIOBase(f)->tab;\
1b7a0411
JH
88 if (tab && tab->callback) \
89 return (*tab->callback) args; \
90 SETERRNO(EINVAL, LIB_INVARG); \
91 } \
92 else \
93 SETERRNO(EBADF, SS_IVCHAN); \
94 return failure
95
96/* Call the callback or PerlIOBase, and be void. */
b32dd47e 97#define Perl_PerlIO_or_Base_void(f, callback, base, args) \
1b7a0411 98 if (PerlIOValid(f)) { \
46c461b5 99 const PerlIO_funcs * const tab = PerlIOBase(f)->tab;\
1b7a0411
JH
100 if (tab && tab->callback) \
101 (*tab->callback) args; \
102 else \
103 PerlIOBase_ ## base args; \
1b7a0411
JH
104 } \
105 else \
106 SETERRNO(EBADF, SS_IVCHAN)
107
108/* Call the callback or fail, and be void. */
b32dd47e 109#define Perl_PerlIO_or_fail_void(f, callback, args) \
1b7a0411 110 if (PerlIOValid(f)) { \
46c461b5 111 const PerlIO_funcs * const tab = PerlIOBase(f)->tab;\
1b7a0411
JH
112 if (tab && tab->callback) \
113 (*tab->callback) args; \
37725cdc
NIS
114 else \
115 SETERRNO(EINVAL, LIB_INVARG); \
1b7a0411
JH
116 } \
117 else \
118 SETERRNO(EBADF, SS_IVCHAN)
119
89a3a251
JH
120#if defined(__osf__) && _XOPEN_SOURCE < 500
121extern int fseeko(FILE *, off_t, int);
122extern off_t ftello(FILE *);
123#endif
124
71ab4674 125#ifndef USE_SFIO
a0c21aa1
JH
126
127EXTERN_C int perlsio_binmode(FILE *fp, int iotype, int mode);
128
71ab4674
SP
129int
130perlsio_binmode(FILE *fp, int iotype, int mode)
131{
132 /*
133 * This used to be contents of do_binmode in doio.c
134 */
135#ifdef DOSISH
136# if defined(atarist) || defined(__MINT__)
58c0efa5 137 PERL_UNUSED_ARG(iotype);
71ab4674
SP
138 if (!fflush(fp)) {
139 if (mode & O_BINARY)
140 ((FILE *) fp)->_flag |= _IOBIN;
141 else
142 ((FILE *) fp)->_flag &= ~_IOBIN;
143 return 1;
144 }
145 return 0;
146# else
147 dTHX;
58c0efa5 148 PERL_UNUSED_ARG(iotype);
71ab4674
SP
149#ifdef NETWARE
150 if (PerlLIO_setmode(fp, mode) != -1) {
151#else
152 if (PerlLIO_setmode(fileno(fp), mode) != -1) {
153#endif
154# if defined(WIN32) && defined(__BORLANDC__)
155 /*
156 * The translation mode of the stream is maintained independent
157of
158 * the translation mode of the fd in the Borland RTL (heavy
159 * digging through their runtime sources reveal). User has to
160set
161 * the mode explicitly for the stream (though they don't
162document
163 * this anywhere). GSAR 97-5-24
164 */
165 fseek(fp, 0L, 0);
166 if (mode & O_BINARY)
167 fp->flags |= _F_BIN;
168 else
169 fp->flags &= ~_F_BIN;
170# endif
171 return 1;
172 }
173 else
174 return 0;
175# endif
176#else
177# if defined(USEMYBINMODE)
178 dTHX;
58c0efa5
RGS
179# if defined(__CYGWIN__)
180 PERL_UNUSED_ARG(iotype);
181# endif
71ab4674
SP
182 if (my_binmode(fp, iotype, mode) != FALSE)
183 return 1;
184 else
185 return 0;
186# else
187 PERL_UNUSED_ARG(fp);
188 PERL_UNUSED_ARG(iotype);
189 PERL_UNUSED_ARG(mode);
190 return 1;
191# endif
192#endif
193}
194#endif /* sfio */
195
06c7082d 196#ifndef O_ACCMODE
22569500 197#define O_ACCMODE 3 /* Assume traditional implementation */
06c7082d
NIS
198#endif
199
200int
201PerlIO_intmode2str(int rawmode, char *mode, int *writing)
202{
de009b76 203 const int result = rawmode & O_ACCMODE;
06c7082d
NIS
204 int ix = 0;
205 int ptype;
206 switch (result) {
207 case O_RDONLY:
208 ptype = IoTYPE_RDONLY;
209 break;
210 case O_WRONLY:
211 ptype = IoTYPE_WRONLY;
212 break;
213 case O_RDWR:
214 default:
215 ptype = IoTYPE_RDWR;
216 break;
217 }
218 if (writing)
219 *writing = (result != O_RDONLY);
220
221 if (result == O_RDONLY) {
222 mode[ix++] = 'r';
223 }
224#ifdef O_APPEND
225 else if (rawmode & O_APPEND) {
226 mode[ix++] = 'a';
227 if (result != O_WRONLY)
228 mode[ix++] = '+';
229 }
230#endif
231 else {
232 if (result == O_WRONLY)
233 mode[ix++] = 'w';
234 else {
235 mode[ix++] = 'r';
236 mode[ix++] = '+';
237 }
238 }
239 if (rawmode & O_BINARY)
240 mode[ix++] = 'b';
241 mode[ix] = '\0';
242 return ptype;
243}
244
eb73beca
NIS
245#ifndef PERLIO_LAYERS
246int
247PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names)
248{
6874a2de
NIS
249 if (!names || !*names
250 || strEQ(names, ":crlf")
251 || strEQ(names, ":raw")
252 || strEQ(names, ":bytes")
253 ) {
14a5cf38
JH
254 return 0;
255 }
256 Perl_croak(aTHX_ "Cannot apply \"%s\" in non-PerlIO perl", names);
257 /*
71200d45 258 * NOTREACHED
14a5cf38
JH
259 */
260 return -1;
eb73beca
NIS
261}
262
13621cfb
NIS
263void
264PerlIO_destruct(pTHX)
265{
266}
267
f5b9d040
NIS
268int
269PerlIO_binmode(pTHX_ PerlIO *fp, int iotype, int mode, const char *names)
270{
92bff44d 271#ifdef USE_SFIO
8772537c
AL
272 PERL_UNUSED_ARG(iotype);
273 PERL_UNUSED_ARG(mode);
274 PERL_UNUSED_ARG(names);
14a5cf38 275 return 1;
92bff44d 276#else
14a5cf38 277 return perlsio_binmode(fp, iotype, mode);
92bff44d 278#endif
f5b9d040 279}
60382766 280
e0fa5af2 281PerlIO *
ecdeb87c 282PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags)
e0fa5af2 283{
a0fd4948 284#if defined(PERL_MICRO) || defined(__SYMBIAN32__)
0553478e
NIS
285 return NULL;
286#else
287#ifdef PERL_IMPLICIT_SYS
22569500 288 return PerlSIO_fdupopen(f);
0553478e 289#else
30753f56
NIS
290#ifdef WIN32
291 return win32_fdupopen(f);
292#else
e0fa5af2 293 if (f) {
504618e9 294 const int fd = PerlLIO_dup(PerlIO_fileno(f));
e0fa5af2 295 if (fd >= 0) {
06c7082d 296 char mode[8];
a5936e02 297#ifdef DJGPP
dcda55fc
AL
298 const int omode = djgpp_get_stream_mode(f);
299#else
300 const int omode = fcntl(fd, F_GETFL);
a5936e02 301#endif
06c7082d 302 PerlIO_intmode2str(omode,mode,NULL);
e0fa5af2 303 /* the r+ is a hack */
06c7082d 304 return PerlIO_fdopen(fd, mode);
e0fa5af2
NIS
305 }
306 return NULL;
307 }
308 else {
93189314 309 SETERRNO(EBADF, SS_IVCHAN);
e0fa5af2 310 }
7114a2d2 311#endif
e0fa5af2 312 return NULL;
0553478e 313#endif
30753f56 314#endif
e0fa5af2
NIS
315}
316
317
14a5cf38 318/*
71200d45 319 * De-mux PerlIO_openn() into fdopen, freopen and fopen type entries
14a5cf38 320 */
ee518936
NIS
321
322PerlIO *
14a5cf38
JH
323PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd,
324 int imode, int perm, PerlIO *old, int narg, SV **args)
325{
7cf31beb
NIS
326 if (narg) {
327 if (narg > 1) {
3b8752bb 328 Perl_croak(aTHX_ "More than one argument to open");
7cf31beb 329 }
14a5cf38
JH
330 if (*args == &PL_sv_undef)
331 return PerlIO_tmpfile();
332 else {
e62f0680 333 const char *name = SvPV_nolen_const(*args);
3b6c1aba 334 if (*mode == IoTYPE_NUMERIC) {
14a5cf38
JH
335 fd = PerlLIO_open3(name, imode, perm);
336 if (fd >= 0)
de009b76 337 return PerlIO_fdopen(fd, mode + 1);
14a5cf38
JH
338 }
339 else if (old) {
340 return PerlIO_reopen(name, mode, old);
341 }
342 else {
343 return PerlIO_open(name, mode);
344 }
345 }
346 }
347 else {
348 return PerlIO_fdopen(fd, (char *) mode);
349 }
350 return NULL;
ee518936
NIS
351}
352
0c4f7ff0
NIS
353XS(XS_PerlIO__Layer__find)
354{
14a5cf38
JH
355 dXSARGS;
356 if (items < 2)
357 Perl_croak(aTHX_ "Usage class->find(name[,load])");
358 else {
dcda55fc 359 const char * const name = SvPV_nolen_const(ST(1));
14a5cf38
JH
360 ST(0) = (strEQ(name, "crlf")
361 || strEQ(name, "raw")) ? &PL_sv_yes : &PL_sv_undef;
362 XSRETURN(1);
363 }
0c4f7ff0
NIS
364}
365
366
367void
368Perl_boot_core_PerlIO(pTHX)
369{
14a5cf38 370 newXS("PerlIO::Layer::find", XS_PerlIO__Layer__find, __FILE__);
0c4f7ff0
NIS
371}
372
ac27b0f5
NIS
373#endif
374
32e30700 375
6f9d8c32 376#ifdef PERLIO_IS_STDIO
760ac839
LW
377
378void
e8632036 379PerlIO_init(pTHX)
760ac839 380{
96a5add6 381 PERL_UNUSED_CONTEXT;
14a5cf38
JH
382 /*
383 * Does nothing (yet) except force this file to be included in perl
71200d45 384 * binary. That allows this file to force inclusion of other functions
14a5cf38 385 * that may be required by loadable extensions e.g. for
71200d45 386 * FileHandle::tmpfile
14a5cf38 387 */
760ac839
LW
388}
389
33dcbb9a 390#undef PerlIO_tmpfile
391PerlIO *
8ac85365 392PerlIO_tmpfile(void)
33dcbb9a 393{
14a5cf38 394 return tmpfile();
33dcbb9a 395}
396
22569500 397#else /* PERLIO_IS_STDIO */
760ac839
LW
398
399#ifdef USE_SFIO
400
401#undef HAS_FSETPOS
402#undef HAS_FGETPOS
403
14a5cf38
JH
404/*
405 * This section is just to make sure these functions get pulled in from
71200d45 406 * libsfio.a
14a5cf38 407 */
760ac839
LW
408
409#undef PerlIO_tmpfile
410PerlIO *
c78749f2 411PerlIO_tmpfile(void)
760ac839 412{
14a5cf38 413 return sftmp(0);
760ac839
LW
414}
415
416void
e8632036 417PerlIO_init(pTHX)
760ac839 418{
96a5add6 419 PERL_UNUSED_CONTEXT;
14a5cf38
JH
420 /*
421 * Force this file to be included in perl binary. Which allows this
422 * file to force inclusion of other functions that may be required by
71200d45 423 * loadable extensions e.g. for FileHandle::tmpfile
14a5cf38 424 */
760ac839 425
14a5cf38 426 /*
71200d45 427 * Hack sfio does its own 'autoflush' on stdout in common cases. Flush
14a5cf38 428 * results in a lot of lseek()s to regular files and lot of small
71200d45 429 * writes to pipes.
14a5cf38
JH
430 */
431 sfset(sfstdout, SF_SHARE, 0);
760ac839
LW
432}
433
b9d6bf13 434/* This is not the reverse of PerlIO_exportFILE(), PerlIO_releaseFILE() is. */
92bff44d 435PerlIO *
4b069b44 436PerlIO_importFILE(FILE *stdio, const char *mode)
92bff44d 437{
de009b76 438 const int fd = fileno(stdio);
4b069b44 439 if (!mode || !*mode) {
81428673 440 mode = "r+";
4b069b44
NIS
441 }
442 return PerlIO_fdopen(fd, mode);
92bff44d
NIS
443}
444
445FILE *
446PerlIO_findFILE(PerlIO *pio)
447{
de009b76
AL
448 const int fd = PerlIO_fileno(pio);
449 FILE * const f = fdopen(fd, "r+");
14a5cf38
JH
450 PerlIO_flush(pio);
451 if (!f && errno == EINVAL)
452 f = fdopen(fd, "w");
453 if (!f && errno == EINVAL)
454 f = fdopen(fd, "r");
455 return f;
92bff44d
NIS
456}
457
458
22569500 459#else /* USE_SFIO */
6f9d8c32 460/*======================================================================================*/
14a5cf38 461/*
71200d45 462 * Implement all the PerlIO interface ourselves.
9e353e3b 463 */
760ac839 464
76ced9ad
NIS
465#include "perliol.h"
466
14a5cf38
JH
467/*
468 * We _MUST_ have <unistd.h> if we are using lseek() and may have large
71200d45 469 * files
14a5cf38 470 */
02f66e2f
NIS
471#ifdef I_UNISTD
472#include <unistd.h>
473#endif
06da4f11
NIS
474#ifdef HAS_MMAP
475#include <sys/mman.h>
476#endif
477
6f9d8c32 478void
14a5cf38
JH
479PerlIO_debug(const char *fmt, ...)
480{
14a5cf38
JH
481 va_list ap;
482 dSYS;
483 va_start(ap, fmt);
582588d2
NC
484 if (!PL_perlio_debug_fd) {
485 if (!PL_tainting && PL_uid == PL_euid && PL_gid == PL_egid) {
486 const char * const s = PerlEnv_getenv("PERLIO_DEBUG");
487 if (s && *s)
488 PL_perlio_debug_fd
489 = PerlLIO_open3(s, O_WRONLY | O_CREAT | O_APPEND, 0666);
490 else
491 PL_perlio_debug_fd = -1;
492 } else {
493 /* tainting or set*id, so ignore the environment, and ensure we
494 skip these tests next time through. */
27da23d5 495 PL_perlio_debug_fd = -1;
582588d2 496 }
14a5cf38 497 }
27da23d5 498 if (PL_perlio_debug_fd > 0) {
14a5cf38 499 dTHX;
70ace5da 500#ifdef USE_ITHREADS
dcda55fc 501 const char * const s = CopFILE(PL_curcop);
70ace5da
NIS
502 /* Use fixed buffer as sv_catpvf etc. needs SVs */
503 char buffer[1024];
1208b3dd
JH
504 const STRLEN len1 = my_snprintf(buffer, sizeof(buffer), "%.40s:%" IVdf " ", s ? s : "(none)", (IV) CopLINE(PL_curcop));
505 const STRLEN len2 = my_vsnprintf(buffer + len1, sizeof(buffer) - len1, fmt, ap);
506 PerlLIO_write(PL_perlio_debug_fd, buffer, len1 + len2);
70ace5da 507#else
dcda55fc
AL
508 const char *s = CopFILE(PL_curcop);
509 STRLEN len;
396482e1 510 SV * const sv = newSVpvs("");
dcda55fc 511 Perl_sv_catpvf(aTHX_ sv, "%s:%" IVdf " ", s ? s : "(none)",
14a5cf38
JH
512 (IV) CopLINE(PL_curcop));
513 Perl_sv_vcatpvf(aTHX_ sv, fmt, &ap);
514
b83604b4 515 s = SvPV_const(sv, len);
27da23d5 516 PerlLIO_write(PL_perlio_debug_fd, s, len);
14a5cf38 517 SvREFCNT_dec(sv);
70ace5da 518#endif
14a5cf38
JH
519 }
520 va_end(ap);
6f9d8c32
NIS
521}
522
9e353e3b
NIS
523/*--------------------------------------------------------------------------------------*/
524
14a5cf38 525/*
71200d45 526 * Inner level routines
14a5cf38 527 */
9e353e3b 528
14a5cf38 529/*
71200d45 530 * Table of pointers to the PerlIO structs (malloc'ed)
14a5cf38 531 */
05d1247b 532#define PERLIO_TABLE_SIZE 64
6f9d8c32 533
760ac839 534PerlIO *
5f1a76d0 535PerlIO_allocate(pTHX)
6f9d8c32 536{
97aff369 537 dVAR;
14a5cf38 538 /*
71200d45 539 * Find a free slot in the table, allocating new table as necessary
14a5cf38
JH
540 */
541 PerlIO **last;
542 PerlIO *f;
a1ea730d 543 last = &PL_perlio;
14a5cf38
JH
544 while ((f = *last)) {
545 int i;
546 last = (PerlIO **) (f);
547 for (i = 1; i < PERLIO_TABLE_SIZE; i++) {
548 if (!*++f) {
549 return f;
550 }
551 }
552 }
a02a5408 553 Newxz(f,PERLIO_TABLE_SIZE,PerlIO);
14a5cf38
JH
554 if (!f) {
555 return NULL;
556 }
557 *last = f;
558 return f + 1;
05d1247b
NIS
559}
560
a1ea730d
NIS
561#undef PerlIO_fdupopen
562PerlIO *
ecdeb87c 563PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags)
a1ea730d 564{
04892f78 565 if (PerlIOValid(f)) {
de009b76 566 const PerlIO_funcs * const tab = PerlIOBase(f)->tab;
fe5a182c 567 PerlIO_debug("fdupopen f=%p param=%p\n",(void*)f,(void*)param);
210e727c
JH
568 if (tab && tab->Dup)
569 return (*tab->Dup)(aTHX_ PerlIO_allocate(aTHX), f, param, flags);
37725cdc
NIS
570 else {
571 return PerlIOBase_dup(aTHX_ PerlIO_allocate(aTHX), f, param, flags);
572 }
a1ea730d 573 }
210e727c
JH
574 else
575 SETERRNO(EBADF, SS_IVCHAN);
576
577 return NULL;
a1ea730d
NIS
578}
579
580void
5f1a76d0 581PerlIO_cleantable(pTHX_ PerlIO **tablep)
05d1247b 582{
dcda55fc 583 PerlIO * const table = *tablep;
14a5cf38
JH
584 if (table) {
585 int i;
586 PerlIO_cleantable(aTHX_(PerlIO **) & (table[0]));
587 for (i = PERLIO_TABLE_SIZE - 1; i > 0; i--) {
dcda55fc 588 PerlIO * const f = table + i;
14a5cf38
JH
589 if (*f) {
590 PerlIO_close(f);
591 }
592 }
3a1ee7e8 593 Safefree(table);
14a5cf38 594 *tablep = NULL;
05d1247b 595 }
05d1247b
NIS
596}
597
fcf2db38
NIS
598
599PerlIO_list_t *
3a1ee7e8 600PerlIO_list_alloc(pTHX)
fcf2db38 601{
14a5cf38 602 PerlIO_list_t *list;
96a5add6 603 PERL_UNUSED_CONTEXT;
a02a5408 604 Newxz(list, 1, PerlIO_list_t);
14a5cf38
JH
605 list->refcnt = 1;
606 return list;
fcf2db38
NIS
607}
608
609void
3a1ee7e8 610PerlIO_list_free(pTHX_ PerlIO_list_t *list)
fcf2db38 611{
14a5cf38
JH
612 if (list) {
613 if (--list->refcnt == 0) {
614 if (list->array) {
14a5cf38
JH
615 IV i;
616 for (i = 0; i < list->cur; i++) {
617 if (list->array[i].arg)
618 SvREFCNT_dec(list->array[i].arg);
619 }
620 Safefree(list->array);
621 }
622 Safefree(list);
623 }
624 }
fcf2db38
NIS
625}
626
627void
3a1ee7e8 628PerlIO_list_push(pTHX_ PerlIO_list_t *list, PerlIO_funcs *funcs, SV *arg)
14a5cf38 629{
97aff369 630 dVAR;
334e202e 631 PerlIO_pair_t *p;
b37c2d43
AL
632 PERL_UNUSED_CONTEXT;
633
14a5cf38
JH
634 if (list->cur >= list->len) {
635 list->len += 8;
636 if (list->array)
637 Renew(list->array, list->len, PerlIO_pair_t);
638 else
a02a5408 639 Newx(list->array, list->len, PerlIO_pair_t);
14a5cf38
JH
640 }
641 p = &(list->array[list->cur++]);
642 p->funcs = funcs;
643 if ((p->arg = arg)) {
f84c484e 644 SvREFCNT_inc_simple_void_NN(arg);
14a5cf38 645 }
fcf2db38
NIS
646}
647
3a1ee7e8
NIS
648PerlIO_list_t *
649PerlIO_clone_list(pTHX_ PerlIO_list_t *proto, CLONE_PARAMS *param)
650{
b37c2d43 651 PerlIO_list_t *list = NULL;
694c95cf
JH
652 if (proto) {
653 int i;
654 list = PerlIO_list_alloc(aTHX);
655 for (i=0; i < proto->cur; i++) {
a951d81d
BL
656 SV *arg = proto->array[i].arg;
657#ifdef sv_dup
658 if (arg && param)
659 arg = sv_dup(arg, param);
660#else
661 PERL_UNUSED_ARG(param);
662#endif
694c95cf
JH
663 PerlIO_list_push(aTHX_ list, proto->array[i].funcs, arg);
664 }
3a1ee7e8
NIS
665 }
666 return list;
667}
4a4a6116 668
05d1247b 669void
3a1ee7e8 670PerlIO_clone(pTHX_ PerlInterpreter *proto, CLONE_PARAMS *param)
9a6404c5 671{
3aaf42a7 672#ifdef USE_ITHREADS
3a1ee7e8
NIS
673 PerlIO **table = &proto->Iperlio;
674 PerlIO *f;
675 PL_perlio = NULL;
676 PL_known_layers = PerlIO_clone_list(aTHX_ proto->Iknown_layers, param);
677 PL_def_layerlist = PerlIO_clone_list(aTHX_ proto->Idef_layerlist, param);
678 PerlIO_allocate(aTHX); /* root slot is never used */
a25429c6 679 PerlIO_debug("Clone %p from %p\n",(void*)aTHX,(void*)proto);
3a1ee7e8
NIS
680 while ((f = *table)) {
681 int i;
682 table = (PerlIO **) (f++);
683 for (i = 1; i < PERLIO_TABLE_SIZE; i++) {
684 if (*f) {
93a8090d 685 (void) fp_dup(f, 0, param);
3a1ee7e8
NIS
686 }
687 f++;
688 }
689 }
1b6737cc 690#else
a25429c6 691 PERL_UNUSED_CONTEXT;
1b6737cc
AL
692 PERL_UNUSED_ARG(proto);
693 PERL_UNUSED_ARG(param);
3aaf42a7 694#endif
9a6404c5
DM
695}
696
697void
13621cfb
NIS
698PerlIO_destruct(pTHX)
699{
97aff369 700 dVAR;
a1ea730d 701 PerlIO **table = &PL_perlio;
14a5cf38 702 PerlIO *f;
694c95cf 703#ifdef USE_ITHREADS
a25429c6 704 PerlIO_debug("Destruct %p\n",(void*)aTHX);
694c95cf 705#endif
14a5cf38
JH
706 while ((f = *table)) {
707 int i;
708 table = (PerlIO **) (f++);
709 for (i = 1; i < PERLIO_TABLE_SIZE; i++) {
710 PerlIO *x = f;
dcda55fc 711 const PerlIOl *l;
14a5cf38
JH
712 while ((l = *x)) {
713 if (l->tab->kind & PERLIO_K_DESTRUCT) {
714 PerlIO_debug("Destruct popping %s\n", l->tab->name);
715 PerlIO_flush(x);
716 PerlIO_pop(aTHX_ x);
717 }
718 else {
719 x = PerlIONext(x);
720 }
721 }
722 f++;
723 }
724 }
13621cfb
NIS
725}
726
727void
a999f61b 728PerlIO_pop(pTHX_ PerlIO *f)
760ac839 729{
dcda55fc 730 const PerlIOl *l = *f;
14a5cf38 731 if (l) {
fe5a182c 732 PerlIO_debug("PerlIO_pop f=%p %s\n", (void*)f, l->tab->name);
14a5cf38
JH
733 if (l->tab->Popped) {
734 /*
735 * If popped returns non-zero do not free its layer structure
736 * it has either done so itself, or it is shared and still in
71200d45 737 * use
14a5cf38 738 */
f62ce20a 739 if ((*l->tab->Popped) (aTHX_ f) != 0)
14a5cf38
JH
740 return;
741 }
b47cad08 742 *f = l->next;
3a1ee7e8 743 Safefree(l);
a8c08ecd 744 }
6f9d8c32
NIS
745}
746
39f7a870
JH
747/* Return as an array the stack of layers on a filehandle. Note that
748 * the stack is returned top-first in the array, and there are three
749 * times as many array elements as there are layers in the stack: the
750 * first element of a layer triplet is the name, the second one is the
751 * arguments, and the third one is the flags. */
752
753AV *
754PerlIO_get_layers(pTHX_ PerlIO *f)
755{
97aff369 756 dVAR;
dcda55fc 757 AV * const av = newAV();
39f7a870 758
dcda55fc
AL
759 if (PerlIOValid(f)) {
760 PerlIOl *l = PerlIOBase(f);
761
762 while (l) {
763 SV * const name = l->tab && l->tab->name ?
764 newSVpv(l->tab->name, 0) : &PL_sv_undef;
765 SV * const arg = l->tab && l->tab->Getarg ?
766 (*l->tab->Getarg)(aTHX_ &l, 0, 0) : &PL_sv_undef;
767 av_push(av, name);
768 av_push(av, arg);
769 av_push(av, newSViv((IV)l->flags));
770 l = l->next;
771 }
772 }
39f7a870 773
dcda55fc 774 return av;
39f7a870
JH
775}
776
9e353e3b 777/*--------------------------------------------------------------------------------------*/
14a5cf38 778/*
71200d45 779 * XS Interface for perl code
14a5cf38 780 */
9e353e3b 781
fcf2db38 782PerlIO_funcs *
2edd7e44 783PerlIO_find_layer(pTHX_ const char *name, STRLEN len, int load)
f3862f8b 784{
27da23d5 785 dVAR;
14a5cf38
JH
786 IV i;
787 if ((SSize_t) len <= 0)
788 len = strlen(name);
3a1ee7e8 789 for (i = 0; i < PL_known_layers->cur; i++) {
46c461b5 790 PerlIO_funcs * const f = PL_known_layers->array[i].funcs;
a9f76400 791 if (memEQ(f->name, name, len) && f->name[len] == 0) {
fe5a182c 792 PerlIO_debug("%.*s => %p\n", (int) len, name, (void*)f);
14a5cf38
JH
793 return f;
794 }
795 }
3a1ee7e8
NIS
796 if (load && PL_subname && PL_def_layerlist
797 && PL_def_layerlist->cur >= 2) {
d7a09b41
SR
798 if (PL_in_load_module) {
799 Perl_croak(aTHX_ "Recursive call to Perl_load_module in PerlIO_find_layer");
800 return NULL;
801 } else {
396482e1 802 SV * const pkgsv = newSVpvs("PerlIO");
46c461b5 803 SV * const layer = newSVpvn(name, len);
780a5241 804 CV * const cv = Perl_get_cvn_flags(aTHX_ STR_WITH_LEN("PerlIO::Layer::NoWarnings"), 0);
46c461b5 805 ENTER;
d7a09b41 806 SAVEINT(PL_in_load_module);
c9bca74a 807 if (cv) {
9cfa90c0 808 SAVEGENERICSV(PL_warnhook);
b37c2d43 809 PL_warnhook = (SV *) (SvREFCNT_inc_simple_NN(cv));
c9bca74a 810 }
d7a09b41
SR
811 PL_in_load_module++;
812 /*
813 * The two SVs are magically freed by load_module
814 */
a0714e2c 815 Perl_load_module(aTHX_ 0, pkgsv, NULL, layer, NULL);
d7a09b41
SR
816 PL_in_load_module--;
817 LEAVE;
818 return PerlIO_find_layer(aTHX_ name, len, 0);
819 }
14a5cf38
JH
820 }
821 PerlIO_debug("Cannot find %.*s\n", (int) len, name);
822 return NULL;
f3862f8b
NIS
823}
824
2a1bc955 825#ifdef USE_ATTRIBUTES_FOR_PERLIO
b13b2135
NIS
826
827static int
828perlio_mg_set(pTHX_ SV *sv, MAGIC *mg)
829{
14a5cf38 830 if (SvROK(sv)) {
dcda55fc
AL
831 IO * const io = GvIOn((GV *) SvRV(sv));
832 PerlIO * const ifp = IoIFP(io);
833 PerlIO * const ofp = IoOFP(io);
be2597df
MHM
834 Perl_warn(aTHX_ "set %" SVf " %p %p %p",
835 SVfARG(sv), (void*)io, (void*)ifp, (void*)ofp);
14a5cf38
JH
836 }
837 return 0;
b13b2135
NIS
838}
839
840static int
841perlio_mg_get(pTHX_ SV *sv, MAGIC *mg)
842{
14a5cf38 843 if (SvROK(sv)) {
dcda55fc
AL
844 IO * const io = GvIOn((GV *) SvRV(sv));
845 PerlIO * const ifp = IoIFP(io);
846 PerlIO * const ofp = IoOFP(io);
be2597df
MHM
847 Perl_warn(aTHX_ "get %" SVf " %p %p %p",
848 SVfARG(sv), (void*)io, (void*)ifp, (void*)ofp);
14a5cf38
JH
849 }
850 return 0;
b13b2135
NIS
851}
852
853static int
854perlio_mg_clear(pTHX_ SV *sv, MAGIC *mg)
855{
be2597df 856 Perl_warn(aTHX_ "clear %" SVf, SVfARG(sv));
14a5cf38 857 return 0;
b13b2135
NIS
858}
859
860static int
861perlio_mg_free(pTHX_ SV *sv, MAGIC *mg)
862{
be2597df 863 Perl_warn(aTHX_ "free %" SVf, SVfARG(sv));
14a5cf38 864 return 0;
b13b2135
NIS
865}
866
867MGVTBL perlio_vtab = {
14a5cf38
JH
868 perlio_mg_get,
869 perlio_mg_set,
22569500 870 NULL, /* len */
14a5cf38
JH
871 perlio_mg_clear,
872 perlio_mg_free
b13b2135
NIS
873};
874
875XS(XS_io_MODIFY_SCALAR_ATTRIBUTES)
876{
14a5cf38 877 dXSARGS;
dcda55fc
AL
878 SV * const sv = SvRV(ST(1));
879 AV * const av = newAV();
14a5cf38
JH
880 MAGIC *mg;
881 int count = 0;
882 int i;
883 sv_magic(sv, (SV *) av, PERL_MAGIC_ext, NULL, 0);
884 SvRMAGICAL_off(sv);
885 mg = mg_find(sv, PERL_MAGIC_ext);
886 mg->mg_virtual = &perlio_vtab;
887 mg_magical(sv);
be2597df 888 Perl_warn(aTHX_ "attrib %" SVf, SVfARG(sv));
14a5cf38
JH
889 for (i = 2; i < items; i++) {
890 STRLEN len;
dcda55fc
AL
891 const char * const name = SvPV_const(ST(i), len);
892 SV * const layer = PerlIO_find_layer(aTHX_ name, len, 1);
14a5cf38 893 if (layer) {
b37c2d43 894 av_push(av, SvREFCNT_inc_simple_NN(layer));
14a5cf38
JH
895 }
896 else {
897 ST(count) = ST(i);
898 count++;
899 }
900 }
901 SvREFCNT_dec(av);
902 XSRETURN(count);
903}
904
22569500 905#endif /* USE_ATTIBUTES_FOR_PERLIO */
2a1bc955 906
e3f3bf95
NIS
907SV *
908PerlIO_tab_sv(pTHX_ PerlIO_funcs *tab)
f3862f8b 909{
da51bb9b 910 HV * const stash = gv_stashpvs("PerlIO::Layer", GV_ADD);
46c461b5 911 SV * const sv = sv_bless(newRV_noinc(newSViv(PTR2IV(tab))), stash);
14a5cf38 912 return sv;
e3f3bf95
NIS
913}
914
5ca1d77f 915XS(XS_PerlIO__Layer__NoWarnings)
c9bca74a 916{
37725cdc 917 /* This is used as a %SIG{__WARN__} handler to supress warnings
c9bca74a
NIS
918 during loading of layers.
919 */
97aff369 920 dVAR;
c9bca74a 921 dXSARGS;
58c0efa5 922 PERL_UNUSED_ARG(cv);
c9bca74a 923 if (items)
e62f0680 924 PerlIO_debug("warning:%s\n",SvPV_nolen_const(ST(0)));
c9bca74a
NIS
925 XSRETURN(0);
926}
927
5ca1d77f 928XS(XS_PerlIO__Layer__find)
0c4f7ff0 929{
97aff369 930 dVAR;
14a5cf38 931 dXSARGS;
58c0efa5 932 PERL_UNUSED_ARG(cv);
14a5cf38
JH
933 if (items < 2)
934 Perl_croak(aTHX_ "Usage class->find(name[,load])");
935 else {
de009b76 936 STRLEN len;
46c461b5 937 const char * const name = SvPV_const(ST(1), len);
de009b76 938 const bool load = (items > 2) ? SvTRUE(ST(2)) : 0;
46c461b5 939 PerlIO_funcs * const layer = PerlIO_find_layer(aTHX_ name, len, load);
14a5cf38
JH
940 ST(0) =
941 (layer) ? sv_2mortal(PerlIO_tab_sv(aTHX_ layer)) :
942 &PL_sv_undef;
943 XSRETURN(1);
944 }
0c4f7ff0
NIS
945}
946
e3f3bf95
NIS
947void
948PerlIO_define_layer(pTHX_ PerlIO_funcs *tab)
949{
97aff369 950 dVAR;
3a1ee7e8
NIS
951 if (!PL_known_layers)
952 PL_known_layers = PerlIO_list_alloc(aTHX);
a0714e2c 953 PerlIO_list_push(aTHX_ PL_known_layers, tab, NULL);
fe5a182c 954 PerlIO_debug("define %s %p\n", tab->name, (void*)tab);
f3862f8b
NIS
955}
956
1141d9f8 957int
fcf2db38 958PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names)
1141d9f8 959{
97aff369 960 dVAR;
14a5cf38
JH
961 if (names) {
962 const char *s = names;
963 while (*s) {
964 while (isSPACE(*s) || *s == ':')
965 s++;
966 if (*s) {
967 STRLEN llen = 0;
968 const char *e = s;
bd61b366 969 const char *as = NULL;
14a5cf38
JH
970 STRLEN alen = 0;
971 if (!isIDFIRST(*s)) {
972 /*
973 * Message is consistent with how attribute lists are
974 * passed. Even though this means "foo : : bar" is
71200d45 975 * seen as an invalid separator character.
14a5cf38 976 */
de009b76 977 const char q = ((*s == '\'') ? '"' : '\'');
99ef548b 978 if (ckWARN(WARN_LAYER))
22569500 979 Perl_warner(aTHX_ packWARN(WARN_LAYER),
b4581f09 980 "Invalid separator character %c%c%c in PerlIO layer specification %s",
1e616cf5 981 q, *s, q, s);
93189314 982 SETERRNO(EINVAL, LIB_INVARG);
14a5cf38
JH
983 return -1;
984 }
985 do {
986 e++;
987 } while (isALNUM(*e));
988 llen = e - s;
989 if (*e == '(') {
990 int nesting = 1;
991 as = ++e;
992 while (nesting) {
993 switch (*e++) {
994 case ')':
995 if (--nesting == 0)
996 alen = (e - 1) - as;
997 break;
998 case '(':
999 ++nesting;
1000 break;
1001 case '\\':
1002 /*
1003 * It's a nul terminated string, not allowed
1004 * to \ the terminating null. Anything other
71200d45 1005 * character is passed over.
14a5cf38
JH
1006 */
1007 if (*e++) {
1008 break;
1009 }
1010 /*
71200d45 1011 * Drop through
14a5cf38
JH
1012 */
1013 case '\0':
1014 e--;
22569500
NIS
1015 if (ckWARN(WARN_LAYER))
1016 Perl_warner(aTHX_ packWARN(WARN_LAYER),
b4581f09 1017 "Argument list not closed for PerlIO layer \"%.*s\"",
14a5cf38
JH
1018 (int) (e - s), s);
1019 return -1;
1020 default:
1021 /*
71200d45 1022 * boring.
14a5cf38
JH
1023 */
1024 break;
1025 }
1026 }
1027 }
1028 if (e > s) {
46c461b5 1029 PerlIO_funcs * const layer =
14a5cf38
JH
1030 PerlIO_find_layer(aTHX_ s, llen, 1);
1031 if (layer) {
a951d81d
BL
1032 SV *arg = NULL;
1033 if (as)
1034 arg = newSVpvn(as, alen);
3a1ee7e8 1035 PerlIO_list_push(aTHX_ av, layer,
a951d81d
BL
1036 (arg) ? arg : &PL_sv_undef);
1037 if (arg)
1038 SvREFCNT_dec(arg);
14a5cf38
JH
1039 }
1040 else {
041457d9 1041 if (ckWARN(WARN_LAYER))
b4581f09 1042 Perl_warner(aTHX_ packWARN(WARN_LAYER), "Unknown PerlIO layer \"%.*s\"",
14a5cf38
JH
1043 (int) llen, s);
1044 return -1;
1045 }
1046 }
1047 s = e;
1048 }
1049 }
1050 }
1051 return 0;
1141d9f8
NIS
1052}
1053
dfebf958 1054void
fcf2db38 1055PerlIO_default_buffer(pTHX_ PerlIO_list_t *av)
dfebf958 1056{
97aff369 1057 dVAR;
27da23d5 1058 PERLIO_FUNCS_DECL(*tab) = &PerlIO_perlio;
35990314 1059#ifdef PERLIO_USING_CRLF
6ce75a77 1060 tab = &PerlIO_crlf;
846be114 1061#else
6ce75a77 1062 if (PerlIO_stdio.Set_ptrcnt)
22569500 1063 tab = &PerlIO_stdio;
846be114 1064#endif
14a5cf38 1065 PerlIO_debug("Pushing %s\n", tab->name);
3a1ee7e8 1066 PerlIO_list_push(aTHX_ av, PerlIO_find_layer(aTHX_ tab->name, 0, 0),
14a5cf38 1067 &PL_sv_undef);
dfebf958
NIS
1068}
1069
e3f3bf95 1070SV *
14a5cf38 1071PerlIO_arg_fetch(PerlIO_list_t *av, IV n)
e3f3bf95 1072{
14a5cf38 1073 return av->array[n].arg;
e3f3bf95
NIS
1074}
1075
f3862f8b 1076PerlIO_funcs *
14a5cf38 1077PerlIO_layer_fetch(pTHX_ PerlIO_list_t *av, IV n, PerlIO_funcs *def)
f3862f8b 1078{
14a5cf38
JH
1079 if (n >= 0 && n < av->cur) {
1080 PerlIO_debug("Layer %" IVdf " is %s\n", n,
1081 av->array[n].funcs->name);
1082 return av->array[n].funcs;
1083 }
1084 if (!def)
1085 Perl_croak(aTHX_ "panic: PerlIO layer array corrupt");
1086 return def;
e3f3bf95
NIS
1087}
1088
4ec2216f
NIS
1089IV
1090PerlIOPop_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
1091{
8772537c
AL
1092 PERL_UNUSED_ARG(mode);
1093 PERL_UNUSED_ARG(arg);
1094 PERL_UNUSED_ARG(tab);
4ec2216f
NIS
1095 if (PerlIOValid(f)) {
1096 PerlIO_flush(f);
1097 PerlIO_pop(aTHX_ f);
1098 return 0;
1099 }
1100 return -1;
1101}
1102
27da23d5 1103PERLIO_FUNCS_DECL(PerlIO_remove) = {
4ec2216f
NIS
1104 sizeof(PerlIO_funcs),
1105 "pop",
1106 0,
1107 PERLIO_K_DUMMY | PERLIO_K_UTF8,
1108 PerlIOPop_pushed,
1109 NULL,
1110 NULL,
1111 NULL,
1112 NULL,
1113 NULL,
1114 NULL,
1115 NULL,
1116 NULL,
1117 NULL,
1118 NULL,
de009b76
AL
1119 NULL,
1120 NULL,
4ec2216f
NIS
1121 NULL, /* flush */
1122 NULL, /* fill */
1123 NULL,
1124 NULL,
1125 NULL,
1126 NULL,
1127 NULL, /* get_base */
1128 NULL, /* get_bufsiz */
1129 NULL, /* get_ptr */
1130 NULL, /* get_cnt */
1131 NULL, /* set_ptrcnt */
1132};
1133
fcf2db38 1134PerlIO_list_t *
e3f3bf95
NIS
1135PerlIO_default_layers(pTHX)
1136{
97aff369 1137 dVAR;
3a1ee7e8 1138 if (!PL_def_layerlist) {
bd61b366 1139 const char * const s = (PL_tainting) ? NULL : PerlEnv_getenv("PERLIO");
27da23d5 1140 PERLIO_FUNCS_DECL(*osLayer) = &PerlIO_unix;
3a1ee7e8 1141 PL_def_layerlist = PerlIO_list_alloc(aTHX);
27da23d5 1142 PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_unix));
979e2c82 1143#if defined(WIN32)
27da23d5 1144 PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_win32));
2f8118af 1145#if 0
14a5cf38 1146 osLayer = &PerlIO_win32;
0c4128ad 1147#endif
2f8118af 1148#endif
27da23d5
JH
1149 PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_raw));
1150 PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_perlio));
1151 PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_stdio));
1152 PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_crlf));
06da4f11 1153#ifdef HAS_MMAP
27da23d5 1154 PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_mmap));
06da4f11 1155#endif
27da23d5
JH
1156 PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_utf8));
1157 PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_remove));
1158 PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_byte));
3a1ee7e8 1159 PerlIO_list_push(aTHX_ PL_def_layerlist,
14a5cf38
JH
1160 PerlIO_find_layer(aTHX_ osLayer->name, 0, 0),
1161 &PL_sv_undef);
1162 if (s) {
3a1ee7e8 1163 PerlIO_parse_layers(aTHX_ PL_def_layerlist, s);
14a5cf38
JH
1164 }
1165 else {
3a1ee7e8 1166 PerlIO_default_buffer(aTHX_ PL_def_layerlist);
14a5cf38 1167 }
1141d9f8 1168 }
3a1ee7e8
NIS
1169 if (PL_def_layerlist->cur < 2) {
1170 PerlIO_default_buffer(aTHX_ PL_def_layerlist);
f3862f8b 1171 }
3a1ee7e8 1172 return PL_def_layerlist;
e3f3bf95
NIS
1173}
1174
0c4f7ff0
NIS
1175void
1176Perl_boot_core_PerlIO(pTHX)
1177{
1178#ifdef USE_ATTRIBUTES_FOR_PERLIO
14a5cf38
JH
1179 newXS("io::MODIFY_SCALAR_ATTRIBUTES", XS_io_MODIFY_SCALAR_ATTRIBUTES,
1180 __FILE__);
0c4f7ff0 1181#endif
14a5cf38 1182 newXS("PerlIO::Layer::find", XS_PerlIO__Layer__find, __FILE__);
c9bca74a 1183 newXS("PerlIO::Layer::NoWarnings", XS_PerlIO__Layer__NoWarnings, __FILE__);
0c4f7ff0 1184}
e3f3bf95
NIS
1185
1186PerlIO_funcs *
1187PerlIO_default_layer(pTHX_ I32 n)
1188{
97aff369 1189 dVAR;
46c461b5 1190 PerlIO_list_t * const av = PerlIO_default_layers(aTHX);
14a5cf38
JH
1191 if (n < 0)
1192 n += av->cur;
27da23d5 1193 return PerlIO_layer_fetch(aTHX_ av, n, PERLIO_FUNCS_CAST(&PerlIO_stdio));
f3862f8b
NIS
1194}
1195
a999f61b
NIS
1196#define PerlIO_default_top() PerlIO_default_layer(aTHX_ -1)
1197#define PerlIO_default_btm() PerlIO_default_layer(aTHX_ 0)
60382766
NIS
1198
1199void
1141d9f8 1200PerlIO_stdstreams(pTHX)
60382766 1201{
97aff369 1202 dVAR;
a1ea730d 1203 if (!PL_perlio) {
14a5cf38
JH
1204 PerlIO_allocate(aTHX);
1205 PerlIO_fdopen(0, "Ir" PERLIO_STDTEXT);
1206 PerlIO_fdopen(1, "Iw" PERLIO_STDTEXT);
1207 PerlIO_fdopen(2, "Iw" PERLIO_STDTEXT);
1208 }
60382766
NIS
1209}
1210
1211PerlIO *
27da23d5 1212PerlIO_push(pTHX_ PerlIO *f, PERLIO_FUNCS_DECL(*tab), const char *mode, SV *arg)
14a5cf38 1213{
2dc2558e
NIS
1214 if (tab->fsize != sizeof(PerlIO_funcs)) {
1215 mismatch:
1216 Perl_croak(aTHX_ "Layer does not match this perl");
1217 }
1218 if (tab->size) {
b464bac0 1219 PerlIOl *l;
2dc2558e
NIS
1220 if (tab->size < sizeof(PerlIOl)) {
1221 goto mismatch;
1222 }
1223 /* Real layer with a data area */
002e75cf
JH
1224 if (f) {
1225 char *temp;
1226 Newxz(temp, tab->size, char);
1227 l = (PerlIOl*)temp;
1228 if (l) {
1229 l->next = *f;
1230 l->tab = (PerlIO_funcs*) tab;
1231 *f = l;
1232 PerlIO_debug("PerlIO_push f=%p %s %s %p\n",
1233 (void*)f, tab->name,
1234 (mode) ? mode : "(Null)", (void*)arg);
1235 if (*l->tab->Pushed &&
1236 (*l->tab->Pushed)
1237 (aTHX_ f, mode, arg, (PerlIO_funcs*) tab) != 0) {
1238 PerlIO_pop(aTHX_ f);
1239 return NULL;
1240 }
2dc2558e 1241 }
002e75cf
JH
1242 else
1243 return NULL;
2dc2558e
NIS
1244 }
1245 }
1246 else if (f) {
1247 /* Pseudo-layer where push does its own stack adjust */
00f51856
NIS
1248 PerlIO_debug("PerlIO_push f=%p %s %s %p\n", (void*)f, tab->name,
1249 (mode) ? mode : "(Null)", (void*)arg);
210e727c 1250 if (tab->Pushed &&
27da23d5 1251 (*tab->Pushed) (aTHX_ f, mode, arg, (PerlIO_funcs*) tab) != 0) {
210e727c 1252 return NULL;
14a5cf38
JH
1253 }
1254 }
1255 return f;
60382766
NIS
1256}
1257
dfebf958 1258IV
86e05cf2
NIS
1259PerlIOBase_binmode(pTHX_ PerlIO *f)
1260{
1261 if (PerlIOValid(f)) {
1262 /* Is layer suitable for raw stream ? */
1263 if (PerlIOBase(f)->tab->kind & PERLIO_K_RAW) {
1264 /* Yes - turn off UTF-8-ness, to undo UTF-8 locale effects */
1265 PerlIOBase(f)->flags &= ~PERLIO_F_UTF8;
1266 }
1267 else {
1268 /* Not suitable - pop it */
1269 PerlIO_pop(aTHX_ f);
1270 }
1271 return 0;
1272 }
1273 return -1;
1274}
1275
1276IV
2dc2558e 1277PerlIORaw_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
dfebf958 1278{
8772537c
AL
1279 PERL_UNUSED_ARG(mode);
1280 PERL_UNUSED_ARG(arg);
1281 PERL_UNUSED_ARG(tab);
86e05cf2 1282
04892f78 1283 if (PerlIOValid(f)) {
86e05cf2 1284 PerlIO *t;
de009b76 1285 const PerlIOl *l;
14a5cf38 1286 PerlIO_flush(f);
86e05cf2
NIS
1287 /*
1288 * Strip all layers that are not suitable for a raw stream
1289 */
1290 t = f;
1291 while (t && (l = *t)) {
1292 if (l->tab->Binmode) {
1293 /* Has a handler - normal case */
1294 if ((*l->tab->Binmode)(aTHX_ f) == 0) {
1295 if (*t == l) {
1296 /* Layer still there - move down a layer */
1297 t = PerlIONext(t);
1298 }
1299 }
1300 else {
1301 return -1;
1302 }
14a5cf38
JH
1303 }
1304 else {
86e05cf2
NIS
1305 /* No handler - pop it */
1306 PerlIO_pop(aTHX_ t);
14a5cf38
JH
1307 }
1308 }
86e05cf2
NIS
1309 if (PerlIOValid(f)) {
1310 PerlIO_debug(":raw f=%p :%s\n", (void*)f, PerlIOBase(f)->tab->name);
1311 return 0;
1312 }
14a5cf38
JH
1313 }
1314 return -1;
dfebf958
NIS
1315}
1316
ac27b0f5 1317int
14a5cf38 1318PerlIO_apply_layera(pTHX_ PerlIO *f, const char *mode,
d9dac8cd 1319 PerlIO_list_t *layers, IV n, IV max)
14a5cf38 1320{
14a5cf38
JH
1321 int code = 0;
1322 while (n < max) {
8772537c 1323 PerlIO_funcs * const tab = PerlIO_layer_fetch(aTHX_ layers, n, NULL);
14a5cf38
JH
1324 if (tab) {
1325 if (!PerlIO_push(aTHX_ f, tab, mode, PerlIOArg)) {
1326 code = -1;
1327 break;
1328 }
1329 }
1330 n++;
1331 }
1332 return code;
e3f3bf95
NIS
1333}
1334
1335int
ac27b0f5
NIS
1336PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names)
1337{
14a5cf38 1338 int code = 0;
53f1b6d2 1339 if (f && names) {
8772537c 1340 PerlIO_list_t * const layers = PerlIO_list_alloc(aTHX);
14a5cf38
JH
1341 code = PerlIO_parse_layers(aTHX_ layers, names);
1342 if (code == 0) {
d9dac8cd 1343 code = PerlIO_apply_layera(aTHX_ f, mode, layers, 0, layers->cur);
14a5cf38 1344 }
3a1ee7e8 1345 PerlIO_list_free(aTHX_ layers);
ac27b0f5 1346 }
14a5cf38 1347 return code;
ac27b0f5
NIS
1348}
1349
f3862f8b 1350
60382766 1351/*--------------------------------------------------------------------------------------*/
14a5cf38 1352/*
71200d45 1353 * Given the abstraction above the public API functions
14a5cf38 1354 */
60382766
NIS
1355
1356int
f5b9d040 1357PerlIO_binmode(pTHX_ PerlIO *f, int iotype, int mode, const char *names)
76ced9ad 1358{
68b5363f
PD
1359 PerlIO_debug("PerlIO_binmode f=%p %s %c %x %s\n", (void*)f,
1360 (PerlIOBase(f)) ? PerlIOBase(f)->tab->name : "(Null)",
1361 iotype, mode, (names) ? names : "(Null)");
1362
03c0554d
NIS
1363 if (names) {
1364 /* Do not flush etc. if (e.g.) switching encodings.
1365 if a pushed layer knows it needs to flush lower layers
1366 (for example :unix which is never going to call them)
1367 it can do the flush when it is pushed.
1368 */
1369 return PerlIO_apply_layers(aTHX_ f, NULL, names) == 0 ? TRUE : FALSE;
1370 }
1371 else {
86e05cf2 1372 /* Fake 5.6 legacy of using this call to turn ON O_TEXT */
35990314 1373#ifdef PERLIO_USING_CRLF
03c0554d
NIS
1374 /* Legacy binmode only has meaning if O_TEXT has a value distinct from
1375 O_BINARY so we can look for it in mode.
1376 */
1377 if (!(mode & O_BINARY)) {
1378 /* Text mode */
86e05cf2
NIS
1379 /* FIXME?: Looking down the layer stack seems wrong,
1380 but is a way of reaching past (say) an encoding layer
1381 to flip CRLF-ness of the layer(s) below
1382 */
03c0554d
NIS
1383 while (*f) {
1384 /* Perhaps we should turn on bottom-most aware layer
1385 e.g. Ilya's idea that UNIX TTY could serve
1386 */
1387 if (PerlIOBase(f)->tab->kind & PERLIO_K_CANCRLF) {
1388 if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF)) {
1389 /* Not in text mode - flush any pending stuff and flip it */
1390 PerlIO_flush(f);
1391 PerlIOBase(f)->flags |= PERLIO_F_CRLF;
1392 }
1393 /* Only need to turn it on in one layer so we are done */
1394 return TRUE;
ed53a2bb 1395 }
03c0554d 1396 f = PerlIONext(f);
14a5cf38 1397 }
03c0554d
NIS
1398 /* Not finding a CRLF aware layer presumably means we are binary
1399 which is not what was requested - so we failed
1400 We _could_ push :crlf layer but so could caller
1401 */
1402 return FALSE;
14a5cf38 1403 }
6ce75a77 1404#endif
86e05cf2
NIS
1405 /* Legacy binmode is now _defined_ as being equivalent to pushing :raw
1406 So code that used to be here is now in PerlIORaw_pushed().
03c0554d 1407 */
a0714e2c 1408 return PerlIO_push(aTHX_ f, PERLIO_FUNCS_CAST(&PerlIO_raw), NULL, NULL) ? TRUE : FALSE;
14a5cf38 1409 }
f5b9d040
NIS
1410}
1411
f5b9d040 1412int
e87a358a 1413PerlIO__close(pTHX_ PerlIO *f)
f5b9d040 1414{
37725cdc 1415 if (PerlIOValid(f)) {
46c461b5 1416 PerlIO_funcs * const tab = PerlIOBase(f)->tab;
37725cdc
NIS
1417 if (tab && tab->Close)
1418 return (*tab->Close)(aTHX_ f);
1419 else
1420 return PerlIOBase_close(aTHX_ f);
1421 }
14a5cf38 1422 else {
93189314 1423 SETERRNO(EBADF, SS_IVCHAN);
14a5cf38
JH
1424 return -1;
1425 }
76ced9ad
NIS
1426}
1427
b931b1d9 1428int
e87a358a 1429Perl_PerlIO_close(pTHX_ PerlIO *f)
b931b1d9 1430{
de009b76 1431 const int code = PerlIO__close(aTHX_ f);
37725cdc
NIS
1432 while (PerlIOValid(f)) {
1433 PerlIO_pop(aTHX_ f);
f6c77cf1 1434 }
14a5cf38 1435 return code;
b931b1d9
NIS
1436}
1437
b931b1d9 1438int
e87a358a 1439Perl_PerlIO_fileno(pTHX_ PerlIO *f)
b931b1d9 1440{
97aff369 1441 dVAR;
b32dd47e 1442 Perl_PerlIO_or_Base(f, Fileno, fileno, -1, (aTHX_ f));
b931b1d9
NIS
1443}
1444
1141d9f8 1445
fcf2db38 1446static PerlIO_funcs *
2edd7e44
NIS
1447PerlIO_layer_from_ref(pTHX_ SV *sv)
1448{
97aff369 1449 dVAR;
14a5cf38 1450 /*
71200d45 1451 * For any scalar type load the handler which is bundled with perl
14a5cf38 1452 */
75208dda
RGS
1453 if (SvTYPE(sv) < SVt_PVAV) {
1454 PerlIO_funcs *f = PerlIO_find_layer(aTHX_ STR_WITH_LEN("scalar"), 1);
1455 /* This isn't supposed to happen, since PerlIO::scalar is core,
1456 * but could happen anyway in smaller installs or with PAR */
1457 if (!f && ckWARN(WARN_LAYER))
1458 Perl_warner(aTHX_ packWARN(WARN_LAYER), "Unknown PerlIO layer \"scalar\"");
1459 return f;
1460 }
14a5cf38
JH
1461
1462 /*
71200d45 1463 * For other types allow if layer is known but don't try and load it
14a5cf38
JH
1464 */
1465 switch (SvTYPE(sv)) {
1466 case SVt_PVAV:
6a245ed1 1467 return PerlIO_find_layer(aTHX_ STR_WITH_LEN("Array"), 0);
14a5cf38 1468 case SVt_PVHV:
6a245ed1 1469 return PerlIO_find_layer(aTHX_ STR_WITH_LEN("Hash"), 0);
14a5cf38 1470 case SVt_PVCV:
6a245ed1 1471 return PerlIO_find_layer(aTHX_ STR_WITH_LEN("Code"), 0);
14a5cf38 1472 case SVt_PVGV:
6a245ed1 1473 return PerlIO_find_layer(aTHX_ STR_WITH_LEN("Glob"), 0);
42d0e0b7
AL
1474 default:
1475 return NULL;
14a5cf38 1476 }
2edd7e44
NIS
1477}
1478
fcf2db38 1479PerlIO_list_t *
14a5cf38
JH
1480PerlIO_resolve_layers(pTHX_ const char *layers,
1481 const char *mode, int narg, SV **args)
1482{
97aff369 1483 dVAR;
14a5cf38
JH
1484 PerlIO_list_t *def = PerlIO_default_layers(aTHX);
1485 int incdef = 1;
a1ea730d 1486 if (!PL_perlio)
14a5cf38
JH
1487 PerlIO_stdstreams(aTHX);
1488 if (narg) {
dcda55fc 1489 SV * const arg = *args;
14a5cf38 1490 /*
71200d45
NIS
1491 * If it is a reference but not an object see if we have a handler
1492 * for it
14a5cf38
JH
1493 */
1494 if (SvROK(arg) && !sv_isobject(arg)) {
46c461b5 1495 PerlIO_funcs * const handler = PerlIO_layer_from_ref(aTHX_ SvRV(arg));
14a5cf38 1496 if (handler) {
3a1ee7e8
NIS
1497 def = PerlIO_list_alloc(aTHX);
1498 PerlIO_list_push(aTHX_ def, handler, &PL_sv_undef);
14a5cf38
JH
1499 incdef = 0;
1500 }
1501 /*
e934609f 1502 * Don't fail if handler cannot be found :via(...) etc. may do
14a5cf38 1503 * something sensible else we will just stringfy and open
71200d45 1504 * resulting string.
14a5cf38
JH
1505 */
1506 }
1507 }
9fe371da 1508 if (!layers || !*layers)
11bcd5da 1509 layers = Perl_PerlIO_context_layers(aTHX_ mode);
14a5cf38
JH
1510 if (layers && *layers) {
1511 PerlIO_list_t *av;
1512 if (incdef) {
a951d81d 1513 av = PerlIO_clone_list(aTHX_ def, NULL);
14a5cf38
JH
1514 }
1515 else {
1516 av = def;
1517 }
0cff2cf3
NIS
1518 if (PerlIO_parse_layers(aTHX_ av, layers) == 0) {
1519 return av;
1520 }
1521 else {
1522 PerlIO_list_free(aTHX_ av);
b37c2d43 1523 return NULL;
0cff2cf3 1524 }
14a5cf38
JH
1525 }
1526 else {
1527 if (incdef)
1528 def->refcnt++;
1529 return def;
1530 }
ee518936
NIS
1531}
1532
1533PerlIO *
14a5cf38
JH
1534PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd,
1535 int imode, int perm, PerlIO *f, int narg, SV **args)
1536{
97aff369 1537 dVAR;
14a5cf38
JH
1538 if (!f && narg == 1 && *args == &PL_sv_undef) {
1539 if ((f = PerlIO_tmpfile())) {
9fe371da 1540 if (!layers || !*layers)
11bcd5da 1541 layers = Perl_PerlIO_context_layers(aTHX_ mode);
14a5cf38
JH
1542 if (layers && *layers)
1543 PerlIO_apply_layers(aTHX_ f, mode, layers);
1544 }
1545 }
1546 else {
de009b76 1547 PerlIO_list_t *layera;
14a5cf38
JH
1548 IV n;
1549 PerlIO_funcs *tab = NULL;
04892f78 1550 if (PerlIOValid(f)) {
14a5cf38 1551 /*
71200d45
NIS
1552 * This is "reopen" - it is not tested as perl does not use it
1553 * yet
14a5cf38
JH
1554 */
1555 PerlIOl *l = *f;
3a1ee7e8 1556 layera = PerlIO_list_alloc(aTHX);
14a5cf38 1557 while (l) {
a951d81d
BL
1558 SV *arg = NULL;
1559 if (l->tab->Getarg)
1560 arg = (*l->tab->Getarg) (aTHX_ &l, NULL, 0);
1561 PerlIO_list_push(aTHX_ layera, l->tab,
1562 (arg) ? arg : &PL_sv_undef);
1563 if (arg)
1564 SvREFCNT_dec(arg);
14a5cf38
JH
1565 l = *PerlIONext(&l);
1566 }
1567 }
1568 else {
1569 layera = PerlIO_resolve_layers(aTHX_ layers, mode, narg, args);
0cff2cf3
NIS
1570 if (!layera) {
1571 return NULL;
1572 }
14a5cf38
JH
1573 }
1574 /*
71200d45 1575 * Start at "top" of layer stack
14a5cf38
JH
1576 */
1577 n = layera->cur - 1;
1578 while (n >= 0) {
46c461b5 1579 PerlIO_funcs * const t = PerlIO_layer_fetch(aTHX_ layera, n, NULL);
14a5cf38
JH
1580 if (t && t->Open) {
1581 tab = t;
1582 break;
1583 }
1584 n--;
1585 }
1586 if (tab) {
1587 /*
71200d45 1588 * Found that layer 'n' can do opens - call it
14a5cf38 1589 */
7cf31beb 1590 if (narg > 1 && !(tab->kind & PERLIO_K_MULTIARG)) {
3b8752bb 1591 Perl_croak(aTHX_ "More than one argument to open(,':%s')",tab->name);
7cf31beb 1592 }
14a5cf38 1593 PerlIO_debug("openn(%s,'%s','%s',%d,%x,%o,%p,%d,%p)\n",
355d3743
PD
1594 tab->name, layers ? layers : "(Null)", mode, fd,
1595 imode, perm, (void*)f, narg, (void*)args);
210e727c
JH
1596 if (tab->Open)
1597 f = (*tab->Open) (aTHX_ tab, layera, n, mode, fd, imode, perm,
1598 f, narg, args);
1599 else {
1600 SETERRNO(EINVAL, LIB_INVARG);
1601 f = NULL;
1602 }
14a5cf38
JH
1603 if (f) {
1604 if (n + 1 < layera->cur) {
1605 /*
1606 * More layers above the one that we used to open -
71200d45 1607 * apply them now
14a5cf38 1608 */
d9dac8cd
NIS
1609 if (PerlIO_apply_layera(aTHX_ f, mode, layera, n + 1, layera->cur) != 0) {
1610 /* If pushing layers fails close the file */
1611 PerlIO_close(f);
14a5cf38
JH
1612 f = NULL;
1613 }
1614 }
1615 }
1616 }
3a1ee7e8 1617 PerlIO_list_free(aTHX_ layera);
14a5cf38
JH
1618 }
1619 return f;
ee518936 1620}
b931b1d9
NIS
1621
1622
9e353e3b 1623SSize_t
e87a358a 1624Perl_PerlIO_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
6f9d8c32 1625{
b32dd47e 1626 Perl_PerlIO_or_Base(f, Read, read, -1, (aTHX_ f, vbuf, count));
760ac839
LW
1627}
1628
313ca112 1629SSize_t
e87a358a 1630Perl_PerlIO_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
760ac839 1631{
b32dd47e 1632 Perl_PerlIO_or_Base(f, Unread, unread, -1, (aTHX_ f, vbuf, count));
760ac839
LW
1633}
1634
9e353e3b 1635SSize_t
e87a358a 1636Perl_PerlIO_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
760ac839 1637{
b32dd47e 1638 Perl_PerlIO_or_fail(f, Write, -1, (aTHX_ f, vbuf, count));
760ac839
LW
1639}
1640
6f9d8c32 1641int
e87a358a 1642Perl_PerlIO_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
760ac839 1643{
b32dd47e 1644 Perl_PerlIO_or_fail(f, Seek, -1, (aTHX_ f, offset, whence));
760ac839
LW
1645}
1646
9e353e3b 1647Off_t
e87a358a 1648Perl_PerlIO_tell(pTHX_ PerlIO *f)
760ac839 1649{
b32dd47e 1650 Perl_PerlIO_or_fail(f, Tell, -1, (aTHX_ f));
760ac839
LW
1651}
1652
6f9d8c32 1653int
e87a358a 1654Perl_PerlIO_flush(pTHX_ PerlIO *f)
760ac839 1655{
97aff369 1656 dVAR;
14a5cf38
JH
1657 if (f) {
1658 if (*f) {
de009b76 1659 const PerlIO_funcs *tab = PerlIOBase(f)->tab;
1b7a0411
JH
1660
1661 if (tab && tab->Flush)
f62ce20a 1662 return (*tab->Flush) (aTHX_ f);
1b7a0411
JH
1663 else
1664 return 0; /* If no Flush defined, silently succeed. */
14a5cf38
JH
1665 }
1666 else {
fe5a182c 1667 PerlIO_debug("Cannot flush f=%p\n", (void*)f);
93189314 1668 SETERRNO(EBADF, SS_IVCHAN);
14a5cf38
JH
1669 return -1;
1670 }
1671 }
1672 else {
1673 /*
1674 * Is it good API design to do flush-all on NULL, a potentially
1675 * errorneous input? Maybe some magical value (PerlIO*
1676 * PERLIO_FLUSH_ALL = (PerlIO*)-1;)? Yes, stdio does similar
1677 * things on fflush(NULL), but should we be bound by their design
71200d45 1678 * decisions? --jhi
14a5cf38 1679 */
a1ea730d 1680 PerlIO **table = &PL_perlio;
14a5cf38
JH
1681 int code = 0;
1682 while ((f = *table)) {
1683 int i;
1684 table = (PerlIO **) (f++);
1685 for (i = 1; i < PERLIO_TABLE_SIZE; i++) {
1686 if (*f && PerlIO_flush(f) != 0)
1687 code = -1;
1688 f++;
1689 }
1690 }
1691 return code;
1692 }
760ac839
LW
1693}
1694
a9c883f6 1695void
f62ce20a 1696PerlIOBase_flush_linebuf(pTHX)
a9c883f6 1697{
97aff369 1698 dVAR;
a1ea730d 1699 PerlIO **table = &PL_perlio;
14a5cf38
JH
1700 PerlIO *f;
1701 while ((f = *table)) {
1702 int i;
1703 table = (PerlIO **) (f++);
1704 for (i = 1; i < PERLIO_TABLE_SIZE; i++) {
1705 if (*f
1706 && (PerlIOBase(f)->
1707 flags & (PERLIO_F_LINEBUF | PERLIO_F_CANWRITE))
1708 == (PERLIO_F_LINEBUF | PERLIO_F_CANWRITE))
1709 PerlIO_flush(f);
1710 f++;
1711 }
a9c883f6 1712 }
a9c883f6
NIS
1713}
1714
06da4f11 1715int
e87a358a 1716Perl_PerlIO_fill(pTHX_ PerlIO *f)
06da4f11 1717{
b32dd47e 1718 Perl_PerlIO_or_fail(f, Fill, -1, (aTHX_ f));
06da4f11
NIS
1719}
1720
f3862f8b
NIS
1721int
1722PerlIO_isutf8(PerlIO *f)
1723{
1b7a0411
JH
1724 if (PerlIOValid(f))
1725 return (PerlIOBase(f)->flags & PERLIO_F_UTF8) != 0;
1726 else
1727 SETERRNO(EBADF, SS_IVCHAN);
37725cdc 1728
1b7a0411 1729 return -1;
f3862f8b
NIS
1730}
1731
6f9d8c32 1732int
e87a358a 1733Perl_PerlIO_eof(pTHX_ PerlIO *f)
760ac839 1734{
b32dd47e 1735 Perl_PerlIO_or_Base(f, Eof, eof, -1, (aTHX_ f));
9e353e3b
NIS
1736}
1737
9e353e3b 1738int
e87a358a 1739Perl_PerlIO_error(pTHX_ PerlIO *f)
9e353e3b 1740{
b32dd47e 1741 Perl_PerlIO_or_Base(f, Error, error, -1, (aTHX_ f));
9e353e3b
NIS
1742}
1743
9e353e3b 1744void
e87a358a 1745Perl_PerlIO_clearerr(pTHX_ PerlIO *f)
9e353e3b 1746{
b32dd47e 1747 Perl_PerlIO_or_Base_void(f, Clearerr, clearerr, (aTHX_ f));
9e353e3b
NIS
1748}
1749
9e353e3b 1750void
e87a358a 1751Perl_PerlIO_setlinebuf(pTHX_ PerlIO *f)
9e353e3b 1752{
b32dd47e 1753 Perl_PerlIO_or_Base_void(f, Setlinebuf, setlinebuf, (aTHX_ f));
9e353e3b
NIS
1754}
1755
9e353e3b
NIS
1756int
1757PerlIO_has_base(PerlIO *f)
1758{
1b7a0411 1759 if (PerlIOValid(f)) {
46c461b5 1760 const PerlIO_funcs * const tab = PerlIOBase(f)->tab;
1b7a0411
JH
1761
1762 if (tab)
1763 return (tab->Get_base != NULL);
1764 SETERRNO(EINVAL, LIB_INVARG);
1765 }
1766 else
1767 SETERRNO(EBADF, SS_IVCHAN);
1768
1769 return 0;
760ac839
LW
1770}
1771
9e353e3b
NIS
1772int
1773PerlIO_fast_gets(PerlIO *f)
760ac839 1774{
04892f78 1775 if (PerlIOValid(f) && (PerlIOBase(f)->flags & PERLIO_F_FASTGETS)) {
46c461b5 1776 const PerlIO_funcs * const tab = PerlIOBase(f)->tab;
1b7a0411
JH
1777
1778 if (tab)
1779 return (tab->Set_ptrcnt != NULL);
1780 SETERRNO(EINVAL, LIB_INVARG);
14a5cf38 1781 }
1b7a0411
JH
1782 else
1783 SETERRNO(EBADF, SS_IVCHAN);
1784
14a5cf38 1785 return 0;
9e353e3b
NIS
1786}
1787
9e353e3b
NIS
1788int
1789PerlIO_has_cntptr(PerlIO *f)
1790{
04892f78 1791 if (PerlIOValid(f)) {
46c461b5 1792 const PerlIO_funcs * const tab = PerlIOBase(f)->tab;
1b7a0411
JH
1793
1794 if (tab)
1795 return (tab->Get_ptr != NULL && tab->Get_cnt != NULL);
1796 SETERRNO(EINVAL, LIB_INVARG);
14a5cf38 1797 }
1b7a0411
JH
1798 else
1799 SETERRNO(EBADF, SS_IVCHAN);
1800
14a5cf38 1801 return 0;
9e353e3b
NIS
1802}
1803
9e353e3b
NIS
1804int
1805PerlIO_canset_cnt(PerlIO *f)
1806{
04892f78 1807 if (PerlIOValid(f)) {
46c461b5 1808 const PerlIO_funcs * const tab = PerlIOBase(f)->tab;
1b7a0411
JH
1809
1810 if (tab)
1811 return (tab->Set_ptrcnt != NULL);
1812 SETERRNO(EINVAL, LIB_INVARG);
14a5cf38 1813 }
1b7a0411
JH
1814 else
1815 SETERRNO(EBADF, SS_IVCHAN);
1816
14a5cf38 1817 return 0;
760ac839
LW
1818}
1819
888911fc 1820STDCHAR *
e87a358a 1821Perl_PerlIO_get_base(pTHX_ PerlIO *f)
760ac839 1822{
b32dd47e 1823 Perl_PerlIO_or_fail(f, Get_base, NULL, (aTHX_ f));
9e353e3b
NIS
1824}
1825
9e353e3b 1826int
e87a358a 1827Perl_PerlIO_get_bufsiz(pTHX_ PerlIO *f)
9e353e3b 1828{
b32dd47e 1829 Perl_PerlIO_or_fail(f, Get_bufsiz, -1, (aTHX_ f));
9e353e3b
NIS
1830}
1831
9e353e3b 1832STDCHAR *
e87a358a 1833Perl_PerlIO_get_ptr(pTHX_ PerlIO *f)
9e353e3b 1834{
b32dd47e 1835 Perl_PerlIO_or_fail(f, Get_ptr, NULL, (aTHX_ f));
9e353e3b
NIS
1836}
1837
05d1247b 1838int
e87a358a 1839Perl_PerlIO_get_cnt(pTHX_ PerlIO *f)
9e353e3b 1840{
b32dd47e 1841 Perl_PerlIO_or_fail(f, Get_cnt, -1, (aTHX_ f));
9e353e3b
NIS
1842}
1843
9e353e3b 1844void
e87a358a 1845Perl_PerlIO_set_cnt(pTHX_ PerlIO *f, int cnt)
9e353e3b 1846{
b32dd47e 1847 Perl_PerlIO_or_fail_void(f, Set_ptrcnt, (aTHX_ f, NULL, cnt));
9e353e3b
NIS
1848}
1849
9e353e3b 1850void
e87a358a 1851Perl_PerlIO_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, int cnt)
9e353e3b 1852{
b32dd47e 1853 Perl_PerlIO_or_fail_void(f, Set_ptrcnt, (aTHX_ f, ptr, cnt));
9e353e3b
NIS
1854}
1855
4ec2216f 1856
9e353e3b 1857/*--------------------------------------------------------------------------------------*/
14a5cf38 1858/*
71200d45 1859 * utf8 and raw dummy layers
14a5cf38 1860 */
dfebf958 1861
26fb694e 1862IV
2dc2558e 1863PerlIOUtf8_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
26fb694e 1864{
96a5add6 1865 PERL_UNUSED_CONTEXT;
8772537c
AL
1866 PERL_UNUSED_ARG(mode);
1867 PERL_UNUSED_ARG(arg);
00f51856 1868 if (PerlIOValid(f)) {
14a5cf38
JH
1869 if (tab->kind & PERLIO_K_UTF8)
1870 PerlIOBase(f)->flags |= PERLIO_F_UTF8;
1871 else
1872 PerlIOBase(f)->flags &= ~PERLIO_F_UTF8;
1873 return 0;
1874 }
1875 return -1;
26fb694e
NIS
1876}
1877
27da23d5 1878PERLIO_FUNCS_DECL(PerlIO_utf8) = {
2dc2558e 1879 sizeof(PerlIO_funcs),
14a5cf38 1880 "utf8",
2dc2558e 1881 0,
6874a2de 1882 PERLIO_K_DUMMY | PERLIO_K_UTF8,
14a5cf38
JH
1883 PerlIOUtf8_pushed,
1884 NULL,
1885 NULL,
1886 NULL,
1887 NULL,
1888 NULL,
1889 NULL,
1890 NULL,
1891 NULL,
1892 NULL,
1893 NULL,
de009b76
AL
1894 NULL,
1895 NULL,
22569500
NIS
1896 NULL, /* flush */
1897 NULL, /* fill */
14a5cf38
JH
1898 NULL,
1899 NULL,
1900 NULL,
1901 NULL,
22569500
NIS
1902 NULL, /* get_base */
1903 NULL, /* get_bufsiz */
1904 NULL, /* get_ptr */
1905 NULL, /* get_cnt */
1906 NULL, /* set_ptrcnt */
26fb694e
NIS
1907};
1908
27da23d5 1909PERLIO_FUNCS_DECL(PerlIO_byte) = {
2dc2558e 1910 sizeof(PerlIO_funcs),
14a5cf38 1911 "bytes",
2dc2558e 1912 0,
14a5cf38
JH
1913 PERLIO_K_DUMMY,
1914 PerlIOUtf8_pushed,
1915 NULL,
1916 NULL,
1917 NULL,
1918 NULL,
1919 NULL,
1920 NULL,
1921 NULL,
1922 NULL,
1923 NULL,
1924 NULL,
de009b76
AL
1925 NULL,
1926 NULL,
22569500
NIS
1927 NULL, /* flush */
1928 NULL, /* fill */
14a5cf38
JH
1929 NULL,
1930 NULL,
1931 NULL,
1932 NULL,
22569500
NIS
1933 NULL, /* get_base */
1934 NULL, /* get_bufsiz */
1935 NULL, /* get_ptr */
1936 NULL, /* get_cnt */
1937 NULL, /* set_ptrcnt */
dfebf958
NIS
1938};
1939
1940PerlIO *
14a5cf38
JH
1941PerlIORaw_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
1942 IV n, const char *mode, int fd, int imode, int perm,
1943 PerlIO *old, int narg, SV **args)
dfebf958 1944{
8772537c
AL
1945 PerlIO_funcs * const tab = PerlIO_default_btm();
1946 PERL_UNUSED_ARG(self);
210e727c
JH
1947 if (tab && tab->Open)
1948 return (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm,
1949 old, narg, args);
1950 SETERRNO(EINVAL, LIB_INVARG);
1951 return NULL;
dfebf958
NIS
1952}
1953
27da23d5 1954PERLIO_FUNCS_DECL(PerlIO_raw) = {
2dc2558e 1955 sizeof(PerlIO_funcs),
14a5cf38 1956 "raw",
2dc2558e 1957 0,
14a5cf38
JH
1958 PERLIO_K_DUMMY,
1959 PerlIORaw_pushed,
1960 PerlIOBase_popped,
1961 PerlIORaw_open,
1962 NULL,
1963 NULL,
1964 NULL,
1965 NULL,
1966 NULL,
1967 NULL,
1968 NULL,
1969 NULL,
de009b76
AL
1970 NULL,
1971 NULL,
22569500
NIS
1972 NULL, /* flush */
1973 NULL, /* fill */
14a5cf38
JH
1974 NULL,
1975 NULL,
1976 NULL,
1977 NULL,
22569500
NIS
1978 NULL, /* get_base */
1979 NULL, /* get_bufsiz */
1980 NULL, /* get_ptr */
1981 NULL, /* get_cnt */
1982 NULL, /* set_ptrcnt */
dfebf958
NIS
1983};
1984/*--------------------------------------------------------------------------------------*/
1985/*--------------------------------------------------------------------------------------*/
14a5cf38 1986/*
71200d45 1987 * "Methods" of the "base class"
14a5cf38 1988 */
9e353e3b
NIS
1989
1990IV
f62ce20a 1991PerlIOBase_fileno(pTHX_ PerlIO *f)
9e353e3b 1992{
04892f78 1993 return PerlIOValid(f) ? PerlIO_fileno(PerlIONext(f)) : -1;
9e353e3b
NIS
1994}
1995
f5b9d040 1996char *
81428673 1997PerlIO_modestr(PerlIO * f, char *buf)
14a5cf38
JH
1998{
1999 char *s = buf;
81428673 2000 if (PerlIOValid(f)) {
de009b76 2001 const IV flags = PerlIOBase(f)->flags;
81428673
NIS
2002 if (flags & PERLIO_F_APPEND) {
2003 *s++ = 'a';
2004 if (flags & PERLIO_F_CANREAD) {
2005 *s++ = '+';
2006 }
14a5cf38 2007 }
81428673
NIS
2008 else if (flags & PERLIO_F_CANREAD) {
2009 *s++ = 'r';
2010 if (flags & PERLIO_F_CANWRITE)
2011 *s++ = '+';
2012 }
2013 else if (flags & PERLIO_F_CANWRITE) {
2014 *s++ = 'w';
2015 if (flags & PERLIO_F_CANREAD) {
2016 *s++ = '+';
2017 }
14a5cf38 2018 }
35990314 2019#ifdef PERLIO_USING_CRLF
81428673
NIS
2020 if (!(flags & PERLIO_F_CRLF))
2021 *s++ = 'b';
5f1a76d0 2022#endif
81428673 2023 }
14a5cf38
JH
2024 *s = '\0';
2025 return buf;
f5b9d040
NIS
2026}
2027
81428673 2028
76ced9ad 2029IV
2dc2558e 2030PerlIOBase_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
9e353e3b 2031{
de009b76 2032 PerlIOl * const l = PerlIOBase(f);
96a5add6 2033 PERL_UNUSED_CONTEXT;
8772537c 2034 PERL_UNUSED_ARG(arg);
de009b76 2035
14a5cf38
JH
2036 l->flags &= ~(PERLIO_F_CANREAD | PERLIO_F_CANWRITE |
2037 PERLIO_F_TRUNCATE | PERLIO_F_APPEND);
2038 if (tab->Set_ptrcnt != NULL)
2039 l->flags |= PERLIO_F_FASTGETS;
2040 if (mode) {
3b6c1aba 2041 if (*mode == IoTYPE_NUMERIC || *mode == IoTYPE_IMPLICIT)
14a5cf38
JH
2042 mode++;
2043 switch (*mode++) {
2044 case 'r':
2045 l->flags |= PERLIO_F_CANREAD;
2046 break;
2047 case 'a':
2048 l->flags |= PERLIO_F_APPEND | PERLIO_F_CANWRITE;
2049 break;
2050 case 'w':
2051 l->flags |= PERLIO_F_TRUNCATE | PERLIO_F_CANWRITE;
2052 break;
2053 default:
93189314 2054 SETERRNO(EINVAL, LIB_INVARG);
14a5cf38
JH
2055 return -1;
2056 }
2057 while (*mode) {
2058 switch (*mode++) {
2059 case '+':
2060 l->flags |= PERLIO_F_CANREAD | PERLIO_F_CANWRITE;
2061 break;
2062 case 'b':
2063 l->flags &= ~PERLIO_F_CRLF;
2064 break;
2065 case 't':
2066 l->flags |= PERLIO_F_CRLF;
2067 break;
2068 default:
93189314 2069 SETERRNO(EINVAL, LIB_INVARG);
14a5cf38
JH
2070 return -1;
2071 }
2072 }
2073 }
2074 else {
2075 if (l->next) {
2076 l->flags |= l->next->flags &
2077 (PERLIO_F_CANREAD | PERLIO_F_CANWRITE | PERLIO_F_TRUNCATE |
2078 PERLIO_F_APPEND);
2079 }
2080 }
5e2ab84b 2081#if 0
14a5cf38 2082 PerlIO_debug("PerlIOBase_pushed f=%p %s %s fl=%08" UVxf " (%s)\n",
6c9570dc 2083 (void*)f, PerlIOBase(f)->tab->name, (omode) ? omode : "(Null)",
14a5cf38 2084 l->flags, PerlIO_modestr(f, temp));
5e2ab84b 2085#endif
14a5cf38 2086 return 0;
76ced9ad
NIS
2087}
2088
2089IV
f62ce20a 2090PerlIOBase_popped(pTHX_ PerlIO *f)
76ced9ad 2091{
96a5add6 2092 PERL_UNUSED_CONTEXT;
8772537c 2093 PERL_UNUSED_ARG(f);
14a5cf38 2094 return 0;
760ac839
LW
2095}
2096
9e353e3b 2097SSize_t
f62ce20a 2098PerlIOBase_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
9e353e3b 2099{
14a5cf38 2100 /*
71200d45 2101 * Save the position as current head considers it
14a5cf38 2102 */
de009b76 2103 const Off_t old = PerlIO_tell(f);
a0714e2c 2104 PerlIO_push(aTHX_ f, PERLIO_FUNCS_CAST(&PerlIO_pending), "r", NULL);
14a5cf38 2105 PerlIOSelf(f, PerlIOBuf)->posn = old;
de009b76 2106 return PerlIOBuf_unread(aTHX_ f, vbuf, count);
9e353e3b
NIS
2107}
2108
f6c77cf1 2109SSize_t
f62ce20a 2110PerlIOBase_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
f6c77cf1 2111{
14a5cf38
JH
2112 STDCHAR *buf = (STDCHAR *) vbuf;
2113 if (f) {
263df5f1
JH
2114 if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD)) {
2115 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
2116 SETERRNO(EBADF, SS_IVCHAN);
2117 return 0;
2118 }
14a5cf38 2119 while (count > 0) {
93c2c2ec
IZ
2120 get_cnt:
2121 {
14a5cf38
JH
2122 SSize_t avail = PerlIO_get_cnt(f);
2123 SSize_t take = 0;
2124 if (avail > 0)
bb7a0f54 2125 take = ((SSize_t)count < avail) ? (SSize_t)count : avail;
14a5cf38
JH
2126 if (take > 0) {
2127 STDCHAR *ptr = PerlIO_get_ptr(f);
2128 Copy(ptr, buf, take, STDCHAR);
2129 PerlIO_set_ptrcnt(f, ptr + take, (avail -= take));
2130 count -= take;
2131 buf += take;
93c2c2ec
IZ
2132 if (avail == 0) /* set_ptrcnt could have reset avail */
2133 goto get_cnt;
14a5cf38
JH
2134 }
2135 if (count > 0 && avail <= 0) {
2136 if (PerlIO_fill(f) != 0)
2137 break;
2138 }
93c2c2ec 2139 }
14a5cf38
JH
2140 }
2141 return (buf - (STDCHAR *) vbuf);
2142 }
f6c77cf1 2143 return 0;
f6c77cf1
NIS
2144}
2145
9e353e3b 2146IV
f62ce20a 2147PerlIOBase_noop_ok(pTHX_ PerlIO *f)
9e353e3b 2148{
96a5add6 2149 PERL_UNUSED_CONTEXT;
8772537c 2150 PERL_UNUSED_ARG(f);
14a5cf38 2151 return 0;
9e353e3b
NIS
2152}
2153
2154IV
f62ce20a 2155PerlIOBase_noop_fail(pTHX_ PerlIO *f)
06da4f11 2156{
96a5add6 2157 PERL_UNUSED_CONTEXT;
8772537c 2158 PERL_UNUSED_ARG(f);
14a5cf38 2159 return -1;
06da4f11
NIS
2160}
2161
2162IV
f62ce20a 2163PerlIOBase_close(pTHX_ PerlIO *f)
9e353e3b 2164{
37725cdc
NIS
2165 IV code = -1;
2166 if (PerlIOValid(f)) {
2167 PerlIO *n = PerlIONext(f);
2168 code = PerlIO_flush(f);
2169 PerlIOBase(f)->flags &=
2170 ~(PERLIO_F_CANREAD | PERLIO_F_CANWRITE | PERLIO_F_OPEN);
2171 while (PerlIOValid(n)) {
de009b76 2172 const PerlIO_funcs * const tab = PerlIOBase(n)->tab;
37725cdc
NIS
2173 if (tab && tab->Close) {
2174 if ((*tab->Close)(aTHX_ n) != 0)
2175 code = -1;
2176 break;
2177 }
2178 else {
2179 PerlIOBase(n)->flags &=
2180 ~(PERLIO_F_CANREAD | PERLIO_F_CANWRITE | PERLIO_F_OPEN);
2181 }
2182 n = PerlIONext(n);
2183 }
2184 }
2185 else {
2186 SETERRNO(EBADF, SS_IVCHAN);
2187 }
14a5cf38 2188 return code;
9e353e3b
NIS
2189}
2190
2191IV
f62ce20a 2192PerlIOBase_eof(pTHX_ PerlIO *f)
9e353e3b 2193{
96a5add6 2194 PERL_UNUSED_CONTEXT;
04892f78 2195 if (PerlIOValid(f)) {
14a5cf38
JH
2196 return (PerlIOBase(f)->flags & PERLIO_F_EOF) != 0;
2197 }
2198 return 1;
9e353e3b
NIS
2199}
2200
2201IV
f62ce20a 2202PerlIOBase_error(pTHX_ PerlIO *f)
9e353e3b 2203{
96a5add6 2204 PERL_UNUSED_CONTEXT;
04892f78 2205 if (PerlIOValid(f)) {
14a5cf38
JH
2206 return (PerlIOBase(f)->flags & PERLIO_F_ERROR) != 0;
2207 }
2208 return 1;
9e353e3b
NIS
2209}
2210
2211void
f62ce20a 2212PerlIOBase_clearerr(pTHX_ PerlIO *f)
9e353e3b 2213{
04892f78 2214 if (PerlIOValid(f)) {
dcda55fc 2215 PerlIO * const n = PerlIONext(f);
14a5cf38 2216 PerlIOBase(f)->flags &= ~(PERLIO_F_ERROR | PERLIO_F_EOF);
04892f78 2217 if (PerlIOValid(n))
14a5cf38
JH
2218 PerlIO_clearerr(n);
2219 }
9e353e3b
NIS
2220}
2221
2222void
f62ce20a 2223PerlIOBase_setlinebuf(pTHX_ PerlIO *f)
9e353e3b 2224{
96a5add6 2225 PERL_UNUSED_CONTEXT;
04892f78 2226 if (PerlIOValid(f)) {
14a5cf38
JH
2227 PerlIOBase(f)->flags |= PERLIO_F_LINEBUF;
2228 }
9e353e3b
NIS
2229}
2230
93a8090d
NIS
2231SV *
2232PerlIO_sv_dup(pTHX_ SV *arg, CLONE_PARAMS *param)
2233{
2234 if (!arg)
a0714e2c 2235 return NULL;
93a8090d
NIS
2236#ifdef sv_dup
2237 if (param) {
a951d81d
BL
2238 arg = sv_dup(arg, param);
2239 SvREFCNT_inc_simple_void_NN(arg);
2240 return arg;
93a8090d
NIS
2241 }
2242 else {
2243 return newSVsv(arg);
2244 }
2245#else
1b6737cc 2246 PERL_UNUSED_ARG(param);
93a8090d
NIS
2247 return newSVsv(arg);
2248#endif
2249}
2250
2251PerlIO *
ecdeb87c 2252PerlIOBase_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
93a8090d 2253{
1b6737cc 2254 PerlIO * const nexto = PerlIONext(o);
04892f78 2255 if (PerlIOValid(nexto)) {
de009b76 2256 const PerlIO_funcs * const tab = PerlIOBase(nexto)->tab;
37725cdc
NIS
2257 if (tab && tab->Dup)
2258 f = (*tab->Dup)(aTHX_ f, nexto, param, flags);
2259 else
2260 f = PerlIOBase_dup(aTHX_ f, nexto, param, flags);
93a8090d
NIS
2261 }
2262 if (f) {
dcda55fc 2263 PerlIO_funcs * const self = PerlIOBase(o)->tab;
a951d81d 2264 SV *arg = NULL;
93a8090d 2265 char buf[8];
fe5a182c
JH
2266 PerlIO_debug("PerlIOBase_dup %s f=%p o=%p param=%p\n",
2267 self->name, (void*)f, (void*)o, (void*)param);
210e727c
JH
2268 if (self->Getarg)
2269 arg = (*self->Getarg)(aTHX_ o, param, flags);
93a8090d 2270 f = PerlIO_push(aTHX_ f, self, PerlIO_modestr(o,buf), arg);
f0720f70
RGS
2271 if (PerlIOBase(o)->flags & PERLIO_F_UTF8)
2272 PerlIOBase(f)->flags |= PERLIO_F_UTF8;
a951d81d 2273 if (arg)
93a8090d 2274 SvREFCNT_dec(arg);
93a8090d
NIS
2275 }
2276 return f;
2277}
2278
27da23d5 2279/* PL_perlio_fd_refcnt[] is in intrpvar.h */
93a8090d 2280
8b84d7dd 2281/* Must be called with PL_perlio_mutex locked. */
22c96fc1
NC
2282static void
2283S_more_refcounted_fds(pTHX_ const int new_fd) {
7a89be66 2284 dVAR;
22c96fc1 2285 const int old_max = PL_perlio_fd_refcnt_size;
f4ae5be6 2286 const int new_max = 16 + (new_fd & ~15);
22c96fc1
NC
2287 int *new_array;
2288
2289 PerlIO_debug("More fds - old=%d, need %d, new=%d\n",
2290 old_max, new_fd, new_max);
2291
2292 if (new_fd < old_max) {
2293 return;
2294 }
2295
f4ae5be6
NC
2296 assert (new_max > new_fd);
2297
eae082a0
JH
2298 /* Use plain realloc() since we need this memory to be really
2299 * global and visible to all the interpreters and/or threads. */
2300 new_array = (int*) realloc(PL_perlio_fd_refcnt, new_max * sizeof(int));
22c96fc1
NC
2301
2302 if (!new_array) {
8b84d7dd 2303#ifdef USE_ITHREADS
6cb8cb21 2304 MUTEX_UNLOCK(&PL_perlio_mutex);
22c96fc1
NC
2305#endif
2306 /* Can't use PerlIO to write as it allocates memory */
2307 PerlLIO_write(PerlIO_fileno(Perl_error_log),
2308 PL_no_mem, strlen(PL_no_mem));
2309 my_exit(1);
2310 }
2311
2312 PL_perlio_fd_refcnt_size = new_max;
2313 PL_perlio_fd_refcnt = new_array;
2314
95b63a38
JH
2315 PerlIO_debug("Zeroing %p, %d\n",
2316 (void*)(new_array + old_max),
2317 new_max - old_max);
22c96fc1
NC
2318
2319 Zero(new_array + old_max, new_max - old_max, int);
2320}
2321
2322
93a8090d
NIS
2323void
2324PerlIO_init(pTHX)
2325{
8b84d7dd 2326 /* MUTEX_INIT(&PL_perlio_mutex) is done in PERL_SYS_INIT3(). */
96a5add6 2327 PERL_UNUSED_CONTEXT;
93a8090d
NIS
2328}
2329
168d5872
NIS
2330void
2331PerlIOUnix_refcnt_inc(int fd)
2332{
27da23d5 2333 dTHX;
22c96fc1 2334 if (fd >= 0) {
97aff369 2335 dVAR;
22c96fc1 2336
8b84d7dd 2337#ifdef USE_ITHREADS
6cb8cb21 2338 MUTEX_LOCK(&PL_perlio_mutex);
168d5872 2339#endif
22c96fc1
NC
2340 if (fd >= PL_perlio_fd_refcnt_size)
2341 S_more_refcounted_fds(aTHX_ fd);
2342
27da23d5 2343 PL_perlio_fd_refcnt[fd]++;
8b84d7dd
RGS
2344 if (PL_perlio_fd_refcnt[fd] <= 0) {
2345 Perl_croak(aTHX_ "refcnt_inc: fd %d: %d <= 0\n",
2346 fd, PL_perlio_fd_refcnt[fd]);
2347 }
2348 PerlIO_debug("refcnt_inc: fd %d refcnt=%d\n",
2349 fd, PL_perlio_fd_refcnt[fd]);
22c96fc1 2350
8b84d7dd 2351#ifdef USE_ITHREADS
6cb8cb21 2352 MUTEX_UNLOCK(&PL_perlio_mutex);
168d5872 2353#endif
8b84d7dd
RGS
2354 } else {
2355 Perl_croak(aTHX_ "refcnt_inc: fd %d < 0\n", fd);
168d5872
NIS
2356 }
2357}
2358
168d5872
NIS
2359int
2360PerlIOUnix_refcnt_dec(int fd)
2361{
27da23d5 2362 dTHX;
168d5872 2363 int cnt = 0;
22c96fc1 2364 if (fd >= 0) {
97aff369 2365 dVAR;
8b84d7dd 2366#ifdef USE_ITHREADS
6cb8cb21 2367 MUTEX_LOCK(&PL_perlio_mutex);
168d5872 2368#endif
8b84d7dd
RGS
2369 if (fd >= PL_perlio_fd_refcnt_size) {
2370 Perl_croak(aTHX_ "refcnt_dec: fd %d >= refcnt_size %d\n",
2371 fd, PL_perlio_fd_refcnt_size);
2372 }
2373 if (PL_perlio_fd_refcnt[fd] <= 0) {
2374 Perl_croak(aTHX_ "refcnt_dec: fd %d: %d <= 0\n",
2375 fd, PL_perlio_fd_refcnt[fd]);
2376 }
27da23d5 2377 cnt = --PL_perlio_fd_refcnt[fd];
8b84d7dd
RGS
2378 PerlIO_debug("refcnt_dec: fd %d refcnt=%d\n", fd, cnt);
2379#ifdef USE_ITHREADS
6cb8cb21 2380 MUTEX_UNLOCK(&PL_perlio_mutex);
168d5872 2381#endif
8b84d7dd
RGS
2382 } else {
2383 Perl_croak(aTHX_ "refcnt_dec: fd %d < 0\n", fd);
168d5872
NIS
2384 }
2385 return cnt;
2386}
2387
694c95cf
JH
2388void
2389PerlIO_cleanup(pTHX)
2390{
97aff369 2391 dVAR;
694c95cf
JH
2392 int i;
2393#ifdef USE_ITHREADS
a25429c6 2394 PerlIO_debug("Cleanup layers for %p\n",(void*)aTHX);
9f4bd222
NIS
2395#else
2396 PerlIO_debug("Cleanup layers\n");
694c95cf 2397#endif
e47547a8 2398
694c95cf
JH
2399 /* Raise STDIN..STDERR refcount so we don't close them */
2400 for (i=0; i < 3; i++)
2401 PerlIOUnix_refcnt_inc(i);
2402 PerlIO_cleantable(aTHX_ &PL_perlio);
2403 /* Restore STDIN..STDERR refcount */
2404 for (i=0; i < 3; i++)
2405 PerlIOUnix_refcnt_dec(i);
9f4bd222
NIS
2406
2407 if (PL_known_layers) {
2408 PerlIO_list_free(aTHX_ PL_known_layers);
2409 PL_known_layers = NULL;
2410 }
27da23d5 2411 if (PL_def_layerlist) {
9f4bd222
NIS
2412 PerlIO_list_free(aTHX_ PL_def_layerlist);
2413 PL_def_layerlist = NULL;
2414 }
6cb8cb21
RGS
2415}
2416
2417void PerlIO_teardown(pTHX) /* Call only from PERL_SYS_TERM(). */
2418{
53d44271 2419 dVAR;
6cb8cb21
RGS
2420#ifdef DEBUGGING
2421 {
2422 /* By now all filehandles should have been closed, so any
2423 * stray (non-STD-)filehandles indicate *possible* (PerlIO)
2424 * errors. */
2425 int i;
2426 for (i = 3; i < PL_perlio_fd_refcnt_size; i++) {
2427 if (PL_perlio_fd_refcnt[i])
2428 PerlIO_debug("PerlIO_cleanup: fd %d refcnt=%d\n",
2429 i, PL_perlio_fd_refcnt[i]);
2430 }
2431 }
2432#endif
eae082a0
JH
2433 /* Not bothering with PL_perlio_mutex since by now
2434 * all the interpreters are gone. */
1cd82952
RGS
2435 if (PL_perlio_fd_refcnt_size /* Assuming initial size of zero. */
2436 && PL_perlio_fd_refcnt) {
eae082a0 2437 free(PL_perlio_fd_refcnt); /* To match realloc() in S_more_refcounted_fds(). */
432ce874
YO
2438 PL_perlio_fd_refcnt = NULL;
2439 PL_perlio_fd_refcnt_size = 0;
1cd82952 2440 }
694c95cf
JH
2441}
2442
9e353e3b 2443/*--------------------------------------------------------------------------------------*/
14a5cf38 2444/*
71200d45 2445 * Bottom-most level for UNIX-like case
14a5cf38 2446 */
9e353e3b 2447
14a5cf38 2448typedef struct {
22569500
NIS
2449 struct _PerlIO base; /* The generic part */
2450 int fd; /* UNIX like file descriptor */
2451 int oflags; /* open/fcntl flags */
9e353e3b
NIS
2452} PerlIOUnix;
2453
6f9d8c32 2454int
9e353e3b 2455PerlIOUnix_oflags(const char *mode)
760ac839 2456{
14a5cf38 2457 int oflags = -1;
3b6c1aba 2458 if (*mode == IoTYPE_IMPLICIT || *mode == IoTYPE_NUMERIC)
14a5cf38
JH
2459 mode++;
2460 switch (*mode) {
2461 case 'r':
2462 oflags = O_RDONLY;
2463 if (*++mode == '+') {
2464 oflags = O_RDWR;
2465 mode++;
2466 }
2467 break;
2468
2469 case 'w':
2470 oflags = O_CREAT | O_TRUNC;
2471 if (*++mode == '+') {
2472 oflags |= O_RDWR;
2473 mode++;
2474 }
2475 else
2476 oflags |= O_WRONLY;
2477 break;
2478
2479 case 'a':
2480 oflags = O_CREAT | O_APPEND;
2481 if (*++mode == '+') {
2482 oflags |= O_RDWR;
2483 mode++;
2484 }
2485 else
2486 oflags |= O_WRONLY;
2487 break;
2488 }
2489 if (*mode == 'b') {
2490 oflags |= O_BINARY;
2491 oflags &= ~O_TEXT;
2492 mode++;
2493 }
2494 else if (*mode == 't') {
2495 oflags |= O_TEXT;
2496 oflags &= ~O_BINARY;
2497 mode++;
2498 }
2499 /*
71200d45 2500 * Always open in binary mode
14a5cf38
JH
2501 */
2502 oflags |= O_BINARY;
2503 if (*mode || oflags == -1) {
93189314 2504 SETERRNO(EINVAL, LIB_INVARG);
14a5cf38
JH
2505 oflags = -1;
2506 }
2507 return oflags;
9e353e3b
NIS
2508}
2509
2510IV
f62ce20a 2511PerlIOUnix_fileno(pTHX_ PerlIO *f)
9e353e3b 2512{
96a5add6 2513 PERL_UNUSED_CONTEXT;
14a5cf38 2514 return PerlIOSelf(f, PerlIOUnix)->fd;
9e353e3b
NIS
2515}
2516
aa063c35
NIS
2517static void
2518PerlIOUnix_setfd(pTHX_ PerlIO *f, int fd, int imode)
4b803d04 2519{
de009b76 2520 PerlIOUnix * const s = PerlIOSelf(f, PerlIOUnix);
6caa5a9c 2521#if defined(WIN32)
aa063c35
NIS
2522 Stat_t st;
2523 if (PerlLIO_fstat(fd, &st) == 0) {
6caa5a9c 2524 if (!S_ISREG(st.st_mode)) {
aa063c35 2525 PerlIO_debug("%d is not regular file\n",fd);
6caa5a9c
NIS
2526 PerlIOBase(f)->flags |= PERLIO_F_NOTREG;
2527 }
aa063c35
NIS
2528 else {
2529 PerlIO_debug("%d _is_ a regular file\n",fd);
2530 }
6caa5a9c
NIS
2531 }
2532#endif
aa063c35
NIS
2533 s->fd = fd;
2534 s->oflags = imode;
2535 PerlIOUnix_refcnt_inc(fd);
96a5add6 2536 PERL_UNUSED_CONTEXT;
aa063c35
NIS
2537}
2538
2539IV
2540PerlIOUnix_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
2541{
2542 IV code = PerlIOBase_pushed(aTHX_ f, mode, arg, tab);
14a5cf38 2543 if (*PerlIONext(f)) {
4b069b44 2544 /* We never call down so do any pending stuff now */
03c0554d 2545 PerlIO_flush(PerlIONext(f));
14a5cf38 2546 /*
71200d45 2547 * XXX could (or should) we retrieve the oflags from the open file
14a5cf38 2548 * handle rather than believing the "mode" we are passed in? XXX
71200d45 2549 * Should the value on NULL mode be 0 or -1?
14a5cf38 2550 */
acbd16bf 2551 PerlIOUnix_setfd(aTHX_ f, PerlIO_fileno(PerlIONext(f)),
aa063c35 2552 mode ? PerlIOUnix_oflags(mode) : -1);
14a5cf38
JH
2553 }
2554 PerlIOBase(f)->flags |= PERLIO_F_OPEN;
6caa5a9c 2555
14a5cf38 2556 return code;
4b803d04
NIS
2557}
2558
c2fcde81
JH
2559IV
2560PerlIOUnix_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
2561{
de009b76 2562 const int fd = PerlIOSelf(f, PerlIOUnix)->fd;
0723351e 2563 Off_t new_loc;
96a5add6 2564 PERL_UNUSED_CONTEXT;
c2fcde81
JH
2565 if (PerlIOBase(f)->flags & PERLIO_F_NOTREG) {
2566#ifdef ESPIPE
2567 SETERRNO(ESPIPE, LIB_INVARG);
2568#else
2569 SETERRNO(EINVAL, LIB_INVARG);
2570#endif
2571 return -1;
2572 }
0723351e
NC
2573 new_loc = PerlLIO_lseek(fd, offset, whence);
2574 if (new_loc == (Off_t) - 1)
dcda55fc 2575 return -1;
c2fcde81
JH
2576 PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
2577 return 0;
2578}
2579
9e353e3b 2580PerlIO *
14a5cf38
JH
2581PerlIOUnix_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
2582 IV n, const char *mode, int fd, int imode,
2583 int perm, PerlIO *f, int narg, SV **args)
2584{
d9dac8cd 2585 if (PerlIOValid(f)) {
14a5cf38 2586 if (PerlIOBase(f)->flags & PERLIO_F_OPEN)
f62ce20a 2587 (*PerlIOBase(f)->tab->Close)(aTHX_ f);
14a5cf38
JH
2588 }
2589 if (narg > 0) {
3b6c1aba 2590 if (*mode == IoTYPE_NUMERIC)
14a5cf38
JH
2591 mode++;
2592 else {
2593 imode = PerlIOUnix_oflags(mode);
2594 perm = 0666;
2595 }
2596 if (imode != -1) {
e62f0680 2597 const char *path = SvPV_nolen_const(*args);
14a5cf38
JH
2598 fd = PerlLIO_open3(path, imode, perm);
2599 }
2600 }
2601 if (fd >= 0) {
3b6c1aba 2602 if (*mode == IoTYPE_IMPLICIT)
14a5cf38
JH
2603 mode++;
2604 if (!f) {
2605 f = PerlIO_allocate(aTHX);
d9dac8cd
NIS
2606 }
2607 if (!PerlIOValid(f)) {
a33cf58c
NIS
2608 if (!(f = PerlIO_push(aTHX_ f, self, mode, PerlIOArg))) {
2609 return NULL;
2610 }
d9dac8cd 2611 }
aa063c35 2612 PerlIOUnix_setfd(aTHX_ f, fd, imode);
14a5cf38 2613 PerlIOBase(f)->flags |= PERLIO_F_OPEN;
c2fcde81
JH
2614 if (*mode == IoTYPE_APPEND)
2615 PerlIOUnix_seek(aTHX_ f, 0, SEEK_END);
14a5cf38
JH
2616 return f;
2617 }
2618 else {
2619 if (f) {
6f207bd3 2620 NOOP;
14a5cf38 2621 /*
71200d45 2622 * FIXME: pop layers ???
14a5cf38
JH
2623 */
2624 }
2625 return NULL;
2626 }
9e353e3b
NIS
2627}
2628
71200d45 2629PerlIO *
ecdeb87c 2630PerlIOUnix_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
71200d45 2631{
dcda55fc 2632 const PerlIOUnix * const os = PerlIOSelf(o, PerlIOUnix);
93a8090d 2633 int fd = os->fd;
ecdeb87c
NIS
2634 if (flags & PERLIO_DUP_FD) {
2635 fd = PerlLIO_dup(fd);
2636 }
22c96fc1 2637 if (fd >= 0) {
ecdeb87c 2638 f = PerlIOBase_dup(aTHX_ f, o, param, flags);
71200d45
NIS
2639 if (f) {
2640 /* If all went well overwrite fd in dup'ed lay with the dup()'ed fd */
aa063c35 2641 PerlIOUnix_setfd(aTHX_ f, fd, os->oflags);
71200d45
NIS
2642 return f;
2643 }
71200d45
NIS
2644 }
2645 return NULL;
2646}
2647
2648
9e353e3b 2649SSize_t
f62ce20a 2650PerlIOUnix_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
9e353e3b 2651{
97aff369 2652 dVAR;
de009b76 2653 const int fd = PerlIOSelf(f, PerlIOUnix)->fd;
27da23d5
JH
2654#ifdef PERLIO_STD_SPECIAL
2655 if (fd == 0)
2656 return PERLIO_STD_IN(fd, vbuf, count);
2657#endif
81428673 2658 if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD) ||
1fd8f4ce 2659 PerlIOBase(f)->flags & (PERLIO_F_EOF|PERLIO_F_ERROR)) {
263df5f1 2660 return 0;
1fd8f4ce 2661 }
14a5cf38 2662 while (1) {
b464bac0 2663 const SSize_t len = PerlLIO_read(fd, vbuf, count);
14a5cf38 2664 if (len >= 0 || errno != EINTR) {
ba85f2ea
NIS
2665 if (len < 0) {
2666 if (errno != EAGAIN) {
2667 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
2668 }
2669 }
2670 else if (len == 0 && count != 0) {
14a5cf38 2671 PerlIOBase(f)->flags |= PERLIO_F_EOF;
ba85f2ea
NIS
2672 SETERRNO(0,0);
2673 }
14a5cf38
JH
2674 return len;
2675 }
2676 PERL_ASYNC_CHECK();
2677 }
b464bac0 2678 /*NOTREACHED*/
9e353e3b
NIS
2679}
2680
2681SSize_t
f62ce20a 2682PerlIOUnix_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
9e353e3b 2683{
97aff369 2684 dVAR;
de009b76 2685 const int fd = PerlIOSelf(f, PerlIOUnix)->fd;
27da23d5
JH
2686#ifdef PERLIO_STD_SPECIAL
2687 if (fd == 1 || fd == 2)
2688 return PERLIO_STD_OUT(fd, vbuf, count);
2689#endif
14a5cf38 2690 while (1) {
de009b76 2691 const SSize_t len = PerlLIO_write(fd, vbuf, count);
14a5cf38 2692 if (len >= 0 || errno != EINTR) {
ba85f2ea
NIS
2693 if (len < 0) {
2694 if (errno != EAGAIN) {
2695 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
2696 }
2697 }
14a5cf38
JH
2698 return len;
2699 }
2700 PERL_ASYNC_CHECK();
06da4f11 2701 }
1b6737cc 2702 /*NOTREACHED*/
9e353e3b
NIS
2703}
2704
9e353e3b 2705Off_t
f62ce20a 2706PerlIOUnix_tell(pTHX_ PerlIO *f)
9e353e3b 2707{
96a5add6
AL
2708 PERL_UNUSED_CONTEXT;
2709
14a5cf38 2710 return PerlLIO_lseek(PerlIOSelf(f, PerlIOUnix)->fd, 0, SEEK_CUR);
9e353e3b
NIS
2711}
2712
71200d45 2713
9e353e3b 2714IV
f62ce20a 2715PerlIOUnix_close(pTHX_ PerlIO *f)
9e353e3b 2716{
97aff369 2717 dVAR;
de009b76 2718 const int fd = PerlIOSelf(f, PerlIOUnix)->fd;
14a5cf38 2719 int code = 0;
168d5872
NIS
2720 if (PerlIOBase(f)->flags & PERLIO_F_OPEN) {
2721 if (PerlIOUnix_refcnt_dec(fd) > 0) {
93a8090d
NIS
2722 PerlIOBase(f)->flags &= ~PERLIO_F_OPEN;
2723 return 0;
22569500 2724 }
93a8090d
NIS
2725 }
2726 else {
93189314 2727 SETERRNO(EBADF,SS_IVCHAN);
93a8090d
NIS
2728 return -1;
2729 }
14a5cf38
JH
2730 while (PerlLIO_close(fd) != 0) {
2731 if (errno != EINTR) {
2732 code = -1;
2733 break;
2734 }
2735 PERL_ASYNC_CHECK();
2736 }
2737 if (code == 0) {
2738 PerlIOBase(f)->flags &= ~PERLIO_F_OPEN;
2739 }
2740 return code;
9e353e3b
NIS
2741}
2742
27da23d5 2743PERLIO_FUNCS_DECL(PerlIO_unix) = {
2dc2558e 2744 sizeof(PerlIO_funcs),
14a5cf38
JH
2745 "unix",
2746 sizeof(PerlIOUnix),
2747 PERLIO_K_RAW,
2748 PerlIOUnix_pushed,
44798d05 2749 PerlIOBase_popped,
14a5cf38 2750 PerlIOUnix_open,
86e05cf2 2751 PerlIOBase_binmode, /* binmode */
14a5cf38
JH
2752 NULL,
2753 PerlIOUnix_fileno,
71200d45 2754 PerlIOUnix_dup,
14a5cf38
JH
2755 PerlIOUnix_read,
2756 PerlIOBase_unread,
2757 PerlIOUnix_write,
2758 PerlIOUnix_seek,
2759 PerlIOUnix_tell,
2760 PerlIOUnix_close,
22569500
NIS
2761 PerlIOBase_noop_ok, /* flush */
2762 PerlIOBase_noop_fail, /* fill */
14a5cf38
JH
2763 PerlIOBase_eof,
2764 PerlIOBase_error,
2765 PerlIOBase_clearerr,
2766 PerlIOBase_setlinebuf,
22569500
NIS
2767 NULL, /* get_base */
2768 NULL, /* get_bufsiz */
2769 NULL, /* get_ptr */
2770 NULL, /* get_cnt */
2771 NULL, /* set_ptrcnt */
9e353e3b
NIS
2772};
2773
2774/*--------------------------------------------------------------------------------------*/
14a5cf38 2775/*
71200d45 2776 * stdio as a layer
14a5cf38 2777 */
9e353e3b 2778
313e59c8
NIS
2779#if defined(VMS) && !defined(STDIO_BUFFER_WRITABLE)
2780/* perl5.8 - This ensures the last minute VMS ungetc fix is not
2781 broken by the last second glibc 2.3 fix
2782 */
2783#define STDIO_BUFFER_WRITABLE
2784#endif
2785
2786
14a5cf38
JH
2787typedef struct {
2788 struct _PerlIO base;
22569500 2789 FILE *stdio; /* The stream */
9e353e3b
NIS
2790} PerlIOStdio;
2791
2792IV
f62ce20a 2793PerlIOStdio_fileno(pTHX_ PerlIO *f)
9e353e3b 2794{
96a5add6
AL
2795 PERL_UNUSED_CONTEXT;
2796
c4420975
AL
2797 if (PerlIOValid(f)) {
2798 FILE * const s = PerlIOSelf(f, PerlIOStdio)->stdio;
2799 if (s)
2800 return PerlSIO_fileno(s);
439ba545
NIS
2801 }
2802 errno = EBADF;
2803 return -1;
9e353e3b
NIS
2804}
2805
766a733e 2806char *
14a5cf38
JH
2807PerlIOStdio_mode(const char *mode, char *tmode)
2808{
de009b76 2809 char * const ret = tmode;
a0625d38
SR
2810 if (mode) {
2811 while (*mode) {
2812 *tmode++ = *mode++;
2813 }
14a5cf38 2814 }
95005ad8 2815#if defined(PERLIO_USING_CRLF) || defined(__CYGWIN__)
6ce75a77
JH
2816 *tmode++ = 'b';
2817#endif
14a5cf38
JH
2818 *tmode = '\0';
2819 return ret;
2820}
2821
4b803d04 2822IV
2dc2558e 2823PerlIOStdio_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
4b803d04 2824{
1fd8f4ce
NIS
2825 PerlIO *n;
2826 if (PerlIOValid(f) && PerlIOValid(n = PerlIONext(f))) {
46c461b5 2827 PerlIO_funcs * const toptab = PerlIOBase(n)->tab;
1fd8f4ce
NIS
2828 if (toptab == tab) {
2829 /* Top is already stdio - pop self (duplicate) and use original */
2830 PerlIO_pop(aTHX_ f);
2831 return 0;
2832 } else {
de009b76 2833 const int fd = PerlIO_fileno(n);
1fd8f4ce
NIS
2834 char tmode[8];
2835 FILE *stdio;
81428673 2836 if (fd >= 0 && (stdio = PerlSIO_fdopen(fd,
1fd8f4ce
NIS
2837 mode = PerlIOStdio_mode(mode, tmode)))) {
2838 PerlIOSelf(f, PerlIOStdio)->stdio = stdio;
2839 /* We never call down so do any pending stuff now */
2840 PerlIO_flush(PerlIONext(f));
81428673 2841 }
1fd8f4ce
NIS
2842 else {
2843 return -1;
2844 }
2845 }
14a5cf38 2846 }
2dc2558e 2847 return PerlIOBase_pushed(aTHX_ f, mode, arg, tab);
4b803d04
NIS
2848}
2849
22569500 2850
9e353e3b 2851PerlIO *
4b069b44 2852PerlIO_importFILE(FILE *stdio, const char *mode)
9e353e3b 2853{
14a5cf38
JH
2854 dTHX;
2855 PerlIO *f = NULL;
2856 if (stdio) {
22569500 2857 PerlIOStdio *s;
4b069b44
NIS
2858 if (!mode || !*mode) {
2859 /* We need to probe to see how we can open the stream
2860 so start with read/write and then try write and read
2861 we dup() so that we can fclose without loosing the fd.
2862
2863 Note that the errno value set by a failing fdopen
2864 varies between stdio implementations.
2865 */
de009b76 2866 const int fd = PerlLIO_dup(fileno(stdio));
a33cf58c 2867 FILE *f2 = PerlSIO_fdopen(fd, (mode = "r+"));
4b069b44 2868 if (!f2) {
a33cf58c 2869 f2 = PerlSIO_fdopen(fd, (mode = "w"));
4b069b44
NIS
2870 }
2871 if (!f2) {
a33cf58c 2872 f2 = PerlSIO_fdopen(fd, (mode = "r"));
4b069b44
NIS
2873 }
2874 if (!f2) {
2875 /* Don't seem to be able to open */
2876 PerlLIO_close(fd);
2877 return f;
2878 }
2879 fclose(f2);
22569500 2880 }
a0714e2c 2881 if ((f = PerlIO_push(aTHX_(f = PerlIO_allocate(aTHX)), PERLIO_FUNCS_CAST(&PerlIO_stdio), mode, NULL))) {
a33cf58c
NIS
2882 s = PerlIOSelf(f, PerlIOStdio);
2883 s->stdio = stdio;
c586124f 2884 PerlIOUnix_refcnt_inc(fileno(stdio));
a33cf58c 2885 }
14a5cf38
JH
2886 }
2887 return f;
9e353e3b
NIS
2888}
2889
2890PerlIO *
14a5cf38
JH
2891PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
2892 IV n, const char *mode, int fd, int imode,
2893 int perm, PerlIO *f, int narg, SV **args)
2894{
2895 char tmode[8];
d9dac8cd 2896 if (PerlIOValid(f)) {
dcda55fc
AL
2897 const char * const path = SvPV_nolen_const(*args);
2898 PerlIOStdio * const s = PerlIOSelf(f, PerlIOStdio);
1751d015
NIS
2899 FILE *stdio;
2900 PerlIOUnix_refcnt_dec(fileno(s->stdio));
2901 stdio = PerlSIO_freopen(path, (mode = PerlIOStdio_mode(mode, tmode)),
14a5cf38
JH
2902 s->stdio);
2903 if (!s->stdio)
2904 return NULL;
2905 s->stdio = stdio;
1751d015 2906 PerlIOUnix_refcnt_inc(fileno(s->stdio));
14a5cf38
JH
2907 return f;
2908 }
2909 else {
2910 if (narg > 0) {
dcda55fc 2911 const char * const path = SvPV_nolen_const(*args);
3b6c1aba 2912 if (*mode == IoTYPE_NUMERIC) {
14a5cf38
JH
2913 mode++;
2914 fd = PerlLIO_open3(path, imode, perm);
2915 }
2916 else {
95005ad8
GH
2917 FILE *stdio;
2918 bool appended = FALSE;
2919#ifdef __CYGWIN__
2920 /* Cygwin wants its 'b' early. */
2921 appended = TRUE;
2922 mode = PerlIOStdio_mode(mode, tmode);
2923#endif
2924 stdio = PerlSIO_fopen(path, mode);
6f0313ac 2925 if (stdio) {
6f0313ac
JH
2926 if (!f) {
2927 f = PerlIO_allocate(aTHX);
2928 }
95005ad8
GH
2929 if (!appended)
2930 mode = PerlIOStdio_mode(mode, tmode);
2931 f = PerlIO_push(aTHX_ f, self, mode, PerlIOArg);
2932 if (f) {
0f0f9e2b
JH
2933 PerlIOSelf(f, PerlIOStdio)->stdio = stdio;
2934 PerlIOUnix_refcnt_inc(fileno(stdio));
2935 } else {
2936 PerlSIO_fclose(stdio);
6f0313ac
JH
2937 }
2938 return f;
2939 }
2940 else {
2941 return NULL;
2942 }
14a5cf38
JH
2943 }
2944 }
2945 if (fd >= 0) {
2946 FILE *stdio = NULL;
2947 int init = 0;
3b6c1aba 2948 if (*mode == IoTYPE_IMPLICIT) {
14a5cf38
JH
2949 init = 1;
2950 mode++;
2951 }
2952 if (init) {
2953 switch (fd) {
2954 case 0:
2955 stdio = PerlSIO_stdin;
2956 break;
2957 case 1:
2958 stdio = PerlSIO_stdout;
2959 break;
2960 case 2:
2961 stdio = PerlSIO_stderr;
2962 break;
2963 }
2964 }
2965 else {
2966 stdio = PerlSIO_fdopen(fd, mode =
2967 PerlIOStdio_mode(mode, tmode));
2968 }
2969 if (stdio) {
d9dac8cd
NIS
2970 if (!f) {
2971 f = PerlIO_allocate(aTHX);
2972 }
a33cf58c 2973 if ((f = PerlIO_push(aTHX_ f, self, mode, PerlIOArg))) {
1a159fba
JH
2974 PerlIOSelf(f, PerlIOStdio)->stdio = stdio;
2975 PerlIOUnix_refcnt_inc(fileno(stdio));
a33cf58c 2976 }
14a5cf38
JH
2977 return f;
2978 }
2979 }
2980 }
ee518936 2981 return NULL;
9e353e3b
NIS
2982}
2983
1751d015 2984PerlIO *
ecdeb87c 2985PerlIOStdio_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
1751d015
NIS
2986{
2987 /* This assumes no layers underneath - which is what
2988 happens, but is not how I remember it. NI-S 2001/10/16
2989 */
ecdeb87c 2990 if ((f = PerlIOBase_dup(aTHX_ f, o, param, flags))) {
694c95cf 2991 FILE *stdio = PerlIOSelf(o, PerlIOStdio)->stdio;
de009b76 2992 const int fd = fileno(stdio);
9217ff3f 2993 char mode[8];
ecdeb87c 2994 if (flags & PERLIO_DUP_FD) {
de009b76 2995 const int dfd = PerlLIO_dup(fileno(stdio));
9217ff3f
NIS
2996 if (dfd >= 0) {
2997 stdio = PerlSIO_fdopen(dfd, PerlIO_modestr(o,mode));
2998 goto set_this;
ecdeb87c
NIS
2999 }
3000 else {
6f207bd3 3001 NOOP;
ecdeb87c
NIS
3002 /* FIXME: To avoid messy error recovery if dup fails
3003 re-use the existing stdio as though flag was not set
3004 */
3005 }
3006 }
9217ff3f
NIS
3007 stdio = PerlSIO_fdopen(fd, PerlIO_modestr(o,mode));
3008 set_this:
694c95cf
JH
3009 PerlIOSelf(f, PerlIOStdio)->stdio = stdio;
3010 PerlIOUnix_refcnt_inc(fileno(stdio));
1751d015
NIS
3011 }
3012 return f;
3013}
3014
0d7a5398
NIS
3015static int
3016PerlIOStdio_invalidate_fileno(pTHX_ FILE *f)
3017{
96a5add6
AL
3018 PERL_UNUSED_CONTEXT;
3019
0d7a5398 3020 /* XXX this could use PerlIO_canset_fileno() and
37725cdc 3021 * PerlIO_set_fileno() support from Configure
0d7a5398 3022 */
ef8eacb8
AT
3023# if defined(__UCLIBC__)
3024 /* uClibc must come before glibc because it defines __GLIBC__ as well. */
3025 f->__filedes = -1;
3026 return 1;
3027# elif defined(__GLIBC__)
0d7a5398 3028 /* There may be a better way for GLIBC:
37725cdc 3029 - libio.h defines a flag to not close() on cleanup
0d7a5398
NIS
3030 */
3031 f->_fileno = -1;
3032 return 1;
3033# elif defined(__sun__)
f5992bc4 3034 PERL_UNUSED_ARG(f);
cfedb851 3035 return 0;
0d7a5398
NIS
3036# elif defined(__hpux)
3037 f->__fileH = 0xff;
3038 f->__fileL = 0xff;
3039 return 1;
9837d373 3040 /* Next one ->_file seems to be a reasonable fallback, i.e. if
37725cdc 3041 your platform does not have special entry try this one.
9837d373
NIS
3042 [For OSF only have confirmation for Tru64 (alpha)
3043 but assume other OSFs will be similar.]
37725cdc 3044 */
9837d373 3045# elif defined(_AIX) || defined(__osf__) || defined(__irix__)
0d7a5398
NIS
3046 f->_file = -1;
3047 return 1;
3048# elif defined(__FreeBSD__)
3049 /* There may be a better way on FreeBSD:
37725cdc
NIS
3050 - we could insert a dummy func in the _close function entry
3051 f->_close = (int (*)(void *)) dummy_close;
0d7a5398
NIS
3052 */
3053 f->_file = -1;
0c49ea6a
SU
3054 return 1;
3055# elif defined(__OpenBSD__)
3056 /* There may be a better way on OpenBSD:
3057 - we could insert a dummy func in the _close function entry
3058 f->_close = (int (*)(void *)) dummy_close;
3059 */
3060 f->_file = -1;
0d7a5398 3061 return 1;
59ad941d
IZ
3062# elif defined(__EMX__)
3063 /* f->_flags &= ~_IOOPEN; */ /* Will leak stream->_buffer */
3064 f->_handle = -1;
3065 return 1;
0d7a5398
NIS
3066# elif defined(__CYGWIN__)
3067 /* There may be a better way on CYGWIN:
37725cdc
NIS
3068 - we could insert a dummy func in the _close function entry
3069 f->_close = (int (*)(void *)) dummy_close;
0d7a5398
NIS
3070 */
3071 f->_file = -1;
3072 return 1;
3073# elif defined(WIN32)
3074# if defined(__BORLANDC__)
3075 f->fd = PerlLIO_dup(fileno(f));
b475b3e6
JH
3076# elif defined(UNDER_CE)
3077 /* WIN_CE does not have access to FILE internals, it hardly has FILE
3078 structure at all
3079 */
0d7a5398
NIS
3080# else
3081 f->_file = -1;
3082# endif
3083 return 1;
3084# else
3085#if 0
37725cdc 3086 /* Sarathy's code did this - we fall back to a dup/dup2 hack
0d7a5398 3087 (which isn't thread safe) instead
37725cdc 3088 */
0d7a5398
NIS
3089# error "Don't know how to set FILE.fileno on your platform"
3090#endif
8772537c 3091 PERL_UNUSED_ARG(f);
0d7a5398
NIS
3092 return 0;
3093# endif
3094}
3095
1751d015 3096IV
f62ce20a 3097PerlIOStdio_close(pTHX_ PerlIO *f)
1751d015 3098{
c4420975 3099 FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
439ba545
NIS
3100 if (!stdio) {
3101 errno = EBADF;
3102 return -1;
3103 }
9217ff3f 3104 else {
de009b76 3105 const int fd = fileno(stdio);
0d7a5398 3106 int invalidate = 0;
bbfd922f 3107 IV result = 0;
0d7a5398
NIS
3108 int saveerr = 0;
3109 int dupfd = 0;
3110#ifdef SOCKS5_VERSION_NAME
37725cdc
NIS
3111 /* Socks lib overrides close() but stdio isn't linked to
3112 that library (though we are) - so we must call close()
3113 on sockets on stdio's behalf.
3114 */
0d7a5398
NIS
3115 int optval;
3116 Sock_size_t optlen = sizeof(int);
6b4ce6c8 3117 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *) &optval, &optlen) == 0)
37725cdc 3118 invalidate = 1;
0d7a5398 3119#endif
6b4ce6c8 3120 if (PerlIOUnix_refcnt_dec(fd) > 0) /* File descriptor still in use */
0d7a5398 3121 invalidate = 1;
0d7a5398 3122 if (invalidate) {
6b4ce6c8
AL
3123 /* For STD* handles, don't close stdio, since we shared the FILE *, too. */
3124 if (stdio == stdin) /* Some stdios are buggy fflush-ing inputs */
3125 return 0;
3126 if (stdio == stdout || stdio == stderr)
3127 return PerlIO_flush(f);
37725cdc
NIS
3128 /* Tricky - must fclose(stdio) to free memory but not close(fd)
3129 Use Sarathy's trick from maint-5.6 to invalidate the
3130 fileno slot of the FILE *
3131 */
bbfd922f 3132 result = PerlIO_flush(f);
0d7a5398 3133 saveerr = errno;
6b4ce6c8
AL
3134 invalidate = PerlIOStdio_invalidate_fileno(aTHX_ stdio);
3135 if (!invalidate)
3136 dupfd = PerlLIO_dup(fd);
37725cdc 3137 }
0d7a5398 3138 result = PerlSIO_fclose(stdio);
37725cdc
NIS
3139 /* We treat error from stdio as success if we invalidated
3140 errno may NOT be expected EBADF
e8529473
NIS
3141 */
3142 if (invalidate && result != 0) {
0d7a5398
NIS
3143 errno = saveerr;
3144 result = 0;
37725cdc 3145 }
6b4ce6c8
AL
3146#ifdef SOCKS5_VERSION_NAME
3147 /* in SOCKS' case, let close() determine return value */
3148 result = close(fd);
3149#endif
0d7a5398
NIS
3150 if (dupfd) {
3151 PerlLIO_dup2(dupfd,fd);
8a521f28 3152 PerlLIO_close(dupfd);
9217ff3f
NIS
3153 }
3154 return result;
37725cdc 3155 }
1751d015
NIS
3156}
3157
9e353e3b 3158SSize_t
f62ce20a 3159PerlIOStdio_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
9e353e3b 3160{
97aff369 3161 dVAR;
c4420975 3162 FILE * const s = PerlIOSelf(f, PerlIOStdio)->stdio;
14a5cf38 3163 SSize_t got = 0;
4d948241
NIS
3164 for (;;) {
3165 if (count == 1) {
3166 STDCHAR *buf = (STDCHAR *) vbuf;
3167 /*
3168 * Perl is expecting PerlIO_getc() to fill the buffer Linux's
3169 * stdio does not do that for fread()
3170 */
de009b76 3171 const int ch = PerlSIO_fgetc(s);
4d948241
NIS
3172 if (ch != EOF) {
3173 *buf = ch;
3174 got = 1;
3175 }
14a5cf38 3176 }
4d948241
NIS
3177 else
3178 got = PerlSIO_fread(vbuf, 1, count, s);
b1d8b47a
CS
3179 if (got == 0 && PerlSIO_ferror(s))
3180 got = -1;
42a7a32f 3181 if (got >= 0 || errno != EINTR)
4d948241
NIS
3182 break;
3183 PERL_ASYNC_CHECK();
42a7a32f 3184 SETERRNO(0,0); /* just in case */
14a5cf38 3185 }
14a5cf38 3186 return got;
9e353e3b
NIS
3187}
3188
3189SSize_t
f62ce20a 3190PerlIOStdio_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
9e353e3b 3191{
14a5cf38 3192 SSize_t unread = 0;
c4420975 3193 FILE * const s = PerlIOSelf(f, PerlIOStdio)->stdio;
93679785 3194
313e59c8 3195#ifdef STDIO_BUFFER_WRITABLE
9f7cd136 3196 if (PerlIO_fast_gets(f) && PerlIO_has_base(f)) {
93679785
NIS
3197 STDCHAR *buf = ((STDCHAR *) vbuf) + count;
3198 STDCHAR *base = PerlIO_get_base(f);
3199 SSize_t cnt = PerlIO_get_cnt(f);
3200 STDCHAR *ptr = PerlIO_get_ptr(f);
3201 SSize_t avail = ptr - base;
3202 if (avail > 0) {
3203 if (avail > count) {
3204 avail = count;
3205 }
3206 ptr -= avail;
3207 Move(buf-avail,ptr,avail,STDCHAR);
3208 count -= avail;
3209 unread += avail;
3210 PerlIO_set_ptrcnt(f,ptr,cnt+avail);
9f7cd136
NIS
3211 if (PerlSIO_feof(s) && unread >= 0)
3212 PerlSIO_clearerr(s);
3213 }
3214 }
313e59c8
NIS
3215 else
3216#endif
3217 if (PerlIO_has_cntptr(f)) {
9f7cd136
NIS
3218 /* We can get pointer to buffer but not its base
3219 Do ungetc() but check chars are ending up in the
3220 buffer
3221 */
3222 STDCHAR *eptr = (STDCHAR*)PerlSIO_get_ptr(s);
3223 STDCHAR *buf = ((STDCHAR *) vbuf) + count;
3224 while (count > 0) {
de009b76 3225 const int ch = *--buf & 0xFF;
9f7cd136
NIS
3226 if (ungetc(ch,s) != ch) {
3227 /* ungetc did not work */
3228 break;
3229 }
3230 if ((STDCHAR*)PerlSIO_get_ptr(s) != --eptr || ((*eptr & 0xFF) != ch)) {
3231 /* Did not change pointer as expected */
3232 fgetc(s); /* get char back again */
3233 break;
3234 }
3235 /* It worked ! */
3236 count--;
3237 unread++;
93679785
NIS
3238 }
3239 }
3240
3241 if (count > 0) {
3242 unread += PerlIOBase_unread(aTHX_ f, vbuf, count);
14a5cf38
JH
3243 }
3244 return unread;
9e353e3b
NIS
3245}
3246
3247SSize_t
f62ce20a 3248PerlIOStdio_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
9e353e3b 3249{
97aff369 3250 dVAR;
4d948241
NIS
3251 SSize_t got;
3252 for (;;) {
3253 got = PerlSIO_fwrite(vbuf, 1, count,
3254 PerlIOSelf(f, PerlIOStdio)->stdio);
42a7a32f 3255 if (got >= 0 || errno != EINTR)
4d948241
NIS
3256 break;
3257 PERL_ASYNC_CHECK();
42a7a32f 3258 SETERRNO(0,0); /* just in case */
4d948241
NIS
3259 }
3260 return got;
9e353e3b
NIS
3261}
3262
94a175e1 3263IV
f62ce20a 3264PerlIOStdio_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
9e353e3b 3265{
c4420975 3266 FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
96a5add6
AL
3267 PERL_UNUSED_CONTEXT;
3268
94a175e1 3269 return PerlSIO_fseek(stdio, offset, whence);
9e353e3b
NIS
3270}
3271
3272Off_t
f62ce20a 3273PerlIOStdio_tell(pTHX_ PerlIO *f)
9e353e3b 3274{
c4420975 3275 FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
96a5add6
AL
3276 PERL_UNUSED_CONTEXT;
3277
94a175e1 3278 return PerlSIO_ftell(stdio);
9e353e3b
NIS
3279}
3280
3281IV
f62ce20a 3282PerlIOStdio_flush(pTHX_ PerlIO *f)
9e353e3b 3283{
c4420975 3284 FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
96a5add6
AL
3285 PERL_UNUSED_CONTEXT;
3286
14a5cf38
JH
3287 if (PerlIOBase(f)->flags & PERLIO_F_CANWRITE) {
3288 return PerlSIO_fflush(stdio);
3289 }
3290 else {
6f207bd3 3291 NOOP;
88b61e10 3292#if 0
14a5cf38
JH
3293 /*
3294 * FIXME: This discards ungetc() and pre-read stuff which is not
71200d45 3295 * right if this is just a "sync" from a layer above Suspect right
14a5cf38 3296 * design is to do _this_ but not have layer above flush this
71200d45 3297 * layer read-to-read
14a5cf38
JH
3298 */
3299 /*
71200d45 3300 * Not writeable - sync by attempting a seek
14a5cf38 3301 */
79852593 3302 const int err = errno;
14a5cf38
JH
3303 if (PerlSIO_fseek(stdio, (Off_t) 0, SEEK_CUR) != 0)
3304 errno = err;
88b61e10 3305#endif
14a5cf38
JH
3306 }
3307 return 0;
9e353e3b
NIS
3308}
3309
3310IV
f62ce20a 3311PerlIOStdio_eof(pTHX_ PerlIO *f)
9e353e3b 3312{
96a5add6
AL
3313 PERL_UNUSED_CONTEXT;
3314
14a5cf38 3315 return PerlSIO_feof(PerlIOSelf(f, PerlIOStdio)->stdio);
9e353e3b
NIS
3316}
3317
3318IV
f62ce20a 3319PerlIOStdio_error(pTHX_ PerlIO *f)
9e353e3b 3320{
96a5add6
AL
3321 PERL_UNUSED_CONTEXT;
3322
263df5f1 3323 return PerlSIO_ferror(PerlIOSelf(f, PerlIOStdio)->stdio);
9e353e3b
NIS
3324}
3325
3326void
f62ce20a 3327PerlIOStdio_clearerr(pTHX_ PerlIO *f)
9e353e3b 3328{
96a5add6
AL
3329 PERL_UNUSED_CONTEXT;
3330
14a5cf38 3331 PerlSIO_clearerr(PerlIOSelf(f, PerlIOStdio)->stdio);
9e353e3b
NIS
3332}
3333
3334void
f62ce20a 3335PerlIOStdio_setlinebuf(pTHX_ PerlIO *f)
9e353e3b 3336{
96a5add6
AL
3337 PERL_UNUSED_CONTEXT;
3338
9e353e3b 3339#ifdef HAS_SETLINEBUF
14a5cf38 3340 PerlSIO_setlinebuf(PerlIOSelf(f, PerlIOStdio)->stdio);
9e353e3b 3341#else
bd61b366 3342 PerlSIO_setvbuf(PerlIOSelf(f, PerlIOStdio)->stdio, NULL, _IOLBF, 0);
9e353e3b
NIS
3343#endif
3344}
3345
3346#ifdef FILE_base
3347STDCHAR *
f62ce20a 3348PerlIOStdio_get_base(pTHX_ PerlIO *f)
9e353e3b 3349{
c4420975 3350 FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
cc00df79 3351 return (STDCHAR*)PerlSIO_get_base(stdio);
9e353e3b
NIS
3352}
3353
3354Size_t
f62ce20a 3355PerlIOStdio_get_bufsiz(pTHX_ PerlIO *f)
9e353e3b 3356{
c4420975 3357 FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
14a5cf38 3358 return PerlSIO_get_bufsiz(stdio);
9e353e3b
NIS
3359}
3360#endif
3361
3362#ifdef USE_STDIO_PTR
3363STDCHAR *
f62ce20a 3364PerlIOStdio_get_ptr(pTHX_ PerlIO *f)
9e353e3b 3365{
c4420975 3366 FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
cc00df79 3367 return (STDCHAR*)PerlSIO_get_ptr(stdio);
9e353e3b
NIS
3368}
3369
3370SSize_t
f62ce20a 3371PerlIOStdio_get_cnt(pTHX_ PerlIO *f)
9e353e3b 3372{
c4420975 3373 FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
14a5cf38 3374 return PerlSIO_get_cnt(stdio);
9e353e3b
NIS
3375}
3376
3377void
f62ce20a 3378PerlIOStdio_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
9e353e3b 3379{
c4420975 3380 FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
14a5cf38 3381 if (ptr != NULL) {
9e353e3b 3382#ifdef STDIO_PTR_LVALUE
d06fc7d4 3383 PerlSIO_set_ptr(stdio, ptr); /* LHS STDCHAR* cast non-portable */
9e353e3b 3384#ifdef STDIO_PTR_LVAL_SETS_CNT
14a5cf38 3385 if (PerlSIO_get_cnt(stdio) != (cnt)) {
14a5cf38
JH
3386 assert(PerlSIO_get_cnt(stdio) == (cnt));
3387 }
9e353e3b
NIS
3388#endif
3389#if (!defined(STDIO_PTR_LVAL_NOCHANGE_CNT))
14a5cf38 3390 /*
71200d45 3391 * Setting ptr _does_ change cnt - we are done
14a5cf38
JH
3392 */
3393 return;
9e353e3b 3394#endif
22569500 3395#else /* STDIO_PTR_LVALUE */
14a5cf38 3396 PerlProc_abort();
22569500 3397#endif /* STDIO_PTR_LVALUE */
14a5cf38
JH
3398 }
3399 /*
71200d45 3400 * Now (or only) set cnt
14a5cf38 3401 */
9e353e3b 3402#ifdef STDIO_CNT_LVALUE
14a5cf38 3403 PerlSIO_set_cnt(stdio, cnt);
22569500 3404#else /* STDIO_CNT_LVALUE */
9e353e3b 3405#if (defined(STDIO_PTR_LVALUE) && defined(STDIO_PTR_LVAL_SETS_CNT))
14a5cf38
JH
3406 PerlSIO_set_ptr(stdio,
3407 PerlSIO_get_ptr(stdio) + (PerlSIO_get_cnt(stdio) -
3408 cnt));
22569500 3409#else /* STDIO_PTR_LVAL_SETS_CNT */
14a5cf38 3410 PerlProc_abort();
22569500
NIS
3411#endif /* STDIO_PTR_LVAL_SETS_CNT */
3412#endif /* STDIO_CNT_LVALUE */
9e353e3b
NIS
3413}
3414
93679785 3415
9e353e3b
NIS
3416#endif
3417
93679785
NIS
3418IV
3419PerlIOStdio_fill(pTHX_ PerlIO *f)
3420{
c4420975 3421 FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
93679785 3422 int c;
96a5add6
AL
3423 PERL_UNUSED_CONTEXT;
3424
93679785
NIS
3425 /*
3426 * fflush()ing read-only streams can cause trouble on some stdio-s
3427 */
3428 if ((PerlIOBase(f)->flags & PERLIO_F_CANWRITE)) {
3429 if (PerlSIO_fflush(stdio) != 0)
3430 return EOF;
3431 }
f3be3723
BL
3432 for (;;) {
3433 c = PerlSIO_fgetc(stdio);
3434 if (c != EOF)
3435 break;
3436 if (! PerlSIO_ferror(stdio) || errno != EINTR)
3437 return EOF;
3438 PERL_ASYNC_CHECK();
3439 SETERRNO(0,0);
3440 }
93679785
NIS
3441
3442#if (defined(STDIO_PTR_LVALUE) && (defined(STDIO_CNT_LVALUE) || defined(STDIO_PTR_LVAL_SETS_CNT)))
313e59c8
NIS
3443
3444#ifdef STDIO_BUFFER_WRITABLE
9f7cd136 3445 if (PerlIO_fast_gets(f) && PerlIO_has_base(f)) {
93679785
NIS
3446 /* Fake ungetc() to the real buffer in case system's ungetc
3447 goes elsewhere
3448 */
3449 STDCHAR *base = (STDCHAR*)PerlSIO_get_base(stdio);
3450 SSize_t cnt = PerlSIO_get_cnt(stdio);
3451 STDCHAR *ptr = (STDCHAR*)PerlSIO_get_ptr(stdio);
3452 if (ptr == base+1) {
3453 *--ptr = (STDCHAR) c;
3454 PerlIOStdio_set_ptrcnt(aTHX_ f,ptr,cnt+1);
3455 if (PerlSIO_feof(stdio))
3456 PerlSIO_clearerr(stdio);
3457 return 0;
3458 }
3459 }
313e59c8
NIS
3460 else
3461#endif
3462 if (PerlIO_has_cntptr(f)) {
9f7cd136
NIS
3463 STDCHAR ch = c;
3464 if (PerlIOStdio_unread(aTHX_ f,&ch,1) == 1) {
3465 return 0;
3466 }
3467 }
93679785
NIS
3468#endif
3469
3470#if defined(VMS)
3471 /* An ungetc()d char is handled separately from the regular
3472 * buffer, so we stuff it in the buffer ourselves.
3473 * Should never get called as should hit code above
3474 */
bad9695d
NIS
3475 *(--((*stdio)->_ptr)) = (unsigned char) c;
3476 (*stdio)->_cnt++;
93679785
NIS
3477#else
3478 /* If buffer snoop scheme above fails fall back to
9f7cd136 3479 using ungetc().
93679785
NIS
3480 */
3481 if (PerlSIO_ungetc(c, stdio) != c)
3482 return EOF;
3483#endif
3484 return 0;
3485}
3486
3487
3488
27da23d5 3489PERLIO_FUNCS_DECL(PerlIO_stdio) = {
2dc2558e 3490 sizeof(PerlIO_funcs),
14a5cf38
JH
3491 "stdio",
3492 sizeof(PerlIOStdio),
86e05cf2 3493 PERLIO_K_BUFFERED|PERLIO_K_RAW,
1fd8f4ce 3494 PerlIOStdio_pushed,
44798d05 3495 PerlIOBase_popped,
14a5cf38 3496 PerlIOStdio_open,
86e05cf2 3497 PerlIOBase_binmode, /* binmode */
14a5cf38
JH
3498 NULL,
3499 PerlIOStdio_fileno,
71200d45 3500 PerlIOStdio_dup,
14a5cf38
JH
3501 PerlIOStdio_read,
3502 PerlIOStdio_unread,
3503 PerlIOStdio_write,
3504 PerlIOStdio_seek,
3505 PerlIOStdio_tell,
3506 PerlIOStdio_close,
3507 PerlIOStdio_flush,
3508 PerlIOStdio_fill,
3509 PerlIOStdio_eof,
3510 PerlIOStdio_error,
3511 PerlIOStdio_clearerr,
3512 PerlIOStdio_setlinebuf,
9e353e3b 3513#ifdef FILE_base
14a5cf38
JH
3514 PerlIOStdio_get_base,
3515 PerlIOStdio_get_bufsiz,
9e353e3b 3516#else
14a5cf38
JH
3517 NULL,
3518 NULL,
9e353e3b
NIS
3519#endif
3520#ifdef USE_STDIO_PTR
14a5cf38
JH
3521 PerlIOStdio_get_ptr,
3522 PerlIOStdio_get_cnt,
15b61c98 3523# if defined(HAS_FAST_STDIO) && defined(USE_FAST_STDIO)
79ed0f43 3524 PerlIOStdio_set_ptrcnt,
15b61c98
JH
3525# else
3526 NULL,
3527# endif /* HAS_FAST_STDIO && USE_FAST_STDIO */
3528#else
3529 NULL,
14a5cf38
JH
3530 NULL,
3531 NULL,
15b61c98 3532#endif /* USE_STDIO_PTR */
9e353e3b
NIS
3533};
3534
b9d6bf13
JH
3535/* Note that calls to PerlIO_exportFILE() are reversed using
3536 * PerlIO_releaseFILE(), not importFILE. */
9e353e3b 3537FILE *
81428673 3538PerlIO_exportFILE(PerlIO * f, const char *mode)
9e353e3b 3539{
e87a358a 3540 dTHX;
81428673
NIS
3541 FILE *stdio = NULL;
3542 if (PerlIOValid(f)) {
3543 char buf[8];
3544 PerlIO_flush(f);
3545 if (!mode || !*mode) {
3546 mode = PerlIO_modestr(f, buf);
3547 }
3548 stdio = PerlSIO_fdopen(PerlIO_fileno(f), mode);
3549 if (stdio) {
3550 PerlIOl *l = *f;
9f75cc58 3551 PerlIO *f2;
81428673
NIS
3552 /* De-link any lower layers so new :stdio sticks */
3553 *f = NULL;
a0714e2c 3554 if ((f2 = PerlIO_push(aTHX_ f, PERLIO_FUNCS_CAST(&PerlIO_stdio), buf, NULL))) {
9f75cc58 3555 PerlIOStdio *s = PerlIOSelf((f = f2), PerlIOStdio);
81428673 3556 s->stdio = stdio;
6b54a403 3557 PerlIOUnix_refcnt_inc(fileno(stdio));
81428673
NIS
3558 /* Link previous lower layers under new one */
3559 *PerlIONext(f) = l;
3560 }
3561 else {
3562 /* restore layers list */
3563 *f = l;
3564 }
a33cf58c 3565 }
14a5cf38
JH
3566 }
3567 return stdio;
9e353e3b
NIS
3568}
3569
81428673 3570
9e353e3b
NIS
3571FILE *
3572PerlIO_findFILE(PerlIO *f)
3573{
14a5cf38
JH
3574 PerlIOl *l = *f;
3575 while (l) {
3576 if (l->tab == &PerlIO_stdio) {
3577 PerlIOStdio *s = PerlIOSelf(&l, PerlIOStdio);
3578 return s->stdio;
3579 }
3580 l = *PerlIONext(&l);
f7e7eb72 3581 }
4b069b44 3582 /* Uses fallback "mode" via PerlIO_modestr() in PerlIO_exportFILE */
bd61b366 3583 return PerlIO_exportFILE(f, NULL);
9e353e3b
NIS
3584}
3585
b9d6bf13 3586/* Use this to reverse PerlIO_exportFILE calls. */
9e353e3b
NIS
3587void
3588PerlIO_releaseFILE(PerlIO *p, FILE *f)
3589{
27da23d5 3590 dVAR;
22569500
NIS
3591 PerlIOl *l;
3592 while ((l = *p)) {
3593 if (l->tab == &PerlIO_stdio) {
3594 PerlIOStdio *s = PerlIOSelf(&l, PerlIOStdio);
3595 if (s->stdio == f) {
3596 dTHX;
6b54a403
NC
3597 const int fd = fileno(f);
3598 if (fd >= 0)
3599 PerlIOUnix_refcnt_dec(fd);
22569500
NIS
3600 PerlIO_pop(aTHX_ p);
3601 return;
3602 }
3603 }
3604 p = PerlIONext(p);
3605 }
3606 return;
9e353e3b
NIS
3607}
3608
3609/*--------------------------------------------------------------------------------------*/
14a5cf38 3610/*
71200d45 3611 * perlio buffer layer
14a5cf38 3612 */
9e353e3b 3613
5e2ab84b 3614IV
2dc2558e 3615PerlIOBuf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
5e2ab84b 3616{
14a5cf38 3617 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
de009b76 3618 const int fd = PerlIO_fileno(f);
14a5cf38
JH
3619 if (fd >= 0 && PerlLIO_isatty(fd)) {
3620 PerlIOBase(f)->flags |= PERLIO_F_LINEBUF | PERLIO_F_TTY;
3621 }
4b069b44 3622 if (*PerlIONext(f)) {
de009b76 3623 const Off_t posn = PerlIO_tell(PerlIONext(f));
4b069b44
NIS
3624 if (posn != (Off_t) - 1) {
3625 b->posn = posn;
3626 }
14a5cf38 3627 }
2dc2558e 3628 return PerlIOBase_pushed(aTHX_ f, mode, arg, tab);
5e2ab84b
NIS
3629}
3630
9e353e3b 3631PerlIO *
14a5cf38
JH
3632PerlIOBuf_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
3633 IV n, const char *mode, int fd, int imode, int perm,
3634 PerlIO *f, int narg, SV **args)
3635{
04892f78 3636 if (PerlIOValid(f)) {
14a5cf38 3637 PerlIO *next = PerlIONext(f);
67363c0d
JH
3638 PerlIO_funcs *tab =
3639 PerlIO_layer_fetch(aTHX_ layers, n - 1, PerlIOBase(next)->tab);
3640 if (tab && tab->Open)
3641 next =
3642 (*tab->Open)(aTHX_ tab, layers, n - 1, mode, fd, imode, perm,
3643 next, narg, args);
2dc2558e 3644 if (!next || (*PerlIOBase(f)->tab->Pushed) (aTHX_ f, mode, PerlIOArg, self) != 0) {
14a5cf38
JH
3645 return NULL;
3646 }
3647 }
3648 else {
04892f78 3649 PerlIO_funcs *tab = PerlIO_layer_fetch(aTHX_ layers, n - 1, PerlIO_default_btm());
14a5cf38 3650 int init = 0;
3b6c1aba 3651 if (*mode == IoTYPE_IMPLICIT) {
14a5cf38
JH
3652 init = 1;
3653 /*
71200d45 3654 * mode++;
14a5cf38
JH
3655 */
3656 }
67363c0d
JH
3657 if (tab && tab->Open)
3658 f = (*tab->Open)(aTHX_ tab, layers, n - 1, mode, fd, imode, perm,
3659 f, narg, args);
3660 else
3661 SETERRNO(EINVAL, LIB_INVARG);
14a5cf38 3662 if (f) {
22569500 3663 if (PerlIO_push(aTHX_ f, self, mode, PerlIOArg) == 0) {
b26b1ab5
NC
3664 /*
3665 * if push fails during open, open fails. close will pop us.
3666 */
3667 PerlIO_close (f);
3668 return NULL;
3669 } else {
3670 fd = PerlIO_fileno(f);
b26b1ab5
NC
3671 if (init && fd == 2) {
3672 /*
3673 * Initial stderr is unbuffered
3674 */
3675 PerlIOBase(f)->flags |= PERLIO_F_UNBUF;
3676 }
23b84778
IZ
3677#ifdef PERLIO_USING_CRLF
3678# ifdef PERLIO_IS_BINMODE_FD
3679 if (PERLIO_IS_BINMODE_FD(fd))
bd61b366 3680 PerlIO_binmode(aTHX_ f, '<'/*not used*/, O_BINARY, NULL);
23b84778
IZ
3681 else
3682# endif
3683 /*
3684 * do something about failing setmode()? --jhi
3685 */
3686 PerlLIO_setmode(fd, O_BINARY);
3687#endif
14a5cf38
JH
3688 }
3689 }
ee518936 3690 }
14a5cf38 3691 return f;
9e353e3b
NIS
3692}
3693
14a5cf38
JH
3694/*
3695 * This "flush" is akin to sfio's sync in that it handles files in either
93c2c2ec
IZ
3696 * read or write state. For write state, we put the postponed data through
3697 * the next layers. For read state, we seek() the next layers to the
3698 * offset given by current position in the buffer, and discard the buffer
3699 * state (XXXX supposed to be for seek()able buffers only, but now it is done
3700 * in any case?). Then the pass the stick further in chain.
14a5cf38 3701 */
9e353e3b 3702IV
f62ce20a 3703PerlIOBuf_flush(pTHX_ PerlIO *f)
6f9d8c32 3704{
dcda55fc 3705 PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
14a5cf38 3706 int code = 0;
04892f78 3707 PerlIO *n = PerlIONext(f);
14a5cf38
JH
3708 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF) {
3709 /*
71200d45 3710 * write() the buffer
14a5cf38 3711 */
de009b76
AL
3712 const STDCHAR *buf = b->buf;
3713 const STDCHAR *p = buf;
14a5cf38
JH
3714 while (p < b->ptr) {
3715 SSize_t count = PerlIO_write(n, p, b->ptr - p);
3716 if (count > 0) {
3717 p += count;
3718 }
3719 else if (count < 0 || PerlIO_error(n)) {
3720 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
3721 code = -1;
3722 break;
3723 }
3724 }
3725 b->posn += (p - buf);
3726 }
3727 else if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
3728 STDCHAR *buf = PerlIO_get_base(f);
3729 /*
71200d45 3730 * Note position change
14a5cf38
JH
3731 */
3732 b->posn += (b->ptr - buf);
3733 if (b->ptr < b->end) {
4b069b44
NIS
3734 /* We did not consume all of it - try and seek downstream to
3735 our logical position
14a5cf38 3736 */
4b069b44 3737 if (PerlIOValid(n) && PerlIO_seek(n, b->posn, SEEK_SET) == 0) {
04892f78
NIS
3738 /* Reload n as some layers may pop themselves on seek */
3739 b->posn = PerlIO_tell(n = PerlIONext(f));
14a5cf38 3740 }
ba5c3fe9 3741 else {
4b069b44
NIS
3742 /* Seek failed (e.g. pipe or tty). Do NOT clear buffer or pre-read
3743 data is lost for good - so return saying "ok" having undone
3744 the position adjust
3745 */
3746 b->posn -= (b->ptr - buf);
ba5c3fe9
NIS
3747 return code;
3748 }
14a5cf38
JH
3749 }
3750 }
3751 b->ptr = b->end = b->buf;
3752 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
04892f78 3753 /* We check for Valid because of dubious decision to make PerlIO_flush(NULL) flush all */
04892f78 3754 if (PerlIOValid(n) && PerlIO_flush(n) != 0)
14a5cf38
JH
3755 code = -1;
3756 return code;
6f9d8c32
NIS
3757}
3758
93c2c2ec
IZ
3759/* This discards the content of the buffer after b->ptr, and rereads
3760 * the buffer from the position off in the layer downstream; here off
3761 * is at offset corresponding to b->ptr - b->buf.
3762 */
06da4f11 3763IV
f62ce20a 3764PerlIOBuf_fill(pTHX_ PerlIO *f)
06da4f11 3765{
dcda55fc 3766 PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
14a5cf38
JH
3767 PerlIO *n = PerlIONext(f);
3768 SSize_t avail;
3769 /*
4b069b44
NIS
3770 * Down-stream flush is defined not to loose read data so is harmless.
3771 * we would not normally be fill'ing if there was data left in anycase.
14a5cf38 3772 */
93c2c2ec 3773 if (PerlIO_flush(f) != 0) /* XXXX Check that its seek() succeeded?! */
14a5cf38
JH
3774 return -1;
3775 if (PerlIOBase(f)->flags & PERLIO_F_TTY)
f62ce20a 3776 PerlIOBase_flush_linebuf(aTHX);
14a5cf38
JH
3777
3778 if (!b->buf)
22569500 3779 PerlIO_get_base(f); /* allocate via vtable */
14a5cf38 3780
0f0eef27 3781 assert(b->buf); /* The b->buf does get allocated via the vtable system. */
ec6fa4f0 3782
14a5cf38 3783 b->ptr = b->end = b->buf;
4b069b44
NIS
3784
3785 if (!PerlIOValid(n)) {
3786 PerlIOBase(f)->flags |= PERLIO_F_EOF;
3787 return -1;
3788 }
3789
14a5cf38
JH
3790 if (PerlIO_fast_gets(n)) {
3791 /*
04892f78 3792 * Layer below is also buffered. We do _NOT_ want to call its
14a5cf38
JH
3793 * ->Read() because that will loop till it gets what we asked for
3794 * which may hang on a pipe etc. Instead take anything it has to
71200d45 3795 * hand, or ask it to fill _once_.
14a5cf38
JH
3796 */
3797 avail = PerlIO_get_cnt(n);
3798 if (avail <= 0) {
3799 avail = PerlIO_fill(n);
3800 if (avail == 0)
3801 avail = PerlIO_get_cnt(n);
3802 else {
3803 if (!PerlIO_error(n) && PerlIO_eof(n))
3804 avail = 0;
3805 }
3806 }
3807 if (avail > 0) {
3808 STDCHAR *ptr = PerlIO_get_ptr(n);
dcda55fc 3809 const SSize_t cnt = avail;
eb160463 3810 if (avail > (SSize_t)b->bufsiz)
14a5cf38
JH
3811 avail = b->bufsiz;
3812 Copy(ptr, b->buf, avail, STDCHAR);
3813 PerlIO_set_ptrcnt(n, ptr + avail, cnt - avail);
3814 }
3815 }
3816 else {
3817 avail = PerlIO_read(n, b->ptr, b->bufsiz);
3818 }
3819 if (avail <= 0) {
3820 if (avail == 0)
3821 PerlIOBase(f)->flags |= PERLIO_F_EOF;
3822 else
3823 PerlIOBase(f)->flags |= PERLIO_F_ERROR;
3824 return -1;
3825 }
3826 b->end = b->buf + avail;
3827 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
3828 return 0;
06da4f11
NIS
3829}
3830
6f9d8c32 3831SSize_t
f62ce20a 3832PerlIOBuf_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
6f9d8c32 3833{
04892f78 3834 if (PerlIOValid(f)) {
dcda55fc 3835 const PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
14a5cf38
JH
3836 if (!b->ptr)
3837 PerlIO_get_base(f);
f62ce20a 3838 return PerlIOBase_read(aTHX_ f, vbuf, count);
14a5cf38
JH
3839 }
3840 return 0;
6f9d8c32
NIS
3841}
3842
9e353e3b 3843SSize_t
f62ce20a 3844PerlIOBuf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
760ac839 3845{
14a5cf38 3846 const STDCHAR *buf = (const STDCHAR *) vbuf + count;
dcda55fc 3847 PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
14a5cf38
JH
3848 SSize_t unread = 0;
3849 SSize_t avail;
3850 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
3851 PerlIO_flush(f);
3852 if (!b->buf)
3853 PerlIO_get_base(f);
3854 if (b->buf) {
3855 if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
3856 /*
3857 * Buffer is already a read buffer, we can overwrite any chars
71200d45 3858 * which have been read back to buffer start
14a5cf38
JH
3859 */
3860 avail = (b->ptr - b->buf);
3861 }
3862 else {
3863 /*
3864 * Buffer is idle, set it up so whole buffer is available for
71200d45 3865 * unread
14a5cf38
JH
3866 */
3867 avail = b->bufsiz;
3868 b->end = b->buf + avail;
3869 b->ptr = b->end;
3870 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
3871 /*
71200d45 3872 * Buffer extends _back_ from where we are now
14a5cf38
JH
3873 */
3874 b->posn -= b->bufsiz;
3875 }
3876 if (avail > (SSize_t) count) {
3877 /*
71200d45 3878 * If we have space for more than count, just move count
14a5cf38
JH
3879 */
3880 avail = count;
3881 }
3882 if (avail > 0) {
3883 b->ptr -= avail;
3884 buf -= avail;
3885 /*
3886 * In simple stdio-like ungetc() case chars will be already
71200d45 3887 * there
14a5cf38
JH
3888 */
3889 if (buf != b->ptr) {
3890 Copy(buf, b->ptr, avail, STDCHAR);
3891 }
3892 count -= avail;
3893 unread += avail;
3894 PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
3895 }
3896 }
93679785
NIS
3897 if (count > 0) {
3898 unread += PerlIOBase_unread(aTHX_ f, vbuf, count);
3899 }
14a5cf38 3900 return unread;
760ac839
LW
3901}
3902
9e353e3b 3903SSize_t
f62ce20a 3904PerlIOBuf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
760ac839 3905{
de009b76 3906 PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
14a5cf38 3907 const STDCHAR *buf = (const STDCHAR *) vbuf;
ee56a6b9 3908 const STDCHAR *flushptr = buf;
14a5cf38
JH
3909 Size_t written = 0;
3910 if (!b->buf)
3911 PerlIO_get_base(f);
3912 if (!(PerlIOBase(f)->flags & PERLIO_F_CANWRITE))
3913 return 0;
0678cb22
NIS
3914 if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
3915 if (PerlIO_flush(f) != 0) {
3916 return 0;
3917 }
3918 }
ee56a6b9
CS
3919 if (PerlIOBase(f)->flags & PERLIO_F_LINEBUF) {
3920 flushptr = buf + count;
3921 while (flushptr > buf && *(flushptr - 1) != '\n')
3922 --flushptr;
3923 }
14a5cf38
JH
3924 while (count > 0) {
3925 SSize_t avail = b->bufsiz - (b->ptr - b->buf);
3926 if ((SSize_t) count < avail)
3927 avail = count;
ee56a6b9
CS
3928 if (flushptr > buf && flushptr <= buf + avail)
3929 avail = flushptr - buf;
14a5cf38 3930 PerlIOBase(f)->flags |= PERLIO_F_WRBUF;
ee56a6b9
CS
3931 if (avail) {
3932 Copy(buf, b->ptr, avail, STDCHAR);
3933 count -= avail;
3934 buf += avail;
3935 written += avail;
3936 b->ptr += avail;
3937 if (buf == flushptr)
3938 PerlIO_flush(f);
14a5cf38
JH
3939 }
3940 if (b->ptr >= (b->buf + b->bufsiz))
3941 PerlIO_flush(f);
3942 }
3943 if (PerlIOBase(f)->flags & PERLIO_F_UNBUF)
3944 PerlIO_flush(f);
3945 return written;
9e353e3b
NIS
3946}
3947
94a175e1 3948IV
f62ce20a 3949PerlIOBuf_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
9e353e3b 3950{
14a5cf38
JH
3951 IV code;
3952 if ((code = PerlIO_flush(f)) == 0) {
14a5cf38
JH
3953 PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
3954 code = PerlIO_seek(PerlIONext(f), offset, whence);
3955 if (code == 0) {
de009b76 3956 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
14a5cf38
JH
3957 b->posn = PerlIO_tell(PerlIONext(f));
3958 }
9e353e3b 3959 }
14a5cf38 3960 return code;
9e353e3b
NIS
3961}
3962
3963Off_t
f62ce20a 3964PerlIOBuf_tell(pTHX_ PerlIO *f)
9e353e3b 3965{
dcda55fc 3966 PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
14a5cf38 3967 /*
71200d45 3968 * b->posn is file position where b->buf was read, or will be written
14a5cf38
JH
3969 */
3970 Off_t posn = b->posn;
37725cdc 3971 if ((PerlIOBase(f)->flags & PERLIO_F_APPEND) &&
0678cb22
NIS
3972 (PerlIOBase(f)->flags & PERLIO_F_WRBUF)) {
3973#if 1
3974 /* As O_APPEND files are normally shared in some sense it is better
3975 to flush :
3976 */
3977 PerlIO_flush(f);
3978#else
37725cdc 3979 /* when file is NOT shared then this is sufficient */
0678cb22
NIS
3980 PerlIO_seek(PerlIONext(f),0, SEEK_END);
3981#endif
3982 posn = b->posn = PerlIO_tell(PerlIONext(f));
3983 }
14a5cf38
JH
3984 if (b->buf) {
3985 /*
71200d45 3986 * If buffer is valid adjust position by amount in buffer
14a5cf38
JH
3987 */
3988 posn += (b->ptr - b->buf);
3989 }
3990 return posn;
9e353e3b
NIS
3991}
3992
3993IV
44798d05
NIS
3994PerlIOBuf_popped(pTHX_ PerlIO *f)
3995{
de009b76
AL
3996 const IV code = PerlIOBase_popped(aTHX_ f);
3997 PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
44798d05
NIS
3998 if (b->buf && b->buf != (STDCHAR *) & b->oneword) {
3999 Safefree(b->buf);
4000 }
dcda55fc 4001 b->ptr = b->end = b->buf = NULL;
44798d05
NIS
4002 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
4003 return code;
4004}
4005
4006IV
f62ce20a 4007PerlIOBuf_close(pTHX_ PerlIO *f)
9e353e3b 4008{
de009b76
AL
4009 const IV code = PerlIOBase_close(aTHX_ f);
4010 PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
14a5cf38 4011 if (b->buf && b->buf != (STDCHAR *) & b->oneword) {
3a1ee7e8 4012 Safefree(b->buf);
14a5cf38 4013 }
dcda55fc 4014 b->ptr = b->end = b->buf = NULL;
14a5cf38
JH
4015 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
4016 return code;
760ac839
LW
4017}
4018
9e353e3b 4019STDCHAR *
f62ce20a 4020PerlIOBuf_get_ptr(pTHX_ PerlIO *f)
9e353e3b 4021{
dcda55fc 4022 const PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
14a5cf38
JH
4023 if (!b->buf)
4024 PerlIO_get_base(f);
4025 return b->ptr;
9e353e3b
NIS
4026}
4027
05d1247b 4028SSize_t
f62ce20a 4029PerlIOBuf_get_cnt(pTHX_ PerlIO *f)
9e353e3b 4030{
dcda55fc 4031 const PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
14a5cf38
JH
4032 if (!b->buf)
4033 PerlIO_get_base(f);
4034 if (PerlIOBase(f)->flags & PERLIO_F_RDBUF)
4035 return (b->end - b->ptr);
4036 return 0;
9e353e3b
NIS
4037}
4038
4039STDCHAR *
f62ce20a 4040PerlIOBuf_get_base(pTHX_ PerlIO *f)
9e353e3b 4041{
dcda55fc 4042 PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
96a5add6
AL
4043 PERL_UNUSED_CONTEXT;
4044
14a5cf38
JH
4045 if (!b->buf) {
4046 if (!b->bufsiz)
4047 b->bufsiz = 4096;
a02a5408 4048 b->buf = Newxz(b->buf,b->bufsiz, STDCHAR);
14a5cf38
JH
4049 if (!b->buf) {
4050 b->buf = (STDCHAR *) & b->oneword;
4051 b->bufsiz = sizeof(b->oneword);
4052 }
dcda55fc 4053 b->end = b->ptr = b->buf;
06da4f11 4054 }
14a5cf38 4055 return b->buf;
9e353e3b
NIS
4056}
4057
4058Size_t
f62ce20a 4059PerlIOBuf_bufsiz(pTHX_ PerlIO *f)
9e353e3b 4060{
dcda55fc 4061 const PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
14a5cf38
JH
4062 if (!b->buf)
4063 PerlIO_get_base(f);
4064 return (b->end - b->buf);
9e353e3b
NIS
4065}
4066
4067void
f62ce20a 4068PerlIOBuf_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
9e353e3b 4069{
dcda55fc 4070 PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
14a5cf38
JH
4071 if (!b->buf)
4072 PerlIO_get_base(f);
4073 b->ptr = ptr;
4074 if (PerlIO_get_cnt(f) != cnt || b->ptr < b->buf) {
14a5cf38
JH
4075 assert(PerlIO_get_cnt(f) == cnt);
4076 assert(b->ptr >= b->buf);
4077 }
4078 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
760ac839
LW
4079}
4080
71200d45 4081PerlIO *
ecdeb87c 4082PerlIOBuf_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
71200d45 4083{
ecdeb87c 4084 return PerlIOBase_dup(aTHX_ f, o, param, flags);
71200d45
NIS
4085}
4086
4087
4088
27da23d5 4089PERLIO_FUNCS_DECL(PerlIO_perlio) = {
2dc2558e 4090 sizeof(PerlIO_funcs),
14a5cf38
JH
4091 "perlio",
4092 sizeof(PerlIOBuf),
86e05cf2 4093 PERLIO_K_BUFFERED|PERLIO_K_RAW,
14a5cf38 4094 PerlIOBuf_pushed,
44798d05 4095 PerlIOBuf_popped,
14a5cf38 4096 PerlIOBuf_open,
86e05cf2 4097 PerlIOBase_binmode, /* binmode */
14a5cf38
JH
4098 NULL,
4099 PerlIOBase_fileno,
71200d45 4100 PerlIOBuf_dup,
14a5cf38
JH
4101 PerlIOBuf_read,
4102 PerlIOBuf_unread,
4103 PerlIOBuf_write,
4104 PerlIOBuf_seek,
4105 PerlIOBuf_tell,
4106 PerlIOBuf_close,
4107 PerlIOBuf_flush,
4108 PerlIOBuf_fill,
4109 PerlIOBase_eof,
4110 PerlIOBase_error,
4111 PerlIOBase_clearerr,
4112 PerlIOBase_setlinebuf,
4113 PerlIOBuf_get_base,
4114 PerlIOBuf_bufsiz,
4115 PerlIOBuf_get_ptr,
4116 PerlIOBuf_get_cnt,
4117 PerlIOBuf_set_ptrcnt,
9e353e3b
NIS
4118};
4119
66ecd56b 4120/*--------------------------------------------------------------------------------------*/
14a5cf38 4121/*
71200d45 4122 * Temp layer to hold unread chars when cannot do it any other way
14a5cf38 4123 */
5e2ab84b
NIS
4124
4125IV
f62ce20a 4126PerlIOPending_fill(pTHX_ PerlIO *f)
5e2ab84b 4127{
14a5cf38 4128 /*
71200d45 4129 * Should never happen
14a5cf38
JH
4130 */
4131 PerlIO_flush(f);
4132 return 0;
5e2ab84b
NIS
4133}
4134
4135IV
f62ce20a 4136PerlIOPending_close(pTHX_ PerlIO *f)
5e2ab84b 4137{
14a5cf38 4138 /*
71200d45 4139 * A tad tricky - flush pops us, then we close new top
14a5cf38
JH
4140 */
4141 PerlIO_flush(f);
4142 return PerlIO_close(f);
5e2ab84b
NIS
4143}
4144
94a175e1 4145IV
f62ce20a 4146PerlIOPending_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
5e2ab84b 4147{
14a5cf38 4148 /*
71200d45 4149 * A tad tricky - flush pops us, then we seek new top
14a5cf38
JH
4150 */
4151 PerlIO_flush(f);
4152 return PerlIO_seek(f, offset, whence);
5e2ab84b
NIS
4153}
4154
4155
4156IV
f62ce20a 4157PerlIOPending_flush(pTHX_ PerlIO *f)
5e2ab84b 4158{
dcda55fc 4159 PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
14a5cf38 4160 if (b->buf && b->buf != (STDCHAR *) & b->oneword) {
3a1ee7e8 4161 Safefree(b->buf);
14a5cf38
JH
4162 b->buf = NULL;
4163 }
4164 PerlIO_pop(aTHX_ f);
4165 return 0;
5e2ab84b
NIS
4166}
4167
4168void
f62ce20a 4169PerlIOPending_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
5e2ab84b 4170{
14a5cf38
JH
4171 if (cnt <= 0) {
4172 PerlIO_flush(f);
4173 }
4174 else {
f62ce20a 4175 PerlIOBuf_set_ptrcnt(aTHX_ f, ptr, cnt);
14a5cf38 4176 }
5e2ab84b
NIS
4177}
4178
4179IV
2dc2558e 4180PerlIOPending_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
5e2ab84b 4181{
de009b76 4182 const IV code = PerlIOBase_pushed(aTHX_ f, mode, arg, tab);
dcda55fc 4183 PerlIOl * const l = PerlIOBase(f);
14a5cf38 4184 /*
71200d45
NIS
4185 * Our PerlIO_fast_gets must match what we are pushed on, or sv_gets()
4186 * etc. get muddled when it changes mid-string when we auto-pop.
14a5cf38
JH
4187 */
4188 l->flags = (l->flags & ~(PERLIO_F_FASTGETS | PERLIO_F_UTF8)) |
4189 (PerlIOBase(PerlIONext(f))->
4190 flags & (PERLIO_F_FASTGETS | PERLIO_F_UTF8));
4191 return code;
5e2ab84b
NIS
4192}
4193
4194SSize_t
f62ce20a 4195PerlIOPending_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
5e2ab84b 4196{
14a5cf38
JH
4197 SSize_t avail = PerlIO_get_cnt(f);
4198 SSize_t got = 0;
eb160463 4199 if ((SSize_t)count < avail)
14a5cf38
JH
4200 avail = count;
4201 if (avail > 0)
f62ce20a 4202 got = PerlIOBuf_read(aTHX_ f, vbuf, avail);
eb160463 4203 if (got >= 0 && got < (SSize_t)count) {
de009b76 4204 const SSize_t more =
14a5cf38
JH
4205 PerlIO_read(f, ((STDCHAR *) vbuf) + got, count - got);
4206 if (more >= 0 || got == 0)
4207 got += more;
4208 }
4209 return got;
5e2ab84b
NIS
4210}
4211
27da23d5 4212PERLIO_FUNCS_DECL(PerlIO_pending) = {
2dc2558e 4213 sizeof(PerlIO_funcs),
14a5cf38
JH
4214 "pending",
4215 sizeof(PerlIOBuf),
86e05cf2 4216 PERLIO_K_BUFFERED|PERLIO_K_RAW, /* not sure about RAW here */
14a5cf38 4217 PerlIOPending_pushed,
44798d05 4218 PerlIOBuf_popped,
14a5cf38 4219 NULL,
86e05cf2 4220 PerlIOBase_binmode, /* binmode */
14a5cf38
JH
4221 NULL,
4222 PerlIOBase_fileno,
71200d45 4223 PerlIOBuf_dup,
14a5cf38
JH
4224 PerlIOPending_read,
4225 PerlIOBuf_unread,
4226 PerlIOBuf_write,
4227 PerlIOPending_seek,
4228 PerlIOBuf_tell,
4229 PerlIOPending_close,
4230 PerlIOPending_flush,
4231 PerlIOPending_fill,
4232 PerlIOBase_eof,
4233 PerlIOBase_error,
4234 PerlIOBase_clearerr,
4235 PerlIOBase_setlinebuf,
4236 PerlIOBuf_get_base,
4237 PerlIOBuf_bufsiz,
4238 PerlIOBuf_get_ptr,
4239 PerlIOBuf_get_cnt,
4240 PerlIOPending_set_ptrcnt,
5e2ab84b
NIS
4241};
4242
4243
4244
4245/*--------------------------------------------------------------------------------------*/
14a5cf38
JH
4246/*
4247 * crlf - translation On read translate CR,LF to "\n" we do this by
4248 * overriding ptr/cnt entries to hand back a line at a time and keeping a
71200d45 4249 * record of which nl we "lied" about. On write translate "\n" to CR,LF
93c2c2ec
IZ
4250 *
4251 * c->nl points on the first byte of CR LF pair when it is temporarily
4252 * replaced by LF, or to the last CR of the buffer. In the former case
4253 * the caller thinks that the buffer ends at c->nl + 1, in the latter
4254 * that it ends at c->nl; these two cases can be distinguished by
4255 * *c->nl. c->nl is set during _getcnt() call, and unset during
4256 * _unread() and _flush() calls.
4257 * It only matters for read operations.
66ecd56b
NIS
4258 */
4259
14a5cf38 4260typedef struct {
22569500
NIS
4261 PerlIOBuf base; /* PerlIOBuf stuff */
4262 STDCHAR *nl; /* Position of crlf we "lied" about in the
14a5cf38 4263 * buffer */
99efab12
NIS
4264} PerlIOCrlf;
4265
ff1e3883
JD
4266/* Inherit the PERLIO_F_UTF8 flag from previous layer.
4267 * Otherwise the :crlf layer would always revert back to
4268 * raw mode.
4269 */
4270static void
4271S_inherit_utf8_flag(PerlIO *f)
4272{
4273 PerlIO *g = PerlIONext(f);
4274 if (PerlIOValid(g)) {
4275 if (PerlIOBase(g)->flags & PERLIO_F_UTF8) {
4276 PerlIOBase(f)->flags |= PERLIO_F_UTF8;
4277 }
4278 }
4279}
4280
f5b9d040 4281IV
2dc2558e 4282PerlIOCrlf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
f5b9d040 4283{
14a5cf38
JH
4284 IV code;
4285 PerlIOBase(f)->flags |= PERLIO_F_CRLF;
2dc2558e 4286 code = PerlIOBuf_pushed(aTHX_ f, mode, arg, tab);
5e2ab84b 4287#if 0
14a5cf38 4288 PerlIO_debug("PerlIOCrlf_pushed f=%p %s %s fl=%08" UVxf "\n",
6c9570dc 4289 (void*)f, PerlIOBase(f)->tab->name, (mode) ? mode : "(Null)",
14a5cf38 4290 PerlIOBase(f)->flags);
5e2ab84b 4291#endif
8229d19f
JH
4292 {
4293 /* Enable the first CRLF capable layer you can find, but if none
4294 * found, the one we just pushed is fine. This results in at
4295 * any given moment at most one CRLF-capable layer being enabled
4296 * in the whole layer stack. */
4297 PerlIO *g = PerlIONext(f);
ff1e3883 4298 while (PerlIOValid(g)) {
8229d19f
JH
4299 PerlIOl *b = PerlIOBase(g);
4300 if (b && b->tab == &PerlIO_crlf) {
4301 if (!(b->flags & PERLIO_F_CRLF))
4302 b->flags |= PERLIO_F_CRLF;
ff1e3883 4303 S_inherit_utf8_flag(g);
8229d19f
JH
4304 PerlIO_pop(aTHX_ f);
4305 return code;
4306 }
4307 g = PerlIONext(g);
4308 }
4309 }
ff1e3883 4310 S_inherit_utf8_flag(f);
14a5cf38 4311 return code;
f5b9d040
NIS
4312}
4313
4314
99efab12 4315SSize_t
f62ce20a 4316PerlIOCrlf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
99efab12 4317{
dcda55fc 4318 PerlIOCrlf * const c = PerlIOSelf(f, PerlIOCrlf);
93c2c2ec 4319 if (c->nl) { /* XXXX Shouldn't it be done only if b->ptr > c->nl? */
14a5cf38
JH
4320 *(c->nl) = 0xd;
4321 c->nl = NULL;
4322 }
4323 if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF))
f62ce20a 4324 return PerlIOBuf_unread(aTHX_ f, vbuf, count);
14a5cf38
JH
4325 else {
4326 const STDCHAR *buf = (const STDCHAR *) vbuf + count;
4327 PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
4328 SSize_t unread = 0;
4329 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
4330 PerlIO_flush(f);
4331 if (!b->buf)
4332 PerlIO_get_base(f);
4333 if (b->buf) {
4334 if (!(PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
4335 b->end = b->ptr = b->buf + b->bufsiz;
4336 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
4337 b->posn -= b->bufsiz;
4338 }
4339 while (count > 0 && b->ptr > b->buf) {
dcda55fc 4340 const int ch = *--buf;
14a5cf38
JH
4341 if (ch == '\n') {
4342 if (b->ptr - 2 >= b->buf) {
4343 *--(b->ptr) = 0xa;
4344 *--(b->ptr) = 0xd;
4345 unread++;
4346 count--;
4347 }
4348 else {
93c2c2ec
IZ
4349 /* If b->ptr - 1 == b->buf, we are undoing reading 0xa */
4350 *--(b->ptr) = 0xa; /* Works even if 0xa == '\r' */
4351 unread++;
4352 count--;
14a5cf38
JH
4353 }
4354 }
4355 else {
4356 *--(b->ptr) = ch;
4357 unread++;
4358 count--;
4359 }
4360 }
4361 }
4362 return unread;
4363 }
99efab12
NIS
4364}
4365
93c2c2ec 4366/* XXXX This code assumes that buffer size >=2, but does not check it... */
99efab12 4367SSize_t
f62ce20a 4368PerlIOCrlf_get_cnt(pTHX_ PerlIO *f)
99efab12 4369{
dcda55fc 4370 PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
14a5cf38
JH
4371 if (!b->buf)
4372 PerlIO_get_base(f);
4373 if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) {
dcda55fc 4374 PerlIOCrlf * const c = PerlIOSelf(f, PerlIOCrlf);
23b3c6af
NIS
4375 if ((PerlIOBase(f)->flags & PERLIO_F_CRLF) && (!c->nl || *c->nl == 0xd)) {
4376 STDCHAR *nl = (c->nl) ? c->nl : b->ptr;
14a5cf38
JH
4377 scan:
4378 while (nl < b->end && *nl != 0xd)
4379 nl++;
4380 if (nl < b->end && *nl == 0xd) {
4381 test:
4382 if (nl + 1 < b->end) {
4383 if (nl[1] == 0xa) {
4384 *nl = '\n';
4385 c->nl = nl;
4386 }
4387 else {
4388 /*
71200d45 4389 * Not CR,LF but just CR
14a5cf38
JH
4390 */
4391 nl++;
4392 goto scan;
4393 }
4394 }
4395 else {
4396 /*
71200d45 4397 * Blast - found CR as last char in buffer
14a5cf38 4398 */
e87a358a 4399
14a5cf38
JH
4400 if (b->ptr < nl) {
4401 /*
4402 * They may not care, defer work as long as
71200d45 4403 * possible
14a5cf38 4404 */
a0d1d361 4405 c->nl = nl;
14a5cf38
JH
4406 return (nl - b->ptr);
4407 }
4408 else {
4409 int code;
22569500 4410 b->ptr++; /* say we have read it as far as
14a5cf38 4411 * flush() is concerned */
22569500 4412 b->buf++; /* Leave space in front of buffer */
e949e37c
NIS
4413 /* Note as we have moved buf up flush's
4414 posn += ptr-buf
4415 will naturally make posn point at CR
4416 */
22569500
NIS
4417 b->bufsiz--; /* Buffer is thus smaller */
4418 code = PerlIO_fill(f); /* Fetch some more */
4419 b->bufsiz++; /* Restore size for next time */
4420 b->buf--; /* Point at space */
4421 b->ptr = nl = b->buf; /* Which is what we hand
14a5cf38 4422 * off */
22569500 4423 *nl = 0xd; /* Fill in the CR */
14a5cf38 4424 if (code == 0)
22569500 4425 goto test; /* fill() call worked */
14a5cf38 4426 /*
71200d45 4427 * CR at EOF - just fall through
14a5cf38 4428 */
a0d1d361 4429 /* Should we clear EOF though ??? */
14a5cf38
JH
4430 }
4431 }
4432 }
4433 }
4434 return (((c->nl) ? (c->nl + 1) : b->end) - b->ptr);
4435 }
4436 return 0;
99efab12
NIS
4437}
4438
4439void
f62ce20a 4440PerlIOCrlf_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
14a5cf38 4441{
dcda55fc
AL
4442 PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
4443 PerlIOCrlf * const c = PerlIOSelf(f, PerlIOCrlf);
14a5cf38
JH
4444 if (!b->buf)
4445 PerlIO_get_base(f);
4446 if (!ptr) {
a0d1d361 4447 if (c->nl) {
14a5cf38 4448 ptr = c->nl + 1;
22569500 4449 if (ptr == b->end && *c->nl == 0xd) {
a0d1d361 4450 /* Defered CR at end of buffer case - we lied about count */
22569500
NIS
4451 ptr--;
4452 }
4453 }
14a5cf38
JH
4454 else {
4455 ptr = b->end;
14a5cf38
JH
4456 }
4457 ptr -= cnt;
4458 }
4459 else {
6f207bd3 4460 NOOP;
3b4bd3fd 4461#if 0
14a5cf38 4462 /*
71200d45 4463 * Test code - delete when it works ...
14a5cf38 4464 */
3b4bd3fd 4465 IV flags = PerlIOBase(f)->flags;
ba7abf9d 4466 STDCHAR *chk = (c->nl) ? (c->nl+1) : b->end;
22569500 4467 if (ptr+cnt == c->nl && c->nl+1 == b->end && *c->nl == 0xd) {
a0d1d361
NIS
4468 /* Defered CR at end of buffer case - we lied about count */
4469 chk--;
22569500 4470 }
14a5cf38
JH
4471 chk -= cnt;
4472
a0d1d361 4473 if (ptr != chk ) {
99ef548b 4474 Perl_croak(aTHX_ "ptr wrong %p != %p fl=%08" UVxf
6c9570dc
MHM
4475 " nl=%p e=%p for %d", (void*)ptr, (void*)chk,
4476 flags, c->nl, b->end, cnt);
14a5cf38 4477 }
99ef548b 4478#endif
14a5cf38
JH
4479 }
4480 if (c->nl) {
4481 if (ptr > c->nl) {
4482 /*
71200d45 4483 * They have taken what we lied about
14a5cf38
JH
4484 */
4485 *(c->nl) = 0xd;
4486 c->nl = NULL;
4487 ptr++;
4488 }
4489 }
4490 b->ptr = ptr;
4491 PerlIOBase(f)->flags |= PERLIO_F_RDBUF;
99efab12
NIS
4492}
4493
4494SSize_t
f62ce20a 4495PerlIOCrlf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
99efab12 4496{
14a5cf38 4497 if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF))
f62ce20a 4498 return PerlIOBuf_write(aTHX_ f, vbuf, count);
14a5cf38 4499 else {
dcda55fc 4500 PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
14a5cf38 4501 const STDCHAR *buf = (const STDCHAR *) vbuf;
dcda55fc 4502 const STDCHAR * const ebuf = buf + count;
14a5cf38
JH
4503 if (!b->buf)
4504 PerlIO_get_base(f);
4505 if (!(PerlIOBase(f)->flags & PERLIO_F_CANWRITE))
4506 return 0;
4507 while (buf < ebuf) {
dcda55fc 4508 const STDCHAR * const eptr = b->buf + b->bufsiz;
14a5cf38
JH
4509 PerlIOBase(f)->flags |= PERLIO_F_WRBUF;
4510 while (buf < ebuf && b->ptr < eptr) {
4511 if (*buf == '\n') {
4512 if ((b->ptr + 2) > eptr) {
4513 /*
71200d45 4514 * Not room for both
14a5cf38
JH
4515 */
4516 PerlIO_flush(f);
4517 break;
4518 }
4519 else {
22569500
NIS
4520 *(b->ptr)++ = 0xd; /* CR */
4521 *(b->ptr)++ = 0xa; /* LF */
14a5cf38
JH
4522 buf++;
4523 if (PerlIOBase(f)->flags & PERLIO_F_LINEBUF) {
4524 PerlIO_flush(f);
4525 break;
4526 }
4527 }
4528 }
4529 else {
dcda55fc 4530 *(b->ptr)++ = *buf++;
14a5cf38
JH
4531 }
4532 if (b->ptr >= eptr) {
4533 PerlIO_flush(f);
4534 break;
4535 }
4536 }
4537 }
4538 if (PerlIOBase(f)->flags & PERLIO_F_UNBUF)
4539 PerlIO_flush(f);
4540 return (buf - (STDCHAR *) vbuf);
4541 }
99efab12
NIS
4542}
4543
4544IV
f62ce20a 4545PerlIOCrlf_flush(pTHX_ PerlIO *f)
99efab12 4546{
dcda55fc 4547 PerlIOCrlf * const c = PerlIOSelf(f, PerlIOCrlf);
14a5cf38
JH
4548 if (c->nl) {
4549 *(c->nl) = 0xd;
4550 c->nl = NULL;
4551 }
f62ce20a 4552 return PerlIOBuf_flush(aTHX_ f);
99efab12
NIS
4553}
4554
86e05cf2
NIS
4555IV
4556PerlIOCrlf_binmode(pTHX_ PerlIO *f)
4557{
4558 if ((PerlIOBase(f)->flags & PERLIO_F_CRLF)) {
4559 /* In text mode - flush any pending stuff and flip it */
4560 PerlIOBase(f)->flags &= ~PERLIO_F_CRLF;
4561#ifndef PERLIO_USING_CRLF
4562 /* CRLF is unusual case - if this is just the :crlf layer pop it */
4563 if (PerlIOBase(f)->tab == &PerlIO_crlf) {
4564 PerlIO_pop(aTHX_ f);
4565 }
4566#endif
4567 }
4568 return 0;
4569}
4570
27da23d5 4571PERLIO_FUNCS_DECL(PerlIO_crlf) = {
2dc2558e 4572 sizeof(PerlIO_funcs),
14a5cf38
JH
4573 "crlf",
4574 sizeof(PerlIOCrlf),
86e05cf2 4575 PERLIO_K_BUFFERED | PERLIO_K_CANCRLF | PERLIO_K_RAW,
14a5cf38 4576 PerlIOCrlf_pushed,
44798d05 4577 PerlIOBuf_popped, /* popped */
14a5cf38 4578 PerlIOBuf_open,
86e05cf2 4579 PerlIOCrlf_binmode, /* binmode */
14a5cf38
JH
4580 NULL,
4581 PerlIOBase_fileno,
71200d45 4582 PerlIOBuf_dup,
de009b76 4583 PerlIOBuf_read, /* generic read works with ptr/cnt lies */
22569500
NIS
4584 PerlIOCrlf_unread, /* Put CR,LF in buffer for each '\n' */
4585 PerlIOCrlf_write, /* Put CR,LF in buffer for each '\n' */
14a5cf38
JH
4586 PerlIOBuf_seek,
4587 PerlIOBuf_tell,
4588 PerlIOBuf_close,
4589 PerlIOCrlf_flush,
4590 PerlIOBuf_fill,
4591 PerlIOBase_eof,
4592 PerlIOBase_error,
4593 PerlIOBase_clearerr,
4594 PerlIOBase_setlinebuf,
4595 PerlIOBuf_get_base,
4596 PerlIOBuf_bufsiz,
4597 PerlIOBuf_get_ptr,
4598 PerlIOCrlf_get_cnt,
4599 PerlIOCrlf_set_ptrcnt,
66ecd56b
NIS
4600};
4601
06da4f11
NIS
4602#ifdef HAS_MMAP
4603/*--------------------------------------------------------------------------------------*/
14a5cf38 4604/*
71200d45 4605 * mmap as "buffer" layer
14a5cf38 4606 */
06da4f11 4607
14a5cf38 4608typedef struct {
22569500
NIS
4609 PerlIOBuf base; /* PerlIOBuf stuff */
4610 Mmap_t mptr; /* Mapped address */
4611 Size_t len; /* mapped length */
4612 STDCHAR *bbuf; /* malloced buffer if map fails */
06da4f11
NIS
4613} PerlIOMmap;
4614
4615IV
f62ce20a 4616PerlIOMmap_map(pTHX_ PerlIO *f)
06da4f11 4617{
27da23d5 4618 dVAR;
de009b76
AL
4619 PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
4620 const IV flags = PerlIOBase(f)->flags;
14a5cf38
JH
4621 IV code = 0;
4622 if (m->len)
4623 abort();
4624 if (flags & PERLIO_F_CANREAD) {
dcda55fc 4625 PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
de009b76 4626 const int fd = PerlIO_fileno(f);
10eefe7f
CB
4627 Stat_t st;
4628 code = Fstat(fd, &st);
14a5cf38
JH
4629 if (code == 0 && S_ISREG(st.st_mode)) {
4630 SSize_t len = st.st_size - b->posn;
4631 if (len > 0) {
4632 Off_t posn;
27da23d5
JH
4633 if (PL_mmap_page_size <= 0)
4634 Perl_croak(aTHX_ "panic: bad pagesize %" IVdf,
4635 PL_mmap_page_size);
14a5cf38
JH
4636 if (b->posn < 0) {
4637 /*
4638 * This is a hack - should never happen - open should
71200d45 4639 * have set it !
14a5cf38
JH
4640 */
4641 b->posn = PerlIO_tell(PerlIONext(f));
4642 }
27da23d5 4643 posn = (b->posn / PL_mmap_page_size) * PL_mmap_page_size;
14a5cf38 4644 len = st.st_size - posn;
b91fbb93 4645 m->mptr = (Mmap_t)mmap(NULL, len, PROT_READ, MAP_SHARED, fd, posn);
14a5cf38 4646 if (m->mptr && m->mptr != (Mmap_t) - 1) {
a5262162 4647#if 0 && defined(HAS_MADVISE) && defined(MADV_SEQUENTIAL)
14a5cf38 4648 madvise(m->mptr, len, MADV_SEQUENTIAL);
06da4f11 4649#endif
a5262162 4650#if 0 && defined(HAS_MADVISE) && defined(MADV_WILLNEED)
14a5cf38 4651 madvise(m->mptr, len, MADV_WILLNEED);
a5262162 4652#endif
14a5cf38
JH
4653 PerlIOBase(f)->flags =
4654 (flags & ~PERLIO_F_EOF) | PERLIO_F_RDBUF;
4655 b->end = ((STDCHAR *) m->mptr) + len;
4656 b->buf = ((STDCHAR *) m->mptr) + (b->posn - posn);
4657 b->ptr = b->buf;
4658 m->len = len;
4659 }
4660 else {
4661 b->buf = NULL;
4662 }
4663 }
4664 else {
4665 PerlIOBase(f)->flags =
4666 flags | PERLIO_F_EOF | PERLIO_F_RDBUF;
4667 b->buf = NULL;
4668 b->ptr = b->end = b->ptr;
4669 code = -1;
4670 }
4671 }
4672 }
4673 return code;
06da4f11
NIS
4674}
4675
4676IV
e87a358a 4677PerlIOMmap_unmap(pTHX_ PerlIO *f)
06da4f11 4678{
dcda55fc 4679 PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
14a5cf38
JH
4680 IV code = 0;
4681 if (m->len) {
dcda55fc 4682 PerlIOBuf * const b = &m->base;
14a5cf38 4683 if (b->buf) {
1ccb7c8d
JH
4684 /* The munmap address argument is tricky: depending on the
4685 * standard it is either "void *" or "caddr_t" (which is
4686 * usually "char *" (signed or unsigned). If we cast it
4687 * to "void *", those that have it caddr_t and an uptight
4688 * C++ compiler, will freak out. But casting it as char*
4689 * should work. Maybe. (Using Mmap_t figured out by
4690 * Configure doesn't always work, apparently.) */
4691 code = munmap((char*)m->mptr, m->len);
14a5cf38
JH
4692 b->buf = NULL;
4693 m->len = 0;
4694 m->mptr = NULL;
4695 if (PerlIO_seek(PerlIONext(f), b->posn, SEEK_SET) != 0)
4696 code = -1;
4697 }
4698 b->ptr = b->end = b->buf;
4699 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
4700 }
4701 return code;
06da4f11
NIS
4702}
4703
4704STDCHAR *
f62ce20a 4705PerlIOMmap_get_base(pTHX_ PerlIO *f)
06da4f11 4706{
dcda55fc
AL
4707 PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
4708 PerlIOBuf * const b = &m->base;
14a5cf38
JH
4709 if (b->buf && (PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
4710 /*
71200d45 4711 * Already have a readbuffer in progress
14a5cf38
JH
4712 */
4713 return b->buf;
4714 }
4715 if (b->buf) {
4716 /*
71200d45 4717 * We have a write buffer or flushed PerlIOBuf read buffer
14a5cf38 4718 */
22569500
NIS
4719 m->bbuf = b->buf; /* save it in case we need it again */
4720 b->buf = NULL; /* Clear to trigger below */
14a5cf38
JH
4721 }
4722 if (!b->buf) {
22569500 4723 PerlIOMmap_map(aTHX_ f); /* Try and map it */
14a5cf38
JH
4724 if (!b->buf) {
4725 /*
71200d45 4726 * Map did not work - recover PerlIOBuf buffer if we have one
14a5cf38
JH
4727 */
4728 b->buf = m->bbuf;
4729 }
4730 }
4731 b->ptr = b->end = b->buf;
4732 if (b->buf)
4733 return b->buf;
f62ce20a 4734 return PerlIOBuf_get_base(aTHX_ f);
06da4f11
NIS
4735}
4736
4737SSize_t
f62ce20a 4738PerlIOMmap_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
06da4f11 4739{
dcda55fc
AL
4740 PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
4741 PerlIOBuf * const b = &m->base;
14a5cf38
JH
4742 if (PerlIOBase(f)->flags & PERLIO_F_WRBUF)
4743 PerlIO_flush(f);
4744 if (b->ptr && (b->ptr - count) >= b->buf
4745 && memEQ(b->ptr - count, vbuf, count)) {
4746 b->ptr -= count;
4747 PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
4748 return count;
4749 }
4750 if (m->len) {
4751 /*
71200d45 4752 * Loose the unwritable mapped buffer
14a5cf38
JH
4753 */
4754 PerlIO_flush(f);
4755 /*
71200d45 4756 * If flush took the "buffer" see if we have one from before
14a5cf38
JH
4757 */
4758 if (!b->buf && m->bbuf)
4759 b->buf = m->bbuf;
4760 if (!b->buf) {
f62ce20a 4761 PerlIOBuf_get_base(aTHX_ f);
14a5cf38
JH
4762 m->bbuf = b->buf;
4763 }
4764 }
f62ce20a 4765 return PerlIOBuf_unread(aTHX_ f, vbuf, count);
06da4f11
NIS
4766}
4767
4768SSize_t
f62ce20a 4769PerlIOMmap_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
06da4f11 4770{
de009b76
AL
4771 PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
4772 PerlIOBuf * const b = &m->base;
4773
14a5cf38
JH
4774 if (!b->buf || !(PerlIOBase(f)->flags & PERLIO_F_WRBUF)) {
4775 /*
71200d45 4776 * No, or wrong sort of, buffer
14a5cf38
JH
4777 */
4778 if (m->len) {
e87a358a 4779 if (PerlIOMmap_unmap(aTHX_ f) != 0)
14a5cf38
JH
4780 return 0;
4781 }
4782 /*
71200d45 4783 * If unmap took the "buffer" see if we have one from before
14a5cf38
JH
4784 */
4785 if (!b->buf && m->bbuf)
4786 b->buf = m->bbuf;
4787 if (!b->buf) {
f62ce20a 4788 PerlIOBuf_get_base(aTHX_ f);
14a5cf38
JH
4789 m->bbuf = b->buf;
4790 }
06da4f11 4791 }
f62ce20a 4792 return PerlIOBuf_write(aTHX_ f, vbuf, count);
06da4f11
NIS
4793}
4794
4795IV
f62ce20a 4796PerlIOMmap_flush(pTHX_ PerlIO *f)
06da4f11 4797{
dcda55fc
AL
4798 PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
4799 PerlIOBuf * const b = &m->base;
f62ce20a 4800 IV code = PerlIOBuf_flush(aTHX_ f);
14a5cf38 4801 /*
71200d45 4802 * Now we are "synced" at PerlIOBuf level
14a5cf38
JH
4803 */
4804 if (b->buf) {
4805 if (m->len) {
4806 /*
71200d45 4807 * Unmap the buffer
14a5cf38 4808 */
e87a358a 4809 if (PerlIOMmap_unmap(aTHX_ f) != 0)
14a5cf38
JH
4810 code = -1;
4811 }
4812 else {
4813 /*
4814 * We seem to have a PerlIOBuf buffer which was not mapped
71200d45 4815 * remember it in case we need one later
14a5cf38
JH
4816 */
4817 m->bbuf = b->buf;
4818 }
4819 }
4820 return code;
06da4f11
NIS
4821}
4822
4823IV
f62ce20a 4824PerlIOMmap_fill(pTHX_ PerlIO *f)
06da4f11 4825{
dcda55fc 4826 PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf);
14a5cf38
JH
4827 IV code = PerlIO_flush(f);
4828 if (code == 0 && !b->buf) {
f62ce20a 4829 code = PerlIOMmap_map(aTHX_ f);
14a5cf38
JH
4830 }
4831 if (code == 0 && !(PerlIOBase(f)->flags & PERLIO_F_RDBUF)) {
f62ce20a 4832 code = PerlIOBuf_fill(aTHX_ f);
14a5cf38
JH
4833 }
4834 return code;
06da4f11
NIS
4835}
4836
4837IV
f62ce20a 4838PerlIOMmap_close(pTHX_ PerlIO *f)
06da4f11 4839{
dcda55fc
AL
4840 PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap);
4841 PerlIOBuf * const b = &m->base;
14a5cf38
JH
4842 IV code = PerlIO_flush(f);
4843 if (m->bbuf) {
4844 b->buf = m->bbuf;
4845 m->bbuf = NULL;
4846 b->ptr = b->end = b->buf;
4847 }
f62ce20a 4848 if (PerlIOBuf_close(aTHX_ f) != 0)
14a5cf38
JH
4849 code = -1;
4850 return code;
06da4f11
NIS
4851}
4852
71200d45 4853PerlIO *
ecdeb87c 4854PerlIOMmap_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags)
71200d45 4855{
ecdeb87c 4856 return PerlIOBase_dup(aTHX_ f, o, param, flags);
71200d45
NIS
4857}
4858
06da4f11 4859
27da23d5 4860PERLIO_FUNCS_DECL(PerlIO_mmap) = {
2dc2558e 4861 sizeof(PerlIO_funcs),
14a5cf38
JH
4862 "mmap",
4863 sizeof(PerlIOMmap),
86e05cf2 4864 PERLIO_K_BUFFERED|PERLIO_K_RAW,
14a5cf38 4865 PerlIOBuf_pushed,
44798d05 4866 PerlIOBuf_popped,
14a5cf38 4867 PerlIOBuf_open,
86e05cf2 4868 PerlIOBase_binmode, /* binmode */
14a5cf38
JH
4869 NULL,
4870 PerlIOBase_fileno,
71200d45 4871 PerlIOMmap_dup,
14a5cf38
JH
4872 PerlIOBuf_read,
4873 PerlIOMmap_unread,
4874 PerlIOMmap_write,
4875 PerlIOBuf_seek,
4876 PerlIOBuf_tell,
4877 PerlIOBuf_close,
4878 PerlIOMmap_flush,
4879 PerlIOMmap_fill,
4880 PerlIOBase_eof,
4881 PerlIOBase_error,
4882 PerlIOBase_clearerr,
4883 PerlIOBase_setlinebuf,
4884 PerlIOMmap_get_base,
4885 PerlIOBuf_bufsiz,
4886 PerlIOBuf_get_ptr,
4887 PerlIOBuf_get_cnt,
4888 PerlIOBuf_set_ptrcnt,
06da4f11
NIS
4889};
4890
22569500 4891#endif /* HAS_MMAP */
06da4f11 4892
9e353e3b 4893PerlIO *
e87a358a 4894Perl_PerlIO_stdin(pTHX)
9e353e3b 4895{
97aff369 4896 dVAR;
a1ea730d 4897 if (!PL_perlio) {
14a5cf38
JH
4898 PerlIO_stdstreams(aTHX);
4899 }
a1ea730d 4900 return &PL_perlio[1];
9e353e3b
NIS
4901}
4902
9e353e3b 4903PerlIO *
e87a358a 4904Perl_PerlIO_stdout(pTHX)
9e353e3b 4905{
97aff369 4906 dVAR;
a1ea730d 4907 if (!PL_perlio) {
14a5cf38
JH
4908 PerlIO_stdstreams(aTHX);
4909 }
a1ea730d 4910 return &PL_perlio[2];
9e353e3b
NIS
4911}
4912
9e353e3b 4913PerlIO *
e87a358a 4914Perl_PerlIO_stderr(pTHX)
9e353e3b 4915{
97aff369 4916 dVAR;
a1ea730d 4917 if (!PL_perlio) {
14a5cf38
JH
4918 PerlIO_stdstreams(aTHX);
4919 }
a1ea730d 4920 return &PL_perlio[3];
9e353e3b
NIS
4921}
4922
4923/*--------------------------------------------------------------------------------------*/
4924
9e353e3b
NIS
4925char *
4926PerlIO_getname(PerlIO *f, char *buf)
4927{
14a5cf38 4928 dTHX;
a15cef0c 4929#ifdef VMS
73d840c0 4930 char *name = NULL;
7659f319 4931 bool exported = FALSE;
14a5cf38 4932 FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio;
7659f319
CB
4933 if (!stdio) {
4934 stdio = PerlIO_exportFILE(f,0);
4935 exported = TRUE;
4936 }
4937 if (stdio) {
14a5cf38 4938 name = fgetname(stdio, buf);
7659f319
CB
4939 if (exported) PerlIO_releaseFILE(f,stdio);
4940 }
73d840c0 4941 return name;
a15cef0c 4942#else
8772537c
AL
4943 PERL_UNUSED_ARG(f);
4944 PERL_UNUSED_ARG(buf);
14a5cf38 4945 Perl_croak(aTHX_ "Don't know how to get file name");
bd61b366 4946 return NULL;
a15cef0c 4947#endif
9e353e3b
NIS
4948}
4949
4950
4951/*--------------------------------------------------------------------------------------*/
14a5cf38
JH
4952/*
4953 * Functions which can be called on any kind of PerlIO implemented in
71200d45 4954 * terms of above
14a5cf38 4955 */
9e353e3b 4956
e87a358a
NIS
4957#undef PerlIO_fdopen
4958PerlIO *
4959PerlIO_fdopen(int fd, const char *mode)
4960{
4961 dTHX;
bd61b366 4962 return PerlIO_openn(aTHX_ NULL, mode, fd, 0, 0, NULL, 0, NULL);
e87a358a
NIS
4963}
4964
4965#undef PerlIO_open
4966PerlIO *
4967PerlIO_open(const char *path, const char *mode)
4968{
4969 dTHX;
42d9b98d 4970 SV *name = sv_2mortal(newSVpv(path, 0));
bd61b366 4971 return PerlIO_openn(aTHX_ NULL, mode, -1, 0, 0, NULL, 1, &name);
e87a358a
NIS
4972}
4973
4974#undef Perlio_reopen
4975PerlIO *
4976PerlIO_reopen(const char *path, const char *mode, PerlIO *f)
4977{
4978 dTHX;
42d9b98d 4979 SV *name = sv_2mortal(newSVpv(path,0));
bd61b366 4980 return PerlIO_openn(aTHX_ NULL, mode, -1, 0, 0, f, 1, &name);
e87a358a
NIS
4981}
4982
9e353e3b 4983#undef PerlIO_getc
6f9d8c32 4984int
9e353e3b 4985PerlIO_getc(PerlIO *f)
760ac839 4986{
e87a358a 4987 dTHX;
14a5cf38 4988 STDCHAR buf[1];
de009b76 4989 if ( 1 == PerlIO_read(f, buf, 1) ) {
14a5cf38
JH
4990 return (unsigned char) buf[0];
4991 }
4992 return EOF;
313ca112
NIS
4993}
4994
4995#undef PerlIO_ungetc
4996int
4997PerlIO_ungetc(PerlIO *f, int ch)
4998{
e87a358a 4999 dTHX;
14a5cf38
JH
5000 if (ch != EOF) {
5001 STDCHAR buf = ch;
5002 if (PerlIO_unread(f, &buf, 1) == 1)
5003 return ch;
5004 }
5005 return EOF;
760ac839
LW
5006}
5007
9e353e3b
NIS
5008#undef PerlIO_putc
5009int
5010PerlIO_putc(PerlIO *f, int ch)
760ac839 5011{
e87a358a 5012 dTHX;
14a5cf38
JH
5013 STDCHAR buf = ch;
5014 return PerlIO_write(f, &buf, 1);
760ac839
LW
5015}
5016
9e353e3b 5017#undef PerlIO_puts
760ac839 5018int
9e353e3b 5019PerlIO_puts(PerlIO *f, const char *s)
760ac839 5020{
e87a358a 5021 dTHX;
dcda55fc 5022 return PerlIO_write(f, s, strlen(s));
760ac839
LW
5023}
5024
5025#undef PerlIO_rewind
5026void
c78749f2 5027PerlIO_rewind(PerlIO *f)
760ac839 5028{
e87a358a 5029 dTHX;
14a5cf38
JH
5030 PerlIO_seek(f, (Off_t) 0, SEEK_SET);
5031 PerlIO_clearerr(f);
6f9d8c32
NIS
5032}
5033
5034#undef PerlIO_vprintf
5035int
5036PerlIO_vprintf(PerlIO *f, const char *fmt, va_list ap)
5037{
14a5cf38 5038 dTHX;
396482e1 5039 SV * const sv = newSVpvs("");
b83604b4 5040 const char *s;
14a5cf38
JH
5041 STRLEN len;
5042 SSize_t wrote;
2cc61e15 5043#ifdef NEED_VA_COPY
14a5cf38
JH
5044 va_list apc;
5045 Perl_va_copy(ap, apc);
5046 sv_vcatpvf(sv, fmt, &apc);
2cc61e15 5047#else
14a5cf38 5048 sv_vcatpvf(sv, fmt, &ap);
2cc61e15 5049#endif
b83604b4 5050 s = SvPV_const(sv, len);
14a5cf38
JH
5051 wrote = PerlIO_write(f, s, len);
5052 SvREFCNT_dec(sv);
5053 return wrote;
760ac839
LW
5054}
5055
5056#undef PerlIO_printf
6f9d8c32 5057int
14a5cf38 5058PerlIO_printf(PerlIO *f, const char *fmt, ...)
760ac839 5059{
14a5cf38
JH
5060 va_list ap;
5061 int result;
5062 va_start(ap, fmt);
5063 result = PerlIO_vprintf(f, fmt, ap);
5064 va_end(ap);
5065 return result;
760ac839
LW
5066}
5067
5068#undef PerlIO_stdoutf
6f9d8c32 5069int
14a5cf38 5070PerlIO_stdoutf(const char *fmt, ...)
760ac839 5071{
e87a358a 5072 dTHX;
14a5cf38
JH
5073 va_list ap;
5074 int result;
5075 va_start(ap, fmt);
5076 result = PerlIO_vprintf(PerlIO_stdout(), fmt, ap);
5077 va_end(ap);
5078 return result;
760ac839
LW
5079}
5080
5081#undef PerlIO_tmpfile
5082PerlIO *
c78749f2 5083PerlIO_tmpfile(void)
760ac839 5084{
2941a2e1
JH
5085 dTHX;
5086 PerlIO *f = NULL;
2941a2e1 5087#ifdef WIN32
de009b76 5088 const int fd = win32_tmpfd();
2941a2e1
JH
5089 if (fd >= 0)
5090 f = PerlIO_fdopen(fd, "w+b");
5091#else /* WIN32 */
460c8493 5092# if defined(HAS_MKSTEMP) && ! defined(VMS) && ! defined(OS2)
396482e1 5093 SV * const sv = newSVpvs("/tmp/PerlIO_XXXXXX");
2941a2e1
JH
5094 /*
5095 * I have no idea how portable mkstemp() is ... NI-S
5096 */
de009b76 5097 const int fd = mkstemp(SvPVX(sv));
2941a2e1
JH
5098 if (fd >= 0) {
5099 f = PerlIO_fdopen(fd, "w+");
5100 if (f)
5101 PerlIOBase(f)->flags |= PERLIO_F_TEMP;
b15aece3 5102 PerlLIO_unlink(SvPVX_const(sv));
2941a2e1 5103 }
b2166d27 5104 SvREFCNT_dec(sv);
2941a2e1 5105# else /* !HAS_MKSTEMP, fallback to stdio tmpfile(). */
c4420975 5106 FILE * const stdio = PerlSIO_tmpfile();
2941a2e1 5107
085e731f
CB
5108 if (stdio)
5109 f = PerlIO_fdopen(fileno(stdio), "w+");
5110
2941a2e1
JH
5111# endif /* else HAS_MKSTEMP */
5112#endif /* else WIN32 */
5113 return f;
760ac839
LW
5114}
5115
6f9d8c32
NIS
5116#undef HAS_FSETPOS
5117#undef HAS_FGETPOS
5118
22569500
NIS
5119#endif /* USE_SFIO */
5120#endif /* PERLIO_IS_STDIO */
760ac839 5121
9e353e3b 5122/*======================================================================================*/
14a5cf38 5123/*
71200d45
NIS
5124 * Now some functions in terms of above which may be needed even if we are
5125 * not in true PerlIO mode
9e353e3b 5126 */
188f0c84
YO
5127const char *
5128Perl_PerlIO_context_layers(pTHX_ const char *mode)
5129{
5130 dVAR;
8b850bd5
NC
5131 const char *direction = NULL;
5132 SV *layers;
188f0c84
YO
5133 /*
5134 * Need to supply default layer info from open.pm
5135 */
8b850bd5
NC
5136
5137 if (!PL_curcop)
5138 return NULL;
5139
5140 if (mode && mode[0] != 'r') {
5141 if (PL_curcop->cop_hints & HINT_LEXICAL_IO_OUT)
5142 direction = "open>";
5143 } else {
5144 if (PL_curcop->cop_hints & HINT_LEXICAL_IO_IN)
5145 direction = "open<";
188f0c84 5146 }
8b850bd5
NC
5147 if (!direction)
5148 return NULL;
5149
5150 layers = Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash,
5151 0, direction, 5, 0, 0);
5152
5153 assert(layers);
5154 return SvOK(layers) ? SvPV_nolen_const(layers) : NULL;
188f0c84
YO
5155}
5156
9e353e3b 5157
760ac839
LW
5158#ifndef HAS_FSETPOS
5159#undef PerlIO_setpos
5160int
766a733e 5161PerlIO_setpos(PerlIO *f, SV *pos)
760ac839 5162{
14a5cf38
JH
5163 dTHX;
5164 if (SvOK(pos)) {
5165 STRLEN len;
c4420975 5166 const Off_t * const posn = (Off_t *) SvPV(pos, len);
14a5cf38
JH
5167 if (f && len == sizeof(Off_t))
5168 return PerlIO_seek(f, *posn, SEEK_SET);
5169 }
93189314 5170 SETERRNO(EINVAL, SS_IVCHAN);
14a5cf38 5171 return -1;
760ac839 5172}
c411622e 5173#else
c411622e 5174#undef PerlIO_setpos
5175int
766a733e 5176PerlIO_setpos(PerlIO *f, SV *pos)
c411622e 5177{
14a5cf38
JH
5178 dTHX;
5179 if (SvOK(pos)) {
5180 STRLEN len;
c4420975 5181 Fpos_t * const fpos = (Fpos_t *) SvPV(pos, len);
14a5cf38 5182 if (f && len == sizeof(Fpos_t)) {
2d4389e4 5183#if defined(USE_64_BIT_STDIO) && defined(USE_FSETPOS64)
14a5cf38 5184 return fsetpos64(f, fpos);
d9b3e12d 5185#else
14a5cf38 5186 return fsetpos(f, fpos);
d9b3e12d 5187#endif
14a5cf38 5188 }
766a733e 5189 }
93189314 5190 SETERRNO(EINVAL, SS_IVCHAN);
14a5cf38 5191 return -1;
c411622e 5192}
5193#endif
760ac839
LW
5194
5195#ifndef HAS_FGETPOS
5196#undef PerlIO_getpos
5197int
766a733e 5198PerlIO_getpos(PerlIO *f, SV *pos)
760ac839 5199{
14a5cf38
JH
5200 dTHX;
5201 Off_t posn = PerlIO_tell(f);
5202 sv_setpvn(pos, (char *) &posn, sizeof(posn));
5203 return (posn == (Off_t) - 1) ? -1 : 0;
760ac839 5204}
c411622e 5205#else
c411622e 5206#undef PerlIO_getpos
5207int
766a733e 5208PerlIO_getpos(PerlIO *f, SV *pos)
c411622e 5209{
14a5cf38
JH
5210 dTHX;
5211 Fpos_t fpos;
5212 int code;
2d4389e4 5213#if defined(USE_64_BIT_STDIO) && defined(USE_FSETPOS64)
14a5cf38 5214 code = fgetpos64(f, &fpos);
d9b3e12d 5215#else
14a5cf38 5216 code = fgetpos(f, &fpos);
d9b3e12d 5217#endif
14a5cf38
JH
5218 sv_setpvn(pos, (char *) &fpos, sizeof(fpos));
5219 return code;
c411622e 5220}
5221#endif
760ac839
LW
5222
5223#if (defined(PERLIO_IS_STDIO) || !defined(USE_SFIO)) && !defined(HAS_VPRINTF)
5224
5225int
c78749f2 5226vprintf(char *pat, char *args)
662a7e3f
CS
5227{
5228 _doprnt(pat, args, stdout);
22569500 5229 return 0; /* wrong, but perl doesn't use the return
14a5cf38 5230 * value */
662a7e3f
CS
5231}
5232
5233int
c78749f2 5234vfprintf(FILE *fd, char *pat, char *args)
760ac839
LW
5235{
5236 _doprnt(pat, args, fd);
22569500 5237 return 0; /* wrong, but perl doesn't use the return
14a5cf38 5238 * value */
760ac839
LW
5239}
5240
5241#endif
5242
5243#ifndef PerlIO_vsprintf
6f9d8c32 5244int
8ac85365 5245PerlIO_vsprintf(char *s, int n, const char *fmt, va_list ap)
760ac839 5246{
8ff9a42b 5247 dTHX;
d9fad198 5248 const int val = my_vsnprintf(s, n > 0 ? n : 0, fmt, ap);
14333449
AL
5249 PERL_UNUSED_CONTEXT;
5250
1208b3dd
JH
5251#ifndef PERL_MY_VSNPRINTF_GUARDED
5252 if (val < 0 || (n > 0 ? val >= n : 0)) {
37405f90 5253 Perl_croak(aTHX_ "panic: my_vsnprintf overflow in PerlIO_vsprintf\n");
760ac839 5254 }
1208b3dd 5255#endif
14a5cf38 5256 return val;
760ac839
LW
5257}
5258#endif
5259
5260#ifndef PerlIO_sprintf
6f9d8c32 5261int
14a5cf38 5262PerlIO_sprintf(char *s, int n, const char *fmt, ...)
760ac839 5263{
14a5cf38
JH
5264 va_list ap;
5265 int result;
5266 va_start(ap, fmt);
5267 result = PerlIO_vsprintf(s, n, fmt, ap);
5268 va_end(ap);
5269 return result;
760ac839
LW
5270}
5271#endif
9cfa90c0
NC
5272
5273/*
5274 * Local variables:
5275 * c-indentation-style: bsd
5276 * c-basic-offset: 4
5277 * indent-tabs-mode: t
5278 * End:
5279 *
37442d52
RGS
5280 * ex: set ts=8 sts=4 sw=4 noet:
5281 */