www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - code to get LCN from filename

I hacked up one of the file.d functions to create a function that 
returns the first Logical Cluster Number for a regular file.  
I've tested it on the 2GB layout that has been defragged with the 
myDefrag sortByName() operation, and it works as expected.  
Values of 0 mean the file was small enough to fit in the MFT.  
The LCN numbers would be a good thing to sort by before doing 
accesses on entries coming from any large directory operations 
... for example zip, copy, delete of directories.



enum {
	FILE_DEVICE_FILE_SYSTEM = 9,
	METHOD_NEITHER = 3,
	FILE_ANY_ACCESS = 0
}
uint CTL_CODE(uint t, uint f, uint m, uint a) {
	return (t << 16) | (a << 14) | (f << 2) | m;
}

const FSCTL_GET_RETRIEVAL_POINTERS = 
CTL_CODE(FILE_DEVICE_FILE_SYSTEM,28,METHOD_NEITHER,FILE_ANY_ACCESS);

/*********************************************
extern (Windows) int DeviceIoControl(void *, uint, void *, uint, 
void *, uint, uint *, _OVERLAPPED *);
from WinIoCtl.h in SDK
#define FSCTL_GET_RETRIEVAL_POINTERS    
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 28,  METHOD_NEITHER, 
FILE_ANY_ACCESS) // STARTING_VCN_INPUT_BUFFER, 
RETRIEVAL_POINTERS_BUFFER

*/
struct  RETRIEVAL_POINTERS_BUFFER{
}
ulong getStartLCN (in char[] name)
{
	int[] buffer = [ 0 ];
     version(Windows)
     {
         alias TypeTuple!(GENERIC_READ, FILE_SHARE_READ, null, 
OPEN_EXISTING,
						 FILE_ATTRIBUTE_NORMAL,
						 HANDLE.init)
             defaults;
         auto h = useWfuncs
             ? CreateFileW(std.utf.toUTF16z(name), defaults)
             : CreateFileA(toMBSz(name), defaults);

         cenforce(h != INVALID_HANDLE_VALUE, name);
         scope(exit) cenforce(CloseHandle(h), name);

		alias long LARGE_INTEGER ;
		struct STARTING_VCN_INPUT_BUFFER {
			LARGE_INTEGER StartingVcn;
		}
		STARTING_VCN_INPUT_BUFFER inputVcn;
		inputVcn.StartingVcn = 0;

		struct RPExtents{
			LARGE_INTEGER NextVcn;
			LARGE_INTEGER Lcn;
		}
		struct RETRIEVAL_POINTERS_BUFFER {
			DWORD         ExtentCount;
			LARGE_INTEGER StartingVcn;
			RPExtents rpExtents[1];
		}
		RETRIEVAL_POINTERS_BUFFER rpBuf;

		DWORD numBytes;

		//expect only a partial return of one rpExtent
		 DeviceIoControl(
								 h, FSCTL_GET_RETRIEVAL_POINTERS,
								 cast(void*)&inputVcn, inputVcn.sizeof,
								 cast(void*)&rpBuf, rpBuf.sizeof,
								 &numBytes, null
								 );

		return cast(ulong)rpBuf.rpExtents[0].Lcn;
     }
     else version(Posix)
         return 0; // not implemented
}
Apr 08 2012