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