⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 create.c

📁 This is a ReiserFs file system driver for Windows NT/2000/XP/Vista.
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * COPYRIGHT:        GNU GENERAL PUBLIC LICENSE VERSION 2
 * PROJECT:          ReiserFs file system driver for Windows NT/2000/XP/Vista.
 * FILE:             create.c
 * PURPOSE:          
 * PROGRAMMER:       Mark Piper, Matt Wu, Bo Brant閚.
 * HOMEPAGE:         
 * UPDATE HISTORY: 
 */

/* INCLUDES *****************************************************************/

#include "ntifs.h"
#include "rfsd.h"

/* GLOBALS *****************************************************************/

extern PRFSD_GLOBAL RfsdGlobal;

/* DEFINITIONS *************************************************************/

NTSTATUS
RfsdScanDirCallback(
	ULONG		BlockNumber,
	PVOID		pContext );

typedef struct _RFSD_SCANDIR_CALLBACK_CONTEXT {
	IN  PRFSD_VCB				Vcb;
	IN  PRFSD_KEY_IN_MEMORY		pDirectoryKey;
	IN  PUNICODE_STRING			pTargetFilename;

	ULONG idxCurrentDentry;									/// Running count of the dentries processed, so that MatchingIndex will be relative to all dentry spans

	OUT PRFSD_DENTRY_HEAD		pMatchingDentry;			/// If a matching dentry is found, the callback will fill this structure with it
	OUT PULONG					pMatchingIndex;				/// Index of the matching entry (relative to all dentry spans for the directory)
} RFSD_SCANDIR_CALLBACK_CONTEXT, *PRFSD_SCANDIR_CALLBACK_CONTEXT;

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RfsdLookupFileName)
#pragma alloc_text(PAGE, RfsdSearchFcbList)
#pragma alloc_text(PAGE, RfsdScanDir)
#pragma alloc_text(PAGE, RfsdCreateFile)
#pragma alloc_text(PAGE, RfsdCreateVolume)
#pragma alloc_text(PAGE, RfsdCreate)

#if DISABLED
#pragma alloc_text(PAGE, RfsdCreateInode)
#pragma alloc_text(PAGE, RfsdSupersedeOrOverWriteFile)
#endif 

#pragma alloc_text(PAGE, RfsdScanDirCallback)
#endif

NTSTATUS
RfsdLookupFileName (IN PRFSD_VCB    Vcb,
            IN PUNICODE_STRING      FullFileName,
            IN PRFSD_MCB            ParentMcb,
            OUT PRFSD_MCB *         RfsdMcb,
            IN OUT PRFSD_INODE      Inode)					// An allocated, but unfilled inode, to which the matching file's information will be put
{
    NTSTATUS        Status;
    UNICODE_STRING  FileName;
    PRFSD_MCB       Mcb;

    RFSD_DENTRY_HEAD	DirectoryEntry;
    int             i = 0;
    BOOLEAN         bRun = TRUE;
    BOOLEAN         bParent = FALSE;
    RFSD_INODE      in;
    ULONG           off = 0;

    Status = STATUS_OBJECT_NAME_NOT_FOUND;

    *RfsdMcb = NULL;


	// Determine the parent node
    if (ParentMcb) {
		// Looking up a file in the tree, starting at an arbitrary parent node.
        bParent = TRUE;
    } else if (FullFileName->Buffer[0] == L'\\') {
		// Looking up from the root (so there was no parent).  Assign the root node parent from the VCB.
        ParentMcb = Vcb->McbTree;
    } else {
		// Otherwise, fail attempt to lookup non-rooted filename
        return STATUS_OBJECT_PATH_NOT_FOUND;
    }

	RtlZeroMemory(&DirectoryEntry, sizeof(RFSD_DENTRY_HEAD));

	// Sanity check that the filename is valid
    if (FullFileName->Length == 0) {
        return Status;
    }

	// Only if we're looking up *exactly* the root node, load it, and return it
    if (FullFileName->Length == 2 && FullFileName->Buffer[0] == L'\\') {		
        if (!RfsdLoadInode(Vcb, &(ParentMcb->Key), Inode))  {
            return Status;      
        }

        *RfsdMcb = Vcb->McbTree;

        return STATUS_SUCCESS;
    }

	// Begin lookup from the parent node
    while (bRun && i < FullFileName->Length/2) {
        int Length;
        ULONG FileAttr = FILE_ATTRIBUTE_NORMAL;

        if (bParent) {
            bParent = FALSE;
        } else  {
			// Advance through the (potentially) consecutive '\' path seperators in the filename
            while(i < FullFileName->Length/2 && FullFileName->Buffer[i] == L'\\') i++;
        }

        Length = i;

		// Advance to the next '\' path seperator
        while(i < FullFileName->Length/2 && (FullFileName->Buffer[i] != L'\\')) i++;

		if ( (i - Length) <= 0) {
			// All of the tokens have been parsed...
			break;
		}
		else {
			// There remains a token between the path seperators...
			
			// FileName is a (non-null-terminated) view into the FullFileName structure
            FileName = *FullFileName;
            FileName.Buffer += Length;
            FileName.Length = (USHORT)((i - Length) * 2);

			// Check to see if the parent MCB already contains a child MCB matching the target FileName
            Mcb = RfsdSearchMcb(Vcb, ParentMcb, &FileName);

            if (Mcb) {
                ParentMcb = Mcb;

                Status = STATUS_SUCCESS;

                if (!IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
                    if (i < FullFileName->Length/2) {
                        Status = STATUS_OBJECT_PATH_NOT_FOUND;
                    }

                    break;
                }
            } else {
				// The parent has no child MCB, or there was no child MCB sibling named FileName.  Check the disk using ScanDir...
				
                // Load the parent directory's inode / stat data structure
				// For ReiserFS, I'd need the parent's key.  This has to be a key leading to a directory... I'm just getting it to pass it to scan.				
				if (!RfsdLoadInode(Vcb, &(ParentMcb->Key), &in)) {
                    Status = STATUS_OBJECT_NAME_NOT_FOUND;
                    break;
                }

				// Sanity check that we loaded a directory (unless we loaded the last token, in which case it's ok that we loaded something else??)
                if (!S_ISDIR(in.i_mode)) {
                    if (i < FullFileName->Length/2) {
                        Status =  STATUS_OBJECT_NAME_NOT_FOUND;
                        break;
                    }
                }


                Status = RfsdScanDir (
                            Vcb,
                            ParentMcb,
                            &FileName,
                            &off,			// <
                            &(DirectoryEntry) );		// <

                if (!NT_SUCCESS(Status)) {
					// No such file (or an error occurred), so drop out.
                    bRun = FALSE;
/*
                    if (i >= FullFileName->Length/2)
                    {
                        *RfsdMcb = ParentMcb;
                    }
*/
                } else {
					// We've found what we were looking for...
#if 0			// disabled by ffs too
                    if (IsFlagOn( SUPER_BLOCK->s_feature_incompat, 
                                  RFSD_FEATURE_INCOMPAT_FILETYPE)) {
                        if (rfsd_dir.file_type == RFSD_FT_DIR)
                            SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY);
                    } else 
#endif						  
						{							
						RFSD_KEY_IN_MEMORY key;
						key.k_dir_id = DirectoryEntry.deh_dir_id;
						key.k_objectid = DirectoryEntry.deh_objectid;

                        if (!RfsdLoadInode(Vcb, &key, &in)) {
                            Status = STATUS_OBJECT_NAME_NOT_FOUND;
                            break;
                        }
                        if (S_ISDIR(in.i_mode)) {
                            SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY);
                        }
                    }

                    SetFlag(ParentMcb->Flags, MCB_IN_USE);
                    Mcb = RfsdAllocateMcb(Vcb, &FileName, FileAttr);
                    ClearFlag(ParentMcb->Flags, MCB_IN_USE);

                    if (!Mcb) {
                        Status = STATUS_OBJECT_NAME_NOT_FOUND;
                        break;
                    }

                    // NOTE: It should be OK to leave off the 3rd / 4th part of key, because (AFAIK) the only place this is used is ScanDir
					Mcb->Key.k_dir_id = DirectoryEntry.deh_dir_id;  
					Mcb->Key.k_objectid = DirectoryEntry.deh_objectid;
					Mcb->Key.k_offset = Mcb->Key.k_type = 0;
					
                    Mcb->DeOffset = off;
                    RfsdAddMcbNode(Vcb, ParentMcb, Mcb);
                    ParentMcb = Mcb;
                }
            }
        }
    }

    if (NT_SUCCESS(Status)) {
		// If the name has been found, load it according to the inode number in the MCB...
		// The result will be returned to the caller via Inode
        *RfsdMcb = Mcb;
		if (Inode) {
            if (!RfsdLoadInode(Vcb, &(Mcb->Key), Inode)) {
                RfsdPrint((DBG_ERROR, "RfsdLookupFileName: error loading Inode %x,%xh\n",
                          Mcb->Key.k_dir_id, Mcb->Key.k_objectid));
                Status = STATUS_INSUFFICIENT_RESOURCES;
            }
        }
    }

    return Status;
}


/** (This function is only called by LookupFileName.)
 NOTE: The offset and type of the key passed are irrelevant, as the function will always open a a directory for searching, and will search for the contents by file name -- not key.
 
 STATUS_INSUFFICIENT_RESOURCES		if the filename or diskreading buffer could not be allocated
 STATUS_UNSUCCESSFUL				if the buffer could not be read from disk
 STATUS_NO_SUCH_FILE				if the FileName given was not found in the directory scanned
*/
NTSTATUS
RfsdScanDir (IN PRFSD_VCB       Vcb,
         IN PRFSD_MCB           ParentMcb,				// Mcb of the directory to be scanned (which holds the ->Key of the directory)
         IN PUNICODE_STRING     FileName,				// Short file name (not necisarilly null-terminated!)
         IN OUT PULONG          Index,					// Offset (in bytes) of the dentry relative to the start of the directory listing
         IN OUT PRFSD_DENTRY_HEAD rfsd_dir)				// Directory entry of the found item
{
    NTSTATUS                Status = STATUS_UNSUCCESSFUL;
	RFSD_KEY_IN_MEMORY		DirectoryKey;
	

    	// Construct the key (for the directory to be searched), by copying the structure
		DirectoryKey = ParentMcb->Key;
		DirectoryKey.k_offset	= 0x1;
		DirectoryKey.k_type		= RFSD_KEY_TYPE_v2_DIRENTRY;

		// Request that the filesystem tree be parsed, looking for FileName in directory spans belonging to DirectoryKey
		{			
			RFSD_SCANDIR_CALLBACK_CONTEXT	CallbackContext;

			CallbackContext.Vcb					= Vcb;
			CallbackContext.pDirectoryKey		= &DirectoryKey;
			CallbackContext.pTargetFilename		= FileName;

			CallbackContext.idxCurrentDentry	= 0;
			
			CallbackContext.pMatchingDentry		= rfsd_dir;
			CallbackContext.pMatchingIndex		= Index;

			Status = RfsdParseFilesystemTree(Vcb, &DirectoryKey, Vcb->SuperBlock->s_root_block, &RfsdScanDirCallback, &CallbackContext);

			if (Status == STATUS_EVENT_DONE)
			{
				Status = STATUS_SUCCESS;
			}
			else if (Status == STATUS_SUCCESS)
			{
				Status = STATUS_NO_SUCH_FILE;
			}
			else
			{
				Status = STATUS_UNSUCCESSFUL;
			}
		}

    RfsdPrint((DBG_TRACE, __FUNCTION__ " returning %s\n", RfsdNtStatusToString(Status)));
    return Status;
}


NTSTATUS
RfsdCreateFile(PRFSD_IRP_CONTEXT IrpContext, PRFSD_VCB Vcb)
{
    NTSTATUS            Status = STATUS_UNSUCCESSFUL;
    PIO_STACK_LOCATION  IrpSp;
    PRFSD_FCB           Fcb = NULL;
    PRFSD_MCB           RfsdMcb = NULL;

    PRFSD_FCB           ParentFcb = NULL;
    PRFSD_MCB           ParentMcb = NULL;

    BOOLEAN             bParentFcbCreated = FALSE;

    PRFSD_CCB           Ccb = NULL;
    PRFSD_INODE         Inode;
    BOOLEAN             VcbResourceAcquired = FALSE;
    BOOLEAN             bDir = FALSE;
    BOOLEAN             bFcbAllocated = FALSE;
    BOOLEAN             bCreated = FALSE;
    UNICODE_STRING      FileName;
    PIRP                Irp;

    ULONG               Options;
    ULONG               CreateDisposition;

    BOOLEAN             OpenDirectory;
    BOOLEAN             OpenTargetDirectory;
    BOOLEAN             CreateDirectory;
    BOOLEAN             SequentialOnly;
    BOOLEAN             NoIntermediateBuffering;
    BOOLEAN             IsPagingFile;
    BOOLEAN             DirectoryFile;
    BOOLEAN             NonDirectoryFile;
    BOOLEAN             NoEaKnowledge;
    BOOLEAN             DeleteOnClose;
    BOOLEAN             TemporaryFile;
    BOOLEAN             CaseSensitive;

    ACCESS_MASK         DesiredAccess;
    ULONG               ShareAccess;


    Irp = IrpContext->Irp;
    IrpSp = IoGetCurrentIrpStackLocation(Irp);

    Options  = IrpSp->Parameters.Create.Options;
    
    DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE);
    OpenTargetDirectory = IsFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);

    NonDirectoryFile = IsFlagOn(Options, FILE_NON_DIRECTORY_FILE);
    SequentialOnly = IsFlagOn(Options, FILE_SEQUENTIAL_ONLY);
    NoIntermediateBuffering = IsFlagOn( Options, FILE_NO_INTERMEDIATE_BUFFERING );
    NoEaKnowledge = IsFlagOn(Options, FILE_NO_EA_KNOWLEDGE);
    DeleteOnClose = IsFlagOn(Options, FILE_DELETE_ON_CLOSE);

    CaseSensitive = IsFlagOn(IrpSp->Flags, SL_CASE_SENSITIVE);

    TemporaryFile = IsFlagOn(IrpSp->Parameters.Create.FileAttributes,
                                   FILE_ATTRIBUTE_TEMPORARY );

    CreateDisposition = (Options >> 24) & 0x000000ff;

    IsPagingFile = IsFlagOn(IrpSp->Flags, SL_OPEN_PAGING_FILE);

    CreateDirectory = (BOOLEAN)(DirectoryFile &&
                                ((CreateDisposition == FILE_CREATE) ||
                                 (CreateDisposition == FILE_OPEN_IF)));

    OpenDirectory   = (BOOLEAN)(DirectoryFile &&
                                ((CreateDisposition == FILE_OPEN) ||
                                 (CreateDisposition == FILE_OPEN_IF)));

    DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
    ShareAccess   = IrpSp->Parameters.Create.ShareAccess;

    FileName.Buffer = NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -