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 * 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);
} }