p1/machine/StubFileSystem.java

217 lines
4.5 KiB
Java

// PART OF THE MACHINE SIMULATION. DO NOT CHANGE.
package nachos.machine;
import nachos.security.*;
import nachos.threads.*;
import java.io.File;
import java.io.RandomAccessFile;
import java.io.IOException;
/**
* This class implements a file system that redirects all requests to the host
* operating system's file system.
*/
public class StubFileSystem implements FileSystem {
/**
* Allocate a new stub file system.
*
* @param privilege encapsulates privileged access to the Nachos
* machine.
* @param directory the root directory of the stub file system.
*/
public StubFileSystem(Privilege privilege, File directory) {
this.privilege = privilege;
this.directory = directory;
}
public OpenFile open(String name, boolean truncate) {
if (!checkName(name))
return null;
delay();
try {
return new StubOpenFile(name, truncate);
}
catch (IOException e) {
return null;
}
}
public boolean remove(String name) {
if (!checkName(name))
return false;
delay();
FileRemover fr = new FileRemover(new File(directory, name));
privilege.doPrivileged(fr);
return fr.successful;
}
private class FileRemover implements Runnable {
public FileRemover(File f) {
this.f = f;
}
public void run() {
successful = f.delete();
}
public boolean successful = false;
private File f;
}
private void delay() {
long time = Machine.timer().getTime();
int amount = 1000;
ThreadedKernel.alarm.waitUntil(amount);
Lib.assertTrue(Machine.timer().getTime() >= time+amount);
}
private class StubOpenFile extends OpenFileWithPosition {
StubOpenFile(final String name, final boolean truncate)
throws IOException {
super(StubFileSystem.this, name);
final File f = new File(directory, name);
if (openCount == maxOpenFiles)
throw new IOException();
privilege.doPrivileged(new Runnable() {
public void run() { getRandomAccessFile(f, truncate); }
});
if (file == null)
throw new IOException();
open = true;
openCount++;
}
private void getRandomAccessFile(File f, boolean truncate) {
try {
if (!truncate && !f.exists())
return;
file = new RandomAccessFile(f, "rw");
if (truncate)
file.setLength(0);
}
catch (IOException e) {
}
}
public int read(int pos, byte[] buf, int offset, int length) {
if (!open)
return -1;
try {
delay();
file.seek(pos);
return Math.max(0, file.read(buf, offset, length));
}
catch (IOException e) {
return -1;
}
}
public int write(int pos, byte[] buf, int offset, int length) {
if (!open)
return -1;
try {
delay();
file.seek(pos);
file.write(buf, offset, length);
return length;
}
catch (IOException e) {
return -1;
}
}
public int length() {
try {
return (int) file.length();
}
catch (IOException e) {
return -1;
}
}
public void close() {
if (open) {
open = false;
openCount--;
}
try {
file.close();
}
catch (IOException e) {
}
}
private RandomAccessFile file = null;
private boolean open = false;
}
private int openCount = 0;
private static final int maxOpenFiles = 16;
private Privilege privilege;
private File directory;
private static boolean checkName(String name) {
char[] chars = name.toCharArray();
for (int i=0; i<chars.length; i++) {
if (chars[i] < 0 || chars[i] >= allowedFileNameCharacters.length)
return false;
if (!allowedFileNameCharacters[(int) chars[i]])
return false;
}
return true;
}
private static boolean[] allowedFileNameCharacters = new boolean[0x80];
private static void reject(char c) {
allowedFileNameCharacters[c] = false;
}
private static void allow(char c) {
allowedFileNameCharacters[c] = true;
}
private static void reject(char first, char last) {
for (char c=first; c<=last; c++)
allowedFileNameCharacters[c] = false;
}
private static void allow(char first, char last) {
for (char c=first; c<=last; c++)
allowedFileNameCharacters[c] = true;
}
static {
reject((char) 0x00, (char) 0x7F);
allow('A', 'Z');
allow('a', 'z');
allow('0', '9');
allow('-');
allow('_');
allow('.');
allow(',');
}
}