mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-09-27 06:38:20 +00:00
e85cdacbc5
Added the complete source code to ComputerCraft 1.79 for Minecraft 1.8.9, plus newly written README and LICENSE files for the open source release.
387 lines
7.3 KiB
Java
387 lines
7.3 KiB
Java
/**
|
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
|
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
|
|
* Send enquiries to dratcliffe@gmail.com
|
|
*/
|
|
|
|
package dan200.computercraft.core.filesystem;
|
|
|
|
import dan200.computercraft.api.filesystem.IWritableMount;
|
|
|
|
import java.io.*;
|
|
import java.util.List;
|
|
|
|
public class FileMount implements IWritableMount
|
|
{
|
|
private static int MINIMUM_FILE_SIZE = 500;
|
|
|
|
private class CountingOutputStream extends OutputStream
|
|
{
|
|
private OutputStream m_innerStream;
|
|
private long m_ignoredBytesLeft;
|
|
|
|
public CountingOutputStream( OutputStream innerStream, long bytesToIgnore )
|
|
{
|
|
m_innerStream = innerStream;
|
|
m_ignoredBytesLeft = bytesToIgnore;
|
|
}
|
|
|
|
@Override
|
|
public void close() throws IOException
|
|
{
|
|
m_innerStream.close();
|
|
}
|
|
|
|
@Override
|
|
public void flush() throws IOException
|
|
{
|
|
m_innerStream.flush();
|
|
}
|
|
|
|
@Override
|
|
public void write( byte[] b ) throws IOException
|
|
{
|
|
count( b.length );
|
|
m_innerStream.write( b );
|
|
}
|
|
|
|
@Override
|
|
public void write( byte[] b, int off, int len ) throws IOException
|
|
{
|
|
count( len );
|
|
m_innerStream.write( b, off, len );
|
|
}
|
|
|
|
@Override
|
|
public void write( int b ) throws IOException
|
|
{
|
|
count( 1 );
|
|
m_innerStream.write( b );
|
|
}
|
|
|
|
private void count( long n ) throws IOException
|
|
{
|
|
m_ignoredBytesLeft -= n;
|
|
if( m_ignoredBytesLeft < 0 )
|
|
{
|
|
long newBytes = -m_ignoredBytesLeft;
|
|
m_ignoredBytesLeft = 0;
|
|
|
|
long bytesLeft = m_capacity - m_usedSpace;
|
|
if( newBytes > bytesLeft )
|
|
{
|
|
throw new IOException( "Out of space" );
|
|
}
|
|
else
|
|
{
|
|
m_usedSpace += newBytes;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private File m_rootPath;
|
|
private long m_capacity;
|
|
private long m_usedSpace;
|
|
|
|
public FileMount( File rootPath, long capacity )
|
|
{
|
|
m_rootPath = rootPath;
|
|
m_capacity = capacity + MINIMUM_FILE_SIZE;
|
|
m_usedSpace = created() ? measureUsedSpace( m_rootPath ) : MINIMUM_FILE_SIZE;
|
|
}
|
|
|
|
// IMount implementation
|
|
|
|
@Override
|
|
public boolean exists( String path ) throws IOException
|
|
{
|
|
if( !created() )
|
|
{
|
|
return path.length() == 0;
|
|
}
|
|
else
|
|
{
|
|
File file = getRealPath( path );
|
|
return file.exists();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isDirectory( String path ) throws IOException
|
|
{
|
|
if( !created() )
|
|
{
|
|
return path.length() == 0;
|
|
}
|
|
else
|
|
{
|
|
File file = getRealPath( path );
|
|
return file.exists() && file.isDirectory();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void list( String path, List<String> contents ) throws IOException
|
|
{
|
|
if( !created() )
|
|
{
|
|
if( path.length() != 0 )
|
|
{
|
|
throw new IOException( "Not a directory" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
File file = getRealPath( path );
|
|
if( file.exists() && file.isDirectory() )
|
|
{
|
|
String[] paths = file.list();
|
|
for( String subPath : paths )
|
|
{
|
|
if( new File( file, subPath ).exists() )
|
|
{
|
|
contents.add( subPath );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new IOException( "Not a directory" );
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public long getSize( String path ) throws IOException
|
|
{
|
|
if( !created() )
|
|
{
|
|
if( path.length() == 0 )
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
File file = getRealPath( path );
|
|
if( file.exists() )
|
|
{
|
|
if( file.isDirectory() )
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return file.length();
|
|
}
|
|
}
|
|
}
|
|
throw new IOException( "No such file" );
|
|
}
|
|
|
|
@Override
|
|
public InputStream openForRead( String path ) throws IOException
|
|
{
|
|
if( created() )
|
|
{
|
|
File file = getRealPath( path );
|
|
if( file.exists() && !file.isDirectory() )
|
|
{
|
|
return new FileInputStream( file );
|
|
}
|
|
}
|
|
throw new IOException( "No such file" );
|
|
}
|
|
|
|
// IWritableMount implementation
|
|
|
|
@Override
|
|
public void makeDirectory( String path ) throws IOException
|
|
{
|
|
create();
|
|
File file = getRealPath( path );
|
|
if( file.exists() )
|
|
{
|
|
if( !file.isDirectory() )
|
|
{
|
|
throw new IOException( "File exists" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int dirsToCreate = 1;
|
|
File parent = file.getParentFile();
|
|
while( !parent.exists() )
|
|
{
|
|
++dirsToCreate;
|
|
parent = parent.getParentFile();
|
|
}
|
|
|
|
if( getRemainingSpace() < dirsToCreate * MINIMUM_FILE_SIZE )
|
|
{
|
|
throw new IOException( "Out of space" );
|
|
}
|
|
|
|
boolean success = file.mkdirs();
|
|
if( success )
|
|
{
|
|
m_usedSpace += dirsToCreate * MINIMUM_FILE_SIZE;
|
|
}
|
|
else
|
|
{
|
|
throw new IOException( "Access denied" );
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void delete( String path ) throws IOException
|
|
{
|
|
if( path.length() == 0 )
|
|
{
|
|
throw new IOException( "Access denied" );
|
|
}
|
|
|
|
if( created() )
|
|
{
|
|
File file = getRealPath( path );
|
|
if( file.exists() )
|
|
{
|
|
deleteRecursively( file );
|
|
}
|
|
}
|
|
}
|
|
|
|
private void deleteRecursively( File file ) throws IOException
|
|
{
|
|
// Empty directories first
|
|
if( file.isDirectory() )
|
|
{
|
|
String[] children = file.list();
|
|
for( int i=0; i<children.length; i++ )
|
|
{
|
|
deleteRecursively( new File( file, children[i] ) );
|
|
}
|
|
}
|
|
|
|
// Then delete
|
|
long fileSize = file.isDirectory() ? 0 : file.length();
|
|
boolean success = file.delete();
|
|
if( success )
|
|
{
|
|
m_usedSpace -= Math.max( MINIMUM_FILE_SIZE, fileSize );
|
|
}
|
|
else
|
|
{
|
|
throw new IOException( "Access denied" );
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public OutputStream openForWrite( String path ) throws IOException
|
|
{
|
|
create();
|
|
File file = getRealPath( path );
|
|
if( file.exists() && file.isDirectory() )
|
|
{
|
|
throw new IOException( "Cannot write to directory" );
|
|
}
|
|
else
|
|
{
|
|
if( !file.exists() )
|
|
{
|
|
if( getRemainingSpace() < MINIMUM_FILE_SIZE )
|
|
{
|
|
throw new IOException( "Out of space" );
|
|
}
|
|
else
|
|
{
|
|
m_usedSpace += MINIMUM_FILE_SIZE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_usedSpace -= Math.max( file.length(), MINIMUM_FILE_SIZE );
|
|
m_usedSpace += MINIMUM_FILE_SIZE;
|
|
}
|
|
return new CountingOutputStream( new FileOutputStream( file, false ), MINIMUM_FILE_SIZE );
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public OutputStream openForAppend( String path ) throws IOException
|
|
{
|
|
if( created() )
|
|
{
|
|
File file = getRealPath( path );
|
|
if( !file.exists() )
|
|
{
|
|
throw new IOException( "No such file" );
|
|
}
|
|
else if( file.isDirectory() )
|
|
{
|
|
throw new IOException( "Cannot write to directory" );
|
|
}
|
|
else
|
|
{
|
|
return new CountingOutputStream( new FileOutputStream( file, true ), Math.max( MINIMUM_FILE_SIZE - file.length(), 0 ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new IOException( "No such file" );
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public long getRemainingSpace() throws IOException
|
|
{
|
|
return Math.max( m_capacity - m_usedSpace, 0 );
|
|
}
|
|
|
|
public File getRealPath( String path )
|
|
{
|
|
return new File( m_rootPath, path );
|
|
}
|
|
|
|
private boolean created()
|
|
{
|
|
return m_rootPath.exists();
|
|
}
|
|
|
|
private void create() throws IOException
|
|
{
|
|
if( !m_rootPath.exists() )
|
|
{
|
|
boolean success = m_rootPath.mkdirs();
|
|
if( !success )
|
|
{
|
|
throw new IOException( "Access denied" );
|
|
}
|
|
}
|
|
}
|
|
|
|
private long measureUsedSpace( File file )
|
|
{
|
|
if( !file.exists() )
|
|
{
|
|
return 0;
|
|
}
|
|
if( file.isDirectory() )
|
|
{
|
|
long size = MINIMUM_FILE_SIZE;
|
|
String[] contents = file.list();
|
|
for( int i=0; i<contents.length; ++i )
|
|
{
|
|
size += measureUsedSpace( new File( file, contents[i] ) );
|
|
}
|
|
return size;
|
|
}
|
|
else
|
|
{
|
|
return Math.max( file.length(), MINIMUM_FILE_SIZE );
|
|
}
|
|
}
|
|
}
|