xref: /openbsd/sbin/fsck_msdos/check.c (revision bc5a8259)
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, &currentFat);
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