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