/usr/share/systemtap/tapset/linux/ctime.stp is in systemtap-common 2.3-1ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | /* ctime.stp - Convert seconds to human readable date string.
*
* This code was adapted from the newlib mktm_r() and asctime_r()
* functions. In newlib, mktm_r.c states that it was adapted from
* tzcode maintained by Arthur David Olson. In newlib, asctime_r.c
* doesn't have any author/copyright information.
*
* Changes copyright (C) 2006, 2008 Red Hat Inc.
*/
/**
* sfunction ctime - Convert seconds since epoch into human readable date/time string
*
* @epochsecs: Number of seconds since epoch (as returned by gettimeofday_s())
*
* Description: Takes an argument of seconds since the epoch as returned by
* gettimeofday_s(). Returns a string of the form
*
* "Wed Jun 30 21:49:08 1993"
*
* The string will always be exactly 24 characters. If the time would
* be unreasonable far in the past (before what can be represented
* with a 32 bit offset in seconds from the epoch) an error will occur
* (which can be avoided with try/catch). If the time would be
* unreasonable far in the future, an error will also occur.
*
* Note that the epoch (zero) corresponds to
*
* "Thu Jan 1 00:00:00 1970"
*
* The earliest full date given by ctime, corresponding to epochsecs
* -2147483648 is "Fri Dec 13 20:45:52 1901". The latest full date
* given by ctime, corresponding to epochsecs 2147483647 is
* "Tue Jan 19 03:14:07 2038".
*
* The abbreviations for the days of the week are ‘Sun’, ‘Mon’, ‘Tue’,
* ‘Wed’, ‘Thu’, ‘Fri’, and ‘Sat’. The abbreviations for the months
* are ‘Jan’, ‘Feb’, ‘Mar’, ‘Apr’, ‘May’, ‘Jun’, ‘Jul’, ‘Aug’, ‘Sep’,
* ‘Oct’, ‘Nov’, and ‘Dec’.
*
* Note that the real C library ctime() function puts a newline ('\n')
* character at the end of the string that this function does not.
* Also note that since the kernel has no concept of timezones, the
* returned time is always in GMT.
*/
function ctime:string(epochsecs:long)
%{ /* pure */
#define SECSPERMIN 60L
#define MINSPERHOUR 60L
#define HOURSPERDAY 24L
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
#define SECSPERDAY (SECSPERHOUR * HOURSPERDAY)
#define DAYSPERWEEK 7
#define MONSPERYEAR 12
#define EPOCH_YEAR 1970
#define EPOCH_WDAY 4
#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
static const int mon_lengths[2][MONSPERYEAR] = {
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
} ;
static const int year_lengths[2] = {
365,
366
} ;
static const char day_name[7][3] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static const char mon_name[12][3] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
long days, rem;
time_t lcltime;
int yleap;
const int *ip;
int tm_sec; /* seconds */
int tm_min; /* minutes */
int tm_hour; /* hours */
int tm_mday; /* day of the month */
int tm_mon; /* month */
int tm_year; /* year */
int tm_wday; /* day of the week */
// Check that the numer of seconds is "reasonable".
// Otherwise (especially on 64bit machines) we will be spending
// way too much time calculating the correct year, month and
// day. Also we would like the returned string to always be 24 chars.
// So cap to what can be represented normally on a 32bit machine.
int64_t MAX_POS_SECS = 2147483647LL;
int64_t MIN_NEG_SECS = -2147483648LL;
if (STAP_ARG_epochsecs > MAX_POS_SECS)
{
#if STAP_COMPAT_VERSION <= STAP_VERSION(2,2)
strlcpy(STAP_RETVALUE, "far far in the future...", MAXSTRINGLEN);
#else
CONTEXT->last_error = "Time too far in the future to be converted";
#endif
return;
}
if (STAP_ARG_epochsecs < MIN_NEG_SECS)
{
#if STAP_COMPAT_VERSION <= STAP_VERSION(2,2)
strlcpy(STAP_RETVALUE, "a long, long time ago...", MAXSTRINGLEN);
#else
CONTEXT->last_error = "Time too far in the past to be converted";
#endif
return;
}
lcltime = STAP_ARG_epochsecs;
days = ((long)lcltime) / SECSPERDAY;
rem = ((long)lcltime) % SECSPERDAY;
while (rem < 0)
{
rem += SECSPERDAY;
--days;
}
while (rem >= SECSPERDAY)
{
rem -= SECSPERDAY;
++days;
}
/* compute hour, min, and sec */
tm_hour = (int) (rem / SECSPERHOUR);
rem %= SECSPERHOUR;
tm_min = (int) (rem / SECSPERMIN);
tm_sec = (int) (rem % SECSPERMIN);
/* compute day of week */
if ((tm_wday = ((EPOCH_WDAY + days) % DAYSPERWEEK)) < 0)
tm_wday += DAYSPERWEEK;
/* compute year & day of year */
tm_year = EPOCH_YEAR;
if (days >= 0)
{
for (;;)
{
yleap = isleap(tm_year);
if (days < year_lengths[yleap])
break;
tm_year++;
days -= year_lengths[yleap];
}
}
else
{
do
{
--tm_year;
yleap = isleap(tm_year);
days += year_lengths[yleap];
} while (days < 0);
}
ip = mon_lengths[yleap];
for (tm_mon = 0; days >= ip[tm_mon]; ++tm_mon)
days -= ip[tm_mon];
tm_mday = days + 1;
/*
* At this point we have all our information. Now we need to
* convert it to an ascii representation.
*/
snprintf (STAP_RETVALUE, MAXSTRINGLEN, "%.3s %.3s%3d %.2d:%.2d:%.2d %d",
day_name[tm_wday], mon_name[tm_mon],
tm_mday, tm_hour, tm_min,
tm_sec, tm_year);
%}
|