// // 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.Globalization; using System.IO; using System.Security.Principal; internal sealed class Quotas { private IndexView _ownerIndex; private IndexView _quotaIndex; public Quotas(File file) { _ownerIndex = new IndexView(file.GetIndex("$O")); _quotaIndex = new IndexView(file.GetIndex("$Q")); } public static Quotas Initialize(File file) { Index ownerIndex = file.CreateIndex("$O", (AttributeType)0, AttributeCollationRule.Sid); Index quotaIndox = file.CreateIndex("$Q", (AttributeType)0, AttributeCollationRule.UnsignedLong); IndexView ownerIndexView = new IndexView(ownerIndex); IndexView quotaIndexView = new IndexView(quotaIndox); OwnerKey adminSid = new OwnerKey(new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null)); OwnerRecord adminOwnerId = new OwnerRecord(256); ownerIndexView[adminSid] = adminOwnerId; quotaIndexView[new OwnerRecord(1)] = new QuotaRecord(null); quotaIndexView[adminOwnerId] = new QuotaRecord(adminSid.Sid); return new Quotas(file); } public void Dump(TextWriter writer, string indent) { writer.WriteLine(indent + "QUOTAS"); writer.WriteLine(indent + " OWNER INDEX"); foreach (var entry in _ownerIndex.Entries) { writer.WriteLine(indent + " OWNER INDEX ENTRY"); writer.WriteLine(indent + " SID: " + entry.Key.Sid); writer.WriteLine(indent + " Owner Id: " + entry.Value.OwnerId); } writer.WriteLine(indent + " QUOTA INDEX"); foreach (var entry in _quotaIndex.Entries) { writer.WriteLine(indent + " QUOTA INDEX ENTRY"); writer.WriteLine(indent + " Owner Id: " + entry.Key.OwnerId); writer.WriteLine(indent + " User SID: " + entry.Value.Sid); writer.WriteLine(indent + " Changed: " + entry.Value.ChangeTime); writer.WriteLine(indent + " Exceeded: " + entry.Value.ExceededTime); writer.WriteLine(indent + " Bytes Used: " + entry.Value.BytesUsed); writer.WriteLine(indent + " Flags: " + entry.Value.Flags); writer.WriteLine(indent + " Hard Limit: " + entry.Value.HardLimit); writer.WriteLine(indent + " Warning Limit: " + entry.Value.WarningLimit); writer.WriteLine(indent + " Version: " + entry.Value.Version); } } internal sealed class OwnerKey : IByteArraySerializable { public SecurityIdentifier Sid; public OwnerKey() { } public OwnerKey(SecurityIdentifier sid) { Sid = sid; } public int Size { get { return Sid.BinaryLength; } } public int ReadFrom(byte[] buffer, int offset) { Sid = new SecurityIdentifier(buffer, offset); return Sid.BinaryLength; } public void WriteTo(byte[] buffer, int offset) { Sid.GetBinaryForm(buffer, offset); } public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "[Sid:{0}]", Sid); } } internal sealed class OwnerRecord : IByteArraySerializable { public int OwnerId; public OwnerRecord() { } public OwnerRecord(int ownerId) { OwnerId = ownerId; } public int Size { get { return 4; } } public int ReadFrom(byte[] buffer, int offset) { OwnerId = Utilities.ToInt32LittleEndian(buffer, offset); return 4; } public void WriteTo(byte[] buffer, int offset) { Utilities.WriteBytesLittleEndian(OwnerId, buffer, offset); } public override string ToString() { return "[OwnerId:" + OwnerId + "]"; } } internal sealed class QuotaRecord : IByteArraySerializable { public int Version; public int Flags; public long BytesUsed; public DateTime ChangeTime; public long WarningLimit; public long HardLimit; public long ExceededTime; public SecurityIdentifier Sid; public QuotaRecord() { } public QuotaRecord(SecurityIdentifier sid) { Version = 2; Flags = 1; ChangeTime = DateTime.UtcNow; WarningLimit = -1; HardLimit = -1; Sid = sid; } public int Size { get { return 0x30 + (Sid == null ? 0 : Sid.BinaryLength); } } public int ReadFrom(byte[] buffer, int offset) { Version = Utilities.ToInt32LittleEndian(buffer, offset); Flags = Utilities.ToInt32LittleEndian(buffer, offset + 0x04); BytesUsed = Utilities.ToInt64LittleEndian(buffer, offset + 0x08); ChangeTime = DateTime.FromFileTimeUtc(Utilities.ToInt64LittleEndian(buffer, offset + 0x10)); WarningLimit = Utilities.ToInt64LittleEndian(buffer, offset + 0x18); HardLimit = Utilities.ToInt64LittleEndian(buffer, offset + 0x20); ExceededTime = Utilities.ToInt64LittleEndian(buffer, offset + 0x28); if (buffer.Length - offset > 0x30) { Sid = new SecurityIdentifier(buffer, offset + 0x30); return 0x30 + Sid.BinaryLength; } return 0x30; } public void WriteTo(byte[] buffer, int offset) { Utilities.WriteBytesLittleEndian(Version, buffer, offset); Utilities.WriteBytesLittleEndian(Flags, buffer, offset + 0x04); Utilities.WriteBytesLittleEndian(BytesUsed, buffer, offset + 0x08); Utilities.WriteBytesLittleEndian(ChangeTime.ToFileTimeUtc(), buffer, offset + 0x10); Utilities.WriteBytesLittleEndian(WarningLimit, buffer, offset + 0x18); Utilities.WriteBytesLittleEndian(HardLimit, buffer, offset + 0x20); Utilities.WriteBytesLittleEndian(ExceededTime, buffer, offset + 0x28); if (Sid != null) { Sid.GetBinaryForm(buffer, offset + 0x30); } } public override string ToString() { return "[V:" + Version + ",F:" + Flags + ",BU:" + BytesUsed + ",CT:" + ChangeTime + ",WL:" + WarningLimit + ",HL:" + HardLimit + ",ET:" + ExceededTime + ",SID:" + Sid + "]"; } } } }