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

228 lines
8.8 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.Globalization;
using System.IO;
using System.Security.Principal;
internal sealed class Quotas
{
private IndexView<OwnerKey, OwnerRecord> _ownerIndex;
private IndexView<OwnerRecord, QuotaRecord> _quotaIndex;
public Quotas(File file)
{
_ownerIndex = new IndexView<OwnerKey, OwnerRecord>(file.GetIndex("$O"));
_quotaIndex = new IndexView<OwnerRecord, QuotaRecord>(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<OwnerKey, OwnerRecord> ownerIndexView = new IndexView<OwnerKey, OwnerRecord>(ownerIndex);
IndexView<OwnerRecord, QuotaRecord> quotaIndexView = new IndexView<OwnerRecord, QuotaRecord>(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 + "]";
}
}
}
}