From 4bc363485f6fb97042f14c7dbe8bf3517b6e40de Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Tue, 26 Dec 2023 14:01:31 +0200 Subject: [PATCH] fix: losts of FS API improvements --- src/me/topchetoeu/jscript/Filename.java | 11 +++-- .../jscript/filesystem/Filesystem.java | 3 +- .../jscript/filesystem/ListFile.java | 44 +++++++++--------- .../jscript/filesystem/MemoryFilesystem.java | 7 +-- .../topchetoeu/jscript/filesystem/Paths.java | 9 ++-- .../jscript/filesystem/PhysicalFile.java | 17 +++---- .../filesystem/PhysicalFilesystem.java | 22 ++++----- .../jscript/filesystem/RootFilesystem.java | 25 +++++----- src/me/topchetoeu/jscript/lib/FileLib.java | 22 +++------ .../topchetoeu/jscript/lib/FilesystemLib.java | 46 +++++++++++-------- 10 files changed, 100 insertions(+), 106 deletions(-) diff --git a/src/me/topchetoeu/jscript/Filename.java b/src/me/topchetoeu/jscript/Filename.java index 3138887..36e6a89 100644 --- a/src/me/topchetoeu/jscript/Filename.java +++ b/src/me/topchetoeu/jscript/Filename.java @@ -1,6 +1,7 @@ package me.topchetoeu.jscript; import java.io.File; +import java.nio.file.Path; public class Filename { public final String protocol; @@ -40,9 +41,7 @@ public class Filename { return true; } - public static Filename fromFile(File file) { - return new Filename("file", file.getAbsolutePath()); - } + public Filename(String protocol, String path) { @@ -57,4 +56,10 @@ public class Filename { if (i >= 0) return new Filename(val.substring(0, i).trim(), val.substring(i + 3).trim()); else return new Filename("file", val.trim()); } + public static Path normalize(String path) { + return Path.of(Path.of("/" + path.trim().replace("\\", "/")).normalize().toString().substring(1)); + } + public static Filename fromFile(File file) { + return new Filename("file", file.getAbsolutePath()); + } } diff --git a/src/me/topchetoeu/jscript/filesystem/Filesystem.java b/src/me/topchetoeu/jscript/filesystem/Filesystem.java index e75a00d..c21fb9e 100644 --- a/src/me/topchetoeu/jscript/filesystem/Filesystem.java +++ b/src/me/topchetoeu/jscript/filesystem/Filesystem.java @@ -1,8 +1,7 @@ package me.topchetoeu.jscript.filesystem; public interface Filesystem { - String cwd(String cwd, String path); - String normalize(String path); + String normalize(String... path); File open(String path, Mode mode) throws FilesystemException; void create(String path, EntryType type) throws FilesystemException; FileStat stat(String path) throws FilesystemException; diff --git a/src/me/topchetoeu/jscript/filesystem/ListFile.java b/src/me/topchetoeu/jscript/filesystem/ListFile.java index 8987ded..308f3bb 100644 --- a/src/me/topchetoeu/jscript/filesystem/ListFile.java +++ b/src/me/topchetoeu/jscript/filesystem/ListFile.java @@ -1,56 +1,56 @@ package me.topchetoeu.jscript.filesystem; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; +import java.util.Iterator; import java.util.stream.Stream; import me.topchetoeu.jscript.filesystem.FilesystemException.FSCode; public class ListFile implements File { - private Stream stream; + private Iterator it; private String filename; private byte[] currFile; private long ptr = 0, start = 0, end = 0; private void next() { - while (stream != null) { - var opt = stream.findFirst(); - - if (opt.isPresent()) { - start = end; - currFile = (opt.get().toString() + "\n").getBytes(); - end = start + currFile.length; - } - else { - stream = null; - currFile = null; - } + if (it != null && it.hasNext()) { + start = end; + currFile = (it.next() + "\n").getBytes(); + end = start + currFile.length; + } + else { + it = null; + currFile = null; + end = -1; } } @Override public void close() { - stream = null; + it = null; currFile = null; } @Override public int read(byte[] buff) { - if (stream == null) throw new FilesystemException(filename, FSCode.NO_PERMISSIONS_R); if (ptr < start) return 0; + if (it == null) return 0; var i = 0; while (i < buff.length) { - while (i > end) next(); + while (i + ptr >= end) { + next(); + if (it == null) return 0; + } int cpyN = Math.min(currFile.length, buff.length - i); - System.arraycopy(buff, i, currFile, 0, cpyN); + System.arraycopy(currFile, (int)(ptr + i - start), buff, i, cpyN); i += cpyN; } + ptr += i; return i; } @@ -66,8 +66,8 @@ public class ListFile implements File { throw new FilesystemException(filename, FSCode.NO_PERMISSIONS_RW); } - public ListFile(Path path) throws IOException { - stream = Files.list(path); - filename = path.toString(); + public ListFile(String filename, Stream stream) throws IOException { + this.it = stream.iterator(); + this.filename = filename; } } diff --git a/src/me/topchetoeu/jscript/filesystem/MemoryFilesystem.java b/src/me/topchetoeu/jscript/filesystem/MemoryFilesystem.java index 2f2f162..5270439 100644 --- a/src/me/topchetoeu/jscript/filesystem/MemoryFilesystem.java +++ b/src/me/topchetoeu/jscript/filesystem/MemoryFilesystem.java @@ -18,15 +18,10 @@ public class MemoryFilesystem implements Filesystem { } @Override - public String normalize(String path) { + public String normalize(String... path) { return Paths.normalize(path); } - @Override - public String cwd(String cwd, String path) { - return Paths.cwd(cwd, path); - } - @Override public void create(String _path, EntryType type) { var path = realPath(_path); diff --git a/src/me/topchetoeu/jscript/filesystem/Paths.java b/src/me/topchetoeu/jscript/filesystem/Paths.java index b59609e..e6f6c38 100644 --- a/src/me/topchetoeu/jscript/filesystem/Paths.java +++ b/src/me/topchetoeu/jscript/filesystem/Paths.java @@ -3,8 +3,8 @@ package me.topchetoeu.jscript.filesystem; import java.util.ArrayList; public class Paths { - public static String normalize(String path) { - var parts = path.split("[\\\\/]"); + public static String normalize(String... path) { + var parts = String.join("/", path).split("[\\\\/]"); var res = new ArrayList(); for (var part : parts) { @@ -12,14 +12,15 @@ public class Paths { else if (part.equals("..")) { if (res.size() > 0) res.remove(res.size() - 1); } - else if (!part.equals(".")) res.add(part); + else if (!part.equals(".") && !part.isEmpty()) res.add(part); } var sb = new StringBuilder(); for (var el : res) sb.append("/").append(el); - return sb.toString(); + if (sb.isEmpty()) return "/"; + else return sb.toString(); } public static String chroot(String root, String path) { diff --git a/src/me/topchetoeu/jscript/filesystem/PhysicalFile.java b/src/me/topchetoeu/jscript/filesystem/PhysicalFile.java index cc3b78c..76365e7 100644 --- a/src/me/topchetoeu/jscript/filesystem/PhysicalFile.java +++ b/src/me/topchetoeu/jscript/filesystem/PhysicalFile.java @@ -9,24 +9,24 @@ import me.topchetoeu.jscript.filesystem.FilesystemException.FSCode; public class PhysicalFile implements File { private String filename; private RandomAccessFile file; - private Mode perms; + private Mode mode; @Override public int read(byte[] buff) { - if (file == null || !perms.readable) throw new FilesystemException(filename, FSCode.NO_PERMISSIONS_R); + if (file == null || !mode.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); + if (file == null || !mode.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 long seek(long offset, int pos) { - if (file == null || !perms.readable) throw new FilesystemException(filename, FSCode.NO_PERMISSIONS_R); + if (file == null || !mode.readable) throw new FilesystemException(filename, FSCode.NO_PERMISSIONS_R); try { if (pos == 1) offset += file.getFilePointer(); @@ -43,14 +43,15 @@ public class PhysicalFile implements File { try { file.close(); } catch (IOException e) {} // SHUT file = null; - perms = Mode.NONE; + mode = Mode.NONE; } - public PhysicalFile(String path, Mode mode) throws FileNotFoundException { + public PhysicalFile(String name, String path, Mode mode) throws FileNotFoundException { + this.filename = name; + this.mode = mode; + 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; } } diff --git a/src/me/topchetoeu/jscript/filesystem/PhysicalFilesystem.java b/src/me/topchetoeu/jscript/filesystem/PhysicalFilesystem.java index f590ee5..b1d497e 100644 --- a/src/me/topchetoeu/jscript/filesystem/PhysicalFilesystem.java +++ b/src/me/topchetoeu/jscript/filesystem/PhysicalFilesystem.java @@ -11,9 +11,9 @@ public class PhysicalFilesystem implements Filesystem { private void checkMode(Path path, Mode mode) { if (!path.startsWith(root)) throw new FilesystemException(path.toString(), FSCode.NO_PERMISSIONS_R); - var stat = stat(path.toString()); - if (mode.readable && !stat.mode.readable) throw new FilesystemException(path.toString(), FSCode.NO_PERMISSIONS_R); - if (mode.writable && !stat.mode.writable) throw new FilesystemException(path.toString(), FSCode.NO_PERMISSIONS_RW); + + if (mode.readable && !Files.isReadable(path)) throw new FilesystemException(path.toString(), FSCode.NO_PERMISSIONS_R); + if (mode.writable && !Files.isWritable(path)) throw new FilesystemException(path.toString(), FSCode.NO_PERMISSIONS_RW); } private Path realPath(String path) { @@ -21,24 +21,20 @@ public class PhysicalFilesystem implements Filesystem { } @Override - public String normalize(String path) { - return Paths.normalize(path); - } - - @Override - public String cwd(String cwd, String path) { - return Paths.cwd(cwd, path); + public String normalize(String... paths) { + return Paths.normalize(paths); } @Override public File open(String _path, Mode perms) { + _path = normalize(_path); var path = realPath(_path); checkMode(path, perms); - try { - if (Files.isDirectory(path)) return new ListFile(path); - else return new PhysicalFile(path.toString(), perms); + try { + if (Files.isDirectory(path)) return new ListFile(_path, Files.list(path).map((v -> v.getFileName().toString()))); + else return new PhysicalFile(_path, path.toString(), perms); } catch (IOException e) { throw new FilesystemException(path.toString(), FSCode.DOESNT_EXIST); } } diff --git a/src/me/topchetoeu/jscript/filesystem/RootFilesystem.java b/src/me/topchetoeu/jscript/filesystem/RootFilesystem.java index 74055c6..afa2ba3 100644 --- a/src/me/topchetoeu/jscript/filesystem/RootFilesystem.java +++ b/src/me/topchetoeu/jscript/filesystem/RootFilesystem.java @@ -23,17 +23,17 @@ public class RootFilesystem implements Filesystem { if (mode.writable && perms != null && !canWrite(_path)) throw new FilesystemException(_path, FSCode.NO_PERMISSIONS_RW); } - @Override public String normalize(String path) { - var filename = Filename.parse(path); - var protocol = protocols.get(filename.protocol); - if (protocol == null) return filename.toString(); - else return new Filename(filename.protocol, protocol.normalize(filename.path)).toString(); - } - @Override public String cwd(String cwd, String path) { - var filename = Filename.parse(cwd); - var protocol = protocols.get(filename.protocol); - if (protocol == null) return filename.toString(); - else return new Filename(filename.protocol, protocol.cwd(filename.path, path)).toString(); + @Override public String normalize(String... paths) { + if (paths.length == 0) return "file://"; + else { + var filename = Filename.parse(paths[0]); + var protocol = protocols.get(filename.protocol); + paths[0] = filename.path; + + + if (protocol == null) return Paths.normalize(paths); + else return filename.protocol + "://" + protocol.normalize(paths); + } } @Override public File open(String path, Mode perms) throws FilesystemException { var filename = Filename.parse(path); @@ -57,9 +57,8 @@ public class RootFilesystem implements Filesystem { 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); } + try { return protocol.stat(filename.path); } catch (FilesystemException e) { throw new FilesystemException(filename.toString(), e.code); } } diff --git a/src/me/topchetoeu/jscript/lib/FileLib.java b/src/me/topchetoeu/jscript/lib/FileLib.java index 8918f10..536e03c 100644 --- a/src/me/topchetoeu/jscript/lib/FileLib.java +++ b/src/me/topchetoeu/jscript/lib/FileLib.java @@ -15,7 +15,7 @@ public class FileLib { @NativeGetter public PromiseLib pointer(Context ctx) { return PromiseLib.await(ctx, () -> { try { - return file.getPtr(); + return file.seek(0, 1); } catch (FilesystemException e) { throw e.toEngineException(); } }); @@ -23,23 +23,14 @@ public class FileLib { @NativeGetter public PromiseLib length(Context ctx) { return PromiseLib.await(ctx, () -> { try { - long curr = file.getPtr(); - file.setPtr(0, 2); - long res = file.getPtr(); - file.setPtr(curr, 0); + long curr = file.seek(0, 1); + long res = file.seek(0, 2); + file.seek(curr, 0); return res; } catch (FilesystemException e) { throw e.toEngineException(); } }); } - @NativeGetter public PromiseLib getMode(Context ctx) { - return PromiseLib.await(ctx, () -> { - try { - return file.mode().name; - } - catch (FilesystemException e) { throw e.toEngineException(); } - }); - } @Native public PromiseLib read(Context ctx, int n) { return PromiseLib.await(ctx, () -> { @@ -73,11 +64,10 @@ public class FileLib { return null; }); } - @Native public PromiseLib setPointer(Context ctx, long ptr) { + @Native public PromiseLib seek(Context ctx, long ptr, int whence) { return PromiseLib.await(ctx, () -> { try { - file.setPtr(ptr, 0); - return null; + return file.seek(ptr, whence); } catch (FilesystemException e) { throw e.toEngineException(); } }); diff --git a/src/me/topchetoeu/jscript/lib/FilesystemLib.java b/src/me/topchetoeu/jscript/lib/FilesystemLib.java index 98a14d3..881f5ad 100644 --- a/src/me/topchetoeu/jscript/lib/FilesystemLib.java +++ b/src/me/topchetoeu/jscript/lib/FilesystemLib.java @@ -20,6 +20,10 @@ import me.topchetoeu.jscript.interop.Native; @Native("Filesystem") public class FilesystemLib { + @Native public static final int SEEK_SET = 0; + @Native public static final int SEEK_CUR = 1; + @Native public static final int SEEK_END = 2; + private static Filesystem fs(Context ctx) { var env = ctx.environment(); if (env != null) { @@ -29,24 +33,28 @@ public class FilesystemLib { throw EngineException.ofError("Current environment doesn't have a file system."); } + @Native public static String normalize(Context ctx, String... paths) { + return fs(ctx).normalize(paths); + } + @Native public static PromiseLib open(Context ctx, String _path, String mode) { - var filename = Filename.parse(_path); + var path = fs(ctx).normalize(_path); var _mode = Mode.parse(mode); return PromiseLib.await(ctx, () -> { try { - if (fs(ctx).stat(filename.path).type != EntryType.FILE) { - throw new FilesystemException(filename.toString(), FSCode.NOT_FILE); + if (fs(ctx).stat(path).type != EntryType.FILE) { + throw new FilesystemException(path, FSCode.NOT_FILE); } - var file = fs(ctx).open(filename.path, _mode); + var file = fs(ctx).open(path, _mode); return new FileLib(file); } catch (FilesystemException e) { throw e.toEngineException(); } }); } @Native public static ObjectValue ls(Context ctx, String _path) throws IOException { - var filename = Filename.parse(_path); + var path = fs(ctx).normalize(_path); return Values.toJSAsyncIterator(ctx, new Iterator<>() { private boolean failed, done; @@ -57,11 +65,11 @@ public class FilesystemLib { if (done) return; if (!failed) { if (file == null) { - if (fs(ctx).stat(filename.path).type != EntryType.FOLDER) { - throw new FilesystemException(filename.toString(), FSCode.NOT_FOLDER); + if (fs(ctx).stat(path).type != EntryType.FOLDER) { + throw new FilesystemException(path, FSCode.NOT_FOLDER); } - file = fs(ctx).open(filename.path, Mode.READ); + file = fs(ctx).open(path, Mode.READ); } if (nextLine == null) { @@ -108,34 +116,34 @@ public class FilesystemLib { }); } - @Native public static PromiseLib mkfile(Context ctx, String _path) throws IOException { + @Native public static PromiseLib mkfile(Context ctx, String path) throws IOException { return PromiseLib.await(ctx, () -> { try { - fs(ctx).create(Filename.parse(_path).toString(), EntryType.FILE); + fs(ctx).create(path, EntryType.FILE); return null; } catch (FilesystemException e) { throw e.toEngineException(); } }); } - @Native public static PromiseLib rm(Context ctx, String _path, boolean recursive) throws IOException { + @Native public static PromiseLib rm(Context ctx, String path, boolean recursive) throws IOException { return PromiseLib.await(ctx, () -> { try { - if (!recursive) fs(ctx).create(Filename.parse(_path).toString(), EntryType.NONE); + if (!recursive) fs(ctx).create(path, EntryType.NONE); else { var stack = new Stack(); - stack.push(_path); + stack.push(path); while (!stack.empty()) { - var path = Filename.parse(stack.pop()).toString(); + var currPath = stack.pop(); FileStat stat; - try { stat = fs(ctx).stat(path); } + try { stat = fs(ctx).stat(currPath); } catch (FilesystemException e) { continue; } if (stat.type == EntryType.FOLDER) { - for (var el : fs(ctx).open(path, Mode.READ).readToString().split("\n")) stack.push(el); + for (var el : fs(ctx).open(currPath, Mode.READ).readToString().split("\n")) stack.push(el); } - else fs(ctx).create(path, EntryType.NONE); + else fs(ctx).create(currPath, EntryType.NONE); } } return null; @@ -143,10 +151,10 @@ public class FilesystemLib { catch (FilesystemException e) { throw e.toEngineException(); } }); } - @Native public static PromiseLib stat(Context ctx, String _path) throws IOException { + @Native public static PromiseLib stat(Context ctx, String path) throws IOException { return PromiseLib.await(ctx, () -> { try { - var stat = fs(ctx).stat(_path); + var stat = fs(ctx).stat(path); var res = new ObjectValue(); res.defineProperty(ctx, "type", stat.type.name);