Author: pschweitzer
Date: Tue Oct 28 19:17:59 2014
New Revision: 65082

URL: http://svn.reactos.org/svn/reactos?rev=65082&view=rev
Log:
[NTFS]
Finally, implement NtfsGetFreeClusters() which will just read the $Data stream 
from $BITMAP file record to get the amount of free clusters to allow estimating 
the free space on a volume.
The implementation is likely under-optimized... But wwell, the rest of the FSD 
is not better. Who talked about caching?! ;-)

Because pictures are more relevant than words in such case: 
http://www.heisspiter.net/~Pierre/rostests/NTFS_disksize.png

Modified:
    trunk/reactos/drivers/filesystems/ntfs/volinfo.c

Modified: trunk/reactos/drivers/filesystems/ntfs/volinfo.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/ntfs/volinfo.c?rev=65082&r1=65081&r2=65082&view=diff
==============================================================================
--- trunk/reactos/drivers/filesystems/ntfs/volinfo.c    [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/ntfs/volinfo.c    [iso-8859-1] Tue Oct 28 
19:17:59 2014
@@ -36,8 +36,67 @@
 ULONGLONG
 NtfsGetFreeClusters(PDEVICE_EXTENSION DeviceExt)
 {
-    UNIMPLEMENTED;
-    return 0;
+    NTSTATUS Status;
+    PFILE_RECORD_HEADER BitmapRecord;
+    PNTFS_ATTR_CONTEXT DataContext;
+    ULONGLONG BitmapDataSize;
+    PCHAR BitmapData;
+    ULONGLONG FreeClusters = 0;
+    ULONG Read = 0;
+    RTL_BITMAP Bitmap;
+
+    DPRINT1("NtfsGetFreeClusters(%p)\n", DeviceExt);
+
+    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);
+    if (!NT_SUCCESS(Status))
+    {
+        ExFreePoolWithTag(BitmapRecord, TAG_NTFS);
+        return 0;
+    }
+
+    BitmapDataSize = AttributeDataLength(&DataContext->Record);
+    ASSERT((BitmapDataSize * 8) >= (DeviceExt->NtfsInfo.SectorCount / 
DeviceExt->NtfsInfo.SectorsPerCluster));
+    BitmapData = ExAllocatePoolWithTag(NonPagedPool, BitmapDataSize, TAG_NTFS);
+    if (BitmapData == NULL)
+    {
+        ReleaseAttributeContext(DataContext);
+        ExFreePoolWithTag(BitmapRecord, TAG_NTFS);
+        return 0;
+    }
+
+    /* FIXME: Totally underoptimized! */
+    for (; Read < BitmapDataSize; Read += DeviceExt->NtfsInfo.BytesPerSector)
+    {
+        ReadAttribute(DeviceExt, DataContext, Read, 
(PCHAR)((ULONG_PTR)BitmapData + Read), DeviceExt->NtfsInfo.BytesPerSector);
+    }
+    ReleaseAttributeContext(DataContext);
+
+    DPRINT1("Total clusters: %I64x\n", DeviceExt->NtfsInfo.SectorCount / 
DeviceExt->NtfsInfo.SectorsPerCluster);
+    DPRINT1("Total clusters in bitmap: %I64x\n", BitmapDataSize * 8);
+    DPRINT1("Diff in size: %I64d B\n", ((BitmapDataSize * 8) - 
(DeviceExt->NtfsInfo.SectorCount / DeviceExt->NtfsInfo.SectorsPerCluster)) * 
DeviceExt->NtfsInfo.SectorsPerCluster * DeviceExt->NtfsInfo.BytesPerSector);
+
+    RtlInitializeBitMap(&Bitmap, (PULONG)BitmapData, 
DeviceExt->NtfsInfo.SectorCount / DeviceExt->NtfsInfo.SectorsPerCluster);
+    FreeClusters = RtlNumberOfClearBits(&Bitmap);
+
+    ExFreePoolWithTag(BitmapData, TAG_NTFS);
+    ExFreePoolWithTag(BitmapRecord, TAG_NTFS);
+
+    return FreeClusters;
 }
 
 static


Reply via email to