/*-
* Copyright (C) 2008 Erik Larsson
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.catacombae.storage.fs;
import java.util.Date;
import org.catacombae.util.Util;
/**
* @author <a href="http://www.catacombae.org/" target="_top">Erik Larsson</a>
*/
public abstract class FSAttributes {
public abstract boolean hasPOSIXFileAttributes();
public abstract POSIXFileAttributes getPOSIXFileAttributes();
public abstract boolean hasWindowsFileAttributes();
public abstract WindowsFileAttributes getWindowsFileAttributes();
public abstract boolean hasCreateDate();
public abstract Date getCreateDate();
public abstract boolean hasModifyDate();
public abstract Date getModifyDate();
public abstract boolean hasAttributeModifyDate();
public abstract Date getAttributeModifyDate();
public abstract boolean hasAccessDate();
public abstract Date getAccessDate();
public abstract boolean hasBackupDate();
public abstract Date getBackupDate();
public abstract boolean hasLinkCount();
public abstract Long getLinkCount();
//public abstract FSAccessControlList getAccessControlList();
public static abstract class POSIXFileAttributes {
/** One of the valid return values for <code>getFileType();</code> */
public static final byte FILETYPE_UNDEFINED = 00;
/** One of the valid return values for <code>getFileType();</code> */
public static final byte FILETYPE_FIFO = 01;
/** One of the valid return values for <code>getFileType();</code> */
public static final byte FILETYPE_CHARACTER_SPECIAL = 02;
/** One of the valid return values for <code>getFileType();</code> */
public static final byte FILETYPE_DIRECTORY = 04;
/** One of the valid return values for <code>getFileType();</code> */
public static final byte FILETYPE_BLOCK_SPECIAL = 06;
/** One of the valid return values for <code>getFileType();</code> */
public static final byte FILETYPE_REGULAR = 010;
/** One of the valid return values for <code>getFileType();</code> */
public static final byte FILETYPE_SYMBOLIC_LINK = 012;
/** One of the valid return values for <code>getFileType();</code> */
public static final byte FILETYPE_SOCKET = 014;
/** One of the valid return values for <code>getFileType();</code> */
public static final byte FILETYPE_WHITEOUT = 016;
public abstract long getUserID();
public abstract long getGroupID();
public abstract byte getFileType();
public abstract boolean canUserRead();
public abstract boolean canUserWrite();
public abstract boolean canUserExecute();
public abstract boolean canGroupRead();
public abstract boolean canGroupWrite();
public abstract boolean canGroupExecute();
public abstract boolean canOthersRead();
public abstract boolean canOthersWrite();
public abstract boolean canOthersExecute();
public abstract boolean isSetUID();
public abstract boolean isSetGID();
public abstract boolean isStickyBit();
public abstract boolean hasInodeNumber();
public abstract Long getInodeNumber();
/**
* Returns the POSIX-type file mode string for this file, as it would appear
* when listing it with 'ls -l'. Example: <code>drwxr-x---</code>.
*
* @return the POSIX-type file mode string for this file.
*/
public String getPermissionString() {
String result;
byte fileType = getFileType();
switch(fileType) {
case FILETYPE_UNDEFINED: // This one appears at the root node (CNID 2) sometimes. dunno what it would look like in ls -l
result = "?";
break;
case FILETYPE_FIFO:
result = "p";
break;
case FILETYPE_CHARACTER_SPECIAL:
result = "c";
break;
case FILETYPE_DIRECTORY:
result = "d";
break;
case FILETYPE_BLOCK_SPECIAL:
result = "b";
break;
case FILETYPE_REGULAR:
result = "-";
break;
case FILETYPE_SYMBOLIC_LINK:
result = "l";
break;
case FILETYPE_SOCKET:
result = "s";
break;
case FILETYPE_WHITEOUT:
result = "w";
break; // How does this appear in "ls -l" ? and what is it?
default:
result = " ";
System.err.println(
"[FSAttributes.POSIXFileAttributes.getPermissionString()] " +
"Unknown file type: " + fileType +
" Mode: 0x" + Util.toHexStringBE(getFileModeWord()));
}
if(canUserRead())
result += "r";
else
result += "-";
if(canUserWrite())
result += "w";
else
result += "-";
if(canUserExecute()) {
if(isSetUID())
result += "s";
else
result += "x";
}
else {
if(isSetUID())
result += "S";
else
result += "-";
}
if(canGroupRead())
result += "r";
else
result += "-";
if(canGroupWrite())
result += "w";
else
result += "-";
if(canGroupExecute()) {
if(isSetGID())
result += "s";
else
result += "x";
}
else {
if(isSetGID())
result += "S";
else
result += "-";
}
if(canOthersRead())
result += "r";
else
result += "-";
if(canOthersWrite())
result += "w";
else
result += "-";
if(canOthersExecute()) {
if(isStickyBit())
result += "t";
else
result += "x";
}
else {
if(isStickyBit())
result += "T";
else
result += "-";
}
return result;
}
/**
* Returns the raw POSIX file mode word, containing user/group/other rwx
* permissions, setuid, setgid, sticky bit and file type.
*
* @return the raw POSIX file mode word.
*/
public short getFileModeWord() {
short result = (short)((getFileType() & 017) << 12);
result = Util.setBit(result, 11, isSetUID());
result = Util.setBit(result, 10, isSetGID());
result = Util.setBit(result, 9, isStickyBit());
result = Util.setBit(result, 8, canUserRead());
result = Util.setBit(result, 7, canUserWrite());
result = Util.setBit(result, 6, canUserExecute());
result = Util.setBit(result, 5, canGroupRead());
result = Util.setBit(result, 4, canGroupWrite());
result = Util.setBit(result, 3, canGroupExecute());
result = Util.setBit(result, 2, canOthersRead());
result = Util.setBit(result, 1, canOthersWrite());
result = Util.setBit(result, 0, canOthersExecute());
return result;
}
}
public static class DefaultPOSIXFileAttributes extends POSIXFileAttributes {
private final short fileMode;
private final long userID;
private final long groupID;
private final Long inodeNumber;
public DefaultPOSIXFileAttributes(long userID, long groupID, short fileMode) {
this(userID, groupID, fileMode, null);
}
public DefaultPOSIXFileAttributes(long userID, long groupID, short fileMode, long inodeNumber) {
this(userID, groupID, fileMode, new Long(inodeNumber));
}
private DefaultPOSIXFileAttributes(long userID, long groupID, short fileMode, Long inodeNumber) {
this.userID = userID;
this.groupID = groupID;
this.fileMode = fileMode;
this.inodeNumber = inodeNumber;
}
/** {@inheritDoc} */
@Override
public long getUserID() { return userID; }
/** {@inheritDoc} */
@Override
public long getGroupID() { return groupID; }
/** {@inheritDoc} */
@Override
public byte getFileType() {
int type = (fileMode >> 12) & 017;
return (byte) type;
}
/** {@inheritDoc} */
@Override
public boolean isSetUID() { return Util.getBit(fileMode, 11); }
/** {@inheritDoc} */
@Override
public boolean isSetGID() { return Util.getBit(fileMode, 10); }
/** {@inheritDoc} */
@Override
public boolean isStickyBit() { return Util.getBit(fileMode, 9); }
/** {@inheritDoc} */
@Override
public boolean canUserRead() { return Util.getBit(fileMode, 8); }
/** {@inheritDoc} */
@Override
public boolean canUserWrite() { return Util.getBit(fileMode, 7); }
/** {@inheritDoc} */
@Override
public boolean canUserExecute() { return Util.getBit(fileMode, 6); }
/** {@inheritDoc} */
@Override
public boolean canGroupRead() { return Util.getBit(fileMode, 5); }
/** {@inheritDoc} */
@Override
public boolean canGroupWrite() { return Util.getBit(fileMode, 4); }
/** {@inheritDoc} */
@Override
public boolean canGroupExecute() { return Util.getBit(fileMode, 3); }
/** {@inheritDoc} */
@Override
public boolean canOthersRead() { return Util.getBit(fileMode, 2); }
/** {@inheritDoc} */
@Override
public boolean canOthersWrite() { return Util.getBit(fileMode, 1); }
/** {@inheritDoc} */
@Override
public boolean canOthersExecute() { return Util.getBit(fileMode, 0); }
/** {@inheritDoc} */
@Override
public short getFileModeWord() {
return fileMode;
}
@Override
public boolean hasInodeNumber() {
return inodeNumber != null;
}
@Override
public Long getInodeNumber() {
return inodeNumber;
}
}
}