xref: /titanic_44/usr/src/cmd/fs.d/cachefs/fsck/fsck.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  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28*7c478bd9Sstevel@tonic-gate /*	    All Rights Reserved */
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate /*
31*7c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley 4.3 BSD
32*7c478bd9Sstevel@tonic-gate  * under license from the Regents of the University of California.
33*7c478bd9Sstevel@tonic-gate  */
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate /*
38*7c478bd9Sstevel@tonic-gate  *
39*7c478bd9Sstevel@tonic-gate  *			fsck.c
40*7c478bd9Sstevel@tonic-gate  *
41*7c478bd9Sstevel@tonic-gate  * Cachefs fsck program.
42*7c478bd9Sstevel@tonic-gate  */
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate #include <locale.h>
45*7c478bd9Sstevel@tonic-gate #include <stdio.h>
46*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
47*7c478bd9Sstevel@tonic-gate #include <string.h>
48*7c478bd9Sstevel@tonic-gate #include <assert.h>
49*7c478bd9Sstevel@tonic-gate #include <stdarg.h>
50*7c478bd9Sstevel@tonic-gate #include <unistd.h>
51*7c478bd9Sstevel@tonic-gate #include <limits.h>
52*7c478bd9Sstevel@tonic-gate #include <errno.h>
53*7c478bd9Sstevel@tonic-gate #include <wait.h>
54*7c478bd9Sstevel@tonic-gate #include <ctype.h>
55*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
56*7c478bd9Sstevel@tonic-gate #include <ftw.h>
57*7c478bd9Sstevel@tonic-gate #include <dirent.h>
58*7c478bd9Sstevel@tonic-gate #include <search.h>
59*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
60*7c478bd9Sstevel@tonic-gate #include <sys/uio.h>
61*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
62*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
63*7c478bd9Sstevel@tonic-gate #include <sys/fcntl.h>
64*7c478bd9Sstevel@tonic-gate #include <sys/mount.h>
65*7c478bd9Sstevel@tonic-gate #include <sys/mntent.h>
66*7c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
67*7c478bd9Sstevel@tonic-gate #include <sys/mman.h>
68*7c478bd9Sstevel@tonic-gate #include <sys/fs/cachefs_fs.h>
69*7c478bd9Sstevel@tonic-gate #include <syslog.h>
70*7c478bd9Sstevel@tonic-gate #include "../common/subr.h"
71*7c478bd9Sstevel@tonic-gate #include "res.h"
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate char *cfs_opts[] = {
74*7c478bd9Sstevel@tonic-gate #define		CFSOPT_PREEN		0
75*7c478bd9Sstevel@tonic-gate 		"preen",
76*7c478bd9Sstevel@tonic-gate #define		CFSOPT_NOCLEAN		1
77*7c478bd9Sstevel@tonic-gate 		"noclean",
78*7c478bd9Sstevel@tonic-gate #define		CFSOPT_VERBOSE		2
79*7c478bd9Sstevel@tonic-gate 		"verbose",
80*7c478bd9Sstevel@tonic-gate #define		CFSOPT_NONOCLEAN	3
81*7c478bd9Sstevel@tonic-gate 		"nonoclean",
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate 		NULL
84*7c478bd9Sstevel@tonic-gate };
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate extern int dlog_ck(char *dir_path, ino64_t *maxlocalfilenop);
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate /* forward references */
89*7c478bd9Sstevel@tonic-gate void usage(char *msgp);
90*7c478bd9Sstevel@tonic-gate void pr_err(char *fmt, ...);
91*7c478bd9Sstevel@tonic-gate int cfs_check(char *cachedirp, int noclean, int mflag, int verbose,
92*7c478bd9Sstevel@tonic-gate     int nonoclean);
93*7c478bd9Sstevel@tonic-gate int cache_label_file(char *cachedirp, struct cache_label *clabelp);
94*7c478bd9Sstevel@tonic-gate int cache_permissions(char *cachedirp);
95*7c478bd9Sstevel@tonic-gate int cache_check_dir(char *cachedirp, char *namep);
96*7c478bd9Sstevel@tonic-gate int process_fsdir(char *cachedirp, char *namep, res *resp, int verbose);
97*7c478bd9Sstevel@tonic-gate int process_fsinfo(char *namep, ino64_t maxlocalfileno,
98*7c478bd9Sstevel@tonic-gate     cachefs_fsinfo_t *fsinfop, int verbose);
99*7c478bd9Sstevel@tonic-gate int process_fsgroup(char *dirp, char *namep, res *resp, ino64_t base,
100*7c478bd9Sstevel@tonic-gate     int fgsize, ino64_t fsid, int local, int verbose);
101*7c478bd9Sstevel@tonic-gate int tree_remove(const char *namep, const struct stat64 *statp, int type,
102*7c478bd9Sstevel@tonic-gate     struct FTW *ftwp);
103*7c478bd9Sstevel@tonic-gate int cache_upgrade(char *cachedirp, int lockid);
104*7c478bd9Sstevel@tonic-gate int file_remove(const char *namep, const struct stat64 *statp, int verbose);
105*7c478bd9Sstevel@tonic-gate void cache_backmnt_cleanup(char *cachedirp, char *backmnt_namep);
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate #define	FLAGS_FTW (FTW_PHYS | FTW_MOUNT | FTW_DEPTH)
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate static int S_verbose = 0;
110*7c478bd9Sstevel@tonic-gate static char S_lostfound[MAXPATHLEN];
111*7c478bd9Sstevel@tonic-gate static int S_move_lostfound = 0;
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate /*
114*7c478bd9Sstevel@tonic-gate  *
115*7c478bd9Sstevel@tonic-gate  *			main
116*7c478bd9Sstevel@tonic-gate  *
117*7c478bd9Sstevel@tonic-gate  * Description:
118*7c478bd9Sstevel@tonic-gate  *	Main routine for the cachefs fsck program.
119*7c478bd9Sstevel@tonic-gate  * Arguments:
120*7c478bd9Sstevel@tonic-gate  *	argc	number of command line arguments
121*7c478bd9Sstevel@tonic-gate  *	argv	list of command line arguments
122*7c478bd9Sstevel@tonic-gate  * Returns:
123*7c478bd9Sstevel@tonic-gate  *	Returns:
124*7c478bd9Sstevel@tonic-gate  *		 0	file system is okay and does not need checking
125*7c478bd9Sstevel@tonic-gate  *		 1	problem unrelated to the file system
126*7c478bd9Sstevel@tonic-gate  *		32	file system is unmounted and needs checking  (fsck
127*7c478bd9Sstevel@tonic-gate  *			-m only)
128*7c478bd9Sstevel@tonic-gate  *		33	file system is already mounted
129*7c478bd9Sstevel@tonic-gate  *		34	cannot stat device
130*7c478bd9Sstevel@tonic-gate  *		36	uncorrectable errors detected - terminate normally
131*7c478bd9Sstevel@tonic-gate  *		37	a signal was caught during processing
132*7c478bd9Sstevel@tonic-gate  *		39	uncorrectable errors detected - terminate  immediately
133*7c478bd9Sstevel@tonic-gate  *		40	for root mounted fs, same as 0
134*7c478bd9Sstevel@tonic-gate  * Preconditions:
135*7c478bd9Sstevel@tonic-gate  */
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate int
main(int argc,char ** argv)138*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
139*7c478bd9Sstevel@tonic-gate {
140*7c478bd9Sstevel@tonic-gate 	int xx;
141*7c478bd9Sstevel@tonic-gate 	int c;
142*7c478bd9Sstevel@tonic-gate 	char *optionp;
143*7c478bd9Sstevel@tonic-gate 	char *valuep;
144*7c478bd9Sstevel@tonic-gate 	int mflag;
145*7c478bd9Sstevel@tonic-gate 	int noclean;
146*7c478bd9Sstevel@tonic-gate 	char *cachedirp;
147*7c478bd9Sstevel@tonic-gate 	int lockid;
148*7c478bd9Sstevel@tonic-gate 	int verbose;
149*7c478bd9Sstevel@tonic-gate 	int nonoclean;
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
152*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
153*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"
154*7c478bd9Sstevel@tonic-gate #endif
155*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 	/* verify root running command */
158*7c478bd9Sstevel@tonic-gate 	if (getuid() != 0) {
159*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, gettext(
160*7c478bd9Sstevel@tonic-gate 			"fsck -F cachefs: must be run by root\n"));
161*7c478bd9Sstevel@tonic-gate 		return (1);
162*7c478bd9Sstevel@tonic-gate 	}
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 	/* process command line options */
165*7c478bd9Sstevel@tonic-gate 	optionp = NULL;
166*7c478bd9Sstevel@tonic-gate 	mflag = 0;
167*7c478bd9Sstevel@tonic-gate 	noclean = 0;
168*7c478bd9Sstevel@tonic-gate 	verbose = 0;
169*7c478bd9Sstevel@tonic-gate 	nonoclean = 0;
170*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "mnNo:yY")) != EOF) {
171*7c478bd9Sstevel@tonic-gate 		switch (c) {
172*7c478bd9Sstevel@tonic-gate 		case 'm':	/* check but do not repair */
173*7c478bd9Sstevel@tonic-gate 			mflag = 1;
174*7c478bd9Sstevel@tonic-gate 			break;
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate 		case 'n':	/* answer no to questions */
177*7c478bd9Sstevel@tonic-gate 		case 'N':
178*7c478bd9Sstevel@tonic-gate 			/* ignored */
179*7c478bd9Sstevel@tonic-gate 			break;
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 		case 'o':
182*7c478bd9Sstevel@tonic-gate 			optionp = optarg;
183*7c478bd9Sstevel@tonic-gate 			while (*optionp) {
184*7c478bd9Sstevel@tonic-gate 				xx = getsubopt(&optionp, cfs_opts, &valuep);
185*7c478bd9Sstevel@tonic-gate 				switch (xx) {
186*7c478bd9Sstevel@tonic-gate 				case CFSOPT_PREEN:
187*7c478bd9Sstevel@tonic-gate 					/* preen is the default mode */
188*7c478bd9Sstevel@tonic-gate 					break;
189*7c478bd9Sstevel@tonic-gate 				case CFSOPT_NOCLEAN:
190*7c478bd9Sstevel@tonic-gate 					noclean = 1;
191*7c478bd9Sstevel@tonic-gate 					break;
192*7c478bd9Sstevel@tonic-gate 				case CFSOPT_VERBOSE:
193*7c478bd9Sstevel@tonic-gate 					verbose++;
194*7c478bd9Sstevel@tonic-gate 					S_verbose++;
195*7c478bd9Sstevel@tonic-gate 					break;
196*7c478bd9Sstevel@tonic-gate 				case CFSOPT_NONOCLEAN:
197*7c478bd9Sstevel@tonic-gate 					nonoclean = 1;
198*7c478bd9Sstevel@tonic-gate 					break;
199*7c478bd9Sstevel@tonic-gate 				default:
200*7c478bd9Sstevel@tonic-gate 				case -1:
201*7c478bd9Sstevel@tonic-gate 					pr_err(gettext("unknown option %s"),
202*7c478bd9Sstevel@tonic-gate 					    valuep);
203*7c478bd9Sstevel@tonic-gate 					return (1);
204*7c478bd9Sstevel@tonic-gate 				}
205*7c478bd9Sstevel@tonic-gate 			}
206*7c478bd9Sstevel@tonic-gate 			break;
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 		case 'y':	/* answer yes to questions */
209*7c478bd9Sstevel@tonic-gate 		case 'Y':
210*7c478bd9Sstevel@tonic-gate 			/* ignored, this is the default */
211*7c478bd9Sstevel@tonic-gate 			break;
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 		default:
214*7c478bd9Sstevel@tonic-gate 			usage("invalid option");
215*7c478bd9Sstevel@tonic-gate 			return (1);
216*7c478bd9Sstevel@tonic-gate 		}
217*7c478bd9Sstevel@tonic-gate 	}
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 	/* verify fsck device is specified */
220*7c478bd9Sstevel@tonic-gate 	if (argc - optind < 1) {
221*7c478bd9Sstevel@tonic-gate 		usage(gettext("must specify cache directory"));
222*7c478bd9Sstevel@tonic-gate 		return (1);
223*7c478bd9Sstevel@tonic-gate 	}
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	/* save cache directory */
226*7c478bd9Sstevel@tonic-gate 	cachedirp = argv[argc - 1];
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate 	/* ensure cache directory exists */
229*7c478bd9Sstevel@tonic-gate 	if (access(cachedirp, F_OK) != 0) {
230*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Cache directory %s does not exist."),
231*7c478bd9Sstevel@tonic-gate 		    cachedirp);
232*7c478bd9Sstevel@tonic-gate 		return (39);
233*7c478bd9Sstevel@tonic-gate 	}
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	/* lock the cache directory non-shared */
236*7c478bd9Sstevel@tonic-gate 	lockid = cachefs_dir_lock(cachedirp, 0);
237*7c478bd9Sstevel@tonic-gate 	if (lockid == -1) {
238*7c478bd9Sstevel@tonic-gate 		/* exit if could not get the lock */
239*7c478bd9Sstevel@tonic-gate 		return (1);
240*7c478bd9Sstevel@tonic-gate 	}
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 	/* is the cache directory in use */
243*7c478bd9Sstevel@tonic-gate 	if (cachefs_inuse(cachedirp)) {
244*7c478bd9Sstevel@tonic-gate 		if (noclean) {
245*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Cache directory %s is in use."),
246*7c478bd9Sstevel@tonic-gate 			    cachedirp);
247*7c478bd9Sstevel@tonic-gate 			xx = 33;
248*7c478bd9Sstevel@tonic-gate 		} else {
249*7c478bd9Sstevel@tonic-gate 			/* assume if in use that it is clean */
250*7c478bd9Sstevel@tonic-gate 			xx = 0;
251*7c478bd9Sstevel@tonic-gate 		}
252*7c478bd9Sstevel@tonic-gate 		cachefs_dir_unlock(lockid);
253*7c478bd9Sstevel@tonic-gate 		return (xx);
254*7c478bd9Sstevel@tonic-gate 	}
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate 	xx = cache_upgrade(cachedirp, lockid);
257*7c478bd9Sstevel@tonic-gate 	if (xx != 0) {
258*7c478bd9Sstevel@tonic-gate 		/* check the file system */
259*7c478bd9Sstevel@tonic-gate 		xx = cfs_check(cachedirp, noclean, mflag, verbose, nonoclean);
260*7c478bd9Sstevel@tonic-gate 	}
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate 	/* unlock the cache directory */
263*7c478bd9Sstevel@tonic-gate 	cachefs_dir_unlock(lockid);
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 	/* inform if files moved to lost+found */
266*7c478bd9Sstevel@tonic-gate 	if (S_move_lostfound) {
267*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Files recovered to %s"), S_lostfound);
268*7c478bd9Sstevel@tonic-gate 	}
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate 	/* return the status of the file system checking */
271*7c478bd9Sstevel@tonic-gate 	return (xx);
272*7c478bd9Sstevel@tonic-gate }
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate /*
275*7c478bd9Sstevel@tonic-gate  *
276*7c478bd9Sstevel@tonic-gate  *			usage
277*7c478bd9Sstevel@tonic-gate  *
278*7c478bd9Sstevel@tonic-gate  * Description:
279*7c478bd9Sstevel@tonic-gate  *	Prints a short usage message.
280*7c478bd9Sstevel@tonic-gate  * Arguments:
281*7c478bd9Sstevel@tonic-gate  *	msgp	message to include with the usage message
282*7c478bd9Sstevel@tonic-gate  * Returns:
283*7c478bd9Sstevel@tonic-gate  * Preconditions:
284*7c478bd9Sstevel@tonic-gate  */
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate void
usage(char * msgp)287*7c478bd9Sstevel@tonic-gate usage(char *msgp)
288*7c478bd9Sstevel@tonic-gate {
289*7c478bd9Sstevel@tonic-gate 	if (msgp) {
290*7c478bd9Sstevel@tonic-gate 		pr_err("%s", msgp);
291*7c478bd9Sstevel@tonic-gate 	}
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
294*7c478bd9Sstevel@tonic-gate 	    gettext("Usage: fsck -F cachefs [ -o specific_options ] [ -m ] "
295*7c478bd9Sstevel@tonic-gate 	    "cachedir\n"));
296*7c478bd9Sstevel@tonic-gate }
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate /*
299*7c478bd9Sstevel@tonic-gate  *
300*7c478bd9Sstevel@tonic-gate  *			pr_err
301*7c478bd9Sstevel@tonic-gate  *
302*7c478bd9Sstevel@tonic-gate  * Description:
303*7c478bd9Sstevel@tonic-gate  *	Prints an error message to stderr.
304*7c478bd9Sstevel@tonic-gate  * Arguments:
305*7c478bd9Sstevel@tonic-gate  *	fmt	printf style format
306*7c478bd9Sstevel@tonic-gate  *	...	arguments for fmt
307*7c478bd9Sstevel@tonic-gate  * Returns:
308*7c478bd9Sstevel@tonic-gate  * Preconditions:
309*7c478bd9Sstevel@tonic-gate  *	precond(fmt)
310*7c478bd9Sstevel@tonic-gate  */
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate void
pr_err(char * fmt,...)313*7c478bd9Sstevel@tonic-gate pr_err(char *fmt, ...)
314*7c478bd9Sstevel@tonic-gate {
315*7c478bd9Sstevel@tonic-gate 	va_list ap;
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
318*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("fsck -F cachefs: "));
319*7c478bd9Sstevel@tonic-gate 	(void) vfprintf(stderr, fmt, ap);
320*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\n");
321*7c478bd9Sstevel@tonic-gate 	va_end(ap);
322*7c478bd9Sstevel@tonic-gate }
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate /*
325*7c478bd9Sstevel@tonic-gate  *
326*7c478bd9Sstevel@tonic-gate  *			cache_upgrade
327*7c478bd9Sstevel@tonic-gate  *
328*7c478bd9Sstevel@tonic-gate  * Description:
329*7c478bd9Sstevel@tonic-gate  *
330*7c478bd9Sstevel@tonic-gate  *	See if the current cache is out of date.  If it is, do
331*7c478bd9Sstevel@tonic-gate  *	whatever magic is necessary to upgrade it.  All such magic
332*7c478bd9Sstevel@tonic-gate  *	should be encapsulated here!
333*7c478bd9Sstevel@tonic-gate  *
334*7c478bd9Sstevel@tonic-gate  * Arguments:
335*7c478bd9Sstevel@tonic-gate  *
336*7c478bd9Sstevel@tonic-gate  *	cachedirp	name of the cache directory to check
337*7c478bd9Sstevel@tonic-gate  *
338*7c478bd9Sstevel@tonic-gate  * Returns:
339*7c478bd9Sstevel@tonic-gate  *	Returns:
340*7c478bd9Sstevel@tonic-gate  *		 0	cache was upgraded and shouldn't be checked
341*7c478bd9Sstevel@tonic-gate  *		 1	problem unrelated to the file system
342*7c478bd9Sstevel@tonic-gate  *		36	uncorrectable errors detected - terminate normally
343*7c478bd9Sstevel@tonic-gate  *		39	uncorrectable errors detected - terminate  immediately
344*7c478bd9Sstevel@tonic-gate  *		50	cache was already up-to-date (maybe we should fsck it)
345*7c478bd9Sstevel@tonic-gate  *		51	cache was upgraded (but you should do fsck)
346*7c478bd9Sstevel@tonic-gate  * Preconditions:
347*7c478bd9Sstevel@tonic-gate  *	precond(cachedirp)
348*7c478bd9Sstevel@tonic-gate  */
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate int
cache_upgrade(char * cachedirp,int lockid)351*7c478bd9Sstevel@tonic-gate cache_upgrade(char *cachedirp, int lockid)
352*7c478bd9Sstevel@tonic-gate {
353*7c478bd9Sstevel@tonic-gate #ifdef CFSRLDEBUG
354*7c478bd9Sstevel@tonic-gate 	static int canupgrade[] = {1, 2, 3, 103, 104, 105, 106, 107,
355*7c478bd9Sstevel@tonic-gate 	    4, 5, 108, 6, 7, 8, 0};
356*7c478bd9Sstevel@tonic-gate #else /* CFSRLDEBUG */
357*7c478bd9Sstevel@tonic-gate 	static int canupgrade[] = {1, 2, 3, 103, 104, 105, 106, 107,
358*7c478bd9Sstevel@tonic-gate 	    4, 108, 5, 109, 110, 6, 111, 0};
359*7c478bd9Sstevel@tonic-gate #endif /* CFSRLDEBUG */
360*7c478bd9Sstevel@tonic-gate 	char labelpath[MAXPATHLEN];
361*7c478bd9Sstevel@tonic-gate 	struct cache_label clabel;
362*7c478bd9Sstevel@tonic-gate 	int i;
363*7c478bd9Sstevel@tonic-gate 
364*7c478bd9Sstevel@tonic-gate 	if (((int)strlen(cachedirp) + (int)strlen(CACHELABEL_NAME) + 2)
365*7c478bd9Sstevel@tonic-gate 	    >= MAXPATHLEN)
366*7c478bd9Sstevel@tonic-gate 		return (1);
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate 	(void) sprintf(labelpath, "%s/%s", cachedirp, CACHELABEL_NAME);
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate 	if (cachefs_label_file_get(labelpath, &clabel) != 0)
371*7c478bd9Sstevel@tonic-gate 		return (1);
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate 	/* nothing to do if we're current */
374*7c478bd9Sstevel@tonic-gate 	if (clabel.cl_cfsversion == CFSVERSION)
375*7c478bd9Sstevel@tonic-gate 		return (50);
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate 	/* see if it's an old version that we know how to upgrade */
378*7c478bd9Sstevel@tonic-gate 	for (i = 0; canupgrade[i] != 0; i++)
379*7c478bd9Sstevel@tonic-gate 		if (clabel.cl_cfsversion == canupgrade[i])
380*7c478bd9Sstevel@tonic-gate 			break;
381*7c478bd9Sstevel@tonic-gate 	if (canupgrade[i] == 0)
382*7c478bd9Sstevel@tonic-gate 		return (36);
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 	syslog(LOG_USER | LOG_INFO,
385*7c478bd9Sstevel@tonic-gate 	    gettext("fsck -F cachefs: Recreating cache %s"), cachedirp);
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate 	/* currently, to `upgrade' we delete the old cache */
388*7c478bd9Sstevel@tonic-gate 	if (cachefs_delete_all_cache(cachedirp) != 0)
389*7c478bd9Sstevel@tonic-gate 		return (36);
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate 	/* do any magic necessary to convert the old label to the new one */
392*7c478bd9Sstevel@tonic-gate 	clabel.cl_cfsversion = CFSVERSION;
393*7c478bd9Sstevel@tonic-gate 
394*7c478bd9Sstevel@tonic-gate 	/* create the new cache! */
395*7c478bd9Sstevel@tonic-gate 	if (cachefs_create_cache(cachedirp, NULL, &clabel) != 0)
396*7c478bd9Sstevel@tonic-gate 		return (36);
397*7c478bd9Sstevel@tonic-gate 
398*7c478bd9Sstevel@tonic-gate 	return (0);
399*7c478bd9Sstevel@tonic-gate }
400*7c478bd9Sstevel@tonic-gate 
401*7c478bd9Sstevel@tonic-gate /*
402*7c478bd9Sstevel@tonic-gate  *
403*7c478bd9Sstevel@tonic-gate  *			cfs_check
404*7c478bd9Sstevel@tonic-gate  *
405*7c478bd9Sstevel@tonic-gate  * Description:
406*7c478bd9Sstevel@tonic-gate  *	This routine performs the actual checking of the cache
407*7c478bd9Sstevel@tonic-gate  *	file system.
408*7c478bd9Sstevel@tonic-gate  *	The file system must be inactive when this routine is called.
409*7c478bd9Sstevel@tonic-gate  * Arguments:
410*7c478bd9Sstevel@tonic-gate  *	cachedirp	name of the cache directory to check
411*7c478bd9Sstevel@tonic-gate  *	noclean		1 means ignore clean flag
412*7c478bd9Sstevel@tonic-gate  *	mflag		1 means no fixes, only check if mountable
413*7c478bd9Sstevel@tonic-gate  *	verbose		indicate level of verbosity for diagnostics
414*7c478bd9Sstevel@tonic-gate  *	nonoclean	1 means honor clean flag; don't by default
415*7c478bd9Sstevel@tonic-gate  * Returns:
416*7c478bd9Sstevel@tonic-gate  *	Returns:
417*7c478bd9Sstevel@tonic-gate  *		 0	file system is okay and does not need checking
418*7c478bd9Sstevel@tonic-gate  *		 1	problem unrelated to the file system
419*7c478bd9Sstevel@tonic-gate  *		32	file system is unmounted and needs checking
420*7c478bd9Sstevel@tonic-gate  *		33	file system is already mounted
421*7c478bd9Sstevel@tonic-gate  *		34	cannot stat device
422*7c478bd9Sstevel@tonic-gate  *		36	uncorrectable errors detected - terminate normally
423*7c478bd9Sstevel@tonic-gate  *		37	a signal was caught during processing
424*7c478bd9Sstevel@tonic-gate  *		39	uncorrectable errors detected - terminate  immediately
425*7c478bd9Sstevel@tonic-gate  *		40	for root mounted fs, same as 0, XXX
426*7c478bd9Sstevel@tonic-gate  * Preconditions:
427*7c478bd9Sstevel@tonic-gate  *	precond(cachedirp)
428*7c478bd9Sstevel@tonic-gate  */
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate int
cfs_check(char * cachedirp,int noclean,int mflag,int verbose,int nonoclean)431*7c478bd9Sstevel@tonic-gate cfs_check(char *cachedirp, int noclean, int mflag, int verbose, int nonoclean)
432*7c478bd9Sstevel@tonic-gate {
433*7c478bd9Sstevel@tonic-gate 	DIR *dp;
434*7c478bd9Sstevel@tonic-gate 	struct dirent64 *dep;
435*7c478bd9Sstevel@tonic-gate 	char buf[MAXPATHLEN];
436*7c478bd9Sstevel@tonic-gate 	struct stat64 statinfo;
437*7c478bd9Sstevel@tonic-gate 	int xx;
438*7c478bd9Sstevel@tonic-gate 	char *namep;
439*7c478bd9Sstevel@tonic-gate 	res *resp;
440*7c478bd9Sstevel@tonic-gate 	struct cache_label clabel;
441*7c478bd9Sstevel@tonic-gate 
442*7c478bd9Sstevel@tonic-gate 	/* if checking the clean flag is sufficient */
443*7c478bd9Sstevel@tonic-gate 	if ((noclean == 0) && (nonoclean || mflag)) {
444*7c478bd9Sstevel@tonic-gate 		/* if the clean flag is set */
445*7c478bd9Sstevel@tonic-gate 		if (cachefs_clean_flag_test(cachedirp)) {
446*7c478bd9Sstevel@tonic-gate 			if (verbose) {
447*7c478bd9Sstevel@tonic-gate 				pr_err(gettext("Cache %s is clean"), cachedirp);
448*7c478bd9Sstevel@tonic-gate 			}
449*7c478bd9Sstevel@tonic-gate 			return (0);
450*7c478bd9Sstevel@tonic-gate 		}
451*7c478bd9Sstevel@tonic-gate 	}
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 	/* if mflag specified then go no farther */
454*7c478bd9Sstevel@tonic-gate 	if (mflag)
455*7c478bd9Sstevel@tonic-gate 		return (32);
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 	/* check the cache label file for correctness */
458*7c478bd9Sstevel@tonic-gate 	xx = cache_label_file(cachedirp, &clabel);
459*7c478bd9Sstevel@tonic-gate 	if (xx)
460*7c478bd9Sstevel@tonic-gate 		return (xx);
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate 	/* make sure the kernel lock file exists */
463*7c478bd9Sstevel@tonic-gate 	sprintf(buf, "%s/%s", cachedirp, CACHEFS_LOCK_FILE);
464*7c478bd9Sstevel@tonic-gate 	xx = open(buf, O_RDWR | O_CREAT, 0700);
465*7c478bd9Sstevel@tonic-gate 	if (xx == -1) {
466*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Cannot create lock file %s"), buf);
467*7c478bd9Sstevel@tonic-gate 		return (39);
468*7c478bd9Sstevel@tonic-gate 	}
469*7c478bd9Sstevel@tonic-gate 	close(xx);
470*7c478bd9Sstevel@tonic-gate 
471*7c478bd9Sstevel@tonic-gate 	/* fix permissions on the cache directory */
472*7c478bd9Sstevel@tonic-gate 	xx = cache_permissions(cachedirp);
473*7c478bd9Sstevel@tonic-gate 	if (xx)
474*7c478bd9Sstevel@tonic-gate 		return (xx);
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate 	/* make the back file system mount directory if necessary */
477*7c478bd9Sstevel@tonic-gate 	xx = cache_check_dir(cachedirp, BACKMNT_NAME);
478*7c478bd9Sstevel@tonic-gate 	if (xx)
479*7c478bd9Sstevel@tonic-gate 		return (xx);
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate 	/* clean out junk in the back file system mount directory */
482*7c478bd9Sstevel@tonic-gate 	cache_backmnt_cleanup(cachedirp, BACKMNT_NAME);
483*7c478bd9Sstevel@tonic-gate 
484*7c478bd9Sstevel@tonic-gate 	/* make the lost+found directory if necessary */
485*7c478bd9Sstevel@tonic-gate 	xx = cache_check_dir(cachedirp, CACHEFS_LOSTFOUND_NAME);
486*7c478bd9Sstevel@tonic-gate 	if (xx)
487*7c478bd9Sstevel@tonic-gate 		return (xx);
488*7c478bd9Sstevel@tonic-gate 
489*7c478bd9Sstevel@tonic-gate 	/* construct the path to the lost and found directory for file_remove */
490*7c478bd9Sstevel@tonic-gate 	sprintf(S_lostfound, "%s/%s", cachedirp, CACHEFS_LOSTFOUND_NAME);
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate 	/* construct the path name of the resource file */
493*7c478bd9Sstevel@tonic-gate 	namep = RESOURCE_NAME;
494*7c478bd9Sstevel@tonic-gate 	xx = strlen(cachedirp) + strlen(namep) + 3;
495*7c478bd9Sstevel@tonic-gate 	if (xx >= MAXPATHLEN) {
496*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Path name too long %s/%s"),
497*7c478bd9Sstevel@tonic-gate 		    cachedirp, namep);
498*7c478bd9Sstevel@tonic-gate 		return (39);
499*7c478bd9Sstevel@tonic-gate 	}
500*7c478bd9Sstevel@tonic-gate 	sprintf(buf, "%s/%s", cachedirp, namep);
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate 	/* make a res object to operate on the resource file */
503*7c478bd9Sstevel@tonic-gate 	resp = res_create(buf, clabel.cl_maxinodes, verbose);
504*7c478bd9Sstevel@tonic-gate 	if (resp == NULL) {
505*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Could not process resource file %s: %s"),
506*7c478bd9Sstevel@tonic-gate 		    buf, strerror(errno));
507*7c478bd9Sstevel@tonic-gate 		return (39);
508*7c478bd9Sstevel@tonic-gate 	}
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate 	/* open the cache directory */
511*7c478bd9Sstevel@tonic-gate 	if ((dp = opendir(cachedirp)) == NULL) {
512*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Cannot open directory %s: %s"), cachedirp,
513*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
514*7c478bd9Sstevel@tonic-gate 		res_destroy(resp);
515*7c478bd9Sstevel@tonic-gate 		return (39);
516*7c478bd9Sstevel@tonic-gate 	}
517*7c478bd9Sstevel@tonic-gate 
518*7c478bd9Sstevel@tonic-gate 	/* mark all directories */
519*7c478bd9Sstevel@tonic-gate 	while ((dep = readdir64(dp)) != NULL) {
520*7c478bd9Sstevel@tonic-gate 		/* ignore . and .. */
521*7c478bd9Sstevel@tonic-gate 		if ((strcmp(dep->d_name, ".") == 0) ||
522*7c478bd9Sstevel@tonic-gate 				(strcmp(dep->d_name, "..") == 0))
523*7c478bd9Sstevel@tonic-gate 			continue;
524*7c478bd9Sstevel@tonic-gate 
525*7c478bd9Sstevel@tonic-gate 		/* check path length */
526*7c478bd9Sstevel@tonic-gate 		xx = strlen(cachedirp) + strlen(dep->d_name) + 3;
527*7c478bd9Sstevel@tonic-gate 		if (xx >= MAXPATHLEN) {
528*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Path name too long %s/%s"),
529*7c478bd9Sstevel@tonic-gate 			    cachedirp, dep->d_name);
530*7c478bd9Sstevel@tonic-gate 			closedir(dp);
531*7c478bd9Sstevel@tonic-gate 			res_destroy(resp);
532*7c478bd9Sstevel@tonic-gate 			return (39);
533*7c478bd9Sstevel@tonic-gate 		}
534*7c478bd9Sstevel@tonic-gate 
535*7c478bd9Sstevel@tonic-gate 		/* stat the file */
536*7c478bd9Sstevel@tonic-gate 		sprintf(buf, "%s/%s", cachedirp, dep->d_name);
537*7c478bd9Sstevel@tonic-gate 		xx = lstat64(buf, &statinfo);
538*7c478bd9Sstevel@tonic-gate 		if (xx == -1) {
539*7c478bd9Sstevel@tonic-gate 			if (errno != ENOENT) {
540*7c478bd9Sstevel@tonic-gate 				pr_err(gettext("Cannot stat %s: %s"), cachedirp,
541*7c478bd9Sstevel@tonic-gate 				    strerror(errno));
542*7c478bd9Sstevel@tonic-gate 				closedir(dp);
543*7c478bd9Sstevel@tonic-gate 				res_destroy(resp);
544*7c478bd9Sstevel@tonic-gate 				return (39);
545*7c478bd9Sstevel@tonic-gate 			}
546*7c478bd9Sstevel@tonic-gate 			continue;
547*7c478bd9Sstevel@tonic-gate 		}
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate 		/* if a directory */
550*7c478bd9Sstevel@tonic-gate 		if (S_ISDIR(statinfo.st_mode)) {
551*7c478bd9Sstevel@tonic-gate 			xx = chmod(buf, 0700);
552*7c478bd9Sstevel@tonic-gate 			if (xx == -1) {
553*7c478bd9Sstevel@tonic-gate 				pr_err(gettext("Cannot chmod %s: %s"), buf,
554*7c478bd9Sstevel@tonic-gate 				    strerror(errno));
555*7c478bd9Sstevel@tonic-gate 				closedir(dp);
556*7c478bd9Sstevel@tonic-gate 				res_destroy(resp);
557*7c478bd9Sstevel@tonic-gate 				return (39);
558*7c478bd9Sstevel@tonic-gate 			}
559*7c478bd9Sstevel@tonic-gate 		}
560*7c478bd9Sstevel@tonic-gate 	}
561*7c478bd9Sstevel@tonic-gate 
562*7c478bd9Sstevel@tonic-gate 	/* process files in the cache directory */
563*7c478bd9Sstevel@tonic-gate 	rewinddir(dp);
564*7c478bd9Sstevel@tonic-gate 	while ((dep = readdir64(dp)) != NULL) {
565*7c478bd9Sstevel@tonic-gate 		/* ignore . and .. */
566*7c478bd9Sstevel@tonic-gate 		if ((strcmp(dep->d_name, ".") == 0) ||
567*7c478bd9Sstevel@tonic-gate 				(strcmp(dep->d_name, "..") == 0))
568*7c478bd9Sstevel@tonic-gate 			continue;
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate 		/* stat the file */
571*7c478bd9Sstevel@tonic-gate 		sprintf(buf, "%s/%s", cachedirp, dep->d_name);
572*7c478bd9Sstevel@tonic-gate 		xx = lstat64(buf, &statinfo);
573*7c478bd9Sstevel@tonic-gate 		if (xx == -1) {
574*7c478bd9Sstevel@tonic-gate 			if (errno != ENOENT) {
575*7c478bd9Sstevel@tonic-gate 				pr_err(gettext("Cannot stat %s: %s"), cachedirp,
576*7c478bd9Sstevel@tonic-gate 				    strerror(errno));
577*7c478bd9Sstevel@tonic-gate 				closedir(dp);
578*7c478bd9Sstevel@tonic-gate 				res_destroy(resp);
579*7c478bd9Sstevel@tonic-gate 				return (39);
580*7c478bd9Sstevel@tonic-gate 			}
581*7c478bd9Sstevel@tonic-gate 			continue;
582*7c478bd9Sstevel@tonic-gate 		}
583*7c478bd9Sstevel@tonic-gate 
584*7c478bd9Sstevel@tonic-gate 		/* ignore directories */
585*7c478bd9Sstevel@tonic-gate 		if (S_ISDIR(statinfo.st_mode))
586*7c478bd9Sstevel@tonic-gate 			continue;
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate 		/* if not a link */
589*7c478bd9Sstevel@tonic-gate 		if (!S_ISLNK(statinfo.st_mode)) {
590*7c478bd9Sstevel@tonic-gate 			/*
591*7c478bd9Sstevel@tonic-gate 			 * XXX make sure a valid file
592*7c478bd9Sstevel@tonic-gate 			 * Update file and block counts for this file.
593*7c478bd9Sstevel@tonic-gate 			 * This file will be <2GB.
594*7c478bd9Sstevel@tonic-gate 			 */
595*7c478bd9Sstevel@tonic-gate 			res_addfile(resp, (long)statinfo.st_size);
596*7c478bd9Sstevel@tonic-gate 			continue;
597*7c478bd9Sstevel@tonic-gate 		}
598*7c478bd9Sstevel@tonic-gate 
599*7c478bd9Sstevel@tonic-gate 		/* process the file system cache directory */
600*7c478bd9Sstevel@tonic-gate 		xx = process_fsdir(cachedirp, dep->d_name, resp, verbose);
601*7c478bd9Sstevel@tonic-gate 		if (xx) {
602*7c478bd9Sstevel@tonic-gate 			closedir(dp);
603*7c478bd9Sstevel@tonic-gate 			res_destroy(resp);
604*7c478bd9Sstevel@tonic-gate 			return (xx);
605*7c478bd9Sstevel@tonic-gate 		}
606*7c478bd9Sstevel@tonic-gate 	}
607*7c478bd9Sstevel@tonic-gate 
608*7c478bd9Sstevel@tonic-gate 	/* look for directories that do not belong */
609*7c478bd9Sstevel@tonic-gate 	rewinddir(dp);
610*7c478bd9Sstevel@tonic-gate 	while ((dep = readdir64(dp)) != NULL) {
611*7c478bd9Sstevel@tonic-gate 		/* ignore . and .. */
612*7c478bd9Sstevel@tonic-gate 		if ((strcmp(dep->d_name, ".") == 0) ||
613*7c478bd9Sstevel@tonic-gate 				(strcmp(dep->d_name, "..") == 0))
614*7c478bd9Sstevel@tonic-gate 			continue;
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate 		/* stat the file */
617*7c478bd9Sstevel@tonic-gate 		sprintf(buf, "%s/%s", cachedirp, dep->d_name);
618*7c478bd9Sstevel@tonic-gate 		xx = lstat64(buf, &statinfo);
619*7c478bd9Sstevel@tonic-gate 		if (xx == -1) {
620*7c478bd9Sstevel@tonic-gate 			if (errno != ENOENT) {
621*7c478bd9Sstevel@tonic-gate 				pr_err(gettext("Cannot stat %s: %s"), cachedirp,
622*7c478bd9Sstevel@tonic-gate 				    strerror(errno));
623*7c478bd9Sstevel@tonic-gate 				closedir(dp);
624*7c478bd9Sstevel@tonic-gate 				res_destroy(resp);
625*7c478bd9Sstevel@tonic-gate 				return (39);
626*7c478bd9Sstevel@tonic-gate 			}
627*7c478bd9Sstevel@tonic-gate 			continue;
628*7c478bd9Sstevel@tonic-gate 		}
629*7c478bd9Sstevel@tonic-gate 
630*7c478bd9Sstevel@tonic-gate 		/* XXX should we unlink extraneous regular files? */
631*7c478bd9Sstevel@tonic-gate 
632*7c478bd9Sstevel@tonic-gate 		/* ignore all but directories */
633*7c478bd9Sstevel@tonic-gate 		if (!S_ISDIR(statinfo.st_mode))
634*7c478bd9Sstevel@tonic-gate 			continue;
635*7c478bd9Sstevel@tonic-gate 
636*7c478bd9Sstevel@tonic-gate 		/* ignore directories we have checked */
637*7c478bd9Sstevel@tonic-gate 		if ((statinfo.st_mode & S_IAMB) != 0700)
638*7c478bd9Sstevel@tonic-gate 			continue;
639*7c478bd9Sstevel@tonic-gate 
640*7c478bd9Sstevel@tonic-gate 		/* ignore the mount directory */
641*7c478bd9Sstevel@tonic-gate 		if (strcmp(dep->d_name, BACKMNT_NAME) == 0)
642*7c478bd9Sstevel@tonic-gate 			continue;
643*7c478bd9Sstevel@tonic-gate 
644*7c478bd9Sstevel@tonic-gate 		/* ignore the lost+found directory */
645*7c478bd9Sstevel@tonic-gate 		if (strcmp(dep->d_name, CACHEFS_LOSTFOUND_NAME) == 0)
646*7c478bd9Sstevel@tonic-gate 			continue;
647*7c478bd9Sstevel@tonic-gate 
648*7c478bd9Sstevel@tonic-gate 		/* remove the directory */
649*7c478bd9Sstevel@tonic-gate 		xx = nftw64(buf, tree_remove, 3, FLAGS_FTW);
650*7c478bd9Sstevel@tonic-gate 		if (xx != 0) {
651*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Error walking tree %s."), namep);
652*7c478bd9Sstevel@tonic-gate 			closedir(dp);
653*7c478bd9Sstevel@tonic-gate 			res_destroy(resp);
654*7c478bd9Sstevel@tonic-gate 			return (39);
655*7c478bd9Sstevel@tonic-gate 		}
656*7c478bd9Sstevel@tonic-gate 
657*7c478bd9Sstevel@tonic-gate 		if (verbose)
658*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Directory removed: %s"), buf);
659*7c478bd9Sstevel@tonic-gate 	}
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate 	/* close the directory */
662*7c478bd9Sstevel@tonic-gate 	closedir(dp);
663*7c478bd9Sstevel@tonic-gate 
664*7c478bd9Sstevel@tonic-gate 	/* add one file and one block for the cache directory itself */
665*7c478bd9Sstevel@tonic-gate 	res_addfile(resp, 1);
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate 	/* finish off the resource file processing */
668*7c478bd9Sstevel@tonic-gate 	xx = res_done(resp);
669*7c478bd9Sstevel@tonic-gate 	if (xx == -1) {
670*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Could not finish resource file %s: %s"),
671*7c478bd9Sstevel@tonic-gate 		    buf, strerror(errno));
672*7c478bd9Sstevel@tonic-gate 		return (39);
673*7c478bd9Sstevel@tonic-gate 	}
674*7c478bd9Sstevel@tonic-gate 	res_destroy(resp);
675*7c478bd9Sstevel@tonic-gate 
676*7c478bd9Sstevel@tonic-gate 	/* return success */
677*7c478bd9Sstevel@tonic-gate 	return (0);
678*7c478bd9Sstevel@tonic-gate }
679*7c478bd9Sstevel@tonic-gate 
680*7c478bd9Sstevel@tonic-gate /*
681*7c478bd9Sstevel@tonic-gate  *
682*7c478bd9Sstevel@tonic-gate  *			cache_label_file
683*7c478bd9Sstevel@tonic-gate  *
684*7c478bd9Sstevel@tonic-gate  * Description:
685*7c478bd9Sstevel@tonic-gate  *	This routine performs the checking and fixing up of the
686*7c478bd9Sstevel@tonic-gate  *	cache label file.
687*7c478bd9Sstevel@tonic-gate  * Arguments:
688*7c478bd9Sstevel@tonic-gate  *	cachedirp	name of the cache directory to check
689*7c478bd9Sstevel@tonic-gate  *	clabelp		cache label contents put here if not NULL
690*7c478bd9Sstevel@tonic-gate  * Returns:
691*7c478bd9Sstevel@tonic-gate  *		 0	file system is okay and does not need checking
692*7c478bd9Sstevel@tonic-gate  *		 1	problem unrelated to the file system
693*7c478bd9Sstevel@tonic-gate  *		32	file system is unmounted and needs checking
694*7c478bd9Sstevel@tonic-gate  *		33	file system is already mounted
695*7c478bd9Sstevel@tonic-gate  *		34	cannot stat device
696*7c478bd9Sstevel@tonic-gate  *		36	uncorrectable errors detected - terminate normally
697*7c478bd9Sstevel@tonic-gate  *		37	a signal was caught during processing
698*7c478bd9Sstevel@tonic-gate  *		39	uncorrectable errors detected - terminate  immediately
699*7c478bd9Sstevel@tonic-gate  * Preconditions:
700*7c478bd9Sstevel@tonic-gate  *	precond(cachedirp)
701*7c478bd9Sstevel@tonic-gate  */
702*7c478bd9Sstevel@tonic-gate 
703*7c478bd9Sstevel@tonic-gate int
cache_label_file(char * cachedirp,struct cache_label * clabelp)704*7c478bd9Sstevel@tonic-gate cache_label_file(char *cachedirp, struct cache_label *clabelp)
705*7c478bd9Sstevel@tonic-gate {
706*7c478bd9Sstevel@tonic-gate 	int xx;
707*7c478bd9Sstevel@tonic-gate 	char buf1[MAXPATHLEN];
708*7c478bd9Sstevel@tonic-gate 	char buf2[MAXPATHLEN];
709*7c478bd9Sstevel@tonic-gate 	char *namep;
710*7c478bd9Sstevel@tonic-gate 	struct cache_label clabel1, clabel2;
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate 	namep = CACHELABEL_NAME;
713*7c478bd9Sstevel@tonic-gate 
714*7c478bd9Sstevel@tonic-gate 	/* see if path name is too long */
715*7c478bd9Sstevel@tonic-gate 	xx = strlen(cachedirp) + strlen(namep) + 10;
716*7c478bd9Sstevel@tonic-gate 	if (xx >= MAXPATHLEN) {
717*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Cache directory name %s is too long"),
718*7c478bd9Sstevel@tonic-gate 		    cachedirp);
719*7c478bd9Sstevel@tonic-gate 		return (39);
720*7c478bd9Sstevel@tonic-gate 	}
721*7c478bd9Sstevel@tonic-gate 
722*7c478bd9Sstevel@tonic-gate 	/* make a path to the cache label file and its backup copy */
723*7c478bd9Sstevel@tonic-gate 	sprintf(buf1, "%s/%s", cachedirp, namep);
724*7c478bd9Sstevel@tonic-gate 	sprintf(buf2, "%s/%s.dup", cachedirp, namep);
725*7c478bd9Sstevel@tonic-gate 
726*7c478bd9Sstevel@tonic-gate 	/* get the contents of the cache label file */
727*7c478bd9Sstevel@tonic-gate 	xx = cachefs_label_file_get(buf1, &clabel1);
728*7c478bd9Sstevel@tonic-gate 	if (xx == -1) {
729*7c478bd9Sstevel@tonic-gate 		/* get the backup cache label file contents */
730*7c478bd9Sstevel@tonic-gate 		xx = cachefs_label_file_get(buf2, &clabel2);
731*7c478bd9Sstevel@tonic-gate 		if (xx == -1) {
732*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Run `cfsadmin -d all %s'\n"
733*7c478bd9Sstevel@tonic-gate 			    "and then run\n"
734*7c478bd9Sstevel@tonic-gate 			    "`cfsadmin -c %s'\n"), cachedirp, cachedirp);
735*7c478bd9Sstevel@tonic-gate 			return (39);
736*7c478bd9Sstevel@tonic-gate 		}
737*7c478bd9Sstevel@tonic-gate 
738*7c478bd9Sstevel@tonic-gate 		/* write the cache label file */
739*7c478bd9Sstevel@tonic-gate 		xx = cachefs_label_file_put(buf1, &clabel2);
740*7c478bd9Sstevel@tonic-gate 		if (xx == -1) {
741*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Run `cfsadmin -d all %s'\n"
742*7c478bd9Sstevel@tonic-gate 			    "and then run\n"
743*7c478bd9Sstevel@tonic-gate 			    "`cfsadmin -c %s'\n"), cachedirp, cachedirp);
744*7c478bd9Sstevel@tonic-gate 			return (39);
745*7c478bd9Sstevel@tonic-gate 		}
746*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Cache label file %s repaired."), buf1);
747*7c478bd9Sstevel@tonic-gate 
748*7c478bd9Sstevel@tonic-gate 		/* copy out the contents to the caller */
749*7c478bd9Sstevel@tonic-gate 		if (clabelp)
750*7c478bd9Sstevel@tonic-gate 			*clabelp = clabel2;
751*7c478bd9Sstevel@tonic-gate 
752*7c478bd9Sstevel@tonic-gate 		/* return success */
753*7c478bd9Sstevel@tonic-gate 		return (0);
754*7c478bd9Sstevel@tonic-gate 	}
755*7c478bd9Sstevel@tonic-gate 
756*7c478bd9Sstevel@tonic-gate 	/* get the contents of the backup cache label file */
757*7c478bd9Sstevel@tonic-gate 	xx = cachefs_label_file_get(buf2, &clabel2);
758*7c478bd9Sstevel@tonic-gate 	if (xx == -1) {
759*7c478bd9Sstevel@tonic-gate 		/* write the backup cache label file */
760*7c478bd9Sstevel@tonic-gate 		xx = cachefs_label_file_put(buf2, &clabel1);
761*7c478bd9Sstevel@tonic-gate 		if (xx == -1) {
762*7c478bd9Sstevel@tonic-gate 			return (39);
763*7c478bd9Sstevel@tonic-gate 		}
764*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Cache label file %s repaired."), buf2);
765*7c478bd9Sstevel@tonic-gate 	}
766*7c478bd9Sstevel@tonic-gate 
767*7c478bd9Sstevel@tonic-gate 	/* copy out the contents to the caller */
768*7c478bd9Sstevel@tonic-gate 	if (clabelp)
769*7c478bd9Sstevel@tonic-gate 		*clabelp = clabel1;
770*7c478bd9Sstevel@tonic-gate 
771*7c478bd9Sstevel@tonic-gate 	/* return success */
772*7c478bd9Sstevel@tonic-gate 	return (0);
773*7c478bd9Sstevel@tonic-gate }
774*7c478bd9Sstevel@tonic-gate 
775*7c478bd9Sstevel@tonic-gate /*
776*7c478bd9Sstevel@tonic-gate  *
777*7c478bd9Sstevel@tonic-gate  *			cache_permissions
778*7c478bd9Sstevel@tonic-gate  *
779*7c478bd9Sstevel@tonic-gate  * Description:
780*7c478bd9Sstevel@tonic-gate  *	Checks the permissions on the cache directory and fixes
781*7c478bd9Sstevel@tonic-gate  *	them if necessary.
782*7c478bd9Sstevel@tonic-gate  * Arguments:
783*7c478bd9Sstevel@tonic-gate  *	cachedirp	name of the cache directory to check
784*7c478bd9Sstevel@tonic-gate  * Returns:
785*7c478bd9Sstevel@tonic-gate  *		 0	file system is okay and does not need checking
786*7c478bd9Sstevel@tonic-gate  *		 1	problem unrelated to the file system
787*7c478bd9Sstevel@tonic-gate  *		32	file system is unmounted and needs checking
788*7c478bd9Sstevel@tonic-gate  *		33	file system is already mounted
789*7c478bd9Sstevel@tonic-gate  *		34	cannot stat device
790*7c478bd9Sstevel@tonic-gate  *		36	uncorrectable errors detected - terminate normally
791*7c478bd9Sstevel@tonic-gate  *		37	a signal was caught during processing
792*7c478bd9Sstevel@tonic-gate  *		39	uncorrectable errors detected - terminate  immediately
793*7c478bd9Sstevel@tonic-gate  * Preconditions:
794*7c478bd9Sstevel@tonic-gate  *	precond(cachedirp)
795*7c478bd9Sstevel@tonic-gate  */
796*7c478bd9Sstevel@tonic-gate 
797*7c478bd9Sstevel@tonic-gate int
cache_permissions(char * cachedirp)798*7c478bd9Sstevel@tonic-gate cache_permissions(char *cachedirp)
799*7c478bd9Sstevel@tonic-gate {
800*7c478bd9Sstevel@tonic-gate 	int xx;
801*7c478bd9Sstevel@tonic-gate 	struct stat64 statinfo;
802*7c478bd9Sstevel@tonic-gate 
803*7c478bd9Sstevel@tonic-gate 	/* get info about the cache directory */
804*7c478bd9Sstevel@tonic-gate 	xx = lstat64(cachedirp, &statinfo);
805*7c478bd9Sstevel@tonic-gate 	if (xx == -1) {
806*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Could not stat %s: %s"), cachedirp,
807*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
808*7c478bd9Sstevel@tonic-gate 		return (34);
809*7c478bd9Sstevel@tonic-gate 	}
810*7c478bd9Sstevel@tonic-gate 
811*7c478bd9Sstevel@tonic-gate 	/* check the mode bits */
812*7c478bd9Sstevel@tonic-gate 	if ((statinfo.st_mode & S_IAMB) != 0) {
813*7c478bd9Sstevel@tonic-gate 
814*7c478bd9Sstevel@tonic-gate 		/* fix the mode bits */
815*7c478bd9Sstevel@tonic-gate 		xx = chmod(cachedirp, 0);
816*7c478bd9Sstevel@tonic-gate 		if (xx == -1) {
817*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Could not set modes bits on "
818*7c478bd9Sstevel@tonic-gate 			    "cache directory %s: %s"),
819*7c478bd9Sstevel@tonic-gate 			    cachedirp, strerror(errno));
820*7c478bd9Sstevel@tonic-gate 			return (36);
821*7c478bd9Sstevel@tonic-gate 		}
822*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Mode bits reset on cache directory %s"),
823*7c478bd9Sstevel@tonic-gate 		    cachedirp);
824*7c478bd9Sstevel@tonic-gate 	}
825*7c478bd9Sstevel@tonic-gate 
826*7c478bd9Sstevel@tonic-gate 	/* return success */
827*7c478bd9Sstevel@tonic-gate 	return (0);
828*7c478bd9Sstevel@tonic-gate }
829*7c478bd9Sstevel@tonic-gate 
830*7c478bd9Sstevel@tonic-gate /*
831*7c478bd9Sstevel@tonic-gate  *
832*7c478bd9Sstevel@tonic-gate  *			cache_check_dir
833*7c478bd9Sstevel@tonic-gate  *
834*7c478bd9Sstevel@tonic-gate  * Description:
835*7c478bd9Sstevel@tonic-gate  *	Checks for the existance of the directory
836*7c478bd9Sstevel@tonic-gate  *	and creates it if necessary.
837*7c478bd9Sstevel@tonic-gate  * Arguments:
838*7c478bd9Sstevel@tonic-gate  *	cachedirp	name of the cache directory containing the dir
839*7c478bd9Sstevel@tonic-gate  *	namep		name of dir
840*7c478bd9Sstevel@tonic-gate  * Returns:
841*7c478bd9Sstevel@tonic-gate  *		 0	file system is okay and does not need checking
842*7c478bd9Sstevel@tonic-gate  *		 1	problem unrelated to the file system
843*7c478bd9Sstevel@tonic-gate  *		32	file system is unmounted and needs checking
844*7c478bd9Sstevel@tonic-gate  *		33	file system is already mounted
845*7c478bd9Sstevel@tonic-gate  *		34	cannot stat device
846*7c478bd9Sstevel@tonic-gate  *		36	uncorrectable errors detected - terminate normally
847*7c478bd9Sstevel@tonic-gate  *		37	a signal was caught during processing
848*7c478bd9Sstevel@tonic-gate  *		39	uncorrectable errors detected - terminate  immediately
849*7c478bd9Sstevel@tonic-gate  * Preconditions:
850*7c478bd9Sstevel@tonic-gate  *	precond(cachedirp)
851*7c478bd9Sstevel@tonic-gate  *	precond(dirp)
852*7c478bd9Sstevel@tonic-gate  */
853*7c478bd9Sstevel@tonic-gate 
854*7c478bd9Sstevel@tonic-gate int
cache_check_dir(char * cachedirp,char * namep)855*7c478bd9Sstevel@tonic-gate cache_check_dir(char *cachedirp, char *namep)
856*7c478bd9Sstevel@tonic-gate {
857*7c478bd9Sstevel@tonic-gate 	int xx;
858*7c478bd9Sstevel@tonic-gate 	char buf[MAXPATHLEN];
859*7c478bd9Sstevel@tonic-gate 	struct stat64 statinfo;
860*7c478bd9Sstevel@tonic-gate 
861*7c478bd9Sstevel@tonic-gate 	/* see if path name is too long */
862*7c478bd9Sstevel@tonic-gate 	xx = strlen(cachedirp) + strlen(namep) + 3;
863*7c478bd9Sstevel@tonic-gate 	if (xx >= MAXPATHLEN) {
864*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Cache directory name %s is too long"),
865*7c478bd9Sstevel@tonic-gate 		    cachedirp);
866*7c478bd9Sstevel@tonic-gate 		return (39);
867*7c478bd9Sstevel@tonic-gate 	}
868*7c478bd9Sstevel@tonic-gate 
869*7c478bd9Sstevel@tonic-gate 	/* make the pathname of the directory */
870*7c478bd9Sstevel@tonic-gate 	sprintf(buf, "%s/%s", cachedirp, namep);
871*7c478bd9Sstevel@tonic-gate 
872*7c478bd9Sstevel@tonic-gate 	/* get info on the directory */
873*7c478bd9Sstevel@tonic-gate 	xx = lstat64(buf, &statinfo);
874*7c478bd9Sstevel@tonic-gate 	if (xx == -1) {
875*7c478bd9Sstevel@tonic-gate 		/* if an error other than it does not exist */
876*7c478bd9Sstevel@tonic-gate 		if (errno != ENOENT) {
877*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Error on lstat(2) of %s: %s"),
878*7c478bd9Sstevel@tonic-gate 			    buf, strerror(errno));
879*7c478bd9Sstevel@tonic-gate 			return (39);
880*7c478bd9Sstevel@tonic-gate 		}
881*7c478bd9Sstevel@tonic-gate 
882*7c478bd9Sstevel@tonic-gate 		/* make the directory */
883*7c478bd9Sstevel@tonic-gate 		xx = mkdir(buf, 0);
884*7c478bd9Sstevel@tonic-gate 		if (xx == -1) {
885*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Could not create directory %s"),
886*7c478bd9Sstevel@tonic-gate 			    buf);
887*7c478bd9Sstevel@tonic-gate 			return (39);
888*7c478bd9Sstevel@tonic-gate 		}
889*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Created directory %s"), buf);
890*7c478bd9Sstevel@tonic-gate 	}
891*7c478bd9Sstevel@tonic-gate 
892*7c478bd9Sstevel@tonic-gate 	/* else see if really a directory */
893*7c478bd9Sstevel@tonic-gate 	else if (!S_ISDIR(statinfo.st_mode)) {
894*7c478bd9Sstevel@tonic-gate 		/* get rid of the file */
895*7c478bd9Sstevel@tonic-gate 		xx = unlink(buf);
896*7c478bd9Sstevel@tonic-gate 		if (xx == -1) {
897*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Cannot remove %s: %s"), buf,
898*7c478bd9Sstevel@tonic-gate 			    strerror(errno));
899*7c478bd9Sstevel@tonic-gate 			return (39);
900*7c478bd9Sstevel@tonic-gate 		}
901*7c478bd9Sstevel@tonic-gate 
902*7c478bd9Sstevel@tonic-gate 		/* make the directory */
903*7c478bd9Sstevel@tonic-gate 		xx = mkdir(buf, 0);
904*7c478bd9Sstevel@tonic-gate 		if (xx == -1) {
905*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Could not create directory %s"),
906*7c478bd9Sstevel@tonic-gate 			    buf);
907*7c478bd9Sstevel@tonic-gate 			return (39);
908*7c478bd9Sstevel@tonic-gate 		}
909*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Created directory %s"), buf);
910*7c478bd9Sstevel@tonic-gate 	}
911*7c478bd9Sstevel@tonic-gate 
912*7c478bd9Sstevel@tonic-gate 	/* return success */
913*7c478bd9Sstevel@tonic-gate 	return (0);
914*7c478bd9Sstevel@tonic-gate }
915*7c478bd9Sstevel@tonic-gate 
916*7c478bd9Sstevel@tonic-gate /*
917*7c478bd9Sstevel@tonic-gate  *
918*7c478bd9Sstevel@tonic-gate  *			process_fsdir
919*7c478bd9Sstevel@tonic-gate  *
920*7c478bd9Sstevel@tonic-gate  * Description:
921*7c478bd9Sstevel@tonic-gate  *	Performs the necessary checking and repair on the
922*7c478bd9Sstevel@tonic-gate  *	specified file system cache directory.
923*7c478bd9Sstevel@tonic-gate  *	Calls res_addfile and res_addident as appropriate.
924*7c478bd9Sstevel@tonic-gate  * Arguments:
925*7c478bd9Sstevel@tonic-gate  *	cachedirp	name of cache directory
926*7c478bd9Sstevel@tonic-gate  *	namep		name of link file for the file system cache
927*7c478bd9Sstevel@tonic-gate  *	resp		res object for res_addfile and res_addident calls
928*7c478bd9Sstevel@tonic-gate  *	verbose		indicate level of verbosity for diagnostics
929*7c478bd9Sstevel@tonic-gate  * Returns:
930*7c478bd9Sstevel@tonic-gate  *		 0	file system is okay and does not need checking
931*7c478bd9Sstevel@tonic-gate  *		 1	problem unrelated to the file system
932*7c478bd9Sstevel@tonic-gate  *		32	file system is unmounted and needs checking
933*7c478bd9Sstevel@tonic-gate  *		33	file system is already mounted
934*7c478bd9Sstevel@tonic-gate  *		34	cannot stat device
935*7c478bd9Sstevel@tonic-gate  *		36	uncorrectable errors detected - terminate normally
936*7c478bd9Sstevel@tonic-gate  *		37	a signal was caught during processing
937*7c478bd9Sstevel@tonic-gate  *		39	uncorrectable errors detected - terminate  immediately
938*7c478bd9Sstevel@tonic-gate  * Preconditions:
939*7c478bd9Sstevel@tonic-gate  *	precond(cachedirp)
940*7c478bd9Sstevel@tonic-gate  *	precond(namep && is a sym link)
941*7c478bd9Sstevel@tonic-gate  *	precond(resp)
942*7c478bd9Sstevel@tonic-gate  */
943*7c478bd9Sstevel@tonic-gate 
944*7c478bd9Sstevel@tonic-gate int
process_fsdir(char * cachedirp,char * namep,res * resp,int verbose)945*7c478bd9Sstevel@tonic-gate process_fsdir(char *cachedirp, char *namep, res *resp, int verbose)
946*7c478bd9Sstevel@tonic-gate {
947*7c478bd9Sstevel@tonic-gate 	DIR *dp;
948*7c478bd9Sstevel@tonic-gate 	struct dirent64 *dep;
949*7c478bd9Sstevel@tonic-gate 	char linkpath[MAXPATHLEN];
950*7c478bd9Sstevel@tonic-gate 	char dirpath[MAXPATHLEN];
951*7c478bd9Sstevel@tonic-gate 	char attrpath[MAXPATHLEN];
952*7c478bd9Sstevel@tonic-gate 	char buf[MAXPATHLEN];
953*7c478bd9Sstevel@tonic-gate 	int xx;
954*7c478bd9Sstevel@tonic-gate 	struct stat64 statinfo;
955*7c478bd9Sstevel@tonic-gate 	char *atp = ATTRCACHE_NAME;
956*7c478bd9Sstevel@tonic-gate 	int fd;
957*7c478bd9Sstevel@tonic-gate 	ino64_t base;
958*7c478bd9Sstevel@tonic-gate 	int local;
959*7c478bd9Sstevel@tonic-gate 	char *strp;
960*7c478bd9Sstevel@tonic-gate 	ino64_t fsid;
961*7c478bd9Sstevel@tonic-gate 	int error = 0;
962*7c478bd9Sstevel@tonic-gate 	int hashsize = 0;
963*7c478bd9Sstevel@tonic-gate 	ENTRY hitem;
964*7c478bd9Sstevel@tonic-gate 	ino64_t maxlocalfileno;
965*7c478bd9Sstevel@tonic-gate 	cachefs_fsinfo_t fsinfo;
966*7c478bd9Sstevel@tonic-gate 	time32_t btime;
967*7c478bd9Sstevel@tonic-gate 
968*7c478bd9Sstevel@tonic-gate 	/* construct the path to the sym link */
969*7c478bd9Sstevel@tonic-gate 	xx = strlen(cachedirp) + strlen(namep) + 3;
970*7c478bd9Sstevel@tonic-gate 	if (xx >= MAXPATHLEN) {
971*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Pathname too long %s/%s"), cachedirp, namep);
972*7c478bd9Sstevel@tonic-gate 		error = 39;
973*7c478bd9Sstevel@tonic-gate 		goto out;
974*7c478bd9Sstevel@tonic-gate 	}
975*7c478bd9Sstevel@tonic-gate 	sprintf(linkpath, "%s/%s", cachedirp, namep);
976*7c478bd9Sstevel@tonic-gate 
977*7c478bd9Sstevel@tonic-gate 	/* read the contents of the link */
978*7c478bd9Sstevel@tonic-gate 	xx = readlink(linkpath, buf, sizeof (buf));
979*7c478bd9Sstevel@tonic-gate 	if (xx == -1) {
980*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Unable to read link %s: %s"), linkpath,
981*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
982*7c478bd9Sstevel@tonic-gate 		error = 39;
983*7c478bd9Sstevel@tonic-gate 		goto out;
984*7c478bd9Sstevel@tonic-gate 	}
985*7c478bd9Sstevel@tonic-gate 	buf[xx] = '\0';
986*7c478bd9Sstevel@tonic-gate 
987*7c478bd9Sstevel@tonic-gate 	/* do a one time check on lengths of files */
988*7c478bd9Sstevel@tonic-gate 	xx = strlen(cachedirp) + strlen(buf) + 20 + 20;
989*7c478bd9Sstevel@tonic-gate 	if (xx >= MAXPATHLEN) {
990*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Pathname too long %s/%s"), cachedirp, buf);
991*7c478bd9Sstevel@tonic-gate 		error = 39;
992*7c478bd9Sstevel@tonic-gate 		goto out;
993*7c478bd9Sstevel@tonic-gate 	}
994*7c478bd9Sstevel@tonic-gate 
995*7c478bd9Sstevel@tonic-gate 	/* construct the path to the directory */
996*7c478bd9Sstevel@tonic-gate 	sprintf(dirpath, "%s/%s", cachedirp, buf);
997*7c478bd9Sstevel@tonic-gate 
998*7c478bd9Sstevel@tonic-gate 	/* stat the directory */
999*7c478bd9Sstevel@tonic-gate 	xx = lstat64(dirpath, &statinfo);
1000*7c478bd9Sstevel@tonic-gate 	if ((xx == -1) || (strtoull(buf, NULL, 16) != statinfo.st_ino)) {
1001*7c478bd9Sstevel@tonic-gate 		if ((xx == -1) && (errno != ENOENT)) {
1002*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Could not stat %s: %s"), dirpath,
1003*7c478bd9Sstevel@tonic-gate 			    strerror(errno));
1004*7c478bd9Sstevel@tonic-gate 			error = 39;
1005*7c478bd9Sstevel@tonic-gate 		} else
1006*7c478bd9Sstevel@tonic-gate 			error = -1;
1007*7c478bd9Sstevel@tonic-gate 		goto out;
1008*7c478bd9Sstevel@tonic-gate 	}
1009*7c478bd9Sstevel@tonic-gate 	fsid = statinfo.st_ino;
1010*7c478bd9Sstevel@tonic-gate 
1011*7c478bd9Sstevel@tonic-gate 	/*
1012*7c478bd9Sstevel@tonic-gate 	 * Check for a disconnect log(dlog) file and verify it.
1013*7c478bd9Sstevel@tonic-gate 	 */
1014*7c478bd9Sstevel@tonic-gate 	xx = dlog_ck(dirpath, &maxlocalfileno);
1015*7c478bd9Sstevel@tonic-gate 	if (xx) {
1016*7c478bd9Sstevel@tonic-gate 		error = -1;
1017*7c478bd9Sstevel@tonic-gate 		goto out;
1018*7c478bd9Sstevel@tonic-gate 	}
1019*7c478bd9Sstevel@tonic-gate 
1020*7c478bd9Sstevel@tonic-gate 	/* process the fsinfo file */
1021*7c478bd9Sstevel@tonic-gate 	sprintf(buf, "%s/%s", dirpath, CACHEFS_FSINFO);
1022*7c478bd9Sstevel@tonic-gate 	xx = process_fsinfo(buf, maxlocalfileno, &fsinfo, verbose);
1023*7c478bd9Sstevel@tonic-gate 	if (xx) {
1024*7c478bd9Sstevel@tonic-gate 		error = -1;
1025*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Cannot update fsinfo file %s"), buf);
1026*7c478bd9Sstevel@tonic-gate 		goto out;
1027*7c478bd9Sstevel@tonic-gate 	}
1028*7c478bd9Sstevel@tonic-gate 
1029*7c478bd9Sstevel@tonic-gate 	/* create the unmount file in the cachedir */
1030*7c478bd9Sstevel@tonic-gate 	sprintf(buf, "%s/%s", dirpath, CACHEFS_UNMNT_FILE);
1031*7c478bd9Sstevel@tonic-gate 	/* this file will be < 2GB */
1032*7c478bd9Sstevel@tonic-gate 	fd = open(buf, O_CREAT | O_RDWR, 0666);
1033*7c478bd9Sstevel@tonic-gate 	if (fd == -1) {
1034*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Cannot create unmnt file %s: %s"), buf,
1035*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
1036*7c478bd9Sstevel@tonic-gate 		error = -1;
1037*7c478bd9Sstevel@tonic-gate 		goto out;
1038*7c478bd9Sstevel@tonic-gate 	}
1039*7c478bd9Sstevel@tonic-gate 	btime = get_boottime();
1040*7c478bd9Sstevel@tonic-gate 	if (write(fd, &btime, sizeof (btime)) == -1) {
1041*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Cannot write cachedir unmnt file %s: %s"), buf,
1042*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
1043*7c478bd9Sstevel@tonic-gate 		error = -1;
1044*7c478bd9Sstevel@tonic-gate 		goto out;
1045*7c478bd9Sstevel@tonic-gate 	}
1046*7c478bd9Sstevel@tonic-gate 	close(fd);
1047*7c478bd9Sstevel@tonic-gate 
1048*7c478bd9Sstevel@tonic-gate 	/* create the unmount file */
1049*7c478bd9Sstevel@tonic-gate 	sprintf(buf, "%s/%s", dirpath, CACHEFS_UNMNT_FILE);
1050*7c478bd9Sstevel@tonic-gate 	/* this file will be < 2GB */
1051*7c478bd9Sstevel@tonic-gate 	fd = open(buf, O_CREAT | O_RDWR, 0666);
1052*7c478bd9Sstevel@tonic-gate 	if (fd == -1) {
1053*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Cannot create unmnt file %s: %s"), buf,
1054*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
1055*7c478bd9Sstevel@tonic-gate 		error = -1;
1056*7c478bd9Sstevel@tonic-gate 		goto out;
1057*7c478bd9Sstevel@tonic-gate 	}
1058*7c478bd9Sstevel@tonic-gate 	close(fd);
1059*7c478bd9Sstevel@tonic-gate 
1060*7c478bd9Sstevel@tonic-gate 	/* construct the name to the attrcache directory */
1061*7c478bd9Sstevel@tonic-gate 	sprintf(attrpath, "%s/%s", dirpath, atp);
1062*7c478bd9Sstevel@tonic-gate 
1063*7c478bd9Sstevel@tonic-gate 	/* open the attrcache directory */
1064*7c478bd9Sstevel@tonic-gate 	if ((dp = opendir(attrpath)) == NULL) {
1065*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Cannot open directory %s: %s"), attrpath,
1066*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
1067*7c478bd9Sstevel@tonic-gate 		error = -1;
1068*7c478bd9Sstevel@tonic-gate 		goto out;
1069*7c478bd9Sstevel@tonic-gate 	}
1070*7c478bd9Sstevel@tonic-gate 
1071*7c478bd9Sstevel@tonic-gate 	/* make one pass, counting how big to make the hash table */
1072*7c478bd9Sstevel@tonic-gate 	while (readdir64(dp) != NULL)
1073*7c478bd9Sstevel@tonic-gate 		++hashsize;
1074*7c478bd9Sstevel@tonic-gate 	if (hcreate(hashsize + 1000) == 0) {
1075*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Cannot allocate heap space."));
1076*7c478bd9Sstevel@tonic-gate 		(void) closedir(dp);
1077*7c478bd9Sstevel@tonic-gate 		hashsize = 0;
1078*7c478bd9Sstevel@tonic-gate 		error = 39;
1079*7c478bd9Sstevel@tonic-gate 		goto out;
1080*7c478bd9Sstevel@tonic-gate 	}
1081*7c478bd9Sstevel@tonic-gate 	rewinddir(dp);
1082*7c478bd9Sstevel@tonic-gate 
1083*7c478bd9Sstevel@tonic-gate 	/* loop reading the contents of the directory */
1084*7c478bd9Sstevel@tonic-gate 	while ((dep = readdir64(dp)) != NULL) {
1085*7c478bd9Sstevel@tonic-gate 		/* ignore . and .. */
1086*7c478bd9Sstevel@tonic-gate 		if ((strcmp(dep->d_name, ".") == 0) ||
1087*7c478bd9Sstevel@tonic-gate 		    (strcmp(dep->d_name, "..") == 0))
1088*7c478bd9Sstevel@tonic-gate 			continue;
1089*7c478bd9Sstevel@tonic-gate 
1090*7c478bd9Sstevel@tonic-gate 		/* check for a reasonable name */
1091*7c478bd9Sstevel@tonic-gate 		xx = strlen(dep->d_name);
1092*7c478bd9Sstevel@tonic-gate 		if ((xx != 16) && (xx != 17)) {
1093*7c478bd9Sstevel@tonic-gate 			/* bad file */
1094*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Unknown file %s/%s"),
1095*7c478bd9Sstevel@tonic-gate 				attrpath, dep->d_name);
1096*7c478bd9Sstevel@tonic-gate 			closedir(dp);
1097*7c478bd9Sstevel@tonic-gate 			error = 39;
1098*7c478bd9Sstevel@tonic-gate 			goto out;
1099*7c478bd9Sstevel@tonic-gate 		}
1100*7c478bd9Sstevel@tonic-gate 
1101*7c478bd9Sstevel@tonic-gate 		/* derive the base number from the file name */
1102*7c478bd9Sstevel@tonic-gate 		if (*(dep->d_name) == 'L') {
1103*7c478bd9Sstevel@tonic-gate 			local = 1;
1104*7c478bd9Sstevel@tonic-gate 			base = strtoull(dep->d_name + 1, &strp, 16);
1105*7c478bd9Sstevel@tonic-gate 		} else {
1106*7c478bd9Sstevel@tonic-gate 			local = 0;
1107*7c478bd9Sstevel@tonic-gate 			base = strtoull(dep->d_name, &strp, 16);
1108*7c478bd9Sstevel@tonic-gate 		}
1109*7c478bd9Sstevel@tonic-gate 		if (*strp != '\0') {
1110*7c478bd9Sstevel@tonic-gate 			/* bad file */
1111*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Unknown file %s/%s"),
1112*7c478bd9Sstevel@tonic-gate 				attrpath, dep->d_name);
1113*7c478bd9Sstevel@tonic-gate 			closedir(dp);
1114*7c478bd9Sstevel@tonic-gate 			error = 39;
1115*7c478bd9Sstevel@tonic-gate 			goto out;
1116*7c478bd9Sstevel@tonic-gate 		}
1117*7c478bd9Sstevel@tonic-gate 
1118*7c478bd9Sstevel@tonic-gate 		/* process the file group */
1119*7c478bd9Sstevel@tonic-gate 		error = process_fsgroup(dirpath, dep->d_name, resp,
1120*7c478bd9Sstevel@tonic-gate 			base, fsinfo.fi_fgsize, fsid, local, verbose);
1121*7c478bd9Sstevel@tonic-gate 		if (error) {
1122*7c478bd9Sstevel@tonic-gate 			closedir(dp);
1123*7c478bd9Sstevel@tonic-gate 			goto out;
1124*7c478bd9Sstevel@tonic-gate 		}
1125*7c478bd9Sstevel@tonic-gate 	}
1126*7c478bd9Sstevel@tonic-gate 	closedir(dp);
1127*7c478bd9Sstevel@tonic-gate 
1128*7c478bd9Sstevel@tonic-gate 	/* open the fscache directory */
1129*7c478bd9Sstevel@tonic-gate 	if ((dp = opendir(dirpath)) == NULL) {
1130*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Cannot open directory %s: %s"), dirpath,
1131*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
1132*7c478bd9Sstevel@tonic-gate 		error = 39;
1133*7c478bd9Sstevel@tonic-gate 		goto out;
1134*7c478bd9Sstevel@tonic-gate 	}
1135*7c478bd9Sstevel@tonic-gate 
1136*7c478bd9Sstevel@tonic-gate 	/* loop reading the contents of the directory */
1137*7c478bd9Sstevel@tonic-gate 	while ((dep = readdir64(dp)) != NULL) {
1138*7c478bd9Sstevel@tonic-gate 		/* ignore . and .. */
1139*7c478bd9Sstevel@tonic-gate 		if ((strcmp(dep->d_name, ".") == 0) ||
1140*7c478bd9Sstevel@tonic-gate 		    (strcmp(dep->d_name, "..") == 0))
1141*7c478bd9Sstevel@tonic-gate 			continue;
1142*7c478bd9Sstevel@tonic-gate 
1143*7c478bd9Sstevel@tonic-gate 		/* ignore cachefs special files */
1144*7c478bd9Sstevel@tonic-gate 		xx = strncmp(dep->d_name, CACHEFS_PREFIX, CACHEFS_PREFIX_LEN);
1145*7c478bd9Sstevel@tonic-gate 		if (xx == 0)
1146*7c478bd9Sstevel@tonic-gate 			continue;
1147*7c478bd9Sstevel@tonic-gate 
1148*7c478bd9Sstevel@tonic-gate 		hitem.key = dep->d_name;
1149*7c478bd9Sstevel@tonic-gate 		hitem.data = NULL;
1150*7c478bd9Sstevel@tonic-gate 		if (hsearch(hitem, FIND) == NULL) {
1151*7c478bd9Sstevel@tonic-gate 			sprintf(buf, "%s/%s", dirpath, dep->d_name);
1152*7c478bd9Sstevel@tonic-gate 			if (verbose) {
1153*7c478bd9Sstevel@tonic-gate 				printf("Unreferenced dir %s\n", buf);
1154*7c478bd9Sstevel@tonic-gate 			}
1155*7c478bd9Sstevel@tonic-gate 			xx = nftw64(buf, tree_remove, 3, FLAGS_FTW);
1156*7c478bd9Sstevel@tonic-gate 			if (xx != 0) {
1157*7c478bd9Sstevel@tonic-gate 				pr_err(gettext("Could not remove %s"), buf);
1158*7c478bd9Sstevel@tonic-gate 				error = 39;
1159*7c478bd9Sstevel@tonic-gate 				closedir(dp);
1160*7c478bd9Sstevel@tonic-gate 				goto out;
1161*7c478bd9Sstevel@tonic-gate 			}
1162*7c478bd9Sstevel@tonic-gate 		}
1163*7c478bd9Sstevel@tonic-gate 	}
1164*7c478bd9Sstevel@tonic-gate 	closedir(dp);
1165*7c478bd9Sstevel@tonic-gate 
1166*7c478bd9Sstevel@tonic-gate 	/* add the info file to the resource */
1167*7c478bd9Sstevel@tonic-gate 	res_addfile(resp, 1);
1168*7c478bd9Sstevel@tonic-gate 
1169*7c478bd9Sstevel@tonic-gate 	/* add the directory to the resources */
1170*7c478bd9Sstevel@tonic-gate 	res_addfile(resp, 1);
1171*7c478bd9Sstevel@tonic-gate 
1172*7c478bd9Sstevel@tonic-gate 	/* add the sym link to the resources */
1173*7c478bd9Sstevel@tonic-gate 	res_addfile(resp, 1);
1174*7c478bd9Sstevel@tonic-gate 
1175*7c478bd9Sstevel@tonic-gate 	/* change the mode on the directory to indicate we visited it */
1176*7c478bd9Sstevel@tonic-gate 	xx = chmod(dirpath, 0777);
1177*7c478bd9Sstevel@tonic-gate 	if (xx == -1) {
1178*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Cannot chmod %s: %s"), dirpath,
1179*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
1180*7c478bd9Sstevel@tonic-gate 		error = 39;
1181*7c478bd9Sstevel@tonic-gate 		goto out;
1182*7c478bd9Sstevel@tonic-gate 	}
1183*7c478bd9Sstevel@tonic-gate 
1184*7c478bd9Sstevel@tonic-gate out:
1185*7c478bd9Sstevel@tonic-gate 	/* free up the heap allocated by the hash functions */
1186*7c478bd9Sstevel@tonic-gate 	if (hashsize != 0)
1187*7c478bd9Sstevel@tonic-gate 		hdestroy();
1188*7c478bd9Sstevel@tonic-gate 
1189*7c478bd9Sstevel@tonic-gate 	if (error == -1) {
1190*7c478bd9Sstevel@tonic-gate 		/* remove the sym link */
1191*7c478bd9Sstevel@tonic-gate 		xx = unlink(linkpath);
1192*7c478bd9Sstevel@tonic-gate 		if (xx == -1) {
1193*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Unable to remove %s: %s"), linkpath,
1194*7c478bd9Sstevel@tonic-gate 			    strerror(errno));
1195*7c478bd9Sstevel@tonic-gate 			error = 39;
1196*7c478bd9Sstevel@tonic-gate 		} else {
1197*7c478bd9Sstevel@tonic-gate 			error = 0;
1198*7c478bd9Sstevel@tonic-gate 		}
1199*7c478bd9Sstevel@tonic-gate 	}
1200*7c478bd9Sstevel@tonic-gate 
1201*7c478bd9Sstevel@tonic-gate 	return (error);
1202*7c478bd9Sstevel@tonic-gate }
1203*7c478bd9Sstevel@tonic-gate 
1204*7c478bd9Sstevel@tonic-gate /*
1205*7c478bd9Sstevel@tonic-gate  * Processes and fixes up the fsinfo file.
1206*7c478bd9Sstevel@tonic-gate  */
1207*7c478bd9Sstevel@tonic-gate int
process_fsinfo(char * namep,ino64_t maxlocalfileno,cachefs_fsinfo_t * fsinfop,int verbose)1208*7c478bd9Sstevel@tonic-gate process_fsinfo(char *namep, ino64_t maxlocalfileno, cachefs_fsinfo_t *fsinfop,
1209*7c478bd9Sstevel@tonic-gate     int verbose)
1210*7c478bd9Sstevel@tonic-gate {
1211*7c478bd9Sstevel@tonic-gate 	int fd;
1212*7c478bd9Sstevel@tonic-gate 	int error;
1213*7c478bd9Sstevel@tonic-gate 	cachefs_fsinfo_t fsinfo;
1214*7c478bd9Sstevel@tonic-gate 	int xx;
1215*7c478bd9Sstevel@tonic-gate 
1216*7c478bd9Sstevel@tonic-gate 	/* open the info file; this file will be <2GB */
1217*7c478bd9Sstevel@tonic-gate 	fd = open(namep, O_RDWR);
1218*7c478bd9Sstevel@tonic-gate 	if (fd == -1) {
1219*7c478bd9Sstevel@tonic-gate 		error = errno;
1220*7c478bd9Sstevel@tonic-gate 		if (verbose)
1221*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Could not open %s: %s"),
1222*7c478bd9Sstevel@tonic-gate 			    namep, strerror(errno));
1223*7c478bd9Sstevel@tonic-gate 		if (error != ENOENT)
1224*7c478bd9Sstevel@tonic-gate 			return (-1);
1225*7c478bd9Sstevel@tonic-gate 
1226*7c478bd9Sstevel@tonic-gate 		/* try to create the info file */
1227*7c478bd9Sstevel@tonic-gate 		fd = open(namep, O_RDWR | O_CREAT, 0666);
1228*7c478bd9Sstevel@tonic-gate 		if (fd == -1) {
1229*7c478bd9Sstevel@tonic-gate 			if (verbose)
1230*7c478bd9Sstevel@tonic-gate 				pr_err(gettext("Could not create %s: %s"),
1231*7c478bd9Sstevel@tonic-gate 				    namep, strerror(errno));
1232*7c478bd9Sstevel@tonic-gate 			return (-1);
1233*7c478bd9Sstevel@tonic-gate 		}
1234*7c478bd9Sstevel@tonic-gate 
1235*7c478bd9Sstevel@tonic-gate 	}
1236*7c478bd9Sstevel@tonic-gate 
1237*7c478bd9Sstevel@tonic-gate 	/* read the contents of the info file */
1238*7c478bd9Sstevel@tonic-gate 	xx = read(fd, &fsinfo, sizeof (fsinfo));
1239*7c478bd9Sstevel@tonic-gate 	if (xx != sizeof (fsinfo)) {
1240*7c478bd9Sstevel@tonic-gate 		memset(&fsinfo, 0, sizeof (fsinfo));
1241*7c478bd9Sstevel@tonic-gate 	}
1242*7c478bd9Sstevel@tonic-gate 
1243*7c478bd9Sstevel@tonic-gate 	/* fix up the fields as necessary */
1244*7c478bd9Sstevel@tonic-gate 	if (fsinfo.fi_popsize < DEF_POP_SIZE)
1245*7c478bd9Sstevel@tonic-gate 		fsinfo.fi_popsize = DEF_POP_SIZE;
1246*7c478bd9Sstevel@tonic-gate 	if (fsinfo.fi_fgsize < DEF_FILEGRP_SIZE)
1247*7c478bd9Sstevel@tonic-gate 		fsinfo.fi_fgsize = DEF_FILEGRP_SIZE;
1248*7c478bd9Sstevel@tonic-gate 	if (fsinfo.fi_localfileno < maxlocalfileno)
1249*7c478bd9Sstevel@tonic-gate 		fsinfo.fi_localfileno = maxlocalfileno;
1250*7c478bd9Sstevel@tonic-gate 
1251*7c478bd9Sstevel@tonic-gate 	/* write back the info to the file */
1252*7c478bd9Sstevel@tonic-gate 	if (lseek(fd, 0, SEEK_SET) == -1) {
1253*7c478bd9Sstevel@tonic-gate 		if (verbose)
1254*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Could not lseek %s: %s"),
1255*7c478bd9Sstevel@tonic-gate 			    namep, strerror(errno));
1256*7c478bd9Sstevel@tonic-gate 		close(fd);
1257*7c478bd9Sstevel@tonic-gate 		return (-1);
1258*7c478bd9Sstevel@tonic-gate 	}
1259*7c478bd9Sstevel@tonic-gate 	xx = write(fd, &fsinfo, sizeof (fsinfo));
1260*7c478bd9Sstevel@tonic-gate 	if (xx != sizeof (fsinfo)) {
1261*7c478bd9Sstevel@tonic-gate 		if (verbose)
1262*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Could not write %s: %s"),
1263*7c478bd9Sstevel@tonic-gate 			    namep, strerror(errno));
1264*7c478bd9Sstevel@tonic-gate 		close(fd);
1265*7c478bd9Sstevel@tonic-gate 		return (-1);
1266*7c478bd9Sstevel@tonic-gate 	}
1267*7c478bd9Sstevel@tonic-gate 
1268*7c478bd9Sstevel@tonic-gate 	if (fsync(fd) == -1) {
1269*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Could not sync %s: %s"),
1270*7c478bd9Sstevel@tonic-gate 		    namep, strerror(errno));
1271*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
1272*7c478bd9Sstevel@tonic-gate 		return (-1);
1273*7c478bd9Sstevel@tonic-gate 	}
1274*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
1275*7c478bd9Sstevel@tonic-gate 	*fsinfop = fsinfo;
1276*7c478bd9Sstevel@tonic-gate 	return (0);
1277*7c478bd9Sstevel@tonic-gate }
1278*7c478bd9Sstevel@tonic-gate 
1279*7c478bd9Sstevel@tonic-gate /*
1280*7c478bd9Sstevel@tonic-gate  *
1281*7c478bd9Sstevel@tonic-gate  *			process_fsgroup
1282*7c478bd9Sstevel@tonic-gate  *
1283*7c478bd9Sstevel@tonic-gate  * Description:
1284*7c478bd9Sstevel@tonic-gate  *	Performs the necessary checking and repair on the
1285*7c478bd9Sstevel@tonic-gate  *	specified file group directory.
1286*7c478bd9Sstevel@tonic-gate  *	Calls res_addfile and res_addident as appropriate.
1287*7c478bd9Sstevel@tonic-gate  * Arguments:
1288*7c478bd9Sstevel@tonic-gate  *	dirpath	pathname to fscache directory
1289*7c478bd9Sstevel@tonic-gate  *	namep	name of fsgroup
1290*7c478bd9Sstevel@tonic-gate  *	resp	res object for res_addfile and res_addident calls
1291*7c478bd9Sstevel@tonic-gate  *	base	base offset for file numbers in this directory
1292*7c478bd9Sstevel@tonic-gate  *	fgsize	size of the file groups
1293*7c478bd9Sstevel@tonic-gate  *	fsid	file system id
1294*7c478bd9Sstevel@tonic-gate  *	local	1 if fsgroup dir is a local dir
1295*7c478bd9Sstevel@tonic-gate  *	verbose		indicate level of verbosity for diagnostics
1296*7c478bd9Sstevel@tonic-gate  * Returns:
1297*7c478bd9Sstevel@tonic-gate  *		 0	file system is okay and does not need checking
1298*7c478bd9Sstevel@tonic-gate  *		 1	problem unrelated to the file system
1299*7c478bd9Sstevel@tonic-gate  *		32	file system is unmounted and needs checking
1300*7c478bd9Sstevel@tonic-gate  *		33	file system is already mounted
1301*7c478bd9Sstevel@tonic-gate  *		34	cannot stat device
1302*7c478bd9Sstevel@tonic-gate  *		36	uncorrectable errors detected - terminate normally
1303*7c478bd9Sstevel@tonic-gate  *		37	a signal was caught during processing
1304*7c478bd9Sstevel@tonic-gate  *		39	uncorrectable errors detected - terminate  immediately
1305*7c478bd9Sstevel@tonic-gate  * Preconditions:
1306*7c478bd9Sstevel@tonic-gate  *	precond(dirp)
1307*7c478bd9Sstevel@tonic-gate  *	precond(namep)
1308*7c478bd9Sstevel@tonic-gate  *	precond(resp)
1309*7c478bd9Sstevel@tonic-gate  *	precond(fgsize > 0)
1310*7c478bd9Sstevel@tonic-gate  */
1311*7c478bd9Sstevel@tonic-gate 
1312*7c478bd9Sstevel@tonic-gate int
process_fsgroup(char * dirp,char * namep,res * resp,ino64_t base,int fgsize,ino64_t fsid,int local,int verbose)1313*7c478bd9Sstevel@tonic-gate process_fsgroup(char *dirp, char *namep, res *resp, ino64_t base, int fgsize,
1314*7c478bd9Sstevel@tonic-gate     ino64_t fsid, int local, int verbose)
1315*7c478bd9Sstevel@tonic-gate {
1316*7c478bd9Sstevel@tonic-gate 	DIR *dp;
1317*7c478bd9Sstevel@tonic-gate 	struct dirent64 *dep;
1318*7c478bd9Sstevel@tonic-gate 	char buf[MAXPATHLEN];
1319*7c478bd9Sstevel@tonic-gate 	char attrfile[MAXPATHLEN];
1320*7c478bd9Sstevel@tonic-gate 	char attrdir[MAXPATHLEN];
1321*7c478bd9Sstevel@tonic-gate 	int xx;
1322*7c478bd9Sstevel@tonic-gate 	struct stat64 statinfo;
1323*7c478bd9Sstevel@tonic-gate 	char *atp = ATTRCACHE_NAME;
1324*7c478bd9Sstevel@tonic-gate 	void *addrp = MAP_FAILED;
1325*7c478bd9Sstevel@tonic-gate 	struct attrcache_header *ahp;
1326*7c478bd9Sstevel@tonic-gate 	struct attrcache_index *startp = NULL;
1327*7c478bd9Sstevel@tonic-gate 	struct attrcache_index *aip;
1328*7c478bd9Sstevel@tonic-gate 	uchar_t *bitp;
1329*7c478bd9Sstevel@tonic-gate 	int offlen;
1330*7c478bd9Sstevel@tonic-gate 	int bitlen;
1331*7c478bd9Sstevel@tonic-gate 	int fd;
1332*7c478bd9Sstevel@tonic-gate 	int offentry;
1333*7c478bd9Sstevel@tonic-gate 	int size;
1334*7c478bd9Sstevel@tonic-gate 	struct cachefs_metadata *metap;
1335*7c478bd9Sstevel@tonic-gate 	int index;
1336*7c478bd9Sstevel@tonic-gate 	char *strp;
1337*7c478bd9Sstevel@tonic-gate 	uint_t offset;
1338*7c478bd9Sstevel@tonic-gate 	int error = 0;
1339*7c478bd9Sstevel@tonic-gate 	ENTRY hitem;
1340*7c478bd9Sstevel@tonic-gate 	int nffs;
1341*7c478bd9Sstevel@tonic-gate 	int rlno;
1342*7c478bd9Sstevel@tonic-gate 	rl_entry_t ent;
1343*7c478bd9Sstevel@tonic-gate 	enum cachefs_rl_type which;
1344*7c478bd9Sstevel@tonic-gate 
1345*7c478bd9Sstevel@tonic-gate 	/* construct the name to the attribute file and front file dir */
1346*7c478bd9Sstevel@tonic-gate 	sprintf(attrfile, "%s/%s/%s", dirp, atp, namep);
1347*7c478bd9Sstevel@tonic-gate 	sprintf(attrdir, "%s/%s", dirp, namep);
1348*7c478bd9Sstevel@tonic-gate 
1349*7c478bd9Sstevel@tonic-gate 	/* get the size of the attribute file */
1350*7c478bd9Sstevel@tonic-gate 	xx = lstat64(attrfile, &statinfo);
1351*7c478bd9Sstevel@tonic-gate 	if (xx == -1) {
1352*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Could not stat %s: %s"), attrfile,
1353*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
1354*7c478bd9Sstevel@tonic-gate 		error = 39;
1355*7c478bd9Sstevel@tonic-gate 		goto out;
1356*7c478bd9Sstevel@tonic-gate 	}
1357*7c478bd9Sstevel@tonic-gate 
1358*7c478bd9Sstevel@tonic-gate 	offlen = sizeof (struct attrcache_index) * fgsize;
1359*7c478bd9Sstevel@tonic-gate 	bitlen = (sizeof (uchar_t) * fgsize + 7) / 8;
1360*7c478bd9Sstevel@tonic-gate 	/* attrfile will be <2GB */
1361*7c478bd9Sstevel@tonic-gate 	size = (int)statinfo.st_size;
1362*7c478bd9Sstevel@tonic-gate 	offentry = sizeof (struct attrcache_header) + offlen + bitlen;
1363*7c478bd9Sstevel@tonic-gate 
1364*7c478bd9Sstevel@tonic-gate 	/* if the attribute file is the wrong size */
1365*7c478bd9Sstevel@tonic-gate 	if (size < offentry) {
1366*7c478bd9Sstevel@tonic-gate 		error = -1;
1367*7c478bd9Sstevel@tonic-gate 		goto out;
1368*7c478bd9Sstevel@tonic-gate 	}
1369*7c478bd9Sstevel@tonic-gate 
1370*7c478bd9Sstevel@tonic-gate 	/* open the attribute file */
1371*7c478bd9Sstevel@tonic-gate 	fd = open(attrfile, O_RDWR);
1372*7c478bd9Sstevel@tonic-gate 	if (fd == -1) {
1373*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Could not open %s: %s"),
1374*7c478bd9Sstevel@tonic-gate 			attrfile, strerror(errno));
1375*7c478bd9Sstevel@tonic-gate 		error = 39;
1376*7c478bd9Sstevel@tonic-gate 		goto out;
1377*7c478bd9Sstevel@tonic-gate 	}
1378*7c478bd9Sstevel@tonic-gate 
1379*7c478bd9Sstevel@tonic-gate 	/* mmap the file into our address space */
1380*7c478bd9Sstevel@tonic-gate 	addrp = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1381*7c478bd9Sstevel@tonic-gate 	if (addrp == MAP_FAILED) {
1382*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Could not map %s: %s"),
1383*7c478bd9Sstevel@tonic-gate 			attrfile, strerror(errno));
1384*7c478bd9Sstevel@tonic-gate 		close(fd);
1385*7c478bd9Sstevel@tonic-gate 		error = 39;
1386*7c478bd9Sstevel@tonic-gate 		goto out;
1387*7c478bd9Sstevel@tonic-gate 	}
1388*7c478bd9Sstevel@tonic-gate 	close(fd);
1389*7c478bd9Sstevel@tonic-gate 
1390*7c478bd9Sstevel@tonic-gate 	/* set up pointers into mapped file */
1391*7c478bd9Sstevel@tonic-gate 	ahp = (struct attrcache_header *)addrp;
1392*7c478bd9Sstevel@tonic-gate 	startp = (struct attrcache_index *)(ahp + 1);
1393*7c478bd9Sstevel@tonic-gate 	bitp = (uchar_t *)((char *)startp + offlen);
1394*7c478bd9Sstevel@tonic-gate 
1395*7c478bd9Sstevel@tonic-gate 	/* clear the bitmap */
1396*7c478bd9Sstevel@tonic-gate 	memset(bitp, 0, bitlen);
1397*7c478bd9Sstevel@tonic-gate 
1398*7c478bd9Sstevel@tonic-gate 	/* fix number of allocated blocks value if necessary */
1399*7c478bd9Sstevel@tonic-gate 	xx = (size + MAXBSIZE - 1) / MAXBSIZE;
1400*7c478bd9Sstevel@tonic-gate 	if (xx != ahp->ach_nblks) {
1401*7c478bd9Sstevel@tonic-gate 		if (verbose) {
1402*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("File %s size wrong, old %d new %d:"
1403*7c478bd9Sstevel@tonic-gate 				"corrected."),
1404*7c478bd9Sstevel@tonic-gate 				attrfile, ahp->ach_nblks, xx);
1405*7c478bd9Sstevel@tonic-gate 		}
1406*7c478bd9Sstevel@tonic-gate 		ahp->ach_nblks = xx;
1407*7c478bd9Sstevel@tonic-gate 	}
1408*7c478bd9Sstevel@tonic-gate 	ahp->ach_nffs = 0;
1409*7c478bd9Sstevel@tonic-gate 	nffs = 0;
1410*7c478bd9Sstevel@tonic-gate 
1411*7c478bd9Sstevel@tonic-gate 	/* verify sanity of attribute file */
1412*7c478bd9Sstevel@tonic-gate 	ahp->ach_count = 0;
1413*7c478bd9Sstevel@tonic-gate 	for (index = 0; index < fgsize; index++) {
1414*7c478bd9Sstevel@tonic-gate 
1415*7c478bd9Sstevel@tonic-gate 		/* get next entry to work on */
1416*7c478bd9Sstevel@tonic-gate 		aip = startp + index;
1417*7c478bd9Sstevel@tonic-gate 
1418*7c478bd9Sstevel@tonic-gate 		/* save offset to data */
1419*7c478bd9Sstevel@tonic-gate 		offset = aip->ach_offset;
1420*7c478bd9Sstevel@tonic-gate 		aip->ach_offset = 0;
1421*7c478bd9Sstevel@tonic-gate 
1422*7c478bd9Sstevel@tonic-gate 		/* if entry not in use */
1423*7c478bd9Sstevel@tonic-gate 		if (aip->ach_written == 0)
1424*7c478bd9Sstevel@tonic-gate 			continue;
1425*7c478bd9Sstevel@tonic-gate 		aip->ach_written = 0;
1426*7c478bd9Sstevel@tonic-gate 
1427*7c478bd9Sstevel@tonic-gate 		/* if offset is out of range or invalid */
1428*7c478bd9Sstevel@tonic-gate 		if ((offset < offentry) ||
1429*7c478bd9Sstevel@tonic-gate 		    ((size - sizeof (struct cachefs_metadata)) < offset) ||
1430*7c478bd9Sstevel@tonic-gate 		    (offset & 3)) {
1431*7c478bd9Sstevel@tonic-gate 			if (verbose)
1432*7c478bd9Sstevel@tonic-gate 				pr_err(gettext("Offset %d invalid - index %d"),
1433*7c478bd9Sstevel@tonic-gate 				    offset, index);
1434*7c478bd9Sstevel@tonic-gate 			continue;
1435*7c478bd9Sstevel@tonic-gate 		}
1436*7c478bd9Sstevel@tonic-gate 
1437*7c478bd9Sstevel@tonic-gate 		/* get pointer to meta data */
1438*7c478bd9Sstevel@tonic-gate 		metap = (struct cachefs_metadata *)((char *)addrp + offset);
1439*7c478bd9Sstevel@tonic-gate 
1440*7c478bd9Sstevel@tonic-gate 		/* sanity check the meta data */
1441*7c478bd9Sstevel@tonic-gate 		if ((metap->md_vattr.va_nodeid != (base + (ino64_t)index)) ||
1442*7c478bd9Sstevel@tonic-gate 		    ((metap->md_flags & (MD_FILE | MD_POPULATED)) ==
1443*7c478bd9Sstevel@tonic-gate 		    MD_POPULATED) ||
1444*7c478bd9Sstevel@tonic-gate 		    ((metap->md_flags & MD_FILE) && (metap->md_rlno == 0)) ||
1445*7c478bd9Sstevel@tonic-gate 		    (metap->md_rltype < CACHEFS_RL_START) ||
1446*7c478bd9Sstevel@tonic-gate 		    (metap->md_rltype > CACHEFS_RL_END)) {
1447*7c478bd9Sstevel@tonic-gate 			if (verbose) {
1448*7c478bd9Sstevel@tonic-gate 				pr_err(gettext("Metadata corrupted %d"), index);
1449*7c478bd9Sstevel@tonic-gate 			}
1450*7c478bd9Sstevel@tonic-gate 			continue;
1451*7c478bd9Sstevel@tonic-gate 		}
1452*7c478bd9Sstevel@tonic-gate 
1453*7c478bd9Sstevel@tonic-gate 		/* if there is a front file */
1454*7c478bd9Sstevel@tonic-gate 		if (metap->md_flags & MD_FILE) {
1455*7c478bd9Sstevel@tonic-gate 			/* make sure front file is still there */
1456*7c478bd9Sstevel@tonic-gate 			if (local)
1457*7c478bd9Sstevel@tonic-gate 				sprintf(buf, "%s/L%016llx", attrdir,
1458*7c478bd9Sstevel@tonic-gate 				    base + (ino64_t)index);
1459*7c478bd9Sstevel@tonic-gate 			else
1460*7c478bd9Sstevel@tonic-gate 				sprintf(buf, "%s/%016llx", attrdir,
1461*7c478bd9Sstevel@tonic-gate 				    base + (ino64_t)index);
1462*7c478bd9Sstevel@tonic-gate 			if (access(buf, F_OK)) {
1463*7c478bd9Sstevel@tonic-gate 				if (verbose) {
1464*7c478bd9Sstevel@tonic-gate 					pr_err(gettext("File error %s %s"),
1465*7c478bd9Sstevel@tonic-gate 					    buf, strerror(errno));
1466*7c478bd9Sstevel@tonic-gate 				}
1467*7c478bd9Sstevel@tonic-gate 				continue;
1468*7c478bd9Sstevel@tonic-gate 			}
1469*7c478bd9Sstevel@tonic-gate 			nffs++;
1470*7c478bd9Sstevel@tonic-gate 
1471*7c478bd9Sstevel@tonic-gate 			/* make sure default ACL directory holder is there */
1472*7c478bd9Sstevel@tonic-gate 			if (metap->md_flags & MD_ACLDIR) {
1473*7c478bd9Sstevel@tonic-gate 				sprintf(buf, (local) ?
1474*7c478bd9Sstevel@tonic-gate 				    "%s/L%016llx.d" : "%s/%016llx.d",
1475*7c478bd9Sstevel@tonic-gate 				    attrdir, base + (ino64_t)index);
1476*7c478bd9Sstevel@tonic-gate 				if (access(buf, F_OK)) {
1477*7c478bd9Sstevel@tonic-gate 					if (verbose) {
1478*7c478bd9Sstevel@tonic-gate 						pr_err(gettext(
1479*7c478bd9Sstevel@tonic-gate 						    "File error %s %s"),
1480*7c478bd9Sstevel@tonic-gate 						    buf, strerror(errno));
1481*7c478bd9Sstevel@tonic-gate 					}
1482*7c478bd9Sstevel@tonic-gate 					continue;
1483*7c478bd9Sstevel@tonic-gate 				}
1484*7c478bd9Sstevel@tonic-gate 			}
1485*7c478bd9Sstevel@tonic-gate 		}
1486*7c478bd9Sstevel@tonic-gate 
1487*7c478bd9Sstevel@tonic-gate 		/* if using a rl slot */
1488*7c478bd9Sstevel@tonic-gate 		if (metap->md_rlno) {
1489*7c478bd9Sstevel@tonic-gate 			/* make sure not on an unusable list */
1490*7c478bd9Sstevel@tonic-gate 			if ((metap->md_rltype == CACHEFS_RL_NONE) ||
1491*7c478bd9Sstevel@tonic-gate 			    (metap->md_rltype == CACHEFS_RL_FREE)) {
1492*7c478bd9Sstevel@tonic-gate 				if (verbose) {
1493*7c478bd9Sstevel@tonic-gate 					pr_err(gettext("Bad list %d, %d"),
1494*7c478bd9Sstevel@tonic-gate 					    metap->md_rltype, index);
1495*7c478bd9Sstevel@tonic-gate 				}
1496*7c478bd9Sstevel@tonic-gate 				continue;
1497*7c478bd9Sstevel@tonic-gate 			}
1498*7c478bd9Sstevel@tonic-gate 
1499*7c478bd9Sstevel@tonic-gate 			/* move from the active to the gc list */
1500*7c478bd9Sstevel@tonic-gate 			if (metap->md_rltype == CACHEFS_RL_ACTIVE)
1501*7c478bd9Sstevel@tonic-gate 				metap->md_rltype = CACHEFS_RL_GC;
1502*7c478bd9Sstevel@tonic-gate 
1503*7c478bd9Sstevel@tonic-gate 			/* move from the mf to the modified list */
1504*7c478bd9Sstevel@tonic-gate 			if (metap->md_rltype == CACHEFS_RL_MF)
1505*7c478bd9Sstevel@tonic-gate 				metap->md_rltype = CACHEFS_RL_MODIFIED;
1506*7c478bd9Sstevel@tonic-gate 
1507*7c478bd9Sstevel@tonic-gate 			/* add to the resource file */
1508*7c478bd9Sstevel@tonic-gate 			ent.rl_attrc = 0;
1509*7c478bd9Sstevel@tonic-gate 			ent.rl_local = local;
1510*7c478bd9Sstevel@tonic-gate 			ent.rl_fsid = fsid;
1511*7c478bd9Sstevel@tonic-gate 			ent.rl_fileno = base + (ino64_t)index;
1512*7c478bd9Sstevel@tonic-gate 			ent.rl_current = metap->md_rltype;
1513*7c478bd9Sstevel@tonic-gate 			xx = res_addident(resp, metap->md_rlno, &ent,
1514*7c478bd9Sstevel@tonic-gate 			    metap->md_frontblks * MAXBSIZE,
1515*7c478bd9Sstevel@tonic-gate 			    (metap->md_flags & MD_FILE) ? 1 : 0);
1516*7c478bd9Sstevel@tonic-gate 			if (xx == -1) {
1517*7c478bd9Sstevel@tonic-gate 				if (verbose) {
1518*7c478bd9Sstevel@tonic-gate 					pr_err(gettext(
1519*7c478bd9Sstevel@tonic-gate 					    "File %s, bad rlno"), attrfile);
1520*7c478bd9Sstevel@tonic-gate 				}
1521*7c478bd9Sstevel@tonic-gate 				continue;
1522*7c478bd9Sstevel@tonic-gate 			}
1523*7c478bd9Sstevel@tonic-gate 			ahp->ach_nffs++;
1524*7c478bd9Sstevel@tonic-gate 		}
1525*7c478bd9Sstevel@tonic-gate 
1526*7c478bd9Sstevel@tonic-gate 		/* mark entry as valid */
1527*7c478bd9Sstevel@tonic-gate 		aip->ach_written = 1;
1528*7c478bd9Sstevel@tonic-gate 		aip->ach_offset = offset;
1529*7c478bd9Sstevel@tonic-gate 
1530*7c478bd9Sstevel@tonic-gate 		/* set bitmap for this entry */
1531*7c478bd9Sstevel@tonic-gate 		xx = (offset - offentry) / sizeof (struct cachefs_metadata);
1532*7c478bd9Sstevel@tonic-gate 		bitp[xx/8] |= 1 << (xx % 8);
1533*7c478bd9Sstevel@tonic-gate 
1534*7c478bd9Sstevel@tonic-gate 		/* bump number of active entries */
1535*7c478bd9Sstevel@tonic-gate 		ahp->ach_count += 1;
1536*7c478bd9Sstevel@tonic-gate 	}
1537*7c478bd9Sstevel@tonic-gate 
1538*7c478bd9Sstevel@tonic-gate 	/* loop reading the contents of the front file directory */
1539*7c478bd9Sstevel@tonic-gate 	dp = opendir(attrdir);
1540*7c478bd9Sstevel@tonic-gate 	while (dp && ((dep = readdir64(dp)) != NULL)) {
1541*7c478bd9Sstevel@tonic-gate 		int acldir;
1542*7c478bd9Sstevel@tonic-gate 
1543*7c478bd9Sstevel@tonic-gate 		/* ignore . and .. */
1544*7c478bd9Sstevel@tonic-gate 		if ((strcmp(dep->d_name, ".") == 0) ||
1545*7c478bd9Sstevel@tonic-gate 		    (strcmp(dep->d_name, "..") == 0))
1546*7c478bd9Sstevel@tonic-gate 			continue;
1547*7c478bd9Sstevel@tonic-gate 
1548*7c478bd9Sstevel@tonic-gate 		acldir = 0;
1549*7c478bd9Sstevel@tonic-gate 		xx = strlen(dep->d_name);
1550*7c478bd9Sstevel@tonic-gate 		/* check for valid ACL directory */
1551*7c478bd9Sstevel@tonic-gate 		if ((xx > 2) && (strcmp(dep->d_name + xx - 2, ".d") == 0)) {
1552*7c478bd9Sstevel@tonic-gate 			acldir = 1;
1553*7c478bd9Sstevel@tonic-gate 		} else if ((xx != 16) && (xx != 17)) {
1554*7c478bd9Sstevel@tonic-gate 			/*
1555*7c478bd9Sstevel@tonic-gate 			 * Bad file.
1556*7c478bd9Sstevel@tonic-gate 			 * Front file dir name is based on 64 bit inode number.
1557*7c478bd9Sstevel@tonic-gate 			 */
1558*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Unknown file %s/%s"),
1559*7c478bd9Sstevel@tonic-gate 				attrdir, dep->d_name);
1560*7c478bd9Sstevel@tonic-gate 			closedir(dp);
1561*7c478bd9Sstevel@tonic-gate 			error = 39;
1562*7c478bd9Sstevel@tonic-gate 			goto out;
1563*7c478bd9Sstevel@tonic-gate 		}
1564*7c478bd9Sstevel@tonic-gate 
1565*7c478bd9Sstevel@tonic-gate 		sprintf(buf, "%s/%s", attrdir, dep->d_name);
1566*7c478bd9Sstevel@tonic-gate 
1567*7c478bd9Sstevel@tonic-gate 		/* determine index into file group */
1568*7c478bd9Sstevel@tonic-gate 		if (*(dep->d_name) == 'L') {
1569*7c478bd9Sstevel@tonic-gate 			index = (int)(strtoull(dep->d_name + 1, &strp,
1570*7c478bd9Sstevel@tonic-gate 			    16) - base);
1571*7c478bd9Sstevel@tonic-gate 		} else {
1572*7c478bd9Sstevel@tonic-gate 			index = (int)(strtoull(dep->d_name, &strp, 16) - base);
1573*7c478bd9Sstevel@tonic-gate 		}
1574*7c478bd9Sstevel@tonic-gate 
1575*7c478bd9Sstevel@tonic-gate 		/* verify a valid file */
1576*7c478bd9Sstevel@tonic-gate 		if (((! acldir) && (*strp != '\0')) ||
1577*7c478bd9Sstevel@tonic-gate 		    ((acldir) && (strcmp(strp, ".d") != 0)) ||
1578*7c478bd9Sstevel@tonic-gate 		    (index < 0) || (fgsize <= index) ||
1579*7c478bd9Sstevel@tonic-gate 		    (startp[index].ach_written == 0)) {
1580*7c478bd9Sstevel@tonic-gate 			/* remove the file */
1581*7c478bd9Sstevel@tonic-gate 			xx = file_remove(buf, NULL, verbose);
1582*7c478bd9Sstevel@tonic-gate 			if (xx == -1) {
1583*7c478bd9Sstevel@tonic-gate 				error = 39;
1584*7c478bd9Sstevel@tonic-gate 				goto out;
1585*7c478bd9Sstevel@tonic-gate 			}
1586*7c478bd9Sstevel@tonic-gate 			continue;
1587*7c478bd9Sstevel@tonic-gate 		}
1588*7c478bd9Sstevel@tonic-gate 
1589*7c478bd9Sstevel@tonic-gate 		/* verify file should be there */
1590*7c478bd9Sstevel@tonic-gate 		aip = startp + index;
1591*7c478bd9Sstevel@tonic-gate 		offset = aip->ach_offset;
1592*7c478bd9Sstevel@tonic-gate 		metap = (struct cachefs_metadata *)((char *)addrp + offset);
1593*7c478bd9Sstevel@tonic-gate 		if (((metap->md_flags & MD_FILE) == 0) ||
1594*7c478bd9Sstevel@tonic-gate 		    ((acldir) && ((metap->md_flags & MD_ACLDIR) == 0))) {
1595*7c478bd9Sstevel@tonic-gate 			/* remove the file */
1596*7c478bd9Sstevel@tonic-gate 			if (acldir)
1597*7c478bd9Sstevel@tonic-gate 				xx = rmdir(buf);
1598*7c478bd9Sstevel@tonic-gate 			else
1599*7c478bd9Sstevel@tonic-gate 				xx = file_remove(buf, NULL, verbose);
1600*7c478bd9Sstevel@tonic-gate 			if (xx == -1) {
1601*7c478bd9Sstevel@tonic-gate 				error = 39;
1602*7c478bd9Sstevel@tonic-gate 				goto out;
1603*7c478bd9Sstevel@tonic-gate 			}
1604*7c478bd9Sstevel@tonic-gate 			continue;
1605*7c478bd9Sstevel@tonic-gate 		}
1606*7c478bd9Sstevel@tonic-gate 		if (! acldir)
1607*7c478bd9Sstevel@tonic-gate 			nffs--;
1608*7c478bd9Sstevel@tonic-gate 	}
1609*7c478bd9Sstevel@tonic-gate 
1610*7c478bd9Sstevel@tonic-gate 	/* close the directory */
1611*7c478bd9Sstevel@tonic-gate 	if (dp)
1612*7c478bd9Sstevel@tonic-gate 		closedir(dp);
1613*7c478bd9Sstevel@tonic-gate 
1614*7c478bd9Sstevel@tonic-gate 	/* if we did not find the correct number of front files in the dir */
1615*7c478bd9Sstevel@tonic-gate 	rlno = ahp->ach_rlno;
1616*7c478bd9Sstevel@tonic-gate 	if (nffs != 0) {
1617*7c478bd9Sstevel@tonic-gate 		if (verbose) {
1618*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Front file mismatch %d in %s"),
1619*7c478bd9Sstevel@tonic-gate 			    nffs, attrdir);
1620*7c478bd9Sstevel@tonic-gate 		}
1621*7c478bd9Sstevel@tonic-gate 		error = -1;
1622*7c478bd9Sstevel@tonic-gate 		goto out;
1623*7c478bd9Sstevel@tonic-gate 	}
1624*7c478bd9Sstevel@tonic-gate 
1625*7c478bd9Sstevel@tonic-gate 	/* add the attrcache file to the resouce file */
1626*7c478bd9Sstevel@tonic-gate 	which = (ahp->ach_nffs == 0) ? CACHEFS_RL_GC : CACHEFS_RL_ATTRFILE;
1627*7c478bd9Sstevel@tonic-gate 	ahp->ach_rl_current = which;
1628*7c478bd9Sstevel@tonic-gate 	ent.rl_attrc = 1;
1629*7c478bd9Sstevel@tonic-gate 	ent.rl_local = local;
1630*7c478bd9Sstevel@tonic-gate 	ent.rl_fsid = fsid;
1631*7c478bd9Sstevel@tonic-gate 	ent.rl_fileno = base;
1632*7c478bd9Sstevel@tonic-gate 	ent.rl_current = which;
1633*7c478bd9Sstevel@tonic-gate 	error = res_addident(resp, rlno, &ent, size, 1);
1634*7c478bd9Sstevel@tonic-gate 	if (error == -1) {
1635*7c478bd9Sstevel@tonic-gate 		if (verbose) {
1636*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("%s bad rlno %d\n"), attrfile, rlno);
1637*7c478bd9Sstevel@tonic-gate 		}
1638*7c478bd9Sstevel@tonic-gate 		goto out;
1639*7c478bd9Sstevel@tonic-gate 	} else if (ahp->ach_nffs > 0) {
1640*7c478bd9Sstevel@tonic-gate 		/* add the directory to the resources */
1641*7c478bd9Sstevel@tonic-gate 		res_addfile(resp, 1);
1642*7c478bd9Sstevel@tonic-gate 
1643*7c478bd9Sstevel@tonic-gate 		/* indicate that the file group directory is okay */
1644*7c478bd9Sstevel@tonic-gate 		hitem.key = strdup(namep);
1645*7c478bd9Sstevel@tonic-gate 		hitem.data = NULL;
1646*7c478bd9Sstevel@tonic-gate 		if (hsearch(hitem, ENTER) == NULL) {
1647*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Hash table full"));
1648*7c478bd9Sstevel@tonic-gate 			error = 39;
1649*7c478bd9Sstevel@tonic-gate 			goto out;
1650*7c478bd9Sstevel@tonic-gate 		}
1651*7c478bd9Sstevel@tonic-gate 	}
1652*7c478bd9Sstevel@tonic-gate 
1653*7c478bd9Sstevel@tonic-gate out:
1654*7c478bd9Sstevel@tonic-gate 	if (error == -1) {
1655*7c478bd9Sstevel@tonic-gate 		if (startp) {
1656*7c478bd9Sstevel@tonic-gate 			/* clear idents we created for this attrcache file */
1657*7c478bd9Sstevel@tonic-gate 			for (index = 0; index < fgsize; index++) {
1658*7c478bd9Sstevel@tonic-gate 				aip = startp + index;
1659*7c478bd9Sstevel@tonic-gate 				if (aip->ach_written == 0)
1660*7c478bd9Sstevel@tonic-gate 					continue;
1661*7c478bd9Sstevel@tonic-gate 				metap = (struct cachefs_metadata *)((char *)
1662*7c478bd9Sstevel@tonic-gate 				    addrp + aip->ach_offset);
1663*7c478bd9Sstevel@tonic-gate 				if (metap->md_rlno != 0) {
1664*7c478bd9Sstevel@tonic-gate 					/* clear the resource file idents */
1665*7c478bd9Sstevel@tonic-gate 					res_clearident(resp, metap->md_rlno,
1666*7c478bd9Sstevel@tonic-gate 					    (metap->md_frontblks * MAXBSIZE),
1667*7c478bd9Sstevel@tonic-gate 					    (metap->md_flags & MD_FILE) ? 1:0);
1668*7c478bd9Sstevel@tonic-gate 					if (verbose) {
1669*7c478bd9Sstevel@tonic-gate 						pr_err(gettext("Removed %d"),
1670*7c478bd9Sstevel@tonic-gate 							metap->md_rlno);
1671*7c478bd9Sstevel@tonic-gate 					}
1672*7c478bd9Sstevel@tonic-gate 				}
1673*7c478bd9Sstevel@tonic-gate 			}
1674*7c478bd9Sstevel@tonic-gate 		}
1675*7c478bd9Sstevel@tonic-gate 
1676*7c478bd9Sstevel@tonic-gate 		/* nuke the attrcache file */
1677*7c478bd9Sstevel@tonic-gate 		xx = unlink(attrfile);
1678*7c478bd9Sstevel@tonic-gate 		if (xx == -1) {
1679*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Unable to remove %s"), attrfile);
1680*7c478bd9Sstevel@tonic-gate 			error = 39;
1681*7c478bd9Sstevel@tonic-gate 		} else {
1682*7c478bd9Sstevel@tonic-gate 			error = 0;
1683*7c478bd9Sstevel@tonic-gate 			if (verbose) {
1684*7c478bd9Sstevel@tonic-gate 				pr_err(gettext("Removed attrcache %s"),
1685*7c478bd9Sstevel@tonic-gate 					attrfile);
1686*7c478bd9Sstevel@tonic-gate 			}
1687*7c478bd9Sstevel@tonic-gate 		}
1688*7c478bd9Sstevel@tonic-gate 	}
1689*7c478bd9Sstevel@tonic-gate 
1690*7c478bd9Sstevel@tonic-gate 	if (msync(addrp, size, MS_SYNC) == -1) {
1691*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Unable to sync %s"), attrfile);
1692*7c478bd9Sstevel@tonic-gate 		error = 39;
1693*7c478bd9Sstevel@tonic-gate 	}
1694*7c478bd9Sstevel@tonic-gate 
1695*7c478bd9Sstevel@tonic-gate 	/* unmap the attribute file */
1696*7c478bd9Sstevel@tonic-gate 	if (addrp != MAP_FAILED)
1697*7c478bd9Sstevel@tonic-gate 		munmap(addrp, size);
1698*7c478bd9Sstevel@tonic-gate 
1699*7c478bd9Sstevel@tonic-gate 	return (error);
1700*7c478bd9Sstevel@tonic-gate }
1701*7c478bd9Sstevel@tonic-gate 
1702*7c478bd9Sstevel@tonic-gate /*
1703*7c478bd9Sstevel@tonic-gate  *
1704*7c478bd9Sstevel@tonic-gate  *			tree_remove
1705*7c478bd9Sstevel@tonic-gate  *
1706*7c478bd9Sstevel@tonic-gate  * Description:
1707*7c478bd9Sstevel@tonic-gate  *	Called via the nftw64(3c) routine, this routine removes
1708*7c478bd9Sstevel@tonic-gate  *	the specified file.
1709*7c478bd9Sstevel@tonic-gate  * Arguments:
1710*7c478bd9Sstevel@tonic-gate  *	namep	pathname to the file
1711*7c478bd9Sstevel@tonic-gate  *	statp	stat info on the file
1712*7c478bd9Sstevel@tonic-gate  *	type	ftw type information
1713*7c478bd9Sstevel@tonic-gate  *	ftwp	pointer to additional ftw information
1714*7c478bd9Sstevel@tonic-gate  * Returns:
1715*7c478bd9Sstevel@tonic-gate  *	Returns 0 for success or -1 if an error occurs.
1716*7c478bd9Sstevel@tonic-gate  * Preconditions:
1717*7c478bd9Sstevel@tonic-gate  *	precond(namep)
1718*7c478bd9Sstevel@tonic-gate  *	precond(statp)
1719*7c478bd9Sstevel@tonic-gate  *	precond(ftwp)
1720*7c478bd9Sstevel@tonic-gate  */
1721*7c478bd9Sstevel@tonic-gate 
1722*7c478bd9Sstevel@tonic-gate int
tree_remove(const char * namep,const struct stat64 * statp,int type,struct FTW * ftwp)1723*7c478bd9Sstevel@tonic-gate tree_remove(const char *namep, const struct stat64 *statp, int type,
1724*7c478bd9Sstevel@tonic-gate     struct FTW *ftwp)
1725*7c478bd9Sstevel@tonic-gate {
1726*7c478bd9Sstevel@tonic-gate 	int xx;
1727*7c478bd9Sstevel@tonic-gate 
1728*7c478bd9Sstevel@tonic-gate 	switch (type) {
1729*7c478bd9Sstevel@tonic-gate 	case FTW_D:
1730*7c478bd9Sstevel@tonic-gate 	case FTW_DP:
1731*7c478bd9Sstevel@tonic-gate 	case FTW_DNR:
1732*7c478bd9Sstevel@tonic-gate 		xx = rmdir(namep);
1733*7c478bd9Sstevel@tonic-gate 		if (xx != 0) {
1734*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Could not remove directory %s: %s"),
1735*7c478bd9Sstevel@tonic-gate 			    namep, strerror(errno));
1736*7c478bd9Sstevel@tonic-gate 			return (-1);
1737*7c478bd9Sstevel@tonic-gate 		}
1738*7c478bd9Sstevel@tonic-gate #if 0
1739*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Directory %s removed."), namep);
1740*7c478bd9Sstevel@tonic-gate #endif
1741*7c478bd9Sstevel@tonic-gate 		break;
1742*7c478bd9Sstevel@tonic-gate 
1743*7c478bd9Sstevel@tonic-gate 	default:
1744*7c478bd9Sstevel@tonic-gate 		xx = file_remove(namep, statp, S_verbose);
1745*7c478bd9Sstevel@tonic-gate #if 0
1746*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("File %s removed."), namep);
1747*7c478bd9Sstevel@tonic-gate #endif
1748*7c478bd9Sstevel@tonic-gate 		break;
1749*7c478bd9Sstevel@tonic-gate 	}
1750*7c478bd9Sstevel@tonic-gate 
1751*7c478bd9Sstevel@tonic-gate 	/* return success */
1752*7c478bd9Sstevel@tonic-gate 	return (0);
1753*7c478bd9Sstevel@tonic-gate }
1754*7c478bd9Sstevel@tonic-gate 
1755*7c478bd9Sstevel@tonic-gate /*
1756*7c478bd9Sstevel@tonic-gate  *
1757*7c478bd9Sstevel@tonic-gate  *			file_remove
1758*7c478bd9Sstevel@tonic-gate  *
1759*7c478bd9Sstevel@tonic-gate  * Description:
1760*7c478bd9Sstevel@tonic-gate  *	Removes the specified file.
1761*7c478bd9Sstevel@tonic-gate  *	If the file is a local file or has been modified locally
1762*7c478bd9Sstevel@tonic-gate  *	then it is moved to lost+found.
1763*7c478bd9Sstevel@tonic-gate  *	Should only be called for non-directory files.
1764*7c478bd9Sstevel@tonic-gate  * Arguments:
1765*7c478bd9Sstevel@tonic-gate  *	namep	pathname to the file
1766*7c478bd9Sstevel@tonic-gate  *	statp	stat info on the file or NULL
1767*7c478bd9Sstevel@tonic-gate  *	verbose	1 means be verbose about what is being removed
1768*7c478bd9Sstevel@tonic-gate  * Returns:
1769*7c478bd9Sstevel@tonic-gate  *	Returns 0 for success or -1 if an error occurs.
1770*7c478bd9Sstevel@tonic-gate  * Preconditions:
1771*7c478bd9Sstevel@tonic-gate  *	precond(namep)
1772*7c478bd9Sstevel@tonic-gate  */
1773*7c478bd9Sstevel@tonic-gate 
1774*7c478bd9Sstevel@tonic-gate int
file_remove(const char * namep,const struct stat64 * statp,int verbose)1775*7c478bd9Sstevel@tonic-gate file_remove(const char *namep, const struct stat64 *statp, int verbose)
1776*7c478bd9Sstevel@tonic-gate {
1777*7c478bd9Sstevel@tonic-gate 	int xx;
1778*7c478bd9Sstevel@tonic-gate 	int ii;
1779*7c478bd9Sstevel@tonic-gate 	struct stat64 statinfo;
1780*7c478bd9Sstevel@tonic-gate 	int dolf = 0;
1781*7c478bd9Sstevel@tonic-gate 	char newname[MAXPATHLEN * 2];
1782*7c478bd9Sstevel@tonic-gate 	char *strp;
1783*7c478bd9Sstevel@tonic-gate 
1784*7c478bd9Sstevel@tonic-gate 	/* get stat info on the file if we were not passed it */
1785*7c478bd9Sstevel@tonic-gate 	if (statp == NULL) {
1786*7c478bd9Sstevel@tonic-gate 		xx = stat64(namep, &statinfo);
1787*7c478bd9Sstevel@tonic-gate 		if (xx) {
1788*7c478bd9Sstevel@tonic-gate 			if (verbose) {
1789*7c478bd9Sstevel@tonic-gate 				pr_err(gettext("stat failed %s %d"),
1790*7c478bd9Sstevel@tonic-gate 				    namep, errno);
1791*7c478bd9Sstevel@tonic-gate 			}
1792*7c478bd9Sstevel@tonic-gate 			return (-1);
1793*7c478bd9Sstevel@tonic-gate 		}
1794*7c478bd9Sstevel@tonic-gate 		statp = &statinfo;
1795*7c478bd9Sstevel@tonic-gate 	}
1796*7c478bd9Sstevel@tonic-gate 
1797*7c478bd9Sstevel@tonic-gate 	/* ignore directories */
1798*7c478bd9Sstevel@tonic-gate 	if (S_ISDIR(statp->st_mode)) {
1799*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
1800*7c478bd9Sstevel@tonic-gate 		return (-1);
1801*7c478bd9Sstevel@tonic-gate 	}
1802*7c478bd9Sstevel@tonic-gate 
1803*7c478bd9Sstevel@tonic-gate 	/* if a local file then move to lost+found */
1804*7c478bd9Sstevel@tonic-gate 	strp = strrchr(namep, '/');
1805*7c478bd9Sstevel@tonic-gate 	if (strp == NULL) {
1806*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
1807*7c478bd9Sstevel@tonic-gate 		return (-1);
1808*7c478bd9Sstevel@tonic-gate 	}
1809*7c478bd9Sstevel@tonic-gate 	strp++;
1810*7c478bd9Sstevel@tonic-gate 	if (*strp == 'L')
1811*7c478bd9Sstevel@tonic-gate 		dolf = 1;
1812*7c478bd9Sstevel@tonic-gate 
1813*7c478bd9Sstevel@tonic-gate 	/* if a modified file then move to lost+found */
1814*7c478bd9Sstevel@tonic-gate 	if ((statp->st_mode & S_IAMB) == 0766)
1815*7c478bd9Sstevel@tonic-gate 		dolf = 1;
1816*7c478bd9Sstevel@tonic-gate 
1817*7c478bd9Sstevel@tonic-gate 	/* if moving to lost+found */
1818*7c478bd9Sstevel@tonic-gate 	if (dolf) {
1819*7c478bd9Sstevel@tonic-gate 		sprintf(newname, "%s/%s", S_lostfound, strp);
1820*7c478bd9Sstevel@tonic-gate 		xx = stat64(newname, &statinfo);
1821*7c478bd9Sstevel@tonic-gate 		for (ii = 1; ((ii < 1000) && (xx == 0)); ii++) {
1822*7c478bd9Sstevel@tonic-gate 			sprintf(newname, "%s/%s_%d", S_lostfound, strp, ii);
1823*7c478bd9Sstevel@tonic-gate 			xx = stat64(newname, &statinfo);
1824*7c478bd9Sstevel@tonic-gate 		}
1825*7c478bd9Sstevel@tonic-gate 		xx = rename(namep, newname);
1826*7c478bd9Sstevel@tonic-gate 		if (xx) {
1827*7c478bd9Sstevel@tonic-gate 			pr_err(gettext("Could not move file %s to %s: %s"),
1828*7c478bd9Sstevel@tonic-gate 			    namep, newname, strerror(errno));
1829*7c478bd9Sstevel@tonic-gate 			exit(-1);
1830*7c478bd9Sstevel@tonic-gate 		}
1831*7c478bd9Sstevel@tonic-gate 		S_move_lostfound = 1;
1832*7c478bd9Sstevel@tonic-gate 		return (0);
1833*7c478bd9Sstevel@tonic-gate 	}
1834*7c478bd9Sstevel@tonic-gate 
1835*7c478bd9Sstevel@tonic-gate 	/* remove the file */
1836*7c478bd9Sstevel@tonic-gate 	xx = unlink(namep);
1837*7c478bd9Sstevel@tonic-gate 	if (xx == -1) {
1838*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Could not remove file %s: %s"),
1839*7c478bd9Sstevel@tonic-gate 		    namep, strerror(errno));
1840*7c478bd9Sstevel@tonic-gate 	} else if (verbose) {
1841*7c478bd9Sstevel@tonic-gate 		pr_err(gettext("Removed %s"), namep);
1842*7c478bd9Sstevel@tonic-gate 	}
1843*7c478bd9Sstevel@tonic-gate 
1844*7c478bd9Sstevel@tonic-gate 	return (0);
1845*7c478bd9Sstevel@tonic-gate }
1846*7c478bd9Sstevel@tonic-gate 
1847*7c478bd9Sstevel@tonic-gate void
cache_backmnt_cleanup(char * cachedirp,char * backmnt_namep)1848*7c478bd9Sstevel@tonic-gate cache_backmnt_cleanup(char *cachedirp, char *backmnt_namep)
1849*7c478bd9Sstevel@tonic-gate {
1850*7c478bd9Sstevel@tonic-gate 	DIR *dirp;
1851*7c478bd9Sstevel@tonic-gate 	struct dirent *entp;
1852*7c478bd9Sstevel@tonic-gate 	char dirname[MAXPATHLEN * 2];
1853*7c478bd9Sstevel@tonic-gate 
1854*7c478bd9Sstevel@tonic-gate 	/* open the directory */
1855*7c478bd9Sstevel@tonic-gate 	sprintf(dirname, "%s/%s", cachedirp, backmnt_namep);
1856*7c478bd9Sstevel@tonic-gate 	dirp = opendir(dirname);
1857*7c478bd9Sstevel@tonic-gate 	if (dirp == NULL)
1858*7c478bd9Sstevel@tonic-gate 		return;
1859*7c478bd9Sstevel@tonic-gate 
1860*7c478bd9Sstevel@tonic-gate 	/*
1861*7c478bd9Sstevel@tonic-gate 	 * Try to remove everything in the directory with rmdir.
1862*7c478bd9Sstevel@tonic-gate 	 * Should only be empty directories in here at this point.
1863*7c478bd9Sstevel@tonic-gate 	 * If not, do not worry about it.
1864*7c478bd9Sstevel@tonic-gate 	 */
1865*7c478bd9Sstevel@tonic-gate 	for (;;) {
1866*7c478bd9Sstevel@tonic-gate 		/* get the next dir entry */
1867*7c478bd9Sstevel@tonic-gate 		entp = readdir(dirp);
1868*7c478bd9Sstevel@tonic-gate 		if (entp == NULL)
1869*7c478bd9Sstevel@tonic-gate 			break;
1870*7c478bd9Sstevel@tonic-gate 
1871*7c478bd9Sstevel@tonic-gate 		/*
1872*7c478bd9Sstevel@tonic-gate 		 * Try and remove the directory.
1873*7c478bd9Sstevel@tonic-gate 		 * This will fail if there is anything in the dir,
1874*7c478bd9Sstevel@tonic-gate 		 * like a mounted file system.
1875*7c478bd9Sstevel@tonic-gate 		 */
1876*7c478bd9Sstevel@tonic-gate 		rmdir(entp->d_name);
1877*7c478bd9Sstevel@tonic-gate 	}
1878*7c478bd9Sstevel@tonic-gate 	closedir(dirp);
1879*7c478bd9Sstevel@tonic-gate }
1880