aboutsummaryrefslogtreecommitdiffstats
path: root/lcmodfs.py
blob: 92a1b2dd77939b744629e02d5e1bb2d6ef488a20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/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
from base import *
import sys, pdb
import errno, stat
import faulthandler
import requests, threading
sys.path.append("../larryviewer") #FIXME
HAVE_QT = False
from larryviewer 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()):
            e = v.ui.lsEntries.item(i)
            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:
            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)
        
        if flags & os.O_APPEND:
            raise llfuse.FUSEError(errno.EROFS)
        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
        if not r:
            raise llfuse.FUSEError(errno.EREMOTEIO)
        
        elif r.status_code == 206:
            return r.raw.read(size)
        
        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)


if __name__ == "__main__":
    # Usage: ./lcfs.py <mountpoint>
    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:
        #threading.Thread(target=findBrokenEntries).start()
        llfuse.main(workers=1)
    except:
        llfuse.close(unmount=True)
        raise
    llfuse.close()