📄 chkdsk.c
字号:
* . updates gl.n_hidden_clusters or ..
* . updates gl.n_file_clusters
* It then checks the bit map of already accounted for clusters, if the
* cluster is accounted for it adds the cluster to the list of lost
* chains by calling add_cluster_to_crossed(), if another cluster in the
* chain was already found to be crossed we don't call add_cluster_to_crossed()
* since it works with the whole chain.
*
* After the chain has been traversed its size is compared with the size
* recorded in the directory. If they differ the file is printed and if -f
* was specified the size is adjusted.
*/
short process_used_map(DROBJ *pobj, char *filename) /*__fn__*/
{
CLTYPE cluster;
CLTYPE n_clusters;
CLTYPE proper_size;
CLTYPE true_size;
short is_dir;
short is_hidden;
short found_an_intersection;
if (pc_isroot(pobj))
#if (!FAT32)
return(TRUE);
#else
/* FAT32 stores the root directory as a cluster chain */
{
if (pobj->pdrive->fasize == 8) /* FAT32 volume */
{
cluster = pc_sec2cluster(pobj->pdrive,pobj->pdrive->rootblock);
is_dir = TRUE;
}
else
return(TRUE);
}
#endif /* FAT32 */
else
{
/* For tracking crossed chains. We only want to note the intersection
points of lost chains not every cluster in the chain. */
if (pobj->finode->fattribute & ADIRENT)
is_dir = TRUE;
else
{
if (pobj->finode->fattribute & AHIDDEN)
is_hidden = TRUE;
else
is_hidden = FALSE;
is_dir = FALSE;
}
cluster = pc_finode_cluster(pobj->pdrive, pobj->finode);
}
found_an_intersection = FALSE;
n_clusters = 0;
while (cluster)
{
n_clusters += 1;
if ( (gl.cl_start <= cluster) && (cluster < gl.cl_end) )
{
/* If the cluster is already in use we have a problem it's
a crossed chain */
if ( get_bit(gl.bm_used, cluster - gl.cl_start) )
{
if (!found_an_intersection)
{
if (!add_cluster_to_crossed(cluster))
return(FALSE);
found_an_intersection = TRUE;
}
}
set_bit(gl.bm_used, cluster - gl.cl_start);
}
cluster = pc_clnext(pobj->pdrive, cluster);
}
if (gl.on_first_pass)
{
if (is_dir)
gl.n_dir_clusters += n_clusters;
else
{
if (is_hidden)
gl.n_hidden_clusters += n_clusters;
else
gl.n_file_clusters += n_clusters;
/* Check the file size here */
/* Re-use the true size variable to save a little stack (we're
inside a recursive algorithm here */
#define cl_size_minus_1 true_size
cl_size_minus_1 = pobj->pdrive->secpalloc;
cl_size_minus_1 <<= 9; /* *= 512 */
cl_size_minus_1 -=1;
/* This is how many bytes the file should occupy in the FAT. */
proper_size = (pobj->finode->fsize + cl_size_minus_1) & ~cl_size_minus_1;
#undef cl_size_minus_1
true_size = n_clusters;
true_size <<= pobj->pdrive->log2_secpalloc;
true_size <<= 9; /* *= 512 */
if (proper_size != true_size)
{
/* Size in the directory entry doesn't match the size of the
chain. If -f was specified update the file size in the directory */
if (gl.write_chains)
{
pobj->finode->fsize = true_size;
if (!pc_update_inode(pobj, TRUE, TRUE))
{
tm_printf_2("Failed Writing Adusted File: %s\n", filename);
return(FALSE);
}
tm_printf_2("Size Adusted, File: %s\n", filename);
}
else
{
tm_printf_2("Size Needs Adusting, File: %s\n", filename);
}
}
}
} /* if (on_first_pass) */
return(TRUE);
}
#if (VFAT)
/* scan_for_bad_lfns(DROBJ *pmom)
*
* Scan through a directory and count all Win95 long file name errors.
*
* Errors detected:
* Bad lfn checksums
* Bad lfn sequence numbers
* Stray lfn chains
* Incomplete lfn chains
*
* If gl.delete_bad_lfn is set, free up the directory space used up by
* invalid long file name information by deleting invalid chains
*
* Returns: number of invalid lfn chains found
*
* This fn is based on pc_findin (drobj.c)
*/
dword scan_for_bad_lfns(DROBJ *pmom) /*__fn__*/
{
DROBJ *pobj;
BLKBUFF *rbuf;
DIRBLK *pd;
DOSINODE *pi;
LFNINODE *lfn_node;
SEGDESC s;
byte lastsegorder;
dword bad_lfn_count;
pc_zeroseglist(&s);
lastsegorder = 0;
/* pobj will be used to scan through the directory */
pobj = pc_mkchild(pmom);
if (!pobj)
return(0);
bad_lfn_count = 0;
/* For convenience. We want to get at block info here */
pd = &pobj->blkinfo;
/* Read the data */
pobj->pblkbuff = rbuf = pc_read_blk(pobj->pdrive, pobj->blkinfo.my_block);
while (rbuf)
{
pi = (DOSINODE *) &rbuf->data[0];
/* Look at the current inode */
pi += pd->my_index;
while ( pd->my_index < INOPBLOCK )
{
/* End of dir if name is 0 */
if (!pi->fname[0])
{
pc_free_buf(rbuf,FALSE);
pc_freeobj(pobj);
return(bad_lfn_count);
}
if (pi->fname[0] == PCDELETE)
{
if (s.nsegs)
{
/* lfn chain interrupted by empty dir entry */
bad_lfn_count++;
if (gl.delete_bad_lfn)
pc_deleteseglist(pobj->pdrive, &s);
pc_zeroseglist(&s);
lastsegorder = 0;
}
}
else
{
if (pi->fattribute == CHICAGO_EXT)
{
/* Found a piece of an lfn */
lfn_node = (LFNINODE *) pi;
if (lfn_node->lfnorder & FIRST_NAMESEG)
{
if (s.nsegs) /* if a chain already exists */
{
/* lfn chain begins in the middle of another one;
Delete the one that was interrupted, keep the
new one. */
bad_lfn_count++;
if (gl.delete_bad_lfn)
pc_deleteseglist(pobj->pdrive, &s);
pc_zeroseglist(&s);
}
lastsegorder = lfn_node->lfnorder;
pc_addtoseglist(&s, pd->my_block, pd->my_index);
s.ncksum = lfn_node->lfncksum;
}
else
{
/* optimization - the current segment should first be
linked onto the chain in each of the branches
below */
pc_addtoseglist(&s, pd->my_block, pd->my_index);
if ((s.nsegs - 1) &&
(lfn_node->lfnorder & NAMESEG_ORDER) == (lastsegorder & NAMESEG_ORDER) - 1 &&
lfn_node->lfncksum == s.ncksum )
{
/* Sequence number and checksum match; Add new
segment to lfn chain */
lastsegorder = lfn_node->lfnorder;
}
else
{
/* New segment has a checksum or sequence number
that doesn't match the current chain; Delete
the whole chain plus new segment */
bad_lfn_count++;
if (gl.delete_bad_lfn)
pc_deleteseglist(pobj->pdrive, &s);
pc_zeroseglist(&s);
lastsegorder = 0;
}
}
}
else
/* if (pi->fattribute != CHICAGO_EXT) */
{
/* Found a file entry - make sure our lfn chain matches
(if we have one) */
if (s.nsegs) /* if a chain has been built up */
{
if (pc_cksum((byte*)pi) != s.ncksum ||
(lastsegorder & NAMESEG_ORDER) != 1)
{
/* chain's checksum doesn't match the DOSINODE,
or the last sequence number isn't 1; Delete
the lfn chain */
bad_lfn_count++;
if (gl.delete_bad_lfn)
pc_deleteseglist(pobj->pdrive, &s);
}
/* We want to release this chain, whether good or bad */
pc_zeroseglist(&s);
lastsegorder = 0;
}
} /* if (!CHICAGO_EXT) */
} /* if (!PCDELETE) */
pd->my_index++;
pi++;
}
/* Current block is clean; go to next one */
pc_free_buf(rbuf,FALSE);
/* Update the objects block pointer */
if (!pc_next_block(pobj))
break;
pd->my_index = 0;
pobj->pblkbuff = rbuf = pc_read_blk(pobj->pdrive, pobj->blkinfo.my_block);
}
pc_freeobj(pobj);
return (bad_lfn_count);
}
#endif /* VFAT */
/************************************************************************
* *
* Lost cluster fns *
* *
************************************************************************/
/* check_lost_clusters(DDRIVE *pdr)
*
* This routine is called by (app_entry()) after scan_all_files() was called
* to produce the bm_used bitmap of clusters cliamed by files and
* sub-direcories.
* It scans the FILE allocation table. A cluster is lost if it
* is allocated in the FAT but not in the bm_used bitmap we built up while
* scanning the file system (scan_all_files()). We maintain an array of
* chain heads of lost clusters.
*/
short check_lost_clusters(DDRIVE *pdr) /*__fn__*/
{
CLTYPE cluster;
CLTYPE nxt;
for (cluster = gl.cl_start ; cluster < gl.cl_end; cluster++)
{
if (!pc_faxx(pdr, cluster, &nxt))
{
return(FALSE);
}
if (nxt != 0)
{
/* If we didn't see the cluster during the directory scan */
if ( !get_bit(gl.bm_used, cluster - gl.cl_start) )
{
/* ff(f)7 marks a bad cluster if it is not already in
a chain. */
if ( ((pdr->fasize == 3) && (nxt == 0xff7)) ||
((pdr->fasize == 4) && (nxt == 0xfff7))
#if (FAT32)
&& ((pdr->fasize == 8) && (nxt == 0xfffffff7ul))
#endif /* FAT32 */
)
gl.n_bad_clusters += 1;
if ( ((pdr->fasize == 3) && ((nxt < 0xff0) || (nxt > 0xff8))) ||
((pdr->fasize == 4) && ((nxt < 0xfff0) || (nxt > 0xfff8)))
#if (FAT32)
|| ((pdr->fasize == 8) && ((nxt < 0xfffffff0ul) || (nxt > 0xfffffff8ul)))
#endif /* FAT32 */
)
{
/* And if it is not a bad or reserved cluster */
/* Add it to the lost list */
tm_printf_3("Add lost cluster %ld sector == %ld\n", (dword) cluster, pc_cl2sector(pdr, cluster));
if (!add_cluster_to_lost_list(pdr, cluster))
return(FALSE);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -