1 /* $OpenBSD: check.c,v 1.21 2021/07/12 15:09:18 beck Exp $ */
2 /* $NetBSD: check.c,v 1.8 1997/10/17 11:19:29 ws Exp $ */
3
4 /*
5 * Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank
6 * Copyright (c) 1995 Martin Husemann
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/types.h>
30 #include <sys/ioctl.h>
31 #include <sys/dkio.h>
32 #include <sys/disklabel.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include <stdio.h>
37 #include <unistd.h>
38 #include <limits.h>
39 #include <fcntl.h>
40 #include <util.h>
41 #include <err.h>
42
43 #include "ext.h"
44
45 struct disklabel lab;
46
47 int
checkfilesys(const char * fname)48 checkfilesys(const char *fname)
49 {
50 int dosfs;
51 struct bootblock boot;
52 struct fatEntry *fat = NULL;
53 char *realdev;
54 int i;
55 int mod = 0;
56
57 if (unveil("/dev", "rw") == -1)
58 err(1, "unveil /dev");
59
60 rdonly = alwaysno;
61
62 dosfs = opendev(fname, rdonly ? O_RDONLY : O_RDWR, 0, &realdev);
63 if (dosfs == -1 && !rdonly) {
64 dosfs = opendev(fname, O_RDONLY, 0, &realdev);
65 rdonly = 1;
66 }
67 if (dosfs == -1) {
68 xperror("Can't open");
69 return (8);
70 }
71
72 if (!preen) {
73 printf("** %s", realdev);
74 if (strncmp(fname, realdev, PATH_MAX) != 0)
75 printf(" (%s)", fname);
76 if (rdonly)
77 printf(" (NO WRITE)");
78 printf("\n");
79 }
80
81 if (ioctl(dosfs, DIOCGDINFO, (char *)&lab) == -1)
82 pfatal("can't read disk label for %s\n", fname);
83
84 if (pledge("stdio", NULL) == -1)
85 err(1, "pledge");
86
87 if (readboot(dosfs, &boot) != FSOK) {
88 (void)close(dosfs);
89 return (8);
90 }
91
92 if (!preen) {
93 if (boot.ValidFat < 0)
94 printf("** Phase 1 - Read and Compare FATs\n");
95 else
96 printf("** Phase 1 - Read FAT\n");
97 }
98
99 mod |= readfat(dosfs, &boot, boot.ValidFat >= 0 ? boot.ValidFat : 0, &fat);
100 if (mod & FSFATAL) {
101 (void)close(dosfs);
102 return 8;
103 }
104
105 if (boot.ValidFat < 0)
106 for (i = 1; i < boot.FATs; i++) {
107 struct fatEntry *currentFat;
108 mod |= readfat(dosfs, &boot, i, ¤tFat);
109
110 if (mod & FSFATAL) {
111 free(fat);
112 (void)close(dosfs);
113 return 8;
114 }
115
116 mod |= comparefat(&boot, fat, currentFat, i);
117 free(currentFat);
118 if (mod & FSFATAL) {
119 free(fat);
120 (void)close(dosfs);
121 return (8);
122 }
123 }
124
125 if (!preen)
126 printf("** Phase 2 - Check Cluster Chains\n");
127
128 mod |= checkfat(&boot, fat);
129 if (mod & FSFATAL) {
130 free(fat);
131 (void)close(dosfs);
132 return (8);
133 }
134
135 if (mod & FSFATMOD)
136 mod |= writefat(dosfs, &boot, fat); /* delay writing fats? XXX */
137 if (mod & FSFATAL) {
138 free(fat);
139 (void)close(dosfs);
140 return (8);
141 }
142
143 if (!preen)
144 printf("** Phase 3 - Check Directories\n");
145
146 mod |= resetDosDirSection(&boot, fat);
147 if (mod & FSFATAL) {
148 free(fat);
149 close(dosfs);
150 return 8;
151 }
152
153 if (mod & FSFATMOD)
154 mod |= writefat(dosfs, &boot, fat); /* delay writing fats? XXX */
155 if (mod & FSFATAL) {
156 finishDosDirSection();
157 free(fat);
158 (void)close(dosfs);
159 return (8);
160 }
161
162 mod |= handleDirTree(dosfs, &boot, fat);
163 if (mod & FSFATAL) {
164 finishDosDirSection();
165 free(fat);
166 (void)close(dosfs);
167 return (8);
168 }
169
170 if (!preen)
171 printf("** Phase 4 - Check for Lost Files\n");
172
173 mod |= checklost(dosfs, &boot, fat);
174 if (mod & FSFATAL) {
175 finishDosDirSection();
176 free(fat);
177 (void)close(dosfs);
178 return 8;
179 }
180
181 if (mod & FSFATMOD)
182 mod |= writefat(dosfs, &boot, fat); /* delay writing fats? XXX */
183
184 finishDosDirSection();
185 free(fat);
186 (void)close(dosfs);
187 if (mod & FSFATAL)
188 return 8;
189
190 if (boot.NumBad)
191 pwarn("%d files, %d free (%d clusters), %d bad (%d clusters)\n",
192 boot.NumFiles,
193 boot.NumFree * boot.ClusterSize / 1024, boot.NumFree,
194 boot.NumBad * boot.ClusterSize / 1024, boot.NumBad);
195 else
196 pwarn("%d files, %d free (%d clusters)\n",
197 boot.NumFiles,
198 boot.NumFree * boot.ClusterSize / 1024, boot.NumFree);
199
200 if (mod & (FSFATAL | FSERROR))
201 return (8);
202 if (mod) {
203 pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n");
204 return (4);
205 }
206 return (0);
207 }
208