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