package challengetask.group02.fuseimpl; import challengetask.group02.controllers.*; import challengetask.group02.controllers.exceptions.*; import net.fusejna.*; import net.fusejna.StructFuseFileInfo.FileInfoWrapper; import net.fusejna.types.TypeMode; import net.fusejna.util.FuseFilesystemAdapterAssumeImplemented; import java.io.IOException; import java.nio.ByteBuffer; import java.util.logging.Logger; import java.util.Objects; /* Fuse interface implementation requires the mount point and the controller for the constructor. Information about FUSE can be found in the project wiki, to know more about fuse-jna go to https://github.com/EtiennePerot/fuse-jna */ public class Fuse extends FuseFilesystemAdapterAssumeImplemented { private final String path; private ControllerContext controller; public Fuse(ControllerContext controller, String path) { this.controller = controller; this.path = path; } public void run(Logger logger) throws FuseException { try { this.log(false).mount(path); //this.log(logger).mount(path); } catch (FuseException e) { e.printStackTrace(); } } @Override public int getattr(final String path, final StructStat.StatWrapper stat) { try { controller.updateFileMetaData(path, stat); return 0; } catch (FsException e) { return getErrorCode(e); } catch (ClassNotFoundException | IOException e) { e.printStackTrace(); } return -ErrorCodes.ENOENT(); } @Override public int read(final String path, final ByteBuffer buffer, final long size, final long offset, final StructFuseFileInfo.FileInfoWrapper info) { // Compute substring that we are being asked to read byte[] s = new byte[0]; try { s = controller.readFile(path, size, offset); } catch (FsException e) { return getErrorCode(e); } catch (ClassNotFoundException | IOException e) { e.printStackTrace(); } catch (CRCException e) { e.printStackTrace(); } buffer.put(s); return s.length; } @Override public int readdir(final String path, final DirectoryFiller filler) { try { for (String child : controller.readDir(path)) { filler.add(child); } } catch (FsException e) { return getErrorCode(e); } catch (ClassNotFoundException | IOException e) { e.printStackTrace(); } return 0; } @Override public int mkdir(final String path, final TypeMode.ModeWrapper mode) { try { controller.createDir(path); } catch (FsException e) { return getErrorCode(e); } catch (ClassNotFoundException | IOException e) { e.printStackTrace(); } return 0; } @Override public int create(final String path, final TypeMode.ModeWrapper mode, final StructFuseFileInfo.FileInfoWrapper info) { try { controller.createFile(path); //mode.setMode(TypeMode.NodeType.DIRECTORY); } catch (FsException e) { return getErrorCode(e); } catch (ClassNotFoundException | IOException e) { e.printStackTrace(); } return 0; } @Override public int rename(final String path, final String newName) { try { controller.rename(path, newName); } catch (FsException e) { return getErrorCode(e); } catch (ClassNotFoundException | IOException e) { e.printStackTrace(); } return 0; } @Override public int rmdir(final String path) { try { controller.deleteDirectory(path); } catch (FsException e) { return getErrorCode(e); } catch (ClassNotFoundException | IOException e) { e.printStackTrace(); } return 0; } @Override public int unlink(final String path) { try { controller.deleteFile(path); } catch (FsException e) { return getErrorCode(e); } catch (ClassNotFoundException | IOException e) { e.printStackTrace(); } return 0; } @Override public int write(final String path, final ByteBuffer buf, final long bufSize, final long writeOffset, final StructFuseFileInfo.FileInfoWrapper wrapper) { try { return controller.writeFile(path, buf, bufSize, writeOffset); } catch (FsException e) { return getErrorCode(e); } catch (ClassNotFoundException | IOException e) { e.printStackTrace(); } //return ((MemoryFile) p).write(buf, bufSize, writeOffset); return 0; } @Override public int flush(final String path, final FileInfoWrapper info) { //introduced for the locking mechanism //flush is only used in context with file try { controller.whenFileClosed(path); } catch (FsException e) { return getErrorCode(e); } catch (ClassNotFoundException | IOException e) { e.printStackTrace(); } return 0; } /** * This method returns the right FUSE error code, depending on what type the FsException is. * * @param e FsException * @return int Fuse Error code */ private int getErrorCode(FsException e) { if (Objects.equals(e.getClass().getName(), NotADirectoryException.class.getName())) { return -ErrorCodes.ENOTDIR(); } if (Objects.equals(e.getClass().getName(), DirectoryNotEmptyException.class.getName())) { return -ErrorCodes.ENOTEMPTY(); } if (Objects.equals(e.getClass().getName(), BusyException.class.getName())) { //TODO is this the right error code? return -ErrorCodes.EBUSY(); } if (Objects.equals(e.getClass().getName(), NoSuchFileOrDirectoryException.class.getName())) { return -ErrorCodes.ENOENT(); } if (Objects.equals(e.getClass().getName(), NotAFileException.class.getName())) { return -ErrorCodes.EISDIR(); } if (Objects.equals(e.getClass().getName(), FileExistsException.class.getName())) { return -ErrorCodes.EEXIST(); } else { return -1; } } }