summaryrefslogtreecommitdiff
path: root/pp_sys.c
diff options
context:
space:
mode:
authorMichael G Schwern <schwern@pobox.com>2008-09-12 17:18:02 -0700
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>2009-01-03 18:36:05 +0100
commita272e669f4b28ef6839df6dcd80d81421a1924dc (patch)
treed0114ac536208fcdbaff03440cf0e58e7e65f9b7 /pp_sys.c
parentb51c85cfecd5519fb69801887d6d6ebf80d9fce4 (diff)
downloadperl-a272e669f4b28ef6839df6dcd80d81421a1924dc.tar.gz
Patch in a 64 bit clean gmtime_r() and localtime_r() from the y2038 project. http://y2038.googlecode.com/ so Perl is no longer subject to the y2038 bug.
Use Quad_t for our 64 bit time_t replacement. Temporarily through out the "broken localtime work around". That will have to be integrated into localtime64_r(). Fix Time::Local to handle the new expanded date range. "use integer" had to go as it pegged scalars to 32 bit integers which aren't large enough to hold the new time range. There are probably portability issues. timegm, for example, is not portable. Also the assumption that "long" is 64 bits is probably wrong.
Diffstat (limited to 'pp_sys.c')
-rw-r--r--pp_sys.c74
1 files changed, 40 insertions, 34 deletions
diff --git a/pp_sys.c b/pp_sys.c
index 481864b2c2..1e445da087 100644
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -27,6 +27,8 @@
#include "EXTERN.h"
#define PERL_IN_PP_SYS_C
#include "perl.h"
+#include "localtime64.h"
+#include "localtime64.c"
#ifdef I_SHADOW
/* Shadow password support for solaris - pdo@cs.umd.edu
@@ -4446,60 +4448,64 @@ PP(pp_gmtime)
{
dVAR;
dSP;
- Time_t when;
- const struct tm *tmbuf;
+ Time64_T when;
+ struct tm tmbuf;
+ struct tm *err;
static const char * const dayname[] =
{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
static const char * const monname[] =
{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
- if (MAXARG < 1)
- (void)time(&when);
+ if (MAXARG < 1) {
+ time_t now;
+ (void)time(&now);
+ when = (Time64_T)now;
+ }
else
-#ifdef BIG_TIME
- when = (Time_t)SvNVx(POPs);
-#else
- when = (Time_t)SvIVx(POPs);
-#endif
+ when = (Time64_T)SvNVx(POPs);
if (PL_op->op_type == OP_LOCALTIME)
-#ifdef LOCALTIME_EDGECASE_BROKEN
- tmbuf = S_my_localtime(aTHX_ &when);
-#else
- tmbuf = localtime(&when);
-#endif
+ err = localtime64_r(&when, &tmbuf);
else
- tmbuf = gmtime(&when);
+ err = gmtime64_r(&when, &tmbuf);
- if (GIMME != G_ARRAY) {
+ if( (tmbuf.tm_year + 1900) < 0 )
+ Perl_warner(aTHX_ packWARN(WARN_OVERFLOW),
+ "local/gmtime under/overflowed the year");
+
+ if (GIMME != G_ARRAY) { /* scalar context */
SV *tsv;
EXTEND(SP, 1);
EXTEND_MORTAL(1);
- if (!tmbuf)
+ if (err == NULL)
RETPUSHUNDEF;
+
tsv = Perl_newSVpvf(aTHX_ "%s %s %2d %02d:%02d:%02d %d",
- dayname[tmbuf->tm_wday],
- monname[tmbuf->tm_mon],
- tmbuf->tm_mday,
- tmbuf->tm_hour,
- tmbuf->tm_min,
- tmbuf->tm_sec,
- tmbuf->tm_year + 1900);
+ dayname[tmbuf.tm_wday],
+ monname[tmbuf.tm_mon],
+ tmbuf.tm_mday,
+ tmbuf.tm_hour,
+ tmbuf.tm_min,
+ tmbuf.tm_sec,
+ tmbuf.tm_year + 1900);
mPUSHs(tsv);
}
- else if (tmbuf) {
+ else { /* list context */
+ if ( err == NULL )
+ RETURN;
+
EXTEND(SP, 9);
EXTEND_MORTAL(9);
- mPUSHi(tmbuf->tm_sec);
- mPUSHi(tmbuf->tm_min);
- mPUSHi(tmbuf->tm_hour);
- mPUSHi(tmbuf->tm_mday);
- mPUSHi(tmbuf->tm_mon);
- mPUSHi(tmbuf->tm_year);
- mPUSHi(tmbuf->tm_wday);
- mPUSHi(tmbuf->tm_yday);
- mPUSHi(tmbuf->tm_isdst);
+ mPUSHi(tmbuf.tm_sec);
+ mPUSHi(tmbuf.tm_min);
+ mPUSHi(tmbuf.tm_hour);
+ mPUSHi(tmbuf.tm_mday);
+ mPUSHi(tmbuf.tm_mon);
+ mPUSHi(tmbuf.tm_year);
+ mPUSHi(tmbuf.tm_wday);
+ mPUSHi(tmbuf.tm_yday);
+ mPUSHi(tmbuf.tm_isdst);
}
RETURN;
}