still use non cached routines).
svn path=/trunk/; revision=2038
-/* $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
/* 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
(((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;
* 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 ("FileName %S\n", FileName);
-
- string = FileName;
- ParentFcb = NULL;
- Fcb = vfatNewFCB (L"\\");
- next = &string[0];
-
- CHECKPOINT;
- if (*next == 0 || *(next+1) == 0) // root
+ DPRINT ("No existing FCB found, making a new one if file exists.\n");
+ Status = vfatGetFCBForFile (DeviceExt, &ParentFcb, &Fcb, FileName);
+ if (ParentFcb != NULL)
{
- 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;
+ vfatReleaseFCB (DeviceExt, ParentFcb);
}
- else
+ if (!NT_SUCCESS (Status))
{
- 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 ("Could not make a new FCB, status: %x\n", Status);
- 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;
- }
+ if (AbsFileName)
+ ExFreePool (AbsFileName);
- Temp = Fcb;
-
- Fcb = ParentFcb;
- ParentFcb = Temp;
- ParentFcb->ObjectName = &(wcschr (ParentFcb->ObjectName, '\\'))[1];
- }
+ return Status;
}
+ }
- 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);
+ DPRINT ("Attaching FCB to fileObject\n");
+ Status = vfatAttachFCBToFileObject (DeviceExt, Fcb, FileObject);
- if (Fcb)
- ExFreePool (Fcb);
if (AbsFileName)
ExFreePool (AbsFileName);
- CHECKPOINT;
- return (STATUS_SUCCESS);
+ return Status;
}
-
NTSTATUS
VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
/*
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return RC;
}
+
+
--- /dev/null
+/* $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 *) ¤tPage,
+ &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 *) ¤tPage,
+ &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 *) ¤tPage,
+ &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;
+}
+
+
+
+
+
-/* $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
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);
{
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))
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,
+ ¤tCluster,
+ 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),
+ ¤tCluster,
+ 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);
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;
}
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,
+ ¤tDirEntry);
+ 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 (¤tDirEntry))
+ {
+ if (currentLongName [0] != L'\0' && wstrcmpjoki (currentLongName, pFileToFind))
+ {
+ DPRINT ("Match found, %S\n", currentLongName);
+ status = vfatMakeFCBFromDirEntry (pDeviceExt,
+ pDirectoryFCB,
+ currentLongName,
+ ¤tDirEntry,
+ pFoundFCB);
+ return status;
+ }
+ else
+ {
+ vfatGetDirEntryName (¤tDirEntry, currentEntryName);
+ DPRINT (" entryName:%S\n", currentEntryName);
+
+ if (wstrcmpjoki (currentEntryName, pFileToFind))
+ {
+ DPRINT ("Match found, %S\n", currentEntryName);
+ status = vfatMakeFCBFromDirEntry (pDeviceExt,
+ pDirectoryFCB,
+ currentLongName,
+ ¤tDirEntry,
+ pFoundFCB);
+ return status;
+ }
+ }
+ }
+ }
+
+ return STATUS_OBJECT_NAME_NOT_FOUND;
}
NTSTATUS
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
{
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)
// 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;
vfatWSubString (pathName,
pFileName,
vfatGetNextPathElement (currentElement) - pFileName);
+ DPRINT (" pathName:%S\n", pathName);
FCB = vfatGrabFCBFromTable (pVCB, pathName);
if (FCB == NULL)
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;
}
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;
-/* $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
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;
-# $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
-/* $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
PWCHAR
vfatGetNextPathElement (PWCHAR pFileName)
{
- if (*pFileName != L'\0')
+ if (*pFileName == L'\0')
{
return 0;
}
-/* $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>
unsigned long FileSize;
} __attribute__((packed));
-typedef struct _FATDirEntry FATDirEntry;
+typedef struct _FATDirEntry FATDirEntry, FAT_DIR_ENTRY, *PFAT_DIR_ENTRY;
struct _slot
{
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
{
PDEVICE_EXTENSION pDevExt;
LIST_ENTRY FcbListEntry;
struct _VFATFCB* parentFcb;
+ BOOL isCacheInitialized;
} VFATFCB, *PVFATFCB;
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))
/*
* functions from fat.c
*/
+NTSTATUS
+OffsetToCluster(PDEVICE_EXTENSION DeviceExt,
+ ULONG FirstCluster,
+ ULONG FileOffset,
+ PULONG Cluster,
+ BOOLEAN Extend);
ULONG
ClusterToSector(PDEVICE_EXTENSION DeviceExt,
ULONG Cluster);
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
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);
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,