mirror of
https://github.com/reactos/reactos.git
synced 2024-08-13 22:56:37 +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,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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -136,14 +136,13 @@ VfatReadBigCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Valid = FALSE;
|
Valid = FALSE;
|
||||||
if (InternalOffset == 0)
|
if (InternalLength == DeviceExt->BytesPerCluster)
|
||||||
{
|
{
|
||||||
BaseAddress = Destination;
|
BaseAddress = Destination;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BaseAddress = ExAllocatePool(NonPagedPool,
|
BaseAddress = ExAllocatePool(NonPagedPool, DeviceExt->BytesPerCluster);
|
||||||
DeviceExt->BytesPerCluster);
|
|
||||||
if (BaseAddress == NULL)
|
if (BaseAddress == NULL)
|
||||||
{
|
{
|
||||||
return(STATUS_NO_MEMORY);
|
return(STATUS_NO_MEMORY);
|
||||||
|
@ -164,7 +163,7 @@ VfatReadBigCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
{
|
{
|
||||||
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, FALSE);
|
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, FALSE);
|
||||||
}
|
}
|
||||||
else if (InternalOffset != 0)
|
else if (InternalLength != DeviceExt->BytesPerCluster)
|
||||||
{
|
{
|
||||||
ExFreePool(BaseAddress);
|
ExFreePool(BaseAddress);
|
||||||
}
|
}
|
||||||
|
@ -174,7 +173,7 @@ VfatReadBigCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
/*
|
/*
|
||||||
* Copy the data from the cache to the caller
|
* Copy the data from the cache to the caller
|
||||||
*/
|
*/
|
||||||
if (InternalOffset != 0 || !NoCache)
|
if (InternalLength != DeviceExt->BytesPerCluster || !NoCache)
|
||||||
{
|
{
|
||||||
memcpy(Destination, BaseAddress + InternalOffset, InternalLength);
|
memcpy(Destination, BaseAddress + InternalOffset, InternalLength);
|
||||||
}
|
}
|
||||||
|
@ -182,7 +181,7 @@ VfatReadBigCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
{
|
{
|
||||||
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, TRUE);
|
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, TRUE);
|
||||||
}
|
}
|
||||||
else if (InternalOffset != 0)
|
else if (InternalLength != DeviceExt->BytesPerCluster)
|
||||||
{
|
{
|
||||||
ExFreePool(BaseAddress);
|
ExFreePool(BaseAddress);
|
||||||
}
|
}
|
||||||
|
@ -230,7 +229,7 @@ VfatReadSmallCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Valid = FALSE;
|
Valid = FALSE;
|
||||||
if (InternalOffset == 0)
|
if (InternalLength == PAGESIZE)
|
||||||
{
|
{
|
||||||
BaseAddress = Destination;
|
BaseAddress = Destination;
|
||||||
}
|
}
|
||||||
|
@ -265,7 +264,7 @@ VfatReadSmallCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
{
|
{
|
||||||
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, FALSE);
|
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, FALSE);
|
||||||
}
|
}
|
||||||
else if (InternalOffset != 0)
|
else if (InternalLength != PAGESIZE)
|
||||||
{
|
{
|
||||||
ExFreePool(BaseAddress);
|
ExFreePool(BaseAddress);
|
||||||
}
|
}
|
||||||
|
@ -295,15 +294,16 @@ VfatReadSmallCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
/*
|
/*
|
||||||
* Copy the data from the cache to the caller
|
* Copy the data from the cache to the caller
|
||||||
*/
|
*/
|
||||||
if (InternalOffset != 0 || !NoCache)
|
if (InternalLength != PAGESIZE || !NoCache)
|
||||||
{
|
{
|
||||||
memcpy(Destination, BaseAddress + InternalOffset, InternalLength);
|
memcpy(Destination, BaseAddress + InternalOffset, InternalLength);
|
||||||
}
|
}
|
||||||
if (!NoCache)
|
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);
|
ExFreePool(BaseAddress);
|
||||||
}
|
}
|
||||||
|
@ -345,7 +345,6 @@ VfatReadCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
InternalOffset,
|
InternalOffset,
|
||||||
InternalLength));
|
InternalLength));
|
||||||
}
|
}
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
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
|
* Select an appropiate size for reads
|
||||||
*/
|
*/
|
||||||
|
@ -436,35 +444,42 @@ VfatReadFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
if ((ReadOffset % ChunkSize) != 0 )
|
if ((ReadOffset % ChunkSize) != 0 )
|
||||||
{
|
{
|
||||||
TempLength = min (Length, ChunkSize - (ReadOffset % ChunkSize));
|
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,
|
FirstCluster, &CurrentCluster, Buffer, NoCache,
|
||||||
ReadOffset % ChunkSize, TempLength);
|
ReadOffset % ChunkSize, TempLength);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
(*LengthRead) = (*LengthRead) + TempLength;
|
(*LengthRead) = (*LengthRead) + TempLength;
|
||||||
Length = Length - TempLength;
|
Length = Length - TempLength;
|
||||||
Buffer = Buffer + TempLength;
|
Buffer = Buffer + TempLength;
|
||||||
ReadOffset = ReadOffset + 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,
|
FirstCluster, &CurrentCluster, Buffer, NoCache, 0,
|
||||||
ChunkSize);
|
ChunkSize);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
(*LengthRead) = (*LengthRead) + ChunkSize;
|
(*LengthRead) = (*LengthRead) + ChunkSize;
|
||||||
Buffer = Buffer + ChunkSize;
|
Buffer = Buffer + ChunkSize;
|
||||||
Length = Length - ChunkSize;
|
Length = Length - ChunkSize;
|
||||||
ReadOffset = ReadOffset + 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,
|
FirstCluster, &CurrentCluster, Buffer, NoCache, 0,
|
||||||
Length);
|
Length);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
(*LengthRead) = (*LengthRead) + Length;
|
(*LengthRead) = (*LengthRead) + Length;
|
||||||
}
|
}
|
||||||
return (STATUS_SUCCESS);
|
}
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -506,7 +521,7 @@ VfatWriteBigCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
* If we are bypassing the cache and not writing starting on
|
* If we are bypassing the cache and not writing starting on
|
||||||
* cluster boundary then allocate a temporary buffer
|
* cluster boundary then allocate a temporary buffer
|
||||||
*/
|
*/
|
||||||
if (InternalOffset != 0)
|
if (InternalLength != DeviceExt->BytesPerCluster)
|
||||||
{
|
{
|
||||||
BaseAddress = ExAllocatePool(NonPagedPool,
|
BaseAddress = ExAllocatePool(NonPagedPool,
|
||||||
DeviceExt->BytesPerCluster);
|
DeviceExt->BytesPerCluster);
|
||||||
|
@ -531,7 +546,7 @@ VfatWriteBigCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
{
|
{
|
||||||
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, FALSE);
|
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, FALSE);
|
||||||
}
|
}
|
||||||
else if (InternalOffset != 0)
|
else if (InternalLength != DeviceExt->BytesPerCluster)
|
||||||
{
|
{
|
||||||
ExFreePool(BaseAddress);
|
ExFreePool(BaseAddress);
|
||||||
}
|
}
|
||||||
|
@ -558,7 +573,7 @@ VfatWriteBigCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
{
|
{
|
||||||
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, TRUE);
|
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, TRUE);
|
||||||
}
|
}
|
||||||
else if (InternalOffset != 0)
|
else if (InternalLength != DeviceExt->BytesPerCluster)
|
||||||
{
|
{
|
||||||
ExFreePool(BaseAddress);
|
ExFreePool(BaseAddress);
|
||||||
}
|
}
|
||||||
|
@ -609,7 +624,7 @@ VfatWriteSmallCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Valid = FALSE;
|
Valid = FALSE;
|
||||||
if (InternalOffset != 0)
|
if (InternalLength != PAGESIZE)
|
||||||
{
|
{
|
||||||
BaseAddress = ExAllocatePool(NonPagedPool, PAGESIZE);
|
BaseAddress = ExAllocatePool(NonPagedPool, PAGESIZE);
|
||||||
if (BaseAddress == NULL)
|
if (BaseAddress == NULL)
|
||||||
|
@ -646,7 +661,7 @@ VfatWriteSmallCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
{
|
{
|
||||||
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, FALSE);
|
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, FALSE);
|
||||||
}
|
}
|
||||||
else if (InternalOffset != 0)
|
else if (InternalLength != PAGESIZE)
|
||||||
{
|
{
|
||||||
ExFreePool(BaseAddress);
|
ExFreePool(BaseAddress);
|
||||||
}
|
}
|
||||||
|
@ -664,6 +679,7 @@ VfatWriteSmallCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
/*
|
/*
|
||||||
* Otherwise just move onto the next cluster
|
* Otherwise just move onto the next cluster
|
||||||
*/
|
*/
|
||||||
|
NCluster = *CurrentCluster;
|
||||||
for (i = 0; i < (PAGESIZE / DeviceExt->BytesPerCluster); i++)
|
for (i = 0; i < (PAGESIZE / DeviceExt->BytesPerCluster); i++)
|
||||||
{
|
{
|
||||||
NextCluster(DeviceExt, FirstCluster, &NCluster, Extend);
|
NextCluster(DeviceExt, FirstCluster, &NCluster, Extend);
|
||||||
|
@ -701,12 +717,25 @@ VfatWriteSmallCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
{
|
{
|
||||||
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, FALSE);
|
CcRosReleaseCacheSegment(Fcb->RFCB.Bcb, CacheSeg, FALSE);
|
||||||
}
|
}
|
||||||
else if (InternalOffset != 0)
|
else if (InternalLength != PAGESIZE)
|
||||||
{
|
{
|
||||||
ExFreePool(BaseAddress);
|
ExFreePool(BaseAddress);
|
||||||
}
|
}
|
||||||
return(Status);
|
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);
|
Status = NextCluster(DeviceExt, FirstCluster, &NCluster, Extend);
|
||||||
if (NCluster == 0xFFFFFFFF)
|
if (NCluster == 0xFFFFFFFF)
|
||||||
{
|
{
|
||||||
|
@ -717,9 +746,11 @@ VfatWriteSmallCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
|
|
||||||
if (!NoCache)
|
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);
|
ExFreePool(BaseAddress);
|
||||||
}
|
}
|
||||||
|
@ -847,11 +878,18 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
Fcb->entry.FileSize = WriteOffset + Length;
|
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
|
* If the offset in the cluster doesn't fall on the cluster boundary
|
||||||
* then we have to write only from the specified offset
|
* then we have to write only from the specified offset
|
||||||
*/
|
*/
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
if ((WriteOffset % ChunkSize) != 0)
|
if ((WriteOffset % ChunkSize) != 0)
|
||||||
{
|
{
|
||||||
TempLength = min (Length, ChunkSize - (WriteOffset % ChunkSize));
|
TempLength = min (Length, ChunkSize - (WriteOffset % ChunkSize));
|
||||||
|
@ -873,12 +911,15 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
WriteOffset % ChunkSize,
|
WriteOffset % ChunkSize,
|
||||||
TempLength,
|
TempLength,
|
||||||
Extend);
|
Extend);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
Buffer = Buffer + TempLength;
|
Buffer = Buffer + TempLength;
|
||||||
Length = Length - TempLength;
|
Length = Length - TempLength;
|
||||||
WriteOffset = WriteOffset + TempLength;
|
WriteOffset = WriteOffset + TempLength;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (Length >= ChunkSize)
|
while (Length >= ChunkSize && CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
if ((Length - ChunkSize) > 0)
|
if ((Length - ChunkSize) > 0)
|
||||||
{
|
{
|
||||||
|
@ -898,13 +939,17 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
0,
|
0,
|
||||||
ChunkSize,
|
ChunkSize,
|
||||||
Extend);
|
Extend);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
Buffer = Buffer + ChunkSize;
|
Buffer = Buffer + ChunkSize;
|
||||||
Length = Length - ChunkSize;
|
Length = Length - ChunkSize;
|
||||||
WriteOffset = WriteOffset + ChunkSize;
|
WriteOffset = WriteOffset + ChunkSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the remainder */
|
/* Write the remainder */
|
||||||
if (Length > 0)
|
if (Length > 0 && CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
Status = VfatWriteCluster(DeviceExt,
|
Status = VfatWriteCluster(DeviceExt,
|
||||||
Fcb,
|
Fcb,
|
||||||
|
@ -916,6 +961,10 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
0,
|
0,
|
||||||
Length,
|
Length,
|
||||||
FALSE);
|
FALSE);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Length = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -931,6 +980,14 @@ VfatWriteFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
updEntry (DeviceExt, FileObject);
|
updEntry (DeviceExt, FileObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
if (Length > 0)
|
||||||
|
{
|
||||||
|
return STATUS_DISK_FULL;
|
||||||
|
}
|
||||||
return (STATUS_SUCCESS);
|
return (STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue