feat: implement bulk of fs
This commit is contained in:
parent
7ecb8bfabb
commit
3e25068219
@ -1,7 +1,13 @@
|
||||
package me.topchetoeu.jscript.filesystem;
|
||||
|
||||
public enum EntryType {
|
||||
NONE,
|
||||
FILE,
|
||||
FOLDER,
|
||||
NONE("none"),
|
||||
FILE("file"),
|
||||
FOLDER("folder");
|
||||
|
||||
public final String name;
|
||||
|
||||
private EntryType(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
@ -1,27 +1,39 @@
|
||||
package me.topchetoeu.jscript.filesystem;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface File {
|
||||
int read() throws IOException, InterruptedException;
|
||||
boolean write(byte val) throws IOException, InterruptedException;
|
||||
long tell() throws IOException, InterruptedException;
|
||||
void seek(long offset, int pos) throws IOException, InterruptedException;
|
||||
void close() throws IOException, InterruptedException;
|
||||
Permissions perms();
|
||||
int read(byte[] buff);
|
||||
void write(byte[] buff);
|
||||
long getPtr();
|
||||
void setPtr(long offset, int pos);
|
||||
void close();
|
||||
Mode mode();
|
||||
|
||||
default String readToString() throws IOException, InterruptedException {
|
||||
seek(0, 2);
|
||||
long len = tell();
|
||||
default String readToString() {
|
||||
setPtr(0, 2);
|
||||
long len = getPtr();
|
||||
if (len < 0) return null;
|
||||
|
||||
seek(0, 0);
|
||||
byte[] res = new byte[(int)len];
|
||||
setPtr(0, 0);
|
||||
|
||||
for (var i = 0; i < len; i++) {
|
||||
res[i] = (byte)read();
|
||||
}
|
||||
byte[] res = new byte[(int)len];
|
||||
read(res);
|
||||
|
||||
return new String(res);
|
||||
}
|
||||
default String readLine() {
|
||||
var res = new Buffer(new byte[0]);
|
||||
var buff = new byte[1];
|
||||
|
||||
while (true) {
|
||||
if (read(buff) == 0) {
|
||||
if (res.length() == 0) return null;
|
||||
else break;
|
||||
}
|
||||
|
||||
if (buff[0] == '\n') break;
|
||||
|
||||
res.write(res.length(), buff);
|
||||
}
|
||||
return new String(res.data());
|
||||
}
|
||||
}
|
11
src/me/topchetoeu/jscript/filesystem/FileStat.java
Normal file
11
src/me/topchetoeu/jscript/filesystem/FileStat.java
Normal file
@ -0,0 +1,11 @@
|
||||
package me.topchetoeu.jscript.filesystem;
|
||||
|
||||
public class FileStat {
|
||||
public final Mode mode;
|
||||
public final EntryType type;
|
||||
|
||||
public FileStat(Mode mode, EntryType type) {
|
||||
this.mode = mode;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
@ -1,10 +1,7 @@
|
||||
package me.topchetoeu.jscript.filesystem;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface Filesystem {
|
||||
File open(String path) throws IOException, InterruptedException;
|
||||
boolean mkdir(String path) throws IOException, InterruptedException;
|
||||
EntryType type(String path) throws IOException, InterruptedException;
|
||||
boolean rm(String path) throws IOException, InterruptedException;
|
||||
File open(String path, Mode mode) throws FilesystemException;
|
||||
void create(String path, EntryType type) throws FilesystemException;
|
||||
FileStat stat(String path) throws FilesystemException;
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package me.topchetoeu.jscript.filesystem;
|
||||
|
||||
import me.topchetoeu.jscript.engine.values.Values;
|
||||
import me.topchetoeu.jscript.exceptions.EngineException;
|
||||
|
||||
public class FilesystemException extends RuntimeException {
|
||||
public static enum FSCode {
|
||||
DOESNT_EXIST(0x1),
|
||||
NOT_FILE(0x2),
|
||||
NOT_FOLDER(0x3),
|
||||
NO_PERMISSIONS_R(0x4),
|
||||
NO_PERMISSIONS_RW(0x5),
|
||||
FOLDER_NOT_EMPTY(0x6),
|
||||
ALREADY_EXISTS(0x7),
|
||||
FOLDER_EXISTS(0x8);
|
||||
|
||||
public final int code;
|
||||
|
||||
private FSCode(int code) { this.code = code; }
|
||||
}
|
||||
|
||||
public static final String[] MESSAGES = {
|
||||
"How did we get here?",
|
||||
"The file or folder '%s' doesn't exist or is inaccessible.",
|
||||
"'%s' is not a file",
|
||||
"'%s' is not a folder",
|
||||
"No permissions to read '%s'",
|
||||
"No permissions to write '%s'",
|
||||
"Can't delete '%s', since it is a full folder.",
|
||||
"'%s' already exists."
|
||||
};
|
||||
|
||||
public final String message, filename;
|
||||
public final FSCode code;
|
||||
|
||||
public FilesystemException(String message, String filename, FSCode code) {
|
||||
super(code + ": " + message.formatted(filename));
|
||||
this.message = message;
|
||||
this.code = code;
|
||||
this.filename = filename;
|
||||
}
|
||||
public FilesystemException(String filename, FSCode code) {
|
||||
super(code + ": " + MESSAGES[code.code].formatted(filename));
|
||||
this.message = MESSAGES[code.code];
|
||||
this.code = code;
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public EngineException toEngineException() {
|
||||
var res = EngineException.ofError("IOError", getMessage());
|
||||
Values.setMember(null, res.value, "code", code);
|
||||
Values.setMember(null, res.value, "filename", filename.toString());
|
||||
return res;
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
package me.topchetoeu.jscript.filesystem;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class InaccessibleFile implements File {
|
||||
public static final InaccessibleFile INSTANCE = new InaccessibleFile();
|
||||
|
||||
@Override
|
||||
public int read() throws IOException, InterruptedException {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean write(byte val) throws IOException, InterruptedException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long tell() throws IOException, InterruptedException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seek(long offset, int pos) throws IOException, InterruptedException { }
|
||||
|
||||
@Override
|
||||
public void close() throws IOException, InterruptedException { }
|
||||
|
||||
@Override
|
||||
public Permissions perms() {
|
||||
return Permissions.NONE;
|
||||
}
|
||||
|
||||
private InaccessibleFile() { }
|
||||
}
|
31
src/me/topchetoeu/jscript/filesystem/Mode.java
Normal file
31
src/me/topchetoeu/jscript/filesystem/Mode.java
Normal file
@ -0,0 +1,31 @@
|
||||
package me.topchetoeu.jscript.filesystem;
|
||||
|
||||
public enum Mode {
|
||||
NONE("", false, false),
|
||||
READ("r", true, false),
|
||||
READ_WRITE("rw", true, true);
|
||||
|
||||
public final String name;
|
||||
public final boolean readable;
|
||||
public final boolean writable;
|
||||
|
||||
public Mode intersect(Mode other) {
|
||||
if (this == NONE || other == NONE) return NONE;
|
||||
if (this == READ_WRITE && other == READ_WRITE) return READ_WRITE;
|
||||
return READ;
|
||||
}
|
||||
|
||||
private Mode(String mode, boolean r, boolean w) {
|
||||
this.name = mode;
|
||||
this.readable = r;
|
||||
this.writable = w;
|
||||
}
|
||||
|
||||
public static Mode parse(String mode) {
|
||||
switch (mode) {
|
||||
case "r": return READ;
|
||||
case "rw": return READ_WRITE;
|
||||
default: return NONE;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package me.topchetoeu.jscript.filesystem;
|
||||
|
||||
public enum Permissions {
|
||||
NONE("", false, false),
|
||||
READ("r", true, false),
|
||||
READ_WRITE("rw", true, true);
|
||||
|
||||
public final String readMode;
|
||||
public final boolean readable;
|
||||
public final boolean writable;
|
||||
|
||||
private Permissions(String mode, boolean r, boolean w) {
|
||||
this.readMode = mode;
|
||||
this.readable = r;
|
||||
this.writable = w;
|
||||
}
|
||||
}
|
@ -1,50 +1,62 @@
|
||||
package me.topchetoeu.jscript.filesystem;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
import me.topchetoeu.jscript.filesystem.FilesystemException.FSCode;
|
||||
|
||||
public class PhysicalFile implements File {
|
||||
private String filename;
|
||||
private RandomAccessFile file;
|
||||
private Permissions perms;
|
||||
private Mode perms;
|
||||
|
||||
@Override
|
||||
public int read() throws IOException, InterruptedException {
|
||||
if (file == null || !perms.readable) return -1;
|
||||
else return file.read();
|
||||
public int read(byte[] buff) {
|
||||
if (file == null || !perms.readable) throw new FilesystemException(filename, FSCode.NO_PERMISSIONS_R);
|
||||
else try { return file.read(buff); }
|
||||
catch (IOException e) { throw new FilesystemException(filename, FSCode.NO_PERMISSIONS_R); }
|
||||
}
|
||||
@Override
|
||||
public void write(byte[] buff) {
|
||||
if (file == null || !perms.writable) throw new FilesystemException(filename, FSCode.NO_PERMISSIONS_RW);
|
||||
else try { file.write(buff); }
|
||||
catch (IOException e) { throw new FilesystemException(filename, FSCode.NO_PERMISSIONS_RW); }
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean write(byte val) throws IOException, InterruptedException {
|
||||
if (file == null || !perms.writable) return false;
|
||||
file.write(val);
|
||||
return true;
|
||||
public long getPtr() {
|
||||
if (file == null || !perms.readable) throw new FilesystemException(filename, FSCode.NO_PERMISSIONS_R);
|
||||
else try { return file.getFilePointer(); }
|
||||
catch (IOException e) { throw new FilesystemException(filename, FSCode.NO_PERMISSIONS_R); }
|
||||
}
|
||||
@Override
|
||||
public void setPtr(long offset, int pos) {
|
||||
if (file == null || !perms.readable) throw new FilesystemException(filename, FSCode.NO_PERMISSIONS_R);
|
||||
|
||||
try {
|
||||
if (pos == 1) pos += file.getFilePointer();
|
||||
else if (pos == 2) pos += file.length();
|
||||
file.seek(pos);
|
||||
}
|
||||
catch (IOException e) { throw new FilesystemException(filename, FSCode.NO_PERMISSIONS_R); }
|
||||
}
|
||||
|
||||
@Override
|
||||
public long tell() throws IOException, InterruptedException {
|
||||
if (file == null) return 0;
|
||||
return file.getFilePointer();
|
||||
}
|
||||
@Override
|
||||
public void seek(long offset, int pos) throws IOException, InterruptedException {
|
||||
public void close() {
|
||||
if (file == null) return;
|
||||
if (pos == 0) file.seek(pos);
|
||||
else if (pos == 1) file.seek(file.getFilePointer() + pos);
|
||||
else if (pos == 2) file.seek(file.length() + pos);
|
||||
try { file.close(); }
|
||||
catch (IOException e) {} // SHUT
|
||||
file = null;
|
||||
perms = Mode.NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException, InterruptedException {
|
||||
if (file == null) return;
|
||||
file.close();
|
||||
}
|
||||
public Mode mode() { return perms; }
|
||||
|
||||
@Override
|
||||
public Permissions perms() { return perms; }
|
||||
|
||||
public PhysicalFile(String path, Permissions mode) throws IOException {
|
||||
if (mode == Permissions.NONE) file = null;
|
||||
else file = new RandomAccessFile(path, mode.readMode);
|
||||
public PhysicalFile(String path, Mode mode) throws FileNotFoundException {
|
||||
if (mode == Mode.NONE) file = null;
|
||||
else try { file = new RandomAccessFile(path, mode.name); }
|
||||
catch (FileNotFoundException e) { throw new FilesystemException(filename, FSCode.DOESNT_EXIST); }
|
||||
|
||||
perms = mode;
|
||||
}
|
||||
|
@ -1,74 +1,75 @@
|
||||
package me.topchetoeu.jscript.filesystem;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import me.topchetoeu.jscript.filesystem.FilesystemException.FSCode;
|
||||
|
||||
public class PhysicalFilesystem implements Filesystem {
|
||||
public final Path root;
|
||||
|
||||
private Permissions getPerms(Path path) {
|
||||
var file = path.toFile();
|
||||
if (!path.startsWith(root)) return Permissions.NONE;
|
||||
if (file.canRead() && file.canWrite()) return Permissions.READ_WRITE;
|
||||
if (file.canRead()) return Permissions.READ;
|
||||
|
||||
return Permissions.NONE;
|
||||
}
|
||||
private Path getPath(String name) {
|
||||
return root.resolve(name);
|
||||
return root.resolve(name.replace("\\", "/")).normalize();
|
||||
}
|
||||
|
||||
private void checkMode(Path path, Mode mode) {
|
||||
if (!path.startsWith(root)) throw new FilesystemException(path.toString(), FSCode.NO_PERMISSIONS_R);
|
||||
if (mode.readable && !path.toFile().canRead()) throw new FilesystemException(path.toString(), FSCode.NO_PERMISSIONS_R);
|
||||
if (mode.writable && !path.toFile().canWrite()) throw new FilesystemException(path.toString(), FSCode.NO_PERMISSIONS_RW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File open(String path) throws IOException, InterruptedException {
|
||||
var _path = root.resolve(path);
|
||||
|
||||
var perms = getPerms(_path);
|
||||
if (perms == Permissions.NONE) return InaccessibleFile.INSTANCE;
|
||||
|
||||
public File open(String path, Mode perms) {
|
||||
var _path = getPath(path);
|
||||
var f = _path.toFile();
|
||||
|
||||
if (f.isDirectory()) {
|
||||
var res = new StringBuilder();
|
||||
checkMode(_path, perms);
|
||||
|
||||
for (var child : f.listFiles()) res.append(child.toString()).append('\n');
|
||||
|
||||
return new MemoryFile(res.toString().getBytes(), Permissions.READ);
|
||||
if (f.isDirectory()) return MemoryFile.fromFileList(path, f.listFiles());
|
||||
else try { return new PhysicalFile(path, perms); }
|
||||
catch (FileNotFoundException e) { throw new FilesystemException(_path.toString(), FSCode.DOESNT_EXIST); }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(String path, EntryType type) {
|
||||
var _path = getPath(path);
|
||||
var f = _path.toFile();
|
||||
|
||||
checkMode(_path, Mode.READ_WRITE);
|
||||
switch (type) {
|
||||
case FILE:
|
||||
try {
|
||||
if (!f.createNewFile()) throw new FilesystemException(_path.toString(), FSCode.ALREADY_EXISTS);
|
||||
else break;
|
||||
}
|
||||
catch (IOException e) { throw new FilesystemException(_path.toString(), FSCode.NO_PERMISSIONS_RW); }
|
||||
case FOLDER:
|
||||
if (!f.mkdir()) throw new FilesystemException(_path.toString(), FSCode.ALREADY_EXISTS);
|
||||
else break;
|
||||
case NONE:
|
||||
default:
|
||||
if (!f.delete()) throw new FilesystemException(_path.toString(), FSCode.DOESNT_EXIST);
|
||||
else break;
|
||||
}
|
||||
else return new PhysicalFile(path, perms);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mkdir(String path) throws IOException, InterruptedException {
|
||||
public FileStat stat(String path) {
|
||||
var _path = getPath(path);
|
||||
var perms = getPerms(_path);
|
||||
var f = _path.toFile();
|
||||
|
||||
if (!perms.writable) return false;
|
||||
else return f.mkdir();
|
||||
}
|
||||
if (f.exists()) throw new FilesystemException(_path.toString(), FSCode.DOESNT_EXIST);
|
||||
checkMode(_path, Mode.READ);
|
||||
|
||||
@Override
|
||||
public EntryType type(String path) throws IOException, InterruptedException {
|
||||
var _path = getPath(path);
|
||||
var perms = getPerms(_path);
|
||||
var f = _path.toFile();
|
||||
|
||||
if (perms == Permissions.NONE) return EntryType.NONE;
|
||||
else if (f.isFile()) return EntryType.FILE;
|
||||
else return EntryType.FOLDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean rm(String path) throws IOException, InterruptedException {
|
||||
var _path = getPath(path);
|
||||
var perms = getPerms(_path);
|
||||
var f = _path.toFile();
|
||||
|
||||
if (!perms.writable) return false;
|
||||
else return f.delete();
|
||||
return new FileStat(
|
||||
f.canWrite() ? Mode.READ_WRITE : Mode.READ,
|
||||
f.isFile() ? EntryType.FILE : EntryType.FOLDER
|
||||
);
|
||||
}
|
||||
|
||||
public PhysicalFilesystem(Path root) {
|
||||
this.root = root;
|
||||
this.root = root.toAbsolutePath().normalize();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user