|
|
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
tfat.c
Abstract:
Test program for the Fat File system
Author:
Gary Kimura [GaryKi] 24-May-1989
Revision History:
--*/
#include <stdio.h>
#include <string.h>
#define toupper(C) ((C) >= 'a' && (C) <= 'z' ? (C) - ('a' - 'A') : (C))
#define isdigit(C) ((C) >= '0' && (C) <= '9')
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#define simprintf(X,Y) {if (!Silent) {printf(X,Y);} }
BOOLEAN Silent;
//
// The buffer size must be a multiple of 512
//
#define BUFFERSIZE 1024
UCHAR Buffer[BUFFERSIZE];
CHAR Prefix[64];
ULONG WriteThrough = 0;
VOID WaitForSingleObjectError( IN NTSTATUS Status );
VOID CreateFileError( IN NTSTATUS Status, PCHAR File );
VOID OpenFileError( IN NTSTATUS Status, PCHAR File );
VOID ReadFileError( IN NTSTATUS Status );
VOID WriteFileError( IN NTSTATUS Status );
VOID CheckIoStatus( IN PIO_STATUS_BLOCK IoStatus, IN ULONG Length, IN BOOLEAN Read );
VOID SetInformationFileError( IN NTSTATUS Status );
VOID QueryInformationFileError( IN NTSTATUS Status );
VOID CloseError( IN NTSTATUS Status );
VOID IoStatusError( IN NTSTATUS Status );
VOID main( int argc, char *argv[] ) { ULONG i; ULONG Count; VOID FatMain(); CHAR Device[8]; STRING NtDevice; CHAR NtDeviceBuffer[32];
if (argc <= 1) {
printf("usage: %s drive: [iterations [writethrough] ]\n", argv[0]); return; }
//
// Decode the device/drive
//
strcpy( Device, argv[1] );
NtDevice.MaximumLength = NtDevice.Length = 32; NtDevice.Buffer = NtDeviceBuffer;
if (!RtlDosPathNameToNtPathName( Device, &NtDevice, NULL, NULL )) { printf( "Invalid Dos Device Name\n" ); RtlFreeHeap(RtlProcessHeap(), 0, NtDevice.Buffer); return; }
if (NtDevice.Length > 31) { NtDevice.Length = 31; }
NtDevice.Buffer[NtDevice.Length] = 0;
//
// Now do the iteration count
//
if (argc >= 3) { Count = 0; for (i = 0; isdigit(argv[2][i]); i += 1) { Count = Count * 10 + argv[2][i] - '0'; } } else { Count = 1; }
//
// Check for write through
//
if (argc >= 4) { WriteThrough = FILE_WRITE_THROUGH; }
//
// Check for silent operation
//
if (toupper(Device[0]) != Device[0]) { Silent = TRUE; } else { Silent = FALSE; }
//
// Do the work
//
FatMain(Count, NtDevice.Buffer);
RtlFreeHeap(RtlProcessHeap(), 0, NtDevice.Buffer);
return; }
VOID FatMain( IN ULONG LoopCount, IN CHAR Device[] ) { VOID Create(),Delete(),Mkdir(),Directory(),Read();
CHAR Str[64]; CHAR LoopStr[64]; ULONG i; LARGE_INTEGER Time;
printf("FatMain %d\n", LoopCount);
NtQuerySystemTime(&Time); strcpy( Prefix, Device); Prefix[48] = 0; RtlIntegerToChar((ULONG)NtCurrentTeb()->ClientId.UniqueProcess, 16, -8, &Prefix[strlen(Device)]);
Mkdir( Prefix ); Directory( Device ); Directory( Prefix );
for (i = 0; i < LoopCount; i += 1) {
NtQuerySystemTime(&Time); strcpy(LoopStr, "Start loop xxxxxxxx "); RtlIntegerToChar(i, 16, -8, &LoopStr[11]); strcat( LoopStr, Prefix ); printf(LoopStr); printf("\n");
strcpy( Str, Prefix ); Create( strcat( Str, "\\1.tmp" ), Time.LowPart, 1 ); strcpy( Str, Prefix ); Create( strcat( Str, "\\2.tmp" ), Time.LowPart, 2 ); strcpy( Str, Prefix ); Create( strcat( Str, "\\4.tmp" ), Time.LowPart, 4 ); strcpy( Str, Prefix ); Create( strcat( Str, "\\8.tmp" ), Time.LowPart, 8 ); strcpy( Str, Prefix ); Create( strcat( Str, "\\16.tmp" ), Time.LowPart, 16 ); strcpy( Str, Prefix ); Create( strcat( Str, "\\32.tmp" ), Time.LowPart, 32 ); strcpy( Str, Prefix ); Create( strcat( Str, "\\64.tmp" ), Time.LowPart, 64 ); strcpy( Str, Prefix ); Create( strcat( Str, "\\128.tmp" ), Time.LowPart, 128 ); strcpy( Str, Prefix ); Create( strcat( Str, "\\236.tmp" ), Time.LowPart, 256 ); strcpy( Str, Prefix ); Create( strcat( Str, "\\512.tmp" ), Time.LowPart, 512 ); strcpy( Str, Prefix ); Create( strcat( Str, "\\1024.tmp" ), Time.LowPart, 1024 ); strcpy( Str, Prefix ); Create( strcat( Str, "\\2048.tmp" ), Time.LowPart, 2048 ); strcpy( Str, Prefix ); Create( strcat( Str, "\\4096.tmp" ), Time.LowPart, 4096 ); strcpy( Str, Prefix ); Create( strcat( Str, "\\8192.tmp" ), Time.LowPart, 8192 ); strcpy( Str, Prefix ); Create( strcat( Str, "\\16384.tmp" ), Time.LowPart, 16384 ); strcpy( Str, Prefix ); Create( strcat( Str, "\\32768.tmp" ), Time.LowPart, 32768 );
strcpy( Str, Prefix ); Read( strcat( Str, "\\1.tmp" ), Time.LowPart, 1 ); strcpy( Str, Prefix ); Read( strcat( Str, "\\2.tmp" ), Time.LowPart, 2 ); strcpy( Str, Prefix ); Read( strcat( Str, "\\4.tmp" ), Time.LowPart, 4 ); strcpy( Str, Prefix ); Read( strcat( Str, "\\8.tmp" ), Time.LowPart, 8 ); strcpy( Str, Prefix ); Read( strcat( Str, "\\16.tmp" ), Time.LowPart, 16 ); strcpy( Str, Prefix ); Read( strcat( Str, "\\32.tmp" ), Time.LowPart, 32 ); strcpy( Str, Prefix ); Read( strcat( Str, "\\64.tmp" ), Time.LowPart, 64 ); strcpy( Str, Prefix ); Read( strcat( Str, "\\128.tmp" ), Time.LowPart, 128 ); strcpy( Str, Prefix ); Read( strcat( Str, "\\236.tmp" ), Time.LowPart, 256 ); strcpy( Str, Prefix ); Read( strcat( Str, "\\512.tmp" ), Time.LowPart, 512 ); strcpy( Str, Prefix ); Read( strcat( Str, "\\1024.tmp" ), Time.LowPart, 1024 ); strcpy( Str, Prefix ); Read( strcat( Str, "\\2048.tmp" ), Time.LowPart, 2048 ); strcpy( Str, Prefix ); Read( strcat( Str, "\\4096.tmp" ), Time.LowPart, 4096 ); strcpy( Str, Prefix ); Read( strcat( Str, "\\8192.tmp" ), Time.LowPart, 8192 ); strcpy( Str, Prefix ); Read( strcat( Str, "\\16384.tmp" ), Time.LowPart, 16384 ); strcpy( Str, Prefix ); Read( strcat( Str, "\\32768.tmp" ), Time.LowPart, 32768 );
Directory( Device ); Directory( Prefix );
strcpy( Str, Prefix ); Delete( strcat( Str, "\\1.tmp" ) ); strcpy( Str, Prefix ); Delete( strcat( Str, "\\2.tmp" ) ); strcpy( Str, Prefix ); Delete( strcat( Str, "\\4.tmp" ) ); strcpy( Str, Prefix ); Delete( strcat( Str, "\\8.tmp" ) ); strcpy( Str, Prefix ); Delete( strcat( Str, "\\16.tmp" ) ); strcpy( Str, Prefix ); Delete( strcat( Str, "\\32.tmp" ) ); strcpy( Str, Prefix ); Delete( strcat( Str, "\\64.tmp" ) ); strcpy( Str, Prefix ); Delete( strcat( Str, "\\128.tmp" ) ); strcpy( Str, Prefix ); Delete( strcat( Str, "\\236.tmp" ) ); strcpy( Str, Prefix ); Delete( strcat( Str, "\\512.tmp" ) ); strcpy( Str, Prefix ); Delete( strcat( Str, "\\1024.tmp" ) ); strcpy( Str, Prefix ); Delete( strcat( Str, "\\2048.tmp" ) ); strcpy( Str, Prefix ); Delete( strcat( Str, "\\4096.tmp" ) ); strcpy( Str, Prefix ); Delete( strcat( Str, "\\8192.tmp" ) ); strcpy( Str, Prefix ); Delete( strcat( Str, "\\16384.tmp" ) ); strcpy( Str, Prefix ); Delete( strcat( Str, "\\32768.tmp" ) );
Directory( Device ); Directory( Prefix ); }
printf( "Done\n" );
return; }
VOID Create( IN PCHAR FileName, IN ULONG FileTime, IN ULONG FileCount ) { NTSTATUS Status;
HANDLE FileHandle; OBJECT_ATTRIBUTES ObjectAttributes; STRING NameString; IO_STATUS_BLOCK IoStatus; LARGE_INTEGER AllocationSize;
LARGE_INTEGER ByteOffset; ULONG Count;
ULONG Pattern[3];
//
// Get the filename
//
simprintf("Create ", 0); simprintf(FileName, 0); simprintf("\n", 0);
//
// Create the new file
//
AllocationSize = LiFromUlong( FileCount * 4 ); RtlInitString( &NameString, FileName ); InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL ); if (!NT_SUCCESS(Status = NtCreateFile( &FileHandle, FILE_WRITE_DATA | SYNCHRONIZE, &ObjectAttributes, &IoStatus, &AllocationSize, FILE_ATTRIBUTE_NORMAL, 0L, FILE_SUPERSEDE, WriteThrough, (PVOID)NULL, 0L ))) { CreateFileError( Status , FileName ); return; }
//
// The main loop writes out the test pattern our test pattern
// is <FileTime> <FileSize> <Count> where count is the current
// iteration count for the current test pattern output.
//
Pattern[0] = FileTime; Pattern[1] = FileCount;
for (Count = 0; Count < FileCount; Count += 1) {
Pattern[2] = Count;
ByteOffset = LiFromUlong( Count * 3 * 4 );
if (!NT_SUCCESS(Status = NtWriteFile( FileHandle, (HANDLE)NULL, (PIO_APC_ROUTINE)NULL, (PVOID)NULL, &IoStatus, Pattern, 3 * 4, &ByteOffset, (PULONG) NULL ))) { WriteFileError( Status ); return; }
if (!NT_SUCCESS(Status = NtWaitForSingleObject(FileHandle, TRUE, NULL))) { WaitForSingleObjectError( Status ); return; }
//
// check how the write turned out
//
CheckIoStatus( &IoStatus, 3 * 4, FALSE ); if (!NT_SUCCESS(IoStatus.Status)) { IoStatusError( IoStatus.Status ); break; } }
//
// Now close the file
//
if (!NT_SUCCESS(Status = NtClose( FileHandle ))) { CloseError( Status ); }
//
// And return to our caller
//
return; }
VOID Read( IN PCHAR FileName, IN ULONG FileTime, IN ULONG FileCount ) { NTSTATUS Status;
HANDLE FileHandle; OBJECT_ATTRIBUTES ObjectAttributes; STRING NameString; IO_STATUS_BLOCK IoStatus; LARGE_INTEGER AllocationSize;
LARGE_INTEGER ByteOffset; ULONG Count;
ULONG Pattern[3];
//
// Get the filename
//
simprintf("Read ", 0); simprintf(FileName, 0); simprintf("\n", 0);
//
// Open the existing file
//
AllocationSize = LiFromUlong( FileCount * 4 ); RtlInitString( &NameString, FileName ); InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL ); if (!NT_SUCCESS(Status = NtOpenFile( &FileHandle, FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE, &ObjectAttributes, &IoStatus, 0L, WriteThrough ))) { OpenFileError( Status, FileName ); return; }
//
// The main loop read in the test pattern our test pattern
// is <FileTime> <FileSize> <Count> where count is the current
// iteration count for the current test pattern output.
//
for (Count = 0; Count < FileCount; Count += 1) {
ByteOffset = LiFromUlong( Count * 3 * 4 );
if (!NT_SUCCESS(Status = NtReadFile( FileHandle, (HANDLE)NULL, (PIO_APC_ROUTINE)NULL, (PVOID)NULL, &IoStatus, Pattern, 3 * 4, &ByteOffset, (PULONG) NULL ))) {
ReadFileError( Status ); return; }
if (!NT_SUCCESS(Status = NtWaitForSingleObject(FileHandle, TRUE, NULL))) { WaitForSingleObjectError( Status ); return; }
//
// check how the read turned out
//
CheckIoStatus( &IoStatus, 3 * 4, TRUE ); if (!NT_SUCCESS(IoStatus.Status)) { IoStatusError( IoStatus.Status ); break; }
//
// Now compare the what we read with what we should have read
//
if ((Pattern[0] != FileTime) || (Pattern[1] != FileCount) || (Pattern[2] != Count)) {
printf("**** Read Error ****\n"); NtPartyByNumber( 50 ); return; } }
//
// Now close the file
//
if (!NT_SUCCESS(Status = NtClose( FileHandle ))) { CloseError( Status ); }
//
// And return to our caller
//
return; }
VOID Delete( IN PCHAR FileName ) { NTSTATUS Status;
HANDLE FileHandle; OBJECT_ATTRIBUTES ObjectAttributes; STRING NameString; IO_STATUS_BLOCK IoStatus;
//
// Get the filename
//
simprintf("Delete ", 0); simprintf(FileName, 0); simprintf("\n", 0);
//
// Open the file for delete access
//
RtlInitString( &NameString, FileName ); InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL ); if (!NT_SUCCESS(Status = NtCreateFile( &FileHandle, DELETE | SYNCHRONIZE, &ObjectAttributes, &IoStatus, (PLARGE_INTEGER)NULL, 0L, 0L, FILE_OPEN, WriteThrough, (PVOID)NULL, 0L ))) { CreateFileError( Status, FileName ); return; }
//
// Mark the file for delete
//
((PFILE_DISPOSITION_INFORMATION)&Buffer[0])->DeleteFile = TRUE;
if (!NT_SUCCESS(Status = NtSetInformationFile( FileHandle, &IoStatus, Buffer, sizeof(FILE_DISPOSITION_INFORMATION), FileDispositionInformation))) { SetInformationFileError( Status ); return; }
//
// Now close the file
//
if (!NT_SUCCESS(Status = NtClose( FileHandle ))) { CloseError( Status ); }
//
// And return to our caller
//
return; }
VOID Directory( IN PCHAR String ) { NTSTATUS Status;
HANDLE FileHandle; OBJECT_ATTRIBUTES ObjectAttributes; STRING NameString; IO_STATUS_BLOCK IoStatus;
NTSTATUS NtStatus;
PFILE_ADIRECTORY_INFORMATION FileInfo; ULONG i;
//
// Get the filename
//
simprintf("Directory ", 0); simprintf(String, 0); simprintf("\n", 0);
//
// Open the file for list directory access
//
RtlInitString( &NameString, String ); InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL ); if (!NT_SUCCESS(Status = NtOpenFile( &FileHandle, FILE_LIST_DIRECTORY | SYNCHRONIZE, &ObjectAttributes, &IoStatus, FILE_SHARE_READ, WriteThrough | FILE_DIRECTORY_FILE ))) { OpenFileError( Status , String ); return; }
//
// zero out the buffer so next time we'll recognize the end of data
//
for (i = 0; i < BUFFERSIZE; i += 1) { Buffer[i] = 0; }
//
// Do the directory loop
//
for (NtStatus = NtQueryDirectoryFile( FileHandle, (HANDLE)NULL, (PIO_APC_ROUTINE)NULL, (PVOID)NULL, &IoStatus, Buffer, BUFFERSIZE, FileADirectoryInformation, FALSE, (PSTRING)NULL, TRUE); NT_SUCCESS(NtStatus); NtStatus = NtQueryDirectoryFile( FileHandle, (HANDLE)NULL, (PIO_APC_ROUTINE)NULL, (PVOID)NULL, &IoStatus, Buffer, BUFFERSIZE, FileADirectoryInformation, FALSE, (PSTRING)NULL, FALSE) ) {
if (!NT_SUCCESS(Status = NtWaitForSingleObject(FileHandle, TRUE, NULL))) { // NtPartyByNumber(50);
WaitForSingleObjectError( Status ); return; }
//
// Check the Irp for success
//
if (!NT_SUCCESS(IoStatus.Status)) {
break;
}
//
// For every record in the buffer type out the directory information
//
//
// Point to the first record in the buffer, we are guaranteed to have
// one otherwise IoStatus would have been No More Files
//
FileInfo = (PFILE_ADIRECTORY_INFORMATION)&Buffer[0];
while (TRUE) {
//
// Print out information about the file
//
simprintf("%8lx ", FileInfo->FileAttributes); simprintf("%8lx/", FileInfo->EndOfFile.LowPart); simprintf("%8lx ", FileInfo->AllocationSize.LowPart);
{ CHAR Saved; Saved = FileInfo->FileName[FileInfo->FileNameLength]; FileInfo->FileName[FileInfo->FileNameLength] = 0; simprintf(FileInfo->FileName, 0); FileInfo->FileName[FileInfo->FileNameLength] = Saved; }
simprintf("\n", 0);
//
// Check if there is another record, if there isn't then we
// simply get out of this loop
//
if (FileInfo->NextEntryOffset == 0) { break; }
//
// There is another record so advance FileInfo to the next
// record
//
FileInfo = (PFILE_ADIRECTORY_INFORMATION)(((PUCHAR)FileInfo) + FileInfo->NextEntryOffset);
}
//
// zero out the buffer so next time we'll recognize the end of data
//
for (i = 0; i < BUFFERSIZE; i += 1) { Buffer[i] = 0; }
}
//
// Now close the file
//
if (!NT_SUCCESS(Status = NtClose( FileHandle ))) { CloseError( Status ); }
//
// And return to our caller
//
return;
}
VOID Mkdir( IN PCHAR String ) { NTSTATUS Status;
HANDLE FileHandle; OBJECT_ATTRIBUTES ObjectAttributes; STRING NameString; IO_STATUS_BLOCK IoStatus; LARGE_INTEGER AllocationSize;
//
// Get the filename
//
simprintf("Mkdir ", 0); simprintf(String, 0); simprintf("\n", 0);
//
// Create the new directory
//
AllocationSize = LiFromLong( 4 ); RtlInitString( &NameString, String ); InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL ); if (!NT_SUCCESS(Status = NtCreateFile( &FileHandle, SYNCHRONIZE, &ObjectAttributes, &IoStatus, &AllocationSize, 0L, 0L, FILE_CREATE, WriteThrough | FILE_DIRECTORY_FILE, (PVOID)NULL, 0L ))) { CreateFileError( Status , String ); return; }
//
// Now close the directory
//
if (!NT_SUCCESS(Status = NtClose( FileHandle ))) { CloseError( Status ); }
//
// And return to our caller
//
return; }
VOID WaitForSingleObjectError(NTSTATUS Status) { printf("%s WaitForSingleObject Error %X\n", Prefix, Status); }
VOID CreateFileError(NTSTATUS Status, PCHAR File) { printf("%s CreateFile of %s Error %X\n", Prefix, File, Status); }
VOID OpenFileError(NTSTATUS Status, PCHAR File) { printf("%s OpenFile of %s Error %X\n", Prefix, File, Status); }
VOID ReadFileError(NTSTATUS Status) { printf("%s ReadFile Error %X\n", Prefix, Status); }
VOID WriteFileError(NTSTATUS Status) { printf("%s WriteFile Error %X\n", Prefix, Status); }
VOID SetInformationFileError(NTSTATUS Status) { printf("%s SetInfoFile Error %X\n", Prefix, Status); }
VOID QueryInformationFileError(NTSTATUS Status) { printf("%s QueryInfoFile Error %X\n", Prefix, Status); }
VOID CloseError(NTSTATUS Status) { printf("%s Close Error %X\n", Prefix, Status); }
VOID IoStatusError(NTSTATUS Status) { printf("%s IoStatus Error %X\n", Prefix, Status); }
VOID CheckIoStatus(PIO_STATUS_BLOCK IoStatus, ULONG Length, BOOLEAN Read) { if (!NT_SUCCESS(IoStatus->Status)) { printf(" IoStatus->Status Error %08lx\n", IoStatus->Status); } if ((!Read && (IoStatus->Information != Length))
||
(Read && (IoStatus->Information > Length))) {
printf(" IoStatus->Information Error %08lx\n", IoStatus->Information); } }
|