[fastfat_new]
[reactos.git] / reactos / drivers / filesystems / fastfat_new / fcb.c
index 3a44f59..eee2097 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * PROJECT:         ReactOS FAT file system driver
  * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            drivers/filesystems/fastfat/rw.c
- * PURPOSE:         Read/write support
- * PROGRAMMERS:     
+ * FILE:            drivers/filesystems/fastfat/fcb.c
+ * PURPOSE:         FCB manipulation routines.
+ * PROGRAMMERS:     Aleksey Bragin <aleksey@reactos.org>
  */
 
 /* INCLUDES *****************************************************************/
 #define NDEBUG
 #include "fastfat.h"
 
+#define TAG_FILENAME 'fBnF'
+
 /* FUNCTIONS ****************************************************************/
 
+FSRTL_COMPARISON_RESULT
+NTAPI
+FatiCompareNames(PSTRING NameA,
+                 PSTRING NameB)
+{
+    ULONG MinimumLen, i;
+
+    /* Calc the minimum length */
+    MinimumLen = NameA->Length < NameB->Length ? NameA->Length :
+                                                NameB->Length;
+
+    /* Actually compare them */
+    i = (ULONG)RtlCompareMemory( NameA->Buffer, NameB->Buffer, MinimumLen );
+
+    if (i < MinimumLen)
+    {
+        /* Compare prefixes */
+        if (NameA->Buffer[i] < NameB->Buffer[i])
+            return LessThan;
+        else
+            return GreaterThan;
+    }
+
+    /* Final comparison */
+    if (NameA->Length < NameB->Length)
+        return LessThan;
+    else if (NameA->Length > NameB->Length)
+        return GreaterThan;
+    else
+        return EqualTo;
+}
+
+PFCB
+NTAPI
+FatFindFcb(PFAT_IRP_CONTEXT IrpContext,
+           PRTL_SPLAY_LINKS *RootNode,
+           PSTRING AnsiName,
+           PBOOLEAN IsDosName)
+{
+    PFCB_NAME_LINK Node;
+    FSRTL_COMPARISON_RESULT Comparison;
+    PRTL_SPLAY_LINKS Links;
+
+    Links = *RootNode;
+
+    while (Links)
+    {
+        Node = CONTAINING_RECORD(Links, FCB_NAME_LINK, Links);
+
+        /* Compare the prefix */
+        if (*(PUCHAR)Node->Name.Ansi.Buffer != *(PUCHAR)AnsiName->Buffer)
+        {
+            if (*(PUCHAR)Node->Name.Ansi.Buffer < *(PUCHAR)AnsiName->Buffer)
+                Comparison = LessThan;
+            else
+                Comparison = GreaterThan;
+        }
+        else
+        {
+            /* Perform real comparison */
+            Comparison = FatiCompareNames(&Node->Name.Ansi, AnsiName);
+        }
+
+        /* Do they match? */
+        if (Comparison == GreaterThan)
+        {
+            /* No, it's greater, go to the left child */
+            Links = RtlLeftChild(Links);
+        }
+        else if (Comparison == LessThan)
+        {
+            /* No, it's lesser, go to the right child */
+            Links = RtlRightChild(Links);
+        }
+        else
+        {
+            /* Exact match, balance the tree */
+            *RootNode = RtlSplay(Links);
+
+            /* Save type of the name, if needed */
+            if (IsDosName)
+                *IsDosName = Node->IsDosName;
+
+            /* Return the found fcb */
+            return Node->Fcb;
+        }
+    }
+
+    /* Nothing found */
+    return NULL;
+}
+
+PFCB
+NTAPI
+FatCreateFcb(IN PFAT_IRP_CONTEXT IrpContext,
+             IN PVCB Vcb,
+             IN PFCB ParentDcb,
+             IN FF_FILE *FileHandle)
+{
+    PFCB Fcb;
+
+    /* Allocate it and zero it */
+    Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(FCB), TAG_FCB);
+    RtlZeroMemory(Fcb, sizeof(FCB));
+
+    /* Set node types */
+    Fcb->Header.NodeTypeCode = FAT_NTC_FCB;
+    Fcb->Header.NodeByteSize = sizeof(FCB);
+    Fcb->Condition = FcbGood;
+
+    /* Initialize resources */
+    Fcb->Header.Resource = &Fcb->Resource;
+    ExInitializeResourceLite(Fcb->Header.Resource);
+
+    Fcb->Header.PagingIoResource = &Fcb->PagingIoResource;
+    ExInitializeResourceLite(Fcb->Header.PagingIoResource);
+
+    /* Initialize mutexes */
+    Fcb->Header.FastMutex = &Fcb->HeaderMutex;
+    ExInitializeFastMutex(&Fcb->HeaderMutex);
+    FsRtlSetupAdvancedHeader(&Fcb->Header, &Fcb->HeaderMutex);
+
+    /* Insert into parent's DCB list */
+    InsertTailList(&ParentDcb->Dcb.ParentDcbList, &Fcb->ParentDcbLinks);
+
+    /* Set backlinks */
+    Fcb->ParentFcb = ParentDcb;
+    Fcb->Vcb = Vcb;
+
+    /* Set file handle and sizes */
+    Fcb->Header.FileSize.LowPart = FileHandle->Filesize;
+    Fcb->Header.ValidDataLength.LowPart = FileHandle->Filesize;
+    Fcb->FatHandle = FileHandle;
+
+    return Fcb;
+}
+
+PCCB
+NTAPI
+FatCreateCcb()
+{
+    PCCB Ccb;
+
+    /* Allocate the CCB and zero it */
+    Ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), TAG_CCB);
+    RtlZeroMemory(Ccb, sizeof(CCB));
+
+    /* Set mandatory header */
+    Ccb->NodeTypeCode = FAT_NTC_FCB;
+    Ccb->NodeByteSize = sizeof(CCB);
+
+    return Ccb;
+}
+
+VOID
+NTAPI
+FatSetFullNameInFcb(PFCB Fcb,
+                    PUNICODE_STRING Name)
+{
+    PUNICODE_STRING ParentName;
+
+    /* Make sure this FCB's name wasn't already set */
+    ASSERT(Fcb->FullFileName.Buffer == NULL);
+
+    /* First of all, check exact case name */
+    if (Fcb->ExactCaseLongName.Buffer)
+    {
+        ASSERT(Fcb->ExactCaseLongName.Length != 0);
+
+        /* Use exact case name */
+        Name = &Fcb->ExactCaseLongName;
+    }
+
+    /* Treat root dir different */
+    if (FatNodeType(Fcb->ParentFcb) == FAT_NTC_ROOT_DCB)
+    {
+        /* Set lengths */
+        Fcb->FullFileName.MaximumLength = sizeof(WCHAR) + Name->Length;
+        Fcb->FullFileName.Length = Fcb->FullFileName.MaximumLength;
+
+        /* Allocate a buffer */
+        Fcb->FullFileName.Buffer = FsRtlAllocatePoolWithTag(PagedPool,
+                                                            Fcb->FullFileName.Length,
+                                                            TAG_FILENAME);
+
+        /* Prefix with a backslash */
+        Fcb->FullFileName.Buffer[0] = L'\\';
+
+        /* Copy the name here */
+        RtlCopyMemory(&Fcb->FullFileName.Buffer[1],
+                      &Name->Buffer[0],
+                       Name->Length );
+    }
+    else
+    {
+        ParentName = &Fcb->ParentFcb->FullFileName;
+
+        /* Check if parent's name is set */
+        if (!ParentName->Buffer)
+            return;
+
+        /* Set lengths */
+        Fcb->FullFileName.MaximumLength =
+            ParentName->Length + sizeof(WCHAR) + Name->Length;
+        Fcb->FullFileName.Length = Fcb->FullFileName.MaximumLength;
+
+        /* Allocate a buffer */
+        Fcb->FullFileName.Buffer = FsRtlAllocatePoolWithTag(PagedPool,
+                                                            Fcb->FullFileName.Length,
+                                                            TAG_FILENAME );
+
+        /* Copy parent's name here */
+        RtlCopyMemory(&Fcb->FullFileName.Buffer[0],
+                      &ParentName->Buffer[0],
+                      ParentName->Length );
+
+        /* Add a backslash */
+        Fcb->FullFileName.Buffer[ParentName->Length / sizeof(WCHAR)] = L'\\';
+
+        /* Copy given name here */
+        RtlCopyMemory(&Fcb->FullFileName.Buffer[(ParentName->Length / sizeof(WCHAR)) + 1],
+                      &Name->Buffer[0],
+                      Name->Length );
+    }
+}
 
 /* EOF */