4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 * Time routines, snagged from libc.
29 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include <sys/types.h>
33 #include <sys/bootvfs.h>
34 #include <sys/salib.h>
35 #include <sys/promif.h>
41 static time_t start_time
, secs_since_boot
;
43 const int __year_lengths
[2] = {
44 DAYS_PER_NYEAR
, DAYS_PER_LYEAR
46 const int __mon_lengths
[2][MONS_PER_YEAR
] = {
47 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
48 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
52 * Initializes our "clock" to the creation date of /timestamp, which is
53 * made on the fly for us by the web server. Thereafter, time() will keep
54 * time sort of up to date.
61 if (start_time
== 0) {
62 if (stat("/timestamp", &sb
) < 0)
63 prom_panic("init_boot_time: cannot stat /timestamp");
65 start_time
= sb
.st_ctim
.tv_sec
;
66 secs_since_boot
= prom_gettime() / 1000;
71 * Time is crudely incremented.
78 time_now
= start_time
+ ((prom_gettime() / 1000) - secs_since_boot
);
90 gmtime(const time_t *clock
)
92 static struct tm result
;
101 days
= *clock
/ SECS_PER_DAY
;
102 rem
= *clock
% SECS_PER_DAY
;
107 while (rem
>= SECS_PER_DAY
) {
111 tmp
->tm_hour
= (int)(rem
/ SECS_PER_HOUR
);
112 rem
= rem
% SECS_PER_HOUR
;
113 tmp
->tm_min
= (int)(rem
/ SECS_PER_MIN
);
114 tmp
->tm_sec
= (int)(rem
% SECS_PER_MIN
);
115 tmp
->tm_wday
= (int)((EPOCH_WDAY
+ days
) % DAYS_PER_WEEK
);
116 if (tmp
->tm_wday
< 0)
117 tmp
->tm_wday
+= DAYS_PER_WEEK
;
120 #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
122 while (days
< 0 || days
>= (long)__year_lengths
[isleap(y
)]) {
123 newy
= y
+ days
/ DAYS_PER_NYEAR
;
126 days
-= ((long)newy
- (long)y
) * DAYS_PER_NYEAR
+
127 LEAPS_THRU_END_OF(newy
> 0 ? newy
- 1L : newy
) -
128 LEAPS_THRU_END_OF(y
> 0 ? y
- 1L : y
);
132 tmp
->tm_year
= y
- TM_YEAR_BASE
;
134 ip
= __mon_lengths
[isleap(y
)];
135 for (tmp
->tm_mon
= 0; days
>= ip
[tmp
->tm_mon
]; ++(tmp
->tm_mon
))
136 days
= days
- ip
[tmp
->tm_mon
];
137 tmp
->tm_mday
= (days
+ 1);
143 * The standalone booter runs in GMT.
146 localtime(const time_t *clock
)
148 return (gmtime(clock
));
152 ct_numb(char *cp
, int n
)
156 *cp
++ = (n
/ 10) % 10 + '0';
158 *cp
++ = ' '; /* Pad with blanks */
159 *cp
++ = n
% 10 + '0';
164 asctime(const struct tm
*t
)
169 const char *Date
= "Day Mon 00 00:00:00 1900\n";
170 const char *Day
= "SunMonTueWedThuFriSat";
171 const char *Month
= "JanFebMarAprMayJunJulAugSepOctNovDec";
172 static char cbuf
[CBUFSIZ
];
175 for (ncp
= Date
; *cp
++ = *ncp
++; /* */);
176 ncp
= Day
+ (3 * t
->tm_wday
);
183 ncp
= Month
+ ((*tp
) * 3);
187 cp
= ct_numb(cp
, *--tp
);
188 cp
= ct_numb(cp
, *--tp
+ 100);
189 cp
= ct_numb(cp
, *--tp
+ 100);
191 cp
= ct_numb(cp
, *tp
+ 100);
192 if (t
->tm_year
< 100) {
193 /* Common case: "19" already in buffer */
195 } else if (t
->tm_year
< 8100) {
196 cp
= ct_numb(cp
, (1900 + t
->tm_year
) / 100);
199 /* Only 4-digit years are supported */
203 (void) ct_numb(cp
, t
->tm_year
+ 100);
208 ctime(const time_t *t
)
210 return (asctime(localtime(t
)));