ReactOS 0.4.16-dev-2603-gfeb9feb
fat.c File Reference
#include "vfatlib.h"
#include <debug.h>
Include dependency graph for fat.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

void get_fat (FAT_ENTRY *entry, void *fat, uint32_t cluster, DOS_FS *fs)
 
void read_fat (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)
 
static void tag_free (DOS_FS *fs, DOS_FILE *owner, uint32_t *num_refs, uint32_t start_cluster)
 
void reclaim_file (DOS_FS *fs)
 
uint32_t update_free (DOS_FS *fs)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 29 of file fat.c.

Function Documentation

◆ bad_cluster()

int bad_cluster ( DOS_FS fs,
uint32_t  cluster 
)

Definition at line 290 of file fat.c.

291{
292 FAT_ENTRY curEntry;
293 get_fat(&curEntry, fs->fat, cluster, fs);
294
295 return FAT_IS_BAD(fs, curEntry.value);
296}
#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 321 of file fat.c.

322{
323 return fs->data_start + ((off_t)cluster - 2) * (uint64_t)fs->cluster_size;
324}
#define off_t
Definition: types.h:60
#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 354 of file fat.c.

355{
356 uint32_t i;
357
358 if (verbose)
359 printf("Checking for bad clusters.\n");
360 for (i = 2; i < fs->data_clusters + 2; i++) {
361 FAT_ENTRY curEntry;
362 get_fat(&curEntry, fs->fat, i, fs);
363
364 if (!get_owner(fs, i) && !FAT_IS_BAD(fs, curEntry.value))
365 if (!fs_test(cluster_start(fs, i), fs->cluster_size)) {
366 printf("Cluster %lu is unreadable.\n", (unsigned long)i);
367 set_fat(fs, i, -2);
368 }
369 }
370}
UINT32 uint32_t
Definition: types.h:75
#define printf
Definition: freeldr.h:104
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:346
off_t cluster_start(DOS_FS *fs, uint32_t cluster)
Definition: fat.c:321
void set_fat(DOS_FS *fs, uint32_t cluster, int32_t new)
Definition: fat.c:214
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 346 of file fat.c.

347{
348 if (fs->cluster_owner == NULL)
349 return NULL;
350 else
351 return fs->cluster_owner[cluster];
352}
#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 308 of file fat.c.

309{
311 FAT_ENTRY curEntry;
312
313 get_fat(&curEntry, fs->fat, cluster, fs);
314
315 value = curEntry.value;
316 if (FAT_IS_BAD(fs, value))
317 die("Internal error: next_cluster on bad cluster");
318 return FAT_IS_EOF(fs, value) ? -1 : value;
319}
#define FAT_IS_EOF(fs, v)
Definition: fsck.fat.h:226
Definition: pdh_main.c:96

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#ifdef __REACTOS__
122 if (rw)
123 fs_write(fs->fat_start + fs->fat_size, eff_size, first);
124#else
125 fs_write(fs->fat_start + fs->fat_size, eff_size, first);
126#endif
127 }
128 if (!first_ok && second_ok) {
129 printf("FATs differ - using second FAT.\n");
130#ifdef __REACTOS__
131 if (rw)
132 fs_write(fs->fat_start, eff_size, second);
133#else
134 fs_write(fs->fat_start, eff_size, second);
135#endif
136 memcpy(first, second, eff_size);
137 }
138 if (first_ok && second_ok) {
139 if (interactive) {
140 printf("FATs differ but appear to be intact. Use which FAT ?\n"
141 "1) Use first FAT\n2) Use second FAT\n");
142 if (get_key("12", "?") == '1') {
143#ifdef __REACTOS__
144 if (rw)
145 fs_write(fs->fat_start + fs->fat_size, eff_size, first);
146#else
147 fs_write(fs->fat_start + fs->fat_size, eff_size, first);
148#endif
149 } else {
150#ifdef __REACTOS__
151 if (rw)
152 fs_write(fs->fat_start, eff_size, second);
153#else
154 fs_write(fs->fat_start, eff_size, second);
155#endif
156 memcpy(first, second, eff_size);
157 }
158 } else {
159 printf("FATs differ but appear to be intact. Using first "
160 "FAT.\n");
161#ifdef __REACTOS__
162 if (rw)
163 fs_write(fs->fat_start + fs->fat_size, eff_size, first);
164#else
165 fs_write(fs->fat_start + fs->fat_size, eff_size, first);
166#endif
167 }
168 }
169 if (!first_ok && !second_ok) {
170 printf("Both FATs appear to be corrupt. Giving up.\n");
171 exit(1);
172 }
173 }
174 if (second) {
175 free(second);
176 }
177 fs->fat = (unsigned char *)first;
178
179 fs->cluster_owner = alloc(total_num_clusters * sizeof(DOS_FILE *));
180 memset(fs->cluster_owner, 0, (total_num_clusters * sizeof(DOS_FILE *)));
181
182 /* Truncate any cluster chains that link to something out of range */
183 for (i = 2; i < fs->data_clusters + 2; i++) {
184 FAT_ENTRY curEntry;
185 get_fat(&curEntry, fs->fat, i, fs);
186 if (curEntry.value == 1) {
187 printf("Cluster %ld out of range (1). Setting to EOF.\n",
188 (long)(i - 2));
189 set_fat(fs, i, -1);
190 }
191 if (curEntry.value >= fs->data_clusters + 2 &&
192 (curEntry.value < FAT_MIN_BAD(fs))) {
193 printf("Cluster %ld out of range (%ld > %ld). Setting to EOF.\n",
194 (long)(i - 2), (long)curEntry.value,
195 (long)(fs->data_clusters + 2 - 1));
196 set_fat(fs, i, -1);
197 }
198 }
199}
#define free
Definition: debug_ros.c:5
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
#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 rw
Definition: rosglue.h:38
#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 458 of file fat.c.

459{
461 int reclaimed, files;
462 int changed = 0;
463 uint32_t i, next, walk;
464 uint32_t *num_refs = NULL; /* Only for orphaned clusters */
465 uint32_t total_num_clusters;
466
467 if (verbose)
468 printf("Reclaiming unconnected clusters.\n");
469
470 total_num_clusters = fs->data_clusters + 2;
471 num_refs = alloc(total_num_clusters * sizeof(uint32_t));
472 memset(num_refs, 0, (total_num_clusters * sizeof(uint32_t)));
473
474 /* Guarantee that all orphan chains (except cycles) end cleanly
475 * with an end-of-chain mark.
476 */
477
478 for (i = 2; i < total_num_clusters; i++) {
479 FAT_ENTRY curEntry;
480 get_fat(&curEntry, fs->fat, i, fs);
481
482 next = curEntry.value;
483 if (!get_owner(fs, i) && next && next < fs->data_clusters + 2) {
484 /* Cluster is linked, but not owned (orphan) */
485 FAT_ENTRY nextEntry;
486 get_fat(&nextEntry, fs->fat, next, fs);
487
488 /* Mark it end-of-chain if it links into an owned cluster,
489 * a free cluster, or a bad cluster.
490 */
491 if (get_owner(fs, next) || !nextEntry.value ||
492 FAT_IS_BAD(fs, nextEntry.value))
493 set_fat(fs, i, -1);
494 else
495 num_refs[next]++;
496 }
497 }
498
499 /* Scan until all the orphans are accounted for,
500 * and all cycles and cross-links are broken
501 */
502 do {
503 tag_free(fs, &orphan, num_refs, changed);
504 changed = 0;
505
506 /* Any unaccounted-for orphans must be part of a cycle */
507 for (i = 2; i < total_num_clusters; i++) {
508 FAT_ENTRY curEntry;
509 get_fat(&curEntry, fs->fat, i, fs);
510
511 if (curEntry.value && !FAT_IS_BAD(fs, curEntry.value) &&
512 !get_owner(fs, i)) {
513 if (!num_refs[curEntry.value]--)
514 die("Internal error: num_refs going below zero");
515 set_fat(fs, i, -1);
516 changed = curEntry.value;
517 printf("Broke cycle at cluster %lu in free chain.\n", (unsigned long)i);
518
519 /* If we've created a new chain head,
520 * tag_free() can claim it
521 */
522 if (num_refs[curEntry.value] == 0)
523 break;
524 }
525 }
526 }
527 while (changed);
528
529#ifdef __REACTOS__
530 if (rw) {
531#endif
532 /* Now we can start recovery */
533 files = reclaimed = 0;
534 for (i = 2; i < total_num_clusters; i++)
535 /* If this cluster is the head of an orphan chain... */
536 if (get_owner(fs, i) == &orphan && !num_refs[i]) {
537 DIR_ENT de;
539 files++;
540 offset = alloc_rootdir_entry(fs, &de, "FSCK%04dREC", 1);
541 de.start = htole16(i & 0xffff);
542 if (fs->fat_bits == 32)
543 de.starthi = htole16(i >> 16);
544 for (walk = i; walk > 0 && walk != -1;
545 walk = next_cluster(fs, walk)) {
546 de.size = htole32(le32toh(de.size) + fs->cluster_size);
547 reclaimed++;
548 }
549#ifdef __REACTOS__
550 if (rw)
551 fs_write(offset, sizeof(DIR_ENT), &de);
552#else
553 fs_write(offset, sizeof(DIR_ENT), &de);
554#endif
555 }
556 if (reclaimed)
557 printf("Reclaimed %d unused cluster%s (%llu bytes) in %d chain%s.\n",
558 reclaimed, reclaimed == 1 ? "" : "s",
559 (unsigned long long)reclaimed * fs->cluster_size, files,
560 files == 1 ? "" : "s");
561#ifdef __REACTOS__
562 }
563#endif
564
565 free(num_refs);
566}
__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
uint32_t next_cluster(DOS_FS *fs, uint32_t cluster)
Definition: fat.c:308
static void tag_free(DOS_FS *fs, DOS_FILE *owner, uint32_t *num_refs, uint32_t start_cluster)
Definition: fat.c:410
#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 372 of file fat.c.

373{
374 int reclaimed;
375 uint32_t i;
376
377 if (verbose)
378 printf("Checking for unused clusters.\n");
379 reclaimed = 0;
380 for (i = 2; i < fs->data_clusters + 2; i++) {
381 FAT_ENTRY curEntry;
382 get_fat(&curEntry, fs->fat, i, fs);
383
384 if (!get_owner(fs, i) && curEntry.value &&
385#ifndef __REACTOS__
386 !FAT_IS_BAD(fs, curEntry.value)) {
387#else
388 !FAT_IS_BAD(fs, curEntry.value) && rw) {
389#endif
390 set_fat(fs, i, 0);
391 reclaimed++;
392 }
393 }
394 if (reclaimed)
395 printf("Reclaimed %d unused cluster%s (%llu bytes).\n", (int)reclaimed,
396 reclaimed == 1 ? "" : "s",
397 (unsigned long long)reclaimed * fs->cluster_size);
398}

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 214 of file fat.c.

215{
216 unsigned char *data = NULL;
217 int size;
218 off_t offs;
219
220 if (cluster > fs->data_clusters + 1) {
221 die("Internal error: cluster out of range in set_fat() (%lu > %lu).",
222 (unsigned long)cluster, (unsigned long)(fs->data_clusters + 1));
223 }
224
225 if (new == -1)
226 new = FAT_EOF(fs);
227 else if ((long)new == -2)
228 new = FAT_BAD(fs);
229 else if (new > fs->data_clusters + 1) {
230 die("Internal error: new cluster out of range in set_fat() (%lu > %lu).",
231 (unsigned long)new, (unsigned long)(fs->data_clusters + 1));
232 }
233
234 switch (fs->fat_bits) {
235 case 12:
236 data = fs->fat + cluster * 3 / 2;
237 offs = fs->fat_start + cluster * 3 / 2;
238 if (cluster & 1) {
239 FAT_ENTRY prevEntry;
240 get_fat(&prevEntry, fs->fat, cluster - 1, fs);
241 data[0] = ((new & 0xf) << 4) | (prevEntry.value >> 8);
242 data[1] = new >> 4;
243 } else {
244 FAT_ENTRY subseqEntry;
245 if (cluster != fs->data_clusters + 1)
246 get_fat(&subseqEntry, fs->fat, cluster + 1, fs);
247 else
248 subseqEntry.value = 0;
249 data[0] = new & 0xff;
250 data[1] = (new >> 8) | ((0xff & subseqEntry.value) << 4);
251 }
252 size = 2;
253 break;
254 case 16:
255 data = fs->fat + cluster * 2;
256 offs = fs->fat_start + cluster * 2;
257 *(unsigned short *)data = htole16(new);
258 size = 2;
259 break;
260 case 32:
261 {
262 FAT_ENTRY curEntry;
263 get_fat(&curEntry, fs->fat, cluster, fs);
264
265 data = fs->fat + cluster * 4;
266 offs = fs->fat_start + cluster * 4;
267 /* According to M$, the high 4 bits of a FAT32 entry are reserved and
268 * are not part of the cluster number. So we never touch them. */
269 *(uint32_t *)data = htole32((new & 0xfffffff) |
270 (curEntry.reserved << 28));
271 size = 4;
272 }
273 break;
274 default:
275 die("Bad FAT entry size: %d bits.", fs->fat_bits);
276 }
277#ifdef __REACTOS__
278 if (rw)
279 {
280#endif
281 fs_write(offs, size, data);
282 if (fs->nfats > 1) {
283 fs_write(offs + fs->fat_size, size, data);
284 }
285#ifdef __REACTOS__
286 }
287#endif
288}
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 335 of file fat.c.

336{
337 if (fs->cluster_owner == NULL)
338 die("Internal error: attempt to set owner in non-existent table");
339
340 if (owner && fs->cluster_owner[cluster]
341 && (fs->cluster_owner[cluster] != owner))
342 die("Internal error: attempt to change file owner");
343 fs->cluster_owner[cluster] = owner;
344}

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

◆ tag_free()

static void tag_free ( DOS_FS fs,
DOS_FILE owner,
uint32_t num_refs,
uint32_t  start_cluster 
)
static

Assign the specified owner to all orphan chains (except cycles). Break cross-links between orphan chains.

Parameters
[in,out]fsInformation about the filesystem
[in]ownerdentry to be assigned ownership of orphans
[in,out]num_refsFor each orphan cluster [index], how many clusters link to it.
[in]start_clusterWhere to start scanning for orphans

Definition at line 410 of file fat.c.

412{
413 int prev;
414 uint32_t i, walk;
415
416 if (start_cluster == 0)
417 start_cluster = 2;
418
419 for (i = start_cluster; i < fs->data_clusters + 2; i++) {
420 FAT_ENTRY curEntry;
421 get_fat(&curEntry, fs->fat, i, fs);
422
423 /* If the current entry is the head of an un-owned chain... */
424 if (curEntry.value && !FAT_IS_BAD(fs, curEntry.value) &&
425 !get_owner(fs, i) && !num_refs[i]) {
426 prev = 0;
427 /* Walk the chain, claiming ownership as we go */
428 for (walk = i; walk != -1; walk = next_cluster(fs, walk)) {
429 if (!get_owner(fs, walk)) {
430 set_owner(fs, walk, owner);
431 } else {
432 /* We've run into cross-links between orphaned chains,
433 * or a cycle with a tail.
434 * Terminate this orphan chain (break the link)
435 */
436 set_fat(fs, prev, -1);
437
438 /* This is not necessary because 'walk' is owned and thus
439 * will never become the head of a chain (the only case
440 * that would matter during reclaim to files).
441 * It's easier to decrement than to prove that it's
442 * unnecessary.
443 */
444 num_refs[walk]--;
445 break;
446 }
447 prev = walk;
448 }
449 }
450 }
451}
void set_owner(DOS_FS *fs, uint32_t cluster, DOS_FILE *owner)
Definition: fat.c:335

Referenced by reclaim_file().

◆ update_free()

uint32_t update_free ( DOS_FS fs)

Definition at line 568 of file fat.c.

569{
570 uint32_t i;
571 uint32_t free = 0;
572 int do_set = 0;
573
574 for (i = 2; i < fs->data_clusters + 2; i++) {
575 FAT_ENTRY curEntry;
576 get_fat(&curEntry, fs->fat, i, fs);
577
578 if (!get_owner(fs, i) && !FAT_IS_BAD(fs, curEntry.value))
579 ++free;
580 }
581
582 if (!fs->fsinfo_start)
583 return free;
584
585 if (verbose)
586 printf("Checking free cluster summary.\n");
587 if (fs->free_clusters != 0xFFFFFFFF) {
588 if (free != fs->free_clusters) {
589 printf("Free cluster summary wrong (%ld vs. really %ld)\n",
590 (long)fs->free_clusters, (long)free);
591 if (interactive)
592 printf("1) Correct\n2) Don't correct\n");
593 else
594#ifdef __REACTOS__
595 if (rw)
596 printf(" Auto-correcting.\n");
597#else
598 printf(" Auto-correcting.\n");
599#endif
600#ifndef __REACTOS__
601 if (!interactive || get_key("12", "?") == '1')
602#else
603 if ((!interactive && rw) || (interactive && get_key("12", "?") == '1'))
604#endif
605 do_set = 1;
606 }
607 } else {
608 printf("Free cluster summary uninitialized (should be %ld)\n", (long)free);
609 if (rw) {
610 if (interactive)
611 printf("1) Set it\n2) Leave it uninitialized\n");
612 else
613 printf(" Auto-setting.\n");
614 if (!interactive || get_key("12", "?") == '1')
615 do_set = 1;
616 }
617 }
618
619 if (do_set) {
620 uint32_t le_free = htole32(free);
621 fs->free_clusters = free;
622#ifdef __REACTOS__
623 if (rw)
624 fs_write(fs->fsinfo_start + offsetof(struct info_sector, free_clusters),
625 sizeof(le_free), &le_free);
626#else
627 fs_write(fs->fsinfo_start + offsetof(struct info_sector, free_clusters),
628 sizeof(le_free), &le_free);
629#endif
630 fs_write(fs->fsinfo_start + offsetof(struct info_sector, free_clusters),
631 sizeof(le_free), &le_free);
632 }
633
634 return free;
635}
#define offsetof(TYPE, MEMBER)

Referenced by VfatChkdsk().