Files
WPinternals/DiscUtils/Ntfs/FileNameRecord.cs
T
2018-10-25 22:35:49 +02:00

211 lines
8.3 KiB
C#

//
// Copyright (c) 2008-2011, Kenneth Bell
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
namespace DiscUtils.Ntfs
{
using System;
using System.IO;
using System.Text;
[Flags]
internal enum FileAttributeFlags : uint
{
None = 0x00000000,
ReadOnly = 0x00000001,
Hidden = 0x00000002,
System = 0x00000004,
Archive = 0x00000020,
Device = 0x00000040,
Normal = 0x00000080,
Temporary = 0x00000100,
Sparse = 0x00000200,
ReparsePoint = 0x00000400,
Compressed = 0x00000800,
Offline = 0x00001000,
NotIndexed = 0x00002000,
Encrypted = 0x00004000,
Directory = 0x10000000,
IndexView = 0x20000000
}
internal enum FileNameNamespace : byte
{
Posix = 0,
Win32 = 1,
Dos = 2,
Win32AndDos = 3
}
internal class FileNameRecord : IByteArraySerializable, IDiagnosticTraceable, IEquatable<FileNameRecord>
{
public FileRecordReference ParentDirectory;
public DateTime CreationTime;
public DateTime ModificationTime;
public DateTime MftChangedTime;
public DateTime LastAccessTime;
public ulong AllocatedSize;
public ulong RealSize;
public FileAttributeFlags Flags;
public uint EASizeOrReparsePointTag;
public FileNameNamespace FileNameNamespace;
public string FileName;
public FileNameRecord()
{
}
public FileNameRecord(FileNameRecord toCopy)
{
ParentDirectory = toCopy.ParentDirectory;
CreationTime = toCopy.CreationTime;
ModificationTime = toCopy.ModificationTime;
MftChangedTime = toCopy.MftChangedTime;
LastAccessTime = toCopy.LastAccessTime;
AllocatedSize = toCopy.AllocatedSize;
RealSize = toCopy.RealSize;
Flags = toCopy.Flags;
EASizeOrReparsePointTag = toCopy.EASizeOrReparsePointTag;
FileNameNamespace = toCopy.FileNameNamespace;
FileName = toCopy.FileName;
}
public FileAttributes FileAttributes
{
get { return ConvertFlags(Flags); }
}
public int Size
{
get
{
return 0x42 + (FileName.Length * 2);
}
}
public override string ToString()
{
return FileName;
}
public void Dump(TextWriter writer, string indent)
{
writer.WriteLine(indent + "FILE NAME RECORD");
writer.WriteLine(indent + " Parent Directory: " + ParentDirectory);
writer.WriteLine(indent + " Creation Time: " + CreationTime);
writer.WriteLine(indent + " Modification Time: " + ModificationTime);
writer.WriteLine(indent + " MFT Changed Time: " + MftChangedTime);
writer.WriteLine(indent + " Last Access Time: " + LastAccessTime);
writer.WriteLine(indent + " Allocated Size: " + AllocatedSize);
writer.WriteLine(indent + " Real Size: " + RealSize);
writer.WriteLine(indent + " Flags: " + Flags);
if ((Flags & FileAttributeFlags.ReparsePoint) != 0)
{
writer.WriteLine(indent + " Reparse Point Tag: " + EASizeOrReparsePointTag);
}
else
{
writer.WriteLine(indent + " Ext Attr Size: " + (EASizeOrReparsePointTag & 0xFFFF));
}
writer.WriteLine(indent + " Namespace: " + FileNameNamespace);
writer.WriteLine(indent + " File Name: " + FileName);
}
public int ReadFrom(byte[] buffer, int offset)
{
ParentDirectory = new FileRecordReference(Utilities.ToUInt64LittleEndian(buffer, offset + 0x00));
CreationTime = ReadDateTime(buffer, offset + 0x08);
ModificationTime = ReadDateTime(buffer, offset + 0x10);
MftChangedTime = ReadDateTime(buffer, offset + 0x18);
LastAccessTime = ReadDateTime(buffer, offset + 0x20);
AllocatedSize = Utilities.ToUInt64LittleEndian(buffer, offset + 0x28);
RealSize = Utilities.ToUInt64LittleEndian(buffer, offset + 0x30);
Flags = (FileAttributeFlags)Utilities.ToUInt32LittleEndian(buffer, offset + 0x38);
EASizeOrReparsePointTag = Utilities.ToUInt32LittleEndian(buffer, offset + 0x3C);
byte fnLen = buffer[offset + 0x40];
FileNameNamespace = (FileNameNamespace)buffer[offset + 0x41];
FileName = Encoding.Unicode.GetString(buffer, offset + 0x42, fnLen * 2);
return 0x42 + (fnLen * 2);
}
public void WriteTo(byte[] buffer, int offset)
{
Utilities.WriteBytesLittleEndian((ulong)ParentDirectory.Value, buffer, offset + 0x00);
Utilities.WriteBytesLittleEndian((ulong)CreationTime.ToFileTimeUtc(), buffer, offset + 0x08);
Utilities.WriteBytesLittleEndian((ulong)ModificationTime.ToFileTimeUtc(), buffer, offset + 0x10);
Utilities.WriteBytesLittleEndian((ulong)MftChangedTime.ToFileTimeUtc(), buffer, offset + 0x18);
Utilities.WriteBytesLittleEndian((ulong)LastAccessTime.ToFileTimeUtc(), buffer, offset + 0x20);
Utilities.WriteBytesLittleEndian(AllocatedSize, buffer, offset + 0x28);
Utilities.WriteBytesLittleEndian(RealSize, buffer, offset + 0x30);
Utilities.WriteBytesLittleEndian((uint)Flags, buffer, offset + 0x38);
Utilities.WriteBytesLittleEndian(EASizeOrReparsePointTag, buffer, offset + 0x3C);
buffer[offset + 0x40] = (byte)FileName.Length;
buffer[offset + 0x41] = (byte)FileNameNamespace;
Encoding.Unicode.GetBytes(FileName, 0, FileName.Length, buffer, offset + 0x42);
}
public bool Equals(FileNameRecord other)
{
if (other == null)
{
return false;
}
return ParentDirectory == other.ParentDirectory
&& FileNameNamespace == other.FileNameNamespace
&& FileName == other.FileName;
}
internal static FileAttributeFlags SetAttributes(FileAttributes attrs, FileAttributeFlags flags)
{
FileAttributes attrMask = ((FileAttributes)0xFFFF) & ~FileAttributes.Directory;
return (FileAttributeFlags)(((uint)flags & 0xFFFF0000) | (uint)(attrs & attrMask));
}
internal static FileAttributes ConvertFlags(FileAttributeFlags flags)
{
FileAttributes result = (FileAttributes)(((uint)flags) & 0xFFFF);
if ((flags & FileAttributeFlags.Directory) != 0)
{
result |= FileAttributes.Directory;
}
return result;
}
private static DateTime ReadDateTime(byte[] buffer, int offset)
{
try
{
return DateTime.FromFileTimeUtc(Utilities.ToInt64LittleEndian(buffer, offset));
}
catch (ArgumentException)
{
return DateTime.MinValue;
}
}
}
}