#include "XSUB.h"
+#ifdef __Lynx__
+/* Missing proto on LynxOS */
+int mkstemp(char*);
+#endif
+
/* Call the callback or PerlIOBase, and return failure. */
#define Perl_PerlIO_or_Base(f, callback, base, failure, args) \
if (PerlIOValid(f)) { \
return PerlIO_tmpfile();
else {
char *name = SvPV_nolen(*args);
- if (*mode == '#') {
+ if (*mode == IoTYPE_NUMERIC) {
fd = PerlLIO_open3(name, imode, perm);
if (fd >= 0)
return PerlIO_fdopen(fd, (char *) mode + 1);
#include <sys/mman.h>
#endif
-
+/*
+ * Why is this here - not in perlio.h? RMB
+ */
void PerlIO_debug(const char *fmt, ...)
- __attribute__ ((format(__printf__, 1, 2)));
+ __attribute__format__(__printf__, 1, 2);
void
PerlIO_debug(const char *fmt, ...)
len = strlen(name);
for (i = 0; i < PL_known_layers->cur; i++) {
PerlIO_funcs *f = PL_known_layers->array[i].funcs;
- if (memEQ(f->name, name, len)) {
+ if (memEQ(f->name, name, len) && f->name[len] == 0) {
PerlIO_debug("%.*s => %p\n", (int) len, name, (void*)f);
return f;
}
char q = ((*s == '\'') ? '"' : '\'');
if (ckWARN(WARN_LAYER))
Perl_warner(aTHX_ packWARN(WARN_LAYER),
- "perlio: invalid separator character %c%c%c in layer specification list %s",
+ "Invalid separator character %c%c%c in PerlIO layer specification %s",
q, *s, q, s);
SETERRNO(EINVAL, LIB_INVARG);
return -1;
e--;
if (ckWARN(WARN_LAYER))
Perl_warner(aTHX_ packWARN(WARN_LAYER),
- "perlio: argument list not closed for layer \"%.*s\"",
+ "Argument list not closed for PerlIO layer \"%.*s\"",
(int) (e - s), s);
return -1;
default:
}
else {
if (warn_layer)
- Perl_warner(aTHX_ packWARN(WARN_LAYER), "perlio: unknown layer \"%.*s\"",
+ Perl_warner(aTHX_ packWARN(WARN_LAYER), "Unknown PerlIO layer \"%.*s\"",
(int) llen, s);
return -1;
}
PerlIO_funcs *osLayer = &PerlIO_unix;
PL_def_layerlist = PerlIO_list_alloc(aTHX);
PerlIO_define_layer(aTHX_ & PerlIO_unix);
-#if defined(WIN32) && !defined(UNDER_CE)
+#if defined(WIN32)
PerlIO_define_layer(aTHX_ & PerlIO_win32);
#if 0
osLayer = &PerlIO_win32;
if (tab->Set_ptrcnt != NULL)
l->flags |= PERLIO_F_FASTGETS;
if (mode) {
- if (*mode == '#' || *mode == 'I')
+ if (*mode == IoTYPE_NUMERIC || *mode == IoTYPE_IMPLICIT)
mode++;
switch (*mode++) {
case 'r':
{
STDCHAR *buf = (STDCHAR *) vbuf;
if (f) {
- if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD))
+ if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD)) {
+ PerlIOBase(f)->flags |= PERLIO_F_ERROR;
+ SETERRNO(EBADF, SS_IVCHAN);
return 0;
+ }
while (count > 0) {
SSize_t avail = PerlIO_get_cnt(f);
SSize_t take = 0;
PerlIOUnix_oflags(const char *mode)
{
int oflags = -1;
- if (*mode == 'I' || *mode == '#')
+ if (*mode == IoTYPE_IMPLICIT || *mode == IoTYPE_NUMERIC)
mode++;
switch (*mode) {
case 'r':
PerlIOUnix_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
{
IV code = PerlIOBase_pushed(aTHX_ f, mode, arg, tab);
- PerlIOUnix *s = PerlIOSelf(f, PerlIOUnix);
if (*PerlIONext(f)) {
/* We never call down so do any pending stuff now */
PerlIO_flush(PerlIONext(f));
* handle rather than believing the "mode" we are passed in? XXX
* Should the value on NULL mode be 0 or -1?
*/
- PerlIOUnix_setfd(aTHX_ f, PerlIO_fileno(PerlIONext(f)),
+ PerlIOUnix_setfd(aTHX_ f, PerlIO_fileno(PerlIONext(f)),
mode ? PerlIOUnix_oflags(mode) : -1);
}
PerlIOBase(f)->flags |= PERLIO_F_OPEN;
return code;
}
+IV
+PerlIOUnix_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
+{
+ int fd = PerlIOSelf(f, PerlIOUnix)->fd;
+ Off_t new;
+ if (PerlIOBase(f)->flags & PERLIO_F_NOTREG) {
+#ifdef ESPIPE
+ SETERRNO(ESPIPE, LIB_INVARG);
+#else
+ SETERRNO(EINVAL, LIB_INVARG);
+#endif
+ return -1;
+ }
+ new = PerlLIO_lseek(fd, offset, whence);
+ if (new == (Off_t) - 1)
+ {
+ return -1;
+ }
+ PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
+ return 0;
+}
+
PerlIO *
PerlIOUnix_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
IV n, const char *mode, int fd, int imode,
}
if (narg > 0) {
char *path = SvPV_nolen(*args);
- if (*mode == '#')
+ if (*mode == IoTYPE_NUMERIC)
mode++;
else {
imode = PerlIOUnix_oflags(mode);
}
}
if (fd >= 0) {
- if (*mode == 'I')
+ if (*mode == IoTYPE_IMPLICIT)
mode++;
if (!f) {
f = PerlIO_allocate(aTHX);
}
PerlIOUnix_setfd(aTHX_ f, fd, imode);
PerlIOBase(f)->flags |= PERLIO_F_OPEN;
+ if (*mode == IoTYPE_APPEND)
+ PerlIOUnix_seek(aTHX_ f, 0, SEEK_END);
return f;
}
else {
while (1) {
SSize_t len = PerlLIO_read(fd, vbuf, count);
if (len >= 0 || errno != EINTR) {
- if (len < 0)
- PerlIOBase(f)->flags |= PERLIO_F_ERROR;
- else if (len == 0 && count != 0)
+ if (len < 0) {
+ if (errno != EAGAIN) {
+ PerlIOBase(f)->flags |= PERLIO_F_ERROR;
+ }
+ }
+ else if (len == 0 && count != 0) {
PerlIOBase(f)->flags |= PERLIO_F_EOF;
+ SETERRNO(0,0);
+ }
return len;
}
PERL_ASYNC_CHECK();
while (1) {
SSize_t len = PerlLIO_write(fd, vbuf, count);
if (len >= 0 || errno != EINTR) {
- if (len < 0)
- PerlIOBase(f)->flags |= PERLIO_F_ERROR;
+ if (len < 0) {
+ if (errno != EAGAIN) {
+ PerlIOBase(f)->flags |= PERLIO_F_ERROR;
+ }
+ }
return len;
}
PERL_ASYNC_CHECK();
}
}
-IV
-PerlIOUnix_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
-{
- int fd = PerlIOSelf(f, PerlIOUnix)->fd;
- Off_t new;
- if (PerlIOBase(f)->flags & PERLIO_F_NOTREG) {
-#ifdef ESPIPE
- SETERRNO(ESPIPE, LIB_INVARG);
-#else
- SETERRNO(EINVAL, LIB_INVARG);
-#endif
- return -1;
- }
- new = PerlLIO_lseek(fd, offset, whence);
- if (new == (Off_t) - 1)
- {
- return -1;
- }
- PerlIOBase(f)->flags &= ~PERLIO_F_EOF;
- return 0;
-}
-
Off_t
PerlIOUnix_tell(pTHX_ PerlIO *f)
{
PerlIOStdio_mode(const char *mode, char *tmode)
{
char *ret = tmode;
- while (*mode) {
- *tmode++ = *mode++;
+ if (mode) {
+ while (*mode) {
+ *tmode++ = *mode++;
+ }
}
-#ifdef PERLIO_USING_CRLF
+#if defined(PERLIO_USING_CRLF) || defined(__CYGWIN__)
*tmode++ = 'b';
#endif
*tmode = '\0';
else {
if (narg > 0) {
char *path = SvPV_nolen(*args);
- if (*mode == '#') {
+ if (*mode == IoTYPE_NUMERIC) {
mode++;
fd = PerlLIO_open3(path, imode, perm);
}
else {
- FILE *stdio = PerlSIO_fopen(path, mode);
+ FILE *stdio;
+ bool appended = FALSE;
+#ifdef __CYGWIN__
+ /* Cygwin wants its 'b' early. */
+ appended = TRUE;
+ mode = PerlIOStdio_mode(mode, tmode);
+#endif
+ stdio = PerlSIO_fopen(path, mode);
if (stdio) {
PerlIOStdio *s;
if (!f) {
f = PerlIO_allocate(aTHX);
}
- if ((f = PerlIO_push(aTHX_ f, self,
- (mode = PerlIOStdio_mode(mode, tmode)),
- PerlIOArg))) {
+ if (!appended)
+ mode = PerlIOStdio_mode(mode, tmode);
+ f = PerlIO_push(aTHX_ f, self, mode, PerlIOArg);
+ if (f) {
s = PerlIOSelf(f, PerlIOStdio);
s->stdio = stdio;
PerlIOUnix_refcnt_inc(fileno(s->stdio));
if (fd >= 0) {
FILE *stdio = NULL;
int init = 0;
- if (*mode == 'I') {
+ if (*mode == IoTYPE_IMPLICIT) {
init = 1;
mode++;
}
*/
f->_file = -1;
return 1;
+# elif defined(__EMX__)
+ /* f->_flags &= ~_IOOPEN; */ /* Will leak stream->_buffer */
+ f->_handle = -1;
+ return 1;
# elif defined(__CYGWIN__)
/* There may be a better way on CYGWIN:
- we could insert a dummy func in the _close function entry
}
if (dupfd) {
PerlLIO_dup2(dupfd,fd);
- close(dupfd);
+ PerlLIO_close(dupfd);
}
return result;
}
}
else
got = PerlSIO_fread(vbuf, 1, count, s);
- if (got || errno != EINTR)
+ if (got == 0 && PerlSIO_ferror(s))
+ got = -1;
+ if (got >= 0 || errno != EINTR)
break;
PERL_ASYNC_CHECK();
- errno = 0; /* just in case */
+ SETERRNO(0,0); /* just in case */
}
return got;
}
for (;;) {
got = PerlSIO_fwrite(vbuf, 1, count,
PerlIOSelf(f, PerlIOStdio)->stdio);
- if (got || errno != EINTR)
+ if (got >= 0 || errno != EINTR)
break;
PERL_ASYNC_CHECK();
- errno = 0; /* just in case */
+ SETERRNO(0,0); /* just in case */
}
return got;
}
stdio = PerlSIO_fdopen(PerlIO_fileno(f), mode);
if (stdio) {
PerlIOl *l = *f;
+ PerlIO *f2;
/* De-link any lower layers so new :stdio sticks */
*f = NULL;
- if ((f = PerlIO_push(aTHX_ f, &PerlIO_stdio, buf, Nullsv))) {
- PerlIOStdio *s = PerlIOSelf(f, PerlIOStdio);
+ if ((f2 = PerlIO_push(aTHX_ f, &PerlIO_stdio, buf, Nullsv))) {
+ PerlIOStdio *s = PerlIOSelf((f = f2), PerlIOStdio);
s->stdio = stdio;
/* Link previous lower layers under new one */
*PerlIONext(f) = l;
{
if (PerlIOValid(f)) {
PerlIO *next = PerlIONext(f);
- PerlIO_funcs *tab = PerlIO_layer_fetch(aTHX_ layers, n - 1, PerlIOBase(next)->tab);
- next = (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm,
- next, narg, args);
+ PerlIO_funcs *tab =
+ PerlIO_layer_fetch(aTHX_ layers, n - 1, PerlIOBase(next)->tab);
+ if (tab && tab->Open)
+ next =
+ (*tab->Open)(aTHX_ tab, layers, n - 1, mode, fd, imode, perm,
+ next, narg, args);
if (!next || (*PerlIOBase(f)->tab->Pushed) (aTHX_ f, mode, PerlIOArg, self) != 0) {
return NULL;
}
else {
PerlIO_funcs *tab = PerlIO_layer_fetch(aTHX_ layers, n - 1, PerlIO_default_btm());
int init = 0;
- if (*mode == 'I') {
+ if (*mode == IoTYPE_IMPLICIT) {
init = 1;
/*
* mode++;
*/
}
- f = (*tab->Open) (aTHX_ tab, layers, n - 1, mode, fd, imode, perm,
- f, narg, args);
+ if (tab && tab->Open)
+ f = (*tab->Open)(aTHX_ tab, layers, n - 1, mode, fd, imode, perm,
+ f, narg, args);
+ else
+ SETERRNO(EINVAL, LIB_INVARG);
if (f) {
if (PerlIO_push(aTHX_ f, self, mode, PerlIOArg) == 0) {
/*
f, PerlIOBase(f)->tab->name, (mode) ? mode : "(Null)",
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. */
+ PerlIO *g = PerlIONext(f);
+ while (g && *g) {
+ PerlIOl *b = PerlIOBase(g);
+ if (b && b->tab == &PerlIO_crlf) {
+ if (!(b->flags & PERLIO_F_CRLF))
+ b->flags |= PERLIO_F_CRLF;
+ PerlIO_pop(aTHX_ f);
+ return code;
+ }
+ g = PerlIONext(g);
+ }
+ }
return code;
}
dTHX;
PerlIO *f = NULL;
int fd = -1;
- SV *sv = Nullsv;
- GV *gv = gv_fetchpv("File::Temp::tempfile", FALSE, SVt_PVCV);
-
- if (!gv) {
- ENTER;
- Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT,
- newSVpvn("File::Temp", 10), Nullsv, Nullsv, Nullsv);
- gv = gv_fetchpv("File::Temp::tempfile", FALSE, SVt_PVCV);
- GvIMPORTED_CV_on(gv);
- LEAVE;
- }
-
- if (gv && GvCV(gv)) {
- dSP;
- ENTER;
- SAVETMPS;
- PUSHMARK(SP);
- PUTBACK;
- if (call_sv((SV*)GvCV(gv), G_SCALAR)) {
- GV *gv = (GV*)SvRV(newSVsv(*PL_stack_sp--));
- IO *io = gv ? GvIO(gv) : 0;
- fd = io ? PerlIO_fileno(IoIFP(io)) : -1;
- }
- SPAGAIN;
- PUTBACK;
- FREETMPS;
- LEAVE;
- }
-
+#ifdef WIN32
+ fd = win32_tmpfd();
+ if (fd >= 0)
+ f = PerlIO_fdopen(fd, "w+b");
+#else /* WIN32 */
+# if defined(HAS_MKSTEMP) && ! defined(VMS) && ! defined(OS2)
+ SV *sv = newSVpv("/tmp/PerlIO_XXXXXX", 0);
+
+ /*
+ * I have no idea how portable mkstemp() is ... NI-S
+ */
+ fd = mkstemp(SvPVX(sv));
if (fd >= 0) {
f = PerlIO_fdopen(fd, "w+");
- if (sv) {
- if (f)
- PerlIOBase(f)->flags |= PERLIO_F_TEMP;
- PerlLIO_unlink(SvPVX(sv));
- SvREFCNT_dec(sv);
- }
+ if (f)
+ PerlIOBase(f)->flags |= PERLIO_F_TEMP;
+ PerlLIO_unlink(SvPVX(sv));
+ SvREFCNT_dec(sv);
}
+# else /* !HAS_MKSTEMP, fallback to stdio tmpfile(). */
+ FILE *stdio = PerlSIO_tmpfile();
+ if (stdio) {
+ if ((f = PerlIO_push(aTHX_(PerlIO_allocate(aTHX)),
+ &PerlIO_stdio, "w+", Nullsv))) {
+ PerlIOStdio *s = PerlIOSelf(f, PerlIOStdio);
+
+ if (s)
+ s->stdio = stdio;
+ }
+ }
+# endif /* else HAS_MKSTEMP */
+#endif /* else WIN32 */
return f;
}