fsck_msdosfs: truncate directory entry when the head pointer is invalid.
As far as we know, there is no FAT implementation that supported hard links, and our msdosfs driver assumed one cluster chain is only referenced by one directory entry and clears it out when the file is deleted. On the other hand, the current code would proceed with checkchain() when the directory entry's head cluster is a valid numbered cluster without checking if it was a valid head node of a cluster chain. So if the cluster do not being a chain (e.g. CLUST_FREE, CLUST_BAD), or was already referenced by another directory entry, this would trigger an assertion in check_chain() at a later time. Fix this by giving the user an option to truncate the directory entry when the head cluster is an invalid cluster, an visited head node, or not a head node. Reported by: NetApp (kevans@) Reviewed by: kevans, emaste (no objection) MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D32699
This commit is contained in:
parent
15bd9fa3be
commit
890cae1977
@ -400,8 +400,21 @@ checksize(struct fat_descriptor *fat, u_char *p, struct dosDirEntry *dir)
|
||||
if (dir->head == CLUST_FREE) {
|
||||
physicalSize = 0;
|
||||
} else {
|
||||
if (!fat_is_valid_cl(fat, dir->head))
|
||||
return FSERROR;
|
||||
if (!fat_is_valid_cl(fat, dir->head) || !fat_is_cl_head(fat, dir->head)) {
|
||||
pwarn("Directory entry %s of size %u referencing invalid cluster %u\n",
|
||||
fullpath(dir), dir->size, dir->head);
|
||||
if (ask(1, "Truncate")) {
|
||||
p[28] = p[29] = p[30] = p[31] = 0;
|
||||
p[26] = p[27] = 0;
|
||||
if (boot->ClustMask == CLUST32_MASK)
|
||||
p[20] = p[21] = 0;
|
||||
dir->size = 0;
|
||||
dir->head = CLUST_FREE;
|
||||
return FSDIRMOD;
|
||||
} else {
|
||||
return FSERROR;
|
||||
}
|
||||
}
|
||||
ret = checkchain(fat, dir->head, &chainsize);
|
||||
/*
|
||||
* Upon return, chainsize would hold the chain length
|
||||
|
Loading…
x
Reference in New Issue
Block a user