1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright (c) 1989, 1998 by Sun Microsystems, Inc. 3*7c478bd9Sstevel@tonic-gate * All rights reserved. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* 7*7c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 8*7c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 9*7c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 10*7c478bd9Sstevel@tonic-gate */ 11*7c478bd9Sstevel@tonic-gate 12*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 13*7c478bd9Sstevel@tonic-gate 14*7c478bd9Sstevel@tonic-gate #ifndef KERNEL 15*7c478bd9Sstevel@tonic-gate #define KERNEL 16*7c478bd9Sstevel@tonic-gate #endif 17*7c478bd9Sstevel@tonic-gate 18*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 19*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 20*7c478bd9Sstevel@tonic-gate #include <sys/buf.h> 21*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 22*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 23*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 24*7c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 25*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 26*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 27*7c478bd9Sstevel@tonic-gate #include <sys/fs/pc_fs.h> 28*7c478bd9Sstevel@tonic-gate #include <sys/fs/pc_label.h> 29*7c478bd9Sstevel@tonic-gate #include <sys/fs/pc_dir.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/fs/pc_node.h> 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate /* 33*7c478bd9Sstevel@tonic-gate * Structure returned by gmtime and localtime calls (see ctime(3)). 34*7c478bd9Sstevel@tonic-gate */ 35*7c478bd9Sstevel@tonic-gate struct tm { 36*7c478bd9Sstevel@tonic-gate short tm_sec; 37*7c478bd9Sstevel@tonic-gate short tm_min; 38*7c478bd9Sstevel@tonic-gate short tm_hour; 39*7c478bd9Sstevel@tonic-gate short tm_mday; 40*7c478bd9Sstevel@tonic-gate short tm_mon; 41*7c478bd9Sstevel@tonic-gate short tm_year; 42*7c478bd9Sstevel@tonic-gate short tm_wday; 43*7c478bd9Sstevel@tonic-gate short tm_yday; 44*7c478bd9Sstevel@tonic-gate short tm_isdst; 45*7c478bd9Sstevel@tonic-gate }; 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate void pc_tvtopct(timestruc_t *, struct pctime *); 48*7c478bd9Sstevel@tonic-gate void pc_pcttotv(struct pctime *, timestruc_t *); 49*7c478bd9Sstevel@tonic-gate int pc_validchar(char); 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate static struct tm *localtime(time_t *tim); 52*7c478bd9Sstevel@tonic-gate static int sunday(struct tm *, int); 53*7c478bd9Sstevel@tonic-gate static int dysize(int); 54*7c478bd9Sstevel@tonic-gate static struct tm *gmtime(int); 55*7c478bd9Sstevel@tonic-gate static time_t ctime(struct tm *); 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate /* The cm struct defines tm_year relative to 1900 */ 58*7c478bd9Sstevel@tonic-gate #define YEAR_ZERO 1900 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate /* 61*7c478bd9Sstevel@tonic-gate * convert timestruct to pctime 62*7c478bd9Sstevel@tonic-gate */ 63*7c478bd9Sstevel@tonic-gate void 64*7c478bd9Sstevel@tonic-gate pc_tvtopct( 65*7c478bd9Sstevel@tonic-gate timestruc_t *tvp, /* time input */ 66*7c478bd9Sstevel@tonic-gate struct pctime *pctp) /* pctime output */ 67*7c478bd9Sstevel@tonic-gate { 68*7c478bd9Sstevel@tonic-gate struct tm *ctp; 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate ctp = localtime(&tvp->tv_sec); 71*7c478bd9Sstevel@tonic-gate #define setfield(S, FIELD, SFT, MSK) \ 72*7c478bd9Sstevel@tonic-gate S = (ltohs(S) & ~(MSK << SFT)) | (((FIELD) & MSK) << SFT); S = htols(S); 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate setfield(pctp->pct_time, ctp->tm_sec / 2, SECSHIFT, SECMASK); 75*7c478bd9Sstevel@tonic-gate setfield(pctp->pct_time, ctp->tm_min, MINSHIFT, MINMASK); 76*7c478bd9Sstevel@tonic-gate setfield(pctp->pct_time, ctp->tm_hour, HOURSHIFT, HOURMASK); 77*7c478bd9Sstevel@tonic-gate setfield(pctp->pct_date, ctp->tm_mday, DAYSHIFT, DAYMASK); 78*7c478bd9Sstevel@tonic-gate setfield(pctp->pct_date, ctp->tm_mon + 1, MONSHIFT, MONMASK); 79*7c478bd9Sstevel@tonic-gate setfield(pctp->pct_date, ctp->tm_year - 80, YEARSHIFT, YEARMASK); 80*7c478bd9Sstevel@tonic-gate #undef setfield 81*7c478bd9Sstevel@tonic-gate } 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate /* 84*7c478bd9Sstevel@tonic-gate * convert pctime to timeval 85*7c478bd9Sstevel@tonic-gate */ 86*7c478bd9Sstevel@tonic-gate void 87*7c478bd9Sstevel@tonic-gate pc_pcttotv( 88*7c478bd9Sstevel@tonic-gate struct pctime *pctp, /* ptime input */ 89*7c478bd9Sstevel@tonic-gate timestruc_t *tvp) /* tinmeval output */ 90*7c478bd9Sstevel@tonic-gate { 91*7c478bd9Sstevel@tonic-gate struct tm tm; 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate #define getfield(S, SFT, M) (((int)(ltohs(S)) >> SFT) & M) 94*7c478bd9Sstevel@tonic-gate tm.tm_sec = getfield(pctp->pct_time, SECSHIFT, SECMASK) * 2; 95*7c478bd9Sstevel@tonic-gate tm.tm_min = getfield(pctp->pct_time, MINSHIFT, MINMASK); 96*7c478bd9Sstevel@tonic-gate tm.tm_hour = getfield(pctp->pct_time, HOURSHIFT, HOURMASK); 97*7c478bd9Sstevel@tonic-gate tm.tm_mday = getfield(pctp->pct_date, DAYSHIFT, DAYMASK); 98*7c478bd9Sstevel@tonic-gate tm.tm_mon = getfield(pctp->pct_date, MONSHIFT, MONMASK) - 1; 99*7c478bd9Sstevel@tonic-gate tm.tm_year = 80 + getfield(pctp->pct_date, YEARSHIFT, YEARMASK); 100*7c478bd9Sstevel@tonic-gate #undef getfield 101*7c478bd9Sstevel@tonic-gate tvp->tv_nsec = 0; 102*7c478bd9Sstevel@tonic-gate tvp->tv_sec = ctime(&tm); 103*7c478bd9Sstevel@tonic-gate } 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate /* 106*7c478bd9Sstevel@tonic-gate * This routine converts time as follows. 107*7c478bd9Sstevel@tonic-gate * The epoch is 0000 Jan 1 1970 GMT. 108*7c478bd9Sstevel@tonic-gate * The argument time is in seconds since then. 109*7c478bd9Sstevel@tonic-gate * The localtime(t) entry returns a pointer to an array 110*7c478bd9Sstevel@tonic-gate * containing 111*7c478bd9Sstevel@tonic-gate * seconds (0-59) 112*7c478bd9Sstevel@tonic-gate * minutes (0-59) 113*7c478bd9Sstevel@tonic-gate * hours (0-23) 114*7c478bd9Sstevel@tonic-gate * day of month (1-31) 115*7c478bd9Sstevel@tonic-gate * month (0-11) 116*7c478bd9Sstevel@tonic-gate * year-1900 117*7c478bd9Sstevel@tonic-gate * weekday (0-6, Sun is 0) 118*7c478bd9Sstevel@tonic-gate * day of the year 119*7c478bd9Sstevel@tonic-gate * daylight savings flag 120*7c478bd9Sstevel@tonic-gate * 121*7c478bd9Sstevel@tonic-gate * The routine calls the system to determine the local 122*7c478bd9Sstevel@tonic-gate * timezone and whether Daylight Saving Time is permitted locally. 123*7c478bd9Sstevel@tonic-gate * (DST is then determined by the current local rules) 124*7c478bd9Sstevel@tonic-gate * 125*7c478bd9Sstevel@tonic-gate * The routine does not work 126*7c478bd9Sstevel@tonic-gate * in Saudi Arabia which runs on Solar time. 127*7c478bd9Sstevel@tonic-gate * 128*7c478bd9Sstevel@tonic-gate */ 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate static int dmsize[12] = 131*7c478bd9Sstevel@tonic-gate { 132*7c478bd9Sstevel@tonic-gate 31, 133*7c478bd9Sstevel@tonic-gate 28, 134*7c478bd9Sstevel@tonic-gate 31, 135*7c478bd9Sstevel@tonic-gate 30, 136*7c478bd9Sstevel@tonic-gate 31, 137*7c478bd9Sstevel@tonic-gate 30, 138*7c478bd9Sstevel@tonic-gate 31, 139*7c478bd9Sstevel@tonic-gate 31, 140*7c478bd9Sstevel@tonic-gate 30, 141*7c478bd9Sstevel@tonic-gate 31, 142*7c478bd9Sstevel@tonic-gate 30, 143*7c478bd9Sstevel@tonic-gate 31 144*7c478bd9Sstevel@tonic-gate }; 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate /* 147*7c478bd9Sstevel@tonic-gate * The following table is used for 1974 and 1975 and 148*7c478bd9Sstevel@tonic-gate * gives the day number of the first day after the Sunday of the 149*7c478bd9Sstevel@tonic-gate * change. 150*7c478bd9Sstevel@tonic-gate */ 151*7c478bd9Sstevel@tonic-gate struct dstab { 152*7c478bd9Sstevel@tonic-gate int dayyr; 153*7c478bd9Sstevel@tonic-gate int daylb; 154*7c478bd9Sstevel@tonic-gate int dayle; 155*7c478bd9Sstevel@tonic-gate }; 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate static struct dstab usdaytab[] = { 158*7c478bd9Sstevel@tonic-gate 1974, 5, 333, /* 1974: Jan 6 - last Sun. in Nov */ 159*7c478bd9Sstevel@tonic-gate 1975, 58, 303, /* 1975: Last Sun. in Feb - last Sun in Oct */ 160*7c478bd9Sstevel@tonic-gate 0, 119, 303, /* all other years: end Apr - end Oct */ 161*7c478bd9Sstevel@tonic-gate }; 162*7c478bd9Sstevel@tonic-gate static struct dstab ausdaytab[] = { 163*7c478bd9Sstevel@tonic-gate 1970, 400, 0, /* 1970: no daylight saving at all */ 164*7c478bd9Sstevel@tonic-gate 1971, 303, 0, /* 1971: daylight saving from Oct 31 */ 165*7c478bd9Sstevel@tonic-gate 1972, 303, 58, /* 1972: Jan 1 -> Feb 27 & Oct 31 -> dec 31 */ 166*7c478bd9Sstevel@tonic-gate 0, 303, 65, /* others: -> Mar 7, Oct 31 -> */ 167*7c478bd9Sstevel@tonic-gate }; 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate /* 170*7c478bd9Sstevel@tonic-gate * The European tables ... based on hearsay 171*7c478bd9Sstevel@tonic-gate * Believed correct for: 172*7c478bd9Sstevel@tonic-gate * WE: Great Britain, Ireland, Portugal 173*7c478bd9Sstevel@tonic-gate * ME: Belgium, Luxembourg, Netherlands, Denmark, Norway, 174*7c478bd9Sstevel@tonic-gate * Austria, Poland, Czechoslovakia, Sweden, Switzerland, 175*7c478bd9Sstevel@tonic-gate * DDR, DBR, France, Spain, Hungary, Italy, Jugoslavia 176*7c478bd9Sstevel@tonic-gate * Eastern European dst is unknown, we'll make it ME until someone speaks up. 177*7c478bd9Sstevel@tonic-gate * EE: Bulgaria, Finland, Greece, Rumania, Turkey, Western Russia 178*7c478bd9Sstevel@tonic-gate */ 179*7c478bd9Sstevel@tonic-gate static struct dstab wedaytab[] = { 180*7c478bd9Sstevel@tonic-gate 1983, 86, 303, /* 1983: end March - end Oct */ 181*7c478bd9Sstevel@tonic-gate 1984, 86, 303, /* 1984: end March - end Oct */ 182*7c478bd9Sstevel@tonic-gate 1985, 86, 303, /* 1985: end March - end Oct */ 183*7c478bd9Sstevel@tonic-gate 0, 400, 0, /* others: no daylight saving at all ??? */ 184*7c478bd9Sstevel@tonic-gate }; 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate static struct dstab medaytab[] = { 187*7c478bd9Sstevel@tonic-gate 1983, 86, 272, /* 1983: end March - end Sep */ 188*7c478bd9Sstevel@tonic-gate 1984, 86, 272, /* 1984: end March - end Sep */ 189*7c478bd9Sstevel@tonic-gate 1985, 86, 272, /* 1985: end March - end Sep */ 190*7c478bd9Sstevel@tonic-gate 0, 400, 0, /* others: no daylight saving at all ??? */ 191*7c478bd9Sstevel@tonic-gate }; 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate static struct dayrules { 194*7c478bd9Sstevel@tonic-gate int dst_type; /* number obtained from system */ 195*7c478bd9Sstevel@tonic-gate int dst_hrs; /* hours to add when dst on */ 196*7c478bd9Sstevel@tonic-gate struct dstab *dst_rules; /* one of the above */ 197*7c478bd9Sstevel@tonic-gate enum {STH, NTH} dst_hemi; /* southern, northern hemisphere */ 198*7c478bd9Sstevel@tonic-gate } dayrules [] = { 199*7c478bd9Sstevel@tonic-gate DST_USA, 1, usdaytab, NTH, 200*7c478bd9Sstevel@tonic-gate DST_AUST, 1, ausdaytab, STH, 201*7c478bd9Sstevel@tonic-gate DST_WET, 1, wedaytab, NTH, 202*7c478bd9Sstevel@tonic-gate DST_MET, 1, medaytab, NTH, 203*7c478bd9Sstevel@tonic-gate DST_EET, 1, medaytab, NTH, /* XXX */ 204*7c478bd9Sstevel@tonic-gate -1, 205*7c478bd9Sstevel@tonic-gate }; 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate struct pcfs_args pc_tz; /* this is set by pcfs_mount */ 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate static struct tm * 210*7c478bd9Sstevel@tonic-gate localtime(time_t *tim) 211*7c478bd9Sstevel@tonic-gate { 212*7c478bd9Sstevel@tonic-gate int dayno; 213*7c478bd9Sstevel@tonic-gate struct tm *ct; 214*7c478bd9Sstevel@tonic-gate int dalybeg, daylend; 215*7c478bd9Sstevel@tonic-gate struct dayrules *dr; 216*7c478bd9Sstevel@tonic-gate struct dstab *ds; 217*7c478bd9Sstevel@tonic-gate int year; 218*7c478bd9Sstevel@tonic-gate int copyt; 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate copyt = *tim - (int)pc_tz.secondswest; 221*7c478bd9Sstevel@tonic-gate ct = gmtime(copyt); 222*7c478bd9Sstevel@tonic-gate dayno = ct->tm_yday; 223*7c478bd9Sstevel@tonic-gate for (dr = dayrules; dr->dst_type >= 0; dr++) 224*7c478bd9Sstevel@tonic-gate if (dr->dst_type == pc_tz.dsttime) 225*7c478bd9Sstevel@tonic-gate break; 226*7c478bd9Sstevel@tonic-gate if (dr->dst_type >= 0) { 227*7c478bd9Sstevel@tonic-gate year = ct->tm_year + 1900; 228*7c478bd9Sstevel@tonic-gate for (ds = dr->dst_rules; ds->dayyr; ds++) { 229*7c478bd9Sstevel@tonic-gate if (ds->dayyr == year) { 230*7c478bd9Sstevel@tonic-gate break; 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate dalybeg = ds->daylb; /* first Sun after dst starts */ 234*7c478bd9Sstevel@tonic-gate daylend = ds->dayle; /* first Sun after dst ends */ 235*7c478bd9Sstevel@tonic-gate dalybeg = sunday(ct, dalybeg); 236*7c478bd9Sstevel@tonic-gate daylend = sunday(ct, daylend); 237*7c478bd9Sstevel@tonic-gate switch (dr->dst_hemi) { 238*7c478bd9Sstevel@tonic-gate case NTH: 239*7c478bd9Sstevel@tonic-gate if (!( 240*7c478bd9Sstevel@tonic-gate (dayno > dalybeg || 241*7c478bd9Sstevel@tonic-gate (dayno == dalybeg && ct->tm_hour >= 2)) && 242*7c478bd9Sstevel@tonic-gate (dayno < daylend || 243*7c478bd9Sstevel@tonic-gate (dayno == daylend && ct->tm_hour < 1)))) { 244*7c478bd9Sstevel@tonic-gate return (ct); 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate break; 247*7c478bd9Sstevel@tonic-gate case STH: 248*7c478bd9Sstevel@tonic-gate if (!( 249*7c478bd9Sstevel@tonic-gate (dayno > dalybeg || 250*7c478bd9Sstevel@tonic-gate (dayno == dalybeg && ct->tm_hour >= 2)) || 251*7c478bd9Sstevel@tonic-gate (dayno < daylend || 252*7c478bd9Sstevel@tonic-gate (dayno == daylend && ct->tm_hour < 2)))) { 253*7c478bd9Sstevel@tonic-gate return (ct); 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate break; 256*7c478bd9Sstevel@tonic-gate default: 257*7c478bd9Sstevel@tonic-gate return (ct); 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate copyt += dr->dst_hrs*60*60; 260*7c478bd9Sstevel@tonic-gate ct = gmtime(copyt); 261*7c478bd9Sstevel@tonic-gate ct->tm_isdst++; 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate return (ct); 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate /* 267*7c478bd9Sstevel@tonic-gate * The argument is a 0-origin day number. 268*7c478bd9Sstevel@tonic-gate * The value is the day number of the first 269*7c478bd9Sstevel@tonic-gate * Sunday on or after the day. 270*7c478bd9Sstevel@tonic-gate */ 271*7c478bd9Sstevel@tonic-gate static int 272*7c478bd9Sstevel@tonic-gate sunday(struct tm *t, int d) 273*7c478bd9Sstevel@tonic-gate { 274*7c478bd9Sstevel@tonic-gate if (d >= 58) 275*7c478bd9Sstevel@tonic-gate d += dysize(YEAR_ZERO + t->tm_year) - 365; 276*7c478bd9Sstevel@tonic-gate return (d - (d - t->tm_yday + t->tm_wday + 700) % 7); 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate static int 280*7c478bd9Sstevel@tonic-gate dysize(int y) 281*7c478bd9Sstevel@tonic-gate { 282*7c478bd9Sstevel@tonic-gate if (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) 283*7c478bd9Sstevel@tonic-gate return (366); 284*7c478bd9Sstevel@tonic-gate return (365); 285*7c478bd9Sstevel@tonic-gate } 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate static struct tm * 288*7c478bd9Sstevel@tonic-gate gmtime(int tim) 289*7c478bd9Sstevel@tonic-gate { 290*7c478bd9Sstevel@tonic-gate int d0, d1; 291*7c478bd9Sstevel@tonic-gate int hms, day; 292*7c478bd9Sstevel@tonic-gate short *tp; 293*7c478bd9Sstevel@tonic-gate static struct tm xtime; 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate /* 296*7c478bd9Sstevel@tonic-gate * break initial number into days 297*7c478bd9Sstevel@tonic-gate */ 298*7c478bd9Sstevel@tonic-gate hms = tim % 86400; 299*7c478bd9Sstevel@tonic-gate day = tim / 86400; 300*7c478bd9Sstevel@tonic-gate if (hms < 0) { 301*7c478bd9Sstevel@tonic-gate hms += 86400; 302*7c478bd9Sstevel@tonic-gate day -= 1; 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate tp = (short *)&xtime; 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate /* 307*7c478bd9Sstevel@tonic-gate * generate hours:minutes:seconds 308*7c478bd9Sstevel@tonic-gate */ 309*7c478bd9Sstevel@tonic-gate *tp++ = hms%60; 310*7c478bd9Sstevel@tonic-gate d1 = hms/60; 311*7c478bd9Sstevel@tonic-gate *tp++ = d1%60; 312*7c478bd9Sstevel@tonic-gate d1 /= 60; 313*7c478bd9Sstevel@tonic-gate *tp++ = (short)d1; 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate /* 316*7c478bd9Sstevel@tonic-gate * day is the day number. 317*7c478bd9Sstevel@tonic-gate * generate day of the week. 318*7c478bd9Sstevel@tonic-gate * The addend is 4 mod 7 (1/1/1970 was Thursday) 319*7c478bd9Sstevel@tonic-gate */ 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate xtime.tm_wday = (day+7340036)%7; 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate /* 324*7c478bd9Sstevel@tonic-gate * year number 325*7c478bd9Sstevel@tonic-gate */ 326*7c478bd9Sstevel@tonic-gate if (day >= 0) 327*7c478bd9Sstevel@tonic-gate for (d1 = 70; day >= dysize(YEAR_ZERO + d1); d1++) 328*7c478bd9Sstevel@tonic-gate day -= dysize(YEAR_ZERO + d1); 329*7c478bd9Sstevel@tonic-gate else 330*7c478bd9Sstevel@tonic-gate for (d1 = 70; day < 0; d1--) 331*7c478bd9Sstevel@tonic-gate day += dysize(YEAR_ZERO + d1 - 1); 332*7c478bd9Sstevel@tonic-gate xtime.tm_year = (short)d1; 333*7c478bd9Sstevel@tonic-gate xtime.tm_yday = d0 = day; 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate /* 336*7c478bd9Sstevel@tonic-gate * generate month 337*7c478bd9Sstevel@tonic-gate */ 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate if (dysize(YEAR_ZERO + d1) == 366) 340*7c478bd9Sstevel@tonic-gate dmsize[1] = 29; 341*7c478bd9Sstevel@tonic-gate for (d1 = 0; d0 >= dmsize[d1]; d1++) 342*7c478bd9Sstevel@tonic-gate d0 -= dmsize[d1]; 343*7c478bd9Sstevel@tonic-gate dmsize[1] = 28; 344*7c478bd9Sstevel@tonic-gate *tp++ = d0+1; 345*7c478bd9Sstevel@tonic-gate *tp++ = (short)d1; 346*7c478bd9Sstevel@tonic-gate xtime.tm_isdst = 0; 347*7c478bd9Sstevel@tonic-gate return (&xtime); 348*7c478bd9Sstevel@tonic-gate } 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate /* 351*7c478bd9Sstevel@tonic-gate * convert year, month, day, hour, minute, sec to (int)time. 352*7c478bd9Sstevel@tonic-gate */ 353*7c478bd9Sstevel@tonic-gate static time_t 354*7c478bd9Sstevel@tonic-gate ctime(struct tm *tp) 355*7c478bd9Sstevel@tonic-gate { 356*7c478bd9Sstevel@tonic-gate int i; 357*7c478bd9Sstevel@tonic-gate time_t ct; 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate if (tp->tm_mon < 0 || tp->tm_mon > 11 || 360*7c478bd9Sstevel@tonic-gate tp->tm_mday < 1 || tp->tm_mday > 31 || 361*7c478bd9Sstevel@tonic-gate tp->tm_hour < 0 || tp->tm_hour > 23 || 362*7c478bd9Sstevel@tonic-gate tp->tm_min < 0 || tp->tm_min > 59 || 363*7c478bd9Sstevel@tonic-gate tp->tm_sec < 0 || tp->tm_sec > 59) { 364*7c478bd9Sstevel@tonic-gate return (0); 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate ct = 0; 367*7c478bd9Sstevel@tonic-gate for (i = /* 19 */ 70; i < tp->tm_year; i++) 368*7c478bd9Sstevel@tonic-gate ct += dysize(YEAR_ZERO + i); 369*7c478bd9Sstevel@tonic-gate /* Leap year */ 370*7c478bd9Sstevel@tonic-gate if (dysize(YEAR_ZERO + tp->tm_year) == 366 && tp->tm_mon >= 2) 371*7c478bd9Sstevel@tonic-gate ct++; 372*7c478bd9Sstevel@tonic-gate i = tp->tm_mon + 1; 373*7c478bd9Sstevel@tonic-gate while (--i) 374*7c478bd9Sstevel@tonic-gate ct += dmsize[i-1]; 375*7c478bd9Sstevel@tonic-gate ct += tp->tm_mday-1; 376*7c478bd9Sstevel@tonic-gate ct = 24*ct + tp->tm_hour; 377*7c478bd9Sstevel@tonic-gate ct = 60*ct + tp->tm_min; 378*7c478bd9Sstevel@tonic-gate ct = 60*ct + tp->tm_sec; 379*7c478bd9Sstevel@tonic-gate /* convert to GMT assuming local time */ 380*7c478bd9Sstevel@tonic-gate ct += (int)pc_tz.secondswest; 381*7c478bd9Sstevel@tonic-gate /* now fix up local daylight time */ 382*7c478bd9Sstevel@tonic-gate if (localtime(&ct)->tm_isdst) 383*7c478bd9Sstevel@tonic-gate ct -= 60*60; 384*7c478bd9Sstevel@tonic-gate return (ct); 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate /* 388*7c478bd9Sstevel@tonic-gate * Determine whether a character is valid for a pc 8.3 file system file name. 389*7c478bd9Sstevel@tonic-gate * The Windows 95 Resource Kit claims that these are valid: 390*7c478bd9Sstevel@tonic-gate * uppercase letters and numbers 391*7c478bd9Sstevel@tonic-gate * blank 392*7c478bd9Sstevel@tonic-gate * ASCII characters greater than 127 393*7c478bd9Sstevel@tonic-gate * $%'-_@~`!()^#& 394*7c478bd9Sstevel@tonic-gate * Long file names can also have 395*7c478bd9Sstevel@tonic-gate * lowercase letters 396*7c478bd9Sstevel@tonic-gate * +,;=[] 397*7c478bd9Sstevel@tonic-gate */ 398*7c478bd9Sstevel@tonic-gate int 399*7c478bd9Sstevel@tonic-gate pc_validchar(char c) 400*7c478bd9Sstevel@tonic-gate { 401*7c478bd9Sstevel@tonic-gate char *cp; 402*7c478bd9Sstevel@tonic-gate int n; 403*7c478bd9Sstevel@tonic-gate static char valtab[] = { 404*7c478bd9Sstevel@tonic-gate "$#&@!%()-{}<>`_^~|' " 405*7c478bd9Sstevel@tonic-gate }; 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate /* 408*7c478bd9Sstevel@tonic-gate * Should be "$#&@!%()-{}`_^~' " ?? 409*7c478bd9Sstevel@tonic-gate * From experiment in DOSWindows, *+=|\[];:",<>.?/ are illegal. 410*7c478bd9Sstevel@tonic-gate * See IBM DOS4.0 Tech Ref. B-57. 411*7c478bd9Sstevel@tonic-gate */ 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate if (c >= 'A' && c <= 'Z') 414*7c478bd9Sstevel@tonic-gate return (1); 415*7c478bd9Sstevel@tonic-gate if (c >= '0' && c <= '9') 416*7c478bd9Sstevel@tonic-gate return (1); 417*7c478bd9Sstevel@tonic-gate cp = valtab; 418*7c478bd9Sstevel@tonic-gate n = sizeof (valtab); 419*7c478bd9Sstevel@tonic-gate while (n--) { 420*7c478bd9Sstevel@tonic-gate if (c == *cp++) 421*7c478bd9Sstevel@tonic-gate return (1); 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate return (0); 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate /* 427*7c478bd9Sstevel@tonic-gate * Determine whether a character is valid for a pc 8.3 file system file name. 428*7c478bd9Sstevel@tonic-gate * The Windows 95 Resource Kit claims that these are valid: 429*7c478bd9Sstevel@tonic-gate * uppercase letters and numbers 430*7c478bd9Sstevel@tonic-gate * blank 431*7c478bd9Sstevel@tonic-gate * ASCII characters greater than 127 432*7c478bd9Sstevel@tonic-gate * $%'-_@~`!()^#& 433*7c478bd9Sstevel@tonic-gate * Long file names can also have 434*7c478bd9Sstevel@tonic-gate * lowercase letters 435*7c478bd9Sstevel@tonic-gate * +,;=[]. 436*7c478bd9Sstevel@tonic-gate */ 437*7c478bd9Sstevel@tonic-gate int 438*7c478bd9Sstevel@tonic-gate pc_valid_lfn_char(char c) 439*7c478bd9Sstevel@tonic-gate { 440*7c478bd9Sstevel@tonic-gate char *cp; 441*7c478bd9Sstevel@tonic-gate int n; 442*7c478bd9Sstevel@tonic-gate static char valtab[] = { 443*7c478bd9Sstevel@tonic-gate "+,;=[].$#&@!%()-{}<>`_^~|' " 444*7c478bd9Sstevel@tonic-gate }; 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate if (c >= 'a' && c <= 'z') 447*7c478bd9Sstevel@tonic-gate return (1); 448*7c478bd9Sstevel@tonic-gate if (c >= 'A' && c <= 'Z') 449*7c478bd9Sstevel@tonic-gate return (1); 450*7c478bd9Sstevel@tonic-gate if (c >= '0' && c <= '9') 451*7c478bd9Sstevel@tonic-gate return (1); 452*7c478bd9Sstevel@tonic-gate cp = valtab; 453*7c478bd9Sstevel@tonic-gate n = sizeof (valtab); 454*7c478bd9Sstevel@tonic-gate while (n--) { 455*7c478bd9Sstevel@tonic-gate if (c == *cp++) 456*7c478bd9Sstevel@tonic-gate return (1); 457*7c478bd9Sstevel@tonic-gate } 458*7c478bd9Sstevel@tonic-gate return (0); 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate int 462*7c478bd9Sstevel@tonic-gate pc_valid_long_fn(char *namep) 463*7c478bd9Sstevel@tonic-gate { 464*7c478bd9Sstevel@tonic-gate char *tmp; 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate for (tmp = namep; *tmp != '\0'; tmp++) 467*7c478bd9Sstevel@tonic-gate if (!pc_valid_lfn_char(*tmp)) 468*7c478bd9Sstevel@tonic-gate return (0); 469*7c478bd9Sstevel@tonic-gate if ((tmp - namep) >= PCMAXNAMLEN) 470*7c478bd9Sstevel@tonic-gate return (0); 471*7c478bd9Sstevel@tonic-gate return (1); 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate int 475*7c478bd9Sstevel@tonic-gate pc_fname_ext_to_name(char *namep, char *fname, char *ext, int foldcase) 476*7c478bd9Sstevel@tonic-gate { 477*7c478bd9Sstevel@tonic-gate int i; 478*7c478bd9Sstevel@tonic-gate char *tp = namep; 479*7c478bd9Sstevel@tonic-gate char c; 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate i = PCFNAMESIZE; 482*7c478bd9Sstevel@tonic-gate while (i-- && ((c = *fname) != ' ')) { 483*7c478bd9Sstevel@tonic-gate if (!(c == '.' || pc_validchar(c))) { 484*7c478bd9Sstevel@tonic-gate return (-1); 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate if (foldcase) 487*7c478bd9Sstevel@tonic-gate *tp++ = tolower(c); 488*7c478bd9Sstevel@tonic-gate else 489*7c478bd9Sstevel@tonic-gate *tp++ = c; 490*7c478bd9Sstevel@tonic-gate fname++; 491*7c478bd9Sstevel@tonic-gate } 492*7c478bd9Sstevel@tonic-gate if (*ext != ' ') { 493*7c478bd9Sstevel@tonic-gate *tp++ = '.'; 494*7c478bd9Sstevel@tonic-gate i = PCFEXTSIZE; 495*7c478bd9Sstevel@tonic-gate while (i-- && ((c = *ext) != ' ')) { 496*7c478bd9Sstevel@tonic-gate if (!pc_validchar(c)) { 497*7c478bd9Sstevel@tonic-gate return (-1); 498*7c478bd9Sstevel@tonic-gate } 499*7c478bd9Sstevel@tonic-gate if (foldcase) 500*7c478bd9Sstevel@tonic-gate *tp++ = tolower(c); 501*7c478bd9Sstevel@tonic-gate else 502*7c478bd9Sstevel@tonic-gate *tp++ = c; 503*7c478bd9Sstevel@tonic-gate ext++; 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate *tp = '\0'; 507*7c478bd9Sstevel@tonic-gate return (0); 508*7c478bd9Sstevel@tonic-gate } 509