#undef PERL_EFF_ACCESS_W_OK
#undef PERL_EFF_ACCESS_X_OK
+/* AIX 5.2 and below use mktime for localtime, and defines the edge case
+ * for time 0x7fffffff to be valid only in UTC. AIX 5.3 provides localtime64
+ * available in the 32bit environment, which could warrant Configure
+ * checks in the future.
+ */
+#ifdef _AIX
+#define LOCALTIME_EDGECASE_BROKEN
+#endif
+
/* F_OK unused: if stat() cannot find it... */
#if !defined(PERL_EFF_ACCESS_R_OK) && defined(HAS_ACCESS) && defined(EFF_ONLY_OK) && !defined(NO_EFF_ONLY_OK)
if (SvPOK(error) && SvCUR(error))
sv_catpv(error, "\t...propagated");
tmpsv = error;
- tmps = SvPV_const(tmpsv, len);
+ if (SvOK(tmpsv))
+ tmps = SvPV_const(tmpsv, len);
+ else
+ tmps = Nullch;
}
}
if (!tmps || !len)
sv = *++MARK;
}
else {
- sv = GvSV(gv);
+ sv = GvSVn(gv);
}
tmps = SvPV_const(sv, len);
LEAVE;
SPAGAIN;
}
- else if (ckWARN(WARN_UNTIE)) {
- if (mg && SvREFCNT(obj) > 1)
+ else if (mg && SvREFCNT(obj) > 1 && ckWARN(WARN_UNTIE)) {
Perl_warner(aTHX_ packWARN(WARN_UNTIE),
"untie attempted while %"UVuf" inner references still exist",
(UV)SvREFCNT(obj) - 1 ) ;
#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
s = SvPVX(sv);
- New(403, fd_sets[i], growsize, char);
+ Newx(fd_sets[i], growsize, char);
for (offset = 0; offset < growsize; offset += masksize) {
for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
fd_sets[i][j+offset] = s[(k % masksize) + offset];
RETURN;
}
if (!gv || do_eof(gv)) { /* make sure we have fp with something */
- if (ckWARN2(WARN_UNOPENED,WARN_CLOSED)
- && (!io || (!IoIFP(io) && IoTYPE(io) != IoTYPE_WRONLY)))
+ if ((!io || (!IoIFP(io) && IoTYPE(io) != IoTYPE_WRONLY))
+ && ckWARN2(WARN_UNOPENED,WARN_CLOSED))
report_evil_fh(gv, io, PL_op->op_type);
SETERRNO(EBADF,RMS_IFI);
RETPUSHUNDEF;
PUSHBLOCK(cx, CXt_FORMAT, PL_stack_sp);
PUSHFORMAT(cx);
cx->blk_sub.retop = retop;
- PAD_SET_CUR(CvPADLIST(cv), 1);
+ SAVECOMPPAD();
+ PAD_SET_CUR_NOSAVE(CvPADLIST(cv), 1);
setdefout(gv); /* locally select filehandle so $% et al work */
return CvSTART(cv);
register IO * const io = GvIOp(gv);
PerlIO * const ofp = IoOFP(io);
PerlIO *fp;
- SV **newsp = Null(SV**);
- I32 gimme = 0;
+ SV **newsp;
+ I32 gimme;
register PERL_CONTEXT *cx;
- PERL_UNUSED_VAR(newsp);
- PERL_UNUSED_VAR(gimme);
DEBUG_f(PerlIO_printf(Perl_debug_log, "left=%ld, todo=%ld\n",
(long)IoLINES_LEFT(io), (long)FmLINES(PL_formtarget)));
/* bad_ofp: */
PL_formtarget = PL_bodytarget;
PUTBACK;
+ PERL_UNUSED_VAR(newsp);
+ PERL_UNUSED_VAR(gimme);
return cx->blk_sub.retop;
}
PP(pp_chdir)
{
dSP; dTARGET;
- const char *tmps;
- SV **svp;
+ const char *tmps = 0;
+ GV *gv = NULL;
- if( MAXARG == 1 )
- tmps = POPpconstx;
- else
- tmps = 0;
+ if( MAXARG == 1 ) {
+ SV * const sv = POPs;
+ if (SvTYPE(sv) == SVt_PVGV) {
+ gv = (GV*)sv;
+ }
+ else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVGV) {
+ gv = (GV*)SvRV(sv);
+ }
+ else {
+ tmps = SvPVx_nolen_const(sv);
+ }
+ }
+
+ if( !gv && (!tmps || !*tmps) ) {
+ HV * const table = GvHVn(PL_envgv);
+ SV **svp;
- if( !tmps || !*tmps ) {
- if ( (svp = hv_fetch(GvHVn(PL_envgv), "HOME", 4, FALSE))
- || (svp = hv_fetch(GvHVn(PL_envgv), "LOGDIR", 6, FALSE))
+ if ( (svp = hv_fetch(table, "HOME", 4, FALSE))
+ || (svp = hv_fetch(table, "LOGDIR", 6, FALSE))
#ifdef VMS
- || (svp = hv_fetch(GvHVn(PL_envgv), "SYS$LOGIN", 9, FALSE))
+ || (svp = hv_fetch(table, "SYS$LOGIN", 9, FALSE))
#endif
)
{
}
TAINT_PROPER("chdir");
- PUSHi( PerlDir_chdir(tmps) >= 0 );
+ if (gv) {
+#ifdef HAS_FCHDIR
+ IO* const io = GvIO(gv);
+ if (io) {
+ if (IoIFP(io)) {
+ PUSHi(fchdir(PerlIO_fileno(IoIFP(io))) >= 0);
+ }
+ else if (IoDIRP(io)) {
+#ifdef HAS_DIRFD
+ PUSHi(fchdir(dirfd(IoDIRP(io))) >= 0);
+#else
+ DIE(aTHX_ PL_no_func, "dirfd");
+#endif
+ }
+ else {
+ PUSHi(0);
+ }
+ }
+ else {
+ PUSHi(0);
+ }
+#else
+ DIE(aTHX_ PL_no_func, "fchdir");
+#endif
+ }
+ else
+ PUSHi( PerlDir_chdir((char *)tmps) >= 0 );
#ifdef VMS
/* Clear the DEFAULT element of ENV so we'll get the new value
* in the future. */
PerlIO *myfp;
int anum = 1;
- New(666, cmdline, strlen(cmd) + (strlen(filename) * 2) + 10, char);
+ Newx(cmdline, strlen(cmd) + (strlen(filename) * 2) + 10, char);
strcpy(cmdline, cmd);
strcat(cmdline, " ");
for (s = cmdline + strlen(cmdline); *filename; ) {
TAINT_PROPER("mkdir");
#ifdef HAS_MKDIR
- SETi( PerlDir_mkdir(tmps, mode) >= 0 );
+ SETi( PerlDir_mkdir((char *)tmps, mode) >= 0 );
#else
SETi( dooneliner("mkdir", tmps) );
oldumask = PerlLIO_umask(0);
TRIMSLASHES(tmps,len,copy);
TAINT_PROPER("rmdir");
#ifdef HAS_RMDIR
- SETi( PerlDir_rmdir(tmps) >= 0 );
+ SETi( PerlDir_rmdir((char *)tmps) >= 0 );
#else
SETi( dooneliner("rmdir", tmps) );
#endif
if (IoDIRP(io))
PerlDir_close(IoDIRP(io));
- if (!(IoDIRP(io) = PerlDir_open(dirname)))
+ if (!(IoDIRP(io) = PerlDir_open((char *)dirname)))
goto nope;
RETPUSHYES;
if (did_pipes)
PerlLIO_close(pp[1]);
#ifndef PERL_MICRO
- rsignal_save(SIGINT, SIG_IGN, &ihand);
- rsignal_save(SIGQUIT, SIG_IGN, &qhand);
+ rsignal_save(SIGINT, (Sighandler_t) SIG_IGN, &ihand);
+ rsignal_save(SIGQUIT, (Sighandler_t) SIG_IGN, &qhand);
#endif
do {
result = wait4pid(childpid, &status, 0);
return pp_gmtime();
}
+#ifdef LOCALTIME_EDGECASE_BROKEN
+static struct tm *S_my_localtime (pTHX_ Time_t *tp)
+{
+ auto time_t T;
+ auto struct tm *P;
+
+ /* No workarounds in the valid range */
+ if (!tp || *tp < 0x7fff573f || *tp >= 0x80000000)
+ return (localtime (tp));
+
+ /* This edge case is to workaround the undefined behaviour, where the
+ * TIMEZONE makes the time go beyond the defined range.
+ * gmtime (0x7fffffff) => 2038-01-19 03:14:07
+ * If there is a negative offset in TZ, like MET-1METDST, some broken
+ * implementations of localtime () (like AIX 5.2) barf with bogus
+ * return values:
+ * 0x7fffffff gmtime 2038-01-19 03:14:07
+ * 0x7fffffff localtime 1901-12-13 21:45:51
+ * 0x7fffffff mylocaltime 2038-01-19 04:14:07
+ * 0x3c19137f gmtime 2001-12-13 20:45:51
+ * 0x3c19137f localtime 2001-12-13 21:45:51
+ * 0x3c19137f mylocaltime 2001-12-13 21:45:51
+ * Given that legal timezones are typically between GMT-12 and GMT+12
+ * we turn back the clock 23 hours before calling the localtime
+ * function, and add those to the return value. This will never cause
+ * day wrapping problems, since the edge case is Tue Jan *19*
+ */
+ T = *tp - 82800; /* 23 hour. allows up to GMT-23 */
+ P = localtime (&T);
+ P->tm_hour += 23;
+ if (P->tm_hour >= 24) {
+ P->tm_hour -= 24;
+ P->tm_mday++; /* 18 -> 19 */
+ P->tm_wday++; /* Mon -> Tue */
+ P->tm_yday++; /* 18 -> 19 */
+ }
+ return (P);
+} /* S_my_localtime */
+#endif
+
PP(pp_gmtime)
{
dSP;
#endif
if (PL_op->op_type == OP_LOCALTIME)
+#ifdef LOCALTIME_EDGECASE_BROKEN
+ tmbuf = S_my_localtime(aTHX_ &when);
+#else
tmbuf = localtime(&when);
+#endif
else
tmbuf = gmtime(&when);