mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
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:
parent
c0cbc28359
commit
8eeb1a96b8
1 changed files with 541 additions and 484 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue