ReactOS.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
List overview
Download
Ros-diffs
December 2017
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
ros-diffs@reactos.org
26 participants
355 discussions
Start a n
N
ew thread
[reactos] 13/72: [NTFS] Simplify GetLastClusterInDataRun() and clean up NtfsAllocateClusters(). No functional changes.
by Trevor Thompson
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7a6e9bcdf62e24411780c…
commit 7a6e9bcdf62e24411780c03d565097c5051fc06b Author: Trevor Thompson <tmt256(a)email.vccs.edu> AuthorDate: Fri Jul 8 11:59:25 2016 +0000 [NTFS] Simplify GetLastClusterInDataRun() and clean up NtfsAllocateClusters(). No functional changes. svn path=/branches/GSoC_2016/NTFS/; revision=71857 --- drivers/filesystems/ntfs/attrib.c | 18 +++----------- drivers/filesystems/ntfs/volinfo.c | 49 ++++++++++++++++++-------------------- 2 files changed, 26 insertions(+), 41 deletions(-) diff --git a/drivers/filesystems/ntfs/attrib.c b/drivers/filesystems/ntfs/attrib.c index e8625903bc..80022f5957 100644 --- a/drivers/filesystems/ntfs/attrib.c +++ b/drivers/filesystems/ntfs/attrib.c @@ -583,28 +583,16 @@ GetLastClusterInDataRun(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_RECORD Attribute, PULO { DataRun = DecodeRun(DataRun, &DataRunOffset, &DataRunLength); - if (DataRunOffset == -1) - { - // sparse run - if (*DataRun == 0) - { - // if it's the last run, return the last cluster of the last run - *LastCluster = LastLCN + DataRunLength - 1; - break; - } - } - else + if (DataRunOffset != -1) { // Normal data run. DataRunStartLCN = LastLCN + DataRunOffset; LastLCN = DataRunStartLCN; + *LastCluster = LastLCN + DataRunLength - 1; } - if (*DataRun == 0) - { - *LastCluster = LastLCN + DataRunLength - 1; + if (*DataRun == 0) break; - } } return STATUS_SUCCESS; diff --git a/drivers/filesystems/ntfs/volinfo.c b/drivers/filesystems/ntfs/volinfo.c index 0a54cf73b8..68a1050620 100644 --- a/drivers/filesystems/ntfs/volinfo.c +++ b/drivers/filesystems/ntfs/volinfo.c @@ -162,38 +162,35 @@ NtfsAllocateClusters(PDEVICE_EXTENSION DeviceExt, RtlInitializeBitMap(&Bitmap, (PULONG)BitmapData, DeviceExt->NtfsInfo.ClusterCount); FreeClusters = RtlNumberOfClearBits(&Bitmap); - if (FreeClusters >= DesiredClusters) - { - // TODO: Observe MFT reservation zone + if( FreeClusters < DesiredClusters ) + Status = STATUS_DISK_FULL; + + // TODO: Observe MFT reservation zone - // Can we get one contiguous run? - ULONG AssignedRun = RtlFindClearBitsAndSet(&Bitmap, DesiredClusters, FirstDesiredCluster); - ULONG LengthWritten; + // Can we get one contiguous run? + ULONG AssignedRun = RtlFindClearBitsAndSet(&Bitmap, DesiredClusters, FirstDesiredCluster); + ULONG LengthWritten; - if (AssignedRun != 0xFFFFFFFF) + if (AssignedRun != 0xFFFFFFFF) + { + *FirstAssignedCluster = AssignedRun; + *AssignedClusters = DesiredClusters; + } + else + { + // we can't get one contiguous run + *AssignedClusters = RtlFindNextForwardRunClear(&Bitmap, FirstDesiredCluster, FirstAssignedCluster); + + if (*AssignedClusters == 0) { - *FirstAssignedCluster = AssignedRun; - *AssignedClusters = DesiredClusters; + // we couldn't find any runs starting at DesiredFirstCluster + *AssignedClusters = RtlFindLongestRunClear(&Bitmap, FirstAssignedCluster); } - else - { - // we can't get one contiguous run - *AssignedClusters = RtlFindNextForwardRunClear(&Bitmap, FirstDesiredCluster, FirstAssignedCluster); - - if (*AssignedClusters == 0) - { - // we couldn't find any runs starting at DesiredFirstCluster - *AssignedClusters = RtlFindLongestRunClear(&Bitmap, FirstAssignedCluster); - } - } - - Status = WriteAttribute(DeviceExt, DataContext, 0, BitmapData, (ULONG)BitmapDataSize, &LengthWritten); } - else - Status = STATUS_DISK_FULL; - - + + Status = WriteAttribute(DeviceExt, DataContext, 0, BitmapData, (ULONG)BitmapDataSize, &LengthWritten); + ReleaseAttributeContext(DataContext); ExFreePoolWithTag(BitmapData, TAG_NTFS);
7 years
1
0
0
0
[reactos] 12/72: [NTFS] Simplify and optimize InternalSetResidentAttributeLength(), as suggested by Pierre.
by Trevor Thompson
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c08d37d182408f6953364…
commit c08d37d182408f69533644257ee8cc10e6a16f6b Author: Trevor Thompson <tmt256(a)email.vccs.edu> AuthorDate: Thu Jul 7 08:17:07 2016 +0000 [NTFS] Simplify and optimize InternalSetResidentAttributeLength(), as suggested by Pierre. svn path=/branches/GSoC_2016/NTFS/; revision=71837 --- drivers/filesystems/ntfs/mft.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/drivers/filesystems/ntfs/mft.c b/drivers/filesystems/ntfs/mft.c index a5111c18ee..aa203bbe9d 100644 --- a/drivers/filesystems/ntfs/mft.c +++ b/drivers/filesystems/ntfs/mft.c @@ -178,43 +178,37 @@ InternalSetResidentAttributeLength(PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, ULONG DataSize) { - ULONG EndMarker = AttributeEnd; - ULONG FinalMarker = FILE_RECORD_END; + PNTFS_ATTR_RECORD Destination = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttrOffset); ULONG NextAttributeOffset; - ULONG Offset; - USHORT Padding; DPRINT("InternalSetResidentAttributeLength( %p, %p, %lu, %lu )\n", AttrContext, FileRecord, AttrOffset, DataSize); // update ValueLength Field - AttrContext->Record.Resident.ValueLength = DataSize; - Offset = AttrOffset + FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.ValueLength); - RtlCopyMemory((PCHAR)FileRecord + Offset, &DataSize, sizeof(ULONG)); + AttrContext->Record.Resident.ValueLength = + Destination->Resident.ValueLength = DataSize; // calculate the record length and end marker offset - AttrContext->Record.Length = DataSize + AttrContext->Record.Resident.ValueOffset; + AttrContext->Record.Length = + Destination->Length = DataSize + AttrContext->Record.Resident.ValueOffset; NextAttributeOffset = AttrOffset + AttrContext->Record.Length; // Ensure NextAttributeOffset is aligned to an 8-byte boundary if (NextAttributeOffset % 8 != 0) { - Padding = 8 - (NextAttributeOffset % 8); + USHORT Padding = 8 - (NextAttributeOffset % 8); NextAttributeOffset += Padding; AttrContext->Record.Length += Padding; + Destination->Length += Padding; } + + // advance Destination to the final "attribute" and write the end type + (ULONG_PTR)Destination += Destination->Length; + Destination->Type = AttributeEnd; - // update the record length - Offset = AttrOffset + FIELD_OFFSET(NTFS_ATTR_RECORD, Length); - RtlCopyMemory((PCHAR)FileRecord + Offset, &AttrContext->Record.Length, sizeof(ULONG)); + // write the final marker (which shares the same offset and type as the Length field) + Destination->Length = FILE_RECORD_END; - // write the end marker - RtlCopyMemory((PCHAR)FileRecord + NextAttributeOffset, &EndMarker, sizeof(ULONG)); - - // write the final marker - Offset = NextAttributeOffset + sizeof(ULONG); - RtlCopyMemory((PCHAR)FileRecord + Offset, &FinalMarker, sizeof(ULONG)); - - FileRecord->BytesInUse = Offset + sizeof(ULONG); + FileRecord->BytesInUse = NextAttributeOffset + (sizeof(ULONG) * 2); } NTSTATUS
7 years
1
0
0
0
[reactos] 11/72: [NTFS] Fix copy-paste error in SetAttributeDataLength()
by Trevor Thompson
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7eb1264f5f184623f2308…
commit 7eb1264f5f184623f230832cf6aecfa5f362e0bd Author: Trevor Thompson <tmt256(a)email.vccs.edu> AuthorDate: Wed Jul 6 07:57:57 2016 +0000 [NTFS] Fix copy-paste error in SetAttributeDataLength() svn path=/branches/GSoC_2016/NTFS/; revision=71832 --- drivers/filesystems/ntfs/mft.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/filesystems/ntfs/mft.c b/drivers/filesystems/ntfs/mft.c index 4e10584ce0..a5111c18ee 100644 --- a/drivers/filesystems/ntfs/mft.c +++ b/drivers/filesystems/ntfs/mft.c @@ -228,9 +228,9 @@ SetAttributeDataLength(PFILE_OBJECT FileObject, NTSTATUS Status = STATUS_SUCCESS; // are we truncating the file? - if (DataSize->QuadPart < AttributeDataLength(&AttrContext->Record) + if (DataSize->QuadPart < AttributeDataLength(&AttrContext->Record)) { - if (!MmCanFileBeTruncated(FileObject->SectionObjectPointer, (PLARGE_INTEGER)&AllocationSize)) + if (!MmCanFileBeTruncated(FileObject->SectionObjectPointer, DataSize)) { DPRINT1("Can't truncate a memory-mapped file!\n"); return STATUS_USER_MAPPED_FILE;
7 years
1
0
0
0
[reactos] 10/72: [NTFS] Add ability to write to resident attributes. SetAttributeDataLength() - Check if the file is memory mapped before truncating +InternalSetResidentAttributeLength() - Used by SetAttributeDataLength()
by Trevor Thompson
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=760cdfb5aa5043c49c30b…
commit 760cdfb5aa5043c49c30bec6066f682df9e12d28 Author: Trevor Thompson <tmt256(a)email.vccs.edu> AuthorDate: Tue Jul 5 07:00:43 2016 +0000 [NTFS] Add ability to write to resident attributes. SetAttributeDataLength() - Check if the file is memory mapped before truncating +InternalSetResidentAttributeLength() - Used by SetAttributeDataLength() svn path=/branches/GSoC_2016/NTFS/; revision=71820 --- drivers/filesystems/ntfs/attrib.c | 2 + drivers/filesystems/ntfs/mft.c | 189 +++++++++++++++++++++++++++++++------ drivers/filesystems/ntfs/ntfs.h | 5 + drivers/filesystems/ntfs/volinfo.c | 3 +- 4 files changed, 170 insertions(+), 29 deletions(-) diff --git a/drivers/filesystems/ntfs/attrib.c b/drivers/filesystems/ntfs/attrib.c index 9608d1d17b..e8625903bc 100644 --- a/drivers/filesystems/ntfs/attrib.c +++ b/drivers/filesystems/ntfs/attrib.c @@ -509,6 +509,8 @@ NtfsDumpAttribute(PDEVICE_EXTENSION Vcb, DbgPrint(" logical clusters: %I64u - %I64u\n", lcn, lcn + runcount - 1); } + else + DbgPrint(" %u bytes of data\n", Attribute->Resident.ValueLength); } } diff --git a/drivers/filesystems/ntfs/mft.c b/drivers/filesystems/ntfs/mft.c index e1725f9a50..4e10584ce0 100644 --- a/drivers/filesystems/ntfs/mft.c +++ b/drivers/filesystems/ntfs/mft.c @@ -135,6 +135,8 @@ FindAttribute(PDEVICE_EXTENSION Vcb, DPRINT("Found context\n"); *AttrCtx = PrepareAttributeContext(Attribute); + (*AttrCtx)->FileMFTIndex = MftRecord->MFTRecordNumber; + if (Offset != NULL) *Offset = Context.Offset; @@ -170,6 +172,50 @@ AttributeDataLength(PNTFS_ATTR_RECORD AttrRecord) return AttrRecord->Resident.ValueLength; } +void +InternalSetResidentAttributeLength(PNTFS_ATTR_CONTEXT AttrContext, + PFILE_RECORD_HEADER FileRecord, + ULONG AttrOffset, + ULONG DataSize) +{ + ULONG EndMarker = AttributeEnd; + ULONG FinalMarker = FILE_RECORD_END; + ULONG NextAttributeOffset; + ULONG Offset; + USHORT Padding; + + DPRINT("InternalSetResidentAttributeLength( %p, %p, %lu, %lu )\n", AttrContext, FileRecord, AttrOffset, DataSize); + + // update ValueLength Field + AttrContext->Record.Resident.ValueLength = DataSize; + Offset = AttrOffset + FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.ValueLength); + RtlCopyMemory((PCHAR)FileRecord + Offset, &DataSize, sizeof(ULONG)); + + // calculate the record length and end marker offset + AttrContext->Record.Length = DataSize + AttrContext->Record.Resident.ValueOffset; + NextAttributeOffset = AttrOffset + AttrContext->Record.Length; + + // Ensure NextAttributeOffset is aligned to an 8-byte boundary + if (NextAttributeOffset % 8 != 0) + { + Padding = 8 - (NextAttributeOffset % 8); + NextAttributeOffset += Padding; + AttrContext->Record.Length += Padding; + } + + // update the record length + Offset = AttrOffset + FIELD_OFFSET(NTFS_ATTR_RECORD, Length); + RtlCopyMemory((PCHAR)FileRecord + Offset, &AttrContext->Record.Length, sizeof(ULONG)); + + // write the end marker + RtlCopyMemory((PCHAR)FileRecord + NextAttributeOffset, &EndMarker, sizeof(ULONG)); + + // write the final marker + Offset = NextAttributeOffset + sizeof(ULONG); + RtlCopyMemory((PCHAR)FileRecord + Offset, &FinalMarker, sizeof(ULONG)); + + FileRecord->BytesInUse = Offset + sizeof(ULONG); +} NTSTATUS SetAttributeDataLength(PFILE_OBJECT FileObject, @@ -179,6 +225,18 @@ SetAttributeDataLength(PFILE_OBJECT FileObject, PFILE_RECORD_HEADER FileRecord, PLARGE_INTEGER DataSize) { + NTSTATUS Status = STATUS_SUCCESS; + + // are we truncating the file? + if (DataSize->QuadPart < AttributeDataLength(&AttrContext->Record) + { + if (!MmCanFileBeTruncated(FileObject->SectionObjectPointer, (PLARGE_INTEGER)&AllocationSize)) + { + DPRINT1("Can't truncate a memory-mapped file!\n"); + return STATUS_USER_MAPPED_FILE; + } + } + if (AttrContext->Record.IsNonResident) { ULONG BytesPerCluster = Fcb->Vcb->NtfsInfo.BytesPerCluster; @@ -238,28 +296,59 @@ SetAttributeDataLength(PFILE_OBJECT FileObject, AttrContext->Record.NonResident.DataSize = DataSize->QuadPart; AttrContext->Record.NonResident.InitializedSize = DataSize->QuadPart; - Fcb->RFCB.FileSize = *DataSize; - Fcb->RFCB.ValidDataLength = *DataSize; + // copy the attribute record back into the FileRecord + RtlCopyMemory((PCHAR)FileRecord + AttrOffset, &AttrContext->Record, AttrContext->Record.Length); + } + else + { + // resident attribute - DPRINT("Data Size: %I64u\n", Fcb->RFCB.FileSize.QuadPart); + // find the next attribute + ULONG NextAttributeOffset = AttrOffset + AttrContext->Record.Length; + PNTFS_ATTR_RECORD NextAttribute = (PNTFS_ATTR_RECORD)((PCHAR)FileRecord + NextAttributeOffset); //NtfsDumpFileAttributes(Fcb->Vcb, FileRecord); - // copy the attribute back into the FileRecord - RtlCopyMemory((PCHAR)FileRecord + AttrOffset, &AttrContext->Record, AttrContext->Record.Length); - - //NtfsDumpFileAttributes(Fcb->Vcb, FileRecord); + // Do we need to increase the data length? + if (DataSize->QuadPart > AttrContext->Record.Resident.ValueLength) + { + // There's usually padding at the end of a record. Do we need to extend past it? + ULONG MaxValueLength = AttrContext->Record.Length - AttrContext->Record.Resident.ValueOffset; + if (MaxValueLength < DataSize->LowPart) + { + // If this is the last attribute, we could move the end marker to the very end of the file record + MaxValueLength += Fcb->Vcb->NtfsInfo.BytesPerFileRecord - NextAttributeOffset - (sizeof(ULONG) * 2); - // write the updated file record back to disk - UpdateFileRecord(Fcb->Vcb, Fcb->MFTIndex, FileRecord); + if (MaxValueLength < DataSize->LowPart || NextAttribute->Type != AttributeEnd) + { + DPRINT1("FIXME: Need to convert attribute to non-resident!\n"); + return STATUS_NOT_IMPLEMENTED; + } + } + } + else if (DataSize->LowPart < AttrContext->Record.Resident.ValueLength) + { + // we need to decrease the length + if (NextAttribute->Type != AttributeEnd) + { + DPRINT1("FIXME: Don't know how to decrease length of resident attribute unless it's the final attribute!\n"); + return STATUS_NOT_IMPLEMENTED; + } + } - CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->RFCB.AllocationSize); + InternalSetResidentAttributeLength(AttrContext, FileRecord, AttrOffset, DataSize->LowPart); } - else + + //NtfsDumpFileAttributes(Fcb->Vcb, FileRecord); + + // write the updated file record back to disk + Status = UpdateFileRecord(Fcb->Vcb, Fcb->MFTIndex, FileRecord); + + if (NT_SUCCESS(Status)) { - // we can't yet handle resident attributes - DPRINT1("FixMe: Can't handle increasing length of resident attribute\n"); - return STATUS_NOT_IMPLEMENTED; + Fcb->RFCB.FileSize = *DataSize; + Fcb->RFCB.ValidDataLength = *DataSize; + CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->RFCB.AllocationSize); } return STATUS_SUCCESS; @@ -501,29 +590,76 @@ WriteAttribute(PDEVICE_EXTENSION Vcb, DPRINT("WriteAttribute(%p, %p, %I64u, %p, %lu, %p)\n", Vcb, Context, Offset, Buffer, Length, RealLengthWritten); + *RealLengthWritten = 0; + // is this a resident attribute? if (!Context->Record.IsNonResident) { - DPRINT1("FIXME: Writing to resident NTFS records (small files) is not supported at this time.\n"); - // (TODO: This should be really easy to implement) + ULONG AttributeOffset; + PNTFS_ATTR_CONTEXT FoundContext; + PFILE_RECORD_HEADER FileRecord; - /* LeftOver code from ReadAttribute(), may be helpful: - if (Offset > Context->Record.Resident.ValueLength) - return 0; if (Offset + Length > Context->Record.Resident.ValueLength) - Length = (ULONG)(Context->Record.Resident.ValueLength - Offset); - RtlCopyMemory(Buffer, (PCHAR)&Context->Record + Context->Record.Resident.ValueOffset + Offset, Length); - return Length;*/ + { + DPRINT1("DRIVER ERROR: Attribute is too small!\n"); + return STATUS_INVALID_PARAMETER; + } + + FileRecord = ExAllocatePoolWithTag(NonPagedPool, Vcb->NtfsInfo.BytesPerFileRecord, TAG_NTFS); + + if (!FileRecord) + { + DPRINT1("Error: Couldn't allocate file record!\n"); + return STATUS_NO_MEMORY; + } + + // read the file record + ReadFileRecord(Vcb, Context->FileMFTIndex, FileRecord); - return STATUS_NOT_IMPLEMENTED; // until we implement it + // find where to write the attribute data to + Status = FindAttribute(Vcb, FileRecord, + Context->Record.Type, + (PCWSTR)((PCHAR)&Context->Record + Context->Record.NameOffset), + Context->Record.NameLength, + &FoundContext, + &AttributeOffset); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("ERROR: Couldn't find matching attribute!\n"); + ExFreePoolWithTag(FileRecord, TAG_NTFS); + return Status; + } + + DPRINT("Offset: %I64u, AttributeOffset: %u, ValueOffset: %u\n", Offset, AttributeOffset, Context->Record.Resident.ValueLength); + Offset += AttributeOffset + Context->Record.Resident.ValueOffset; + + if (Offset + Length > Vcb->NtfsInfo.BytesPerFileRecord) + { + DPRINT1("DRIVER ERROR: Data being written extends past end of file record!\n"); + ReleaseAttributeContext(FoundContext); + ExFreePoolWithTag(FileRecord, TAG_NTFS); + return STATUS_INVALID_PARAMETER; + } + + // copy the data being written into the file record + RtlCopyMemory((PCHAR)FileRecord + Offset, Buffer, Length); + + Status = UpdateFileRecord(Vcb, Context->FileMFTIndex, FileRecord); + + ReleaseAttributeContext(FoundContext); + ExFreePoolWithTag(FileRecord, TAG_NTFS); + + if (NT_SUCCESS(Status)) + *RealLengthWritten = Length; + + return Status; } // This is a non-resident attribute. // I. Find the corresponding start data run. - *RealLengthWritten = 0; - // FIXME: Cache seems to be non-working. Disable it for now //if(Context->CacheRunOffset <= Offset && Offset < Context->CacheRunOffset + Context->CacheRunLength * Volume->ClusterSize) /*if (0) @@ -718,6 +854,7 @@ ReadFileRecord(PDEVICE_EXTENSION Vcb, } /* Apply update sequence array fixups. */ + DPRINT("Sequence number: %u\n", file->SequenceNumber); return FixupUpdateSequenceArray(Vcb, &file->Ntfs); } @@ -948,8 +1085,6 @@ UpdateFileRecord(PDEVICE_EXTENSION Vcb, // write the file record to the master file table Status = WriteAttribute(Vcb, Vcb->MFTContext, index * Vcb->NtfsInfo.BytesPerFileRecord, (const PUCHAR)file, Vcb->NtfsInfo.BytesPerFileRecord, &BytesWritten); - // TODO: Update MFT mirror - if (!NT_SUCCESS(Status)) { DPRINT1("UpdateFileRecord failed: %I64u written, %u expected\n", BytesWritten, Vcb->NtfsInfo.BytesPerFileRecord); diff --git a/drivers/filesystems/ntfs/ntfs.h b/drivers/filesystems/ntfs/ntfs.h index 66cb37f4bd..238e6d5b2d 100644 --- a/drivers/filesystems/ntfs/ntfs.h +++ b/drivers/filesystems/ntfs/ntfs.h @@ -175,6 +175,10 @@ typedef enum AttributeEnd = 0xFFFFFFFF } ATTRIBUTE_TYPE, *PATTRIBUTE_TYPE; +// FILE_RECORD_END seems to follow AttributeEnd in every file record starting with $Quota. +// No clue what data is being represented here. +#define FILE_RECORD_END 0x11477982 + #define NTFS_FILE_MFT 0 #define NTFS_FILE_MFTMIRR 1 #define NTFS_FILE_LOGFILE 2 @@ -433,6 +437,7 @@ typedef struct _NTFS_ATTR_CONTEXT ULONGLONG CacheRunLength; LONGLONG CacheRunLastLCN; ULONGLONG CacheRunCurrentOffset; + ULONGLONG FileMFTIndex; NTFS_ATTR_RECORD Record; } NTFS_ATTR_CONTEXT, *PNTFS_ATTR_CONTEXT; diff --git a/drivers/filesystems/ntfs/volinfo.c b/drivers/filesystems/ntfs/volinfo.c index df3af4989a..0a54cf73b8 100644 --- a/drivers/filesystems/ntfs/volinfo.c +++ b/drivers/filesystems/ntfs/volinfo.c @@ -116,7 +116,6 @@ NtfsAllocateClusters(PDEVICE_EXTENSION DeviceExt, ULONGLONG BitmapDataSize; PCHAR BitmapData; ULONGLONG FreeClusters = 0; - ULONG Read = 0; RTL_BITMAP Bitmap; DPRINT1("NtfsAllocateClusters(%p, %lu, %lu, %p, %p)\n", DeviceExt, FirstDesiredCluster, DesiredClusters, FirstAssignedCluster, AssignedClusters); @@ -158,7 +157,7 @@ NtfsAllocateClusters(PDEVICE_EXTENSION DeviceExt, DPRINT1("Total clusters in bitmap: %I64x\n", BitmapDataSize * 8); DPRINT1("Diff in size: %I64d B\n", ((BitmapDataSize * 8) - DeviceExt->NtfsInfo.ClusterCount) * DeviceExt->NtfsInfo.SectorsPerCluster * DeviceExt->NtfsInfo.BytesPerSector); - ReadAttribute(DeviceExt, DataContext, Read, (PCHAR)((ULONG_PTR)BitmapData + Read), (ULONG)BitmapDataSize); + ReadAttribute(DeviceExt, DataContext, 0, (PCHAR)BitmapData, (ULONG)BitmapDataSize); RtlInitializeBitMap(&Bitmap, (PULONG)BitmapData, DeviceExt->NtfsInfo.ClusterCount); FreeClusters = RtlNumberOfClearBits(&Bitmap);
7 years
1
0
0
0
[reactos] 09/72: [NTFS] Fix typo in NtfsAllocateClusters(), spotted by ThFabba.
by Trevor Thompson
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=25fdabd8ca59cde07d3b8…
commit 25fdabd8ca59cde07d3b873183d817db8f17ed30 Author: Trevor Thompson <tmt256(a)email.vccs.edu> AuthorDate: Wed Jun 29 17:49:36 2016 +0000 [NTFS] Fix typo in NtfsAllocateClusters(), spotted by ThFabba. svn path=/branches/GSoC_2016/NTFS/; revision=71697 --- drivers/filesystems/ntfs/volinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/filesystems/ntfs/volinfo.c b/drivers/filesystems/ntfs/volinfo.c index c893562189..df3af4989a 100644 --- a/drivers/filesystems/ntfs/volinfo.c +++ b/drivers/filesystems/ntfs/volinfo.c @@ -119,7 +119,7 @@ NtfsAllocateClusters(PDEVICE_EXTENSION DeviceExt, ULONG Read = 0; RTL_BITMAP Bitmap; - DPRINT1("NtfsAllocateClusters(%p, %lu, %lu, %p)\n", DeviceExt, DesiredClusters, FirstDesiredCluster, FirstAssignedCluster, AssignedClusters); + DPRINT1("NtfsAllocateClusters(%p, %lu, %lu, %p, %p)\n", DeviceExt, FirstDesiredCluster, DesiredClusters, FirstAssignedCluster, AssignedClusters); BitmapRecord = ExAllocatePoolWithTag(NonPagedPool, DeviceExt->NtfsInfo.BytesPerFileRecord,
7 years
1
0
0
0
[reactos] 08/72: [NTFS] Lay some groundwork for extending allocation size. +AddRun() - Unimplemented +GetLastClusterInDataRun() +NtfsAllocateClusters()
by Trevor Thompson
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=77fc65dc0e4f7b08cec05…
commit 77fc65dc0e4f7b08cec056bb3f017c70036748f6 Author: Trevor Thompson <tmt256(a)email.vccs.edu> AuthorDate: Wed Jun 29 16:35:36 2016 +0000 [NTFS] Lay some groundwork for extending allocation size. +AddRun() - Unimplemented +GetLastClusterInDataRun() +NtfsAllocateClusters() svn path=/branches/GSoC_2016/NTFS/; revision=71696 --- drivers/filesystems/ntfs/attrib.c | 57 ++++++++++++++++++++ drivers/filesystems/ntfs/mft.c | 48 +++++++++++++++-- drivers/filesystems/ntfs/ntfs.h | 19 ++++++- drivers/filesystems/ntfs/volinfo.c | 104 +++++++++++++++++++++++++++++++++++++ 4 files changed, 223 insertions(+), 5 deletions(-) diff --git a/drivers/filesystems/ntfs/attrib.c b/drivers/filesystems/ntfs/attrib.c index 12474f6c81..9608d1d17b 100644 --- a/drivers/filesystems/ntfs/attrib.c +++ b/drivers/filesystems/ntfs/attrib.c @@ -35,6 +35,19 @@ /* FUNCTIONS ****************************************************************/ +NTSTATUS +AddRun(PNTFS_ATTR_CONTEXT AttrContext, + ULONGLONG NextAssignedCluster, + ULONG RunLength) +{ + UNIMPLEMENTED; + + if (!AttrContext->Record.IsNonResident) + return STATUS_INVALID_PARAMETER; + + return STATUS_NOT_IMPLEMENTED; +} + PUCHAR DecodeRun(PUCHAR DataRun, LONGLONG *DataRunOffset, @@ -551,6 +564,50 @@ GetFileNameFromRecord(PDEVICE_EXTENSION Vcb, return NULL; } +NTSTATUS +GetLastClusterInDataRun(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_RECORD Attribute, PULONGLONG LastCluster) +{ + LONGLONG DataRunOffset; + ULONGLONG DataRunLength; + LONGLONG DataRunStartLCN; + + ULONGLONG LastLCN = 0; + PUCHAR DataRun = (PUCHAR)Attribute + Attribute->NonResident.MappingPairsOffset; + + if (!Attribute->IsNonResident) + return STATUS_INVALID_PARAMETER; + + while (1) + { + DataRun = DecodeRun(DataRun, &DataRunOffset, &DataRunLength); + + if (DataRunOffset == -1) + { + // sparse run + if (*DataRun == 0) + { + // if it's the last run, return the last cluster of the last run + *LastCluster = LastLCN + DataRunLength - 1; + break; + } + } + else + { + // Normal data run. + DataRunStartLCN = LastLCN + DataRunOffset; + LastLCN = DataRunStartLCN; + } + + if (*DataRun == 0) + { + *LastCluster = LastLCN + DataRunLength - 1; + break; + } + } + + return STATUS_SUCCESS; +} + PSTANDARD_INFORMATION GetStandardInformationFromRecord(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord) diff --git a/drivers/filesystems/ntfs/mft.c b/drivers/filesystems/ntfs/mft.c index ae2a6cc2ba..e1725f9a50 100644 --- a/drivers/filesystems/ntfs/mft.c +++ b/drivers/filesystems/ntfs/mft.c @@ -151,7 +151,7 @@ FindAttribute(PDEVICE_EXTENSION Vcb, } -ULONG +ULONGLONG AttributeAllocatedLength(PNTFS_ATTR_RECORD AttrRecord) { if (AttrRecord->IsNonResident) @@ -181,9 +181,49 @@ SetAttributeDataLength(PFILE_OBJECT FileObject, { if (AttrContext->Record.IsNonResident) { + ULONG BytesPerCluster = Fcb->Vcb->NtfsInfo.BytesPerCluster; + ULONGLONG AllocationSize = ROUND_UP(DataSize->QuadPart, BytesPerCluster); + // do we need to increase the allocation size? - if (AttrContext->Record.NonResident.AllocatedSize < DataSize->QuadPart) - { + if (AttrContext->Record.NonResident.AllocatedSize < AllocationSize) + { + ULONG ExistingClusters = AttrContext->Record.NonResident.AllocatedSize / BytesPerCluster; + ULONG ClustersNeeded = (AllocationSize / BytesPerCluster) - ExistingClusters; + LARGE_INTEGER LastClusterInDataRun; + ULONG NextAssignedCluster; + ULONG AssignedClusters; + + NTSTATUS Status = GetLastClusterInDataRun(Fcb->Vcb, &AttrContext->Record, &LastClusterInDataRun.QuadPart); + + DPRINT1("GetLastClusterInDataRun returned: %I64u\n", LastClusterInDataRun.QuadPart); + DPRINT1("Highest VCN of record: %I64u\n", AttrContext->Record.NonResident.HighestVCN); + + while (ClustersNeeded > 0) + { + Status = NtfsAllocateClusters(Fcb->Vcb, + LastClusterInDataRun.LowPart + 1, + ClustersNeeded, + &NextAssignedCluster, + &AssignedClusters); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Error: Unable to allocate requested clusters!\n"); + return Status; + } + + // now we need to add the clusters we allocated to the data run + Status = AddRun(AttrContext, NextAssignedCluster, AssignedClusters); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Error: Unable to add data run!\n"); + return Status; + } + + ClustersNeeded -= AssignedClusters; + LastClusterInDataRun.LowPart = NextAssignedCluster + AssignedClusters - 1; + } + DPRINT1("FixMe: Increasing allocation size is unimplemented!\n"); return STATUS_NOT_IMPLEMENTED; } @@ -459,7 +499,7 @@ WriteAttribute(PDEVICE_EXTENSION Vcb, PUCHAR SourceBuffer = Buffer; LONGLONG StartingOffset; - DPRINT("WriteAttribute(%p, %p, %I64U, %p, %lu)\n", Vcb, Context, Offset, Buffer, Length); + DPRINT("WriteAttribute(%p, %p, %I64u, %p, %lu, %p)\n", Vcb, Context, Offset, Buffer, Length, RealLengthWritten); // is this a resident attribute? if (!Context->Record.IsNonResident) diff --git a/drivers/filesystems/ntfs/ntfs.h b/drivers/filesystems/ntfs/ntfs.h index 4435b4866e..66cb37f4bd 100644 --- a/drivers/filesystems/ntfs/ntfs.h +++ b/drivers/filesystems/ntfs/ntfs.h @@ -511,6 +511,11 @@ NtfsMarkIrpContextForQueue(PNTFS_IRP_CONTEXT IrpContext) //VOID //NtfsDumpAttribute(PATTRIBUTE Attribute); +NTSTATUS +AddRun(PNTFS_ATTR_CONTEXT AttrContext, + ULONGLONG NextAssignedCluster, + ULONG RunLength); + PUCHAR DecodeRun(PUCHAR DataRun, LONGLONG *DataRunOffset, @@ -529,6 +534,11 @@ GetFileNameFromRecord(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord, UCHAR NameType); +NTSTATUS +GetLastClusterInDataRun(PDEVICE_EXTENSION Vcb, + PNTFS_ATTR_RECORD Attribute, + PULONGLONG LastCluster); + PFILENAME_ATTRIBUTE GetBestFileNameFromRecord(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord); @@ -774,7 +784,7 @@ SetAttributeDataLength(PFILE_OBJECT FileObject, PFILE_RECORD_HEADER FileRecord, PLARGE_INTEGER DataSize); -ULONG +ULONGLONG AttributeAllocatedLength(PNTFS_ATTR_RECORD AttrRecord); BOOLEAN @@ -915,6 +925,13 @@ NtfsWrite(PNTFS_IRP_CONTEXT IrpContext); /* volinfo.c */ +NTSTATUS +NtfsAllocateClusters(PDEVICE_EXTENSION DeviceExt, + ULONG FirstDesiredCluster, + ULONG DesiredClusters, + PULONG FirstAssignedCluster, + PULONG AssignedClusters); + ULONGLONG NtfsGetFreeClusters(PDEVICE_EXTENSION DeviceExt); diff --git a/drivers/filesystems/ntfs/volinfo.c b/drivers/filesystems/ntfs/volinfo.c index 13a3b7af7f..c893562189 100644 --- a/drivers/filesystems/ntfs/volinfo.c +++ b/drivers/filesystems/ntfs/volinfo.c @@ -99,6 +99,110 @@ NtfsGetFreeClusters(PDEVICE_EXTENSION DeviceExt) return FreeClusters; } +/** +* NtfsAllocateClusters +* Allocates a run of clusters. The run allocated might be smaller than DesiredClusters. +*/ +NTSTATUS +NtfsAllocateClusters(PDEVICE_EXTENSION DeviceExt, + ULONG FirstDesiredCluster, + ULONG DesiredClusters, + PULONG FirstAssignedCluster, + PULONG AssignedClusters) +{ + NTSTATUS Status; + PFILE_RECORD_HEADER BitmapRecord; + PNTFS_ATTR_CONTEXT DataContext; + ULONGLONG BitmapDataSize; + PCHAR BitmapData; + ULONGLONG FreeClusters = 0; + ULONG Read = 0; + RTL_BITMAP Bitmap; + + DPRINT1("NtfsAllocateClusters(%p, %lu, %lu, %p)\n", DeviceExt, DesiredClusters, FirstDesiredCluster, FirstAssignedCluster, AssignedClusters); + + BitmapRecord = ExAllocatePoolWithTag(NonPagedPool, + DeviceExt->NtfsInfo.BytesPerFileRecord, + TAG_NTFS); + if (BitmapRecord == NULL) + { + return 0; + } + + Status = ReadFileRecord(DeviceExt, NTFS_FILE_BITMAP, BitmapRecord); + if (!NT_SUCCESS(Status)) + { + ExFreePoolWithTag(BitmapRecord, TAG_NTFS); + return 0; + } + + Status = FindAttribute(DeviceExt, BitmapRecord, AttributeData, L"", 0, &DataContext, NULL); + if (!NT_SUCCESS(Status)) + { + ExFreePoolWithTag(BitmapRecord, TAG_NTFS); + return 0; + } + + BitmapDataSize = AttributeDataLength(&DataContext->Record); + BitmapDataSize = min(BitmapDataSize, 0xffffffff); + ASSERT((BitmapDataSize * 8) >= DeviceExt->NtfsInfo.ClusterCount); + BitmapData = ExAllocatePoolWithTag(NonPagedPool, ROUND_UP(BitmapDataSize, DeviceExt->NtfsInfo.BytesPerSector), TAG_NTFS); + if (BitmapData == NULL) + { + ReleaseAttributeContext(DataContext); + ExFreePoolWithTag(BitmapRecord, TAG_NTFS); + return 0; + } + + DPRINT1("Total clusters: %I64x\n", DeviceExt->NtfsInfo.ClusterCount); + DPRINT1("Total clusters in bitmap: %I64x\n", BitmapDataSize * 8); + DPRINT1("Diff in size: %I64d B\n", ((BitmapDataSize * 8) - DeviceExt->NtfsInfo.ClusterCount) * DeviceExt->NtfsInfo.SectorsPerCluster * DeviceExt->NtfsInfo.BytesPerSector); + + ReadAttribute(DeviceExt, DataContext, Read, (PCHAR)((ULONG_PTR)BitmapData + Read), (ULONG)BitmapDataSize); + + RtlInitializeBitMap(&Bitmap, (PULONG)BitmapData, DeviceExt->NtfsInfo.ClusterCount); + FreeClusters = RtlNumberOfClearBits(&Bitmap); + + if (FreeClusters >= DesiredClusters) + { + // TODO: Observe MFT reservation zone + + // Can we get one contiguous run? + ULONG AssignedRun = RtlFindClearBitsAndSet(&Bitmap, DesiredClusters, FirstDesiredCluster); + ULONG LengthWritten; + + if (AssignedRun != 0xFFFFFFFF) + { + *FirstAssignedCluster = AssignedRun; + *AssignedClusters = DesiredClusters; + } + else + { + // we can't get one contiguous run + *AssignedClusters = RtlFindNextForwardRunClear(&Bitmap, FirstDesiredCluster, FirstAssignedCluster); + + if (*AssignedClusters == 0) + { + // we couldn't find any runs starting at DesiredFirstCluster + *AssignedClusters = RtlFindLongestRunClear(&Bitmap, FirstAssignedCluster); + } + + } + + Status = WriteAttribute(DeviceExt, DataContext, 0, BitmapData, (ULONG)BitmapDataSize, &LengthWritten); + } + else + Status = STATUS_DISK_FULL; + + + ReleaseAttributeContext(DataContext); + + ExFreePoolWithTag(BitmapData, TAG_NTFS); + ExFreePoolWithTag(BitmapRecord, TAG_NTFS); + + return Status; +} + static NTSTATUS NtfsGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject,
7 years
1
0
0
0
[reactos] 07/72: [NTFS] Allow for an existing file to be opened with FILE_OVERWRITE, FILE_OVERWRITE_IF, or FILE_SUPERSEDE dispositions, and truncate that file. This allows for a file to be opened and saved in Notepad.exe [provided that file is non-resident and its allocation size doesn't need to change].
by Trevor Thompson
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=84a1280fd6a4572894bbb…
commit 84a1280fd6a4572894bbb70fac70c455958e6d02 Author: Trevor Thompson <tmt256(a)email.vccs.edu> AuthorDate: Sun Jun 26 21:06:02 2016 +0000 [NTFS] Allow for an existing file to be opened with FILE_OVERWRITE, FILE_OVERWRITE_IF, or FILE_SUPERSEDE dispositions, and truncate that file. This allows for a file to be opened and saved in Notepad.exe [provided that file is non-resident and its allocation size doesn't need to change]. svn path=/branches/GSoC_2016/NTFS/; revision=71680 --- drivers/filesystems/ntfs/create.c | 60 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/drivers/filesystems/ntfs/create.c b/drivers/filesystems/ntfs/create.c index 5662806880..344c16464f 100644 --- a/drivers/filesystems/ntfs/create.c +++ b/drivers/filesystems/ntfs/create.c @@ -476,14 +476,66 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject, return Status; } - /* HUGLY HACK: Can't overwrite or supersede a file yet... */ if (RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF || RequestedDisposition == FILE_SUPERSEDE) { - DPRINT1("Cannot yet perform an overwrite or supersede request on NTFS volume\n"); - NtfsCloseFile(DeviceExt, FileObject); - return STATUS_ACCESS_DENIED; + PFILE_RECORD_HEADER fileRecord = NULL; + PNTFS_ATTR_CONTEXT dataContext = NULL; + ULONG DataAttributeOffset; + LARGE_INTEGER Zero; + Zero.QuadPart = 0; + + // TODO: check for appropriate access + + ExAcquireResourceExclusiveLite(&(Fcb->MainResource), TRUE); + + fileRecord = ExAllocatePoolWithTag(NonPagedPool, + Fcb->Vcb->NtfsInfo.BytesPerFileRecord, + TAG_NTFS); + if (fileRecord) + { + + Status = ReadFileRecord(Fcb->Vcb, + Fcb->MFTIndex, + fileRecord); + if (!NT_SUCCESS(Status)) + goto DoneOverwriting; + + // find the data attribute and set it's length to 0 (TODO: Handle Alternate Data Streams) + Status = FindAttribute(Fcb->Vcb, fileRecord, AttributeData, L"", 0, &dataContext, &DataAttributeOffset); + if (!NT_SUCCESS(Status)) + goto DoneOverwriting; + + Status = SetAttributeDataLength(FileObject, Fcb, dataContext, DataAttributeOffset, fileRecord, &Zero); + } + else + { + Status = STATUS_NO_MEMORY; + } + + DoneOverwriting: + if (fileRecord) + ExFreePool(fileRecord); + if (dataContext) + ReleaseAttributeContext(dataContext); + + ExReleaseResourceLite(&(Fcb->MainResource)); + + if (!NT_SUCCESS(Status)) + { + NtfsCloseFile(DeviceExt, FileObject); + return Status; + } + + if (RequestedDisposition == FILE_SUPERSEDE) + { + Irp->IoStatus.Information = FILE_SUPERSEDED; + } + else + { + Irp->IoStatus.Information = FILE_OVERWRITTEN; + } } } else
7 years
1
0
0
0
[reactos] 06/72: [NTFS] Remove unused parameter from SetAttributeDataLength.
by Trevor Thompson
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f47efca89f47655cf845b…
commit f47efca89f47655cf845bfe7f8a84faba40f4b05 Author: Trevor Thompson <tmt256(a)email.vccs.edu> AuthorDate: Sun Jun 26 17:03:31 2016 +0000 [NTFS] Remove unused parameter from SetAttributeDataLength. svn path=/branches/GSoC_2016/NTFS/; revision=71677 --- drivers/filesystems/ntfs/mft.c | 1 - drivers/filesystems/ntfs/ntfs.h | 1 - drivers/filesystems/ntfs/rw.c | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/filesystems/ntfs/mft.c b/drivers/filesystems/ntfs/mft.c index 5d61f534dd..ae2a6cc2ba 100644 --- a/drivers/filesystems/ntfs/mft.c +++ b/drivers/filesystems/ntfs/mft.c @@ -177,7 +177,6 @@ SetAttributeDataLength(PFILE_OBJECT FileObject, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, - PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER DataSize) { if (AttrContext->Record.IsNonResident) diff --git a/drivers/filesystems/ntfs/ntfs.h b/drivers/filesystems/ntfs/ntfs.h index 6ff5b83800..4435b4866e 100644 --- a/drivers/filesystems/ntfs/ntfs.h +++ b/drivers/filesystems/ntfs/ntfs.h @@ -772,7 +772,6 @@ SetAttributeDataLength(PFILE_OBJECT FileObject, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, - PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER DataSize); ULONG diff --git a/drivers/filesystems/ntfs/rw.c b/drivers/filesystems/ntfs/rw.c index 9d11189631..5afb87e9e6 100644 --- a/drivers/filesystems/ntfs/rw.c +++ b/drivers/filesystems/ntfs/rw.c @@ -422,7 +422,7 @@ NTSTATUS NtfsWriteFile(PDEVICE_EXTENSION DeviceExt, AllocationSize = ROUND_UP(DataSize.QuadPart, Fcb->Vcb->NtfsInfo.BytesPerCluster); // set the attribute data length - Status = SetAttributeDataLength(FileObject, Fcb, DataContext, AttributeOffset, FileRecord, DeviceExt, &DataSize); + Status = SetAttributeDataLength(FileObject, Fcb, DataContext, AttributeOffset, FileRecord, &DataSize); if (!NT_SUCCESS(Status)) {
7 years
1
0
0
0
[reactos] 05/72: [NTFS] Update a file's size in the relevant $FILE_NAME attribute of the index entry in the parent directory. +UpdateFileNameRecord() - Searches a parent directory for the proper index entry, then updates the file sizes in that entry. +UpdateIndexEntryFileNameSize() - Recursively searches directory index and applies the size update.
by Trevor Thompson
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a7a2c0d734a447b66d9cc…
commit a7a2c0d734a447b66d9cc5daadb46845dd08327b Author: Trevor Thompson <tmt256(a)email.vccs.edu> AuthorDate: Thu Jun 23 18:02:03 2016 +0000 [NTFS] Update a file's size in the relevant $FILE_NAME attribute of the index entry in the parent directory. +UpdateFileNameRecord() - Searches a parent directory for the proper index entry, then updates the file sizes in that entry. +UpdateIndexEntryFileNameSize() - Recursively searches directory index and applies the size update. svn path=/branches/GSoC_2016/NTFS/; revision=71664 --- drivers/filesystems/ntfs/mft.c | 206 ++++++++++++++++++++++++++++++++++++++++ drivers/filesystems/ntfs/ntfs.h | 27 ++++++ drivers/filesystems/ntfs/rw.c | 17 +++- 3 files changed, 249 insertions(+), 1 deletion(-) diff --git a/drivers/filesystems/ntfs/mft.c b/drivers/filesystems/ntfs/mft.c index 7017ab7695..5d61f534dd 100644 --- a/drivers/filesystems/ntfs/mft.c +++ b/drivers/filesystems/ntfs/mft.c @@ -682,6 +682,212 @@ ReadFileRecord(PDEVICE_EXTENSION Vcb, return FixupUpdateSequenceArray(Vcb, &file->Ntfs); } + +/** +* Searches a file's parent directory (given the parent's index in the mft) +* for the given file. Upon finding an index entry for that file, updates +* Data Size and Allocated Size values in the $FILE_NAME attribute of that entry. +* +* (Most of this code was copied from NtfsFindMftRecord) +*/ +NTSTATUS +UpdateFileNameRecord(PDEVICE_EXTENSION Vcb, + ULONGLONG ParentMFTIndex, + PUNICODE_STRING FileName, + BOOLEAN DirSearch, + ULONGLONG NewDataSize, + ULONGLONG NewAllocationSize) +{ + PFILE_RECORD_HEADER MftRecord; + PNTFS_ATTR_CONTEXT IndexRootCtx; + PINDEX_ROOT_ATTRIBUTE IndexRoot; + PCHAR IndexRecord; + PINDEX_ENTRY_ATTRIBUTE IndexEntry, IndexEntryEnd; + NTSTATUS Status; + ULONG CurrentEntry = 0; + + DPRINT("UpdateFileNameRecord(%p, %I64d, %wZ, %u, %I64u, %I64u)\n", Vcb, ParentMFTIndex, FileName, DirSearch, NewDataSize, NewAllocationSize); + + MftRecord = ExAllocatePoolWithTag(NonPagedPool, + Vcb->NtfsInfo.BytesPerFileRecord, + TAG_NTFS); + if (MftRecord == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + Status = ReadFileRecord(Vcb, ParentMFTIndex, MftRecord); + if (!NT_SUCCESS(Status)) + { + ExFreePoolWithTag(MftRecord, TAG_NTFS); + return Status; + } + + ASSERT(MftRecord->Ntfs.Type == NRH_FILE_TYPE); + Status = FindAttribute(Vcb, MftRecord, AttributeIndexRoot, L"$I30", 4, &IndexRootCtx, NULL); + if (!NT_SUCCESS(Status)) + { + ExFreePoolWithTag(MftRecord, TAG_NTFS); + return Status; + } + + IndexRecord = ExAllocatePoolWithTag(NonPagedPool, Vcb->NtfsInfo.BytesPerIndexRecord, TAG_NTFS); + if (IndexRecord == NULL) + { + ReleaseAttributeContext(IndexRootCtx); + ExFreePoolWithTag(MftRecord, TAG_NTFS); + return STATUS_INSUFFICIENT_RESOURCES; + } + + ReadAttribute(Vcb, IndexRootCtx, 0, IndexRecord, Vcb->NtfsInfo.BytesPerIndexRecord); + IndexRoot = (PINDEX_ROOT_ATTRIBUTE)IndexRecord; + IndexEntry = (PINDEX_ENTRY_ATTRIBUTE)((PCHAR)&IndexRoot->Header + IndexRoot->Header.FirstEntryOffset); + // Index root is always resident. + IndexEntryEnd = (PINDEX_ENTRY_ATTRIBUTE)(IndexRecord + IndexRoot->Header.TotalSizeOfEntries); + + DPRINT("IndexRecordSize: %x IndexBlockSize: %x\n", Vcb->NtfsInfo.BytesPerIndexRecord, IndexRoot->SizeOfEntry); + + Status = UpdateIndexEntryFileNameSize(Vcb, + MftRecord, + IndexRecord, + IndexRoot->SizeOfEntry, + IndexEntry, + IndexEntryEnd, + FileName, + &CurrentEntry, + &CurrentEntry, + DirSearch, + NewDataSize, + NewAllocationSize); + + ReleaseAttributeContext(IndexRootCtx); + ExFreePoolWithTag(IndexRecord, TAG_NTFS); + ExFreePoolWithTag(MftRecord, TAG_NTFS); + + return Status; +} + +/** +* Recursively searches directory index and applies the size update to the $FILE_NAME attribute of the +* proper index entry. +* (Heavily based on BrowseIndexEntries) +*/ +NTSTATUS +UpdateIndexEntryFileNameSize(PDEVICE_EXTENSION Vcb, + PFILE_RECORD_HEADER MftRecord, + PCHAR IndexRecord, + ULONG IndexBlockSize, + PINDEX_ENTRY_ATTRIBUTE FirstEntry, + PINDEX_ENTRY_ATTRIBUTE LastEntry, + PUNICODE_STRING FileName, + PULONG StartEntry, + PULONG CurrentEntry, + BOOLEAN DirSearch, + ULONGLONG NewDataSize, + ULONGLONG NewAllocatedSize) +{ + NTSTATUS Status; + ULONG RecordOffset; + PINDEX_ENTRY_ATTRIBUTE IndexEntry; + PNTFS_ATTR_CONTEXT IndexAllocationCtx; + ULONGLONG IndexAllocationSize; + PINDEX_BUFFER IndexBuffer; + + DPRINT("UpdateIndexEntrySize(%p, %p, %p, %u, %p, %p, %wZ, %u, %u, %u, %I64u, %I64u)\n", Vcb, MftRecord, IndexRecord, IndexBlockSize, FirstEntry, LastEntry, FileName, *StartEntry, *CurrentEntry, DirSearch, NewDataSize, NewAllocatedSize); + + // find the index entry responsible for the file we're trying to update + IndexEntry = FirstEntry; + while (IndexEntry < LastEntry && + !(IndexEntry->Flags & NTFS_INDEX_ENTRY_END)) + { + if ((IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK) > 0x10 && + *CurrentEntry >= *StartEntry && + IndexEntry->FileName.NameType != NTFS_FILE_NAME_DOS && + CompareFileName(FileName, IndexEntry, DirSearch)) + { + *StartEntry = *CurrentEntry; + IndexEntry->FileName.DataSize = NewDataSize; + IndexEntry->FileName.AllocatedSize = NewAllocatedSize; + // indicate that the caller will still need to write the structure to the disk + return STATUS_PENDING; + } + + (*CurrentEntry) += 1; + ASSERT(IndexEntry->Length >= sizeof(INDEX_ENTRY_ATTRIBUTE)); + IndexEntry = (PINDEX_ENTRY_ATTRIBUTE)((PCHAR)IndexEntry + IndexEntry->Length); + } + + /* If we're already browsing a subnode */ + if (IndexRecord == NULL) + { + return STATUS_OBJECT_PATH_NOT_FOUND; + } + + /* If there's no subnode */ + if (!(IndexEntry->Flags & NTFS_INDEX_ENTRY_NODE)) + { + return STATUS_OBJECT_PATH_NOT_FOUND; + } + + Status = FindAttribute(Vcb, MftRecord, AttributeIndexAllocation, L"$I30", 4, &IndexAllocationCtx, NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("Corrupted filesystem!\n"); + return Status; + } + + IndexAllocationSize = AttributeDataLength(&IndexAllocationCtx->Record); + Status = STATUS_OBJECT_PATH_NOT_FOUND; + for (RecordOffset = 0; RecordOffset < IndexAllocationSize; RecordOffset += IndexBlockSize) + { + ReadAttribute(Vcb, IndexAllocationCtx, RecordOffset, IndexRecord, IndexBlockSize); + Status = FixupUpdateSequenceArray(Vcb, &((PFILE_RECORD_HEADER)IndexRecord)->Ntfs); + if (!NT_SUCCESS(Status)) + { + break; + } + + IndexBuffer = (PINDEX_BUFFER)IndexRecord; + ASSERT(IndexBuffer->Ntfs.Type == NRH_INDX_TYPE); + ASSERT(IndexBuffer->Header.AllocatedSize + FIELD_OFFSET(INDEX_BUFFER, Header) == IndexBlockSize); + FirstEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)&IndexBuffer->Header + IndexBuffer->Header.FirstEntryOffset); + LastEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)&IndexBuffer->Header + IndexBuffer->Header.TotalSizeOfEntries); + ASSERT(LastEntry <= (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)IndexBuffer + IndexBlockSize)); + + Status = UpdateIndexEntryFileNameSize(NULL, NULL, NULL, 0, FirstEntry, LastEntry, FileName, StartEntry, CurrentEntry, DirSearch, NewDataSize, NewAllocatedSize); + if (Status == STATUS_PENDING) + { + // write the index record back to disk + ULONG Written; + + // first we need to update the fixup values for the index block + Status = AddFixupArray(Vcb, &((PFILE_RECORD_HEADER)IndexRecord)->Ntfs); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Error: Failed to update fixup sequence array!\n"); + break; + } + + Status = WriteAttribute(Vcb, IndexAllocationCtx, RecordOffset, (const PUCHAR)IndexRecord, IndexBlockSize, &Written); + if (!NT_SUCCESS(Status)) + { + DPRINT1("ERROR Performing write!\n"); + break; + } + + Status = STATUS_SUCCESS; + break; + } + if (NT_SUCCESS(Status)) + { + break; + } + } + + ReleaseAttributeContext(IndexAllocationCtx); + return Status; +} + /** * UpdateFileRecord * @implemented diff --git a/drivers/filesystems/ntfs/ntfs.h b/drivers/filesystems/ntfs/ntfs.h index 9b12a60de8..6ff5b83800 100644 --- a/drivers/filesystems/ntfs/ntfs.h +++ b/drivers/filesystems/ntfs/ntfs.h @@ -778,11 +778,38 @@ SetAttributeDataLength(PFILE_OBJECT FileObject, ULONG AttributeAllocatedLength(PNTFS_ATTR_RECORD AttrRecord); +BOOLEAN +CompareFileName(PUNICODE_STRING FileName, + PINDEX_ENTRY_ATTRIBUTE IndexEntry, + BOOLEAN DirSearch); + NTSTATUS ReadFileRecord(PDEVICE_EXTENSION Vcb, ULONGLONG index, PFILE_RECORD_HEADER file); +NTSTATUS +UpdateIndexEntryFileNameSize(PDEVICE_EXTENSION Vcb, + PFILE_RECORD_HEADER MftRecord, + PCHAR IndexRecord, + ULONG IndexBlockSize, + PINDEX_ENTRY_ATTRIBUTE FirstEntry, + PINDEX_ENTRY_ATTRIBUTE LastEntry, + PUNICODE_STRING FileName, + PULONG StartEntry, + PULONG CurrentEntry, + BOOLEAN DirSearch, + ULONGLONG NewDataSize, + ULONGLONG NewAllocatedSize); + +NTSTATUS +UpdateFileNameRecord(PDEVICE_EXTENSION Vcb, + ULONGLONG ParentMFTIndex, + PUNICODE_STRING FileName, + BOOLEAN DirSearch, + ULONGLONG NewDataSize, + ULONGLONG NewAllocationSize); + NTSTATUS UpdateFileRecord(PDEVICE_EXTENSION Vcb, ULONGLONG index, diff --git a/drivers/filesystems/ntfs/rw.c b/drivers/filesystems/ntfs/rw.c index 5d95300ae2..9d11189631 100644 --- a/drivers/filesystems/ntfs/rw.c +++ b/drivers/filesystems/ntfs/rw.c @@ -413,6 +413,9 @@ NTSTATUS NtfsWriteFile(PDEVICE_EXTENSION DeviceExt, { LARGE_INTEGER DataSize; ULONGLONG AllocationSize; + PFILENAME_ATTRIBUTE fileNameAttribute; + ULONGLONG ParentMFTId; + UNICODE_STRING filename; DataSize.QuadPart = WriteOffset + Length; @@ -430,7 +433,19 @@ NTSTATUS NtfsWriteFile(PDEVICE_EXTENSION DeviceExt, } // now we need to update this file's size in every directory index entry that references it - // (saved for a later commit) + // TODO: put this code in its own function and adapt it to work with every filename / hardlink + // stored in the file record. + fileNameAttribute = GetBestFileNameFromRecord(Fcb->Vcb, FileRecord); + ASSERT(fileNameAttribute); + + ParentMFTId = fileNameAttribute->DirectoryFileReferenceNumber & NTFS_MFT_MASK; + + filename.Buffer = fileNameAttribute->Name; + filename.Length = fileNameAttribute->NameLength * sizeof(WCHAR); + filename.MaximumLength = filename.Length; + + Status = UpdateFileNameRecord(Fcb->Vcb, ParentMFTId, &filename, FALSE, DataSize.QuadPart, AllocationSize); + } else {
7 years
1
0
0
0
[reactos] 04/72: [NTFS] Fix Up AddFixupArray - It needs to accept a PNTFS_RECORD_HEADER for parameter 2, not a PFILE_RECORD_HEADER.
by Trevor Thompson
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4f8133f44b49a9caef0ae…
commit 4f8133f44b49a9caef0aecd0baa1394dce0dfc0e Author: Trevor Thompson <tmt256(a)email.vccs.edu> AuthorDate: Thu Jun 23 15:37:19 2016 +0000 [NTFS] Fix Up AddFixupArray - It needs to accept a PNTFS_RECORD_HEADER for parameter 2, not a PFILE_RECORD_HEADER. svn path=/branches/GSoC_2016/NTFS/; revision=71662 --- drivers/filesystems/ntfs/mft.c | 13 +++++-------- drivers/filesystems/ntfs/ntfs.h | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/filesystems/ntfs/mft.c b/drivers/filesystems/ntfs/mft.c index a53b37fb87..7017ab7695 100644 --- a/drivers/filesystems/ntfs/mft.c +++ b/drivers/filesystems/ntfs/mft.c @@ -698,7 +698,7 @@ UpdateFileRecord(PDEVICE_EXTENSION Vcb, DPRINT("UpdateFileRecord(%p, %I64x, %p)\n", Vcb, index, file); // Add the fixup array to prepare the data for writing to disk - AddFixupArray(Vcb, file); + AddFixupArray(Vcb, &file->Ntfs); // write the file record to the master file table Status = WriteAttribute(Vcb, Vcb->MFTContext, index * Vcb->NtfsInfo.BytesPerFileRecord, (const PUCHAR)file, Vcb->NtfsInfo.BytesPerFileRecord, &BytesWritten); @@ -747,27 +747,24 @@ FixupUpdateSequenceArray(PDEVICE_EXTENSION Vcb, NTSTATUS AddFixupArray(PDEVICE_EXTENSION Vcb, - PFILE_RECORD_HEADER Record) + PNTFS_RECORD_HEADER Record) { USHORT *pShortToFixUp; - unsigned int ArrayEntryCount = Record->BytesAllocated / Vcb->NtfsInfo.BytesPerSector; + unsigned int ArrayEntryCount = Record->UsaCount - 1; unsigned int Offset = Vcb->NtfsInfo.BytesPerSector - 2; int i; - PFIXUP_ARRAY fixupArray = (PFIXUP_ARRAY)((UCHAR*)Record + Record->Ntfs.UsaOffset); + PFIXUP_ARRAY fixupArray = (PFIXUP_ARRAY)((UCHAR*)Record + Record->UsaOffset); DPRINT("AddFixupArray(%p, %p)\n fixupArray->USN: %u, ArrayEntryCount: %u\n", Vcb, Record, fixupArray->USN, ArrayEntryCount); - if (Record->BytesAllocated % Vcb->NtfsInfo.BytesPerSector != 0) - ArrayEntryCount++; - fixupArray->USN++; for (i = 0; i < ArrayEntryCount; i++) { DPRINT("USN: %u\tOffset: %u\n", fixupArray->USN, Offset); - pShortToFixUp = (USHORT*)((UCHAR*)Record + Offset); + pShortToFixUp = (USHORT*)((PCHAR)Record + Offset); fixupArray->Array[i] = *pShortToFixUp; *pShortToFixUp = fixupArray->USN; Offset += Vcb->NtfsInfo.BytesPerSector; diff --git a/drivers/filesystems/ntfs/ntfs.h b/drivers/filesystems/ntfs/ntfs.h index 6b9a86ed07..9b12a60de8 100644 --- a/drivers/filesystems/ntfs/ntfs.h +++ b/drivers/filesystems/ntfs/ntfs.h @@ -811,7 +811,7 @@ FixupUpdateSequenceArray(PDEVICE_EXTENSION Vcb, NTSTATUS AddFixupArray(PDEVICE_EXTENSION Vcb, - PFILE_RECORD_HEADER Record); + PNTFS_RECORD_HEADER Record); NTSTATUS ReadLCN(PDEVICE_EXTENSION Vcb,
7 years
1
0
0
0
← Newer
1
...
24
25
26
27
28
29
30
...
36
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Results per page:
10
25
50
100
200