ReactOS 0.4.16-dev-297-gc569aee
fat.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void read_fat (DOS_FS *fs)
 
void get_fat (FAT_ENTRY *entry, void *fat, uint32_t cluster, DOS_FS *fs)
 
void set_fat (DOS_FS *fs, uint32_t cluster, int32_t new)
 
int bad_cluster (DOS_FS *fs, uint32_t cluster)
 
uint32_t next_cluster (DOS_FS *fs, uint32_t cluster)
 
off_t cluster_start (DOS_FS *fs, uint32_t cluster)
 
void set_owner (DOS_FS *fs, uint32_t cluster, DOS_FILE *owner)
 
DOS_FILEget_owner (DOS_FS *fs, uint32_t cluster)
 
void fix_bad (DOS_FS *fs)
 
void reclaim_free (DOS_FS *fs)
 
void reclaim_file (DOS_FS *fs)
 
uint32_t update_free (DOS_FS *fs)
 

Function Documentation

◆ bad_cluster()

int bad_cluster ( DOS_FS fs,
uint32_t  cluster 
)

Definition at line 258 of file fat.c.

259{
260 FAT_ENTRY curEntry;
261 get_fat(&curEntry, fs->fat, cluster, fs);
262
263 return FAT_IS_BAD(fs, curEntry.value);
264}
#define FAT_IS_BAD(fs, v)
Definition: fsck.fat.h:232
void get_fat(FAT_ENTRY *entry, void *fat, uint32_t cluster, DOS_FS *fs)
Definition: fat.c:41
Definition: fsck.fat.h:192
uint32_t value
Definition: fsck.fat.h:193
Definition: ffs.h:70

Referenced by check_file(), and test_file().

◆ cluster_start()

off_t cluster_start ( DOS_FS fs,
uint32_t  cluster 
)

Definition at line 289 of file fat.c.

290{
291 return fs->data_start + ((off_t)cluster - 2) * (uint64_t)fs->cluster_size;
292}
#define off_t
Definition: dosfsck.h:5
#define uint64_t
Definition: nsiface.idl:62

Referenced by alloc_rootdir_entry(), find_volume_de(), fix_bad(), scan_dir(), and test_file().

◆ fix_bad()

void fix_bad ( DOS_FS fs)

Definition at line 322 of file fat.c.

323{
324 uint32_t i;
325
326 if (verbose)
327 printf("Checking for bad clusters.\n");
328 for (i = 2; i < fs->data_clusters + 2; i++) {
329 FAT_ENTRY curEntry;
330 get_fat(&curEntry, fs->fat, i, fs);
331
332 if (!get_owner(fs, i) && !FAT_IS_BAD(fs, curEntry.value))
333 if (!fs_test(cluster_start(fs, i), fs->cluster_size)) {
334 printf("Cluster %lu is unreadable.\n", (unsigned long)i);
335 set_fat(fs, i, -2);
336 }
337 }
338}
UINT32 uint32_t
Definition: types.h:75
#define printf
Definition: freeldr.h:97
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define verbose
Definition: rosglue.h:36
DOS_FILE * get_owner(DOS_FS *fs, uint32_t cluster)
Definition: fat.c:314
off_t cluster_start(DOS_FS *fs, uint32_t cluster)
Definition: fat.c:289
void set_fat(DOS_FS *fs, uint32_t cluster, int32_t new)
Definition: fat.c:189
int fs_test(off_t pos, int size)
Definition: io.c:322

Referenced by VfatChkdsk().

◆ get_fat()

void get_fat ( FAT_ENTRY entry,
void fat,
uint32_t  cluster,
DOS_FS fs 
)

Fetch the FAT entry for a specified cluster.

Parameters
[out]entryCluster to which cluster of interest is linked
[in]fatFAT table for the partition
[in]clusterCluster of interest
[in]fsInformation from the FAT boot sectors (bits per FAT entry)

Definition at line 41 of file fat.c.

42{
43 unsigned char *ptr;
44
45 if (cluster > fs->data_clusters + 1) {
46 die("Internal error: cluster out of range in get_fat() (%lu > %lu).",
47 (unsigned long)cluster, (unsigned long)(fs->data_clusters + 1));
48 }
49
50 switch (fs->fat_bits) {
51 case 12:
52 ptr = &((unsigned char *)fat)[cluster * 3 / 2];
53 entry->value = 0xfff & (cluster & 1 ? (ptr[0] >> 4) | (ptr[1] << 4) :
54 (ptr[0] | ptr[1] << 8));
55 break;
56 case 16:
57 entry->value = le16toh(((unsigned short *)fat)[cluster]);
58 break;
59 case 32:
60 /* According to M$, the high 4 bits of a FAT32 entry are reserved and
61 * are not part of the cluster number. So we cut them off. */
62 {
63 uint32_t e = le32toh(((unsigned int *)fat)[cluster]);
64 entry->value = e & 0xfffffff;
65 entry->reserved = e >> 28;
66 }
67 break;
68 default:
69 die("Bad FAT entry size: %d bits.", fs->fat_bits);
70 }
71}
uint32_t entry
Definition: isohybrid.c:63
#define e
Definition: ke_i.h:82
#define die(str)
Definition: mkdosfs.c:347
static unsigned char * fat
Definition: mkdosfs.c:542
static PVOID ptr
Definition: dispmode.c:27

Referenced by alloc_rootdir_entry(), bad_cluster(), check_file(), fix_bad(), next_cluster(), read_fat(), reclaim_file(), reclaim_free(), set_fat(), tag_free(), undelete(), and update_free().

◆ get_owner()

DOS_FILE * get_owner ( DOS_FS fs,
uint32_t  cluster 
)

Definition at line 314 of file fat.c.

315{
316 if (fs->cluster_owner == NULL)
317 return NULL;
318 else
319 return fs->cluster_owner[cluster];
320}
#define NULL
Definition: types.h:112

Referenced by fix_bad(), reclaim_file(), reclaim_free(), tag_free(), and update_free().

◆ next_cluster()

uint32_t next_cluster ( DOS_FS fs,
uint32_t  cluster 
)

Get the cluster to which the specified cluster is linked. If the linked cluster is marked bad, abort.

Parameters
[in]fsInformation about the filesystem
[in]clusterCluster to follow
Returns
-1 'cluster' is at the end of the chain
Other values Next cluster in this chain

Definition at line 276 of file fat.c.

277{
279 FAT_ENTRY curEntry;
280
281 get_fat(&curEntry, fs->fat, cluster, fs);
282
283 value = curEntry.value;
284 if (FAT_IS_BAD(fs, value))
285 die("Internal error: next_cluster on bad cluster");
286 return FAT_IS_EOF(fs, value) ? -1 : value;
287}
#define FAT_IS_EOF(fs, v)
Definition: fsck.fat.h:226
Definition: pdh_main.c:94

Referenced by alloc_rootdir_entry(), check_file(), drop_file(), find_volume_de(), reclaim_file(), scan_dir(), tag_free(), test_file(), and truncate_file().

◆ read_fat()

void read_fat ( DOS_FS fs)

Build a bookkeeping structure from the partition's FAT table. If the partition has multiple FATs and they don't agree, try to pick a winner, and queue a command to overwrite the loser. One error that is fixed here is a cluster that links to something out of range.

Parameters
[in,out]fsInformation about the filesystem

Definition at line 81 of file fat.c.

82{
83 int eff_size, alloc_size;
84 uint32_t i;
85 void *first, *second = NULL;
86 int first_ok, second_ok;
87 uint32_t total_num_clusters;
88
89 /* Clean up from previous pass */
90 if (fs->fat)
91 free(fs->fat);
92 if (fs->cluster_owner)
93 free(fs->cluster_owner);
94 fs->fat = NULL;
95 fs->cluster_owner = NULL;
96
97 total_num_clusters = fs->data_clusters + 2;
98 eff_size = (total_num_clusters * fs->fat_bits + 7) / 8ULL;
99
100 if (fs->fat_bits != 12)
101 alloc_size = eff_size;
102 else
103 /* round up to an even number of FAT entries to avoid special
104 * casing the last entry in get_fat() */
105 alloc_size = (total_num_clusters * 12 + 23) / 24 * 3;
106
107 first = alloc(alloc_size);
108 fs_read(fs->fat_start, eff_size, first);
109 if (fs->nfats > 1) {
110 second = alloc(alloc_size);
111 fs_read(fs->fat_start + fs->fat_size, eff_size, second);
112 }
113 if (second && memcmp(first, second, eff_size) != 0) {
114 FAT_ENTRY first_media, second_media;
115 get_fat(&first_media, first, 0, fs);
116 get_fat(&second_media, second, 0, fs);
117 first_ok = (first_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs);
118 second_ok = (second_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs);
119 if (first_ok && !second_ok) {
120 printf("FATs differ - using first FAT.\n");
121 fs_write(fs->fat_start + fs->fat_size, eff_size, first);
122 }
123 if (!first_ok && second_ok) {
124 printf("FATs differ - using second FAT.\n");
125 fs_write(fs->fat_start, eff_size, second);
126 memcpy(first, second, eff_size);
127 }
128 if (first_ok && second_ok) {
129 if (interactive) {
130 printf("FATs differ but appear to be intact. Use which FAT ?\n"
131 "1) Use first FAT\n2) Use second FAT\n");
132 if (get_key("12", "?") == '1') {
133 fs_write(fs->fat_start + fs->fat_size, eff_size, first);
134 } else {
135 fs_write(fs->fat_start, eff_size, second);
136 memcpy(first, second, eff_size);
137 }
138 } else {
139 printf("FATs differ but appear to be intact. Using first "
140 "FAT.\n");
141 fs_write(fs->fat_start + fs->fat_size, eff_size, first);
142 }
143 }
144 if (!first_ok && !second_ok) {
145 printf("Both FATs appear to be corrupt. Giving up.\n");
146 exit(1);
147 }
148 }
149 if (second) {
150 free(second);
151 }
152 fs->fat = (unsigned char *)first;
153
154 fs->cluster_owner = alloc(total_num_clusters * sizeof(DOS_FILE *));
155 memset(fs->cluster_owner, 0, (total_num_clusters * sizeof(DOS_FILE *)));
156
157 /* Truncate any cluster chains that link to something out of range */
158 for (i = 2; i < fs->data_clusters + 2; i++) {
159 FAT_ENTRY curEntry;
160 get_fat(&curEntry, fs->fat, i, fs);
161 if (curEntry.value == 1) {
162 printf("Cluster %ld out of range (1). Setting to EOF.\n",
163 (long)(i - 2));
164 set_fat(fs, i, -1);
165 }
166 if (curEntry.value >= fs->data_clusters + 2 &&
167 (curEntry.value < FAT_MIN_BAD(fs))) {
168 printf("Cluster %ld out of range (%ld > %ld). Setting to EOF.\n",
169 (long)(i - 2), (long)curEntry.value,
170 (long)(fs->data_clusters + 2 - 1));
171 set_fat(fs, i, -1);
172 }
173 }
174}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define free
Definition: debug_ros.c:5
#define FAT_MIN_BAD(fs)
Definition: fsck.fat.h:230
#define FAT_EXTD(fs)
Definition: fsck.fat.h:235
const GLint * first
Definition: glext.h:5794
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define alloc
Definition: rosglue.h:13
#define interactive
Definition: rosglue.h:34
#define exit(n)
Definition: config.h:202
char get_key(const char *valid, const char *prompt)
Definition: common.c:184
void fs_read(off_t pos, int size, void *data)
Definition: io.c:282
void fs_write(off_t pos, int size, void *data)
Definition: io.c:344
#define memset(x, y, z)
Definition: compat.h:39

Referenced by VfatChkdsk().

◆ reclaim_file()

void reclaim_file ( DOS_FS fs)

Recover orphan chains to files, handling any cycles or cross-links.

Parameters
[in,out]fsInformation about the filesystem

Definition at line 426 of file fat.c.

427{
429 int reclaimed, files;
430 int changed = 0;
431 uint32_t i, next, walk;
432 uint32_t *num_refs = NULL; /* Only for orphaned clusters */
433 uint32_t total_num_clusters;
434
435 if (verbose)
436 printf("Reclaiming unconnected clusters.\n");
437
438 total_num_clusters = fs->data_clusters + 2;
439 num_refs = alloc(total_num_clusters * sizeof(uint32_t));
440 memset(num_refs, 0, (total_num_clusters * sizeof(uint32_t)));
441
442 /* Guarantee that all orphan chains (except cycles) end cleanly
443 * with an end-of-chain mark.
444 */
445
446 for (i = 2; i < total_num_clusters; i++) {
447 FAT_ENTRY curEntry;
448 get_fat(&curEntry, fs->fat, i, fs);
449
450 next = curEntry.value;
451 if (!get_owner(fs, i) && next && next < fs->data_clusters + 2) {
452 /* Cluster is linked, but not owned (orphan) */
453 FAT_ENTRY nextEntry;
454 get_fat(&nextEntry, fs->fat, next, fs);
455
456 /* Mark it end-of-chain if it links into an owned cluster,
457 * a free cluster, or a bad cluster.
458 */
459 if (get_owner(fs, next) || !nextEntry.value ||
460 FAT_IS_BAD(fs, nextEntry.value))
461 set_fat(fs, i, -1);
462 else
463 num_refs[next]++;
464 }
465 }
466
467 /* Scan until all the orphans are accounted for,
468 * and all cycles and cross-links are broken
469 */
470 do {
471 tag_free(fs, &orphan, num_refs, changed);
472 changed = 0;
473
474 /* Any unaccounted-for orphans must be part of a cycle */
475 for (i = 2; i < total_num_clusters; i++) {
476 FAT_ENTRY curEntry;
477 get_fat(&curEntry, fs->fat, i, fs);
478
479 if (curEntry.value && !FAT_IS_BAD(fs, curEntry.value) &&
480 !get_owner(fs, i)) {
481 if (!num_refs[curEntry.value]--)
482 die("Internal error: num_refs going below zero");
483 set_fat(fs, i, -1);
484 changed = curEntry.value;
485 printf("Broke cycle at cluster %lu in free chain.\n", (unsigned long)i);
486
487 /* If we've created a new chain head,
488 * tag_free() can claim it
489 */
490 if (num_refs[curEntry.value] == 0)
491 break;
492 }
493 }
494 }
495 while (changed);
496
497#ifdef __REACTOS__
498 if (rw) {
499#endif
500 /* Now we can start recovery */
501 files = reclaimed = 0;
502 for (i = 2; i < total_num_clusters; i++)
503 /* If this cluster is the head of an orphan chain... */
504 if (get_owner(fs, i) == &orphan && !num_refs[i]) {
505 DIR_ENT de;
507 files++;
508 offset = alloc_rootdir_entry(fs, &de, "FSCK%04dREC", 1);
509 de.start = htole16(i & 0xffff);
510 if (fs->fat_bits == 32)
511 de.starthi = htole16(i >> 16);
512 for (walk = i; walk > 0 && walk != -1;
513 walk = next_cluster(fs, walk)) {
514 de.size = htole32(le32toh(de.size) + fs->cluster_size);
515 reclaimed++;
516 }
517 fs_write(offset, sizeof(DIR_ENT), &de);
518 }
519 if (reclaimed)
520 printf("Reclaimed %d unused cluster%s (%llu bytes) in %d chain%s.\n",
521 reclaimed, reclaimed == 1 ? "" : "s",
522 (unsigned long long)reclaimed * fs->cluster_size, files,
523 files == 1 ? "" : "s");
524#ifdef __REACTOS__
525 }
526#endif
527
528 free(num_refs);
529}
__kernel_off_t off_t
Definition: linux.h:201
off_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern, int gen_name)
Definition: check.c:74
GLintptr offset
Definition: glext.h:5920
static unsigned __int64 next
Definition: rand_nt.c:6
#define rw
Definition: rosglue.h:38
uint32_t next_cluster(DOS_FS *fs, uint32_t cluster)
Definition: fat.c:276
static void tag_free(DOS_FS *fs, DOS_FILE *owner, uint32_t *num_refs, uint32_t start_cluster)
Definition: fat.c:378
#define htole16(x)
Definition: storage32.h:546
#define htole32(x)
Definition: storage32.h:543
Definition: send.c:34

Referenced by VfatChkdsk().

◆ reclaim_free()

void reclaim_free ( DOS_FS fs)

Definition at line 340 of file fat.c.

341{
342 int reclaimed;
343 uint32_t i;
344
345 if (verbose)
346 printf("Checking for unused clusters.\n");
347 reclaimed = 0;
348 for (i = 2; i < fs->data_clusters + 2; i++) {
349 FAT_ENTRY curEntry;
350 get_fat(&curEntry, fs->fat, i, fs);
351
352 if (!get_owner(fs, i) && curEntry.value &&
353#ifndef __REACTOS__
354 !FAT_IS_BAD(fs, curEntry.value)) {
355#else
356 !FAT_IS_BAD(fs, curEntry.value) && rw) {
357#endif
358 set_fat(fs, i, 0);
359 reclaimed++;
360 }
361 }
362 if (reclaimed)
363 printf("Reclaimed %d unused cluster%s (%llu bytes).\n", (int)reclaimed,
364 reclaimed == 1 ? "" : "s",
365 (unsigned long long)reclaimed * fs->cluster_size);
366}

Referenced by VfatChkdsk().

◆ set_fat()

void set_fat ( DOS_FS fs,
uint32_t  cluster,
int32_t  new 
)

Update the FAT entry for a specified cluster (i.e., change the cluster it links to). Queue a command to write out this change.

Parameters
[in,out]fsInformation about the filesystem
[in]clusterCluster to change
[in]newCluster to link to Special values: 0 == free cluster -1 == end-of-chain -2 == bad cluster

Definition at line 189 of file fat.c.

190{
191 unsigned char *data = NULL;
192 int size;
193 off_t offs;
194
195 if (cluster > fs->data_clusters + 1) {
196 die("Internal error: cluster out of range in set_fat() (%lu > %lu).",
197 (unsigned long)cluster, (unsigned long)(fs->data_clusters + 1));
198 }
199
200 if (new == -1)
201 new = FAT_EOF(fs);
202 else if ((long)new == -2)
203 new = FAT_BAD(fs);
204 else if (new > fs->data_clusters + 1) {
205 die("Internal error: new cluster out of range in set_fat() (%lu > %lu).",
206 (unsigned long)new, (unsigned long)(fs->data_clusters + 1));
207 }
208
209 switch (fs->fat_bits) {
210 case 12:
211 data = fs->fat + cluster * 3 / 2;
212 offs = fs->fat_start + cluster * 3 / 2;
213 if (cluster & 1) {
214 FAT_ENTRY prevEntry;
215 get_fat(&prevEntry, fs->fat, cluster - 1, fs);
216 data[0] = ((new & 0xf) << 4) | (prevEntry.value >> 8);
217 data[1] = new >> 4;
218 } else {
219 FAT_ENTRY subseqEntry;
220 if (cluster != fs->data_clusters + 1)
221 get_fat(&subseqEntry, fs->fat, cluster + 1, fs);
222 else
223 subseqEntry.value = 0;
224 data[0] = new & 0xff;
225 data[1] = (new >> 8) | ((0xff & subseqEntry.value) << 4);
226 }
227 size = 2;
228 break;
229 case 16:
230 data = fs->fat + cluster * 2;
231 offs = fs->fat_start + cluster * 2;
232 *(unsigned short *)data = htole16(new);
233 size = 2;
234 break;
235 case 32:
236 {
237 FAT_ENTRY curEntry;
238 get_fat(&curEntry, fs->fat, cluster, fs);
239
240 data = fs->fat + cluster * 4;
241 offs = fs->fat_start + cluster * 4;
242 /* According to M$, the high 4 bits of a FAT32 entry are reserved and
243 * are not part of the cluster number. So we never touch them. */
244 *(uint32_t *)data = htole32((new & 0xfffffff) |
245 (curEntry.reserved << 28));
246 size = 4;
247 }
248 break;
249 default:
250 die("Bad FAT entry size: %d bits.", fs->fat_bits);
251 }
252 fs_write(offs, size, data);
253 if (fs->nfats > 1) {
254 fs_write(offs + fs->fat_size, size, data);
255 }
256}
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
#define FAT_BAD
Definition: mkdosfs.c:379
#define FAT_EOF
Definition: mkdosfs.c:378
uint32_t reserved
Definition: fsck.fat.h:194

Referenced by alloc_rootdir_entry(), check_file(), fix_bad(), read_fat(), reclaim_file(), reclaim_free(), tag_free(), test_file(), truncate_file(), and undelete().

◆ set_owner()

void set_owner ( DOS_FS fs,
uint32_t  cluster,
DOS_FILE owner 
)

Update internal bookkeeping to show that the specified cluster belongs to the specified dentry.

Parameters
[in,out]fsInformation about the filesystem
[in]clusterCluster being assigned
[in]ownerInformation on dentry that owns this cluster (may be NULL)

Definition at line 303 of file fat.c.

304{
305 if (fs->cluster_owner == NULL)
306 die("Internal error: attempt to set owner in non-existent table");
307
308 if (owner && fs->cluster_owner[cluster]
309 && (fs->cluster_owner[cluster] != owner))
310 die("Internal error: attempt to change file owner");
311 fs->cluster_owner[cluster] = owner;
312}

Referenced by alloc_rootdir_entry(), check_file(), drop_file(), tag_free(), and test_file().

◆ update_free()

uint32_t update_free ( DOS_FS fs)

Definition at line 531 of file fat.c.

532{
533 uint32_t i;
534 uint32_t free = 0;
535 int do_set = 0;
536
537 for (i = 2; i < fs->data_clusters + 2; i++) {
538 FAT_ENTRY curEntry;
539 get_fat(&curEntry, fs->fat, i, fs);
540
541 if (!get_owner(fs, i) && !FAT_IS_BAD(fs, curEntry.value))
542 ++free;
543 }
544
545 if (!fs->fsinfo_start)
546 return free;
547
548 if (verbose)
549 printf("Checking free cluster summary.\n");
550 if (fs->free_clusters != 0xFFFFFFFF) {
551 if (free != fs->free_clusters) {
552 printf("Free cluster summary wrong (%ld vs. really %ld)\n",
553 (long)fs->free_clusters, (long)free);
554 if (interactive)
555 printf("1) Correct\n2) Don't correct\n");
556 else
557#ifdef __REACTOS__
558 if (rw)
559#endif
560 printf(" Auto-correcting.\n");
561#ifndef __REACTOS__
562 if (!interactive || get_key("12", "?") == '1')
563#else
564 if ((!interactive && rw) || (interactive && get_key("12", "?") == '1'))
565#endif
566 do_set = 1;
567 }
568 } else {
569 printf("Free cluster summary uninitialized (should be %ld)\n", (long)free);
570 if (rw) {
571 if (interactive)
572 printf("1) Set it\n2) Leave it uninitialized\n");
573 else
574 printf(" Auto-setting.\n");
575 if (!interactive || get_key("12", "?") == '1')
576 do_set = 1;
577 }
578 }
579
580 if (do_set) {
581 uint32_t le_free = htole32(free);
582 fs->free_clusters = free;
583 fs_write(fs->fsinfo_start + offsetof(struct info_sector, free_clusters),
584 sizeof(le_free), &le_free);
585 }
586
587 return free;
588}
#define offsetof(TYPE, MEMBER)

Referenced by VfatChkdsk().