/*
* $Id$
*
* Copyright (C) 2003-2015 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.fs.ntfs.attribute;
import org.jnode.fs.ntfs.FileNameAttribute;
import org.jnode.fs.ntfs.FileRecord;
import org.jnode.fs.ntfs.NTFSStructure;
import org.jnode.fs.ntfs.StandardInformationAttribute;
import org.jnode.fs.ntfs.index.IndexAllocationAttribute;
import org.jnode.fs.ntfs.index.IndexRootAttribute;
/**
* @author Chira
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
public abstract class NTFSAttribute extends NTFSStructure {
public static final class Types {
public static final int STANDARD_INFORMATION = 0x10;
public static final int ATTRIBUTE_LIST = 0x20;
public static final int FILE_NAME = 0x30;
public static final int VOLUME_VERSION = 0x40;
public static final int OBJECT_ID = 0x40;
public static final int SECURITY_DESCRIPTOR = 0x50;
public static final int VOLUME_NAME = 0x60;
public static final int VOLUME_INFORMATION = 0x70;
public static final int DATA = 0x80;
public static final int INDEX_ROOT = 0x90;
public static final int INDEX_ALLOCATION = 0xA0;
public static final int BITMAP = 0xB0;
public static final int SYMBOLIC_LINK = 0xC0;
public static final int REPARSE_POINT = 0xC0;
public static final int EA_INFORMATION = 0xD0;
public static final int EA = 0xE0;
public static final int PROPERTY_SET = 0xF0;
public static final int LOGGED_UTILITY_STREAM = 0x100;
}
private final int type;
private final int flags;
private final FileRecord fileRecord;
/**
* Initialize this instance.
*/
public NTFSAttribute(FileRecord fileRecord, int offset) {
super(fileRecord, offset);
this.fileRecord = fileRecord;
this.type = getUInt32AsInt(0);
this.flags = getUInt16(0x0C);
}
/**
* @return Returns the attributeType.
*/
public int getAttributeType() {
return type;
}
/*
* Flag |Description ------------------- 0x0001 |Compressed 0x4000
* |Encrypted 0x8000 |Sparse
*/
public int getFlags() {
return flags;
}
/**
* Checks whether this attribute contains compressed data runs.
*
* @return {@code true} if the attribute contains compressed runs, {@code false} otherwise.
*/
public boolean isCompressedAttribute() {
return (getFlags() & 0x0001) != 0;
}
/**
* @return Returns the nameLength.
*/
public int getNameLength() {
return getUInt8(0x09);
}
/**
* @return Returns the nameOffset.
*/
public int getNameOffset() {
return getUInt16(0x0A);
}
/**
* @return Returns the attributeID.
*/
public int getAttributeID() {
return getUInt16(0x0E);
}
/**
* @return Returns the attributeName.
*/
public String getAttributeName() {
// if it is named fill the attribute name
final int nameLength = getNameLength();
if (nameLength > 0) {
final char[] namebuf = new char[nameLength];
final int nameOffset = getNameOffset();
for (int i = 0; i < nameLength; i++) {
namebuf[i] = getChar16(nameOffset + (i * 2));
}
return new String(namebuf);
}
return null;
}
/**
* @return Returns the fileRecord.
*/
public FileRecord getFileRecord() {
return this.fileRecord;
}
/**
* @return Returns the resident.
*/
public boolean isResident() {
return (getUInt8(0x08) == 0);
}
/**
* Gets the length of this attribute in bytes.
*
* @return the length
*/
public int getSize() {
return getUInt32AsInt(4);
}
/**
* Generates a debug string for the attribute.
*
* @return the debug string.
*/
public abstract String toDebugString();
/**
* Create an NTFSAttribute instance suitable for the given attribute data.
*
* @param fileRecord the containing file record.
* @param offset the offset to read from.
* @return the attribute
*/
public static NTFSAttribute getAttribute(FileRecord fileRecord, int offset) {
int fallbackCompressionUnit = 1; // '1 << 0' is the 'default' unit size
return getAttribute(fileRecord, offset, fallbackCompressionUnit);
}
/**
* Create an NTFSAttribute instance suitable for the given attribute data.
*
* @param fileRecord the containing file record.
* @param offset the offset to read from.
* @param fallbackCompressionUnit the fallback compression unit to use if the attribute is compressed but doesn't
* have a compression unit stored.
* @return the attribute
*/
public static NTFSAttribute getAttribute(FileRecord fileRecord, int offset, int fallbackCompressionUnit) {
final boolean resident = (fileRecord.getUInt8(offset + 0x08) == 0);
final int type = fileRecord.getUInt32AsInt(offset + 0x00);
switch (type) {
case Types.STANDARD_INFORMATION:
return new StandardInformationAttribute(fileRecord, offset);
case Types.ATTRIBUTE_LIST:
if (resident) {
return new AttributeListAttributeRes(fileRecord, offset);
} else {
return new AttributeListAttributeNonRes(fileRecord, offset, fallbackCompressionUnit);
}
case Types.FILE_NAME:
return new FileNameAttribute(fileRecord, offset);
case Types.INDEX_ROOT:
return new IndexRootAttribute(fileRecord, offset);
case Types.INDEX_ALLOCATION:
return new IndexAllocationAttribute(fileRecord, offset, fallbackCompressionUnit);
case Types.REPARSE_POINT:
return new ReparsePointAttribute(fileRecord, offset);
}
// check the resident flag
if (resident) {
// resident
return new NTFSResidentAttribute(fileRecord, offset);
} else {
// non resident
return new NTFSNonResidentAttribute(fileRecord, offset, fallbackCompressionUnit);
}
}
}