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