Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matt-wu/Ext3Fsd.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaho Ng <ngkaho1234@gmail.com>2016-05-27 07:29:18 +0300
committerKaho Ng <ngkaho1234@gmail.com>2016-05-27 07:47:52 +0300
commit4aa3da66e1cf76aca3835efcf125df620721adb3 (patch)
tree6d9e03ddfc3a73b776fd40bb1a90dba9ba2ab655 /Ext3Fsd
parent33bf22739881617ae00f960e148da38b71100b3b (diff)
create: add Ea support upon file creation or overwriting
Diffstat (limited to 'Ext3Fsd')
-rw-r--r--Ext3Fsd/create.c157
-rw-r--r--Ext3Fsd/include/ext2fs.h5
2 files changed, 161 insertions, 1 deletions
diff --git a/Ext3Fsd/create.c b/Ext3Fsd/create.c
index e7ac578..c3bcfa8 100644
--- a/Ext3Fsd/create.c
+++ b/Ext3Fsd/create.c
@@ -671,6 +671,154 @@ errorout:
return Ext2WinntError(rc);
}
+//
+// Any call to this routine must have Fcb's MainResource and FcbLock acquired.
+//
+
+NTSTATUS
+Ext2OverwriteEa(
+ PEXT2_IRP_CONTEXT IrpContext,
+ PEXT2_VCB Vcb,
+ PEXT2_FCB Fcb,
+ PIO_STATUS_BLOCK Iosb
+)
+{
+ PEXT2_MCB Mcb = NULL;
+ PIRP Irp;
+ PIO_STACK_LOCATION IrpSp;
+
+ struct ext4_xattr_ref xattr_ref;
+ BOOLEAN XattrRefAcquired = FALSE;
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+
+ PFILE_FULL_EA_INFORMATION FullEa;
+ PCHAR EaBuffer;
+ ULONG EaBufferLength;
+
+ __try {
+
+ Irp = IrpContext->Irp;
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ Mcb = Fcb->Mcb;
+
+ EaBuffer = Irp->AssociatedIrp.SystemBuffer;
+ EaBufferLength = IrpSp->Parameters.Create.EaLength;
+
+ if (!Mcb)
+ __leave;
+
+ //
+ // Return peacefully if there is no EaBuffer provided.
+ //
+ if (!EaBuffer) {
+ Status = STATUS_SUCCESS;
+ __leave;
+ }
+
+ //
+ // If the caller specifies an EaBuffer, but has no knowledge about Ea,
+ // we reject the request.
+ //
+ if (EaBuffer != NULL &&
+ FlagOn(IrpSp->Parameters.Create.Options, FILE_NO_EA_KNOWLEDGE)) {
+ Status = STATUS_ACCESS_DENIED;
+ __leave;
+ }
+
+ //
+ // Check Ea Buffer validity.
+ //
+ Status = IoCheckEaBufferValidity(EaBuffer, EaBufferLength, &Iosb->Information);
+ if (!NT_SUCCESS(Status))
+ __leave;
+
+ Status = Ext2WinntError(ext4_fs_get_xattr_ref(IrpContext, Vcb, Fcb->Mcb, &xattr_ref));
+ if (!NT_SUCCESS(Status)) {
+ DbgPrint("ext4_fs_get_xattr_ref() failed!\n");
+ __leave;
+ }
+
+ XattrRefAcquired = TRUE;
+
+ //
+ // Remove all existing EA entries.
+ //
+ ext4_xattr_purge_items(&xattr_ref);
+ xattr_ref.dirty = TRUE;
+ Status = STATUS_SUCCESS;
+
+ // Iterate the whole EA buffer to do inspection
+ for (FullEa = (PFILE_FULL_EA_INFORMATION)EaBuffer;
+ FullEa < (PFILE_FULL_EA_INFORMATION)&EaBuffer[EaBufferLength];
+ FullEa = (PFILE_FULL_EA_INFORMATION)(FullEa->NextEntryOffset == 0 ?
+ &EaBuffer[EaBufferLength] :
+ (PCHAR)FullEa + FullEa->NextEntryOffset)) {
+
+ OEM_STRING EaName;
+
+ EaName.MaximumLength = EaName.Length = FullEa->EaNameLength;
+ EaName.Buffer = &FullEa->EaName[0];
+
+ // Check if EA's name is valid
+ if (!Ext2IsEaNameValid(EaName)) {
+ Status = STATUS_INVALID_EA_NAME;
+ __leave;
+ }
+ }
+
+ // Now add EA entries to the inode
+ for (FullEa = (PFILE_FULL_EA_INFORMATION)EaBuffer;
+ FullEa < (PFILE_FULL_EA_INFORMATION)&EaBuffer[EaBufferLength];
+ FullEa = (PFILE_FULL_EA_INFORMATION)(FullEa->NextEntryOffset == 0 ?
+ &EaBuffer[EaBufferLength] :
+ (PCHAR)FullEa + FullEa->NextEntryOffset)) {
+
+ int ret;
+ OEM_STRING EaName;
+
+ EaName.MaximumLength = EaName.Length = FullEa->EaNameLength;
+ EaName.Buffer = &FullEa->EaName[0];
+
+ Status = Ext2WinntError(ret =
+ ext4_fs_set_xattr(&xattr_ref,
+ EXT4_XATTR_INDEX_USER,
+ EaName.Buffer,
+ EaName.Length,
+ &FullEa->EaName[0] + FullEa->EaNameLength + 1,
+ FullEa->EaValueLength,
+ TRUE));
+ if (!NT_SUCCESS(Status) && ret != -ENODATA)
+ __leave;
+
+ if (ret == -ENODATA) {
+ Status = Ext2WinntError(
+ ext4_fs_set_xattr(&xattr_ref,
+ EXT4_XATTR_INDEX_USER,
+ EaName.Buffer,
+ EaName.Length,
+ &FullEa->EaName[0] + FullEa->EaNameLength + 1,
+ FullEa->EaValueLength,
+ FALSE));
+ if (!NT_SUCCESS(Status))
+ __leave;
+
+ }
+ }
+ }
+ __finally {
+
+ if (XattrRefAcquired) {
+ if (!NT_SUCCESS(Status)) {
+ xattr_ref.dirty = FALSE;
+ ext4_fs_put_xattr_ref(&xattr_ref);
+ } else {
+ Status = Ext2WinntError(ext4_fs_put_xattr_ref(&xattr_ref));
+ }
+ }
+ }
+ return Status;
+}
+
NTSTATUS
Ext2CreateFile(
PEXT2_IRP_CONTEXT IrpContext,
@@ -1289,6 +1437,12 @@ Openit:
// This file is just created.
//
+ Status = Ext2OverwriteEa(IrpContext, Vcb, Fcb, &Irp->IoStatus);
+ if (!NT_SUCCESS(Status)) {
+ Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
+ __leave;
+ }
+
if (DirectoryFile) {
Status = Ext2AddDotEntries(IrpContext, &ParentMcb->Inode, &Mcb->Inode);
@@ -2018,5 +2172,6 @@ Ext2SupersedeOrOverWriteFile(
Fcb->Inode->i_mtime = Ext2LinuxTime(CurrentTime);
Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);
- return STATUS_SUCCESS;
+ // See if we need to overwrite EA of the file
+ return Ext2OverwriteEa(IrpContext, Vcb, Fcb, &IrpContext->Irp->IoStatus);
}
diff --git a/Ext3Fsd/include/ext2fs.h b/Ext3Fsd/include/ext2fs.h
index 678b6ad..ba666fe 100644
--- a/Ext3Fsd/include/ext2fs.h
+++ b/Ext3Fsd/include/ext2fs.h
@@ -1597,6 +1597,11 @@ Ext2QueryEa(
IN PEXT2_IRP_CONTEXT IrpContext
);
+BOOLEAN
+Ext2IsEaNameValid(
+ IN OEM_STRING Name
+);
+
NTSTATUS
Ext2SetEa(
IN PEXT2_IRP_CONTEXT IrpContext