VfatReadBigCluster()/VfatReadSmallCluster()/

VfatWriteBigCluster()/VfatWriteSmallCluster():
- Fixed a bug, that will read data over the end
  of the given buffer or write wrong data to
  the disk, when there is a read without caching
  and the start is on the cluster boundery and
  the end not.
VfatReadSmallCluster()/VfatWriteSmallCluster():
- A cache segment is set to valid, when all clusters
  in the segment are readed or written.
VfatWriteSmallCluster():
- The Parameter Extend is set to TRUE (overwritten),
  when the data need a new cluster.
VfatReadFile()/VfatWriteFile():
- Added special handling for the root directory on
  fat12/fat16, so that a read or write operation
  does not touche the cluster area.
- Added some error handling.

svn path=/trunk/; revision=2165
This commit is contained in:
Hartmut Birr 2001-08-08 19:04:13 +00:00
parent c0cbc28359
commit 8eeb1a96b8

View file

@ -1,5 +1,5 @@
/* $Id: rw.c,v 1.29 2001/08/07 15:38:04 hbirr Exp $
/* $Id: rw.c,v 1.30 2001/08/08 19:04:13 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -136,14 +136,13 @@ VfatReadBigCluster(PDEVICE_EXTENSION DeviceExt,
else
{
Valid = FALSE;
if (InternalOffset == 0)
if (InternalLength == DeviceExt->BytesPerCluster)
{
BaseAddress = Destination;
}
else
{
BaseAddress = ExAllocatePool(NonPagedPool,
DeviceExt->BytesPerCluster);
BaseAddress = ExAllocatePool(NonPagedPool, DeviceExt->BytesPerCluster);
if (BaseAddress == NULL)
{
return(STATUS_NO_MEMORY);
@ -164,7 +163,7 @@ VfatReadBigCluster(PDEVICE_EXTENSION DeviceExt,
{
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, FALSE);
}
else if (InternalOffset != 0)
else if (InternalLength != DeviceExt->BytesPerCluster)
{
ExFreePool(BaseAddress);
}
@ -174,7 +173,7 @@ VfatReadBigCluster(PDEVICE_EXTENSION DeviceExt,
/*
* Copy the data from the cache to the caller
*/
if (InternalOffset != 0 || !NoCache)
if (InternalLength != DeviceExt->BytesPerCluster || !NoCache)
{
memcpy(Destination, BaseAddress + InternalOffset, InternalLength);
}
@ -182,7 +181,7 @@ VfatReadBigCluster(PDEVICE_EXTENSION DeviceExt,
{
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, TRUE);
}
else if (InternalOffset != 0)
else if (InternalLength != DeviceExt->BytesPerCluster)
{
ExFreePool(BaseAddress);
}
@ -230,7 +229,7 @@ VfatReadSmallCluster(PDEVICE_EXTENSION DeviceExt,
else
{
Valid = FALSE;
if (InternalOffset == 0)
if (InternalLength == PAGESIZE)
{
BaseAddress = Destination;
}
@ -265,7 +264,7 @@ VfatReadSmallCluster(PDEVICE_EXTENSION DeviceExt,
{
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, FALSE);
}
else if (InternalOffset != 0)
else if (InternalLength != PAGESIZE)
{
ExFreePool(BaseAddress);
}
@ -295,15 +294,16 @@ VfatReadSmallCluster(PDEVICE_EXTENSION DeviceExt,
/*
* Copy the data from the cache to the caller
*/
if (InternalOffset != 0 || !NoCache)
if (InternalLength != PAGESIZE || !NoCache)
{
memcpy(Destination, BaseAddress + InternalOffset, InternalLength);
}
if (!NoCache)
{
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, TRUE);
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg,
Valid || InternalLength == PAGESIZE ? TRUE : FALSE);
}
else if (InternalOffset != 0)
else if (InternalLength != PAGESIZE)
{
ExFreePool(BaseAddress);
}
@ -345,7 +345,6 @@ VfatReadCluster(PDEVICE_EXTENSION DeviceExt,
InternalOffset,
InternalLength));
}
return(STATUS_SUCCESS);
}
NTSTATUS
@ -402,6 +401,15 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
}
}
if (FirstCluster == 1)
{
// root directory of FAT12 od FAT16
if (ReadOffset + Length > DeviceExt->rootDirectorySectors * BLOCKSIZE)
{
Length = DeviceExt->rootDirectorySectors * BLOCKSIZE - ReadOffset;
}
}
/*
* Select an appropiate size for reads
*/
@ -436,35 +444,42 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
if ((ReadOffset % ChunkSize) != 0 )
{
TempLength = min (Length, ChunkSize - (ReadOffset % ChunkSize));
VfatReadCluster(DeviceExt, Fcb, ROUND_DOWN(ReadOffset, ChunkSize),
Status = VfatReadCluster(DeviceExt, Fcb, ROUND_DOWN(ReadOffset, ChunkSize),
FirstCluster, &CurrentCluster, Buffer, NoCache,
ReadOffset % ChunkSize, TempLength);
if (NT_SUCCESS(Status))
{
(*LengthRead) = (*LengthRead) + TempLength;
Length = Length - TempLength;
Buffer = Buffer + TempLength;
ReadOffset = ReadOffset + TempLength;
}
}
while (Length >= ChunkSize && CurrentCluster)
while (Length >= ChunkSize && CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
{
VfatReadCluster(DeviceExt, Fcb, ReadOffset,
Status = VfatReadCluster(DeviceExt, Fcb, ReadOffset,
FirstCluster, &CurrentCluster, Buffer, NoCache, 0,
ChunkSize);
if (NT_SUCCESS(Status))
{
(*LengthRead) = (*LengthRead) + ChunkSize;
Buffer = Buffer + ChunkSize;
Length = Length - ChunkSize;
ReadOffset = ReadOffset + ChunkSize;
}
if (Length > 0 && CurrentCluster)
}
if (Length > 0 && CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
{
VfatReadCluster(DeviceExt, Fcb, ReadOffset,
Status = VfatReadCluster(DeviceExt, Fcb, ReadOffset,
FirstCluster, &CurrentCluster, Buffer, NoCache, 0,
Length);
if (NT_SUCCESS(Status))
{
(*LengthRead) = (*LengthRead) + Length;
}
return (STATUS_SUCCESS);
}
return Status;
}
NTSTATUS
@ -506,7 +521,7 @@ VfatWriteBigCluster(PDEVICE_EXTENSION DeviceExt,
* If we are bypassing the cache and not writing starting on
* cluster boundary then allocate a temporary buffer
*/
if (InternalOffset != 0)
if (InternalLength != DeviceExt->BytesPerCluster)
{
BaseAddress = ExAllocatePool(NonPagedPool,
DeviceExt->BytesPerCluster);
@ -531,7 +546,7 @@ VfatWriteBigCluster(PDEVICE_EXTENSION DeviceExt,
{
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, FALSE);
}
else if (InternalOffset != 0)
else if (InternalLength != DeviceExt->BytesPerCluster)
{
ExFreePool(BaseAddress);
}
@ -558,7 +573,7 @@ VfatWriteBigCluster(PDEVICE_EXTENSION DeviceExt,
{
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, TRUE);
}
else if (InternalOffset != 0)
else if (InternalLength != DeviceExt->BytesPerCluster)
{
ExFreePool(BaseAddress);
}
@ -609,7 +624,7 @@ VfatWriteSmallCluster(PDEVICE_EXTENSION DeviceExt,
else
{
Valid = FALSE;
if (InternalOffset != 0)
if (InternalLength != PAGESIZE)
{
BaseAddress = ExAllocatePool(NonPagedPool, PAGESIZE);
if (BaseAddress == NULL)
@ -646,7 +661,7 @@ VfatWriteSmallCluster(PDEVICE_EXTENSION DeviceExt,
{
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, FALSE);
}
else if (InternalOffset != 0)
else if (InternalLength != PAGESIZE)
{
ExFreePool(BaseAddress);
}
@ -664,6 +679,7 @@ VfatWriteSmallCluster(PDEVICE_EXTENSION DeviceExt,
/*
* Otherwise just move onto the next cluster
*/
NCluster = *CurrentCluster;
for (i = 0; i < (PAGESIZE / DeviceExt->BytesPerCluster); i++)
{
NextCluster(DeviceExt, FirstCluster, &NCluster, Extend);
@ -701,12 +717,25 @@ VfatWriteSmallCluster(PDEVICE_EXTENSION DeviceExt,
{
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, FALSE);
}
else if (InternalOffset != 0)
else if (InternalLength != PAGESIZE)
{
ExFreePool(BaseAddress);
}
return(Status);
}
// FIXME: Overwriting the variable Extend isn't correct,
// but when VFatWriteFile writes the last cache segment,
// than is Extend set to FALSE. We must extend,
// when the data needs a next cluster.
if (i < (PAGESIZE / DeviceExt->BytesPerCluster)-1 &&
InternalOffset + InternalLength > (i+1) * DeviceExt->BytesPerCluster)
{
Extend = TRUE;
}
else
{
Extend = FALSE;
}
Status = NextCluster(DeviceExt, FirstCluster, &NCluster, Extend);
if (NCluster == 0xFFFFFFFF)
{
@ -717,9 +746,11 @@ VfatWriteSmallCluster(PDEVICE_EXTENSION DeviceExt,
if (!NoCache)
{
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, TRUE);
//
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg,
Valid || InternalLength == PAGESIZE ? TRUE : FALSE);
}
else if (InternalOffset != 0)
else if (InternalLength != PAGESIZE)
{
ExFreePool(BaseAddress);
}
@ -847,11 +878,18 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
Fcb->entry.FileSize = WriteOffset + Length;
}
if (FirstCluster == 1)
{
// root directory of FAT12 od FAT16
if (WriteOffset + Length > DeviceExt->rootDirectorySectors * BLOCKSIZE)
return STATUS_END_OF_FILE;
}
/*
* If the offset in the cluster doesn't fall on the cluster boundary
* then we have to write only from the specified offset
*/
Status = STATUS_SUCCESS;
if ((WriteOffset % ChunkSize) != 0)
{
TempLength = min (Length, ChunkSize - (WriteOffset % ChunkSize));
@ -873,12 +911,15 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
WriteOffset % ChunkSize,
TempLength,
Extend);
if (NT_SUCCESS(Status))
{
Buffer = Buffer + TempLength;
Length = Length - TempLength;
WriteOffset = WriteOffset + TempLength;
}
}
while (Length >= ChunkSize)
while (Length >= ChunkSize && CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
{
if ((Length - ChunkSize) > 0)
{
@ -898,13 +939,17 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
0,
ChunkSize,
Extend);
if (!NT_SUCCESS(Status))
{
break;
}
Buffer = Buffer + ChunkSize;
Length = Length - ChunkSize;
WriteOffset = WriteOffset + ChunkSize;
}
/* Write the remainder */
if (Length > 0)
if (Length > 0 && CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
{
Status = VfatWriteCluster(DeviceExt,
Fcb,
@ -916,6 +961,10 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
0,
Length,
FALSE);
if (NT_SUCCESS(Status))
{
Length = 0;
}
}
@ -931,6 +980,14 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
updEntry (DeviceExt, FileObject);
}
if (!NT_SUCCESS(Status))
{
return Status;
}
if (Length > 0)
{
return STATUS_DISK_FULL;
}
return (STATUS_SUCCESS);
}