xref: /netbsd-src/sbin/fsck_msdos/check.c (revision c6dcfc105ba87eedd47752affa51e0cf000f5d42)
1*c6dcfc10Smlelstv /*	$NetBSD: check.c,v 1.20 2022/08/28 10:20:25 mlelstv Exp $	*/
26ae4c91aSws 
36ae4c91aSws /*
4d445160eSws  * Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank
56ae4c91aSws  * Copyright (c) 1995 Martin Husemann
66ae4c91aSws  *
76ae4c91aSws  * Redistribution and use in source and binary forms, with or without
86ae4c91aSws  * modification, are permitted provided that the following conditions
96ae4c91aSws  * are met:
106ae4c91aSws  * 1. Redistributions of source code must retain the above copyright
116ae4c91aSws  *    notice, this list of conditions and the following disclaimer.
126ae4c91aSws  * 2. Redistributions in binary form must reproduce the above copyright
136ae4c91aSws  *    notice, this list of conditions and the following disclaimer in the
146ae4c91aSws  *    documentation and/or other materials provided with the distribution.
156ae4c91aSws  *
166ae4c91aSws  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
176ae4c91aSws  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
186ae4c91aSws  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
196ae4c91aSws  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
206ae4c91aSws  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
216ae4c91aSws  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
226ae4c91aSws  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
236ae4c91aSws  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
246ae4c91aSws  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
256ae4c91aSws  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
266ae4c91aSws  */
276ae4c91aSws 
286ae4c91aSws 
295a94f674Slukem #include <sys/cdefs.h>
306ae4c91aSws #ifndef lint
31*c6dcfc10Smlelstv __RCSID("$NetBSD: check.c,v 1.20 2022/08/28 10:20:25 mlelstv Exp $");
326ae4c91aSws #endif /* not lint */
336ae4c91aSws 
346ae4c91aSws #include <stdlib.h>
356ae4c91aSws #include <string.h>
366ae4c91aSws #include <stdio.h>
376ae4c91aSws #include <unistd.h>
386ae4c91aSws #include <fcntl.h>
396ae4c91aSws 
406ae4c91aSws #include "ext.h"
41a0c84e7dSchristos #include "fsutil.h"
42742b48d5Schristos #include "exitvalues.h"
436ae4c91aSws 
446ae4c91aSws int
checkfilesys(const char * filename)4565e67723Sxtraeme checkfilesys(const char *filename)
466ae4c91aSws {
476ae4c91aSws 	int dosfs;
486ae4c91aSws 	struct bootblock boot;
496ae4c91aSws 	struct fatEntry *fat = NULL;
50a2b5923eSlukem 	int finish_dosdirsection=0;
51a2b5923eSlukem 	u_int i;
526ae4c91aSws 	int mod = 0;
53742b48d5Schristos 	int ret = FSCK_EXIT_CHECK_FAILED;
546ae4c91aSws 
556ae4c91aSws 	rdonly = alwaysno;
566ae4c91aSws 	if (!preen)
578e78c802Swiz 		printf("** %s", filename);
586ae4c91aSws 
598e78c802Swiz 	dosfs = open(filename, rdonly ? O_RDONLY : O_RDWR, 0);
606ae4c91aSws 	if (dosfs < 0 && !rdonly) {
618e78c802Swiz 		dosfs = open(filename, O_RDONLY, 0);
626ae4c91aSws 		if (dosfs >= 0)
636ae4c91aSws 			pwarn(" (NO WRITE)\n");
646ae4c91aSws 		else if (!preen)
656ae4c91aSws 			printf("\n");
666ae4c91aSws 		rdonly = 1;
676ae4c91aSws 	} else if (!preen)
686ae4c91aSws 		printf("\n");
696ae4c91aSws 
706ae4c91aSws 	if (dosfs < 0) {
7115f3040fSchristos 		perr("Can't open `%s'", filename);
72742b48d5Schristos 		return FSCK_EXIT_CHECK_FAILED;
736ae4c91aSws 	}
746ae4c91aSws 
75*c6dcfc10Smlelstv 	mod = readboot(dosfs, &boot);
76*c6dcfc10Smlelstv 	if (mod & FSFATAL) {
776ae4c91aSws 		close(dosfs);
783b81524aSabs 		printf("\n");
79742b48d5Schristos 		return FSCK_EXIT_CHECK_FAILED;
806ae4c91aSws 	}
816ae4c91aSws 
82029a64ccSross 	if (!preen)  {
83d445160eSws 		if (boot.ValidFat < 0)
846ae4c91aSws 			printf("** Phase 1 - Read and Compare FATs\n");
85d445160eSws 		else
86d445160eSws 			printf("** Phase 1 - Read FAT\n");
87029a64ccSross 	}
886ae4c91aSws 
89d445160eSws 	mod |= readfat(dosfs, &boot, boot.ValidFat >= 0 ? boot.ValidFat : 0, &fat);
90d445160eSws 	if (mod & FSFATAL) {
91d445160eSws 		close(dosfs);
92742b48d5Schristos 		return FSCK_EXIT_CHECK_FAILED;
93d445160eSws 	}
94d445160eSws 
95d445160eSws 	if (boot.ValidFat < 0)
96d445160eSws 		for (i = 1; i < boot.FATs; i++) {
976ae4c91aSws 			struct fatEntry *currentFat;
986ae4c91aSws 
996ae4c91aSws 			mod |= readfat(dosfs, &boot, i, &currentFat);
1006ae4c91aSws 
1014ab49897Sjdolecek 			if (mod & FSFATAL)
1024ab49897Sjdolecek 				goto out;
1036ae4c91aSws 
104d445160eSws 			mod |= comparefat(&boot, fat, currentFat, i);
10525e3d62eSws 			free(currentFat);
1064ab49897Sjdolecek 			if (mod & FSFATAL)
1074ab49897Sjdolecek 				goto out;
1086ae4c91aSws 		}
1096ae4c91aSws 
1106ae4c91aSws 	if (!preen)
1116ae4c91aSws 		printf("** Phase 2 - Check Cluster Chains\n");
1126ae4c91aSws 
1136ae4c91aSws 	mod |= checkfat(&boot, fat);
1144ab49897Sjdolecek 	if (mod & FSFATAL)
1154ab49897Sjdolecek 		goto out;
1164ab49897Sjdolecek 	/* delay writing FATs */
1176ae4c91aSws 
1186ae4c91aSws 	if (!preen)
1196ae4c91aSws 		printf("** Phase 3 - Checking Directories\n");
1206ae4c91aSws 
121d445160eSws 	mod |= resetDosDirSection(&boot, fat);
1224ab49897Sjdolecek 	finish_dosdirsection = 1;
1234ab49897Sjdolecek 	if (mod & FSFATAL)
1244ab49897Sjdolecek 		goto out;
1254ab49897Sjdolecek 	/* delay writing FATs */
1266ae4c91aSws 
12725e3d62eSws 	mod |= handleDirTree(dosfs, &boot, fat);
1284ab49897Sjdolecek 	if (mod & FSFATAL)
1294ab49897Sjdolecek 		goto out;
1306ae4c91aSws 
1316ae4c91aSws 	if (!preen)
1326ae4c91aSws 		printf("** Phase 4 - Checking for Lost Files\n");
1336ae4c91aSws 
13425e3d62eSws 	mod |= checklost(dosfs, &boot, fat);
135d445160eSws 	if (mod & FSFATAL)
1364ab49897Sjdolecek 		goto out;
1374ab49897Sjdolecek 
1384ab49897Sjdolecek 	/* now write the FATs */
139698f62dfSchristos 	if (mod & (FSFATMOD|FSFIXFAT)) {
1404ab49897Sjdolecek 		if (ask(1, "Update FATs")) {
1414ab49897Sjdolecek 			mod |= writefat(dosfs, &boot, fat, mod & FSFIXFAT);
1424ab49897Sjdolecek 			if (mod & FSFATAL)
1434ab49897Sjdolecek 				goto out;
1444ab49897Sjdolecek 		} else
1454ab49897Sjdolecek 			mod |= FSERROR;
1464ab49897Sjdolecek 	}
14725e3d62eSws 
148fdbcbfc2Sws 	if (boot.NumBad)
149fdbcbfc2Sws 		pwarn("%d files, %d free (%d clusters), %d bad (%d clusters)\n",
150fdbcbfc2Sws 		      boot.NumFiles,
151fdbcbfc2Sws 		      boot.NumFree * boot.ClusterSize / 1024, boot.NumFree,
152fdbcbfc2Sws 		      boot.NumBad * boot.ClusterSize / 1024, boot.NumBad);
153fdbcbfc2Sws 	else
1546ae4c91aSws 		pwarn("%d files, %d free (%d clusters)\n",
155fdbcbfc2Sws 		      boot.NumFiles,
156fdbcbfc2Sws 		      boot.NumFree * boot.ClusterSize / 1024, boot.NumFree);
157d445160eSws 
1584ab49897Sjdolecek 	if (mod && (mod & FSERROR) == 0) {
1594ab49897Sjdolecek 		if (mod & FSDIRTY) {
1604ab49897Sjdolecek 			if (ask(1, "MARK FILE SYSTEM CLEAN") == 0)
1614ab49897Sjdolecek 				mod &= ~FSDIRTY;
1624ab49897Sjdolecek 
1634ab49897Sjdolecek 			if (mod & FSDIRTY) {
1644ab49897Sjdolecek 				pwarn("MARKING FILE SYSTEM CLEAN\n");
1654ab49897Sjdolecek 				mod |= writefat(dosfs, &boot, fat, 1);
1664ab49897Sjdolecek 			} else {
1674ab49897Sjdolecek 				pwarn("\n***** FILE SYSTEM IS LEFT MARKED AS DIRTY *****\n");
1684ab49897Sjdolecek 				mod |= FSERROR; /* file system not clean */
1696ae4c91aSws 			}
1704ab49897Sjdolecek 		}
1714ab49897Sjdolecek 	}
1724ab49897Sjdolecek 
1734ab49897Sjdolecek 	if (mod & (FSFATAL | FSERROR))
1744ab49897Sjdolecek 		goto out;
1754ab49897Sjdolecek 
176742b48d5Schristos 	ret = FSCK_EXIT_OK;
1774ab49897Sjdolecek 
1784ab49897Sjdolecek     out:
1794ab49897Sjdolecek 	if (finish_dosdirsection)
1804ab49897Sjdolecek 		finishDosDirSection();
1814ab49897Sjdolecek 	free(fat);
1824ab49897Sjdolecek 	close(dosfs);
1834ab49897Sjdolecek 
1844ab49897Sjdolecek 	if (mod & (FSFATMOD|FSDIRMOD))
1854ab49897Sjdolecek 		pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n");
1864ab49897Sjdolecek 
1874ab49897Sjdolecek 	return ret;
1886ae4c91aSws }
189