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