/** * FUSE-J: Java bindings for FUSE (Filesystem in Userspace by Miklos Szeredi (mszeredi@inf.bme.hu)) * * Copyright (C) 2003 Peter Levart (peter@select-tech.si) * * This program can be distributed under the terms of the GNU LGPL. * See the file COPYING.LIB */ package fuse.staticfs; import fuse.*; import fuse.compat.Filesystem1; import fuse.compat.FuseDirEnt; import fuse.compat.FuseStat; import java.nio.ByteBuffer; public class StaticFilesystem implements Filesystem1 { DirectoryNode rootNode; FuseStatfs statfs; public StaticFilesystem(DirectoryNode rootNode) { this.rootNode = rootNode; statfs = new FuseStatfs(); statfs.blocks = 0; statfs.blocksFree = 0; statfs.blockSize = 8192; statfs.files = 0; statfs.filesFree = 0; statfs.namelen = 2048; } public DirectoryNode getRootNode() { return rootNode; } // // Filesystem implementation public void chmod(String path, int mode) throws FuseException { ResolveResult rr = resolvePath(path); if (rr.node instanceof MountpointNode) { ((MountpointNode) rr.node).getFilesystem().chmod(rr.path, mode); return; } throw new FuseException("Read Only").initErrno(FuseException.EROFS); } public void chown(String path, int uid, int gid) throws FuseException { ResolveResult rr = resolvePath(path); if (rr.node instanceof MountpointNode) { ((MountpointNode) rr.node).getFilesystem().chown(rr.path, uid, gid); return; } throw new FuseException("Read Only").initErrno(FuseException.EROFS); } public FuseStat getattr(String path) throws FuseException { ResolveResult rr = resolvePath(path); if (rr.node instanceof MountpointNode) { return ((MountpointNode) rr.node).getFilesystem().getattr(rr.path); } return rr.node.getStat(); } public FuseDirEnt[] getdir(String path) throws FuseException { ResolveResult rr = resolvePath(path); if (rr.node instanceof MountpointNode) { return ((MountpointNode) rr.node).getFilesystem().getdir(rr.path); } if (!(rr.node instanceof DirectoryNode)) throw new FuseException("Not a Directory").initErrno(FuseException.ENOTDIR); Node[] children = ((DirectoryNode) rr.node).getChildren(); FuseDirEnt[] dirEntries = new FuseDirEnt[children.length]; for (int i = 0; i < children.length; i++) { Node child = children[i]; FuseStat stat = (child instanceof MountpointNode) ? ((MountpointNode) child).getFilesystem().getattr("/") : child.getStat(); FuseDirEnt dirEntry = new FuseDirEnt(); dirEntry.name = child.getName(); dirEntry.mode = stat.mode; dirEntries[i] = dirEntry; } return dirEntries; } public void link(String from, String to) throws FuseException { ResolveResult fromRr = resolvePath(from); ResolveResult toRr = resolveParentPath(to); boolean fromIsMount = fromRr.node instanceof MountpointNode; boolean toIsMount = toRr.node instanceof MountpointNode; if (fromIsMount || toIsMount) { if (fromIsMount && toIsMount && fromRr.node == toRr.node) { ((MountpointNode) fromRr.node).getFilesystem().link(fromRr.path, toRr.path); } else { throw new FuseException("Cross Device Link not possible").initErrno(FuseException.EXDEV); } } else { throw new FuseException("Read Only").initErrno(FuseException.EROFS); } } public void mkdir(String path, int mode) throws FuseException { ResolveResult rr = resolveParentPath(path); if (rr.node instanceof MountpointNode) { ((MountpointNode) rr.node).getFilesystem().mkdir(rr.path, mode); return; } throw new FuseException("Read Only").initErrno(FuseException.EROFS); } public void mknod(String path, int mode, int rdev) throws FuseException { ResolveResult rr = resolveParentPath(path); if (rr.node instanceof MountpointNode) { ((MountpointNode) rr.node).getFilesystem().mknod(rr.path, mode, rdev); return; } throw new FuseException("Read Only").initErrno(FuseException.EROFS); } public void open(String path, int flags) throws FuseException { ResolveResult rr = resolvePath(path); if (rr.node instanceof MountpointNode) { ((MountpointNode) rr.node).getFilesystem().open(rr.path, flags); return; } if (rr.node instanceof FileNode) { ((FileNode) rr.node).open(flags); return; } throw new FuseException("Not a File").initErrno(FuseException.EINVAL); } public void read(String path, ByteBuffer buf, long offset) throws FuseException { ResolveResult rr = resolvePath(path); if (rr.node instanceof MountpointNode) { ((MountpointNode) rr.node).getFilesystem().read(rr.path, buf, offset); return; } if (rr.node instanceof FileNode) { ((FileNode) rr.node).read(buf, offset); return; } throw new FuseException("Not a File").initErrno(FuseException.EINVAL); } public String readlink(String path) throws FuseException { ResolveResult rr = resolvePath(path); if (rr.node instanceof MountpointNode) { return ((MountpointNode) rr.node).getFilesystem().readlink(rr.path); } if (rr.node instanceof SymlinkNode) { return ((SymlinkNode) rr.node).getTarget(); } throw new FuseException("Not a Symbolic Link").initErrno(FuseException.EINVAL); } public void release(String path, int flags) throws FuseException { ResolveResult rr = resolvePath(path); if (rr.node instanceof MountpointNode) { ((MountpointNode) rr.node).getFilesystem().release(rr.path, flags); return; } if (rr.node instanceof FileNode) { ((FileNode) rr.node).release(flags); return; } throw new FuseException("Not a File").initErrno(FuseException.EINVAL); } public void rename(String from, String to) throws FuseException { ResolveResult fromRr = resolvePath(from); ResolveResult toRr = resolveParentPath(to); boolean fromIsMount = fromRr.node instanceof MountpointNode; boolean toIsMount = toRr.node instanceof MountpointNode; if (fromIsMount || toIsMount) { if (fromIsMount && toIsMount && fromRr.node == toRr.node) { ((MountpointNode) fromRr.node).getFilesystem().rename(fromRr.path, toRr.path); } else { throw new FuseException("Cross Device Rename not possible").initErrno(FuseException.EXDEV); } } else { throw new FuseException("Read Only").initErrno(FuseException.EROFS); } } public void rmdir(String path) throws FuseException { ResolveResult rr = resolvePath(path); if (rr.node instanceof MountpointNode) { ((MountpointNode) rr.node).getFilesystem().rmdir(rr.path); return; } throw new FuseException("Read Only").initErrno(FuseException.EROFS); } public FuseStatfs statfs() throws FuseException { return statfs; } public void symlink(String from, String to) throws FuseException { ResolveResult rr = resolveParentPath(to); if (rr.node instanceof MountpointNode) { ((MountpointNode) rr.node).getFilesystem().symlink(from, rr.path); return; } throw new FuseException("Read Only").initErrno(FuseException.EROFS); } public void truncate(String path, long size) throws FuseException { ResolveResult rr = resolvePath(path); if (rr.node instanceof MountpointNode) { ((MountpointNode) rr.node).getFilesystem().truncate(rr.path, size); return; } if (rr.node instanceof FileNode) { ((FileNode) rr.node).truncate(size); return; } throw new FuseException("Not a File").initErrno(FuseException.EINVAL); } public void unlink(String path) throws FuseException { ResolveResult rr = resolvePath(path); if (rr.node instanceof MountpointNode) { ((MountpointNode) rr.node).getFilesystem().unlink(rr.path); return; } throw new FuseException("Read Only").initErrno(FuseException.EROFS); } public void utime(String path, int atime, int mtime) throws FuseException { ResolveResult rr = resolvePath(path); if (rr.node instanceof MountpointNode) { ((MountpointNode) rr.node).getFilesystem().utime(rr.path, atime, mtime); return; } if (rr.node instanceof FileNode) { ((FileNode) rr.node).utime(atime, mtime); return; } throw new FuseException("Not a File").initErrno(FuseException.EINVAL); } public void write(String path, ByteBuffer buf, long offset) throws FuseException { ResolveResult rr = resolvePath(path); if (rr.node instanceof MountpointNode) { ((MountpointNode) rr.node).getFilesystem().write(rr.path, buf, offset); return; } if (rr.node instanceof FileNode) { ((FileNode) rr.node).read(buf, offset); return; } throw new FuseException("Not a File").initErrno(FuseException.EINVAL); } // // private methods private ResolveResult resolveParentPath(String path) throws FuseException { return resolvePath(path, true); } private ResolveResult resolvePath(String path) throws FuseException { return resolvePath(path, false); } private ResolveResult resolvePath(String path, boolean resolveParent) throws FuseException { Node node = rootNode; int i = 0; int subPathStart = 0; while (i < path.length() && !(node instanceof MountpointNode)) { while (i < path.length() && path.charAt(i) == '/') { subPathStart = i; i++; } if (i >= path.length()) break; int nameStart = i; while (i < path.length() && path.charAt(i) != '/') i++; // are we resolving parent node & have just parsed the last component of path? if (resolveParent && i >= path.length()) break; String name = path.substring(nameStart, i); if (name.equals(".")) { // same node } else if (name.equals("..")) { // parent node Node parentNode = node.getParent(); if (parentNode != null) node = parentNode; } else { // child node Node childNode = null; if (node instanceof DirectoryNode && (childNode = ((DirectoryNode) node).getChild(name)) != null) node = childNode; else throw new FuseException("No such node").initErrno(FuseException.ENOENT); } subPathStart = i; } String subPath = path.substring(subPathStart); if (subPath.length() == 0 && node instanceof MountpointNode) subPath = "/"; return new ResolveResult(subPath, node); } static class ResolveResult { String path; Node node; ResolveResult(String path, Node node) { this.path = path; this.node = node; } } }