X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/d8723f436e1dd34e1353ad7e3538918033d31d15..2a600bb8f7c0d6b36cb37c899b6c9e82537ec394:/perlio.c diff --git a/perlio.c b/perlio.c index faf8147..d4c43d0 100644 --- a/perlio.c +++ b/perlio.c @@ -1,7 +1,7 @@ /* * perlio.c * Copyright (c) 1996-2006, Nick Ing-Simmons - * Copyright (c) 2006, 2007, 2008 Larry Wall and others + * Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011 Larry Wall and others * * You may distribute under the terms of either the GNU General Public License * or the Artistic License, as specified in the README file. @@ -10,6 +10,8 @@ /* * Hour after hour for nearly three weary days he had jogged up and down, * over passes, and through long dales, and across many streams. + * + * [pp.791-792 of _The Lord of the Rings_, V/iii: "The Muster of Rohan"] */ /* This file contains the functions needed to implement PerlIO, which @@ -29,23 +31,7 @@ #define dSYS dNOOP #endif -#define VOIDUSED 1 -#ifdef PERL_MICRO -# include "uconfig.h" -#else -# ifndef USE_CROSS_COMPILE -# include "config.h" -# else -# include "xconfig.h" -# endif -#endif - #define PERLIO_NOT_STDIO 0 -#if !defined(PERLIO_IS_STDIO) && !defined(USE_SFIO) -/* - * #define PerlIO FILE - */ -#endif /* * This file provides those parts of PerlIO abstraction * which are not #defined in perlio.h. @@ -68,6 +54,12 @@ int mkstemp(char*); #endif +#ifdef VMS +#include +#endif + +#define PerlIO_lockcnt(f) (((PerlIOl*)(f))->head->flags) + /* Call the callback or PerlIOBase, and return failure. */ #define Perl_PerlIO_or_Base(f, callback, base, failure, args) \ if (PerlIOValid(f)) { \ @@ -122,7 +114,8 @@ extern int fseeko(FILE *, off_t, int); extern off_t ftello(FILE *); #endif -#ifndef USE_SFIO +#define NATIVE_0xd CR_NATIVE +#define NATIVE_0xa LF_NATIVE EXTERN_C int perlsio_binmode(FILE *fp, int iotype, int mode); @@ -133,17 +126,6 @@ perlsio_binmode(FILE *fp, int iotype, int mode) * This used to be contents of do_binmode in doio.c */ #ifdef DOSISH -# if defined(atarist) || defined(__MINT__) - PERL_UNUSED_ARG(iotype); - if (!fflush(fp)) { - if (mode & O_BINARY) - ((FILE *) fp)->_flag |= _IOBIN; - else - ((FILE *) fp)->_flag &= ~_IOBIN; - return 1; - } - return 0; -# else dTHX; PERL_UNUSED_ARG(iotype); #ifdef NETWARE @@ -151,28 +133,10 @@ perlsio_binmode(FILE *fp, int iotype, int mode) #else if (PerlLIO_setmode(fileno(fp), mode) != -1) { #endif -# if defined(WIN32) && defined(__BORLANDC__) - /* - * The translation mode of the stream is maintained independent -of - * the translation mode of the fd in the Borland RTL (heavy - * digging through their runtime sources reveal). User has to -set - * the mode explicitly for the stream (though they don't -document - * this anywhere). GSAR 97-5-24 - */ - fseek(fp, 0L, 0); - if (mode & O_BINARY) - fp->flags |= _F_BIN; - else - fp->flags &= ~_F_BIN; -# endif return 1; } else return 0; -# endif #else # if defined(USEMYBINMODE) dTHX; @@ -191,7 +155,6 @@ document # endif #endif } -#endif /* sfio */ #ifndef O_ACCMODE #define O_ACCMODE 3 /* Assume traditional implementation */ @@ -268,14 +231,7 @@ PerlIO_destruct(pTHX) int PerlIO_binmode(pTHX_ PerlIO *fp, int iotype, int mode, const char *names) { -#ifdef USE_SFIO - PERL_UNUSED_ARG(iotype); - PERL_UNUSED_ARG(mode); - PERL_UNUSED_ARG(names); - return 1; -#else return perlsio_binmode(fp, iotype, mode); -#endif } PerlIO * @@ -330,7 +286,11 @@ PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd, if (*args == &PL_sv_undef) return PerlIO_tmpfile(); else { - const char *name = SvPV_nolen_const(*args); + STRLEN len; + const char *name = SvPV_const(*args, len); + if (!IS_SAFE_PATHNAME(name, len, "open")) + return NULL; + if (*mode == IoTYPE_NUMERIC) { fd = PerlLIO_open3(name, imode, perm); if (fd >= 0) @@ -350,6 +310,7 @@ PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd, return NULL; } +XS(XS_PerlIO__Layer__find); /* prototype to pass -Wmissing-prototypes */ XS(XS_PerlIO__Layer__find) { dXSARGS; @@ -396,67 +357,6 @@ PerlIO_tmpfile(void) #else /* PERLIO_IS_STDIO */ -#ifdef USE_SFIO - -#undef HAS_FSETPOS -#undef HAS_FGETPOS - -/* - * This section is just to make sure these functions get pulled in from - * libsfio.a - */ - -#undef PerlIO_tmpfile -PerlIO * -PerlIO_tmpfile(void) -{ - return sftmp(0); -} - -void -PerlIO_init(pTHX) -{ - PERL_UNUSED_CONTEXT; - /* - * Force this file to be included in perl binary. Which allows this - * file to force inclusion of other functions that may be required by - * loadable extensions e.g. for FileHandle::tmpfile - */ - - /* - * Hack sfio does its own 'autoflush' on stdout in common cases. Flush - * results in a lot of lseek()s to regular files and lot of small - * writes to pipes. - */ - sfset(sfstdout, SF_SHARE, 0); -} - -/* This is not the reverse of PerlIO_exportFILE(), PerlIO_releaseFILE() is. */ -PerlIO * -PerlIO_importFILE(FILE *stdio, const char *mode) -{ - const int fd = fileno(stdio); - if (!mode || !*mode) { - mode = "r+"; - } - return PerlIO_fdopen(fd, mode); -} - -FILE * -PerlIO_findFILE(PerlIO *pio) -{ - const int fd = PerlIO_fileno(pio); - FILE * const f = fdopen(fd, "r+"); - PerlIO_flush(pio); - if (!f && errno == EINVAL) - f = fdopen(fd, "w"); - if (!f && errno == EINVAL) - f = fdopen(fd, "r"); - return f; -} - - -#else /* USE_SFIO */ /*======================================================================================*/ /* * Implement all the PerlIO interface ourselves. @@ -464,17 +364,6 @@ PerlIO_findFILE(PerlIO *pio) #include "perliol.h" -/* - * We _MUST_ have if we are using lseek() and may have large - * files - */ -#ifdef I_UNISTD -#include -#endif -#ifdef HAS_MMAP -#include -#endif - void PerlIO_debug(const char *fmt, ...) { @@ -482,7 +371,9 @@ PerlIO_debug(const char *fmt, ...) dSYS; va_start(ap, fmt); if (!PL_perlio_debug_fd) { - if (!PL_tainting && PL_uid == PL_euid && PL_gid == PL_egid) { + if (!TAINTING_get && + PerlProc_getuid() == PerlProc_geteuid() && + PerlProc_getgid() == PerlProc_getegid()) { const char * const s = PerlEnv_getenv("PERLIO_DEBUG"); if (s && *s) PL_perlio_debug_fd @@ -496,14 +387,14 @@ PerlIO_debug(const char *fmt, ...) } } if (PL_perlio_debug_fd > 0) { - dTHX; + int rc = 0; #ifdef USE_ITHREADS const char * const s = CopFILE(PL_curcop); /* Use fixed buffer as sv_catpvf etc. needs SVs */ char buffer[1024]; const STRLEN len1 = my_snprintf(buffer, sizeof(buffer), "%.40s:%" IVdf " ", s ? s : "(none)", (IV) CopLINE(PL_curcop)); const STRLEN len2 = my_vsnprintf(buffer + len1, sizeof(buffer) - len1, fmt, ap); - PerlLIO_write(PL_perlio_debug_fd, buffer, len1 + len2); + rc = PerlLIO_write(PL_perlio_debug_fd, buffer, len1 + len2); #else const char *s = CopFILE(PL_curcop); STRLEN len; @@ -512,9 +403,11 @@ PerlIO_debug(const char *fmt, ...) Perl_sv_vcatpvf(aTHX_ sv, fmt, &ap); s = SvPV_const(sv, len); - PerlLIO_write(PL_perlio_debug_fd, s, len); + rc = PerlLIO_write(PL_perlio_debug_fd, s, len); SvREFCNT_dec(sv); #endif + /* silently ignore failures */ + PERL_UNUSED_VAR(rc); } va_end(ap); } @@ -525,11 +418,47 @@ PerlIO_debug(const char *fmt, ...) * Inner level routines */ +/* check that the head field of each layer points back to the head */ + +#ifdef DEBUGGING +# define VERIFY_HEAD(f) PerlIO_verify_head(aTHX_ f) +static void +PerlIO_verify_head(pTHX_ PerlIO *f) +{ + PerlIOl *head, *p; + int seen = 0; + if (!PerlIOValid(f)) + return; + p = head = PerlIOBase(f)->head; + assert(p); + do { + assert(p->head == head); + if (p == (PerlIOl*)f) + seen = 1; + p = p->next; + } while (p); + assert(seen); +} +#else +# define VERIFY_HEAD(f) +#endif + + /* * Table of pointers to the PerlIO structs (malloc'ed) */ #define PERLIO_TABLE_SIZE 64 +static void +PerlIO_init_table(pTHX) +{ + if (PL_perlio) + return; + Newxz(PL_perlio, PERLIO_TABLE_SIZE, PerlIOl); +} + + + PerlIO * PerlIO_allocate(pTHX) { @@ -537,24 +466,30 @@ PerlIO_allocate(pTHX) /* * Find a free slot in the table, allocating new table as necessary */ - PerlIO **last; - PerlIO *f; + PerlIOl **last; + PerlIOl *f; last = &PL_perlio; while ((f = *last)) { int i; - last = (PerlIO **) (f); + last = (PerlIOl **) (f); for (i = 1; i < PERLIO_TABLE_SIZE; i++) { - if (!*++f) { - return f; + if (!((++f)->next)) { + f->flags = 0; /* lockcnt */ + f->tab = NULL; + f->head = f; + return (PerlIO *)f; } } } - Newxz(f,PERLIO_TABLE_SIZE,PerlIO); + Newxz(f,PERLIO_TABLE_SIZE,PerlIOl); if (!f) { return NULL; } - *last = f; - return f + 1; + *last = (PerlIOl*) f++; + f->flags = 0; /* lockcnt */ + f->tab = NULL; + f->head = f; + return (PerlIO*) f; } #undef PerlIO_fdupopen @@ -577,16 +512,16 @@ PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags) } void -PerlIO_cleantable(pTHX_ PerlIO **tablep) +PerlIO_cleantable(pTHX_ PerlIOl **tablep) { - PerlIO * const table = *tablep; + PerlIOl * const table = *tablep; if (table) { int i; - PerlIO_cleantable(aTHX_(PerlIO **) & (table[0])); + PerlIO_cleantable(aTHX_(PerlIOl **) & (table[0])); for (i = PERLIO_TABLE_SIZE - 1; i > 0; i--) { - PerlIO * const f = table + i; - if (*f) { - PerlIO_close(f); + PerlIOl * const f = table + i; + if (f->next) { + PerlIO_close(&(f->next)); } } Safefree(table); @@ -612,10 +547,8 @@ PerlIO_list_free(pTHX_ PerlIO_list_t *list) if (--list->refcnt == 0) { if (list->array) { IV i; - for (i = 0; i < list->cur; i++) { - if (list->array[i].arg) - SvREFCNT_dec(list->array[i].arg); - } + for (i = 0; i < list->cur; i++) + SvREFCNT_dec(list->array[i].arg); Safefree(list->array); } Safefree(list); @@ -653,7 +586,7 @@ PerlIO_clone_list(pTHX_ PerlIO_list_t *proto, CLONE_PARAMS *param) list = PerlIO_list_alloc(aTHX); for (i=0; i < proto->cur; i++) { SV *arg = proto->array[i].arg; -#ifdef sv_dup +#ifdef USE_ITHREADS if (arg && param) arg = sv_dup(arg, param); #else @@ -669,19 +602,19 @@ void PerlIO_clone(pTHX_ PerlInterpreter *proto, CLONE_PARAMS *param) { #ifdef USE_ITHREADS - PerlIO **table = &proto->Iperlio; - PerlIO *f; + PerlIOl **table = &proto->Iperlio; + PerlIOl *f; PL_perlio = NULL; PL_known_layers = PerlIO_clone_list(aTHX_ proto->Iknown_layers, param); PL_def_layerlist = PerlIO_clone_list(aTHX_ proto->Idef_layerlist, param); - PerlIO_allocate(aTHX); /* root slot is never used */ + PerlIO_init_table(aTHX); PerlIO_debug("Clone %p from %p\n",(void*)aTHX,(void*)proto); while ((f = *table)) { int i; - table = (PerlIO **) (f++); + table = (PerlIOl **) (f++); for (i = 1; i < PERLIO_TABLE_SIZE; i++) { - if (*f) { - (void) fp_dup(f, 0, param); + if (f->next) { + (void) fp_dup(&(f->next), 0, param); } f++; } @@ -697,19 +630,19 @@ void PerlIO_destruct(pTHX) { dVAR; - PerlIO **table = &PL_perlio; - PerlIO *f; + PerlIOl **table = &PL_perlio; + PerlIOl *f; #ifdef USE_ITHREADS PerlIO_debug("Destruct %p\n",(void*)aTHX); #endif while ((f = *table)) { int i; - table = (PerlIO **) (f++); + table = (PerlIOl **) (f++); for (i = 1; i < PERLIO_TABLE_SIZE; i++) { - PerlIO *x = f; + PerlIO *x = &(f->next); const PerlIOl *l; while ((l = *x)) { - if (l->tab->kind & PERLIO_K_DESTRUCT) { + if (l->tab && l->tab->kind & PERLIO_K_DESTRUCT) { PerlIO_debug("Destruct popping %s\n", l->tab->name); PerlIO_flush(x); PerlIO_pop(aTHX_ x); @@ -727,9 +660,11 @@ void PerlIO_pop(pTHX_ PerlIO *f) { const PerlIOl *l = *f; + VERIFY_HEAD(f); if (l) { - PerlIO_debug("PerlIO_pop f=%p %s\n", (void*)f, l->tab->name); - if (l->tab->Popped) { + PerlIO_debug("PerlIO_pop f=%p %s\n", (void*)f, + l->tab ? l->tab->name : "(Null)"); + if (l->tab && l->tab->Popped) { /* * If popped returns non-zero do not free its layer structure * it has either done so itself, or it is shared and still in @@ -738,8 +673,16 @@ PerlIO_pop(pTHX_ PerlIO *f) if ((*l->tab->Popped) (aTHX_ f) != 0) return; } - *f = l->next; - Safefree(l); + if (PerlIO_lockcnt(f)) { + /* we're in use; defer freeing the structure */ + PerlIOBase(f)->flags = PERLIO_F_CLEARED; + PerlIOBase(f)->tab = NULL; + } + else { + *f = l->next; + Safefree(l); + } + } } @@ -792,7 +735,8 @@ PerlIO_find_layer(pTHX_ const char *name, STRLEN len, int load) len = strlen(name); for (i = 0; i < PL_known_layers->cur; i++) { PerlIO_funcs * const f = PL_known_layers->array[i].funcs; - if (memEQ(f->name, name, len) && f->name[len] == 0) { + const STRLEN this_len = strlen(f->name); + if (this_len == len && memEQ(f->name, name, len)) { PerlIO_debug("%.*s => %p\n", (int) len, name, (void*)f); return f; } @@ -805,19 +749,18 @@ PerlIO_find_layer(pTHX_ const char *name, STRLEN len, int load) } else { SV * const pkgsv = newSVpvs("PerlIO"); SV * const layer = newSVpvn(name, len); - CV * const cv = Perl_get_cvn_flags(aTHX_ STR_WITH_LEN("PerlIO::Layer::NoWarnings"), 0); + CV * const cv = get_cvs("PerlIO::Layer::NoWarnings", 0); ENTER; - SAVEINT(PL_in_load_module); + SAVEBOOL(PL_in_load_module); if (cv) { SAVEGENERICSV(PL_warnhook); - PL_warnhook = (SV *) (SvREFCNT_inc_simple_NN(cv)); + PL_warnhook = MUTABLE_SV((SvREFCNT_inc_simple_NN(cv))); } - PL_in_load_module++; + PL_in_load_module = TRUE; /* * The two SVs are magically freed by load_module */ Perl_load_module(aTHX_ 0, pkgsv, NULL, layer, NULL); - PL_in_load_module--; LEAVE; return PerlIO_find_layer(aTHX_ name, len, 0); } @@ -832,7 +775,7 @@ static int perlio_mg_set(pTHX_ SV *sv, MAGIC *mg) { if (SvROK(sv)) { - IO * const io = GvIOn((GV *) SvRV(sv)); + IO * const io = GvIOn(MUTABLE_GV(SvRV(sv))); PerlIO * const ifp = IoIFP(io); PerlIO * const ofp = IoOFP(io); Perl_warn(aTHX_ "set %" SVf " %p %p %p", @@ -845,7 +788,7 @@ static int perlio_mg_get(pTHX_ SV *sv, MAGIC *mg) { if (SvROK(sv)) { - IO * const io = GvIOn((GV *) SvRV(sv)); + IO * const io = GvIOn(MUTABLE_GV(SvRV(sv))); PerlIO * const ifp = IoIFP(io); PerlIO * const ofp = IoOFP(io); Perl_warn(aTHX_ "get %" SVf " %p %p %p", @@ -876,6 +819,7 @@ MGVTBL perlio_vtab = { perlio_mg_free }; +XS(XS_io_MODIFY_SCALAR_ATTRIBUTES); /* prototype to pass -Wmissing-prototypes */ XS(XS_io_MODIFY_SCALAR_ATTRIBUTES) { dXSARGS; @@ -884,7 +828,7 @@ XS(XS_io_MODIFY_SCALAR_ATTRIBUTES) MAGIC *mg; int count = 0; int i; - sv_magic(sv, (SV *) av, PERL_MAGIC_ext, NULL, 0); + sv_magic(sv, MUTABLE_SV(av), PERL_MAGIC_ext, NULL, 0); SvRMAGICAL_off(sv); mg = mg_find(sv, PERL_MAGIC_ext); mg->mg_virtual = &perlio_vtab; @@ -916,9 +860,10 @@ PerlIO_tab_sv(pTHX_ PerlIO_funcs *tab) return sv; } +XS(XS_PerlIO__Layer__NoWarnings); /* prototype to pass -Wmissing-prototypes */ XS(XS_PerlIO__Layer__NoWarnings) { - /* This is used as a %SIG{__WARN__} handler to supress warnings + /* This is used as a %SIG{__WARN__} handler to suppress warnings during loading of layers. */ dVAR; @@ -929,6 +874,7 @@ XS(XS_PerlIO__Layer__NoWarnings) XSRETURN(0); } +XS(XS_PerlIO__Layer__find); /* prototype to pass -Wmissing-prototypes */ XS(XS_PerlIO__Layer__find) { dVAR; @@ -979,16 +925,15 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names) * seen as an invalid separator character. */ const char q = ((*s == '\'') ? '"' : '\''); - if (ckWARN(WARN_LAYER)) - Perl_warner(aTHX_ packWARN(WARN_LAYER), - "Invalid separator character %c%c%c in PerlIO layer specification %s", - q, *s, q, s); + Perl_ck_warner(aTHX_ packWARN(WARN_LAYER), + "Invalid separator character %c%c%c in PerlIO layer specification %s", + q, *s, q, s); SETERRNO(EINVAL, LIB_INVARG); return -1; } do { e++; - } while (isALNUM(*e)); + } while (isWORDCHAR(*e)); llen = e - s; if (*e == '(') { int nesting = 1; @@ -1016,10 +961,9 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names) */ case '\0': e--; - if (ckWARN(WARN_LAYER)) - Perl_warner(aTHX_ packWARN(WARN_LAYER), - "Argument list not closed for PerlIO layer \"%.*s\"", - (int) (e - s), s); + Perl_ck_warner(aTHX_ packWARN(WARN_LAYER), + "Argument list not closed for PerlIO layer \"%.*s\"", + (int) (e - s), s); return -1; default: /* @@ -1038,13 +982,11 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names) arg = newSVpvn(as, alen); PerlIO_list_push(aTHX_ av, layer, (arg) ? arg : &PL_sv_undef); - if (arg) - SvREFCNT_dec(arg); + SvREFCNT_dec(arg); } else { - if (ckWARN(WARN_LAYER)) - Perl_warner(aTHX_ packWARN(WARN_LAYER), "Unknown PerlIO layer \"%.*s\"", - (int) llen, s); + Perl_ck_warner(aTHX_ packWARN(WARN_LAYER), "Unknown PerlIO layer \"%.*s\"", + (int) llen, s); return -1; } } @@ -1111,7 +1053,7 @@ PERLIO_FUNCS_DECL(PerlIO_remove) = { PERLIO_K_DUMMY | PERLIO_K_UTF8, PerlIOPop_pushed, NULL, - NULL, + PerlIOBase_open, NULL, NULL, NULL, @@ -1140,7 +1082,7 @@ PerlIO_default_layers(pTHX) { dVAR; if (!PL_def_layerlist) { - const char * const s = (PL_tainting) ? NULL : PerlEnv_getenv("PERLIO"); + const char * const s = TAINTING_get ? NULL : PerlEnv_getenv("PERLIO"); PERLIO_FUNCS_DECL(*osLayer) = &PerlIO_unix; PL_def_layerlist = PerlIO_list_alloc(aTHX); PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_unix)); @@ -1154,9 +1096,6 @@ PerlIO_default_layers(pTHX) PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_perlio)); PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_stdio)); PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_crlf)); -#ifdef HAS_MMAP - PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_mmap)); -#endif PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_utf8)); PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_remove)); PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_byte)); @@ -1205,7 +1144,7 @@ PerlIO_stdstreams(pTHX) { dVAR; if (!PL_perlio) { - PerlIO_allocate(aTHX); + PerlIO_init_table(aTHX); PerlIO_fdopen(0, "Ir" PERLIO_STDTEXT); PerlIO_fdopen(1, "Iw" PERLIO_STDTEXT); PerlIO_fdopen(2, "Iw" PERLIO_STDTEXT); @@ -1215,14 +1154,20 @@ PerlIO_stdstreams(pTHX) PerlIO * PerlIO_push(pTHX_ PerlIO *f, PERLIO_FUNCS_DECL(*tab), const char *mode, SV *arg) { + VERIFY_HEAD(f); if (tab->fsize != sizeof(PerlIO_funcs)) { - mismatch: - Perl_croak(aTHX_ "Layer does not match this perl"); + Perl_croak( aTHX_ + "%s (%"UVuf") does not match %s (%"UVuf")", + "PerlIO layer function table size", (UV)tab->fsize, + "size expected by this perl", (UV)sizeof(PerlIO_funcs) ); } if (tab->size) { PerlIOl *l; if (tab->size < sizeof(PerlIOl)) { - goto mismatch; + Perl_croak( aTHX_ + "%s (%"UVuf") smaller than %s (%"UVuf")", + "PerlIO layer instance size", (UV)tab->size, + "size expected by this perl", (UV)sizeof(PerlIOl) ); } /* Real layer with a data area */ if (f) { @@ -1232,6 +1177,7 @@ PerlIO_push(pTHX_ PerlIO *f, PERLIO_FUNCS_DECL(*tab), const char *mode, SV *arg) if (l) { l->next = *f; l->tab = (PerlIO_funcs*) tab; + l->head = ((PerlIOl*)f)->head; *f = l; PerlIO_debug("PerlIO_push f=%p %s %s %p\n", (void*)f, tab->name, @@ -1259,12 +1205,30 @@ PerlIO_push(pTHX_ PerlIO *f, PERLIO_FUNCS_DECL(*tab), const char *mode, SV *arg) return f; } +PerlIO * +PerlIOBase_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, + IV n, const char *mode, int fd, int imode, int perm, + PerlIO *old, int narg, SV **args) +{ + PerlIO_funcs * const tab = PerlIO_layer_fetch(aTHX_ layers, n - 1, PerlIO_default_layer(aTHX_ 0)); + if (tab && tab->Open) { + PerlIO* ret = (*tab->Open)(aTHX_ tab, layers, n - 1, mode, fd, imode, perm, old, narg, args); + if (ret && PerlIO_push(aTHX_ ret, self, mode, PerlIOArg) == NULL) { + PerlIO_close(ret); + return NULL; + } + return ret; + } + SETERRNO(EINVAL, LIB_INVARG); + return NULL; +} + IV PerlIOBase_binmode(pTHX_ PerlIO *f) { if (PerlIOValid(f)) { /* Is layer suitable for raw stream ? */ - if (PerlIOBase(f)->tab->kind & PERLIO_K_RAW) { + if (PerlIOBase(f)->tab && PerlIOBase(f)->tab->kind & PERLIO_K_RAW) { /* Yes - turn off UTF-8-ness, to undo UTF-8 locale effects */ PerlIOBase(f)->flags &= ~PERLIO_F_UTF8; } @@ -1293,7 +1257,7 @@ PerlIORaw_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab) */ t = f; while (t && (l = *t)) { - if (l->tab->Binmode) { + if (l->tab && l->tab->Binmode) { /* Has a handler - normal case */ if ((*l->tab->Binmode)(aTHX_ t) == 0) { if (*t == l) { @@ -1311,7 +1275,8 @@ PerlIORaw_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab) } } if (PerlIOValid(f)) { - PerlIO_debug(":raw f=%p :%s\n", (void*)f, PerlIOBase(f)->tab->name); + PerlIO_debug(":raw f=%p :%s\n", (void*)f, + PerlIOBase(f)->tab ? PerlIOBase(f)->tab->name : "(Null)"); return 0; } } @@ -1340,6 +1305,8 @@ int PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names) { int code = 0; + ENTER; + save_scalar(PL_errgv); if (f && names) { PerlIO_list_t * const layers = PerlIO_list_alloc(aTHX); code = PerlIO_parse_layers(aTHX_ layers, names); @@ -1348,6 +1315,7 @@ PerlIO_apply_layers(pTHX_ PerlIO *f, const char *mode, const char *names) } PerlIO_list_free(aTHX_ layers); } + LEAVE; return code; } @@ -1361,7 +1329,8 @@ int PerlIO_binmode(pTHX_ PerlIO *f, int iotype, int mode, const char *names) { PerlIO_debug("PerlIO_binmode f=%p %s %c %x %s\n", (void*)f, - (PerlIOBase(f)) ? PerlIOBase(f)->tab->name : "(Null)", + (PerlIOBase(f) && PerlIOBase(f)->tab) ? + PerlIOBase(f)->tab->name : "(Null)", iotype, mode, (names) ? names : "(Null)"); if (names) { @@ -1388,7 +1357,9 @@ PerlIO_binmode(pTHX_ PerlIO *f, int iotype, int mode, const char *names) /* Perhaps we should turn on bottom-most aware layer e.g. Ilya's idea that UNIX TTY could serve */ - if (PerlIOBase(f)->tab->kind & PERLIO_K_CANCRLF) { + if (PerlIOBase(f)->tab && + PerlIOBase(f)->tab->kind & PERLIO_K_CANCRLF) + { if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF)) { /* Not in text mode - flush any pending stuff and flip it */ PerlIO_flush(f); @@ -1435,6 +1406,9 @@ Perl_PerlIO_close(pTHX_ PerlIO *f) const int code = PerlIO__close(aTHX_ f); while (PerlIOValid(f)) { PerlIO_pop(aTHX_ f); + if (PerlIO_lockcnt(f)) + /* we're in use; the 'pop' deferred freeing the structure */ + f = PerlIONext(f); } return code; } @@ -1454,12 +1428,13 @@ PerlIO_layer_from_ref(pTHX_ SV *sv) /* * For any scalar type load the handler which is bundled with perl */ - if (SvTYPE(sv) < SVt_PVAV) { + if (SvTYPE(sv) < SVt_PVAV && (!isGV_with_GP(sv) || SvFAKE(sv))) { PerlIO_funcs *f = PerlIO_find_layer(aTHX_ STR_WITH_LEN("scalar"), 1); /* This isn't supposed to happen, since PerlIO::scalar is core, * but could happen anyway in smaller installs or with PAR */ - if (!f && ckWARN(WARN_LAYER)) - Perl_warner(aTHX_ packWARN(WARN_LAYER), "Unknown PerlIO layer \"scalar\""); + if (!f) + /* diag_listed_as: Unknown PerlIO layer "%s" */ + Perl_ck_warner(aTHX_ packWARN(WARN_LAYER), "Unknown PerlIO layer \"scalar\""); return f; } @@ -1560,12 +1535,11 @@ PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd, layera = PerlIO_list_alloc(aTHX); while (l) { SV *arg = NULL; - if (l->tab->Getarg) + if (l->tab && l->tab->Getarg) arg = (*l->tab->Getarg) (aTHX_ &l, NULL, 0); PerlIO_list_push(aTHX_ layera, l->tab, (arg) ? arg : &PL_sv_undef); - if (arg) - SvREFCNT_dec(arg); + SvREFCNT_dec(arg); l = *PerlIONext(&l); } } @@ -1682,20 +1656,21 @@ Perl_PerlIO_flush(pTHX_ PerlIO *f) else { /* * Is it good API design to do flush-all on NULL, a potentially - * errorneous input? Maybe some magical value (PerlIO* + * erroneous input? Maybe some magical value (PerlIO* * PERLIO_FLUSH_ALL = (PerlIO*)-1;)? Yes, stdio does similar * things on fflush(NULL), but should we be bound by their design * decisions? --jhi */ - PerlIO **table = &PL_perlio; + PerlIOl **table = &PL_perlio; + PerlIOl *ff; int code = 0; - while ((f = *table)) { + while ((ff = *table)) { int i; - table = (PerlIO **) (f++); + table = (PerlIOl **) (ff++); for (i = 1; i < PERLIO_TABLE_SIZE; i++) { - if (*f && PerlIO_flush(f) != 0) + if (ff->next && PerlIO_flush(&(ff->next)) != 0) code = -1; - f++; + ff++; } } return code; @@ -1706,17 +1681,17 @@ void PerlIOBase_flush_linebuf(pTHX) { dVAR; - PerlIO **table = &PL_perlio; - PerlIO *f; + PerlIOl **table = &PL_perlio; + PerlIOl *f; while ((f = *table)) { int i; - table = (PerlIO **) (f++); + table = (PerlIOl **) (f++); for (i = 1; i < PERLIO_TABLE_SIZE; i++) { - if (*f - && (PerlIOBase(f)-> + if (f->next + && (PerlIOBase(&(f->next))-> flags & (PERLIO_F_LINEBUF | PERLIO_F_CANWRITE)) == (PERLIO_F_LINEBUF | PERLIO_F_CANWRITE)) - PerlIO_flush(f); + PerlIO_flush(&(f->next)); f++; } } @@ -1771,10 +1746,7 @@ PerlIO_has_base(PerlIO *f) if (tab) return (tab->Get_base != NULL); - SETERRNO(EINVAL, LIB_INVARG); } - else - SETERRNO(EBADF, SS_IVCHAN); return 0; } @@ -1782,15 +1754,14 @@ PerlIO_has_base(PerlIO *f) int PerlIO_fast_gets(PerlIO *f) { - if (PerlIOValid(f) && (PerlIOBase(f)->flags & PERLIO_F_FASTGETS)) { - const PerlIO_funcs * const tab = PerlIOBase(f)->tab; + if (PerlIOValid(f)) { + if (PerlIOBase(f)->flags & PERLIO_F_FASTGETS) { + const PerlIO_funcs * const tab = PerlIOBase(f)->tab; - if (tab) - return (tab->Set_ptrcnt != NULL); - SETERRNO(EINVAL, LIB_INVARG); + if (tab) + return (tab->Set_ptrcnt != NULL); + } } - else - SETERRNO(EBADF, SS_IVCHAN); return 0; } @@ -1803,10 +1774,7 @@ PerlIO_has_cntptr(PerlIO *f) if (tab) return (tab->Get_ptr != NULL && tab->Get_cnt != NULL); - SETERRNO(EINVAL, LIB_INVARG); } - else - SETERRNO(EBADF, SS_IVCHAN); return 0; } @@ -1819,10 +1787,7 @@ PerlIO_canset_cnt(PerlIO *f) if (tab) return (tab->Set_ptrcnt != NULL); - SETERRNO(EINVAL, LIB_INVARG); } - else - SETERRNO(EBADF, SS_IVCHAN); return 0; } @@ -1833,9 +1798,10 @@ Perl_PerlIO_get_base(pTHX_ PerlIO *f) Perl_PerlIO_or_fail(f, Get_base, NULL, (aTHX_ f)); } -int +SSize_t Perl_PerlIO_get_bufsiz(pTHX_ PerlIO *f) { + /* Note that Get_bufsiz returns a Size_t */ Perl_PerlIO_or_fail(f, Get_bufsiz, -1, (aTHX_ f)); } @@ -1845,20 +1811,20 @@ Perl_PerlIO_get_ptr(pTHX_ PerlIO *f) Perl_PerlIO_or_fail(f, Get_ptr, NULL, (aTHX_ f)); } -int +SSize_t Perl_PerlIO_get_cnt(pTHX_ PerlIO *f) { Perl_PerlIO_or_fail(f, Get_cnt, -1, (aTHX_ f)); } void -Perl_PerlIO_set_cnt(pTHX_ PerlIO *f, int cnt) +Perl_PerlIO_set_cnt(pTHX_ PerlIO *f, SSize_t cnt) { Perl_PerlIO_or_fail_void(f, Set_ptrcnt, (aTHX_ f, NULL, cnt)); } void -Perl_PerlIO_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, int cnt) +Perl_PerlIO_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt) { Perl_PerlIO_or_fail_void(f, Set_ptrcnt, (aTHX_ f, ptr, cnt)); } @@ -1876,7 +1842,7 @@ PerlIOUtf8_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab) PERL_UNUSED_ARG(mode); PERL_UNUSED_ARG(arg); if (PerlIOValid(f)) { - if (tab->kind & PERLIO_K_UTF8) + if (tab && tab->kind & PERLIO_K_UTF8) PerlIOBase(f)->flags |= PERLIO_F_UTF8; else PerlIOBase(f)->flags &= ~PERLIO_F_UTF8; @@ -1889,10 +1855,10 @@ PERLIO_FUNCS_DECL(PerlIO_utf8) = { sizeof(PerlIO_funcs), "utf8", 0, - PERLIO_K_DUMMY | PERLIO_K_UTF8, + PERLIO_K_DUMMY | PERLIO_K_UTF8 | PERLIO_K_MULTIARG, PerlIOUtf8_pushed, NULL, - NULL, + PerlIOBase_open, NULL, NULL, NULL, @@ -1920,10 +1886,10 @@ PERLIO_FUNCS_DECL(PerlIO_byte) = { sizeof(PerlIO_funcs), "bytes", 0, - PERLIO_K_DUMMY, + PERLIO_K_DUMMY | PERLIO_K_MULTIARG, PerlIOUtf8_pushed, NULL, - NULL, + PerlIOBase_open, NULL, NULL, NULL, @@ -1947,20 +1913,6 @@ PERLIO_FUNCS_DECL(PerlIO_byte) = { NULL, /* set_ptrcnt */ }; -PerlIO * -PerlIORaw_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, - IV n, const char *mode, int fd, int imode, int perm, - PerlIO *old, int narg, SV **args) -{ - PerlIO_funcs * const tab = PerlIO_default_btm(); - PERL_UNUSED_ARG(self); - if (tab && tab->Open) - return (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm, - old, narg, args); - SETERRNO(EINVAL, LIB_INVARG); - return NULL; -} - PERLIO_FUNCS_DECL(PerlIO_raw) = { sizeof(PerlIO_funcs), "raw", @@ -1968,7 +1920,7 @@ PERLIO_FUNCS_DECL(PerlIO_raw) = { PERLIO_K_DUMMY, PerlIORaw_pushed, PerlIOBase_popped, - PerlIORaw_open, + PerlIOBase_open, NULL, NULL, NULL, @@ -2045,7 +1997,7 @@ PerlIOBase_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab) l->flags &= ~(PERLIO_F_CANREAD | PERLIO_F_CANWRITE | PERLIO_F_TRUNCATE | PERLIO_F_APPEND); - if (tab->Set_ptrcnt != NULL) + if (tab && tab->Set_ptrcnt != NULL) l->flags |= PERLIO_F_FASTGETS; if (mode) { if (*mode == IoTYPE_NUMERIC || *mode == IoTYPE_IMPLICIT) @@ -2132,7 +2084,7 @@ PerlIOBase_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) SSize_t avail = PerlIO_get_cnt(f); SSize_t take = 0; if (avail > 0) - take = ((SSize_t)count < avail) ? (SSize_t)count : avail; + take = (((SSize_t) count >= 0) && ((SSize_t)count < avail)) ? (SSize_t)count : avail; if (take > 0) { STDCHAR *ptr = PerlIO_get_ptr(f); Copy(ptr, buf, take, STDCHAR); @@ -2243,7 +2195,7 @@ PerlIO_sv_dup(pTHX_ SV *arg, CLONE_PARAMS *param) { if (!arg) return NULL; -#ifdef sv_dup +#ifdef USE_ITHREADS if (param) { arg = sv_dup(arg, param); SvREFCNT_inc_simple_void_NN(arg); @@ -2274,14 +2226,14 @@ PerlIOBase_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) SV *arg = NULL; char buf[8]; PerlIO_debug("PerlIOBase_dup %s f=%p o=%p param=%p\n", - self->name, (void*)f, (void*)o, (void*)param); - if (self->Getarg) + self ? self->name : "(Null)", + (void*)f, (void*)o, (void*)param); + if (self && self->Getarg) arg = (*self->Getarg)(aTHX_ o, param, flags); f = PerlIO_push(aTHX_ f, self, PerlIO_modestr(o,buf), arg); - if (PerlIOBase(o)->flags & PERLIO_F_UTF8) + if (f && PerlIOBase(o)->flags & PERLIO_F_UTF8) PerlIOBase(f)->flags |= PERLIO_F_UTF8; - if (arg) - SvREFCNT_dec(arg); + SvREFCNT_dec(arg); } return f; } @@ -2313,10 +2265,7 @@ S_more_refcounted_fds(pTHX_ const int new_fd) { #ifdef USE_ITHREADS MUTEX_UNLOCK(&PL_perlio_mutex); #endif - /* Can't use PerlIO to write as it allocates memory */ - PerlLIO_write(PerlIO_fileno(Perl_error_log), - PL_no_mem, strlen(PL_no_mem)); - my_exit(1); + croak_no_mem(); } PL_perlio_fd_refcnt_size = new_max; @@ -2352,6 +2301,7 @@ PerlIOUnix_refcnt_inc(int fd) PL_perlio_fd_refcnt[fd]++; if (PL_perlio_fd_refcnt[fd] <= 0) { + /* diag_listed_as: refcnt_inc: fd %d%s */ Perl_croak(aTHX_ "refcnt_inc: fd %d: %d <= 0\n", fd, PL_perlio_fd_refcnt[fd]); } @@ -2362,6 +2312,7 @@ PerlIOUnix_refcnt_inc(int fd) MUTEX_UNLOCK(&PL_perlio_mutex); #endif } else { + /* diag_listed_as: refcnt_inc: fd %d%s */ Perl_croak(aTHX_ "refcnt_inc: fd %d < 0\n", fd); } } @@ -2369,7 +2320,6 @@ PerlIOUnix_refcnt_inc(int fd) int PerlIOUnix_refcnt_dec(int fd) { - dTHX; int cnt = 0; if (fd >= 0) { dVAR; @@ -2377,11 +2327,13 @@ PerlIOUnix_refcnt_dec(int fd) MUTEX_LOCK(&PL_perlio_mutex); #endif if (fd >= PL_perlio_fd_refcnt_size) { - Perl_croak(aTHX_ "refcnt_dec: fd %d >= refcnt_size %d\n", + /* diag_listed_as: refcnt_dec: fd %d%s */ + Perl_croak_nocontext("refcnt_dec: fd %d >= refcnt_size %d\n", fd, PL_perlio_fd_refcnt_size); } if (PL_perlio_fd_refcnt[fd] <= 0) { - Perl_croak(aTHX_ "refcnt_dec: fd %d: %d <= 0\n", + /* diag_listed_as: refcnt_dec: fd %d%s */ + Perl_croak_nocontext("refcnt_dec: fd %d: %d <= 0\n", fd, PL_perlio_fd_refcnt[fd]); } cnt = --PL_perlio_fd_refcnt[fd]; @@ -2390,7 +2342,39 @@ PerlIOUnix_refcnt_dec(int fd) MUTEX_UNLOCK(&PL_perlio_mutex); #endif } else { - Perl_croak(aTHX_ "refcnt_dec: fd %d < 0\n", fd); + /* diag_listed_as: refcnt_dec: fd %d%s */ + Perl_croak_nocontext("refcnt_dec: fd %d < 0\n", fd); + } + return cnt; +} + +int +PerlIOUnix_refcnt(int fd) +{ + dTHX; + int cnt = 0; + if (fd >= 0) { + dVAR; +#ifdef USE_ITHREADS + MUTEX_LOCK(&PL_perlio_mutex); +#endif + if (fd >= PL_perlio_fd_refcnt_size) { + /* diag_listed_as: refcnt: fd %d%s */ + Perl_croak(aTHX_ "refcnt: fd %d >= refcnt_size %d\n", + fd, PL_perlio_fd_refcnt_size); + } + if (PL_perlio_fd_refcnt[fd] <= 0) { + /* diag_listed_as: refcnt: fd %d%s */ + Perl_croak(aTHX_ "refcnt: fd %d: %d <= 0\n", + fd, PL_perlio_fd_refcnt[fd]); + } + cnt = PL_perlio_fd_refcnt[fd]; +#ifdef USE_ITHREADS + MUTEX_UNLOCK(&PL_perlio_mutex); +#endif + } else { + /* diag_listed_as: refcnt: fd %d%s */ + Perl_croak(aTHX_ "refcnt: fd %d < 0\n", fd); } return cnt; } @@ -2475,6 +2459,41 @@ typedef struct { int oflags; /* open/fcntl flags */ } PerlIOUnix; +static void +S_lockcnt_dec(pTHX_ const void* f) +{ + PerlIO_lockcnt((PerlIO*)f)--; +} + + +/* call the signal handler, and if that handler happens to clear + * this handle, free what we can and return true */ + +static bool +S_perlio_async_run(pTHX_ PerlIO* f) { + ENTER; + SAVEDESTRUCTOR_X(S_lockcnt_dec, (void*)f); + PerlIO_lockcnt(f)++; + PERL_ASYNC_CHECK(); + if ( !(PerlIOBase(f)->flags & PERLIO_F_CLEARED) ) { + LEAVE; + return 0; + } + /* we've just run some perl-level code that could have done + * anything, including closing the file or clearing this layer. + * If so, free any lower layers that have already been + * cleared, then return an error. */ + while (PerlIOValid(f) && + (PerlIOBase(f)->flags & PERLIO_F_CLEARED)) + { + const PerlIOl *l = *f; + *f = l->next; + Safefree(l); + } + LEAVE; + return 1; +} + int PerlIOUnix_oflags(const char *mode) { @@ -2520,10 +2539,15 @@ PerlIOUnix_oflags(const char *mode) oflags &= ~O_BINARY; mode++; } - /* - * Always open in binary mode - */ - oflags |= O_BINARY; + else { +#ifdef PERLIO_USING_CRLF + /* + * If neither "t" nor "b" was specified, open the file + * in O_BINARY mode. + */ + oflags |= O_BINARY; +#endif + } if (*mode || oflags == -1) { SETERRNO(EINVAL, LIB_INVARG); oflags = -1; @@ -2607,7 +2631,7 @@ PerlIOUnix_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, int perm, PerlIO *f, int narg, SV **args) { if (PerlIOValid(f)) { - if (PerlIOBase(f)->flags & PERLIO_F_OPEN) + if (PerlIOBase(f)->tab && PerlIOBase(f)->flags & PERLIO_F_OPEN) (*PerlIOBase(f)->tab->Close)(aTHX_ f); } if (narg > 0) { @@ -2615,10 +2639,17 @@ PerlIOUnix_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, mode++; else { imode = PerlIOUnix_oflags(mode); +#ifdef VMS + perm = 0777; /* preserve RMS defaults, ACL inheritance, etc. */ +#else perm = 0666; +#endif } if (imode != -1) { - const char *path = SvPV_nolen_const(*args); + STRLEN len; + const char *path = SvPV_const(*args, len); + if (!IS_SAFE_PATHNAME(path, len, "open")) + return NULL; fd = PerlLIO_open3(path, imode, perm); } } @@ -2674,7 +2705,10 @@ SSize_t PerlIOUnix_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) { dVAR; - const int fd = PerlIOSelf(f, PerlIOUnix)->fd; + int fd; + if (PerlIO_lockcnt(f)) /* in use: abort ungracefully */ + return -1; + fd = PerlIOSelf(f, PerlIOUnix)->fd; #ifdef PERLIO_STD_SPECIAL if (fd == 0) return PERLIO_STD_IN(fd, vbuf, count); @@ -2697,7 +2731,9 @@ PerlIOUnix_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) } return len; } - PERL_ASYNC_CHECK(); + /* EINTR */ + if (PL_sig_pending && S_perlio_async_run(aTHX_ f)) + return -1; } /*NOTREACHED*/ } @@ -2706,7 +2742,10 @@ SSize_t PerlIOUnix_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count) { dVAR; - const int fd = PerlIOSelf(f, PerlIOUnix)->fd; + int fd; + if (PerlIO_lockcnt(f)) /* in use: abort ungracefully */ + return -1; + fd = PerlIOSelf(f, PerlIOUnix)->fd; #ifdef PERLIO_STD_SPECIAL if (fd == 1 || fd == 2) return PERLIO_STD_OUT(fd, vbuf, count); @@ -2721,7 +2760,9 @@ PerlIOUnix_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count) } return len; } - PERL_ASYNC_CHECK(); + /* EINTR */ + if (PL_sig_pending && S_perlio_async_run(aTHX_ f)) + return -1; } /*NOTREACHED*/ } @@ -2756,7 +2797,9 @@ PerlIOUnix_close(pTHX_ PerlIO *f) code = -1; break; } - PERL_ASYNC_CHECK(); + /* EINTR */ + if (PL_sig_pending && S_perlio_async_run(aTHX_ f)) + return -1; } if (code == 0) { PerlIOBase(f)->flags &= ~PERLIO_F_OPEN; @@ -2862,6 +2905,7 @@ PerlIOStdio_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab PerlIOSelf(f, PerlIOStdio)->stdio = stdio; /* We never call down so do any pending stuff now */ PerlIO_flush(PerlIONext(f)); + return PerlIOBase_pushed(aTHX_ f, mode, arg, tab); } else { return -1; @@ -2918,9 +2962,12 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, { char tmode[8]; if (PerlIOValid(f)) { - const char * const path = SvPV_nolen_const(*args); + STRLEN len; + const char * const path = SvPV_const(*args, len); PerlIOStdio * const s = PerlIOSelf(f, PerlIOStdio); FILE *stdio; + if (!IS_SAFE_PATHNAME(path, len, "open")) + return NULL; PerlIOUnix_refcnt_dec(fileno(s->stdio)); stdio = PerlSIO_freopen(path, (mode = PerlIOStdio_mode(mode, tmode)), s->stdio); @@ -2932,7 +2979,10 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, } else { if (narg > 0) { - const char * const path = SvPV_nolen_const(*args); + STRLEN len; + const char * const path = SvPV_const(*args, len); + if (!IS_SAFE_PATHNAME(path, len, "open")) + return NULL; if (*mode == IoTYPE_NUMERIC) { mode++; fd = PerlLIO_open3(path, imode, perm); @@ -3031,7 +3081,9 @@ PerlIOStdio_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) stdio = PerlSIO_fdopen(fd, PerlIO_modestr(o,mode)); set_this: PerlIOSelf(f, PerlIOStdio)->stdio = stdio; - PerlIOUnix_refcnt_inc(fileno(stdio)); + if(stdio) { + PerlIOUnix_refcnt_inc(fileno(stdio)); + } } return f; } @@ -3054,7 +3106,7 @@ PerlIOStdio_invalidate_fileno(pTHX_ FILE *f) */ f->_fileno = -1; return 1; -# elif defined(__sun__) +# elif defined(__sun) PERL_UNUSED_ARG(f); return 0; # elif defined(__hpux) @@ -3095,9 +3147,7 @@ PerlIOStdio_invalidate_fileno(pTHX_ FILE *f) f->_file = -1; return 1; # elif defined(WIN32) -# if defined(__BORLANDC__) - f->fd = PerlLIO_dup(fileno(f)); -# elif defined(UNDER_CE) +# if defined(UNDER_CE) /* WIN_CE does not have access to FILE internals, it hardly has FILE structure at all */ @@ -3129,8 +3179,8 @@ PerlIOStdio_close(pTHX_ PerlIO *f) const int fd = fileno(stdio); int invalidate = 0; IV result = 0; - int saveerr = 0; int dupfd = -1; + dSAVEDERRNO; #ifdef USE_ITHREADS dVAR; #endif @@ -3164,7 +3214,7 @@ PerlIOStdio_close(pTHX_ PerlIO *f) fileno slot of the FILE * */ result = PerlIO_flush(f); - saveerr = errno; + SAVE_ERRNO; invalidate = PerlIOStdio_invalidate_fileno(aTHX_ stdio); if (!invalidate) { #ifdef USE_ITHREADS @@ -3197,13 +3247,15 @@ PerlIOStdio_close(pTHX_ PerlIO *f) } #endif } + } else { + SAVE_ERRNO; /* This is here only to silence compiler warnings */ } result = PerlSIO_fclose(stdio); /* We treat error from stdio as success if we invalidated errno may NOT be expected EBADF */ if (invalidate && result != 0) { - errno = saveerr; + RESTORE_ERRNO; result = 0; } #ifdef SOCKS5_VERSION_NAME @@ -3225,8 +3277,11 @@ SSize_t PerlIOStdio_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) { dVAR; - FILE * const s = PerlIOSelf(f, PerlIOStdio)->stdio; + FILE * s; SSize_t got = 0; + if (PerlIO_lockcnt(f)) /* in use: abort ungracefully */ + return -1; + s = PerlIOSelf(f, PerlIOStdio)->stdio; for (;;) { if (count == 1) { STDCHAR *buf = (STDCHAR *) vbuf; @@ -3246,7 +3301,8 @@ PerlIOStdio_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) got = -1; if (got >= 0 || errno != EINTR) break; - PERL_ASYNC_CHECK(); + if (PL_sig_pending && S_perlio_async_run(aTHX_ f)) + return -1; SETERRNO(0,0); /* just in case */ } return got; @@ -3315,12 +3371,15 @@ PerlIOStdio_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count) { dVAR; SSize_t got; + if (PerlIO_lockcnt(f)) /* in use: abort ungracefully */ + return -1; for (;;) { got = PerlSIO_fwrite(vbuf, 1, count, PerlIOSelf(f, PerlIOStdio)->stdio); if (got >= 0 || errno != EINTR) break; - PERL_ASYNC_CHECK(); + if (PL_sig_pending && S_perlio_async_run(aTHX_ f)) + return -1; SETERRNO(0,0); /* just in case */ } return got; @@ -3365,9 +3424,9 @@ PerlIOStdio_flush(pTHX_ PerlIO *f) /* * Not writeable - sync by attempting a seek */ - const int err = errno; + dSAVE_ERRNO; if (PerlSIO_fseek(stdio, (Off_t) 0, SEEK_CUR) != 0) - errno = err; + RESTORE_ERRNO; #endif } return 0; @@ -3482,9 +3541,12 @@ PerlIOStdio_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt) IV PerlIOStdio_fill(pTHX_ PerlIO *f) { - FILE * const stdio = PerlIOSelf(f, PerlIOStdio)->stdio; + FILE * stdio; int c; PERL_UNUSED_CONTEXT; + if (PerlIO_lockcnt(f)) /* in use: abort ungracefully */ + return -1; + stdio = PerlIOSelf(f, PerlIOStdio)->stdio; /* * fflush()ing read-only streams can cause trouble on some stdio-s @@ -3499,7 +3561,8 @@ PerlIOStdio_fill(pTHX_ PerlIO *f) break; if (! PerlSIO_ferror(stdio) || errno != EINTR) return EOF; - PERL_ASYNC_CHECK(); + if (PL_sig_pending && S_perlio_async_run(aTHX_ f)) + return -1; SETERRNO(0,0); } @@ -3647,7 +3710,7 @@ PerlIO_findFILE(PerlIO *f) /* Uses fallback "mode" via PerlIO_modestr() in PerlIO_exportFILE */ /* However, we're not really exporting a FILE * to someone else (who becomes responsible for closing it, or calling PerlIO_releaseFILE()) - So we need to undo its refernce count increase on the underlying file + So we need to undo its reference count increase on the underlying file descriptor. We have to do this, because if the loop above returns you the FILE *, then *it* didn't increase any reference count. So there's only one way to be consistent. */ @@ -3669,12 +3732,14 @@ PerlIO_releaseFILE(PerlIO *p, FILE *f) while ((l = *p)) { if (l->tab == &PerlIO_stdio) { PerlIOStdio *s = PerlIOSelf(&l, PerlIOStdio); - if (s->stdio == f) { - dTHX; + if (s->stdio == f) { /* not in a loop */ const int fd = fileno(f); if (fd >= 0) PerlIOUnix_refcnt_dec(fd); - PerlIO_pop(aTHX_ p); + { + dTHX; + PerlIO_pop(aTHX_ p); + } return; } } @@ -3762,6 +3827,21 @@ PerlIOBuf_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, */ PerlLIO_setmode(fd, O_BINARY); #endif +#ifdef VMS + /* Enable line buffering with record-oriented regular files + * so we don't introduce an extraneous record boundary when + * the buffer fills up. + */ + if (PerlIOBase(f)->flags & PERLIO_F_CANWRITE) { + Stat_t st; + if (PerlLIO_fstat(fd, &st) == 0 + && S_ISREG(st.st_mode) + && (st.st_fab_rfm == FAB$C_VAR + || st.st_fab_rfm == FAB$C_VFC)) { + PerlIOBase(f)->flags |= PERLIO_F_LINEBUF; + } + } +#endif } } } @@ -3950,7 +4030,7 @@ PerlIOBuf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count) */ b->posn -= b->bufsiz; } - if (avail > (SSize_t) count) { + if ((SSize_t) count >= 0 && avail > (SSize_t) count) { /* * If we have space for more than count, just move count */ @@ -4000,7 +4080,7 @@ PerlIOBuf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count) } while (count > 0) { SSize_t avail = b->bufsiz - (b->ptr - b->buf); - if ((SSize_t) count < avail) + if ((SSize_t) count >= 0 && (SSize_t) count < avail) avail = count; if (flushptr > buf && flushptr <= buf + avail) avail = flushptr - buf; @@ -4015,7 +4095,8 @@ PerlIOBuf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count) PerlIO_flush(f); } if (b->ptr >= (b->buf + b->bufsiz)) - PerlIO_flush(f); + if (PerlIO_flush(f) == -1) + return -1; } if (PerlIOBase(f)->flags & PERLIO_F_UNBUF) PerlIO_flush(f); @@ -4121,8 +4202,8 @@ PerlIOBuf_get_base(pTHX_ PerlIO *f) if (!b->buf) { if (!b->bufsiz) - b->bufsiz = 4096; - b->buf = Newxz(b->buf,b->bufsiz, STDCHAR); + b->bufsiz = PERLIOBUF_DEFAULT_BUFSIZ; + Newxz(b->buf,b->bufsiz, STDCHAR); if (!b->buf) { b->buf = (STDCHAR *) & b->oneword; b->bufsiz = sizeof(b->oneword); @@ -4274,7 +4355,7 @@ PerlIOPending_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) { SSize_t avail = PerlIO_get_cnt(f); SSize_t got = 0; - if ((SSize_t)count < avail) + if ((SSize_t) count >= 0 && (SSize_t)count < avail) avail = count; if (avail > 0) got = PerlIOBuf_read(aTHX_ f, vbuf, avail); @@ -4368,12 +4449,10 @@ PerlIOCrlf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab) PerlIOBase(f)->flags); #endif { - /* Enable the first CRLF capable layer you can find, but if none - * found, the one we just pushed is fine. This results in at - * any given moment at most one CRLF-capable layer being enabled - * in the whole layer stack. */ + /* If the old top layer is a CRLF layer, reactivate it (if + * necessary) and remove this new layer from the stack */ PerlIO *g = PerlIONext(f); - while (PerlIOValid(g)) { + if (PerlIOValid(g)) { PerlIOl *b = PerlIOBase(g); if (b && b->tab == &PerlIO_crlf) { if (!(b->flags & PERLIO_F_CRLF)) @@ -4381,8 +4460,7 @@ PerlIOCrlf_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab) S_inherit_utf8_flag(g); PerlIO_pop(aTHX_ f); return code; - } - g = PerlIONext(g); + } } } S_inherit_utf8_flag(f); @@ -4395,7 +4473,7 @@ PerlIOCrlf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count) { PerlIOCrlf * const c = PerlIOSelf(f, PerlIOCrlf); if (c->nl) { /* XXXX Shouldn't it be done only if b->ptr > c->nl? */ - *(c->nl) = 0xd; + *(c->nl) = NATIVE_0xd; c->nl = NULL; } if (!(PerlIOBase(f)->flags & PERLIO_F_CRLF)) @@ -4418,14 +4496,15 @@ PerlIOCrlf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count) const int ch = *--buf; if (ch == '\n') { if (b->ptr - 2 >= b->buf) { - *--(b->ptr) = 0xa; - *--(b->ptr) = 0xd; + *--(b->ptr) = NATIVE_0xa; + *--(b->ptr) = NATIVE_0xd; unread++; count--; } else { /* If b->ptr - 1 == b->buf, we are undoing reading 0xa */ - *--(b->ptr) = 0xa; /* Works even if 0xa == '\r' */ + *--(b->ptr) = NATIVE_0xa; /* Works even if 0xa == + '\r' */ unread++; count--; } @@ -4437,6 +4516,8 @@ PerlIOCrlf_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count) } } } + if (count > 0) + unread += PerlIOBase_unread(aTHX_ f, (const STDCHAR *) vbuf + unread, count); return unread; } } @@ -4450,15 +4531,15 @@ PerlIOCrlf_get_cnt(pTHX_ PerlIO *f) PerlIO_get_base(f); if (PerlIOBase(f)->flags & PERLIO_F_RDBUF) { PerlIOCrlf * const c = PerlIOSelf(f, PerlIOCrlf); - if ((PerlIOBase(f)->flags & PERLIO_F_CRLF) && (!c->nl || *c->nl == 0xd)) { + if ((PerlIOBase(f)->flags & PERLIO_F_CRLF) && (!c->nl || *c->nl == NATIVE_0xd)) { STDCHAR *nl = (c->nl) ? c->nl : b->ptr; scan: - while (nl < b->end && *nl != 0xd) + while (nl < b->end && *nl != NATIVE_0xd) nl++; - if (nl < b->end && *nl == 0xd) { + if (nl < b->end && *nl == NATIVE_0xd) { test: if (nl + 1 < b->end) { - if (nl[1] == 0xa) { + if (nl[1] == NATIVE_0xa) { *nl = '\n'; c->nl = nl; } @@ -4498,7 +4579,7 @@ PerlIOCrlf_get_cnt(pTHX_ PerlIO *f) b->buf--; /* Point at space */ b->ptr = nl = b->buf; /* Which is what we hand * off */ - *nl = 0xd; /* Fill in the CR */ + *nl = NATIVE_0xd; /* Fill in the CR */ if (code == 0) goto test; /* fill() call worked */ /* @@ -4524,8 +4605,8 @@ PerlIOCrlf_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt) if (!ptr) { if (c->nl) { ptr = c->nl + 1; - if (ptr == b->end && *c->nl == 0xd) { - /* Defered CR at end of buffer case - we lied about count */ + if (ptr == b->end && *c->nl == NATIVE_0xd) { + /* Deferred CR at end of buffer case - we lied about count */ ptr--; } } @@ -4542,8 +4623,8 @@ PerlIOCrlf_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt) */ IV flags = PerlIOBase(f)->flags; STDCHAR *chk = (c->nl) ? (c->nl+1) : b->end; - if (ptr+cnt == c->nl && c->nl+1 == b->end && *c->nl == 0xd) { - /* Defered CR at end of buffer case - we lied about count */ + if (ptr+cnt == c->nl && c->nl+1 == b->end && *c->nl == NATIVE_0xd) { + /* Deferred CR at end of buffer case - we lied about count */ chk--; } chk -= cnt; @@ -4560,7 +4641,7 @@ PerlIOCrlf_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt) /* * They have taken what we lied about */ - *(c->nl) = 0xd; + *(c->nl) = NATIVE_0xd; c->nl = NULL; ptr++; } @@ -4595,8 +4676,8 @@ PerlIOCrlf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count) break; } else { - *(b->ptr)++ = 0xd; /* CR */ - *(b->ptr)++ = 0xa; /* LF */ + *(b->ptr)++ = NATIVE_0xd; /* CR */ + *(b->ptr)++ = NATIVE_0xa; /* LF */ buf++; if (PerlIOBase(f)->flags & PERLIO_F_LINEBUF) { PerlIO_flush(f); @@ -4624,7 +4705,7 @@ PerlIOCrlf_flush(pTHX_ PerlIO *f) { PerlIOCrlf * const c = PerlIOSelf(f, PerlIOCrlf); if (c->nl) { - *(c->nl) = 0xd; + *(c->nl) = NATIVE_0xd; c->nl = NULL; } return PerlIOBuf_flush(aTHX_ f); @@ -4638,9 +4719,7 @@ PerlIOCrlf_binmode(pTHX_ PerlIO *f) PerlIOBase(f)->flags &= ~PERLIO_F_CRLF; #ifndef PERLIO_USING_CRLF /* CRLF is unusual case - if this is just the :crlf layer pop it */ - if (PerlIOBase(f)->tab == &PerlIO_crlf) { - PerlIO_pop(aTHX_ f); - } + PerlIO_pop(aTHX_ f); #endif } return 0; @@ -4677,297 +4756,6 @@ PERLIO_FUNCS_DECL(PerlIO_crlf) = { PerlIOCrlf_set_ptrcnt, }; -#ifdef HAS_MMAP -/*--------------------------------------------------------------------------------------*/ -/* - * mmap as "buffer" layer - */ - -typedef struct { - PerlIOBuf base; /* PerlIOBuf stuff */ - Mmap_t mptr; /* Mapped address */ - Size_t len; /* mapped length */ - STDCHAR *bbuf; /* malloced buffer if map fails */ -} PerlIOMmap; - -IV -PerlIOMmap_map(pTHX_ PerlIO *f) -{ - dVAR; - PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap); - const IV flags = PerlIOBase(f)->flags; - IV code = 0; - if (m->len) - abort(); - if (flags & PERLIO_F_CANREAD) { - PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf); - const int fd = PerlIO_fileno(f); - Stat_t st; - code = Fstat(fd, &st); - if (code == 0 && S_ISREG(st.st_mode)) { - SSize_t len = st.st_size - b->posn; - if (len > 0) { - Off_t posn; - if (PL_mmap_page_size <= 0) - Perl_croak(aTHX_ "panic: bad pagesize %" IVdf, - PL_mmap_page_size); - if (b->posn < 0) { - /* - * This is a hack - should never happen - open should - * have set it ! - */ - b->posn = PerlIO_tell(PerlIONext(f)); - } - posn = (b->posn / PL_mmap_page_size) * PL_mmap_page_size; - len = st.st_size - posn; - m->mptr = (Mmap_t)mmap(NULL, len, PROT_READ, MAP_SHARED, fd, posn); - if (m->mptr && m->mptr != (Mmap_t) - 1) { -#if 0 && defined(HAS_MADVISE) && defined(MADV_SEQUENTIAL) - madvise(m->mptr, len, MADV_SEQUENTIAL); -#endif -#if 0 && defined(HAS_MADVISE) && defined(MADV_WILLNEED) - madvise(m->mptr, len, MADV_WILLNEED); -#endif - PerlIOBase(f)->flags = - (flags & ~PERLIO_F_EOF) | PERLIO_F_RDBUF; - b->end = ((STDCHAR *) m->mptr) + len; - b->buf = ((STDCHAR *) m->mptr) + (b->posn - posn); - b->ptr = b->buf; - m->len = len; - } - else { - b->buf = NULL; - } - } - else { - PerlIOBase(f)->flags = - flags | PERLIO_F_EOF | PERLIO_F_RDBUF; - b->buf = NULL; - b->ptr = b->end = b->ptr; - code = -1; - } - } - } - return code; -} - -IV -PerlIOMmap_unmap(pTHX_ PerlIO *f) -{ - PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap); - IV code = 0; - if (m->len) { - PerlIOBuf * const b = &m->base; - if (b->buf) { - /* The munmap address argument is tricky: depending on the - * standard it is either "void *" or "caddr_t" (which is - * usually "char *" (signed or unsigned). If we cast it - * to "void *", those that have it caddr_t and an uptight - * C++ compiler, will freak out. But casting it as char* - * should work. Maybe. (Using Mmap_t figured out by - * Configure doesn't always work, apparently.) */ - code = munmap((char*)m->mptr, m->len); - b->buf = NULL; - m->len = 0; - m->mptr = NULL; - if (PerlIO_seek(PerlIONext(f), b->posn, SEEK_SET) != 0) - code = -1; - } - b->ptr = b->end = b->buf; - PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF); - } - return code; -} - -STDCHAR * -PerlIOMmap_get_base(pTHX_ PerlIO *f) -{ - PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap); - PerlIOBuf * const b = &m->base; - if (b->buf && (PerlIOBase(f)->flags & PERLIO_F_RDBUF)) { - /* - * Already have a readbuffer in progress - */ - return b->buf; - } - if (b->buf) { - /* - * We have a write buffer or flushed PerlIOBuf read buffer - */ - m->bbuf = b->buf; /* save it in case we need it again */ - b->buf = NULL; /* Clear to trigger below */ - } - if (!b->buf) { - PerlIOMmap_map(aTHX_ f); /* Try and map it */ - if (!b->buf) { - /* - * Map did not work - recover PerlIOBuf buffer if we have one - */ - b->buf = m->bbuf; - } - } - b->ptr = b->end = b->buf; - if (b->buf) - return b->buf; - return PerlIOBuf_get_base(aTHX_ f); -} - -SSize_t -PerlIOMmap_unread(pTHX_ PerlIO *f, const void *vbuf, Size_t count) -{ - PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap); - PerlIOBuf * const b = &m->base; - if (PerlIOBase(f)->flags & PERLIO_F_WRBUF) - PerlIO_flush(f); - if (b->ptr && (b->ptr - count) >= b->buf - && memEQ(b->ptr - count, vbuf, count)) { - b->ptr -= count; - PerlIOBase(f)->flags &= ~PERLIO_F_EOF; - return count; - } - if (m->len) { - /* - * Loose the unwritable mapped buffer - */ - PerlIO_flush(f); - /* - * If flush took the "buffer" see if we have one from before - */ - if (!b->buf && m->bbuf) - b->buf = m->bbuf; - if (!b->buf) { - PerlIOBuf_get_base(aTHX_ f); - m->bbuf = b->buf; - } - } - return PerlIOBuf_unread(aTHX_ f, vbuf, count); -} - -SSize_t -PerlIOMmap_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count) -{ - PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap); - PerlIOBuf * const b = &m->base; - - if (!b->buf || !(PerlIOBase(f)->flags & PERLIO_F_WRBUF)) { - /* - * No, or wrong sort of, buffer - */ - if (m->len) { - if (PerlIOMmap_unmap(aTHX_ f) != 0) - return 0; - } - /* - * If unmap took the "buffer" see if we have one from before - */ - if (!b->buf && m->bbuf) - b->buf = m->bbuf; - if (!b->buf) { - PerlIOBuf_get_base(aTHX_ f); - m->bbuf = b->buf; - } - } - return PerlIOBuf_write(aTHX_ f, vbuf, count); -} - -IV -PerlIOMmap_flush(pTHX_ PerlIO *f) -{ - PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap); - PerlIOBuf * const b = &m->base; - IV code = PerlIOBuf_flush(aTHX_ f); - /* - * Now we are "synced" at PerlIOBuf level - */ - if (b->buf) { - if (m->len) { - /* - * Unmap the buffer - */ - if (PerlIOMmap_unmap(aTHX_ f) != 0) - code = -1; - } - else { - /* - * We seem to have a PerlIOBuf buffer which was not mapped - * remember it in case we need one later - */ - m->bbuf = b->buf; - } - } - return code; -} - -IV -PerlIOMmap_fill(pTHX_ PerlIO *f) -{ - PerlIOBuf * const b = PerlIOSelf(f, PerlIOBuf); - IV code = PerlIO_flush(f); - if (code == 0 && !b->buf) { - code = PerlIOMmap_map(aTHX_ f); - } - if (code == 0 && !(PerlIOBase(f)->flags & PERLIO_F_RDBUF)) { - code = PerlIOBuf_fill(aTHX_ f); - } - return code; -} - -IV -PerlIOMmap_close(pTHX_ PerlIO *f) -{ - PerlIOMmap * const m = PerlIOSelf(f, PerlIOMmap); - PerlIOBuf * const b = &m->base; - IV code = PerlIO_flush(f); - if (m->bbuf) { - b->buf = m->bbuf; - m->bbuf = NULL; - b->ptr = b->end = b->buf; - } - if (PerlIOBuf_close(aTHX_ f) != 0) - code = -1; - return code; -} - -PerlIO * -PerlIOMmap_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) -{ - return PerlIOBase_dup(aTHX_ f, o, param, flags); -} - - -PERLIO_FUNCS_DECL(PerlIO_mmap) = { - sizeof(PerlIO_funcs), - "mmap", - sizeof(PerlIOMmap), - PERLIO_K_BUFFERED|PERLIO_K_RAW, - PerlIOBuf_pushed, - PerlIOBuf_popped, - PerlIOBuf_open, - PerlIOBase_binmode, /* binmode */ - NULL, - PerlIOBase_fileno, - PerlIOMmap_dup, - PerlIOBuf_read, - PerlIOMmap_unread, - PerlIOMmap_write, - PerlIOBuf_seek, - PerlIOBuf_tell, - PerlIOBuf_close, - PerlIOMmap_flush, - PerlIOMmap_fill, - PerlIOBase_eof, - PerlIOBase_error, - PerlIOBase_clearerr, - PerlIOBase_setlinebuf, - PerlIOMmap_get_base, - PerlIOBuf_bufsiz, - PerlIOBuf_get_ptr, - PerlIOBuf_get_cnt, - PerlIOBuf_set_ptrcnt, -}; - -#endif /* HAS_MMAP */ - PerlIO * Perl_PerlIO_stdin(pTHX) { @@ -4975,7 +4763,7 @@ Perl_PerlIO_stdin(pTHX) if (!PL_perlio) { PerlIO_stdstreams(aTHX); } - return &PL_perlio[1]; + return (PerlIO*)&PL_perlio[1]; } PerlIO * @@ -4985,7 +4773,7 @@ Perl_PerlIO_stdout(pTHX) if (!PL_perlio) { PerlIO_stdstreams(aTHX); } - return &PL_perlio[2]; + return (PerlIO*)&PL_perlio[2]; } PerlIO * @@ -4995,7 +4783,7 @@ Perl_PerlIO_stderr(pTHX) if (!PL_perlio) { PerlIO_stdstreams(aTHX); } - return &PL_perlio[3]; + return (PerlIO*)&PL_perlio[3]; } /*--------------------------------------------------------------------------------------*/ @@ -5003,8 +4791,8 @@ Perl_PerlIO_stderr(pTHX) char * PerlIO_getname(PerlIO *f, char *buf) { - dTHX; #ifdef VMS + dTHX; char *name = NULL; bool exported = FALSE; FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio; @@ -5020,7 +4808,7 @@ PerlIO_getname(PerlIO *f, char *buf) #else PERL_UNUSED_ARG(f); PERL_UNUSED_ARG(buf); - Perl_croak(aTHX_ "Don't know how to get file name"); + Perl_croak_nocontext("Don't know how to get file name"); return NULL; #endif } @@ -5160,7 +4948,9 @@ PerlIO_stdoutf(const char *fmt, ...) PerlIO * PerlIO_tmpfile(void) { +#ifndef WIN32 dTHX; +#endif PerlIO *f = NULL; #ifdef WIN32 const int fd = win32_tmpfd(); @@ -5168,16 +4958,36 @@ PerlIO_tmpfile(void) f = PerlIO_fdopen(fd, "w+b"); #else /* WIN32 */ # if defined(HAS_MKSTEMP) && ! defined(VMS) && ! defined(OS2) - SV * const sv = newSVpvs("/tmp/PerlIO_XXXXXX"); + int fd = -1; + char tempname[] = "/tmp/PerlIO_XXXXXX"; + const char * const tmpdir = TAINTING_get ? NULL : PerlEnv_getenv("TMPDIR"); + SV * sv = NULL; /* * I have no idea how portable mkstemp() is ... NI-S */ - const int fd = mkstemp(SvPVX(sv)); + if (tmpdir && *tmpdir) { + /* if TMPDIR is set and not empty, we try that first */ + sv = newSVpv(tmpdir, 0); + sv_catpv(sv, tempname + 4); + fd = mkstemp(SvPVX(sv)); + } + if (fd < 0) { + SvREFCNT_dec(sv); + sv = NULL; + /* else we try /tmp */ + fd = mkstemp(tempname); + } + if (fd < 0) { + /* Try cwd */ + sv = newSVpvs("."); + sv_catpv(sv, tempname + 4); + fd = mkstemp(SvPVX(sv)); + } if (fd >= 0) { f = PerlIO_fdopen(fd, "w+"); if (f) PerlIOBase(f)->flags |= PERLIO_F_TEMP; - PerlLIO_unlink(SvPVX_const(sv)); + PerlLIO_unlink(sv ? SvPVX_const(sv) : tempname); } SvREFCNT_dec(sv); # else /* !HAS_MKSTEMP, fallback to stdio tmpfile(). */ @@ -5194,7 +5004,6 @@ PerlIO_tmpfile(void) #undef HAS_FSETPOS #undef HAS_FGETPOS -#endif /* USE_SFIO */ #endif /* PERLIO_IS_STDIO */ /*======================================================================================*/ @@ -5225,8 +5034,7 @@ Perl_PerlIO_context_layers(pTHX_ const char *mode) if (!direction) return NULL; - layers = Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash, - 0, direction, 5, 0, 0); + layers = cop_hints_fetch_pvn(PL_curcop, direction, 5, 0, 0); assert(layers); return SvOK(layers) ? SvPV_nolen_const(layers) : NULL; @@ -5238,9 +5046,9 @@ Perl_PerlIO_context_layers(pTHX_ const char *mode) int PerlIO_setpos(PerlIO *f, SV *pos) { - dTHX; if (SvOK(pos)) { STRLEN len; + dTHX; const Off_t * const posn = (Off_t *) SvPV(pos, len); if (f && len == sizeof(Off_t)) return PerlIO_seek(f, *posn, SEEK_SET); @@ -5298,7 +5106,7 @@ PerlIO_getpos(PerlIO *f, SV *pos) } #endif -#if (defined(PERLIO_IS_STDIO) || !defined(USE_SFIO)) && !defined(HAS_VPRINTF) +#if !defined(HAS_VPRINTF) int vprintf(char *pat, char *args) @@ -5318,42 +5126,12 @@ vfprintf(FILE *fd, char *pat, char *args) #endif -#ifndef PerlIO_vsprintf -int -PerlIO_vsprintf(char *s, int n, const char *fmt, va_list ap) -{ - dTHX; - const int val = my_vsnprintf(s, n > 0 ? n : 0, fmt, ap); - PERL_UNUSED_CONTEXT; - -#ifndef PERL_MY_VSNPRINTF_GUARDED - if (val < 0 || (n > 0 ? val >= n : 0)) { - Perl_croak(aTHX_ "panic: my_vsnprintf overflow in PerlIO_vsprintf\n"); - } -#endif - return val; -} -#endif - -#ifndef PerlIO_sprintf -int -PerlIO_sprintf(char *s, int n, const char *fmt, ...) -{ - va_list ap; - int result; - va_start(ap, fmt); - result = PerlIO_vsprintf(s, n, fmt, ap); - va_end(ap); - return result; -} -#endif - /* * Local variables: * c-indentation-style: bsd * c-basic-offset: 4 - * indent-tabs-mode: t + * indent-tabs-mode: nil * End: * - * ex: set ts=8 sts=4 sw=4 noet: + * ex: set ts=8 sts=4 sw=4 et: */