Partial directory caching (create calls cached, but dir info calls

still use non cached routines).

svn path=/trunk/; revision=2038
This commit is contained in:
Rex Jolliff 2001-07-05 01:51:53 +00:00
parent 52ead14335
commit 208eecc0f4
8 changed files with 681 additions and 234 deletions

View file

@ -1,4 +1,4 @@
/* $Id: create.c,v 1.26 2001/06/14 21:05:08 jfilby Exp $
/* $Id: create.c,v 1.27 2001/07/05 01:51:52 rex Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -21,10 +21,6 @@
/* GLOBALS *******************************************************************/
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
#define TAG_CCB TAG('V', 'C', 'C', 'B')
/* FUNCTIONS *****************************************************************/
BOOLEAN
@ -60,7 +56,7 @@ IsDeletedEntry (PVOID Block, ULONG Offset)
(((FATDirEntry *) Block)[Offset].Filename[0] == 0));
}
static void vfat8Dot3ToString (PCHAR pBasename, PCHAR pExtension, PWSTR pName)
void vfat8Dot3ToString (PCHAR pBasename, PCHAR pExtension, PWSTR pName)
{
int fromIndex, toIndex;
@ -475,196 +471,57 @@ VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
* FUNCTION: Opens a file
*/
{
PWSTR current = NULL;
PWSTR next;
PWSTR string;
// PWSTR buffer; // used to store a pointer while checking MAX_PATH conformance
PVFATFCB ParentFcb;
PVFATFCB Fcb;
PVFATFCB Temp;
PVFATCCB newCCB;
NTSTATUS Status;
PWSTR AbsFileName = NULL;
ULONG BytesPerCluster, FileCacheQuantum;
DPRINT ("VfatOpenFile(%08lx, %08lx, %S)\n", DeviceExt, FileObject, FileName);
/* FIXME : treat relative name */
if (FileObject->RelatedFileObject)
{
DPRINT ("Converting relative filename to absolute filename\n");
Status = vfatMakeAbsoluteFilename (FileObject->RelatedFileObject,
FileName,
&AbsFileName);
FileName = AbsFileName;
}
/*
* try first to find an existing FCB in memory
*/
CHECKPOINT;
//FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
DPRINT ("PathName to open: %S\n", FileName);
/* try first to find an existing FCB in memory */
DPRINT ("Checking for existing FCB in memory\n");
Fcb = vfatGrabFCBFromTable (DeviceExt, FileName);
if (Fcb != NULL)
if (Fcb == NULL)
{
FileObject->FsContext = (PVOID)&Fcb->RFCB;
newCCB = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB);
memset (newCCB, 0, sizeof (VFATCCB));
FileObject->Flags = FileObject->Flags |
FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ;
FileObject->SectionObjectPointers = &Fcb->SectionObjectPointers;
FileObject->FsContext2 = newCCB;
newCCB->pFcb = Fcb;
newCCB->PtrFileObject = FileObject;
if (AbsFileName)
ExFreePool (AbsFileName);
return STATUS_SUCCESS;
DPRINT ("No existing FCB found, making a new one if file exists.\n");
Status = vfatGetFCBForFile (DeviceExt, &ParentFcb, &Fcb, FileName);
if (ParentFcb != NULL)
{
vfatReleaseFCB (DeviceExt, ParentFcb);
}
if (!NT_SUCCESS (Status))
{
DPRINT ("Could not make a new FCB, status: %x\n", Status);
if (AbsFileName)
ExFreePool (AbsFileName);
return Status;
}
}
DPRINT ("FileName %S\n", FileName);
DPRINT ("Attaching FCB to fileObject\n");
Status = vfatAttachFCBToFileObject (DeviceExt, Fcb, FileObject);
string = FileName;
ParentFcb = NULL;
Fcb = vfatNewFCB (L"\\");
next = &string[0];
CHECKPOINT;
if (*next == 0 || *(next+1) == 0) // root
{
memset (Fcb->entry.Filename, ' ', 11);
Fcb->entry.FileSize = DeviceExt->rootDirectorySectors * BLOCKSIZE;
Fcb->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY;
if (DeviceExt->FatType == FAT32)
Fcb->entry.FirstCluster = 2;
else
Fcb->entry.FirstCluster = 1;
/* FIXME : is 1 the good value for mark root? */
ParentFcb = Fcb;
DPRINT("%S filename, PathName: %S\n",FileName, ParentFcb->PathName);
Fcb = NULL;
}
else
{
while (TRUE)
{
CHECKPOINT;
*next = '\\';
current = next + 1;
next = wcschr (next + 1, '\\');
if (next != NULL)
{
*next = 0;
}
else
{
/* reached the last path component */
DPRINT ("exiting: current '%S'\n", current);
break;
}
DPRINT ("search for (%S) in (%S)\n", current, ParentFcb ? ParentFcb->PathName : L"");
Status = FindFile (DeviceExt, Fcb, ParentFcb, current, NULL, NULL);
if (Status != STATUS_SUCCESS)
{
CHECKPOINT;
if (Fcb != NULL)
ExFreePool (Fcb);
if (ParentFcb != NULL)
ExFreePool (ParentFcb);
if (AbsFileName)
ExFreePool (AbsFileName);
DPRINT ("error STATUS_OBJECT_PATH_NOT_FOUND\n");
return STATUS_OBJECT_PATH_NOT_FOUND;
}
Temp = Fcb;
CHECKPOINT;
if (ParentFcb == NULL)
{
CHECKPOINT;
Fcb = vfatNewFCB (L"\\");
}
else
Fcb = ParentFcb;
if (*(Temp->ObjectName))
{
vfat_wcsncpy(Fcb->PathName+(Fcb->ObjectName-Fcb->PathName),Temp->PathName+(Fcb->ObjectName-Fcb->PathName), MAX_PATH);
Fcb->ObjectName = &Fcb->PathName[wcslen(Fcb->PathName)];
Fcb->ObjectName[0]='\\';
Fcb->ObjectName=&Fcb->ObjectName[1];
Fcb->ObjectName[0]=0;
}
CHECKPOINT;
ParentFcb = Temp;
}
if( *current != L'\0' ){ //the file name is directory. there will be no last part.
/* searching for last path component */
DPRINT ("search for (%S) in (%S)\n", current, Fcb ? Fcb->PathName : L"");
Status = FindFile (DeviceExt, Fcb, ParentFcb, current, NULL, NULL);
if (Status != STATUS_SUCCESS)
{
/* file does not exist */
CHECKPOINT;
if (Fcb != NULL)
ExFreePool (Fcb);
if (ParentFcb != NULL)
ExFreePool (ParentFcb);
if (AbsFileName)
ExFreePool (AbsFileName);
return STATUS_OBJECT_NAME_NOT_FOUND;
}
Temp = Fcb;
Fcb = ParentFcb;
ParentFcb = Temp;
ParentFcb->ObjectName = &(wcschr (ParentFcb->ObjectName, '\\'))[1];
}
}
FileObject->Flags = FileObject->Flags |
FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ;
FileObject->SectionObjectPointers = &ParentFcb->SectionObjectPointers;
memset(FileObject->SectionObjectPointers, 0,
sizeof(SECTION_OBJECT_POINTERS));
FileObject->FsContext = (PVOID)&ParentFcb->RFCB;
newCCB = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB);
memset (newCCB, 0, sizeof (VFATCCB));
FileObject->FsContext2 = newCCB;
newCCB->pFcb = ParentFcb;
newCCB->PtrFileObject = FileObject;
ParentFcb->RefCount++;
ParentFcb->pDevExt = DeviceExt;
/* FIXME : initialize all fields in FCB and CCB */
BytesPerCluster = DeviceExt->Boot->SectorsPerCluster * BLOCKSIZE;
FileCacheQuantum = (BytesPerCluster >= PAGESIZE) ? BytesPerCluster : PAGESIZE;
Status = CcRosInitializeFileCache(FileObject,
&ParentFcb->RFCB.Bcb,
FileCacheQuantum);
if (!NT_SUCCESS(Status))
{
DbgPrint("CcRosInitializeFileCache failed\n");
KeBugCheck(0);
}
DPRINT ("file open, fcb=%x\n", ParentFcb);
DPRINT ("FileSize %d\n", ParentFcb->entry.FileSize);
vfatAddFCBToTable (DeviceExt, ParentFcb);
if (Fcb)
ExFreePool (Fcb);
if (AbsFileName)
ExFreePool (AbsFileName);
CHECKPOINT;
return (STATUS_SUCCESS);
return Status;
}
NTSTATUS
VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
/*

View file

@ -375,3 +375,5 @@ VfatDirectoryControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return RC;
}

View file

@ -0,0 +1,227 @@
/* $Id: direntry.c,v 1.1 2001/07/05 01:51:52 rex Exp $
*
*
* FILE: DirEntry.c
* PURPOSE: Routines to manipulate directory entries.
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Rex Jolliff (rex@lvcablemodem.com)
*/
/* ------------------------------------------------------- INCLUDES */
#include <ddk/ntddk.h>
#include <wchar.h>
#include <limits.h>
#define NDEBUG
#include <debug.h>
#include "vfat.h"
#define ENTRIES_PER_PAGE(pDeviceExt) (ENTRIES_PER_SECTOR * \
(PAGESIZE / ((pDeviceExt)->BytesPerSector)))
ULONG
vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
PFAT_DIR_ENTRY pFatDirEntry)
{
ULONG cluster;
if (pDeviceExt->FatType == FAT32)
{
cluster = pFatDirEntry->FirstCluster +
pFatDirEntry->FirstClusterHigh * 65536;
}
else
{
cluster = pFatDirEntry->FirstCluster;
}
return cluster;
}
BOOL
vfatIsDirEntryDeleted (FATDirEntry * pFatDirEntry)
{
return pFatDirEntry->Filename [0] == 0xe5;
}
BOOL
vfatIsDirEntryEndMarker (FATDirEntry * pFatDirEntry)
{
return pFatDirEntry->Filename [0] == 0;
}
BOOL
vfatIsDirEntryLongName (FATDirEntry * pFatDirEntry)
{
return pFatDirEntry->Attrib == 0x0f;
}
void
vfatGetDirEntryName (PFAT_DIR_ENTRY dirEntry, PWSTR entryName)
{
vfat8Dot3ToString (dirEntry->Filename, dirEntry->Ext, entryName);
}
NTSTATUS
vfatGetNextDirEntry (PDEVICE_EXTENSION pDeviceExt,
PVFATFCB pDirectoryFCB,
ULONG * pDirectoryIndex,
PWSTR pLongFileName,
PFAT_DIR_ENTRY pDirEntry)
{
NTSTATUS status;
ULONG indexInPage = *pDirectoryIndex % ENTRIES_PER_PAGE(pDeviceExt);
ULONG pageNumber = *pDirectoryIndex / ENTRIES_PER_PAGE(pDeviceExt);
PVOID currentPage = NULL;
PCACHE_SEGMENT cacheSegment = NULL;
FATDirEntry * fatDirEntry;
slot * longNameEntry;
ULONG cpos;
DPRINT ("vfatGetNextDirEntry (%x,%x,%d,%x,%x)\n",
pDeviceExt,
pDirectoryFCB,
*pDirectoryIndex,
pLongFileName,
pDirEntry);
*pLongFileName = 0;
DPRINT ("Validating current directory page\n");
status = vfatRequestAndValidateRegion (pDeviceExt,
pDirectoryFCB,
pageNumber * PAGESIZE,
(PVOID *) &currentPage,
&cacheSegment,
FALSE);
if (!NT_SUCCESS (status))
{
return status;
}
while (TRUE)
{
fatDirEntry = (FATDirEntry *) currentPage;
if (vfatIsDirEntryEndMarker (&fatDirEntry [indexInPage]))
{
DPRINT ("end of directory, returning no more entries\n");
status = vfatReleaseRegion (pDeviceExt,
pDirectoryFCB,
cacheSegment);
return STATUS_NO_MORE_ENTRIES;
}
else if (vfatIsDirEntryLongName (&fatDirEntry [indexInPage]))
{
DPRINT (" long name entry found at %d\n", *pDirectoryIndex);
longNameEntry = (slot *) currentPage;
DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
5, longNameEntry [indexInPage].name0_4,
6, longNameEntry [indexInPage].name5_10,
2, longNameEntry [indexInPage].name11_12);
vfat_initstr (pLongFileName, 256);
vfat_wcsncpy (pLongFileName, longNameEntry [indexInPage].name0_4, 5);
vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name5_10, 5, 6);
vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name11_12, 11, 2);
DPRINT (" longName: [%S]\n", pLongFileName);
cpos = 0;
while ((longNameEntry [indexInPage].id != 0x41) &&
(longNameEntry [indexInPage].id != 0x01) &&
(longNameEntry [indexInPage].attr > 0))
{
(*pDirectoryIndex)++;
indexInPage++;
if (indexInPage == ENTRIES_PER_PAGE(pDeviceExt))
{
indexInPage = 0;
pageNumber++;
status = vfatReleaseRegion (pDeviceExt,
pDirectoryFCB,
cacheSegment);
if (!NT_SUCCESS (status))
{
return status;
}
status = vfatRequestAndValidateRegion (pDeviceExt,
pDirectoryFCB,
pageNumber * PAGESIZE,
(PVOID *) &currentPage,
&cacheSegment,
FALSE);
if (!NT_SUCCESS (status))
{
return status;
}
longNameEntry = (slot *) currentPage;
}
DPRINT (" index %d\n", *pDirectoryIndex);
DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
5, longNameEntry [indexInPage].name0_4,
6, longNameEntry [indexInPage].name5_10,
2, longNameEntry [indexInPage].name11_12);
cpos++;
vfat_movstr (pLongFileName, 13, 0, cpos * 13);
vfat_wcsncpy (pLongFileName, longNameEntry [indexInPage].name0_4, 5);
vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name5_10, 5, 6);
vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name11_12, 11, 2);
DPRINT (" longName: [%S]\n", pLongFileName);
}
(*pDirectoryIndex)++;
indexInPage++;
if (indexInPage == ENTRIES_PER_PAGE(pDeviceExt))
{
indexInPage = 0;
pageNumber++;
status = vfatReleaseRegion (pDeviceExt,
pDirectoryFCB,
cacheSegment);
if (!NT_SUCCESS (status))
{
return status;
}
status = vfatRequestAndValidateRegion (pDeviceExt,
pDirectoryFCB,
pageNumber * PAGESIZE,
(PVOID *) &currentPage,
&cacheSegment,
FALSE);
if (!NT_SUCCESS (status))
{
return status;
}
}
}
else
{
memcpy (pDirEntry, &fatDirEntry [indexInPage], sizeof (FAT_DIR_ENTRY));
(*pDirectoryIndex)++;
break;
}
}
DPRINT ("Releasing current directory page\n");
status = vfatReleaseRegion (pDeviceExt,
pDirectoryFCB,
cacheSegment);
return status;
}

View file

@ -1,4 +1,4 @@
/* $Id: fcb.c,v 1.3 2001/05/10 06:30:23 rex Exp $
/* $Id: fcb.c,v 1.4 2001/07/05 01:51:52 rex Exp $
*
*
* FILE: fcb.c
@ -54,10 +54,27 @@ void vfatDestroyFCB (PVFATFCB pFCB)
ExFreePool (pFCB);
}
BOOL
vfatFCBIsDirectory (PDEVICE_EXTENSION pVCB, PVFATFCB FCB)
{
return FCB->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY;
}
BOOL
vfatFCBIsRoot (PVFATFCB FCB)
{
return wcscmp (FCB->PathName, L"\\") == 0;
}
void vfatGrabFCB (PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
{
KIRQL oldIrql;
DPRINT ("grabbing FCB at %x: %S, refCount:%d\n",
pFCB,
pFCB->PathName,
pFCB->RefCount);
KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql);
pFCB->RefCount++;
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
@ -67,6 +84,11 @@ void vfatReleaseFCB (PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
{
KIRQL oldIrql;
DPRINT ("releasing FCB at %x: %S, refCount:%d\n",
pFCB,
pFCB->PathName,
pFCB->RefCount);
KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql);
pFCB->RefCount--;
if (pFCB->RefCount <= 0 && !vfatFCBIsDirectory (pVCB, pFCB))
@ -95,39 +117,168 @@ vfatGrabFCBFromTable (PDEVICE_EXTENSION pVCB, PWSTR pFileName)
PVFATFCB rcFCB;
PLIST_ENTRY current_entry;
CHECKPOINT;
KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql);
CHECKPOINT;
current_entry = pVCB->FcbListHead.Flink;
while (current_entry != &pVCB->FcbListHead)
{
rcFCB = CONTAINING_RECORD (current_entry, VFATFCB, FcbListEntry);
DPRINT ("Next FCB in list at %x\n", rcFCB);
DPRINT (" PathName:%S\n", rcFCB->PathName);
if (wstrcmpi (pFileName, rcFCB->PathName))
{
rcFCB->RefCount++;
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
return rcFCB;
}
//FIXME: need to compare against short name in FCB here
current_entry = current_entry->Flink;
}
CHECKPOINT;
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
return NULL;
}
PVFATFCB
vfatMakeRootFCB (PDEVICE_EXTENSION pVCB)
NTSTATUS
vfatFCBInitializeCache (PVCB vcb, PVFATFCB fcb)
{
NTSTATUS status;
PVFATFCB FCB;
PFILE_OBJECT fileObject;
ULONG bytesPerCluster;
ULONG fileCacheQuantum;
PVFATCCB newCCB;
fileObject = IoCreateStreamFileObject (NULL, vcb->StorageDevice);
newCCB = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB);
if (newCCB == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
memset (newCCB, 0, sizeof (VFATCCB));
fileObject->Flags = fileObject->Flags | FO_FCB_IS_VALID |
FO_DIRECT_CACHE_PAGING_READ;
fileObject->SectionObjectPointers = &fcb->SectionObjectPointers;
fileObject->FsContext = (PVOID) &fcb->RFCB;
fileObject->FsContext2 = newCCB;
newCCB->pFcb = fcb;
newCCB->PtrFileObject = fileObject;
fcb->pDevExt = vcb;
bytesPerCluster = vcb->Boot->SectorsPerCluster * BLOCKSIZE;
fileCacheQuantum = (bytesPerCluster >= PAGESIZE) ?
bytesPerCluster : PAGESIZE;
status = CcRosInitializeFileCache (fileObject,
&fcb->RFCB.Bcb,
fileCacheQuantum);
if (!NT_SUCCESS (status))
{
DbgPrint ("CcRosInitializeFileCache failed\n");
KeBugCheck (0);
}
ObDereferenceObject (fileObject);
fcb->isCacheInitialized = TRUE;
return status;
}
NTSTATUS
vfatRequestAndValidateRegion (PDEVICE_EXTENSION pDeviceExt,
PVFATFCB pFCB,
ULONG pOffset,
PVOID * pBuffer,
PCACHE_SEGMENT * pCacheSegment,
BOOL pExtend)
{
NTSTATUS status;
BOOLEAN valid;
BOOLEAN isRoot;
ULONG currentCluster;
ULONG i;
status = CcRosRequestCacheSegment(pFCB->RFCB.Bcb,
pOffset,
pBuffer,
&valid,
pCacheSegment);
if (!NT_SUCCESS (status))
{
return status;
}
isRoot = vfatFCBIsRoot (pFCB);
if (!valid)
{
currentCluster = vfatDirEntryGetFirstCluster (pDeviceExt, &pFCB->entry);
status = OffsetToCluster (pDeviceExt,
vfatDirEntryGetFirstCluster (pDeviceExt, &pFCB->entry),
pOffset,
&currentCluster,
pExtend);
if (!NT_SUCCESS (status))
{
return status;
}
if (PAGESIZE > pDeviceExt->BytesPerCluster)
{
for (i = 0; i < (PAGESIZE / pDeviceExt->BytesPerCluster); i++)
{
status = VfatRawReadCluster (pDeviceExt,
vfatDirEntryGetFirstCluster (pDeviceExt, &pFCB->entry),
((PCHAR)*pBuffer) +
(i * pDeviceExt->BytesPerCluster),
currentCluster);
if (!NT_SUCCESS (status))
{
CcRosReleaseCacheSegment(pFCB->RFCB.Bcb, *pCacheSegment, FALSE);
return status;
}
status = NextCluster (pDeviceExt,
vfatDirEntryGetFirstCluster (pDeviceExt, &pFCB->entry),
&currentCluster,
pExtend);
if (!NT_SUCCESS (status))
{
CcRosReleaseCacheSegment(pFCB->RFCB.Bcb, *pCacheSegment, FALSE);
return status;
}
if ((currentCluster) == 0xFFFFFFFF)
{
break;
}
}
}
else
{
status = VfatRawReadCluster (pDeviceExt,
vfatDirEntryGetFirstCluster (pDeviceExt, &pFCB->entry),
*pBuffer,
currentCluster);
if (!NT_SUCCESS (status))
{
CcRosReleaseCacheSegment(pFCB->RFCB.Bcb, *pCacheSegment, FALSE);
return status;
}
}
}
return STATUS_SUCCESS;
}
NTSTATUS
vfatReleaseRegion (PDEVICE_EXTENSION pDeviceExt,
PVFATFCB pFCB,
PCACHE_SEGMENT pCacheSegment)
{
return CcRosReleaseCacheSegment (pFCB->RFCB.Bcb, pCacheSegment, TRUE);
}
PVFATFCB
vfatMakeRootFCB (PDEVICE_EXTENSION pVCB)
{
PVFATFCB FCB;
FCB = vfatNewFCB (L"\\");
memset (FCB->entry.Filename, ' ', 11);
@ -142,21 +293,10 @@ vfatMakeRootFCB (PDEVICE_EXTENSION pVCB)
FCB->entry.FirstCluster = 1;
}
FCB->RefCount = 1;
fileObject = IoCreateStreamFileObject (NULL, pVCB->StorageDevice);
bytesPerCluster = pVCB->Boot->SectorsPerCluster * BLOCKSIZE;
fileCacheQuantum = (bytesPerCluster >= PAGESIZE) ?
bytesPerCluster : PAGESIZE;
status = CcRosInitializeFileCache (fileObject,
&FCB->RFCB.Bcb,
fileCacheQuantum);
if (!NT_SUCCESS (status))
{
DbgPrint ("CcRosInitializeFileCache failed\n");
KeBugCheck (0);
}
ObDereferenceObject (fileObject);
vfatFCBInitializeCache (pVCB, FCB);
vfatAddFCBToTable (pVCB, FCB);
vfatGrabFCB(pVCB, FCB);
return FCB;
}
@ -167,27 +307,191 @@ vfatOpenRootFCB (PDEVICE_EXTENSION pVCB)
PVFATFCB FCB;
FCB = vfatGrabFCBFromTable (pVCB, L"\\");
if (FCB != NULL)
if (FCB == NULL)
{
return FCB;
FCB = vfatMakeRootFCB (pVCB);
}
FCB = vfatMakeRootFCB (pVCB);
return FCB;
}
BOOL
vfatFCBIsDirectory (PDEVICE_EXTENSION pVCB, PVFATFCB FCB)
NTSTATUS
vfatMakeFCBFromDirEntry (PVCB vcb,
PVFATFCB directoryFCB,
PWSTR longName,
PFAT_DIR_ENTRY dirEntry,
PVFATFCB * fileFCB)
{
return FCB->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY;
PVFATFCB rcFCB;
WCHAR pathName [MAX_PATH];
if (longName [0] != 0 && wcslen (directoryFCB->PathName) +
sizeof(WCHAR) + wcslen (longName) > MAX_PATH)
{
return STATUS_OBJECT_NAME_INVALID;
}
wcscpy (pathName, directoryFCB->PathName);
if (!vfatFCBIsRoot (directoryFCB))
{
wcscat (pathName, L"\\");
}
if (longName [0] != 0)
{
wcscat (pathName, longName);
}
else
{
WCHAR entryName [MAX_PATH];
vfatGetDirEntryName (dirEntry, entryName);
wcscat (pathName, entryName);
}
rcFCB = vfatNewFCB (pathName);
memcpy (&rcFCB->entry, dirEntry, sizeof (FAT_DIR_ENTRY));
vfatFCBInitializeCache (vcb, rcFCB);
vfatAddFCBToTable (vcb, rcFCB);
vfatGrabFCB (vcb, rcFCB);
*fileFCB = rcFCB;
return STATUS_SUCCESS;
}
PVFATFCB
vfatDirFindFile (PDEVICE_EXTENSION pVCB,
PVFATFCB parentFCB,
const PWSTR elementName)
NTSTATUS
vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
PVFATFCB fcb,
PFILE_OBJECT fileObject)
{
UNIMPLEMENTED;
NTSTATUS status;
PVFATCCB newCCB;
newCCB = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB);
if (newCCB == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
memset (newCCB, 0, sizeof (VFATCCB));
fileObject->Flags = fileObject->Flags | FO_FCB_IS_VALID |
FO_DIRECT_CACHE_PAGING_READ;
fileObject->SectionObjectPointers = &fcb->SectionObjectPointers;
fileObject->FsContext = (PVOID) &fcb->RFCB;
fileObject->FsContext2 = newCCB;
newCCB->pFcb = fcb;
newCCB->PtrFileObject = fileObject;
fcb->pDevExt = vcb;
if (!fcb->isCacheInitialized)
{
ULONG bytesPerCluster;
ULONG fileCacheQuantum;
bytesPerCluster = vcb->Boot->SectorsPerCluster * BLOCKSIZE;
fileCacheQuantum = (bytesPerCluster >= PAGESIZE) ? bytesPerCluster :
PAGESIZE;
status = CcRosInitializeFileCache (fileObject,
&fcb->RFCB.Bcb,
fileCacheQuantum);
if (!NT_SUCCESS (status))
{
DbgPrint ("CcRosInitializeFileCache failed\n");
KeBugCheck (0);
}
fcb->isCacheInitialized = TRUE;
}
DPRINT ("file open: fcb:%x file size: %d\n", fcb, fcb->entry.FileSize);
return STATUS_SUCCESS;
}
NTSTATUS
vfatDirFindFile (PDEVICE_EXTENSION pDeviceExt,
PVFATFCB pDirectoryFCB,
PWSTR pFileToFind,
PVFATFCB * pFoundFCB)
{
BOOL finishedScanningDirectory;
ULONG directoryIndex;
NTSTATUS status;
WCHAR defaultFileName [2];
WCHAR currentLongName [256];
FAT_DIR_ENTRY currentDirEntry;
WCHAR currentEntryName [256];
assert (pDeviceExt);
assert (pDirectoryFCB);
assert (pFileToFind);
DPRINT ("vfatDirFindFile(VCB:%08x, dirFCB:%08x, File:%S)\n",
pDeviceExt,
pDirectoryFCB,
pFileToFind);
DPRINT ("Dir Path:%S\n", pDirectoryFCB->PathName);
// default to '.' if no filename specified
if (wcslen (pFileToFind) == 0)
{
defaultFileName [0] = L'.';
defaultFileName [1] = 0;
pFileToFind = defaultFileName;
}
directoryIndex = 0;
finishedScanningDirectory = FALSE;
while (!finishedScanningDirectory)
{
status = vfatGetNextDirEntry (pDeviceExt,
pDirectoryFCB,
&directoryIndex,
currentLongName,
&currentDirEntry);
if (status == STATUS_NO_MORE_ENTRIES)
{
finishedScanningDirectory = TRUE;
continue;
}
else if (!NT_SUCCESS(status))
{
return status;
}
DPRINT (" Index:%d longName:%S\n",
directoryIndex,
currentLongName);
if (!vfatIsDirEntryDeleted (&currentDirEntry))
{
if (currentLongName [0] != L'\0' && wstrcmpjoki (currentLongName, pFileToFind))
{
DPRINT ("Match found, %S\n", currentLongName);
status = vfatMakeFCBFromDirEntry (pDeviceExt,
pDirectoryFCB,
currentLongName,
&currentDirEntry,
pFoundFCB);
return status;
}
else
{
vfatGetDirEntryName (&currentDirEntry, currentEntryName);
DPRINT (" entryName:%S\n", currentEntryName);
if (wstrcmpjoki (currentEntryName, pFileToFind))
{
DPRINT ("Match found, %S\n", currentEntryName);
status = vfatMakeFCBFromDirEntry (pDeviceExt,
pDirectoryFCB,
currentLongName,
&currentDirEntry,
pFoundFCB);
return status;
}
}
}
}
return STATUS_OBJECT_NAME_NOT_FOUND;
}
NTSTATUS
@ -196,26 +500,29 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
PVFATFCB *pFCB,
const PWSTR pFileName)
{
NTSTATUS status;
WCHAR pathName [MAX_PATH];
WCHAR elementName [MAX_PATH];
PWCHAR currentElement;
PVFATFCB FCB;
PVFATFCB parentFCB;
DPRINT ("vfatGetFCBForFile (%x,%x,%x,%S)\n",
pVCB,
pParentFCB,
pFCB,
pFileName);
// Trivial case, open of the root directory on volume
if (pFileName [0] == L'\0' || wcscmp (pFileName, L"\\") == 0)
{
currentElement = pFileName;
//FIXME: grab/create root RCB and return it
FCB = vfatGrabFCBFromTable (pVCB, L"\\");
if (FCB == NULL)
{
FCB = vfatMakeRootFCB (pVCB);
*pFCB = FCB;
*pParentFCB = NULL;
DPRINT ("returning root FCB\n");
return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND;
}
FCB = vfatOpenRootFCB (pVCB);
*pFCB = FCB;
*pParentFCB = NULL;
return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND;
}
else
{
@ -235,7 +542,8 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
continue;
}
currentElement = vfatGetNextPathElement (currentElement);
DPRINT ("Parsing, currentElement:%S\n", currentElement);
DPRINT (" parentFCB:%x FCB:%x\n", parentFCB, FCB);
// descend to next directory level
if (parentFCB)
@ -246,8 +554,13 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
// fail if element in FCB is not a directory
if (!vfatFCBIsDirectory (pVCB, FCB))
{
DPRINT ("Element in requested path is not a directory\n");
vfatReleaseFCB (pVCB, FCB);
FCB = 0;
*pParentFCB = NULL;
*pFCB = NULL;
return STATUS_OBJECT_PATH_NOT_FOUND;
}
parentFCB = FCB;
@ -256,6 +569,7 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
vfatWSubString (pathName,
pFileName,
vfatGetNextPathElement (currentElement) - pFileName);
DPRINT (" pathName:%S\n", pathName);
FCB = vfatGrabFCBFromTable (pVCB, pathName);
if (FCB == NULL)
@ -263,12 +577,14 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
vfatWSubString (elementName,
currentElement,
vfatGetNextPathElement (currentElement) - currentElement);
FCB = vfatDirFindFile (pVCB, parentFCB, elementName);
if (FCB == NULL)
DPRINT (" elementName:%S\n", elementName);
status = vfatDirFindFile (pVCB, parentFCB, elementName, &FCB);
if (status == STATUS_OBJECT_NAME_NOT_FOUND)
{
*pParentFCB = parentFCB;
*pFCB = NULL;
if (vfatGetNextPathElement (currentElement) == 0)
if (vfatGetNextPathElement (vfatGetNextPathElement (currentElement) + 1) == 0)
{
return STATUS_OBJECT_NAME_NOT_FOUND;
}
@ -277,9 +593,16 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
return STATUS_OBJECT_PATH_NOT_FOUND;
}
}
else if (!NT_SUCCESS (status))
{
vfatReleaseFCB (pVCB, parentFCB);
*pParentFCB = NULL;
*pFCB = NULL;
// FIXME: check security on directory element and fail if access denied
return status;
}
}
currentElement = vfatGetNextPathElement (currentElement);
}
*pParentFCB = parentFCB;

View file

@ -1,4 +1,4 @@
/* $Id: iface.c,v 1.53 2001/06/11 19:52:22 ekohl Exp $
/* $Id: iface.c,v 1.54 2001/07/05 01:51:52 rex Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -103,6 +103,7 @@ VfatMountDevice (PDEVICE_EXTENSION DeviceExt, PDEVICE_OBJECT DeviceToMount)
DeviceExt->Boot->FATCount * DeviceExt->Boot->FATSectors;
DeviceExt->dataStart =
DeviceExt->rootStart + DeviceExt->rootDirectorySectors;
DeviceExt->BytesPerSector = DeviceExt->Boot->BytesPerSector;
DeviceExt->FATEntriesPerSector = DeviceExt->Boot->BytesPerSector / 32;
DeviceExt->BytesPerCluster = DeviceExt->Boot->SectorsPerCluster *
DeviceExt->Boot->BytesPerSector;

View file

@ -1,12 +1,13 @@
# $Id: makefile,v 1.31 2001/06/22 12:27:48 ekohl Exp $
# $Id: makefile,v 1.32 2001/07/05 01:51:52 rex Exp $
#
#
PATH_TO_TOP = ../../..
TARGET=vfatfs
OBJECTS = blockdev.o close.o create.o dir.o dirwr.o iface.o string.o fat.o \
rw.o finfo.o volume.o shutdown.o cleanup.o fcb.o $(TARGET).coff
OBJECTS = blockdev.o cleanup.o close.o create.o dir.o direntry.o dirwr.o \
fat.o fcb.o finfo.o iface.o rw.o shutdown.o string.o volume.o \
$(TARGET).coff
LIBS = $(PATH_TO_TOP)/ntoskrnl/ntoskrnl.a

View file

@ -1,4 +1,4 @@
/* $Id: string.c,v 1.7 2001/05/10 04:02:21 rex Exp $
/* $Id: string.c,v 1.8 2001/07/05 01:51:53 rex Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -151,7 +151,7 @@ BOOLEAN wstrcmpjoki(PWSTR s1, PWSTR s2)
PWCHAR
vfatGetNextPathElement (PWCHAR pFileName)
{
if (*pFileName != L'\0')
if (*pFileName == L'\0')
{
return 0;
}

View file

@ -1,4 +1,4 @@
/* $Id: vfat.h,v 1.31 2001/06/14 10:02:59 ekohl Exp $ */
/* $Id: vfat.h,v 1.32 2001/07/05 01:51:53 rex Exp $ */
#include <ddk/ntifs.h>
@ -49,7 +49,7 @@ struct _FATDirEntry {
unsigned long FileSize;
} __attribute__((packed));
typedef struct _FATDirEntry FATDirEntry;
typedef struct _FATDirEntry FATDirEntry, FAT_DIR_ENTRY, *PFAT_DIR_ENTRY;
struct _slot
{
@ -87,10 +87,11 @@ typedef struct
PBCB Fat12StorageBcb;
BootSector *Boot;
int rootDirectorySectors, FATStart, rootStart, dataStart;
int BytesPerSector;
int FATEntriesPerSector, FATUnit;
ULONG BytesPerCluster;
ULONG FatType;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB;
typedef struct _VFATFCB
{
@ -105,6 +106,7 @@ typedef struct _VFATFCB
PDEVICE_EXTENSION pDevExt;
LIST_ENTRY FcbListEntry;
struct _VFATFCB* parentFcb;
BOOL isCacheInitialized;
} VFATFCB, *PVFATFCB;
typedef struct _VFATCCB
@ -120,6 +122,9 @@ typedef struct _VFATCCB
// PSTRING DirectorySearchPattern;// for DirectoryControl ?
} VFATCCB, *PVFATCCB;
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
#define TAG_CCB TAG('V', 'C', 'C', 'B')
#define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry))
@ -249,6 +254,12 @@ BOOL vfatIsFileNameValid (PWCHAR pFileName);
/*
* functions from fat.c
*/
NTSTATUS
OffsetToCluster(PDEVICE_EXTENSION DeviceExt,
ULONG FirstCluster,
ULONG FileOffset,
PULONG Cluster,
BOOLEAN Extend);
ULONG
ClusterToSector(PDEVICE_EXTENSION DeviceExt,
ULONG Cluster);
@ -286,9 +297,9 @@ WriteCluster(PDEVICE_EXTENSION DeviceExt,
ULONG ClusterToWrite,
ULONG NewValue);
/*
* From create.c
*/
/* --------------------------------------------------------- create.c */
void vfat8Dot3ToString (PCHAR pBasename, PCHAR pExtension, PWSTR pName);
NTSTATUS
ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt, PVPB Vpb);
NTSTATUS
@ -296,6 +307,18 @@ VfatOpenFile(PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject,
PWSTR FileName);
/* ----------------------------------------------- DirEntry Functions */
ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
PFAT_DIR_ENTRY pDirEntry);
BOOL vfatIsDirEntryDeleted (FATDirEntry * pFatDirEntry);
void vfatGetDirEntryName (PFAT_DIR_ENTRY pDirEntry, PWSTR pEntryName);
NTSTATUS vfatGetNextDirEntry (PDEVICE_EXTENSION pDeviceExt,
PVFATFCB pDirectoryFCB,
ULONG * pDirectoryIndex,
PWSTR pLongFileName,
PFAT_DIR_ENTRY pDirEntry);
/* ----------------------------------------------------- FCB Functions */
PVFATFCB vfatNewFCB (PWCHAR pFileName);
@ -306,12 +329,25 @@ void vfatAddFCBToTable (PDEVICE_EXTENSION pVCB,
PVFATFCB pFCB);
PVFATFCB vfatGrabFCBFromTable (PDEVICE_EXTENSION pDeviceExt,
PWSTR pFileName);
NTSTATUS vfatRequestAndValidateRegion (PDEVICE_EXTENSION pDeviceExt,
PVFATFCB pFCB,
ULONG pOffset,
PVOID * pBuffer,
PCACHE_SEGMENT * pCacheSegment,
BOOL pExtend);
NTSTATUS vfatReleaseRegion (PDEVICE_EXTENSION pDeviceExt,
PVFATFCB pFCB,
PCACHE_SEGMENT pCacheSegment);
PVFATFCB vfatMakeRootFCB (PDEVICE_EXTENSION pVCB);
PVFATFCB vfatOpenRootFCB (PDEVICE_EXTENSION pVCB);
BOOL vfatFCBIsDirectory (PDEVICE_EXTENSION pVCB, PVFATFCB FCB);
PVFATFCB vfatDirFindFile (PDEVICE_EXTENSION pVCB,
PVFATFCB parentFCB,
const PWSTR elementName);
NTSTATUS vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
PVFATFCB fcb,
PFILE_OBJECT fileObject);
NTSTATUS vfatDirFindFile (PDEVICE_EXTENSION pVCB,
PVFATFCB parentFCB,
PWSTR elementName,
PVFATFCB * fileFCB);
NTSTATUS vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
PVFATFCB *pParentFCB,
PVFATFCB *pFCB,