xref: /openbsd/sbin/fsck_msdos/check.c (revision b9fc9a72)
1*b9fc9a72Sderaadt /*	$OpenBSD: check.c,v 1.17 2015/01/16 06:39:58 deraadt 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 
29*b9fc9a72Sderaadt #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>
38*b9fc9a72Sderaadt #include <limits.h>
399646ab25Sderaadt #include <fcntl.h>
404340e61fSmillert #include <util.h>
419646ab25Sderaadt 
429646ab25Sderaadt #include "ext.h"
439646ab25Sderaadt 
4498fba8a9Skrw struct disklabel lab;
4598fba8a9Skrw 
469646ab25Sderaadt int
474e95fccfSderaadt checkfilesys(const char *fname)
489646ab25Sderaadt {
499646ab25Sderaadt 	int dosfs;
509646ab25Sderaadt 	struct bootblock boot;
519646ab25Sderaadt 	struct fatEntry *fat = NULL;
52549405c0Sjsing 	char *realdev;
539646ab25Sderaadt 	int i;
549646ab25Sderaadt 	int mod = 0;
559646ab25Sderaadt 
569646ab25Sderaadt 	rdonly = alwaysno;
579646ab25Sderaadt 
58549405c0Sjsing 	dosfs = opendev(fname, rdonly ? O_RDONLY : O_RDWR, 0, &realdev);
599646ab25Sderaadt 	if (dosfs < 0 && !rdonly) {
60549405c0Sjsing 		dosfs = opendev(fname, O_RDONLY, 0, &realdev);
619646ab25Sderaadt 		rdonly = 1;
62549405c0Sjsing 	}
639646ab25Sderaadt 	if (dosfs < 0) {
64dd133929Sthib 		xperror("Can't open");
65a0dbeb59Smillert 		return (8);
669646ab25Sderaadt 	}
679646ab25Sderaadt 
68549405c0Sjsing 	if (!preen) {
69549405c0Sjsing 		printf("** %s", realdev);
70549405c0Sjsing 		if (strncmp(fname, realdev, PATH_MAX) != 0)
71549405c0Sjsing 			printf(" (%s)", fname);
72549405c0Sjsing 		if (rdonly)
73549405c0Sjsing 			printf(" (NO WRITE)");
74549405c0Sjsing 		printf("\n");
75549405c0Sjsing 	}
76549405c0Sjsing 
7798fba8a9Skrw 	if (ioctl(dosfs, DIOCGDINFO, (char *)&lab) < 0)
7898fba8a9Skrw 		pfatal("can't read disk label for %s\n", fname);
7998fba8a9Skrw 
809646ab25Sderaadt 	if (readboot(dosfs, &boot) != FSOK) {
81a0dbeb59Smillert 		(void)close(dosfs);
82a0dbeb59Smillert 		return (8);
839646ab25Sderaadt 	}
849646ab25Sderaadt 
85a4df0321Sderaadt 	if (!preen) {
86b099d67bSprovos 		if (boot.ValidFat < 0)
879646ab25Sderaadt 			printf("** Phase 1 - Read and Compare FATs\n");
88b099d67bSprovos 		else
89b099d67bSprovos 			printf("** Phase 1 - Read FAT\n");
90a4df0321Sderaadt 	}
919646ab25Sderaadt 
92b099d67bSprovos 	mod |= readfat(dosfs, &boot, boot.ValidFat >= 0 ? boot.ValidFat : 0, &fat);
93b099d67bSprovos 	if (mod & FSFATAL) {
94b099d67bSprovos 		(void)close(dosfs);
95b099d67bSprovos 		return 8;
96b099d67bSprovos 	}
97b099d67bSprovos 
98b099d67bSprovos 	if (boot.ValidFat < 0)
99b099d67bSprovos 		for (i = 1; i < boot.FATs; i++) {
1009646ab25Sderaadt 			struct fatEntry *currentFat;
1019646ab25Sderaadt 			mod |= readfat(dosfs, &boot, i, &currentFat);
1029646ab25Sderaadt 
1039646ab25Sderaadt 			if (mod & FSFATAL) {
1042a4cde9cSderaadt 				free(fat);
105a0dbeb59Smillert 				(void)close(dosfs);
106b099d67bSprovos 				return 8;
1079646ab25Sderaadt 			}
1089646ab25Sderaadt 
109b099d67bSprovos 			mod |= comparefat(&boot, fat, currentFat, i);
1102a4cde9cSderaadt 			free(currentFat);
1119646ab25Sderaadt 			if (mod & FSFATAL) {
1122a4cde9cSderaadt 				free(fat);
113a0dbeb59Smillert 				(void)close(dosfs);
114a0dbeb59Smillert 				return (8);
1159646ab25Sderaadt 			}
1169646ab25Sderaadt 		}
1179646ab25Sderaadt 
1189646ab25Sderaadt 	if (!preen)
1199646ab25Sderaadt 		printf("** Phase 2 - Check Cluster Chains\n");
1209646ab25Sderaadt 
1219646ab25Sderaadt 	mod |= checkfat(&boot, fat);
1229646ab25Sderaadt 	if (mod & FSFATAL) {
1232a4cde9cSderaadt 		free(fat);
124a0dbeb59Smillert 		(void)close(dosfs);
125a0dbeb59Smillert 		return (8);
1269646ab25Sderaadt 	}
1279646ab25Sderaadt 
1289646ab25Sderaadt 	if (mod & FSFATMOD)
1299646ab25Sderaadt 		mod |= writefat(dosfs, &boot, fat); /* delay writing fats?	XXX */
1309646ab25Sderaadt 	if (mod & FSFATAL) {
1312a4cde9cSderaadt 		free(fat);
132a0dbeb59Smillert 		(void)close(dosfs);
133a0dbeb59Smillert 		return (8);
1349646ab25Sderaadt 	}
1359646ab25Sderaadt 
1369646ab25Sderaadt 	if (!preen)
137ca38d4f6Saaron 		printf("** Phase 3 - Check Directories\n");
1389646ab25Sderaadt 
139b099d67bSprovos 	mod |= resetDosDirSection(&boot, fat);
140b099d67bSprovos 	if (mod & FSFATAL) {
141b099d67bSprovos 		free(fat);
142b099d67bSprovos 		close(dosfs);
143b099d67bSprovos 		return 8;
144b099d67bSprovos 	}
145b099d67bSprovos 
146b099d67bSprovos 	if (mod & FSFATMOD)
147b099d67bSprovos 		mod |= writefat(dosfs, &boot, fat); /* delay writing fats?	XXX */
148b099d67bSprovos 	if (mod & FSFATAL) {
149b099d67bSprovos 		finishDosDirSection();
1502a4cde9cSderaadt 		free(fat);
151a0dbeb59Smillert 		(void)close(dosfs);
152a0dbeb59Smillert 		return (8);
1539646ab25Sderaadt 	}
1549646ab25Sderaadt 
1552a4cde9cSderaadt 	mod |= handleDirTree(dosfs, &boot, fat);
1569646ab25Sderaadt 	if (mod & FSFATAL) {
1579646ab25Sderaadt 		finishDosDirSection();
1582a4cde9cSderaadt 		free(fat);
159a0dbeb59Smillert 		(void)close(dosfs);
160a0dbeb59Smillert 		return (8);
1612a4cde9cSderaadt 	}
1629646ab25Sderaadt 
1639646ab25Sderaadt 	if (!preen)
164ca38d4f6Saaron 		printf("** Phase 4 - Check for Lost Files\n");
1659646ab25Sderaadt 
1662a4cde9cSderaadt 	mod |= checklost(dosfs, &boot, fat);
167b099d67bSprovos 	if (mod & FSFATAL) {
168b099d67bSprovos 		finishDosDirSection();
169b099d67bSprovos 		free(fat);
170b099d67bSprovos 		(void)close(dosfs);
171b099d67bSprovos 		return 8;
172b099d67bSprovos 	}
173b099d67bSprovos 
174b099d67bSprovos 	if (mod & FSFATMOD)
175b099d67bSprovos 		mod |= writefat(dosfs, &boot, fat); /* delay writing fats?    XXX */
1769646ab25Sderaadt 
1772a4cde9cSderaadt 	finishDosDirSection();
1782a4cde9cSderaadt 	free(fat);
179a0dbeb59Smillert 	(void)close(dosfs);
180b099d67bSprovos 	if (mod & FSFATAL)
181b099d67bSprovos 		return 8;
1822a4cde9cSderaadt 
183c7481c7eSmillert 	if (boot.NumBad)
184c7481c7eSmillert 		pwarn("%d files, %d free (%d clusters), %d bad (%d clusters)\n",
185c7481c7eSmillert 		      boot.NumFiles,
186c7481c7eSmillert 		      boot.NumFree * boot.ClusterSize / 1024, boot.NumFree,
187c7481c7eSmillert 		      boot.NumBad * boot.ClusterSize / 1024, boot.NumBad);
188c7481c7eSmillert 	else
1899646ab25Sderaadt 		pwarn("%d files, %d free (%d clusters)\n",
190c7481c7eSmillert 		      boot.NumFiles,
191c7481c7eSmillert 		      boot.NumFree * boot.ClusterSize / 1024, boot.NumFree);
192b099d67bSprovos 
1939646ab25Sderaadt 	if (mod & (FSFATAL | FSERROR))
194a0dbeb59Smillert 		return (8);
1959646ab25Sderaadt 	if (mod) {
1969646ab25Sderaadt 		pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n");
197a0dbeb59Smillert 		return (4);
1989646ab25Sderaadt 	}
199a0dbeb59Smillert 	return (0);
2009646ab25Sderaadt }
201