package freenet.support.io; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.Serializable; import freenet.client.async.ClientContext; import freenet.crypt.MasterSecret; import freenet.support.api.LockableRandomAccessBuffer; public class PaddedRandomAccessBuffer implements LockableRandomAccessBuffer, Serializable { private static final long serialVersionUID = 1L; final LockableRandomAccessBuffer raf; final long realSize; public PaddedRandomAccessBuffer(LockableRandomAccessBuffer raf, long realSize) { this.raf = raf; this.realSize = realSize; } @Override public long size() { return realSize; } @Override public void pread(long fileOffset, byte[] buf, int bufOffset, int length) throws IOException { if(fileOffset + length > realSize) throw new IOException("Length limit exceeded"); raf.pread(fileOffset, buf, bufOffset, length); } @Override public void pwrite(long fileOffset, byte[] buf, int bufOffset, int length) throws IOException { if(fileOffset + length > realSize) throw new IOException("Length limit exceeded"); raf.pwrite(fileOffset, buf, bufOffset, length); } @Override public void close() { raf.close(); } @Override public void free() { raf.free(); } @Override public RAFLock lockOpen() throws IOException { return raf.lockOpen(); } @Override public void onResume(ClientContext context) throws ResumeFailedException { raf.onResume(context); } static final int MAGIC = 0x1eaaf330; @Override public void storeTo(DataOutputStream dos) throws IOException { dos.writeInt(MAGIC); dos.writeLong(realSize); raf.storeTo(dos); } public PaddedRandomAccessBuffer(DataInputStream dis, FilenameGenerator fg, PersistentFileTracker persistentFileTracker, MasterSecret masterSecret) throws ResumeFailedException, IOException, StorageFormatException { realSize = dis.readLong(); if(realSize < 0) throw new StorageFormatException("Negative length"); raf = BucketTools.restoreRAFFrom(dis, fg, persistentFileTracker, masterSecret); if(realSize > raf.size()) throw new ResumeFailedException("Padded file is smaller than expected length"); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + raf.hashCode(); result = prime * result + (int) (realSize ^ (realSize >>> 32)); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } PaddedRandomAccessBuffer other = (PaddedRandomAccessBuffer) obj; if (!raf.equals(other.raf)) { return false; } if (realSize != other.realSize) { return false; } return true; } }