1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate * 26*7c478bd9Sstevel@tonic-gate * Time routines, snagged from libc. 27*7c478bd9Sstevel@tonic-gate */ 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #include <errno.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/bootvfs.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/salib.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/promif.h> 36*7c478bd9Sstevel@tonic-gate #include <stdio.h> 37*7c478bd9Sstevel@tonic-gate #include <time.h> 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #define CBUFSIZ 26 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate static time_t start_time, secs_since_boot; 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate const int __year_lengths[2] = { 44*7c478bd9Sstevel@tonic-gate DAYS_PER_NYEAR, DAYS_PER_LYEAR 45*7c478bd9Sstevel@tonic-gate }; 46*7c478bd9Sstevel@tonic-gate const int __mon_lengths[2][MONS_PER_YEAR] = { 47*7c478bd9Sstevel@tonic-gate 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 48*7c478bd9Sstevel@tonic-gate 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 49*7c478bd9Sstevel@tonic-gate }; 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate /* 52*7c478bd9Sstevel@tonic-gate * Initializes our "clock" to the creation date of /timestamp, which is 53*7c478bd9Sstevel@tonic-gate * made on the fly for us by the web server. Thereafter, time() will keep 54*7c478bd9Sstevel@tonic-gate * time sort of up to date. 55*7c478bd9Sstevel@tonic-gate */ 56*7c478bd9Sstevel@tonic-gate void 57*7c478bd9Sstevel@tonic-gate init_boot_time(void) 58*7c478bd9Sstevel@tonic-gate { 59*7c478bd9Sstevel@tonic-gate struct stat sb; 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate if (start_time == 0) { 62*7c478bd9Sstevel@tonic-gate if (stat("/timestamp", &sb) < 0) 63*7c478bd9Sstevel@tonic-gate prom_panic("init_boot_time: cannot stat /timestamp"); 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate start_time = sb.st_ctim.tv_sec; 66*7c478bd9Sstevel@tonic-gate secs_since_boot = prom_gettime() / 1000; 67*7c478bd9Sstevel@tonic-gate } 68*7c478bd9Sstevel@tonic-gate } 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate /* 71*7c478bd9Sstevel@tonic-gate * Time is crudely incremented. 72*7c478bd9Sstevel@tonic-gate */ 73*7c478bd9Sstevel@tonic-gate time_t 74*7c478bd9Sstevel@tonic-gate time(time_t *tloc) 75*7c478bd9Sstevel@tonic-gate { 76*7c478bd9Sstevel@tonic-gate time_t time_now; 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate time_now = start_time + ((prom_gettime() / 1000) - secs_since_boot); 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate if (tloc != NULL) 81*7c478bd9Sstevel@tonic-gate *tloc = time_now; 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate if (start_time == 0) 84*7c478bd9Sstevel@tonic-gate return (0); 85*7c478bd9Sstevel@tonic-gate else 86*7c478bd9Sstevel@tonic-gate return (time_now); 87*7c478bd9Sstevel@tonic-gate } 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate struct tm * 90*7c478bd9Sstevel@tonic-gate gmtime(const time_t *clock) 91*7c478bd9Sstevel@tonic-gate { 92*7c478bd9Sstevel@tonic-gate static struct tm result; 93*7c478bd9Sstevel@tonic-gate struct tm *tmp; 94*7c478bd9Sstevel@tonic-gate long days; 95*7c478bd9Sstevel@tonic-gate int rem; 96*7c478bd9Sstevel@tonic-gate long y; 97*7c478bd9Sstevel@tonic-gate long newy; 98*7c478bd9Sstevel@tonic-gate const int *ip; 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate tmp = &result; 101*7c478bd9Sstevel@tonic-gate days = *clock / SECS_PER_DAY; 102*7c478bd9Sstevel@tonic-gate rem = *clock % SECS_PER_DAY; 103*7c478bd9Sstevel@tonic-gate while (rem < 0) { 104*7c478bd9Sstevel@tonic-gate rem += SECS_PER_DAY; 105*7c478bd9Sstevel@tonic-gate --days; 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate while (rem >= SECS_PER_DAY) { 108*7c478bd9Sstevel@tonic-gate rem -= SECS_PER_DAY; 109*7c478bd9Sstevel@tonic-gate ++days; 110*7c478bd9Sstevel@tonic-gate } 111*7c478bd9Sstevel@tonic-gate tmp->tm_hour = (int)(rem / SECS_PER_HOUR); 112*7c478bd9Sstevel@tonic-gate rem = rem % SECS_PER_HOUR; 113*7c478bd9Sstevel@tonic-gate tmp->tm_min = (int)(rem / SECS_PER_MIN); 114*7c478bd9Sstevel@tonic-gate tmp->tm_sec = (int)(rem % SECS_PER_MIN); 115*7c478bd9Sstevel@tonic-gate tmp->tm_wday = (int)((EPOCH_WDAY + days) % DAYS_PER_WEEK); 116*7c478bd9Sstevel@tonic-gate if (tmp->tm_wday < 0) 117*7c478bd9Sstevel@tonic-gate tmp->tm_wday += DAYS_PER_WEEK; 118*7c478bd9Sstevel@tonic-gate y = EPOCH_YEAR; 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400) 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate while (days < 0 || days >= (long)__year_lengths[isleap(y)]) { 123*7c478bd9Sstevel@tonic-gate newy = y + days / DAYS_PER_NYEAR; 124*7c478bd9Sstevel@tonic-gate if (days < 0) 125*7c478bd9Sstevel@tonic-gate --newy; 126*7c478bd9Sstevel@tonic-gate days -= ((long)newy - (long)y) * DAYS_PER_NYEAR + 127*7c478bd9Sstevel@tonic-gate LEAPS_THRU_END_OF(newy > 0 ? newy - 1L : newy) - 128*7c478bd9Sstevel@tonic-gate LEAPS_THRU_END_OF(y > 0 ? y - 1L : y); 129*7c478bd9Sstevel@tonic-gate y = newy; 130*7c478bd9Sstevel@tonic-gate } 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate tmp->tm_year = y - TM_YEAR_BASE; 133*7c478bd9Sstevel@tonic-gate tmp->tm_yday = days; 134*7c478bd9Sstevel@tonic-gate ip = __mon_lengths[isleap(y)]; 135*7c478bd9Sstevel@tonic-gate for (tmp->tm_mon = 0; days >= ip[tmp->tm_mon]; ++(tmp->tm_mon)) 136*7c478bd9Sstevel@tonic-gate days = days - ip[tmp->tm_mon]; 137*7c478bd9Sstevel@tonic-gate tmp->tm_mday = (days + 1); 138*7c478bd9Sstevel@tonic-gate tmp->tm_isdst = 0; 139*7c478bd9Sstevel@tonic-gate return (tmp); 140*7c478bd9Sstevel@tonic-gate } 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate /* 143*7c478bd9Sstevel@tonic-gate * The standalone booter runs in GMT. 144*7c478bd9Sstevel@tonic-gate */ 145*7c478bd9Sstevel@tonic-gate struct tm * 146*7c478bd9Sstevel@tonic-gate localtime(const time_t *clock) 147*7c478bd9Sstevel@tonic-gate { 148*7c478bd9Sstevel@tonic-gate return (gmtime(clock)); 149*7c478bd9Sstevel@tonic-gate } 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate static char * 152*7c478bd9Sstevel@tonic-gate ct_numb(char *cp, int n) 153*7c478bd9Sstevel@tonic-gate { 154*7c478bd9Sstevel@tonic-gate cp++; 155*7c478bd9Sstevel@tonic-gate if (n >= 10) 156*7c478bd9Sstevel@tonic-gate *cp++ = (n / 10) % 10 + '0'; 157*7c478bd9Sstevel@tonic-gate else 158*7c478bd9Sstevel@tonic-gate *cp++ = ' '; /* Pad with blanks */ 159*7c478bd9Sstevel@tonic-gate *cp++ = n % 10 + '0'; 160*7c478bd9Sstevel@tonic-gate return (cp); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate char * 164*7c478bd9Sstevel@tonic-gate asctime(const struct tm *t) 165*7c478bd9Sstevel@tonic-gate { 166*7c478bd9Sstevel@tonic-gate char *cp; 167*7c478bd9Sstevel@tonic-gate const char *ncp; 168*7c478bd9Sstevel@tonic-gate const int *tp; 169*7c478bd9Sstevel@tonic-gate const char *Date = "Day Mon 00 00:00:00 1900\n"; 170*7c478bd9Sstevel@tonic-gate const char *Day = "SunMonTueWedThuFriSat"; 171*7c478bd9Sstevel@tonic-gate const char *Month = "JanFebMarAprMayJunJulAugSepOctNovDec"; 172*7c478bd9Sstevel@tonic-gate static char cbuf[CBUFSIZ]; 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate cp = cbuf; 175*7c478bd9Sstevel@tonic-gate for (ncp = Date; *cp++ = *ncp++; /* */); 176*7c478bd9Sstevel@tonic-gate ncp = Day + (3 * t->tm_wday); 177*7c478bd9Sstevel@tonic-gate cp = cbuf; 178*7c478bd9Sstevel@tonic-gate *cp++ = *ncp++; 179*7c478bd9Sstevel@tonic-gate *cp++ = *ncp++; 180*7c478bd9Sstevel@tonic-gate *cp++ = *ncp++; 181*7c478bd9Sstevel@tonic-gate cp++; 182*7c478bd9Sstevel@tonic-gate tp = &t->tm_mon; 183*7c478bd9Sstevel@tonic-gate ncp = Month + ((*tp) * 3); 184*7c478bd9Sstevel@tonic-gate *cp++ = *ncp++; 185*7c478bd9Sstevel@tonic-gate *cp++ = *ncp++; 186*7c478bd9Sstevel@tonic-gate *cp++ = *ncp++; 187*7c478bd9Sstevel@tonic-gate cp = ct_numb(cp, *--tp); 188*7c478bd9Sstevel@tonic-gate cp = ct_numb(cp, *--tp + 100); 189*7c478bd9Sstevel@tonic-gate cp = ct_numb(cp, *--tp + 100); 190*7c478bd9Sstevel@tonic-gate --tp; 191*7c478bd9Sstevel@tonic-gate cp = ct_numb(cp, *tp + 100); 192*7c478bd9Sstevel@tonic-gate if (t->tm_year < 100) { 193*7c478bd9Sstevel@tonic-gate /* Common case: "19" already in buffer */ 194*7c478bd9Sstevel@tonic-gate cp += 2; 195*7c478bd9Sstevel@tonic-gate } else if (t->tm_year < 8100) { 196*7c478bd9Sstevel@tonic-gate cp = ct_numb(cp, (1900 + t->tm_year) / 100); 197*7c478bd9Sstevel@tonic-gate cp--; 198*7c478bd9Sstevel@tonic-gate } else { 199*7c478bd9Sstevel@tonic-gate /* Only 4-digit years are supported */ 200*7c478bd9Sstevel@tonic-gate errno = EOVERFLOW; 201*7c478bd9Sstevel@tonic-gate return (NULL); 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate (void) ct_numb(cp, t->tm_year + 100); 204*7c478bd9Sstevel@tonic-gate return (cbuf); 205*7c478bd9Sstevel@tonic-gate } 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate char * 208*7c478bd9Sstevel@tonic-gate ctime(const time_t *t) 209*7c478bd9Sstevel@tonic-gate { 210*7c478bd9Sstevel@tonic-gate return (asctime(localtime(t))); 211*7c478bd9Sstevel@tonic-gate } 212