xref: /illumos-gate/usr/src/uts/common/fs/hsfs/hsfs_subr.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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  * Miscellaneous support subroutines for High Sierra filesystem
24*7c478bd9Sstevel@tonic-gate  *
25*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1990,2000,2001 by Sun Microsystems, Inc.
26*7c478bd9Sstevel@tonic-gate  * All rights reserved.
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 <sys/types.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/buf.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/conf.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/user.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/proc.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/uio.h>
46*7c478bd9Sstevel@tonic-gate #include <vm/hat.h>
47*7c478bd9Sstevel@tonic-gate #include <vm/as.h>
48*7c478bd9Sstevel@tonic-gate #include <vm/seg.h>
49*7c478bd9Sstevel@tonic-gate #include <vm/page.h>
50*7c478bd9Sstevel@tonic-gate #include <vm/pvn.h>
51*7c478bd9Sstevel@tonic-gate #include <vm/seg_map.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/swap.h>
53*7c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h>
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate #include <sys/fs/hsfs_spec.h>
56*7c478bd9Sstevel@tonic-gate #include <sys/fs/hsfs_node.h>
57*7c478bd9Sstevel@tonic-gate #include <sys/fs/hsfs_impl.h>
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate #define	THE_EPOCH	1970
60*7c478bd9Sstevel@tonic-gate #define	END_OF_TIME	2099
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate #ifdef __STDC__
63*7c478bd9Sstevel@tonic-gate static time_t hs_date_to_gmtime(int year, int mon, int day, int gmtoff);
64*7c478bd9Sstevel@tonic-gate #else
65*7c478bd9Sstevel@tonic-gate static time_t hs_date_to_gmtime();
66*7c478bd9Sstevel@tonic-gate #endif
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate /*
69*7c478bd9Sstevel@tonic-gate  * Table used in logging non-fatal errors which should be recorded
70*7c478bd9Sstevel@tonic-gate  * once per mount.  Indexed by HSFS_ERR values (defined in hsfs_node.h).
71*7c478bd9Sstevel@tonic-gate  */
72*7c478bd9Sstevel@tonic-gate struct hsfs_error {
73*7c478bd9Sstevel@tonic-gate 	char	*hdr_text;	/* msg prefix: general error type */
74*7c478bd9Sstevel@tonic-gate 				/* must contain %s for mnt pt */
75*7c478bd9Sstevel@tonic-gate 	char 	*err_text;	/* specific error message */
76*7c478bd9Sstevel@tonic-gate 	uchar_t	multiple;	/* > 1 such error per fs possible? */
77*7c478bd9Sstevel@tonic-gate 	uchar_t	n_printf_args;	/* if err_text printf-like, # addtl args */
78*7c478bd9Sstevel@tonic-gate } hsfs_error[] = {
79*7c478bd9Sstevel@tonic-gate 	/* HSFS_ERR_TRAILING_JUNK */
80*7c478bd9Sstevel@tonic-gate 	"hsfs: Warning: the file system mounted on %s\n"
81*7c478bd9Sstevel@tonic-gate 		"does not conform to the ISO-9660 specification:",
82*7c478bd9Sstevel@tonic-gate 	" trailing blanks or null characters in file or directory name.\n",
83*7c478bd9Sstevel@tonic-gate 	1, 0,
84*7c478bd9Sstevel@tonic-gate 	/* HSFS_ERR_LOWER_CASE_NM */
85*7c478bd9Sstevel@tonic-gate 	"hsfs: Warning: the file system mounted on %s\n"
86*7c478bd9Sstevel@tonic-gate 		"does not conform to the ISO-9660 specification: ",
87*7c478bd9Sstevel@tonic-gate 	" lower case characters in file or directory name.\n",
88*7c478bd9Sstevel@tonic-gate 	1, 0,
89*7c478bd9Sstevel@tonic-gate 	/* HSFS_ERR_BAD_ROOT_DIR */
90*7c478bd9Sstevel@tonic-gate 	"hsfs: Warning: the file system mounted on %s\n"
91*7c478bd9Sstevel@tonic-gate 		"does not conform to the ISO-9660 specification:",
92*7c478bd9Sstevel@tonic-gate 	" invalid root directory.\n",
93*7c478bd9Sstevel@tonic-gate 	0,  0,
94*7c478bd9Sstevel@tonic-gate 	/* HSFS_ERR_UNSUP_TYPE */
95*7c478bd9Sstevel@tonic-gate 	"hsfs: Warning: the file system mounted on %s\n"
96*7c478bd9Sstevel@tonic-gate 		"contains a file or directory with an unsupported type:",
97*7c478bd9Sstevel@tonic-gate 	" 0x%x.\n",
98*7c478bd9Sstevel@tonic-gate 	1, 1,
99*7c478bd9Sstevel@tonic-gate 	/* HSFS_ERR_BAD_FILE_LEN */
100*7c478bd9Sstevel@tonic-gate 	"hsfs: Warning: file system mounted on %s \n"
101*7c478bd9Sstevel@tonic-gate 		"does not conform to the ISO-9660 specification:",
102*7c478bd9Sstevel@tonic-gate 	"file len greater than max allowed\n",
103*7c478bd9Sstevel@tonic-gate 	1, 0,
104*7c478bd9Sstevel@tonic-gate };
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate /*
109*7c478bd9Sstevel@tonic-gate  * hs_parse_dirdate
110*7c478bd9Sstevel@tonic-gate  *
111*7c478bd9Sstevel@tonic-gate  * Parse the short 'directory-format' date into a Unix timeval.
112*7c478bd9Sstevel@tonic-gate  * This is the date format used in Directory Entries.
113*7c478bd9Sstevel@tonic-gate  *
114*7c478bd9Sstevel@tonic-gate  * If the date is not representable, make something up.
115*7c478bd9Sstevel@tonic-gate  */
116*7c478bd9Sstevel@tonic-gate void
117*7c478bd9Sstevel@tonic-gate hs_parse_dirdate(dp, tvp)
118*7c478bd9Sstevel@tonic-gate 	uchar_t *dp;
119*7c478bd9Sstevel@tonic-gate 	struct timeval *tvp;
120*7c478bd9Sstevel@tonic-gate {
121*7c478bd9Sstevel@tonic-gate 	int year, month, day, hour, minute, sec, gmtoff;
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate 	year = HDE_DATE_YEAR(dp);
124*7c478bd9Sstevel@tonic-gate 	month = HDE_DATE_MONTH(dp);
125*7c478bd9Sstevel@tonic-gate 	day = HDE_DATE_DAY(dp);
126*7c478bd9Sstevel@tonic-gate 	hour = HDE_DATE_HOUR(dp);
127*7c478bd9Sstevel@tonic-gate 	minute = HDE_DATE_MIN(dp);
128*7c478bd9Sstevel@tonic-gate 	sec = HDE_DATE_SEC(dp);
129*7c478bd9Sstevel@tonic-gate 	gmtoff = HDE_DATE_GMTOFF(dp);
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate 	tvp->tv_usec = 0;
132*7c478bd9Sstevel@tonic-gate 	if (year < THE_EPOCH) {
133*7c478bd9Sstevel@tonic-gate 		tvp->tv_sec = 0;
134*7c478bd9Sstevel@tonic-gate 	} else {
135*7c478bd9Sstevel@tonic-gate 		tvp->tv_sec = hs_date_to_gmtime(year, month, day, gmtoff);
136*7c478bd9Sstevel@tonic-gate 		if (tvp->tv_sec != -1) {
137*7c478bd9Sstevel@tonic-gate 			tvp->tv_sec += ((hour * 60) + minute) * 60 + sec;
138*7c478bd9Sstevel@tonic-gate 		}
139*7c478bd9Sstevel@tonic-gate 	}
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 	return;
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate }
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate /*
146*7c478bd9Sstevel@tonic-gate  * hs_parse_longdate
147*7c478bd9Sstevel@tonic-gate  *
148*7c478bd9Sstevel@tonic-gate  * Parse the long 'user-oriented' date into a Unix timeval.
149*7c478bd9Sstevel@tonic-gate  * This is the date format used in the Volume Descriptor.
150*7c478bd9Sstevel@tonic-gate  *
151*7c478bd9Sstevel@tonic-gate  * If the date is not representable, make something up.
152*7c478bd9Sstevel@tonic-gate  */
153*7c478bd9Sstevel@tonic-gate void
154*7c478bd9Sstevel@tonic-gate hs_parse_longdate(dp, tvp)
155*7c478bd9Sstevel@tonic-gate 	uchar_t *dp;
156*7c478bd9Sstevel@tonic-gate 	struct timeval *tvp;
157*7c478bd9Sstevel@tonic-gate {
158*7c478bd9Sstevel@tonic-gate 	int year, month, day, hour, minute, sec, gmtoff;
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 	year = HSV_DATE_YEAR(dp);
161*7c478bd9Sstevel@tonic-gate 	month = HSV_DATE_MONTH(dp);
162*7c478bd9Sstevel@tonic-gate 	day = HSV_DATE_DAY(dp);
163*7c478bd9Sstevel@tonic-gate 	hour = HSV_DATE_HOUR(dp);
164*7c478bd9Sstevel@tonic-gate 	minute = HSV_DATE_MIN(dp);
165*7c478bd9Sstevel@tonic-gate 	sec = HSV_DATE_SEC(dp);
166*7c478bd9Sstevel@tonic-gate 	gmtoff = HSV_DATE_GMTOFF(dp);
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate 	tvp->tv_usec = 0;
169*7c478bd9Sstevel@tonic-gate 	if (year < THE_EPOCH) {
170*7c478bd9Sstevel@tonic-gate 		tvp->tv_sec = 0;
171*7c478bd9Sstevel@tonic-gate 	} else {
172*7c478bd9Sstevel@tonic-gate 		tvp->tv_sec = hs_date_to_gmtime(year, month, day, gmtoff);
173*7c478bd9Sstevel@tonic-gate 		if (tvp->tv_sec != -1) {
174*7c478bd9Sstevel@tonic-gate 			tvp->tv_sec += ((hour * 60) + minute) * 60 + sec;
175*7c478bd9Sstevel@tonic-gate 			tvp->tv_usec = HSV_DATE_HSEC(dp) * 10000;
176*7c478bd9Sstevel@tonic-gate 		}
177*7c478bd9Sstevel@tonic-gate 	}
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate }
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate /* cumulative number of seconds per month,  non-leap and leap-year versions */
182*7c478bd9Sstevel@tonic-gate static time_t cum_sec[] = {
183*7c478bd9Sstevel@tonic-gate 	0x0, 0x28de80, 0x4dc880, 0x76a700, 0x9e3400, 0xc71280,
184*7c478bd9Sstevel@tonic-gate 	0xee9f80, 0x1177e00, 0x1405c80, 0x167e980, 0x190c800, 0x1b85500
185*7c478bd9Sstevel@tonic-gate };
186*7c478bd9Sstevel@tonic-gate static time_t cum_sec_leap[] = {
187*7c478bd9Sstevel@tonic-gate 	0x0, 0x28de80, 0x4f1a00, 0x77f880, 0x9f8580, 0xc86400,
188*7c478bd9Sstevel@tonic-gate 	0xeff100, 0x118cf80, 0x141ae00, 0x1693b00, 0x1921980, 0x1b9a680
189*7c478bd9Sstevel@tonic-gate };
190*7c478bd9Sstevel@tonic-gate #define	SEC_PER_DAY	0x15180
191*7c478bd9Sstevel@tonic-gate #define	SEC_PER_YEAR	0x1e13380
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate /*
194*7c478bd9Sstevel@tonic-gate  * hs_date_to_gmtime
195*7c478bd9Sstevel@tonic-gate  *
196*7c478bd9Sstevel@tonic-gate  * Convert year(1970-2099)/month(1-12)/day(1-31) to seconds-since-1970/1/1.
197*7c478bd9Sstevel@tonic-gate  *
198*7c478bd9Sstevel@tonic-gate  * Returns -1 if the date is out of range.
199*7c478bd9Sstevel@tonic-gate  */
200*7c478bd9Sstevel@tonic-gate static time_t
201*7c478bd9Sstevel@tonic-gate hs_date_to_gmtime(year, mon, day, gmtoff)
202*7c478bd9Sstevel@tonic-gate 	int year;
203*7c478bd9Sstevel@tonic-gate 	int mon;
204*7c478bd9Sstevel@tonic-gate 	int day;
205*7c478bd9Sstevel@tonic-gate 	int gmtoff;
206*7c478bd9Sstevel@tonic-gate {
207*7c478bd9Sstevel@tonic-gate 	time_t sum;
208*7c478bd9Sstevel@tonic-gate 	time_t *cp;
209*7c478bd9Sstevel@tonic-gate 	int y;
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate 	if ((year < THE_EPOCH) || (year > END_OF_TIME) ||
212*7c478bd9Sstevel@tonic-gate 	    (mon < 1) || (mon > 12) ||
213*7c478bd9Sstevel@tonic-gate 	    (day < 1) || (day > 31))
214*7c478bd9Sstevel@tonic-gate 		return (-1);
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate 	/*
217*7c478bd9Sstevel@tonic-gate 	 * Figure seconds until this year and correct for leap years.
218*7c478bd9Sstevel@tonic-gate 	 * Note: 2000 is a leap year but not 2100.
219*7c478bd9Sstevel@tonic-gate 	 */
220*7c478bd9Sstevel@tonic-gate 	y = year - THE_EPOCH;
221*7c478bd9Sstevel@tonic-gate 	sum = y * SEC_PER_YEAR;
222*7c478bd9Sstevel@tonic-gate 	sum += ((y + 1) / 4) * SEC_PER_DAY;
223*7c478bd9Sstevel@tonic-gate 	/*
224*7c478bd9Sstevel@tonic-gate 	 * Point to the correct table for this year and
225*7c478bd9Sstevel@tonic-gate 	 * add in seconds until this month.
226*7c478bd9Sstevel@tonic-gate 	 */
227*7c478bd9Sstevel@tonic-gate 	cp = ((y + 2) % 4) ? cum_sec : cum_sec_leap;
228*7c478bd9Sstevel@tonic-gate 	sum += cp[mon - 1];
229*7c478bd9Sstevel@tonic-gate 	/*
230*7c478bd9Sstevel@tonic-gate 	 * Add in seconds until 0:00 of this day.
231*7c478bd9Sstevel@tonic-gate 	 * (days-per-month validation is not done here)
232*7c478bd9Sstevel@tonic-gate 	 */
233*7c478bd9Sstevel@tonic-gate 	sum += (day - 1) * SEC_PER_DAY;
234*7c478bd9Sstevel@tonic-gate 	sum -= (gmtoff * 15 * 60);
235*7c478bd9Sstevel@tonic-gate 	return (sum);
236*7c478bd9Sstevel@tonic-gate }
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate /*
239*7c478bd9Sstevel@tonic-gate  * Indicate whether the directory is valid.
240*7c478bd9Sstevel@tonic-gate  */
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate int
243*7c478bd9Sstevel@tonic-gate hsfs_valid_dir(hd)
244*7c478bd9Sstevel@tonic-gate 	struct hs_direntry *hd;
245*7c478bd9Sstevel@tonic-gate {
246*7c478bd9Sstevel@tonic-gate 	/*
247*7c478bd9Sstevel@tonic-gate 	 * check to see if this directory is not marked as a directory.
248*7c478bd9Sstevel@tonic-gate 	 * check to see if data length is zero.
249*7c478bd9Sstevel@tonic-gate 	 */
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate 	if (hd->ext_size == 0)
252*7c478bd9Sstevel@tonic-gate 		return (0);
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate 	if (hd->type != VDIR)
255*7c478bd9Sstevel@tonic-gate 		return (0);
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 	return (1);
258*7c478bd9Sstevel@tonic-gate }
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate 
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate /*
263*7c478bd9Sstevel@tonic-gate  * If we haven't complained about this error type yet, do.
264*7c478bd9Sstevel@tonic-gate  */
265*7c478bd9Sstevel@tonic-gate void
266*7c478bd9Sstevel@tonic-gate hs_log_bogus_disk_warning(fsp, errtype, data)
267*7c478bd9Sstevel@tonic-gate 	struct hsfs	*fsp;
268*7c478bd9Sstevel@tonic-gate 	int 		errtype;
269*7c478bd9Sstevel@tonic-gate 	uint_t		data;
270*7c478bd9Sstevel@tonic-gate {
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	if (fsp->hsfs_err_flags & (1 << errtype))
273*7c478bd9Sstevel@tonic-gate 		return;		/* already complained */
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 	cmn_err(CE_NOTE, hsfs_error[errtype].hdr_text,
276*7c478bd9Sstevel@tonic-gate 		fsp->hsfs_fsmnt);
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate 	switch (hsfs_error[errtype].n_printf_args) {
279*7c478bd9Sstevel@tonic-gate 	case 0:
280*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, hsfs_error[errtype].err_text);
281*7c478bd9Sstevel@tonic-gate 		break;
282*7c478bd9Sstevel@tonic-gate 	case 1:
283*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, hsfs_error[errtype].err_text, data);
284*7c478bd9Sstevel@tonic-gate 		break;
285*7c478bd9Sstevel@tonic-gate 	default:
286*7c478bd9Sstevel@tonic-gate 		/* don't currently handle more than 1 arg */
287*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "unknown problem; internal error.\n");
288*7c478bd9Sstevel@tonic-gate 	}
289*7c478bd9Sstevel@tonic-gate 	cmn_err(CE_CONT,
290*7c478bd9Sstevel@tonic-gate "Due to this error, the file system may not be correctly interpreted.\n");
291*7c478bd9Sstevel@tonic-gate 	if (hsfs_error[errtype].multiple)
292*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT,
293*7c478bd9Sstevel@tonic-gate "Other such errors in this file system will be silently ignored.\n\n");
294*7c478bd9Sstevel@tonic-gate 	else
295*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "\n");
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate 	fsp->hsfs_err_flags |= (1 << errtype);
298*7c478bd9Sstevel@tonic-gate }
299