Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sbin/fsck_msdosfs/check.c
39475 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank
5
* Copyright (c) 1995 Martin Husemann
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
17
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
*/
27
28
29
#include <sys/cdefs.h>
30
#ifndef lint
31
__RCSID("$NetBSD: check.c,v 1.14 2006/06/05 16:51:18 christos Exp $");
32
#endif /* not lint */
33
34
#ifdef HAVE_LIBUTIL_H
35
#include <libutil.h>
36
#endif
37
#include <stdlib.h>
38
#include <string.h>
39
#include <stdio.h>
40
#include <unistd.h>
41
#include <fcntl.h>
42
43
#include "ext.h"
44
#include "fsutil.h"
45
46
int
47
checkfilesys(const char *fname)
48
{
49
int dosfs;
50
struct bootblock boot;
51
struct fat_descriptor *fat = NULL;
52
int finish_dosdirsection=0;
53
int mod = 0;
54
int ret = 8;
55
int64_t freebytes;
56
int64_t badbytes;
57
58
rdonly = alwaysno;
59
if (!preen)
60
printf("** %s", fname);
61
62
dosfs = open(fname, rdonly ? O_RDONLY : O_RDWR, 0);
63
if (dosfs < 0 && !rdonly) {
64
dosfs = open(fname, O_RDONLY, 0);
65
if (dosfs >= 0)
66
pwarn(" (NO WRITE)\n");
67
else if (!preen)
68
printf("\n");
69
rdonly = 1;
70
} else if (!preen)
71
printf("\n");
72
73
if (dosfs < 0) {
74
perr("Can't open `%s'", fname);
75
printf("\n");
76
return 8;
77
}
78
79
if (readboot(dosfs, &boot) == FSFATAL) {
80
close(dosfs);
81
printf("\n");
82
return 8;
83
}
84
85
if (skipclean && preen && checkdirty(dosfs, &boot)) {
86
printf("%s: ", fname);
87
printf("FILESYSTEM CLEAN; SKIPPING CHECKS\n");
88
ret = 0;
89
goto out;
90
}
91
92
if (!preen) {
93
printf("** Phase 1 - Read FAT and checking connectivity\n");
94
}
95
96
mod |= readfat(dosfs, &boot, &fat);
97
if (mod & FSFATAL) {
98
close(dosfs);
99
return 8;
100
}
101
102
if (!preen)
103
printf("** Phase 2 - Checking Directories\n");
104
105
mod |= resetDosDirSection(fat);
106
finish_dosdirsection = 1;
107
if (mod & FSFATAL)
108
goto out;
109
/* delay writing FATs */
110
111
mod |= handleDirTree(fat);
112
if (mod & FSFATAL)
113
goto out;
114
115
if (!preen)
116
printf("** Phase 3 - Checking for Lost Files\n");
117
118
mod |= checklost(fat);
119
if (mod & FSFATAL)
120
goto out;
121
122
/* now write the FATs */
123
if (mod & FSFATMOD) {
124
if (ask(1, "Update FATs")) {
125
mod |= writefat(fat);
126
if (mod & FSFATAL)
127
goto out;
128
} else
129
mod |= FSERROR;
130
}
131
132
freebytes = (int64_t)boot.NumFree * boot.ClusterSize;
133
badbytes = (int64_t)boot.NumBad * boot.ClusterSize;
134
135
#ifdef HAVE_LIBUTIL_H
136
char freestr[7], badstr[7];
137
138
humanize_number(freestr, sizeof(freestr), freebytes, "",
139
HN_AUTOSCALE, HN_DECIMAL | HN_IEC_PREFIXES);
140
if (boot.NumBad) {
141
humanize_number(badstr, sizeof(badstr), badbytes, "",
142
HN_AUTOSCALE, HN_B | HN_DECIMAL | HN_IEC_PREFIXES);
143
144
pwarn("%d files, %sB free (%d clusters), %sB bad (%d clusters)\n",
145
boot.NumFiles, freestr, boot.NumFree,
146
badstr, boot.NumBad);
147
} else {
148
pwarn("%d files, %sB free (%d clusters)\n",
149
boot.NumFiles, freestr, boot.NumFree);
150
}
151
#else
152
if (boot.NumBad)
153
pwarn("%d files, %jd KiB free (%d clusters), %jd KiB bad (%d clusters)\n",
154
boot.NumFiles, (intmax_t)freebytes / 1024, boot.NumFree,
155
(intmax_t)badbytes / 1024, boot.NumBad);
156
else
157
pwarn("%d files, %jd KiB free (%d clusters)\n",
158
boot.NumFiles, (intmax_t)freebytes / 1024, boot.NumFree);
159
#endif
160
161
if (mod && (mod & FSERROR) == 0) {
162
if (mod & FSDIRTY) {
163
if (ask(1, "MARK FILE SYSTEM CLEAN") == 0)
164
mod &= ~FSDIRTY;
165
166
if (mod & FSDIRTY) {
167
pwarn("MARKING FILE SYSTEM CLEAN\n");
168
mod |= cleardirty(fat);
169
} else {
170
pwarn("\n***** FILE SYSTEM IS LEFT MARKED AS DIRTY *****\n");
171
mod |= FSERROR; /* file system not clean */
172
}
173
}
174
}
175
176
if (mod & (FSFATAL | FSERROR))
177
goto out;
178
179
ret = 0;
180
181
out:
182
if (finish_dosdirsection)
183
finishDosDirSection();
184
free(fat);
185
close(dosfs);
186
187
if (mod & (FSFATMOD|FSDIRMOD))
188
pwarn("\n***** FILE SYSTEM WAS MODIFIED *****\n");
189
190
return ret;
191
}
192
193