438 lines
12 KiB
Java
438 lines
12 KiB
Java
package net.hyperic.sigar;
|
|
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.ArrayList;
|
|
import java.util.Date;
|
|
|
|
public class FileInfo extends FileAttrs {
|
|
|
|
private static final SimpleDateFormat DATE_FORMAT =
|
|
new SimpleDateFormat("MMM dd HH:mm");
|
|
|
|
String name;
|
|
private Sigar sigar;
|
|
private boolean dirStatEnabled = false;
|
|
private DirStat stat = null;
|
|
private boolean lstat;
|
|
private FileInfo oldInfo = null;
|
|
|
|
private static char DIFF_SEP = '|';
|
|
|
|
/**
|
|
* No file type determined.
|
|
*/
|
|
public static final int TYPE_NOFILE = 0;
|
|
/**
|
|
* A regular file.
|
|
*/
|
|
public static final int TYPE_REG = 1;
|
|
/**
|
|
* A directory.
|
|
*/
|
|
public static final int TYPE_DIR = 2;
|
|
/**
|
|
* A character device.
|
|
*/
|
|
public static final int TYPE_CHR = 3;
|
|
/**
|
|
* A block device.
|
|
*/
|
|
public static final int TYPE_BLK = 4;
|
|
/**
|
|
* A FIFO / pipe.
|
|
*/
|
|
public static final int TYPE_PIPE = 5;
|
|
/**
|
|
* A symbolic link.
|
|
*/
|
|
public static final int TYPE_LNK = 6;
|
|
/**
|
|
* A [unix domain] socket.
|
|
*/
|
|
public static final int TYPE_SOCK = 7;
|
|
/**
|
|
* A file of unknown type.
|
|
*/
|
|
public static final int TYPE_UNKFILE = 8;
|
|
|
|
/**
|
|
* Readable by user.
|
|
*/
|
|
public static final int MODE_UREAD = 0x0400;
|
|
/**
|
|
* Writable by user.
|
|
*/
|
|
public static final int MODE_UWRITE = 0x0200;
|
|
/**
|
|
* Executable by user.
|
|
*/
|
|
public static final int MODE_UEXECUTE = 0x0100;
|
|
|
|
/**
|
|
* Readable by group.
|
|
*/
|
|
public static final int MODE_GREAD = 0x0040;
|
|
/**
|
|
* Writable by group.
|
|
*/
|
|
public static final int MODE_GWRITE = 0x0020;
|
|
/**
|
|
* Executable by group.
|
|
*/
|
|
public static final int MODE_GEXECUTE = 0x0010;
|
|
|
|
/**
|
|
* Readable by others.
|
|
*/
|
|
public static final int MODE_WREAD = 0x0004;
|
|
/**
|
|
* Writable by others.
|
|
*/
|
|
public static final int MODE_WWRITE = 0x0002;
|
|
/**
|
|
* Executable by others.
|
|
*/
|
|
public static final int MODE_WEXECUTE = 0x0001;
|
|
|
|
private static native String getTypeString(int type);
|
|
|
|
native void gatherLink(Sigar sigar, String name)
|
|
throws SigarException;
|
|
|
|
public String getTypeString() {
|
|
return FileInfo.getTypeString(this.type);
|
|
}
|
|
|
|
public char getTypeChar() {
|
|
switch (this.type) {
|
|
case TYPE_DIR:
|
|
return 'd';
|
|
case TYPE_CHR:
|
|
return 'c';
|
|
case TYPE_BLK:
|
|
return 'b';
|
|
case TYPE_PIPE:
|
|
return 'p';
|
|
case TYPE_LNK:
|
|
return 'l';
|
|
case TYPE_SOCK:
|
|
return 's';
|
|
default:
|
|
return '-';
|
|
}
|
|
}
|
|
|
|
public String getName() {
|
|
return this.name;
|
|
}
|
|
|
|
public int hashCode() {
|
|
return this.name.hashCode();
|
|
}
|
|
|
|
public boolean equals(Object o) {
|
|
return o.equals(this.name);
|
|
}
|
|
|
|
private static native String getPermissionsString(long type);
|
|
|
|
public String getPermissionsString() {
|
|
return FileInfo.getPermissionsString(this.permissions);
|
|
}
|
|
|
|
private static native int getMode(long permissions);
|
|
|
|
/**
|
|
* Convert permissions bit mask to human readable number.
|
|
* Example:
|
|
* <code>MODE_UREAD|MODE_UWRITE|MODE_GREAD|MODE_WREAD</code>
|
|
* converts to <code>644</code>.
|
|
* @return The file permissions mode.
|
|
*/
|
|
public int getMode() {
|
|
return FileInfo.getMode(this.permissions);
|
|
}
|
|
|
|
public void enableDirStat(boolean value) {
|
|
this.dirStatEnabled = value;
|
|
if (value) {
|
|
if (this.type != TYPE_DIR) {
|
|
throw new IllegalArgumentException(this.name + " is not a directory");
|
|
}
|
|
|
|
try {
|
|
if (this.stat == null) {
|
|
this.stat = this.sigar.getDirStat(this.name);
|
|
}
|
|
else {
|
|
this.stat.gather(this.sigar, this.name);
|
|
}
|
|
} catch (SigarException e) {
|
|
//ok for now
|
|
}
|
|
}
|
|
}
|
|
|
|
private class Diff {
|
|
private String attr, old, cur;
|
|
|
|
Diff(String attr, String old, String cur) {
|
|
this.attr = attr;
|
|
this.old = old;
|
|
this.cur = cur;
|
|
}
|
|
|
|
Diff(String attr, int old, int cur) {
|
|
this(attr,
|
|
String.valueOf(old),
|
|
String.valueOf(cur));
|
|
}
|
|
|
|
Diff(String attr, long old, long cur) {
|
|
this(attr,
|
|
String.valueOf(old),
|
|
String.valueOf(cur));
|
|
}
|
|
|
|
public String toString() {
|
|
return this.attr + ": " +
|
|
this.old + "|" + this.cur;
|
|
}
|
|
}
|
|
|
|
private StringBuffer format(ArrayList changes) {
|
|
StringBuffer sb = new StringBuffer();
|
|
|
|
if (changes.size() == 0) {
|
|
return sb;
|
|
}
|
|
|
|
int size = changes.size();
|
|
for (int i=0; i<size; i++) {
|
|
sb.append('{').append(changes.get(i)).append('}');
|
|
}
|
|
|
|
return sb;
|
|
}
|
|
|
|
private static String formatDate(long time) {
|
|
return DATE_FORMAT.format(new Date(time));
|
|
}
|
|
|
|
public String diff() {
|
|
if (this.oldInfo == null) {
|
|
return "";
|
|
}
|
|
return diff(this.oldInfo);
|
|
}
|
|
|
|
public String diff(DirStat stat) {
|
|
DirStat thisStat = this.stat;
|
|
ArrayList changes = new ArrayList();
|
|
|
|
if (thisStat.files != stat.files) {
|
|
changes.add(new Diff("Files",
|
|
stat.getFiles(),
|
|
thisStat.getFiles()));
|
|
}
|
|
|
|
if (thisStat.subdirs != stat.subdirs) {
|
|
changes.add(new Diff("Subdirs",
|
|
stat.getSubdirs(),
|
|
thisStat.getSubdirs()));
|
|
}
|
|
|
|
if (thisStat.symlinks != stat.symlinks) {
|
|
changes.add(new Diff("Symlinks",
|
|
stat.getSymlinks(),
|
|
thisStat.getSymlinks()));
|
|
}
|
|
|
|
if (thisStat.chrdevs != stat.chrdevs) {
|
|
changes.add(new Diff("Chrdevs",
|
|
stat.getChrdevs(),
|
|
thisStat.getChrdevs()));
|
|
}
|
|
|
|
if (thisStat.blkdevs != stat.blkdevs) {
|
|
changes.add(new Diff("Blkdevs",
|
|
stat.getBlkdevs(),
|
|
thisStat.getBlkdevs()));
|
|
}
|
|
|
|
if (thisStat.sockets != stat.sockets) {
|
|
changes.add(new Diff("Sockets",
|
|
stat.getSockets(),
|
|
thisStat.getSockets()));
|
|
}
|
|
|
|
if (thisStat.total != stat.total) {
|
|
changes.add(new Diff("Total",
|
|
stat.getTotal(),
|
|
thisStat.getTotal()));
|
|
}
|
|
|
|
return format(changes).toString();
|
|
}
|
|
|
|
public String diff(FileInfo info) {
|
|
ArrayList changes = new ArrayList();
|
|
|
|
if (this.getMtime() != info.getMtime()) {
|
|
changes.add(new Diff("Mtime",
|
|
formatDate(info.getMtime()),
|
|
formatDate(this.getMtime())));
|
|
}
|
|
else if (this.getCtime() != info.getCtime()) {
|
|
changes.add(new Diff("Ctime",
|
|
formatDate(info.getCtime()),
|
|
formatDate(this.getCtime())));
|
|
}
|
|
else {
|
|
//no point in checking the rest if all times are the same.
|
|
//or should we include atime in the diff?
|
|
return "";
|
|
}
|
|
|
|
if (this.getPermissions() != info.getPermissions()) {
|
|
changes.add(new Diff("Perms",
|
|
info.getPermissionsString(),
|
|
this.getPermissionsString()));
|
|
}
|
|
|
|
if (this.getType() != info.getType()) {
|
|
changes.add(new Diff("Type",
|
|
info.getTypeString(),
|
|
this.getTypeString()));
|
|
}
|
|
|
|
if (this.getUid() != info.getUid()) {
|
|
changes.add(new Diff("Uid",
|
|
info.getUid(),
|
|
this.getUid()));
|
|
}
|
|
|
|
if (this.getGid() != info.getGid()) {
|
|
changes.add(new Diff("Gid",
|
|
info.getGid(),
|
|
this.getGid()));
|
|
}
|
|
|
|
if (this.getSize() != info.getSize()) {
|
|
changes.add(new Diff("Size",
|
|
info.getSize(),
|
|
this.getSize()));
|
|
}
|
|
|
|
if (!OperatingSystem.IS_WIN32) {
|
|
if (this.getInode() != info.getInode()) {
|
|
changes.add(new Diff("Inode",
|
|
info.getInode(),
|
|
this.getInode()));
|
|
}
|
|
|
|
if (this.getDevice() != info.getDevice()) {
|
|
changes.add(new Diff("Device",
|
|
info.getDevice(),
|
|
this.getDevice()));
|
|
}
|
|
|
|
if (this.getNlink() != info.getNlink()) {
|
|
changes.add(new Diff("Nlink",
|
|
info.getNlink(),
|
|
this.getNlink()));
|
|
}
|
|
}
|
|
|
|
StringBuffer sb = format(changes);
|
|
if (this.dirStatEnabled) {
|
|
sb.append(diff(info.stat));
|
|
}
|
|
|
|
return sb.toString();
|
|
}
|
|
|
|
public FileInfo getPreviousInfo() {
|
|
return this.oldInfo;
|
|
}
|
|
|
|
public boolean modified()
|
|
throws SigarException,
|
|
SigarFileNotFoundException {
|
|
|
|
if (this.oldInfo == null) {
|
|
this.oldInfo = new FileInfo();
|
|
if (this.dirStatEnabled) {
|
|
this.oldInfo.stat = new DirStat();
|
|
}
|
|
}
|
|
copyTo(this.oldInfo);
|
|
if (this.dirStatEnabled) {
|
|
this.stat.copyTo(this.oldInfo.stat);
|
|
}
|
|
|
|
stat();
|
|
|
|
return this.mtime != oldInfo.mtime;
|
|
}
|
|
|
|
public boolean changed()
|
|
throws SigarException,
|
|
SigarFileNotFoundException {
|
|
|
|
return modified() || (this.ctime != oldInfo.ctime);
|
|
}
|
|
|
|
public void stat()
|
|
throws SigarException,
|
|
SigarFileNotFoundException {
|
|
|
|
long mtime = this.mtime;
|
|
|
|
if (this.lstat) {
|
|
this.gatherLink(this.sigar, this.name);
|
|
}
|
|
else {
|
|
this.gather(this.sigar, this.name);
|
|
}
|
|
|
|
if (this.dirStatEnabled &&
|
|
(mtime != this.mtime)) //no need to fetch stat if unmodified.
|
|
{
|
|
this.stat.gather(this.sigar, this.name);
|
|
}
|
|
}
|
|
|
|
private static FileInfo fetchInfo(Sigar sigar, String name,
|
|
boolean followSymlinks)
|
|
throws SigarException {
|
|
|
|
FileInfo info = new FileInfo();
|
|
|
|
if (followSymlinks) {
|
|
info.gather(sigar, name);
|
|
info.lstat = false;
|
|
}
|
|
else {
|
|
info.gatherLink(sigar, name);
|
|
info.lstat = true;
|
|
}
|
|
|
|
info.sigar = sigar;
|
|
info.name = name;
|
|
return info;
|
|
}
|
|
|
|
static FileInfo fetchFileInfo(Sigar sigar, String name)
|
|
throws SigarException {
|
|
|
|
return fetchInfo(sigar, name, true);
|
|
}
|
|
|
|
static FileInfo fetchLinkInfo(Sigar sigar, String name)
|
|
throws SigarException {
|
|
|
|
return fetchInfo(sigar, name, false);
|
|
}
|
|
}
|