1*bc5a8259Sbeck /* $OpenBSD: check.c,v 1.21 2021/07/12 15:09:18 beck Exp $ */
2b099d67bSprovos /* $NetBSD: check.c,v 1.8 1997/10/17 11:19:29 ws Exp $ */
39646ab25Sderaadt
49646ab25Sderaadt /*
5b099d67bSprovos * Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank
69646ab25Sderaadt * Copyright (c) 1995 Martin Husemann
79646ab25Sderaadt *
89646ab25Sderaadt * Redistribution and use in source and binary forms, with or without
99646ab25Sderaadt * modification, are permitted provided that the following conditions
109646ab25Sderaadt * are met:
119646ab25Sderaadt * 1. Redistributions of source code must retain the above copyright
129646ab25Sderaadt * notice, this list of conditions and the following disclaimer.
139646ab25Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
149646ab25Sderaadt * notice, this list of conditions and the following disclaimer in the
159646ab25Sderaadt * documentation and/or other materials provided with the distribution.
169646ab25Sderaadt *
179646ab25Sderaadt * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
189646ab25Sderaadt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
199646ab25Sderaadt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
209646ab25Sderaadt * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
219646ab25Sderaadt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
229646ab25Sderaadt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239646ab25Sderaadt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249646ab25Sderaadt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259646ab25Sderaadt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
269646ab25Sderaadt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279646ab25Sderaadt */
289646ab25Sderaadt
29b9fc9a72Sderaadt #include <sys/types.h>
3098fba8a9Skrw #include <sys/ioctl.h>
3198fba8a9Skrw #include <sys/dkio.h>
3298fba8a9Skrw #include <sys/disklabel.h>
339646ab25Sderaadt #include <stdlib.h>
349646ab25Sderaadt #include <string.h>
359646ab25Sderaadt #include <ctype.h>
369646ab25Sderaadt #include <stdio.h>
379646ab25Sderaadt #include <unistd.h>
38b9fc9a72Sderaadt #include <limits.h>
399646ab25Sderaadt #include <fcntl.h>
404340e61fSmillert #include <util.h>
41c0c611b7Sderaadt #include <err.h>
429646ab25Sderaadt
439646ab25Sderaadt #include "ext.h"
449646ab25Sderaadt
4598fba8a9Skrw struct disklabel lab;
4698fba8a9Skrw
479646ab25Sderaadt int
checkfilesys(const char * fname)484e95fccfSderaadt checkfilesys(const char *fname)
499646ab25Sderaadt {
509646ab25Sderaadt int dosfs;
519646ab25Sderaadt struct bootblock boot;
529646ab25Sderaadt struct fatEntry *fat = NULL;
53549405c0Sjsing char *realdev;
549646ab25Sderaadt int i;
559646ab25Sderaadt int mod = 0;
569646ab25Sderaadt
57c9112980Sderaadt if (unveil("/dev", "rw") == -1)
58*bc5a8259Sbeck err(1, "unveil /dev");
59c9112980Sderaadt
609646ab25Sderaadt rdonly = alwaysno;
619646ab25Sderaadt
62549405c0Sjsing dosfs = opendev(fname, rdonly ? O_RDONLY : O_RDWR, 0, &realdev);
63df69c215Sderaadt if (dosfs == -1 && !rdonly) {
64549405c0Sjsing dosfs = opendev(fname, O_RDONLY, 0, &realdev);
659646ab25Sderaadt rdonly = 1;
66549405c0Sjsing }
67df69c215Sderaadt if (dosfs == -1) {
68dd133929Sthib xperror("Can't open");
69a0dbeb59Smillert return (8);
709646ab25Sderaadt }
719646ab25Sderaadt
72549405c0Sjsing if (!preen) {
73549405c0Sjsing printf("** %s", realdev);
74549405c0Sjsing if (strncmp(fname, realdev, PATH_MAX) != 0)
75549405c0Sjsing printf(" (%s)", fname);
76549405c0Sjsing if (rdonly)
77549405c0Sjsing printf(" (NO WRITE)");
78549405c0Sjsing printf("\n");
79549405c0Sjsing }
80549405c0Sjsing
81df69c215Sderaadt if (ioctl(dosfs, DIOCGDINFO, (char *)&lab) == -1)
8298fba8a9Skrw pfatal("can't read disk label for %s\n", fname);
8398fba8a9Skrw
84c0c611b7Sderaadt if (pledge("stdio", NULL) == -1)
85c0c611b7Sderaadt err(1, "pledge");
86c0c611b7Sderaadt
879646ab25Sderaadt if (readboot(dosfs, &boot) != FSOK) {
88a0dbeb59Smillert (void)close(dosfs);
89a0dbeb59Smillert return (8);
909646ab25Sderaadt }
919646ab25Sderaadt
92a4df0321Sderaadt if (!preen) {
93b099d67bSprovos if (boot.ValidFat < 0)
949646ab25Sderaadt printf("** Phase 1 - Read and Compare FATs\n");
95b099d67bSprovos else
96b099d67bSprovos printf("** Phase 1 - Read FAT\n");
97a4df0321Sderaadt }
989646ab25Sderaadt
99b099d67bSprovos mod |= readfat(dosfs, &boot, boot.ValidFat >= 0 ? boot.ValidFat : 0, &fat);
100b099d67bSprovos if (mod & FSFATAL) {
101b099d67bSprovos (void)close(dosfs);
102b099d67bSprovos return 8;
103b099d67bSprovos }
104b099d67bSprovos
105b099d67bSprovos if (boot.ValidFat < 0)
106b099d67bSprovos for (i = 1; i < boot.FATs; i++) {
1079646ab25Sderaadt struct fatEntry *currentFat;
1089646ab25Sderaadt mod |= readfat(dosfs, &boot, i, ¤tFat);
1099646ab25Sderaadt
1109646ab25Sderaadt if (mod & FSFATAL) {
1112a4cde9cSderaadt free(fat);
112a0dbeb59Smillert (void)close(dosfs);
113b099d67bSprovos return 8;
1149646ab25Sderaadt }
1159646ab25Sderaadt
116b099d67bSprovos mod |= comparefat(&boot, fat, currentFat, i);
1172a4cde9cSderaadt free(currentFat);
1189646ab25Sderaadt if (mod & FSFATAL) {
1192a4cde9cSderaadt free(fat);
120a0dbeb59Smillert (void)close(dosfs);
121a0dbeb59Smillert return (8);
1229646ab25Sderaadt }
1239646ab25Sderaadt }
1249646ab25Sderaadt
1259646ab25Sderaadt if (!preen)
1269646ab25Sderaadt printf("** Phase 2 - Check Cluster Chains\n");
1279646ab25Sderaadt
1289646ab25Sderaadt mod |= checkfat(&boot, fat);
1299646ab25Sderaadt if (mod & FSFATAL) {
1302a4cde9cSderaadt free(fat);
131a0dbeb59Smillert (void)close(dosfs);
132a0dbeb59Smillert return (8);
1339646ab25Sderaadt }
1349646ab25Sderaadt
1359646ab25Sderaadt if (mod & FSFATMOD)
1369646ab25Sderaadt mod |= writefat(dosfs, &boot, fat); /* delay writing fats? XXX */
1379646ab25Sderaadt if (mod & FSFATAL) {
1382a4cde9cSderaadt free(fat);
139a0dbeb59Smillert (void)close(dosfs);
140a0dbeb59Smillert return (8);
1419646ab25Sderaadt }
1429646ab25Sderaadt
1439646ab25Sderaadt if (!preen)
144ca38d4f6Saaron printf("** Phase 3 - Check Directories\n");
1459646ab25Sderaadt
146b099d67bSprovos mod |= resetDosDirSection(&boot, fat);
147b099d67bSprovos if (mod & FSFATAL) {
148b099d67bSprovos free(fat);
149b099d67bSprovos close(dosfs);
150b099d67bSprovos return 8;
151b099d67bSprovos }
152b099d67bSprovos
153b099d67bSprovos if (mod & FSFATMOD)
154b099d67bSprovos mod |= writefat(dosfs, &boot, fat); /* delay writing fats? XXX */
155b099d67bSprovos if (mod & FSFATAL) {
156b099d67bSprovos finishDosDirSection();
1572a4cde9cSderaadt free(fat);
158a0dbeb59Smillert (void)close(dosfs);
159a0dbeb59Smillert return (8);
1609646ab25Sderaadt }
1619646ab25Sderaadt
1622a4cde9cSderaadt mod |= handleDirTree(dosfs, &boot, fat);
1639646ab25Sderaadt if (mod & FSFATAL) {
1649646ab25Sderaadt finishDosDirSection();
1652a4cde9cSderaadt free(fat);
166a0dbeb59Smillert (void)close(dosfs);
167a0dbeb59Smillert return (8);
1682a4cde9cSderaadt }
1699646ab25Sderaadt
1709646ab25Sderaadt if (!preen)
171ca38d4f6Saaron printf("** Phase 4 - Check for Lost Files\n");
1729646ab25Sderaadt
1732a4cde9cSderaadt mod |= checklost(dosfs, &boot, fat);
174b099d67bSprovos if (mod & FSFATAL) {
175b099d67bSprovos finishDosDirSection();
176b099d67bSprovos free(fat);
177b099d67bSprovos (void)close(dosfs);
178b099d67bSprovos return 8;
179b099d67bSprovos }
180b099d67bSprovos
181b099d67bSprovos if (mod & FSFATMOD)
182b099d67bSprovos mod |= writefat(dosfs, &boot, fat); /* delay writing fats? XXX */
1839646ab25Sderaadt
1842a4cde9cSderaadt finishDosDirSection();
1852a4cde9cSderaadt free(fat);
186a0dbeb59Smillert (void)close(dosfs);
187b099d67bSprovos if (mod & FSFATAL)
188b099d67bSprovos return 8;
1892a4cde9cSderaadt
190c7481c7eSmillert if (boot.NumBad)
191c7481c7eSmillert pwarn("%d files, %d free (%d clusters), %d bad (%d clusters)\n",
192c7481c7eSmillert boot.NumFiles,
193c7481c7eSmillert boot.NumFree * boot.ClusterSize / 1024, boot.NumFree,
194c7481c7eSmillert boot.NumBad * boot.ClusterSize / 1024, boot.NumBad);
195c7481c7eSmillert else
1969646ab25Sderaadt pwarn("%d files, %d free (%d clusters)\n",
197c7481c7eSmillert boot.NumFiles,
198c7481c7eSmillert boot.NumFree * boot.ClusterSize / 1024, boot.NumFree);
199b099d67bSprovos
2009646ab25Sderaadt if (mod & (FSFATAL | FSERROR))
201a0dbeb59Smillert return (8);
2029646ab25Sderaadt if (mod) {
2039646ab25Sderaadt pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n");
204a0dbeb59Smillert return (4);
2059646ab25Sderaadt }
206a0dbeb59Smillert return (0);
2079646ab25Sderaadt }
208