xref: /onnv-gate/usr/src/uts/common/fs/pcfs/pc_subr.c (revision 0:68f95e015346)
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