53 die(
"Internal error: cluster out of range in get_fat() (%lu > %lu).",
54 (
unsigned long)cluster, (
unsigned long)(fs->
data_clusters + 1));
59 ptr = &((
unsigned char *)
fat)[cluster * 3 / 2];
60 entry->
value = 0xfff & (cluster & 1 ? (ptr[0] >> 4) | (ptr[1] << 4) :
61 (ptr[0] | ptr[1] << 8));
64 entry->
value = le16toh(((
unsigned short *)
fat)[cluster]);
70 uint32_t e = le32toh(((
unsigned int *)
fat)[cluster]);
71 entry->
value = e & 0xfffffff;
96 printf(
"Fixing first cluster in FAT.\n");
98 *(uint16_t *)first_cluster = htole16((le16toh(*(uint16_t *)first_cluster) & 0xf000) |
FAT_EXTD(fs) | b.
media);
100 *(uint16_t *)first_cluster = htole16(
FAT_EXTD(fs) | b.
media);
102 *(uint32_t *)first_cluster = htole32(
FAT_EXTD(fs) | b.
media);
116 int eff_size, alloc_size;
118 void *first, *second = NULL;
119 int first_ok, second_ok = 0;
121 uint32_t total_num_clusters;
124 die(
"Requested FAT table %ld does not exist.",
fat_table);
126 die(
"Reading FAT table greather than 2 is implemented yet.");
132 eff_size = (total_num_clusters * fs->
fat_bits + 7) / 8ULL;
135 alloc_size = eff_size;
139 alloc_size = (total_num_clusters * 12 + 23) / 24 * 3;
141 first =
alloc(alloc_size);
143 get_fat(&first_media, first, 0, fs);
146 second =
alloc(alloc_size);
148 get_fat(&second_media, second, 0, fs);
152 if (!first_ok && second && !second_ok)
153 die(
"Both FATs appear to be corrupt. Giving up. Run fsck.fat with non-zero -F option.");
154 if (!first_ok && !second)
155 die(
"First FAT appears to be corrupt and second FAT does not exist. Giving up. Run fsck.fat with -F 1 option.");
157 if (mode == 0 && !first_ok && second && second_ok) {
159 void *first_backup = first;
161 second = first_backup;
163 if (mode != 0 &&
fat_table == 0 && second && memcmp(first, second, eff_size) != 0) {
165 die(
"FATs differ, please run fsck.fat");
166 if (first_ok && !second_ok) {
167 printf(
"FATs differ - using first FAT.\n");
169 }
else if (!first_ok && second_ok) {
170 printf(
"FATs differ - using second FAT.\n");
172 memcpy(first, second, eff_size);
174 if (first_ok && second_ok)
175 printf(
"FATs differ but appear to be intact.\n");
177 printf(
"FATs differ and both appear to be corrupt.\n");
181 2,
"Use second FAT") == 1) {
193 memcpy(first, second, eff_size);
199 printf(
"Using first FAT.\n");
204 if (second && memcmp(first, second, eff_size) != 0)
207 printf(
"Using second FAT.\n");
212 if (memcmp(first, second, eff_size) != 0) {
214 memcpy(first, second, eff_size);
221 fs->
fat = (
unsigned char *)first;
233 if (curEntry.
value == 1) {
235 die(
"Cluster %ld out of range (1), please run fsck.fat",
237 printf(
"Cluster %ld out of range (1). Setting to EOF.\n",
244 die(
"Cluster %ld out of range (%ld > %ld), please run fsck.fat",
245 (
long)(i - 2), (
long)curEntry.
value,
247 printf(
"Cluster %ld out of range (%ld > %ld). Setting to EOF.\n",
248 (
long)(i - 2), (
long)curEntry.
value,
270 unsigned char *data = NULL;
275 die(
"Internal error: cluster out of range in set_fat() (%lu > %lu).",
276 (
unsigned long)cluster, (
unsigned long)(fs->
data_clusters + 1));
281 else if ((
long)
new == -2)
284 die(
"Internal error: new cluster out of range in set_fat() (%lu > %lu).",
290 data = fs->
fat + cluster * 3 / 2;
294 get_fat(&prevEntry, fs->
fat, cluster - 1, fs);
295 data[0] = ((
new & 0xf) << 4) | (prevEntry.
value >> 8);
300 get_fat(&subseqEntry, fs->
fat, cluster + 1, fs);
302 subseqEntry.
value = 0;
303 data[0] =
new & 0xff;
304 data[1] = (
new >> 8) | ((0xff & subseqEntry.
value) << 4);
309 data = fs->
fat + cluster * 2;
311 *(
unsigned short *)data = htole16(
new);
319 data = fs->
fat + cluster * 4;
323 *(uint32_t *)data = htole32((
new & 0xfffffff) |
362 value = curEntry.
value;
364 die(
"Internal error: next_cluster on bad cluster");
386 die(
"Internal error: attempt to set owner in non-existent table");
390 die(
"Internal error: attempt to change file owner");
407 printf(
"Checking for bad clusters.\n");
414 printf(
"Cluster %lu is unreadable.\n", (
unsigned long)i);
426 printf(
"Checking for unused clusters.\n");
439 printf(
"Reclaimed %d unused cluster%s (%llu bytes).\n", (
int)reclaimed,
440 reclaimed == 1 ?
"" :
"s",
455 uint32_t start_cluster)
460 if (start_cluster == 0)
472 for (walk = i; walk != -1; walk =
next_cluster(fs, walk)) {
505 int reclaimed, files;
507 uint32_t i, next, walk;
508 uint32_t *num_refs = NULL;
509 uint32_t total_num_clusters;
512 printf(
"Reclaiming unconnected clusters.\n");
515 num_refs =
alloc(total_num_clusters *
sizeof(uint32_t));
516 memset(num_refs, 0, (total_num_clusters *
sizeof(uint32_t)));
522 for (i = 2; i < total_num_clusters; i++) {
526 next = curEntry.
value;
527 if (!
get_owner(fs, i) && next && next < fs->data_clusters + 2) {
547 tag_free(fs, &orphan, num_refs, changed);
551 for (i = 2; i < total_num_clusters; i++) {
557 if (!num_refs[curEntry.
value]--)
558 die(
"Internal error: num_refs going below zero");
560 changed = curEntry.
value;
561 printf(
"Broke cycle at cluster %lu in free chain.\n", (
unsigned long)i);
566 if (num_refs[curEntry.
value] == 0)
574 files = reclaimed = 0;
575 for (i = 2; i < total_num_clusters; i++)
577 if (
get_owner(fs, i) == &orphan && !num_refs[i]) {
582 de.
start = htole16(i & 0xffff);
585 for (walk = i; walk > 0 && walk != -1;
593 printf(
"Reclaimed %d unused cluster%s (%llu bytes) in %d chain%s.\n",
594 reclaimed, reclaimed == 1 ?
"" :
"s",
595 (
unsigned long long)reclaimed * fs->
cluster_size, files,
596 files == 1 ?
"" :
"s");
619 printf(
"Checking free cluster summary.\n");
622 printf(
"Free cluster summary wrong (%ld vs. really %ld)\n",
627 2,
"Don't correct") == 1)
631 printf(
"Free cluster summary uninitialized (should be %ld)\n", (
long)free);
636 2,
"Leave it uninitialized") == 1)
642 uint32_t le_free = htole32(free);
645 sizeof(le_free), &le_free);
off_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern, int gen_name)
void die(const char *msg,...)
int get_choice(int noninteractive_result, const char *noninteractive_msg, int choices,...)
void reclaim_free(DOS_FS *fs)
uint32_t next_cluster(DOS_FS *fs, uint32_t cluster)
void set_owner(DOS_FS *fs, uint32_t cluster, DOS_FILE *owner)
void release_fat(DOS_FS *fs)
int bad_cluster(DOS_FS *fs, uint32_t cluster)
uint32_t update_free(DOS_FS *fs)
void read_fat(DOS_FS *fs, int mode)
off_t cluster_start(DOS_FS *fs, uint32_t cluster)
static void tag_free(DOS_FS *fs, DOS_FILE *owner, uint32_t *num_refs, uint32_t start_cluster)
DOS_FILE * get_owner(DOS_FS *fs, uint32_t cluster)
static void fix_first_cluster(DOS_FS *fs, void *first_cluster)
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)
void reclaim_file(DOS_FS *fs)
#define FAT_IS_BAD(fs, v)
#define FAT_IS_EOF(fs, v)
int fs_test(off_t pos, int size)
void fs_read(off_t pos, int size, void *data)
void fs_write(off_t pos, int size, void *data)
static unsigned char * fat
unsigned int cluster_size
DOS_FILE ** cluster_owner