#!/usr/bin/env python3 # Copyright (c) 2018, George Tokmaji # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. import os import sys, pdb import llfuse, errno, stat import faulthandler import requests, threading sys.path.append("../larryviewer") #FIXME sys.path.append("../lc/src") #FIXME from larryviewer import * from base import * faulthandler.enable() class LCModOperations(LCOperations): _inode_list = None _viewer = None def __init__(self, v : LarryViewer): super().__init__() self._viewer = v for i in range(v.ui.lsEntries.count()): self._add_entry(llfuse.ROOT_INODE, v.ui.lsEntries.item(i).larry, True) def _is_dir(self, inode): return isinstance(self._inode_list[inode], Entry) or super()._is_dir(inode) def opendir(self, inode, ctx=None): if inode != llfuse.ROOT_INODE: print(inode) try: self._get_inode_by_parent(inode) except IndexError: for f in self._inode_list[inode].files(): self._add_entry(inode, {"title" : f, "address" : self._inode_list[inode].filePath(f)}) return inode def getattr(self, inode, ctx=None): attr = super().getattr(inode, ctx) if inode != llfuse.ROOT_INODE: entry = self._inode_list[inode] if attr.st_mode & stat.S_IFREG: attr.st_size = self._inode_list[entry["parent_inode"]].size() return attr def open(self, inode, flags, ctx=None): entry = self._inode_list[inode] if self.getattr(inode).st_mode & stat.S_IFDIR: raise llfuse.FUSEError(errno.EISDIR) print("checking flags") if flags & os.O_APPEND: raise llfuse.FUSEError(errno.EROFS) print("returning") return inode def read(self, inode, off, size): entry = self._inode_list[inode] try: r = requests.get(entry["address"], headers={"Range" : f"bytes={off}-{off+size}"}, stream=True) except Exception as e: print(e) raise llfuse.FUSEError(errno.EREMOTEIO) from e print(r, off, size) if not r: raise llfuse.FUSEError(errno.EREMOTEIO) elif r.status_code == 206: print("partial content", r.headers["Content-Length"]) b = r.raw.read(size) return b else: buf = BytesIO() i = 0 for chunk in r.iter_content(1024): if off <= i: buf.write(chunk) if off + i >= size: break else: raise llfuse.FUSEError(errno.EREMOTEIO) buf.seek(i - off) return buf.read(size) #def flush(self, inode): #pass #def close(self, inode): #pass #def release(self, inode): #pass if __name__ == "__main__": # Usage: ./lcfs.py app = QApplication(sys.argv) cwd = os.getcwd() os.chdir("../larryviewer") #FIXME v = LarryViewer() os.chdir(cwd) for t in threading.enumerate(): if t.name in "ccanlistlarrylist": t.join() fuse_options = set(llfuse.default_options) fuse_options.add("fsname=lcmodfs") fuse_options.add("debug") fuse_options.discard("default_permissions") op = LCModOperations(v) llfuse.init(op, sys.argv[1], fuse_options) try: llfuse.main(workers=1) except: llfuse.close(unmount=True) raise llfuse.close()