X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=perlio.c;h=7c16e435b0cfd1cc317e93a144f4951c34a8620d;hb=10cb7778b2425656148151f1517d115436333ccf;hp=ba91393203e76ff9f39913a86ba3991f76bc1d97;hpb=10eefe7f3dbf3fb8c327fd67268d0d5514fee92f;p=p5sagit%2Fp5-mst-13.2.git diff --git a/perlio.c b/perlio.c index ba91393..7c16e43 100644 --- a/perlio.c +++ b/perlio.c @@ -38,6 +38,11 @@ #define PERL_IN_PERLIO_C #include "perl.h" +#ifdef PERL_IMPLICIT_CONTEXT +#undef dSYS +#define dSYS dTHX +#endif + #include "XSUB.h" int @@ -173,8 +178,9 @@ PerlIO_binmode(pTHX_ PerlIO *fp, int iotype, int mode, const char *names) } PerlIO * -PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param) +PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags) { +#ifndef PERL_MICRO if (f) { int fd = PerlLIO_dup(PerlIO_fileno(f)); if (fd >= 0) { @@ -189,6 +195,7 @@ PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param) else { SETERRNO(EBADF, SS$_IVCHAN); } +#endif return NULL; } @@ -435,13 +442,13 @@ PerlIO_allocate(pTHX) #undef PerlIO_fdupopen PerlIO * -PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param) +PerlIO_fdupopen(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags) { if (f && *f) { PerlIO_funcs *tab = PerlIOBase(f)->tab; PerlIO *new; PerlIO_debug("fdupopen f=%p param=%p\n",f,param); - new = (*tab->Dup)(aTHX_ PerlIO_allocate(aTHX),f,param); + new = (*tab->Dup)(aTHX_ PerlIO_allocate(aTHX),f,param, flags); return new; } else { @@ -517,13 +524,16 @@ PerlIO_list_push(pTHX_ PerlIO_list_t *list, PerlIO_funcs *funcs, SV *arg) PerlIO_list_t * PerlIO_clone_list(pTHX_ PerlIO_list_t *proto, CLONE_PARAMS *param) { - int i; - PerlIO_list_t *list = PerlIO_list_alloc(aTHX); - for (i=0; i < proto->cur; i++) { - SV *arg = Nullsv; - if (proto->array[i].arg) - arg = PerlIO_sv_dup(aTHX_ proto->array[i].arg,param); - PerlIO_list_push(aTHX_ list, proto->array[i].funcs, arg); + PerlIO_list_t *list = (PerlIO_list_t *) NULL; + if (proto) { + int i; + list = PerlIO_list_alloc(aTHX); + for (i=0; i < proto->cur; i++) { + SV *arg = Nullsv; + if (proto->array[i].arg) + arg = PerlIO_sv_dup(aTHX_ proto->array[i].arg,param); + PerlIO_list_push(aTHX_ list, proto->array[i].funcs, arg); + } } return list; } @@ -538,12 +548,13 @@ PerlIO_clone(pTHX_ PerlInterpreter *proto, CLONE_PARAMS *param) 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_debug("Clone %p from %p\n",aTHX,proto); while ((f = *table)) { int i; table = (PerlIO **) (f++); for (i = 1; i < PERLIO_TABLE_SIZE; i++) { if (*f) { - PerlIO_fdupopen(aTHX_ f, param); + (void) fp_dup(f, 0, param); } f++; } @@ -552,16 +563,13 @@ PerlIO_clone(pTHX_ PerlInterpreter *proto, CLONE_PARAMS *param) } void -PerlIO_cleanup(pTHX) -{ - PerlIO_cleantable(aTHX_ &PL_perlio); -} - -void PerlIO_destruct(pTHX) { PerlIO **table = &PL_perlio; PerlIO *f; +#ifdef USE_ITHREADS + PerlIO_debug("Destruct %p\n",aTHX); +#endif while ((f = *table)) { int i; table = (PerlIO **) (f++); @@ -776,8 +784,8 @@ PerlIO_parse_layers(pTHX_ PerlIO_list_t *av, const char *names) */ char q = ((*s == '\'') ? '"' : '\''); Perl_warn(aTHX_ - "perlio: invalid separator character %c%c%c in layer specification list", - q, *s, q); + "perlio: invalid separator character %c%c%c in layer specification list %s", + q, *s, q, s); return -1; } do { @@ -1064,16 +1072,19 @@ PerlIO_binmode(pTHX_ PerlIO *f, int iotype, int mode, const char *names) PerlIO_debug("PerlIO_binmode f=%p %s %c %x %s\n", f, PerlIOBase(f)->tab->name, iotype, mode, (names) ? names : "(Null)"); - PerlIO_flush(f); - if (!names && (O_TEXT != O_BINARY && (mode & O_BINARY))) { - PerlIO *top = f; - while (*top) { - if (PerlIOBase(top)->tab == &PerlIO_crlf) { - PerlIOBase(top)->flags &= ~PERLIO_F_CRLF; - break; + /* Can't flush if switching encodings. */ + if (!(names && memEQ(names, ":encoding(", 10))) { + PerlIO_flush(f); + if (!names && (O_TEXT != O_BINARY && (mode & O_BINARY))) { + PerlIO *top = f; + while (*top) { + if (PerlIOBase(top)->tab == &PerlIO_crlf) { + PerlIOBase(top)->flags &= ~PERLIO_F_CRLF; + break; + } + top = PerlIONext(top); + PerlIO_flush(top); } - top = PerlIONext(top); - PerlIO_flush(top); } } return PerlIO_apply_layers(aTHX_ f, NULL, names) == 0 ? TRUE : FALSE; @@ -1248,7 +1259,7 @@ PerlIO_openn(pTHX_ const char *layers, const char *mode, int fd, while (l) { SV *arg = (l->tab->Getarg) ? (*l->tab-> - Getarg) (&l) : &PL_sv_undef; + Getarg) (aTHX_ &l, NULL, 0) : &PL_sv_undef; PerlIO_list_push(aTHX_ layera, l->tab, arg); l = *PerlIONext(&l); } @@ -1947,6 +1958,112 @@ PerlIOBase_setlinebuf(PerlIO *f) } } +SV * +PerlIO_sv_dup(pTHX_ SV *arg, CLONE_PARAMS *param) +{ + if (!arg) + return Nullsv; +#ifdef sv_dup + if (param) { + return sv_dup(arg, param); + } + else { + return newSVsv(arg); + } +#else + return newSVsv(arg); +#endif +} + +PerlIO * +PerlIOBase_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) +{ + PerlIO *nexto = PerlIONext(o); + if (*nexto) { + PerlIO_funcs *tab = PerlIOBase(nexto)->tab; + f = (*tab->Dup)(aTHX_ f, nexto, param, flags); + } + if (f) { + PerlIO_funcs *self = PerlIOBase(o)->tab; + SV *arg = Nullsv; + char buf[8]; + PerlIO_debug("PerlIOBase_dup %s f=%p o=%p param=%p\n",self->name,f,o,param); + if (self->Getarg) { + arg = (*self->Getarg)(aTHX_ o,param,flags); + } + f = PerlIO_push(aTHX_ f, self, PerlIO_modestr(o,buf), arg); + if (arg) { + SvREFCNT_dec(arg); + } + } + return f; +} + +#define PERLIO_MAX_REFCOUNTABLE_FD 2048 +#ifdef USE_THREADS +perl_mutex PerlIO_mutex; +#endif +int PerlIO_fd_refcnt[PERLIO_MAX_REFCOUNTABLE_FD]; + +void +PerlIO_init(pTHX) +{ + /* Place holder for stdstreams call ??? */ +#ifdef USE_THREADS + MUTEX_INIT(&PerlIO_mutex); +#endif +} + +void +PerlIOUnix_refcnt_inc(int fd) +{ + if (fd >= 0 && fd < PERLIO_MAX_REFCOUNTABLE_FD) { +#ifdef USE_THREADS + MUTEX_LOCK(&PerlIO_mutex); +#endif + PerlIO_fd_refcnt[fd]++; + PerlIO_debug("fd %d refcnt=%d\n",fd,PerlIO_fd_refcnt[fd]); +#ifdef USE_THREADS + MUTEX_UNLOCK(&PerlIO_mutex); +#endif + } +} + +int +PerlIOUnix_refcnt_dec(int fd) +{ + int cnt = 0; + if (fd >= 0 && fd < PERLIO_MAX_REFCOUNTABLE_FD) { +#ifdef USE_THREADS + MUTEX_LOCK(&PerlIO_mutex); +#endif + cnt = --PerlIO_fd_refcnt[fd]; + PerlIO_debug("fd %d refcnt=%d\n",fd,cnt); +#ifdef USE_THREADS + MUTEX_UNLOCK(&PerlIO_mutex); +#endif + } + return cnt; +} + +void +PerlIO_cleanup(pTHX) +{ + int i; +#ifdef USE_ITHREADS + PerlIO_debug("Cleanup %p\n",aTHX); +#endif + /* Raise STDIN..STDERR refcount so we don't close them */ + for (i=0; i < 3; i++) + PerlIOUnix_refcnt_inc(i); + PerlIO_cleantable(aTHX_ &PL_perlio); + /* Restore STDIN..STDERR refcount */ + for (i=0; i < 3; i++) + PerlIOUnix_refcnt_dec(i); +} + + + /*--------------------------------------------------------------------------------------*/ /* * Bottom-most level for UNIX-like case @@ -2024,8 +2141,8 @@ IV PerlIOUnix_pushed(PerlIO *f, const char *mode, SV *arg) { IV code = PerlIOBase_pushed(f, mode, arg); + PerlIOUnix *s = PerlIOSelf(f, PerlIOUnix); if (*PerlIONext(f)) { - PerlIOUnix *s = PerlIOSelf(f, PerlIOUnix); s->fd = PerlIO_fileno(PerlIONext(f)); /* * XXX could (or should) we retrieve the oflags from the open file @@ -2073,6 +2190,7 @@ PerlIOUnix_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, s->fd = fd; s->oflags = imode; PerlIOBase(f)->flags |= PERLIO_F_OPEN; + PerlIOUnix_refcnt_inc(fd); return f; } else { @@ -2085,66 +2203,23 @@ PerlIOUnix_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, } } -SV * -PerlIO_sv_dup(pTHX_ SV *arg, CLONE_PARAMS *param) -{ - if (!arg) - return Nullsv; -#ifdef sv_dup - if (param) { - return sv_dup(arg, param); - } - else { - return newSVsv(arg); - } -#else - return newSVsv(arg); -#endif -} - PerlIO * -PerlIOBase_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param) -{ - PerlIO *nexto = PerlIONext(o); - if (*nexto) { - PerlIO_funcs *tab = PerlIOBase(nexto)->tab; - f = (*tab->Dup)(aTHX_ f, nexto, param); - } - if (f) { - PerlIO_funcs *self = PerlIOBase(o)->tab; - SV *arg = Nullsv; - char buf[8]; - PerlIO_debug("PerlIOBase_dup %s f=%p o=%p param=%p\n",self->name,f,o,param); - if (self->Getarg) { - arg = (*self->Getarg)(o); - if (arg) { - arg = PerlIO_sv_dup(aTHX_ arg, param); - } - } - f = PerlIO_push(aTHX_ f, self, PerlIO_modestr(o,buf), arg); - if (!f && arg) { - SvREFCNT_dec(arg); - } - } - return f; -} - -PerlIO * -PerlIOUnix_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param) +PerlIOUnix_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) { PerlIOUnix *os = PerlIOSelf(o, PerlIOUnix); - int fd = PerlLIO_dup(os->fd); - if (fd >= 0) { - f = PerlIOBase_dup(aTHX_ f, o, param); + int fd = os->fd; + if (flags & PERLIO_DUP_FD) { + fd = PerlLIO_dup(fd); + } + if (fd >= 0 && fd < PERLIO_MAX_REFCOUNTABLE_FD) { + f = PerlIOBase_dup(aTHX_ f, o, param, flags); if (f) { /* If all went well overwrite fd in dup'ed lay with the dup()'ed fd */ PerlIOUnix *s = PerlIOSelf(f, PerlIOUnix); s->fd = fd; + PerlIOUnix_refcnt_inc(fd); return f; } - else { - PerlLIO_close(fd); - } } return NULL; } @@ -2210,6 +2285,16 @@ PerlIOUnix_close(PerlIO *f) dTHX; int fd = PerlIOSelf(f, PerlIOUnix)->fd; int code = 0; + if (PerlIOBase(f)->flags & PERLIO_F_OPEN) { + if (PerlIOUnix_refcnt_dec(fd) > 0) { + PerlIOBase(f)->flags &= ~PERLIO_F_OPEN; + return 0; + } + } + else { + SETERRNO(EBADF,SS$_IVCHAN); + return -1; + } while (PerlLIO_close(fd) != 0) { if (errno != EINTR) { code = -1; @@ -2329,12 +2414,14 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, if (f) { char *path = SvPV_nolen(*args); PerlIOStdio *s = PerlIOSelf(f, PerlIOStdio); - FILE *stdio = - PerlSIO_freopen(path, (mode = PerlIOStdio_mode(mode, tmode)), + FILE *stdio; + PerlIOUnix_refcnt_dec(fileno(s->stdio)); + stdio = PerlSIO_freopen(path, (mode = PerlIOStdio_mode(mode, tmode)), s->stdio); if (!s->stdio) return NULL; s->stdio = stdio; + PerlIOUnix_refcnt_inc(fileno(s->stdio)); return f; } else { @@ -2354,6 +2441,7 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, PerlIOArg), PerlIOStdio); s->stdio = stdio; + PerlIOUnix_refcnt_inc(fileno(s->stdio)); } return f; } @@ -2388,6 +2476,7 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, (aTHX_(f = PerlIO_allocate(aTHX)), self, mode, PerlIOArg), PerlIOStdio); s->stdio = stdio; + PerlIOUnix_refcnt_inc(fileno(s->stdio)); return f; } } @@ -2395,6 +2484,61 @@ PerlIOStdio_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, return NULL; } +PerlIO * +PerlIOStdio_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) +{ + /* This assumes no layers underneath - which is what + happens, but is not how I remember it. NI-S 2001/10/16 + */ + if ((f = PerlIOBase_dup(aTHX_ f, o, param, flags))) { + FILE *stdio = PerlIOSelf(o, PerlIOStdio)->stdio; + if (flags & PERLIO_DUP_FD) { + int fd = PerlLIO_dup(fileno(stdio)); + if (fd >= 0) { + char mode[8]; + stdio = fdopen(fd, PerlIO_modestr(o,mode)); + } + else { + /* FIXME: To avoid messy error recovery if dup fails + re-use the existing stdio as though flag was not set + */ + } + } + PerlIOSelf(f, PerlIOStdio)->stdio = stdio; + PerlIOUnix_refcnt_inc(fileno(stdio)); + } + return f; +} + +IV +PerlIOStdio_close(PerlIO *f) +{ + dSYS; +#ifdef SOCKS5_VERSION_NAME + int optval; + Sock_size_t optlen = sizeof(int); +#endif + FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio; + if (PerlIOUnix_refcnt_dec(fileno(stdio)) > 0) { + /* Do not close it but do flush any buffers */ + PerlIO_flush(f); + return 0; + } + return ( +#ifdef SOCKS5_VERSION_NAME + (getsockopt + (PerlIO_fileno(f), SOL_SOCKET, SO_TYPE, (void *) &optval, + &optlen) < + 0) ? PerlSIO_fclose(stdio) : close(PerlIO_fileno(f)) +#else + PerlSIO_fclose(stdio) +#endif + ); + +} + + + SSize_t PerlIOStdio_read(PerlIO *f, void *vbuf, Size_t count) { @@ -2460,28 +2604,6 @@ PerlIOStdio_tell(PerlIO *f) } IV -PerlIOStdio_close(PerlIO *f) -{ - dSYS; -#ifdef SOCKS5_VERSION_NAME - int optval; - Sock_size_t optlen = sizeof(int); -#endif - FILE *stdio = PerlIOSelf(f, PerlIOStdio)->stdio; - return ( -#ifdef SOCKS5_VERSION_NAME - (getsockopt - (PerlIO_fileno(f), SOL_SOCKET, SO_TYPE, (void *) &optval, - &optlen) < - 0) ? PerlSIO_fclose(stdio) : close(PerlIO_fileno(f)) -#else - PerlSIO_fclose(stdio) -#endif - ); - -} - -IV PerlIOStdio_flush(PerlIO *f) { dSYS; @@ -2636,32 +2758,6 @@ PerlIOStdio_set_ptrcnt(PerlIO *f, STDCHAR * ptr, SSize_t cnt) #endif -PerlIO * -PerlIOStdio_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param) -{ - /* This assumes no layers underneath - which is what - happens, but is not how I remember it. NI-S 2001/10/16 - */ - int fd = PerlLIO_dup(PerlIO_fileno(o)); - if (fd >= 0) { - char buf[8]; - FILE *stdio = PerlSIO_fdopen(fd, PerlIO_modestr(o, buf)); - if (stdio) { - if ((f = PerlIOBase_dup(aTHX_ f, o, param))) { - PerlIOSelf(f, PerlIOStdio)->stdio = stdio; - } - else { - PerlSIO_fclose(stdio); - } - } - else { - PerlLIO_close(fd); - f = NULL; - } - } - return f; -} - PerlIO_funcs PerlIO_stdio = { "stdio", sizeof(PerlIOStdio), @@ -2796,19 +2892,26 @@ PerlIOBuf_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, f = (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm, NULL, narg, args); if (f) { - PerlIO_push(aTHX_ f, self, mode, PerlIOArg); - fd = PerlIO_fileno(f); -#if O_BINARY != O_TEXT - /* - * do something about failing setmode()? --jhi - */ - PerlLIO_setmode(fd, O_BINARY); -#endif - if (init && fd == 2) { + if (PerlIO_push(aTHX_ f, self, mode, PerlIOArg) == 0) { + /* + * if push fails during open, open fails. close will pop us. + */ + PerlIO_close (f); + return NULL; + } else { + fd = PerlIO_fileno(f); +#if (O_BINARY != O_TEXT) && !defined(__BEOS__) /* - * Initial stderr is unbuffered + * do something about failing setmode()? --jhi */ - PerlIOBase(f)->flags |= PERLIO_F_UNBUF; + PerlLIO_setmode(fd, O_BINARY); +#endif + if (init && fd == 2) { + /* + * Initial stderr is unbuffered + */ + PerlIOBase(f)->flags |= PERLIO_F_UNBUF; + } } } } @@ -3155,9 +3258,9 @@ PerlIOBuf_set_ptrcnt(PerlIO *f, STDCHAR * ptr, SSize_t cnt) } PerlIO * -PerlIOBuf_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param) +PerlIOBuf_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) { - return PerlIOBase_dup(aTHX_ f, o, param); + return PerlIOBase_dup(aTHX_ f, o, param, flags); } @@ -3435,7 +3538,7 @@ PerlIOCrlf_get_cnt(PerlIO *f) int code; b->ptr++; /* say we have read it as far as * flush() is concerned */ - b->buf++; /* Leave space an front of buffer */ + b->buf++; /* Leave space in front of buffer */ b->bufsiz--; /* Buffer is thus smaller */ code = PerlIO_fill(f); /* Fetch some more */ b->bufsiz++; /* Restore size for next time */ @@ -3883,9 +3986,9 @@ PerlIOMmap_close(PerlIO *f) } PerlIO * -PerlIOMmap_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param) +PerlIOMmap_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) { - return PerlIOBase_dup(aTHX_ f, o, param); + return PerlIOBase_dup(aTHX_ f, o, param, flags); } @@ -3920,12 +4023,6 @@ PerlIO_funcs PerlIO_mmap = { #endif /* HAS_MMAP */ -void -PerlIO_init(pTHX) -{ - /* Place holder for stdstreams call ??? */ -} - #undef PerlIO_stdin PerlIO * PerlIO_stdin(void) @@ -4241,3 +4338,7 @@ PerlIO_sprintf(char *s, int n, const char *fmt, ...) } #endif + + + +