xref: /aosp_15_r20/external/fsck_msdos/check.c (revision 9558e6ac2e10ab0fef46fdd14187b840555f86f4)
1*9558e6acSTreehugger Robot /*-
2*9558e6acSTreehugger Robot  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*9558e6acSTreehugger Robot  *
4*9558e6acSTreehugger Robot  * Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank
5*9558e6acSTreehugger Robot  * Copyright (c) 1995 Martin Husemann
6*9558e6acSTreehugger Robot  *
7*9558e6acSTreehugger Robot  * Redistribution and use in source and binary forms, with or without
8*9558e6acSTreehugger Robot  * modification, are permitted provided that the following conditions
9*9558e6acSTreehugger Robot  * are met:
10*9558e6acSTreehugger Robot  * 1. Redistributions of source code must retain the above copyright
11*9558e6acSTreehugger Robot  *    notice, this list of conditions and the following disclaimer.
12*9558e6acSTreehugger Robot  * 2. Redistributions in binary form must reproduce the above copyright
13*9558e6acSTreehugger Robot  *    notice, this list of conditions and the following disclaimer in the
14*9558e6acSTreehugger Robot  *    documentation and/or other materials provided with the distribution.
15*9558e6acSTreehugger Robot  *
16*9558e6acSTreehugger Robot  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
17*9558e6acSTreehugger Robot  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*9558e6acSTreehugger Robot  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*9558e6acSTreehugger Robot  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20*9558e6acSTreehugger Robot  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21*9558e6acSTreehugger Robot  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22*9558e6acSTreehugger Robot  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23*9558e6acSTreehugger Robot  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*9558e6acSTreehugger Robot  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25*9558e6acSTreehugger Robot  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*9558e6acSTreehugger Robot  */
27*9558e6acSTreehugger Robot 
28*9558e6acSTreehugger Robot 
29*9558e6acSTreehugger Robot #include <sys/cdefs.h>
30*9558e6acSTreehugger Robot #ifndef lint
31*9558e6acSTreehugger Robot __RCSID("$NetBSD: check.c,v 1.14 2006/06/05 16:51:18 christos Exp $");
32*9558e6acSTreehugger Robot static const char rcsid[] =
33*9558e6acSTreehugger Robot   "$FreeBSD$";
34*9558e6acSTreehugger Robot #endif /* not lint */
35*9558e6acSTreehugger Robot 
36*9558e6acSTreehugger Robot #ifdef HAVE_LIBUTIL_H
37*9558e6acSTreehugger Robot #include <libutil.h>
38*9558e6acSTreehugger Robot #endif
39*9558e6acSTreehugger Robot #include <stdlib.h>
40*9558e6acSTreehugger Robot #include <string.h>
41*9558e6acSTreehugger Robot #include <stdio.h>
42*9558e6acSTreehugger Robot #include <unistd.h>
43*9558e6acSTreehugger Robot #include <fcntl.h>
44*9558e6acSTreehugger Robot 
45*9558e6acSTreehugger Robot #include "ext.h"
46*9558e6acSTreehugger Robot #include "fsutil.h"
47*9558e6acSTreehugger Robot 
48*9558e6acSTreehugger Robot int
checkfilesys(const char * fname)49*9558e6acSTreehugger Robot checkfilesys(const char *fname)
50*9558e6acSTreehugger Robot {
51*9558e6acSTreehugger Robot 	int dosfs;
52*9558e6acSTreehugger Robot 	struct bootblock boot;
53*9558e6acSTreehugger Robot 	struct fat_descriptor *fat = NULL;
54*9558e6acSTreehugger Robot 	int finish_dosdirsection=0;
55*9558e6acSTreehugger Robot 	int mod = 0;
56*9558e6acSTreehugger Robot 	int ret = 8;
57*9558e6acSTreehugger Robot 	int64_t freebytes;
58*9558e6acSTreehugger Robot 	int64_t badbytes;
59*9558e6acSTreehugger Robot 
60*9558e6acSTreehugger Robot 	rdonly = alwaysno;
61*9558e6acSTreehugger Robot 	if (!preen)
62*9558e6acSTreehugger Robot 		printf("** %s", fname);
63*9558e6acSTreehugger Robot 
64*9558e6acSTreehugger Robot 	dosfs = open(fname, rdonly ? O_RDONLY : O_RDWR, 0);
65*9558e6acSTreehugger Robot 	if (dosfs < 0 && !rdonly) {
66*9558e6acSTreehugger Robot 		dosfs = open(fname, O_RDONLY, 0);
67*9558e6acSTreehugger Robot 		if (dosfs >= 0)
68*9558e6acSTreehugger Robot 			pwarn(" (NO WRITE)\n");
69*9558e6acSTreehugger Robot 		else if (!preen)
70*9558e6acSTreehugger Robot 			printf("\n");
71*9558e6acSTreehugger Robot 		rdonly = 1;
72*9558e6acSTreehugger Robot 	} else if (!preen)
73*9558e6acSTreehugger Robot 		printf("\n");
74*9558e6acSTreehugger Robot 
75*9558e6acSTreehugger Robot 	if (dosfs < 0) {
76*9558e6acSTreehugger Robot 		perr("Can't open `%s'", fname);
77*9558e6acSTreehugger Robot 		printf("\n");
78*9558e6acSTreehugger Robot 		return 8;
79*9558e6acSTreehugger Robot 	}
80*9558e6acSTreehugger Robot 
81*9558e6acSTreehugger Robot 	if (readboot(dosfs, &boot) == FSFATAL) {
82*9558e6acSTreehugger Robot 		close(dosfs);
83*9558e6acSTreehugger Robot 		printf("\n");
84*9558e6acSTreehugger Robot 		return 8;
85*9558e6acSTreehugger Robot 	}
86*9558e6acSTreehugger Robot 
87*9558e6acSTreehugger Robot 	if (skipclean && preen && checkdirty(dosfs, &boot)) {
88*9558e6acSTreehugger Robot 		printf("%s: ", fname);
89*9558e6acSTreehugger Robot 		printf("FILESYSTEM CLEAN; SKIPPING CHECKS\n");
90*9558e6acSTreehugger Robot 		ret = 0;
91*9558e6acSTreehugger Robot 		goto out;
92*9558e6acSTreehugger Robot 	}
93*9558e6acSTreehugger Robot 
94*9558e6acSTreehugger Robot 	if (!preen)  {
95*9558e6acSTreehugger Robot 		printf("** Phase 1 - Read FAT and checking connectivity\n");
96*9558e6acSTreehugger Robot 	}
97*9558e6acSTreehugger Robot 
98*9558e6acSTreehugger Robot 	mod |= readfat(dosfs, &boot, &fat);
99*9558e6acSTreehugger Robot 	if (mod & FSFATAL) {
100*9558e6acSTreehugger Robot 		close(dosfs);
101*9558e6acSTreehugger Robot 		return 8;
102*9558e6acSTreehugger Robot 	}
103*9558e6acSTreehugger Robot 
104*9558e6acSTreehugger Robot 	if (!preen)
105*9558e6acSTreehugger Robot 		printf("** Phase 2 - Checking Directories\n");
106*9558e6acSTreehugger Robot 
107*9558e6acSTreehugger Robot 	mod |= resetDosDirSection(fat);
108*9558e6acSTreehugger Robot 	finish_dosdirsection = 1;
109*9558e6acSTreehugger Robot 	if (mod & FSFATAL)
110*9558e6acSTreehugger Robot 		goto out;
111*9558e6acSTreehugger Robot 	/* delay writing FATs */
112*9558e6acSTreehugger Robot 
113*9558e6acSTreehugger Robot 	mod |= handleDirTree(fat);
114*9558e6acSTreehugger Robot 	if (mod & FSFATAL)
115*9558e6acSTreehugger Robot 		goto out;
116*9558e6acSTreehugger Robot 
117*9558e6acSTreehugger Robot 	if (!preen)
118*9558e6acSTreehugger Robot 		printf("** Phase 3 - Checking for Lost Files\n");
119*9558e6acSTreehugger Robot 
120*9558e6acSTreehugger Robot 	mod |= checklost(fat);
121*9558e6acSTreehugger Robot 	if (mod & FSFATAL)
122*9558e6acSTreehugger Robot 		goto out;
123*9558e6acSTreehugger Robot 
124*9558e6acSTreehugger Robot 	/* now write the FATs */
125*9558e6acSTreehugger Robot 	if (mod & FSFATMOD) {
126*9558e6acSTreehugger Robot 		if (ask(1, "Update FATs")) {
127*9558e6acSTreehugger Robot 			mod |= writefat(fat);
128*9558e6acSTreehugger Robot 			if (mod & FSFATAL)
129*9558e6acSTreehugger Robot 				goto out;
130*9558e6acSTreehugger Robot 		} else
131*9558e6acSTreehugger Robot 			mod |= FSERROR;
132*9558e6acSTreehugger Robot 	}
133*9558e6acSTreehugger Robot 
134*9558e6acSTreehugger Robot 	freebytes = (int64_t)boot.NumFree * boot.ClusterSize;
135*9558e6acSTreehugger Robot 	badbytes = (int64_t)boot.NumBad * boot.ClusterSize;
136*9558e6acSTreehugger Robot 
137*9558e6acSTreehugger Robot #ifdef HAVE_LIBUTIL_H
138*9558e6acSTreehugger Robot 	char freestr[7], badstr[7];
139*9558e6acSTreehugger Robot 
140*9558e6acSTreehugger Robot 	humanize_number(freestr, sizeof(freestr), freebytes, "",
141*9558e6acSTreehugger Robot 	    HN_AUTOSCALE, HN_DECIMAL | HN_IEC_PREFIXES);
142*9558e6acSTreehugger Robot 	if (boot.NumBad) {
143*9558e6acSTreehugger Robot 		humanize_number(badstr, sizeof(badstr), badbytes, "",
144*9558e6acSTreehugger Robot 		    HN_AUTOSCALE, HN_B | HN_DECIMAL | HN_IEC_PREFIXES);
145*9558e6acSTreehugger Robot 
146*9558e6acSTreehugger Robot 		pwarn("%d files, %sB free (%d clusters), %sB bad (%d clusters)\n",
147*9558e6acSTreehugger Robot 		      boot.NumFiles, freestr, boot.NumFree,
148*9558e6acSTreehugger Robot 		      badstr, boot.NumBad);
149*9558e6acSTreehugger Robot 	} else {
150*9558e6acSTreehugger Robot 		pwarn("%d files, %sB free (%d clusters)\n",
151*9558e6acSTreehugger Robot 		      boot.NumFiles, freestr, boot.NumFree);
152*9558e6acSTreehugger Robot 	}
153*9558e6acSTreehugger Robot #else
154*9558e6acSTreehugger Robot 	if (boot.NumBad)
155*9558e6acSTreehugger Robot 		pwarn("%d files, %jd KiB free (%d clusters), %jd KiB bad (%d clusters)\n",
156*9558e6acSTreehugger Robot 		      boot.NumFiles, (intmax_t)freebytes / 1024, boot.NumFree,
157*9558e6acSTreehugger Robot 		      (intmax_t)badbytes / 1024, boot.NumBad);
158*9558e6acSTreehugger Robot 	else
159*9558e6acSTreehugger Robot 		pwarn("%d files, %jd KiB free (%d clusters)\n",
160*9558e6acSTreehugger Robot 		      boot.NumFiles, (intmax_t)freebytes / 1024, boot.NumFree);
161*9558e6acSTreehugger Robot #endif
162*9558e6acSTreehugger Robot 
163*9558e6acSTreehugger Robot 	if (mod && (mod & FSERROR) == 0) {
164*9558e6acSTreehugger Robot 		if (mod & FSDIRTY) {
165*9558e6acSTreehugger Robot 			if (ask(1, "MARK FILE SYSTEM CLEAN") == 0)
166*9558e6acSTreehugger Robot 				mod &= ~FSDIRTY;
167*9558e6acSTreehugger Robot 
168*9558e6acSTreehugger Robot 			if (mod & FSDIRTY) {
169*9558e6acSTreehugger Robot 				pwarn("MARKING FILE SYSTEM CLEAN\n");
170*9558e6acSTreehugger Robot 				mod |= cleardirty(fat);
171*9558e6acSTreehugger Robot 			} else {
172*9558e6acSTreehugger Robot 				pwarn("\n***** FILE SYSTEM IS LEFT MARKED AS DIRTY *****\n");
173*9558e6acSTreehugger Robot 				mod |= FSERROR; /* file system not clean */
174*9558e6acSTreehugger Robot 			}
175*9558e6acSTreehugger Robot 		}
176*9558e6acSTreehugger Robot 	}
177*9558e6acSTreehugger Robot 
178*9558e6acSTreehugger Robot 	if (mod & (FSFATAL | FSERROR))
179*9558e6acSTreehugger Robot 		goto out;
180*9558e6acSTreehugger Robot 
181*9558e6acSTreehugger Robot 	ret = 0;
182*9558e6acSTreehugger Robot 
183*9558e6acSTreehugger Robot     out:
184*9558e6acSTreehugger Robot 	if (finish_dosdirsection)
185*9558e6acSTreehugger Robot 		finishDosDirSection();
186*9558e6acSTreehugger Robot 	free(fat);
187*9558e6acSTreehugger Robot 	close(dosfs);
188*9558e6acSTreehugger Robot 
189*9558e6acSTreehugger Robot 	if (mod & (FSFATMOD|FSDIRMOD)){
190*9558e6acSTreehugger Robot 		pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n");
191*9558e6acSTreehugger Robot 		return 4;
192*9558e6acSTreehugger Robot 	}
193*9558e6acSTreehugger Robot 
194*9558e6acSTreehugger Robot 	return ret;
195*9558e6acSTreehugger Robot }
196