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