feat: implement memory and root fs
This commit is contained in:
parent
3e25068219
commit
55e3d46bc2
41
src/me/topchetoeu/jscript/filesystem/Buffer.java
Normal file
41
src/me/topchetoeu/jscript/filesystem/Buffer.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package me.topchetoeu.jscript.filesystem;
|
||||||
|
|
||||||
|
public class Buffer {
|
||||||
|
private byte[] data;
|
||||||
|
private int length;
|
||||||
|
|
||||||
|
public void write(int i, byte[] val) {
|
||||||
|
if (i + val.length > data.length) {
|
||||||
|
var newCap = i + val.length + 1;
|
||||||
|
if (newCap < data.length * 2) newCap = data.length * 2;
|
||||||
|
|
||||||
|
var tmp = new byte[newCap];
|
||||||
|
System.arraycopy(this.data, 0, tmp, 0, length);
|
||||||
|
this.data = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.arraycopy(val, 0, data, i, val.length);
|
||||||
|
if (i + val.length > length) length = i + val.length;
|
||||||
|
}
|
||||||
|
public int read(int i, byte[] buff) {
|
||||||
|
int n = buff.length;
|
||||||
|
if (i + n > length) n = length - i;
|
||||||
|
System.arraycopy(data, i, buff, 0, n);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] data() {
|
||||||
|
var res = new byte[length];
|
||||||
|
System.arraycopy(this.data, 0, res, 0, length);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
public int length() {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Buffer(byte[] data) {
|
||||||
|
this.data = new byte[data.length];
|
||||||
|
this.length = data.length;
|
||||||
|
System.arraycopy(data, 0, this.data, 0, data.length);
|
||||||
|
}
|
||||||
|
}
|
@ -1,53 +1,66 @@
|
|||||||
package me.topchetoeu.jscript.filesystem;
|
package me.topchetoeu.jscript.filesystem;
|
||||||
|
|
||||||
import java.io.IOException;
|
import me.topchetoeu.jscript.filesystem.FilesystemException.FSCode;
|
||||||
|
|
||||||
public class MemoryFile implements File {
|
public class MemoryFile implements File {
|
||||||
private int ptr;
|
private int ptr;
|
||||||
private Permissions mode;
|
private Mode mode;
|
||||||
public final byte[] data;
|
private Buffer data;
|
||||||
|
private String filename;
|
||||||
|
|
||||||
|
public Buffer data() { return data; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read() throws IOException, InterruptedException {
|
public int read(byte[] buff) {
|
||||||
if (data == null || !mode.readable || ptr >= data.length) return -1;
|
if (data == null || !mode.readable) throw new FilesystemException(filename, FSCode.NO_PERMISSIONS_R);
|
||||||
return data[ptr++];
|
var res = data.read(ptr, buff);
|
||||||
|
ptr += res;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void write(byte[] buff) {
|
||||||
|
if (data == null || !mode.writable) throw new FilesystemException(filename, FSCode.NO_PERMISSIONS_RW);
|
||||||
|
|
||||||
|
data.write(ptr, buff);
|
||||||
|
ptr += buff.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean write(byte val) throws IOException, InterruptedException {
|
public long getPtr() {
|
||||||
if (data == null || !mode.writable || ptr >= data.length) return false;
|
if (data == null || !mode.readable) throw new FilesystemException(filename, FSCode.NO_PERMISSIONS_R);
|
||||||
data[ptr++] = val;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long tell() throws IOException, InterruptedException {
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void seek(long offset, int pos) throws IOException, InterruptedException {
|
public void setPtr(long offset, int pos) {
|
||||||
if (data == null) return;
|
if (data == null || !mode.readable) throw new FilesystemException(filename, FSCode.NO_PERMISSIONS_R);
|
||||||
|
|
||||||
if (pos == 0) ptr = (int)offset;
|
if (pos == 0) ptr = (int)offset;
|
||||||
else if (pos == 1) ptr += (int)offset;
|
else if (pos == 1) ptr += (int)offset;
|
||||||
else if (pos == 2) ptr = data.length - (int)offset;
|
else if (pos == 2) ptr = data.length() - (int)offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException, InterruptedException {
|
public void close() {
|
||||||
mode = null;
|
mode = Mode.NONE;
|
||||||
ptr = 0;
|
ptr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Permissions perms() {
|
public Mode mode() {
|
||||||
if (data == null) return Permissions.NONE;
|
if (data == null) return Mode.NONE;
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MemoryFile(byte[] buff, Permissions mode) {
|
public MemoryFile(String filename, Buffer buff, Mode mode) {
|
||||||
|
this.filename = filename;
|
||||||
this.data = buff;
|
this.data = buff;
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MemoryFile fromFileList(String filename, java.io.File[] list) {
|
||||||
|
var res = new StringBuilder();
|
||||||
|
|
||||||
|
for (var el : list) res.append(el.getName()).append('\n');
|
||||||
|
|
||||||
|
return new MemoryFile(filename, new Buffer(res.toString().getBytes()), Mode.READ);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
89
src/me/topchetoeu/jscript/filesystem/MemoryFilesystem.java
Normal file
89
src/me/topchetoeu/jscript/filesystem/MemoryFilesystem.java
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
package me.topchetoeu.jscript.filesystem;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import me.topchetoeu.jscript.filesystem.FilesystemException.FSCode;
|
||||||
|
|
||||||
|
public class MemoryFilesystem implements Filesystem {
|
||||||
|
public final Mode mode;
|
||||||
|
private HashMap<Path, Buffer> files = new HashMap<>();
|
||||||
|
private HashSet<Path> folders = new HashSet<>();
|
||||||
|
|
||||||
|
private Path getPath(String name) {
|
||||||
|
return Path.of("/" + name.replace("\\", "/")).normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create(String path, EntryType type) {
|
||||||
|
var _path = getPath(path);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case FILE:
|
||||||
|
if (!folders.contains(_path.getParent())) throw new FilesystemException(path, FSCode.DOESNT_EXIST);
|
||||||
|
if (folders.contains(_path) || files.containsKey(_path)) throw new FilesystemException(path, FSCode.ALREADY_EXISTS);
|
||||||
|
if (folders.contains(_path)) throw new FilesystemException(path, FSCode.ALREADY_EXISTS);
|
||||||
|
files.put(_path, new Buffer(new byte[0]));
|
||||||
|
break;
|
||||||
|
case FOLDER:
|
||||||
|
if (!folders.contains(_path.getParent())) throw new FilesystemException(path, FSCode.DOESNT_EXIST);
|
||||||
|
if (folders.contains(_path) || files.containsKey(_path)) throw new FilesystemException(path, FSCode.ALREADY_EXISTS);
|
||||||
|
folders.add(_path);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case NONE:
|
||||||
|
if (!folders.remove(_path) && files.remove(_path) == null) throw new FilesystemException(path, FSCode.DOESNT_EXIST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File open(String path, Mode perms) {
|
||||||
|
var _path = getPath(path);
|
||||||
|
var pcount = _path.getNameCount();
|
||||||
|
|
||||||
|
if (files.containsKey(_path)) return new MemoryFile(path, files.get(_path), perms);
|
||||||
|
else if (folders.contains(_path)) {
|
||||||
|
var res = new StringBuilder();
|
||||||
|
for (var folder : folders) {
|
||||||
|
if (pcount + 1 != folder.getNameCount()) continue;
|
||||||
|
if (!folder.startsWith(_path)) continue;
|
||||||
|
res.append(folder.toFile().getName()).append('\n');
|
||||||
|
}
|
||||||
|
for (var file : files.keySet()) {
|
||||||
|
if (pcount + 1 != file.getNameCount()) continue;
|
||||||
|
if (!file.startsWith(_path)) continue;
|
||||||
|
res.append(file.toFile().getName()).append('\n');
|
||||||
|
}
|
||||||
|
return new MemoryFile(path, new Buffer(res.toString().getBytes()), perms.intersect(Mode.READ));
|
||||||
|
}
|
||||||
|
else throw new FilesystemException(path, FSCode.DOESNT_EXIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileStat stat(String path) {
|
||||||
|
var _path = getPath(path);
|
||||||
|
|
||||||
|
if (files.containsKey(_path)) return new FileStat(mode, EntryType.FILE);
|
||||||
|
else if (folders.contains(_path)) return new FileStat(mode, EntryType.FOLDER);
|
||||||
|
else throw new FilesystemException(path, FSCode.DOESNT_EXIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemoryFilesystem put(String path, byte[] data) {
|
||||||
|
var _path = getPath(path);
|
||||||
|
var _curr = "/";
|
||||||
|
|
||||||
|
for (var seg : _path) {
|
||||||
|
create(_curr, EntryType.FOLDER);
|
||||||
|
_curr += seg + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
files.put(_path, new Buffer(data));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemoryFilesystem(Mode mode) {
|
||||||
|
this.mode = mode;
|
||||||
|
folders.add(Path.of("/"));
|
||||||
|
}
|
||||||
|
}
|
60
src/me/topchetoeu/jscript/filesystem/RootFilesystem.java
Normal file
60
src/me/topchetoeu/jscript/filesystem/RootFilesystem.java
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package me.topchetoeu.jscript.filesystem;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import me.topchetoeu.jscript.Filename;
|
||||||
|
import me.topchetoeu.jscript.filesystem.FilesystemException.FSCode;
|
||||||
|
import me.topchetoeu.jscript.permissions.PermissionsManager;
|
||||||
|
|
||||||
|
public class RootFilesystem implements Filesystem {
|
||||||
|
public final Map<String, Filesystem> protocols = new HashMap<>();
|
||||||
|
public final PermissionsManager perms;
|
||||||
|
|
||||||
|
private boolean canRead(PermissionsManager perms, String _path) {
|
||||||
|
return perms.has("jscript.file.read:" + _path, '/');
|
||||||
|
}
|
||||||
|
private boolean canWrite(PermissionsManager perms, String _path) {
|
||||||
|
return perms.has("jscript.file.write:" + _path, '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
private void modeAllowed(String _path, Mode mode) throws FilesystemException {
|
||||||
|
if (mode.readable && perms != null && !canRead(perms, _path)) throw new FilesystemException(_path, FSCode.NO_PERMISSIONS_R);
|
||||||
|
if (mode.writable && perms != null && !canWrite(perms, _path)) throw new FilesystemException(_path, FSCode.NO_PERMISSIONS_RW);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File open(String path, Mode perms) throws FilesystemException {
|
||||||
|
var filename = Filename.parse(path);
|
||||||
|
var protocol = protocols.get(filename.protocol);
|
||||||
|
if (protocol == null) throw new FilesystemException(filename.toString(), FSCode.DOESNT_EXIST);
|
||||||
|
modeAllowed(filename.toString(), perms);
|
||||||
|
|
||||||
|
try { return protocol.open(filename.path, perms); }
|
||||||
|
catch (FilesystemException e) { throw new FilesystemException(filename.toString(), e.code); }
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void create(String path, EntryType type) throws FilesystemException {
|
||||||
|
var filename = Filename.parse(path);
|
||||||
|
var protocol = protocols.get(filename.protocol);
|
||||||
|
if (protocol == null) throw new FilesystemException(filename.toString(), FSCode.DOESNT_EXIST);
|
||||||
|
modeAllowed(filename.toString(), Mode.READ_WRITE);
|
||||||
|
|
||||||
|
try { protocol.create(filename.path, type); }
|
||||||
|
catch (FilesystemException e) { throw new FilesystemException(filename.toString(), e.code); }
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public FileStat stat(String path) throws FilesystemException {
|
||||||
|
var filename = Filename.parse(path);
|
||||||
|
var protocol = protocols.get(filename.protocol);
|
||||||
|
if (protocol == null) throw new FilesystemException(filename.toString(), FSCode.DOESNT_EXIST);
|
||||||
|
modeAllowed(filename.toString(), Mode.READ);
|
||||||
|
|
||||||
|
try { return protocol.stat(path); }
|
||||||
|
catch (FilesystemException e) { throw new FilesystemException(filename.toString(), e.code); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public RootFilesystem(PermissionsManager perms) {
|
||||||
|
this.perms = perms;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user