686 lines
20 KiB
C
686 lines
20 KiB
C
/**************************************************************************
|
|
* *
|
|
* Copyright (C) 1993 Silicon Graphics, Inc. *
|
|
* *
|
|
* These coded instructions, statements, and computer programs contain *
|
|
* unpublished proprietary information of Silicon Graphics, Inc., and *
|
|
* are protected by Federal copyright law. They may not be disclosed *
|
|
* to third parties or copied or duplicated in any form, in whole or *
|
|
* in part, without the prior written consent of Silicon Graphics, Inc. *
|
|
* *
|
|
**************************************************************************/
|
|
|
|
#ident "$Revision: 1.6 $"
|
|
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <bstring.h>
|
|
#include <time.h>
|
|
#include <sys/types.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
#include "fpck.h"
|
|
#include "dosfs.h"
|
|
#include "macLibrary.h" /* adopt the error code */
|
|
|
|
/* utilities functions of fat file system */
|
|
static void clearfatbitmap(dfs_t *, u_short);
|
|
static u_short readfatbitmap(dfs_t *, u_short);
|
|
static int readRootCabinet(dfs_t *);
|
|
static void travFileTree(dfs_t *, dfile_t *, int, FALLOCINFO *, int);
|
|
static int sanitychk(dfs_t *, u_short);
|
|
static void verifyFile(dfs_t *, dfile_t *, FALLOCINFO *, int);
|
|
static int scanbitmap(dfs_t *);
|
|
static void concludeCheck(dfs_t *, int);
|
|
static int chainLostCluster(dfs_t *, u_short, int);
|
|
static int createEntry(dfs_t *, u_short, int, int);
|
|
static int loopClustersChain(dfs_t *, int, CLUSTERLIST **, int);
|
|
static CLUSTERLIST * fatClusterCell(dfs_t * dfs, int);
|
|
static FALLOCINFO * readSubdirCabinet(dfs_t *, dfile_t *, dfile_t **,
|
|
int *, FALLOCINFO *, int);
|
|
static void reportEntryError(FALLOCINFO *, dfile_t *, int);
|
|
static void fatfpckexit(dfs_t *);
|
|
|
|
extern int debug_flag;
|
|
|
|
#ifdef DEBUG
|
|
#include "fatchk.debug"
|
|
#endif /* DEBUG */
|
|
|
|
|
|
/*-------- BeginScanLoop -------------------------------------
|
|
|
|
the main routine for DOS FAT file system checking.
|
|
this function traverse the entire file system and
|
|
diagnose the structure of each found file or
|
|
subdirectory.
|
|
|
|
------------------------------------------------------------*/
|
|
|
|
void
|
|
BeginScanLoop(dfs_t * dfs, int mode)
|
|
{
|
|
/* traverse file system for individual file diagnostic */
|
|
travFileTree(dfs, dfs->dfs_root, dfs->dfs_rootsize,
|
|
(FALLOCINFO *)NULL, mode);
|
|
|
|
if (debug_flag)
|
|
fpMessage("fatchk.c:BeginScanLoop: travFileTree Completed.");
|
|
|
|
#ifdef DEBUG
|
|
travTreeprint(dfs->fblkheadp);
|
|
pscanbitmap(dfs);
|
|
#else /* DEBUG */
|
|
concludeCheck(dfs, mode);
|
|
|
|
if (debug_flag)
|
|
fpMessage("fatchk.c:BeginScanLoop: concludeCheck Completed.");
|
|
#endif /* DEBUG */
|
|
}
|
|
|
|
|
|
/*-------- concludeCheck -------------------------------------
|
|
|
|
this function analyze both collected corss lined
|
|
cluster list and FAT bitmap (the being used clusters
|
|
map, used to compare against FAT) to make final
|
|
correction, if the used specified.
|
|
|
|
------------------------------------------------------------*/
|
|
|
|
static void
|
|
concludeCheck(dfs_t * dfs, int needcorrect)
|
|
{
|
|
CLUSTERLIST * nclusterp;
|
|
FALLOCINFO * curfilep;
|
|
u_short cluster;
|
|
int i, j, entrychanged = 0;
|
|
int error;
|
|
int lostclusters;
|
|
int lostchain = 0;
|
|
int fclusters; /* the number of clusters which
|
|
has been chained into a file */
|
|
|
|
/* handle the files globally cross linked */
|
|
while (dfs->crosslinklist) {
|
|
nclusterp = dfs->crosslinklist->nextcluster;
|
|
|
|
/* search the target cluster against the file cluster
|
|
information list to find the files which own this cluster */
|
|
curfilep = dfs->fblkheadp;
|
|
while (curfilep = searchCrossLinked(curfilep, dfs->crosslinklist)) {
|
|
fpWarn("file %s is cross linked on allocation unit %d\n",
|
|
getUnixPath(curfilep, NULL),
|
|
dfs->crosslinklist->clusterno);
|
|
|
|
curfilep = curfilep->nextfile;
|
|
}
|
|
free((char *) dfs->crosslinklist);
|
|
dfs->crosslinklist = nclusterp;
|
|
}
|
|
|
|
if (lostclusters = scanbitmap(dfs)) {
|
|
|
|
for (i = 0; i < dfs->fatbitmapsz; i++) {
|
|
for (j = 0; j < 8; j++) {
|
|
if ((dfs->fatbitmapp)[i] & (0x01 << j)) {
|
|
cluster = i*BITMAPUNITSZ+j;
|
|
fclusters = chainLostCluster(dfs, cluster, needcorrect);
|
|
lostchain++;
|
|
if (needcorrect &&
|
|
createEntry(dfs, cluster, lostchain, fclusters))
|
|
entrychanged++;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
if (entrychanged)
|
|
dfs->dirtyrootdir = TRUE;
|
|
|
|
fpWarn("there are(is) %d lost cluster found in %d data chain(s)",
|
|
lostclusters, lostchain);
|
|
}
|
|
|
|
if (needcorrect) {
|
|
if (dfs->dirtyrootdir) {
|
|
lseek(dfs->dfs_fd, dfs->dfs_rootaddr, 0);
|
|
if ((error = rfpblockwrite(dfs->dfs_fd, (u_char *) dfs->dfs_root,
|
|
dfs->dfs_rootsize)) != E_NONE) {
|
|
if (error == E_PROTECTION)
|
|
fpError("Medium is write-protected\n");
|
|
else
|
|
fpError("can't write file system information, the floppy is not safe to use!");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
if (dfs->dirtyfat) {
|
|
lseek(dfs->dfs_fd, dfs->dfs_fataddr, 0);
|
|
for (i = 0; i < dfs->dfs_bp.bp_fatcount; i++) {
|
|
if ((error = rfpblockwrite(dfs->dfs_fd, (u_char *) dfs->dfs_fat,
|
|
dfs->dfs_fatsize)) != E_NONE) {
|
|
if (error == E_PROTECTION)
|
|
fpError("Medium is write-protected\n");
|
|
else
|
|
fpError("can't write file system information, the floppy is not safe to use!");
|
|
exit(1);
|
|
}
|
|
lseek(dfs->dfs_fd,
|
|
dfs->dfs_fataddr + dfs->dfs_fatsize * (i + 1), 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
fatfpckexit(dfs);
|
|
}
|
|
|
|
|
|
/*-------- createEntry -------------------------
|
|
|
|
create the entries in the root
|
|
directory for each found data chain.
|
|
|
|
------------------------------------------------*/
|
|
|
|
static int
|
|
createEntry(dfs_t * dfs, u_short startcluster, int chainth, int chainsz)
|
|
{
|
|
time_t mtime;
|
|
dfile_t dfe;
|
|
dfile_t * dfp;
|
|
int i, size;
|
|
|
|
bzero(&dfe, sizeof(dfile_t));
|
|
sprintf(dfe.df_name, "FILE%.4d", chainth);
|
|
strcpy(dfe.df_ext, "CHK");
|
|
dfe.df_attribute = ATTRIB_ARCHIVE;
|
|
mtime = time(NULL);
|
|
to_dostime(dfe.df_date, dfe.df_time, &mtime);
|
|
dfe.df_start[0] = startcluster & 0xff;
|
|
dfe.df_start[1] = startcluster >> 8;
|
|
size = dfs->dfs_clustersize*chainsz;
|
|
dfe.df_size[0] = size & 0xff;
|
|
dfe.df_size[1] = (size >> 8) & 0xff;
|
|
dfe.df_size[2] = (size >> 16) & 0xff;
|
|
dfe.df_size[3] = (size >> 24) & 0xff;
|
|
|
|
for (i = dfs->dfs_rootsize / DIR_ENTRY_SIZE, dfp = dfs->dfs_root;
|
|
i > 0; i--, dfp++) {
|
|
if (dfp->df_name[0] == LAST_ENTRY ||
|
|
dfp->df_name[0] == REUSABLE_ENTRY) {
|
|
|
|
* dfp = dfe;
|
|
|
|
return(E_NONE);
|
|
}
|
|
}
|
|
return(E_SPACE);
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
scanbitmap(dfs_t * dfs)
|
|
{
|
|
int i, j, count =0;
|
|
|
|
for (i = 0; i < dfs->fatbitmapsz; i++)
|
|
for (j = 0; j < 8; j++)
|
|
if ((dfs->fatbitmapp)[i] & (0x01 << j))
|
|
count++;
|
|
|
|
return count;
|
|
}
|
|
|
|
static void
|
|
fatfpckexit(dfs_t * dfs)
|
|
{
|
|
FALLOCINFO * curp;
|
|
CLUSTERLIST * curclusterp;
|
|
|
|
if (dfs->dfs_fat)
|
|
free (dfs->dfs_fat);
|
|
|
|
if (dfs->dfs_root)
|
|
free (dfs->dfs_root);
|
|
|
|
if (dfs->fatbitmapp)
|
|
free(dfs->fatbitmapp);
|
|
|
|
releaseFalloc(&(dfs->fblkheadp));
|
|
|
|
while (dfs->crosslinklist) {
|
|
curclusterp = dfs->crosslinklist;
|
|
dfs->crosslinklist = (dfs->crosslinklist)->nextcluster;
|
|
free((char *) curclusterp);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static u_short
|
|
readfatbitmap(dfs_t * dfs, u_short cluster)
|
|
{
|
|
int offset, index;
|
|
|
|
if (!(dfs->fatbitmapp) || cluster > dfs->fatbitmapsz*BITMAPUNITSZ) {
|
|
fpError("The program encount a bizarre situation");
|
|
exit(1);
|
|
}
|
|
index = cluster / BITMAPUNITSZ;
|
|
offset = cluster % BITMAPUNITSZ;
|
|
return((dfs->fatbitmapp)[index] & (0x01 << offset));
|
|
}
|
|
|
|
|
|
void
|
|
setfatbitmap(dfs_t * dfs, u_short cluster)
|
|
{
|
|
int offset, index;
|
|
BITMAPUNIT tmp;
|
|
|
|
if (!(dfs->fatbitmapp) && cluster > dfs->fatbitmapsz*BITMAPUNITSZ) {
|
|
fpError("The program encount a bizarre situation");
|
|
exit(1);
|
|
}
|
|
index = cluster / BITMAPUNITSZ;
|
|
offset = cluster % BITMAPUNITSZ;
|
|
/* (dfs->fatbitmapp)[index] |= (0x01 << offset); */
|
|
tmp = (0x01 << offset);
|
|
(dfs->fatbitmapp)[index] |= tmp;
|
|
}
|
|
|
|
|
|
static void
|
|
clearfatbitmap(dfs_t * dfs, u_short cluster)
|
|
{
|
|
int offset, index;
|
|
|
|
if (!(dfs->fatbitmapp) && cluster > dfs->fatbitmapsz*BITMAPUNITSZ) {
|
|
fpError("The program encount a bizarre situation");
|
|
exit(1);
|
|
}
|
|
index = cluster / BITMAPUNITSZ;
|
|
offset = cluster % BITMAPUNITSZ;
|
|
(dfs->fatbitmapp)[index] &= ~(0x1 << offset);
|
|
}
|
|
|
|
/*-------- readRootCabinet -------------------
|
|
|
|
read the root directory from floppy
|
|
|
|
--------------------------------------------*/
|
|
|
|
static int
|
|
readRootCabinet(dfs_t * dfs)
|
|
{
|
|
int retval = E_NONE;
|
|
|
|
dfs->dfs_root = (dfile_t *) safemalloc(dfs->dfs_rootsize);
|
|
lseek(dfs->dfs_fd, dfs->dfs_rootaddr, 0);
|
|
return(rfpblockread(dfs->dfs_fd, (u_char *) dfs->dfs_root,
|
|
dfs->dfs_rootsize));
|
|
}
|
|
|
|
|
|
/*-------- travFileTree -----------------------------------------
|
|
|
|
a recursive routine to traverse the entire file
|
|
system, and perform the individual file stucture diagnostic.
|
|
|
|
---------------------------------------------------------------*/
|
|
|
|
static void
|
|
travFileTree(dfs_t * dfs, dfile_t * findex, int dirsz,
|
|
FALLOCINFO * parentdirp, int mode)
|
|
{
|
|
char * tmpname, * dirpath;
|
|
int dirpathlen;
|
|
int i, retsz = 0;
|
|
int count, filenum;
|
|
dfile_t * sdf = 0;
|
|
dfile_t * df = findex;
|
|
FALLOCINFO * suballocinfop;
|
|
|
|
filenum = (dirsz+DIR_ENTRY_SIZE-1) / DIR_ENTRY_SIZE;
|
|
for (i = 0; i < filenum; i++, df++) {
|
|
if (df->df_name[0] == LAST_ENTRY)
|
|
break; /* end of directory */
|
|
|
|
if (df->df_name[0] == REUSABLE_ENTRY)
|
|
continue; /* reusable entry */
|
|
|
|
if (df->df_attribute & ATTRIB_LABEL)
|
|
continue; /* volume label */
|
|
|
|
if (df->df_attribute & ATTRIB_DIR) {
|
|
if (df->df_name[0] != '.') {
|
|
#ifdef DEBUG1
|
|
showfile(dfs, df, parentdirp);
|
|
#endif /* DEBUG */
|
|
suballocinfop = readSubdirCabinet(dfs, df, &sdf,
|
|
&retsz, parentdirp, mode);
|
|
if (suballocinfop) {
|
|
travFileTree(dfs, sdf, retsz, suballocinfop, mode);
|
|
if (sdf)
|
|
free(sdf);
|
|
}
|
|
}
|
|
} else
|
|
#ifndef DEBUG1
|
|
verifyFile(dfs, df, parentdirp, mode);
|
|
#else /*DEBUG */
|
|
showfile(dfs, df, parentdirp);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
sanitychk(dfs_t * dfs, u_short cluster)
|
|
{
|
|
int retval = E_NONE;
|
|
|
|
/* cluster 0 and 1 are not legal */
|
|
if (cluster == 1 || cluster == 0)
|
|
retval = E_UNKNOWN;
|
|
|
|
else if (LAST_CLUSTER(dfs, cluster))
|
|
retval = E_USERSTOP;
|
|
|
|
/* need to consider the bad sector condition */
|
|
|
|
return(retval);
|
|
}
|
|
|
|
|
|
/*-------- readSubdirCabinet ----------------------------------
|
|
|
|
In DOS, subdirectory structure is same with file.
|
|
read in the subdirectory clusters according to FAT table.
|
|
|
|
--------------------------------------------------------------*/
|
|
|
|
static FALLOCINFO *
|
|
readSubdirCabinet(dfs_t * dfs, dfile_t * df, dfile_t ** fpp,
|
|
int * cabinetsz, FALLOCINFO * subdirinfop, int needcorrect)
|
|
{
|
|
int retval = E_NONE;
|
|
u_char * bp;
|
|
char * fullpath = NULL;
|
|
dfile_t * findex;
|
|
u_short cluster;
|
|
int subdircnt = 0;
|
|
int index = 0;
|
|
CLUSTERLIST * subdirheadp = NULL;
|
|
CLUSTERLIST * subdircurp;
|
|
FALLOCINFO * curfbinfop = NULL;
|
|
|
|
/* set 0 before the file cabinet being initialized */
|
|
* cabinetsz = 0;
|
|
cluster = getstartcluster(df);
|
|
|
|
retval = loopClustersChain(dfs, cluster, &subdirheadp, needcorrect);
|
|
|
|
/* the subdirectory is empty */
|
|
if (subdirheadp == (CLUSTERLIST *) NULL) {
|
|
reportEntryError(subdirinfop, df, ATTRIB_ARCHIVE);
|
|
return(curfbinfop);
|
|
}
|
|
|
|
/* create the file/subdirectory allocation
|
|
info block, and link it to the list */
|
|
curfbinfop = fAllocInfoCell(getdosname(df), &subdirheadp,
|
|
countClusterCell(subdirheadp),
|
|
&(dfs->fblkheadp), subdirinfop,
|
|
&dfs->crosslinklist);
|
|
|
|
/* allocate the space to store the subdir file entries */
|
|
findex = (dfile_t *)
|
|
safemalloc(dfs->dfs_clustersize*curfbinfop->blknum);
|
|
* fpp = findex; /* return as the first file entry */
|
|
bp = (u_char *) findex;
|
|
while (index < curfbinfop->blknum) {
|
|
lseek(dfs->dfs_fd, DISK_ADDR(dfs, curfbinfop->blkv[index]), 0);
|
|
fpblockread(dfs->dfs_fd, bp, dfs->dfs_clustersize);
|
|
bp += dfs->dfs_clustersize;
|
|
* cabinetsz += dfs->dfs_clustersize;
|
|
index++;
|
|
}
|
|
|
|
if (retval == E_UNKNOWN)
|
|
fpWarn("subdirectory %s has invalid allocation unit",
|
|
fullpath = getUnixPath(curfbinfop, NULL));
|
|
else if (retval == E_SELFLINK) /* self linked */
|
|
fpWarn("subdirectory %s is delf linked",
|
|
fullpath = getUnixPath(curfbinfop, NULL));
|
|
|
|
if (fullpath)
|
|
free(fullpath);
|
|
|
|
return(curfbinfop) ;
|
|
}
|
|
|
|
|
|
/*-------- verifyFile ----------------------------------
|
|
|
|
check the file integrity by scanning the data
|
|
chain consecutive described in the FAT table.
|
|
|
|
--------------------------------------------------------------*/
|
|
|
|
static void
|
|
verifyFile(dfs_t * dfs, dfile_t * df, FALLOCINFO * subinfop, int needcorrect)
|
|
{
|
|
char * fullpath;
|
|
char * filename;
|
|
int retval = E_NONE;
|
|
FALLOCINFO * curfbinfop;
|
|
FALLOCINFO * croslnkfinfop = NULL;
|
|
int cluster;
|
|
int fdocsz;
|
|
CLUSTERLIST * curfclusterp;
|
|
CLUSTERLIST * fheaderp = NULL;
|
|
|
|
fdocsz = (getfilesz(df)+dfs->dfs_clustersize-1) / dfs->dfs_clustersize;
|
|
|
|
cluster = getstartcluster(df);
|
|
|
|
retval = loopClustersChain(dfs, cluster, &fheaderp, needcorrect);
|
|
|
|
/* the file is empty */
|
|
if (fheaderp == (CLUSTERLIST *) NULL) {
|
|
reportEntryError(subinfop, df, ATTRIB_ARCHIVE);
|
|
return;
|
|
}
|
|
|
|
/* create the file/subdirectory allocation
|
|
info block, and link it to the list */
|
|
curfbinfop = fAllocInfoCell(getdosname(df), &fheaderp,
|
|
countClusterCell(fheaderp),
|
|
&(dfs->fblkheadp), subinfop,
|
|
&dfs->crosslinklist);
|
|
|
|
fullpath = getUnixPath(curfbinfop, NULL);
|
|
|
|
/* try to bring up all the possible errors */
|
|
if (retval == E_UNKNOWN) {
|
|
|
|
/* if this file contain the invalid allocation unit */
|
|
if (fdocsz < curfbinfop->blknum)
|
|
fpWarn("file %s has invalid cluster unit, file expanded",
|
|
fullpath);
|
|
else if (fdocsz > curfbinfop->blknum)
|
|
fpWarn("file %s has invalid cluster unit, file truncated",
|
|
fullpath);
|
|
else
|
|
fpWarn("file %s has invalid cluster unit");
|
|
|
|
} else if (retval == E_SELFLINK) {
|
|
|
|
fpWarn("file %s data chain is self linkd", fullpath);
|
|
|
|
} else {
|
|
|
|
if (fdocsz < curfbinfop->blknum)
|
|
fpWarn("file %s has been expaned", fullpath);
|
|
|
|
else if (fdocsz > curfbinfop->blknum)
|
|
fpWarn("file %s has been truncated.\n", fullpath);
|
|
}
|
|
|
|
free(fullpath);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/*-------- chainLostCluster -------------------------------------
|
|
|
|
chain the lost cluters of the FAT table
|
|
into the individual file
|
|
|
|
---------------------------------------------------------------*/
|
|
|
|
static int
|
|
chainLostCluster(dfs_t * dfs, u_short firstcluster, int needcorrect)
|
|
{
|
|
int retval = E_NONE;
|
|
int count = 0; /* default is one */
|
|
int cluster, oldcluster = 0;
|
|
|
|
cluster = firstcluster;
|
|
|
|
/* only one cluster in this chain */
|
|
if (LAST_CLUSTER(dfs, cluster)) {
|
|
clearfatbitmap(dfs, cluster);
|
|
return ++count;
|
|
}
|
|
|
|
while (1) {
|
|
|
|
/* do the cluster chain sanity checking */
|
|
if ((retval = sanitychk(dfs, cluster)) != E_NONE)
|
|
break;
|
|
|
|
count++;
|
|
clearfatbitmap(dfs, cluster);
|
|
oldcluster = cluster; /* save the previous cluster pointer */
|
|
cluster = (*dfs->dfs_readfat)(dfs, cluster);
|
|
}
|
|
|
|
if (retval != E_USERSTOP && needcorrect) {
|
|
if (oldcluster != 0) {
|
|
(*dfs->dfs_writefat)(dfs, cluster, dfs->dfs_endclustermark);
|
|
dfs->dirtyfat = TRUE;
|
|
}
|
|
} else
|
|
count++;
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
|
|
CLUSTERLIST *
|
|
fatClusterCell(dfs_t * dfs, int cluster)
|
|
{
|
|
CLUSTERLIST * curcellp;
|
|
|
|
curcellp = safemalloc(sizeof(CLUSTERLIST));
|
|
if (readfatbitmap(dfs, cluster)) {
|
|
|
|
clearfatbitmap(dfs, cluster);
|
|
curcellp->status = E_NONE;
|
|
} else
|
|
curcellp->status = E_CROSSLINK;
|
|
|
|
curcellp->clusterno = cluster;
|
|
curcellp->nextcluster = NULL;
|
|
|
|
return(curcellp);
|
|
}
|
|
|
|
|
|
/*-------- loopClustersChain ----------------------------------------
|
|
|
|
the function will take the start cluster number from file
|
|
entry, and step through the cluster chain which described
|
|
int the FAT table.
|
|
return cases: E_USERSTOP, which means no error is found.
|
|
E_SELFLINK, the file is self linked.
|
|
E_UNKNOW, the invalis allocation unit is encounted.
|
|
|
|
-------------------------------------------------------------------*/
|
|
|
|
static int
|
|
loopClustersChain(dfs_t * dfs, int startc, CLUSTERLIST ** fheaderpp,
|
|
int needcorrect)
|
|
{
|
|
char * fullpath;
|
|
int retval = E_NONE;
|
|
int cluster = startc;
|
|
CLUSTERLIST * curfclusterp;
|
|
|
|
while (1) {
|
|
|
|
/* do the cluster chain sanity checking */
|
|
if ((retval = sanitychk(dfs, cluster)) != E_NONE)
|
|
break;
|
|
|
|
else {
|
|
curfclusterp = fatClusterCell(dfs, cluster);
|
|
if (curfclusterp->status == E_CROSSLINK)
|
|
/* detect the condition of the data
|
|
was self linked and became a loop */
|
|
if (selfLinked(* fheaderpp, cluster) != E_NONE) {
|
|
free((char *) curfclusterp);
|
|
retval = E_SELFLINK;
|
|
break;
|
|
}
|
|
linkClusterCells (fheaderpp, curfclusterp);
|
|
cluster = (*dfs->dfs_readfat)(dfs, cluster);
|
|
}
|
|
}
|
|
|
|
/* if it's not a smooth stop, and correction flag is on */
|
|
if (retval != E_USERSTOP && needcorrect) {
|
|
|
|
/* the last cell of the list points to this cluster */
|
|
curfclusterp = lastClusterCell(* fheaderpp);
|
|
|
|
/* it's a empty list, file entry must
|
|
contain invalid allocation unit */
|
|
if (curfclusterp) {
|
|
(* dfs->dfs_writefat) (dfs, curfclusterp->clusterno,
|
|
dfs->dfs_endclustermark);
|
|
dfs->dirtyfat = TRUE;
|
|
}
|
|
}
|
|
return(retval);
|
|
}
|
|
|
|
|
|
static void
|
|
reportEntryError(FALLOCINFO * subinfop, dfile_t * df, int attrib)
|
|
{
|
|
char * filename;
|
|
char * pathname;
|
|
|
|
/* entry is wrong, report the error */
|
|
filename = getdosname(df);
|
|
pathname = getUnixPath(subinfop, filename);
|
|
|
|
fpWarn("%s %s has invalid allocation unit in entry",
|
|
(attrib == ATTRIB_DIR) ? "subdirectory" : "file",
|
|
pathname);
|
|
|
|
free(filename);
|
|
free(pathname);
|
|
return;
|
|
}
|